forked from Imagelibrary/binutils-gdb
Convert frame unwinders to use the current frame and
"struct value". * frame.c (frame_debug): Make global. (get_frame_id): Pass this frame to unwinder routines. (frame_pc_unwind): Remove unused unwind->prev_pc support. (do_frame_register_read): Do not discard the return value of frame_register_read. (frame_register_unwind): Remove debug messages. Use frame_unwind_register_value. (frame_unwind_register_value, get_frame_register_value): New functions. (create_new_frame, get_frame_base_address, get_frame_locals_address) (get_frame_args_address, get_frame_type): Pass this frame to unwinder routines. (frame_cleanup_after_sniffer, frame_prepare_for_sniffer): New functions. * frame.h: Update comments. (frame_debug, frame_unwind_register_value, get_frame_register_value) (frame_prepare_for_sniffer): Declare. * frame-unwind.h: Update comments and parameter names. (default_frame_sniffer): Declare. (frame_prev_register_ftype): Return a struct value *. (struct frame_unwind): Remove prev_pc member. (frame_unwind_sniffer_ftype, frame_unwind_append_sniffer): Delete. (frame_unwind_append_unwinder, frame_unwind_got_optimized) (frame_unwind_got_register, frame_unwind_got_memory) (frame_unwind_got_constant, frame_unwind_got_address): Declare. * frame-base.h: Update comments and parameter names. * valops.c (value_fetch_lazy): Use get_frame_register_value. Iterate if necessary. Add debugging output. * sentinel-frame.c (sentinel_frame_prev_register) (sentinel_frame_this_id): Update for new signature. (sentinel_frame_prev_pc): Delete. (sentinel_frame_unwinder): Remove prev_pc. * ia64-tdep.c (ia64_libunwind_frame_unwind): Do not initialize prev_pc. * libunwind-frame.c (libunwind_frame_unwind): Likewise. * frame-unwind.c (struct frame_unwind_table_entry): Remove sniffer. (frame_unwind_append_sniffer): Delete. (frame_unwind_append_unwinder): New function. (frame_unwind_find_by_frame): Take this frame. Only use sniffers from unwinders. Use frame_prepare_for_sniffer. (default_frame_sniffer, frame_unwind_got_optimized) (frame_unwind_got_register, frame_unwind_got_memory) (frame_unwind_got_constant, frame_unwind_got_address): New functions. * dummy-frame.c (dummy_frame_sniffer): Use gdbarch_dummy_id. (dummy_frame_prev_register, dummy_frame_this_id): Update for new signature. * gdbarch.sh: Replace unwind_dummy_id with dummy_id. * gdbarch.c, gdbarch.c: Regenerated. * frame-base.c (default_frame_base_address) (default_frame_locals_address, default_frame_args_address): Update for new signature. (frame_base_find_by_frame): Pass this frame to unwinder routines. * infcall.c (call_function_by_hand): Update comments. * Makefile.in (frame-unwind.o): Update dependencies. * gdbint.texinfo (Stack Frames): New chapter. (Algorithms): Move Frames text to the new chapter. (Target Conditionals): Delete SAVE_DUMMY_FRAME_TOS. Document gdbarch_dummy_id instead of gdbarch_unwind_dummy_id.
This commit is contained in:
@@ -76,6 +76,7 @@ as the mechanisms that adapt @value{GDBN} to specific hosts and targets.
|
||||
* Algorithms::
|
||||
* User Interface::
|
||||
* libgdb::
|
||||
* Stack Frames::
|
||||
* Symbol Handling::
|
||||
* Language Support::
|
||||
* Host Definition::
|
||||
@@ -273,39 +274,6 @@ cases and real-world issues. This chapter describes the basic
|
||||
algorithms and mentions some of the specific target definitions that
|
||||
they use.
|
||||
|
||||
@section Frames
|
||||
|
||||
@cindex frame
|
||||
@cindex call stack frame
|
||||
A frame is a construct that @value{GDBN} uses to keep track of calling
|
||||
and called functions.
|
||||
|
||||
@cindex frame, unwind
|
||||
@value{GDBN}'s frame model, a fresh design, was implemented with the
|
||||
need to support @sc{dwarf}'s Call Frame Information in mind. In fact,
|
||||
the term ``unwind'' is taken directly from that specification.
|
||||
Developers wishing to learn more about unwinders, are encouraged to
|
||||
read the @sc{dwarf} specification.
|
||||
|
||||
@findex frame_register_unwind
|
||||
@findex get_frame_register
|
||||
@value{GDBN}'s model is that you find a frame's registers by
|
||||
``unwinding'' them from the next younger frame. That is,
|
||||
@samp{get_frame_register} which returns the value of a register in
|
||||
frame #1 (the next-to-youngest frame), is implemented by calling frame
|
||||
#0's @code{frame_register_unwind} (the youngest frame). But then the
|
||||
obvious question is: how do you access the registers of the youngest
|
||||
frame itself?
|
||||
|
||||
@cindex sentinel frame
|
||||
@findex get_frame_type
|
||||
@vindex SENTINEL_FRAME
|
||||
To answer this question, GDB has the @dfn{sentinel} frame, the
|
||||
``-1st'' frame. Unwinding registers from the sentinel frame gives you
|
||||
the current values of the youngest real frame's registers. If @var{f}
|
||||
is a sentinel frame, then @code{get_frame_type (@var{f}) ==
|
||||
SENTINEL_FRAME}.
|
||||
|
||||
@section Prologue Analysis
|
||||
|
||||
@cindex prologue analysis
|
||||
@@ -1853,6 +1821,127 @@ the query interface. Each function is parameterized by a @code{ui-out}
|
||||
builder. The result of the query is constructed using that builder
|
||||
before the query function returns.
|
||||
|
||||
@node Stack Frames
|
||||
@chapter Stack Frames
|
||||
|
||||
@cindex frame
|
||||
@cindex call stack frame
|
||||
A frame is a construct that @value{GDBN} uses to keep track of calling
|
||||
and called functions.
|
||||
|
||||
@cindex unwind frame
|
||||
@value{GDBN}'s frame model, a fresh design, was implemented with the
|
||||
need to support @sc{dwarf}'s Call Frame Information in mind. In fact,
|
||||
the term ``unwind'' is taken directly from that specification.
|
||||
Developers wishing to learn more about unwinders, are encouraged to
|
||||
read the @sc{dwarf} specification, available from
|
||||
@url{http://www.dwarfstd.org}.
|
||||
|
||||
@findex frame_register_unwind
|
||||
@findex get_frame_register
|
||||
@value{GDBN}'s model is that you find a frame's registers by
|
||||
``unwinding'' them from the next younger frame. That is,
|
||||
@samp{get_frame_register} which returns the value of a register in
|
||||
frame #1 (the next-to-youngest frame), is implemented by calling frame
|
||||
#0's @code{frame_register_unwind} (the youngest frame). But then the
|
||||
obvious question is: how do you access the registers of the youngest
|
||||
frame itself?
|
||||
|
||||
@cindex sentinel frame
|
||||
@findex get_frame_type
|
||||
@vindex SENTINEL_FRAME
|
||||
To answer this question, GDB has the @dfn{sentinel} frame, the
|
||||
``-1st'' frame. Unwinding registers from the sentinel frame gives you
|
||||
the current values of the youngest real frame's registers. If @var{f}
|
||||
is a sentinel frame, then @code{get_frame_type (@var{f}) @equiv{}
|
||||
SENTINEL_FRAME}.
|
||||
|
||||
@section Selecting an Unwinder
|
||||
|
||||
@findex frame_unwind_prepend_unwinder
|
||||
@findex frame_unwind_append_unwinder
|
||||
The architecture registers a list of frame unwinders (@code{struct
|
||||
frame_unwind}), using the functions
|
||||
@code{frame_unwind_prepend_unwinder} and
|
||||
@code{frame_unwind_append_unwinder}. Each unwinder includes a
|
||||
sniffer. Whenever @value{GDBN} needs to unwind a frame (to fetch the
|
||||
previous frame's registers or the current frame's ID), it calls
|
||||
registered sniffers in order to find one which recognizes the frame.
|
||||
The first time a sniffer returns non-zero, the corresponding unwinder
|
||||
is assigned to the frame.
|
||||
|
||||
@section Unwinding the Frame ID
|
||||
@cindex frame ID
|
||||
|
||||
Every frame has an associated ID, of type @code{struct frame_id}.
|
||||
The ID includes the stack base and function start address for
|
||||
the frame. The ID persists through the entire life of the frame,
|
||||
including while other called frames are running; it is used to
|
||||
locate an appropriate @code{struct frame_info} from the cache.
|
||||
|
||||
Every time the inferior stops, and at various other times, the frame
|
||||
cache is flushed. Because of this, parts of @value{GDBN} which need
|
||||
to keep track of individual frames cannot use pointers to @code{struct
|
||||
frame_info}. A frame ID provides a stable reference to a frame, even
|
||||
when the unwinder must be run again to generate a new @code{struct
|
||||
frame_info} for the same frame.
|
||||
|
||||
The frame's unwinder's @code{this_id} method is called to find the ID.
|
||||
Note that this is different from register unwinding, where the next
|
||||
frame's @code{prev_register} is called to unwind this frame's
|
||||
registers.
|
||||
|
||||
Both stack base and function address are required to identify the
|
||||
frame, because a recursive function has the same function address for
|
||||
two consecutive frames and a leaf function may have the same stack
|
||||
address as its caller. On some platforms, a third address is part of
|
||||
the ID to further disambiguate frames---for instance, on IA-64
|
||||
the separate register stack address is included in the ID.
|
||||
|
||||
An invalid frame ID (@code{null_frame_id}) returned from the
|
||||
@code{this_id} method means to stop unwinding after this frame.
|
||||
|
||||
@section Unwinding Registers
|
||||
|
||||
Each unwinder includes a @code{prev_register} method. This method
|
||||
takes a frame, an associated cache pointer, and a register number.
|
||||
It returns a @code{struct value *} describing the requested register,
|
||||
as saved by this frame. This is the value of the register that is
|
||||
current in this frame's caller.
|
||||
|
||||
The returned value must have the same type as the register. It may
|
||||
have any lvalue type. In most circumstances one of these routines
|
||||
will generate the appropriate value:
|
||||
|
||||
@table @code
|
||||
@item frame_unwind_got_optimized
|
||||
@findex frame_unwind_got_optimized
|
||||
This register was not saved.
|
||||
|
||||
@item frame_unwind_got_register
|
||||
@findex frame_unwind_got_register
|
||||
This register was copied into another register in this frame. This
|
||||
is also used for unchanged registers; they are ``copied'' into the
|
||||
same register.
|
||||
|
||||
@item frame_unwind_got_memory
|
||||
@findex frame_unwind_got_memory
|
||||
This register was saved in memory.
|
||||
|
||||
@item frame_unwind_got_constant
|
||||
@findex frame_unwind_got_constant
|
||||
This register was not saved, but the unwinder can compute the previous
|
||||
value some other way.
|
||||
|
||||
@item frame_unwind_got_address
|
||||
@findex frame_unwind_got_address
|
||||
Same as @code{frame_unwind_got_constant}, except that the value is a target
|
||||
address. This is frequently used for the stack pointer, which is not
|
||||
explicitly saved but has a known offset from this frame's stack
|
||||
pointer. For architectures with a flat unified address space, this is
|
||||
generally the same as @code{frame_unwind_got_constant}.
|
||||
@end table
|
||||
|
||||
@node Symbol Handling
|
||||
|
||||
@chapter Symbol Handling
|
||||
@@ -3943,14 +4032,6 @@ This method replaces @w{@code{gdbarch_call_dummy_location (@var{gdbarch})}} and
|
||||
Return the name of register @var{regnr} as a string. May return @code{NULL}
|
||||
to indicate that @var{regnr} is not a valid register.
|
||||
|
||||
@item SAVE_DUMMY_FRAME_TOS (@var{sp})
|
||||
@findex SAVE_DUMMY_FRAME_TOS
|
||||
@anchor{SAVE_DUMMY_FRAME_TOS} Used in @samp{call_function_by_hand} to
|
||||
notify the target dependent code of the top-of-stack value that will be
|
||||
passed to the inferior code. This is the value of the @code{SP}
|
||||
after both the dummy frame and space for parameters/results have been
|
||||
allocated on the stack. @xref{gdbarch_unwind_dummy_id}.
|
||||
|
||||
@item int gdbarch_sdb_reg_to_regnum (@var{gdbarch}, @var{sdb_regnr})
|
||||
@findex gdbarch_sdb_reg_to_regnum
|
||||
Use this function to convert sdb register @var{sdb_regnr} into @value{GDBN}
|
||||
@@ -4132,13 +4213,12 @@ the @code{opcodes} library (@pxref{Support Libraries, ,Opcodes}).
|
||||
@file{include/dis-asm.h} used to pass information to the instruction
|
||||
decoding routine.
|
||||
|
||||
@item frame_id gdbarch_unwind_dummy_id (@var{gdbarch}, @var{frame})
|
||||
@findex gdbarch_unwind_dummy_id
|
||||
@anchor{gdbarch_unwind_dummy_id} Given @var{frame} return a @w{@code{struct
|
||||
@item frame_id gdbarch_dummy_id (@var{gdbarch}, @var{frame})
|
||||
@findex gdbarch_dummy_id
|
||||
@anchor{gdbarch_dummy_id} Given @var{frame} return a @w{@code{struct
|
||||
frame_id}} that uniquely identifies an inferior function call's dummy
|
||||
frame. The value returned must match the dummy frame stack value
|
||||
previously saved using @code{SAVE_DUMMY_FRAME_TOS}.
|
||||
@xref{SAVE_DUMMY_FRAME_TOS}.
|
||||
previously saved by @code{call_function_by_hand}.
|
||||
|
||||
@item DEPRECATED_USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
|
||||
@findex DEPRECATED_USE_STRUCT_CONVENTION
|
||||
|
||||
Reference in New Issue
Block a user