diff options
author | Daniel Jacobowitz <drow@false.org> | 2008-04-30 21:16:46 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2008-04-30 21:16:46 +0000 |
commit | 669fac235d5edab8e2f33c4f3382f3b61671dc8e (patch) | |
tree | 2f62ab9d692fd820796a2d9ea9081d0e4ec62434 /gdb/frame-unwind.h | |
parent | 9214ee5f5f55de5082571ea066ea6060497fa229 (diff) | |
download | gdb-669fac235d5edab8e2f33c4f3382f3b61671dc8e.zip gdb-669fac235d5edab8e2f33c4f3382f3b61671dc8e.tar.gz gdb-669fac235d5edab8e2f33c4f3382f3b61671dc8e.tar.bz2 |
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.
Diffstat (limited to 'gdb/frame-unwind.h')
-rw-r--r-- | gdb/frame-unwind.h | 107 |
1 files changed, 63 insertions, 44 deletions
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 8140a80..9ffafff 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -26,6 +26,7 @@ struct frame_id; struct frame_unwind; struct gdbarch; struct regcache; +struct value; #include "frame.h" /* For enum frame_type. */ @@ -41,17 +42,24 @@ struct regcache; as where this frame's prologue stores the previous frame's registers. */ -/* Given the NEXT frame, take a wiff of THIS frame's registers (namely +/* Given THIS frame, take a whiff of its registers (namely the PC and attributes) and if SELF is the applicable unwinder, return non-zero. Possibly also initialize THIS_PROLOGUE_CACHE. */ typedef int (frame_sniffer_ftype) (const struct frame_unwind *self, - struct frame_info *next_frame, + struct frame_info *this_frame, void **this_prologue_cache); +/* A default frame sniffer which always accepts the frame. Used by + fallback prologue unwinders. */ + +int default_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache); + /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); - use the NEXT frame, and its register unwind method, to determine - the frame ID of THIS frame. + use THIS frame, and through it the NEXT frame's register unwind + method, to determine the frame ID of THIS frame. A frame ID provides an invariant that can be used to re-identify an instance of a frame. It is a combination of the frame's `base' and @@ -72,14 +80,14 @@ typedef int (frame_sniffer_ftype) (const struct frame_unwind *self, with the other unwind methods. Memory for that cache should be allocated using FRAME_OBSTACK_ZALLOC(). */ -typedef void (frame_this_id_ftype) (struct frame_info *next_frame, +typedef void (frame_this_id_ftype) (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id); /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); - use the NEXT frame, and its register unwind method, to unwind THIS - frame's registers (returning the value of the specified register - REGNUM in the previous frame). + use THIS frame, and implicitly the NEXT frame's register unwind + method, to unwind THIS frame's registers (returning the value of + the specified register REGNUM in the previous frame). Traditionally, THIS frame's registers were unwound by examining THIS frame's function's prologue and identifying which registers @@ -91,37 +99,22 @@ typedef void (frame_this_id_ftype) (struct frame_info *next_frame, register in the previous frame is found in memory at SP+12, and THIS frame's SP can be obtained by unwinding the NEXT frame's SP. - Why not pass in THIS_FRAME? By passing in NEXT frame and THIS - cache, the supplied parameters are consistent with the sibling - function THIS_ID. + This function takes THIS_FRAME as an argument. It can find the + values of registers in THIS frame by calling get_frame_register + (THIS_FRAME), and reinvoke itself to find other registers in the + PREVIOUS frame by calling frame_unwind_register (THIS_FRAME). - Can the code call ``frame_register (get_prev_frame (NEXT_FRAME))''? - Won't the call frame_register (THIS_FRAME) be faster? Well, - ignoring the possability that the previous frame does not yet - exist, the ``frame_register (FRAME)'' function is expanded to - ``frame_register_unwind (get_next_frame (FRAME)'' and hence that - call will expand to ``frame_register_unwind (get_next_frame - (get_prev_frame (NEXT_FRAME)))''. Might as well call - ``frame_register_unwind (NEXT_FRAME)'' directly. + The result is a GDB value object describing the register value. It + may be a lazy reference to memory, a lazy reference to the value of + a register in THIS frame, or a non-lvalue. THIS_PROLOGUE_CACHE can be used to share any prolog analysis data with the other unwind methods. Memory for that cache should be allocated using FRAME_OBSTACK_ZALLOC(). */ -typedef void (frame_prev_register_ftype) (struct frame_info *next_frame, - void **this_prologue_cache, - int prev_regnum, - int *optimized, - enum lval_type * lvalp, - CORE_ADDR *addrp, - int *realnump, gdb_byte *valuep); - -/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); - use the NEXT frame, and its register unwind method, to return the PREV - frame's program-counter. */ - -typedef CORE_ADDR (frame_prev_pc_ftype) (struct frame_info *next_frame, - void **this_prologue_cache); +typedef struct value * (frame_prev_register_ftype) + (struct frame_info *this_frame, void **this_prologue_cache, + int regnum); /* Deallocate extra memory associated with the frame cache if any. */ @@ -139,7 +132,6 @@ struct frame_unwind frame_prev_register_ftype *prev_register; const struct frame_data *unwind_data; frame_sniffer_ftype *sniffer; - frame_prev_pc_ftype *prev_pc; frame_dealloc_cache_ftype *dealloc_cache; }; @@ -152,23 +144,50 @@ struct frame_unwind extern void frame_unwind_prepend_unwinder (struct gdbarch *gdbarch, const struct frame_unwind *unwinder); -/* Given the NEXT frame, take a wiff of THIS frame's registers (namely - the PC and attributes) and if it is the applicable unwinder return - the unwind methods, or NULL if it is not. */ - -typedef const struct frame_unwind *(frame_unwind_sniffer_ftype) (struct frame_info *next_frame); - /* Add a frame sniffer to the list. The predicates are polled in the order that they are appended. The initial list contains the dummy frame sniffer. */ -extern void frame_unwind_append_sniffer (struct gdbarch *gdbarch, - frame_unwind_sniffer_ftype *sniffer); +extern void frame_unwind_append_unwinder (struct gdbarch *gdbarch, + const struct frame_unwind *unwinder); -/* Iterate through the next frame's sniffers until one returns with an +/* Iterate through sniffers for THIS frame until one returns with an unwinder implementation. Possibly initialize THIS_CACHE. */ -extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *next_frame, +extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache); +/* Helper functions for value-based register unwinding. These return + a (possibly lazy) value of the appropriate type. */ + +/* Return a value which indicates that FRAME did not save REGNUM. */ + +struct value *frame_unwind_got_optimized (struct frame_info *frame, + int regnum); + +/* Return a value which indicates that FRAME copied REGNUM into + register NEW_REGNUM. */ + +struct value *frame_unwind_got_register (struct frame_info *frame, int regnum, + int new_regnum); + +/* Return a value which indicates that FRAME saved REGNUM in memory at + ADDR. */ + +struct value *frame_unwind_got_memory (struct frame_info *frame, int regnum, + CORE_ADDR addr); + +/* Return a value which indicates that FRAME's saved version of + REGNUM has a known constant (computed) value of VAL. */ + +struct value *frame_unwind_got_constant (struct frame_info *frame, int regnum, + ULONGEST val); + +/* Return a value which indicates that FRAME's saved version of REGNUM + has a known constant (computed) value of ADDR. Convert the + CORE_ADDR to a target address if necessary. */ + +struct value *frame_unwind_got_address (struct frame_info *frame, int regnum, + CORE_ADDR addr); + #endif |