This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]