This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[frame] Changing the representation of "can't unwind"


The current frame unwinding model marks a frame which can not be
unwound by setting its frame ID to null_frame_id.

The last frame in a backtrace doesn't necessarily have a null frame ID;
get_prev_frame_1 fails at the null frame ID, but most sites use
get_prev_frame, which fails at a number of weaker conditions like "in
the main function" where get_prev_frame_1 would succeed.  Also, with
the patch I just posted on gdb-patches@, get_prev_frame_1 will stop
when it encounters a zero PC.

One problem with this is that we overload null_frame_id.  For instance,
step_frame_id gets set to null_frame_id initially, and then to the
current frame ID when we need it.  The most frequently encountered
problem from the overloading is in here, in value_assign:

        /* Figure out which frame this is in currently.  */
        frame = frame_find_by_id (VALUE_FRAME_ID (toval));
        value_reg = VALUE_REGNUM (toval);

        if (!frame)
          error (_("Value being assigned to is no longer active."));

frame_find_by_id will call frame_id_p to verify that the specified ID
is not null_frame_id.  And it uses frame_id_eq to compare IDs, which
will not report two null IDs as equal.




The simple way to fix this would be to have two invalid values, one
meaning "there is a frame but its ID is unknown", and the other meaning
"there is no frame".



A more invasive way to fix it would be to change the conventions:

1. Require this_id to return a valid frame ID.  If it can't come up
with a function start address, the current PC is better than nothing. 
If it can't come up with a CFA, the current stack pointer is better
than nothing.  This would mean that the frame ID might change when
single-stepping in the outermost frame, if the prologue analyzer
couldn't interpret it and there were no symbols.  But it also
mostly guarantees that changing functions would indeed change the
frame ID.

2. Add a new frame unwinder method, called perhaps end_of_stack.
In the cases where an unwinder would currently return without
initializing the ID, to indicate that there were no frames after this
one, it could instead fill in a valid ID but return true from
end_of_stack.

For instance, the dwarf2 unwinder can construct a proper frame ID for
marked outermost frames (using the convention we settled on earlier, an
undefined return address - the current function's start address and CFA
are still available).  Then from the same cache it could check
undefined_retaddr in end_of_stack.

As another example, the i386 prologue analyzer returns no ID if
cache->base is zero.  (As an aside, the logic for this seems suspect: a
frameless function called by _start would never be backtraced through,
because ebp == 0 is trusted before cache->locals is checked.)  However,
we could treat _start as a typical frameless function with a small fix
to that logic, and give it a frame id of (_start, appropriate $sp).
Then we could refuse to unwind past it by noting that it cleared %ebp.
The way the i386 prologue analyzer is structured this would actually
be a little tricky, so it wasn't my best choice of examples :-)

Incrementally, a null frame ID could be accepted for unwinders that
don't provide a separate end_of_stack method.



I think that the second way is marginally cleaner; it's got its own
strange spots, though, and it's much more work.  So, I'm not going to
work on either approach without some feedback.  Does anyone else have
an opinion on the right way to solve this problem?

-- 
Daniel Jacobowitz
CodeSourcery


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]