diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/frame-unwind.h | 9 | ||||
-rw-r--r-- | gdb/frame.c | 21 | ||||
-rw-r--r-- | gdb/sentinel-frame.c | 13 |
4 files changed, 40 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 552f75d..e5207e7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2004-11-08 Andrew Cagney <cagney@gnu.org> + + * sentinel-frame.c (sentinel_frame_prev_pc): New function. + (sentinel_frame_unwinder): Add the prev_pc method. + * frame.c (frame_pc_unwind): Use the per-frame pc unwinder when + available. Do not handle the sentinel-frame case. + * frame-unwind.h (frame_prev_register_ftype): Define. + (struct frame_unwind): Add prev_pc; + 2004-11-08 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> * configure.in: Check for ncurses/term.h. diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 12d6dd2..74c0a4a 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -118,6 +118,14 @@ typedef void (frame_prev_register_ftype) (struct frame_info *next_frame, CORE_ADDR *addrp, int *realnump, void *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); + + struct frame_unwind { /* The frame's type. Should this instead be a collection of @@ -129,6 +137,7 @@ 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; }; /* Register a frame unwinder, _prepending_ it to the front of the diff --git a/gdb/frame.c b/gdb/frame.c index d9de0e6..61a9520 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -390,7 +390,15 @@ frame_pc_unwind (struct frame_info *this_frame) if (!this_frame->prev_pc.p) { CORE_ADDR pc; - if (gdbarch_unwind_pc_p (current_gdbarch)) + if (this_frame->unwind == NULL) + this_frame->unwind + = frame_unwind_find_by_frame (this_frame->next, + &this_frame->prologue_cache); + if (this_frame->unwind->prev_pc != NULL) + /* A per-frame unwinder, prefer it. */ + pc = this_frame->unwind->prev_pc (this_frame->next, + &this_frame->prologue_cache); + else if (gdbarch_unwind_pc_p (current_gdbarch)) { /* The right way. The `pure' way. The one true way. This method depends solely on the register-unwind code to @@ -410,17 +418,8 @@ frame_pc_unwind (struct frame_info *this_frame) different ways that a PC could be unwound. */ pc = gdbarch_unwind_pc (current_gdbarch, this_frame); } - else if (this_frame->level < 0) - { - /* FIXME: cagney/2003-03-06: Old code and a sentinel - frame. Do like was always done. Fetch the PC's value - directly from the global registers array (via read_pc). - This assumes that this frame belongs to the current - global register cache. The assumption is dangerous. */ - pc = read_pc (); - } else - internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method"); + internal_error (__FILE__, __LINE__, "No unwind_pc method"); this_frame->prev_pc.value = pc; this_frame->prev_pc.p = 1; if (frame_debug) diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c index f1e5c7f..b17bc82 100644 --- a/gdb/sentinel-frame.c +++ b/gdb/sentinel-frame.c @@ -81,11 +81,22 @@ sentinel_frame_this_id (struct frame_info *next_frame, internal_error (__FILE__, __LINE__, "sentinel_frame_this_id called"); } +static CORE_ADDR +sentinel_frame_prev_pc (struct frame_info *next_frame, + void **this_prologue_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (next_frame); + return gdbarch_unwind_pc (gdbarch, next_frame); +} + const struct frame_unwind sentinel_frame_unwinder = { SENTINEL_FRAME, sentinel_frame_this_id, - sentinel_frame_prev_register + sentinel_frame_prev_register, + NULL, /* unwind_data */ + NULL, /* sniffer */ + sentinel_frame_prev_pc, }; const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder; |