aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/frame-unwind.h9
-rw-r--r--gdb/frame.c21
-rw-r--r--gdb/sentinel-frame.c13
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;