This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[commit] Finally add per-unwinder prev_pc
- From: Andrew Cagney <cagney at gnu dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Mon, 08 Nov 2004 20:13:31 -0500
- Subject: [commit] Finally add per-unwinder prev_pc
Hello,
The addition of a per-unwinder "pc" unwind method has always beeing
lurking in the wings. The thing that's been olding it back was solid
evidence that it was needed. I've now identified two examples so I've
added it.
- dwarf2 CFI's return-address column may not be a real register
This lets dwarf2-frame return the return-address column directly.
- info frame 'Saved registers' printing both "pc" and "lr"
This lets architecture unwinders just return the PC without doing the
PC==LR "trick".
Tested on amd64 and PPC.
committed,
Andrew
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;
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.11
diff -p -u -r1.11 frame-unwind.h
--- frame-unwind.h 8 Apr 2004 20:03:52 -0000 1.11
+++ frame-unwind.h 9 Nov 2004 01:01:11 -0000
@@ -118,6 +118,14 @@ typedef void (frame_prev_register_ftype)
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
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.192
diff -p -u -r1.192 frame.c
--- frame.c 29 Oct 2004 20:23:06 -0000 1.192
+++ frame.c 9 Nov 2004 01:01:12 -0000
@@ -390,7 +390,15 @@ frame_pc_unwind (struct frame_info *this
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
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)
Index: sentinel-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/sentinel-frame.c,v
retrieving revision 1.9
diff -p -u -r1.9 sentinel-frame.c
--- sentinel-frame.c 1 May 2004 19:35:22 -0000 1.9
+++ sentinel-frame.c 9 Nov 2004 01:01:12 -0000
@@ -81,11 +81,22 @@ sentinel_frame_this_id (struct frame_inf
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;