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]

[patch rfc] Fix new frame's off-by-one bug


Hello,

The attached fixes the new frame's code's off-by-one bug. At a most basic level, the fix involves replacing the pair:

  this->unwind->reg (this, &this->cache, regnum, ....);
  this->unwind->id (this, &this->cache, &this->prev->id);

with, effectively:

  this->unwind->prev_register (this->next, &this->cache, regnum, ...);
  this->unwind->this_id (this->next, &this->cache, &this->id);

Notice how the unwind->id method's frame and id parameters were shifted one level relative to the cache parameter; and the unwind->reg method had it's frame shifted one level.

By doing this, both methods are consistently passed the NEXT frame and THIS cache, where THIS cache contains prologue analysis information for THIS frame's function.

Before they weren't and this would result in the two methods having conflicting ideas as to what the cache should contain, and the unwind->id method should return.

The bulk of the patch is adjusting all the references so that they consistently work with it. There are two hacks though:

- legacy_saved_regs_prev_register()
walks along the frame chain so that it has the frame needed by the deprecated init frame extra info method.


- dummy_frame_this_id()
Goes through hoops to get the frame's id when a legacy frame.

Tested in i386 and PPC (old), and d10v (new).
I'll look to commit this after the weekend.

Andrew

PS: I left out off the d10v changes.
2003-03-14  Andrew Cagney  <cagney at redhat dot com>

	* frame-unwind.h (frame_this_id_ftype): Replace
	frame_unwind_id_ftype.
	(frame_prev_register_ftype): Replace frame_unwind_reg_ftype.
	(struct frame_unwind): Replace "id" with "this_id".  Replace "reg"
	with "prev_register".
	* frame-unwind.c (frame_unwind_find_by_pc): Return
	legacy_saved_regs_unwind instead of trad_frame_unwind.  Update
	comment.
	* dummy-frame.c (cached_find_dummy_frame): Delete function.
	(dummy_frame_this_id): Replace dummy_frame_id_unwind.
	(dummy_frame_prev_register): Replace dummy_frame_register_unwind.
	(dummy_frame_unwind): Update.
	* sentinel-frame.c (sentinel_frame_prev_register): Replace
	sentinel_frame_register_unwind.
	(sentinel_frame_this_id): Replace sentinel_frame_id_unwind.
	(sentinel_frame_unwinder): Update.
	* frame.h (legacy_saved_regs_unwind): Replace trad_frame_unwind.
	(struct frame_info): Rename "unwind_cache" to "prologue_cache".
	* frame.c (create_sentinel_frame): Update. Initialize
	"prologue_cache" instead of "unwind_cache".
	(frame_register_unwind): Call this frame's prev_register with the
	next frame and this frame's prologue cache.
	(get_prev_frame): Simplify.  Always call prev frame's this_id with
	this frame and prev frame's prologue cache.  Document that this
	call is shifted one to the left when compared to the
	frame_register_unwind call.
	(legacy_saved_regs_prev_register): Replace
	frame_saved_regs_register_unwind.
	(legacy_saved_regs_this_id): Replace frame_saved_regs_id_unwind.
	(legacy_saved_regs_unwinder): Replace trad_frame_unwinder.
	(legacy_saved_regs_unwind): Replace trad_frame_unwind.

Index: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.12
diff -u -r1.12 dummy-frame.c
--- dummy-frame.c	12 Mar 2003 15:39:30 -0000	1.12
+++ dummy-frame.c	14 Mar 2003 23:49:52 -0000
@@ -30,6 +30,10 @@
 #include "gdb_assert.h"
 #include "frame-unwind.h"
 
+static void dummy_frame_this_id (struct frame_info *next_frame,
+				 void **this_prologue_cache,
+				 struct frame_id *this_id);
+
 /* Dummy frame.  This saves the processor state just prior to setting
    up the inferior function call.  Older targets save the registers
    on the target stack (but that really slows down function calls).  */
@@ -104,14 +108,6 @@
   return NULL;
 }
 
-struct dummy_frame *
-cached_find_dummy_frame (struct frame_info *frame, void **cache)
-{
-  if ((*cache) == NULL)
-    (*cache) = find_dummy_frame (get_frame_pc (frame), get_frame_base (frame));
-  return (*cache);
-}
-
 struct regcache *
 generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
 {
@@ -313,12 +309,19 @@
    register value is taken from the local copy of the register buffer.  */
 
 static void
-dummy_frame_register_unwind (struct frame_info *frame, void **cache,
-			     int regnum, int *optimized,
-			     enum lval_type *lvalp, CORE_ADDR *addrp,
-			     int *realnum, void *bufferp)
+dummy_frame_prev_register (struct frame_info *next_frame,
+			   void **this_prologue_cache,
+			   int regnum, int *optimized,
+			   enum lval_type *lvalp, CORE_ADDR *addrp,
+			   int *realnum, void *bufferp)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+  struct dummy_frame *dummy;
+  struct frame_id id;
+
+  /* Call the ID method which, if at all possible, will set the
+     prologue cache.  */
+  dummy_frame_this_id (next_frame, this_prologue_cache, &id);
+  dummy = (*this_prologue_cache);
   gdb_assert (dummy != NULL);
 
   /* Describe the register's location.  Generic dummy frames always
@@ -339,28 +342,80 @@
     }
 }
 
-/* Assuming that FRAME is a dummy, return the ID of the calling frame
-   (the frame that the dummy has the saved state of).  */
+/* Assuming that THIS frame is a dummy (remember, the NEXT and not
+   THIS frame is passed in), return the ID of THIS frame.  That ID is
+   determined by examining the NEXT frame's unwound registers using
+   the method unwind_dummy_id().  As a side effect, THIS dummy frame's
+   dummy cache is located and and saved in THIS_PROLOGUE_CACHE.  */
 
 static void
-dummy_frame_id_unwind (struct frame_info *frame,
-		       void **cache,
-		       struct frame_id *id)
-{
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
-  /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
-     that the frame doesn't unwind.  Should this function instead
-     return a has-no-caller indication?  */
-  if (dummy == NULL)
-    (*id) = null_frame_id;
+dummy_frame_this_id (struct frame_info *next_frame,
+		     void **this_prologue_cache,
+		     struct frame_id *this_id)
+{
+  struct dummy_frame *dummy = (*this_prologue_cache);
+  if (dummy != NULL)
+    {
+      (*this_id) = dummy->id;
+      return;
+    }
+  /* When unwinding a normal frame, the stack structure is determined
+     by analyzing the frame's function's code (be it using brute force
+     prologue analysis, or the dwarf2 CFI).  In the case of a dummy
+     frame, that simply isn't possible.  The The PC is either the
+     program entry point, or some random address on the stack.  Trying
+     to use that PC to apply standard frame ID unwind techniques is
+     just asking for trouble.  */
+  if (gdbarch_unwind_dummy_id_p (current_gdbarch))
+    {
+      /* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS,
+	 previously saved the dummy frame's ID.  Things only work if
+	 the two return the same value.  */
+      gdb_assert (SAVE_DUMMY_FRAME_TOS_P ());
+      /* Use an architecture specific method to extract the prev's
+	 dummy ID from the next frame.  Note that this method uses
+	 frame_register_unwind to obtain the register values needed to
+	 determine the dummy frame's ID.  */
+      (*this_id) = gdbarch_unwind_dummy_id (current_gdbarch, next_frame);
+    }
+  else if (frame_relative_level (next_frame) < 0)
+    {
+      /* We're unwinding a sentinel frame, the PC of which is pointing
+	 at a stack dummy.  Fake up the dummy frame's ID using the
+	 same sequence as is found a traditional unwinder.  Once all
+	 architectures supply the unwind_dummy_id method, this code
+	 can go away.  */
+      (*this_id).base = read_fp ();
+      (*this_id).pc = read_pc ();
+    }
+  else if (legacy_frame_p (current_gdbarch)
+	   && get_prev_frame (next_frame))
+    {
+      /* Things are looking seriously grim!  Assume that the legacy
+         get_prev_frame code has already created THIS frame and linked
+         it in to the frame chain (a pretty bold assumption), extract
+         the ID from THIS base / pc.  */
+      (*this_id).base = get_frame_base (get_prev_frame (next_frame));
+      (*this_id).pc = get_frame_pc (get_prev_frame (next_frame));
+    }
   else
-    (*id) = dummy->id;
+    {
+      /* Outch!  We're not trying to find the innermost frame's ID yet
+	 we're trying to unwind to a dummy.  The architecture must
+	 provide the unwind_dummy_id() method.  Abandon the unwind
+	 process but only after first warning the user.  */
+      internal_warning (__FILE__, __LINE__,
+			"Missing unwind_dummy_id architecture method");
+      (*this_id) = null_frame_id;
+      return;
+    }
+  (*this_prologue_cache) = find_dummy_frame ((*this_id).pc, (*this_id).base);
 }
 
 static struct frame_unwind dummy_frame_unwind =
 {
-  dummy_frame_id_unwind,
-  dummy_frame_register_unwind
+  dummy_frame_this_id,
+  dummy_frame_prev_register
 };
 
 const struct frame_unwind *
Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.2
diff -u -r1.2 frame-unwind.c
--- frame-unwind.c	18 Jan 2003 17:25:23 -0000	1.2
+++ frame-unwind.c	14 Mar 2003 23:49:52 -0000
@@ -83,16 +83,19 @@
   int i;
   struct frame_unwind_table *table =
     gdbarch_data (gdbarch, frame_unwind_data);
-  /* Seriously old code.  Don't even try to use this new mechanism.  */
   if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
-    return trad_frame_unwind;
+    /* Seriously old code.  Don't even try to use this new mechanism.
+       (Note: The variable USE_GENERIC_DUMMY_FRAMES is deprecated, not
+       the dummy frame mechanism.  All architectures should be using
+       generic dummy frames).  */
+    return legacy_saved_regs_unwind;
   for (i = 0; i < table->nr; i++)
     {
       const struct frame_unwind *desc = table->p[i] (pc);
       if (desc != NULL)
 	return desc;
     }
-  return trad_frame_unwind;
+  return legacy_saved_regs_unwind;
 }
 
 void
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.5
diff -u -r1.5 frame-unwind.h
--- frame-unwind.h	12 Mar 2003 15:39:30 -0000	1.5
+++ frame-unwind.h	14 Mar 2003 23:49:52 -0000
@@ -47,42 +47,92 @@
 							   *gdbarch,
 							   CORE_ADDR pc);
 
-/* Return the location (and possibly value) of REGNUM for the previous
-   (older, up) frame.  All parameters except VALUEP can be assumed to
-   be non NULL.  When VALUEP is NULL, just the location of the
-   register should be returned.
-
-   UNWIND_CACHE is provided as mechanism for implementing a per-frame
-   local cache.  It's initial value being NULL.  Memory for that cache
-   should be allocated using frame_obstack_zalloc().
-
-   Register window architectures (eg SPARC) should note that REGNUM
-   identifies the register for the previous frame.  For instance, a
-   request for the value of "o1" for the previous frame would be found
-   in the register "i1" in this FRAME.  */
-
-typedef void (frame_unwind_reg_ftype) (struct frame_info * frame,
-				       void **unwind_cache,
-				       int regnum,
-				       int *optimized,
-				       enum lval_type * lvalp,
-				       CORE_ADDR *addrp,
-				       int *realnump, void *valuep);
-
-/* Same as for registers above, but return the ID of the frame that
-   called this one.  */
-
-typedef void (frame_unwind_id_ftype) (struct frame_info * frame,
-				      void **unwind_cache,
-				      struct frame_id * id);
+/* The following unwind functions assume a chain of frames forming the
+   sequence: (outer) prev <-> this <-> next (inner).  All the
+   functions are called with called with the next frame's `struct
+   frame_info' and and this frame's prologue cache.
+
+   THIS frame's register values can be obtained by unwinding NEXT
+   frame's registers (a recursive operation).
+
+   THIS frame's prologue cache can be used to cache information such
+   as where this frame's prologue stores the previous frame's
+   registers.  */
+
+/* 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.
+
+   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
+   the frame's function's code address.
+
+   Traditionally, THIS frame's ID was determined by examining THIS
+   frame's function's prologue, and identifying the register/offset
+   used as THIS frame's base.
+
+   Example: An examination of THIS frame's prologue reveals that, on
+   entry, it saves the PC(+12), SP(+8), and R1(+4) registers
+   (decrementing the SP by 12).  Consequently, the frame ID's base can
+   be determined by adding 12 to the THIS frame's stack-pointer, and
+   the value of THIS frame's SP can be obtained by unwinding the NEXT
+   frame's SP.
+
+   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_this_id_ftype) (struct frame_info *next_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).
+
+   Traditionally, THIS frame's registers were unwound by examining
+   THIS frame's function's prologue and identifying which registers
+   that prolog code saved on the stack.
+
+   Example: An examination of THIS frame's prologue reveals that, on
+   entry, it saves the PC(+12), SP(+8), and R1(+4) registers
+   (decrementing the SP by 12).  Consequently, the value of the PC
+   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.
+
+   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.
+
+   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, void *valuep);
 
 struct frame_unwind
 {
   /* Should the frame's type go here? */
   /* Should an attribute indicating the frame's address-in-block go
      here?  */
-  frame_unwind_id_ftype *id;
-  frame_unwind_reg_ftype *reg;
+  frame_this_id_ftype *this_id;
+  frame_prev_register_ftype *prev_register;
 };
 
 #endif
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.85
diff -u -r1.85 frame.c
--- frame.c	14 Mar 2003 20:34:14 -0000	1.85
+++ frame.c	14 Mar 2003 23:49:52 -0000
@@ -247,9 +247,12 @@
      detected the problem before calling here.  */
   gdb_assert (frame != NULL);
 
-  /* Ask this frame to unwind its register.  */
-  frame->unwind->reg (frame, &frame->unwind_cache, regnum,
-		      optimizedp, lvalp, addrp, realnump, bufferp);
+  /* Ask this frame to unwind its register.  See comment in
+     "frame-unwind.h" for why NEXT frame and this unwind cace are
+     passed in.  */
+  frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum,
+				optimizedp, lvalp, addrp, realnump, bufferp);
+
 }
 
 void
@@ -483,7 +486,7 @@
   /* Explicitly initialize the sentinel frame's cache.  Provide it
      with the underlying regcache.  In the future additional
      information, such as the frame's thread will be added.  */
-  frame->unwind_cache = sentinel_frame_cache (regcache);
+  frame->prologue_cache = sentinel_frame_cache (regcache);
   /* For the moment there is only one sentinel frame implementation.  */
   frame->unwind = sentinel_frame_unwind;
   /* Link this frame back to itself.  The frame is self referential
@@ -640,19 +643,20 @@
    most frame.  */
 
 static void
-frame_saved_regs_register_unwind (struct frame_info *frame, void **cache,
-				  int regnum, int *optimizedp,
-				  enum lval_type *lvalp, CORE_ADDR *addrp,
-				  int *realnump, void *bufferp)
-{
-  /* There is always a frame at this point.  And THIS is the frame
-     we're interested in.  */
+legacy_saved_regs_prev_register (struct frame_info *next_frame,
+				 void **this_prologue_cache,
+				 int regnum, int *optimizedp,
+				 enum lval_type *lvalp, CORE_ADDR *addrp,
+				 int *realnump, void *bufferp)
+{
+  /* HACK: New code is passed the next frame and this cache.
+     Unfortunatly, old code expects this frame.  Since this is a
+     backward compatibility hack, cheat by walking one level along the
+     prologue chain to the frame the old code expects.
+
+     Do not try this at home.  Professional driver, closed course.  */
+  struct frame_info *frame = next_frame->prev;
   gdb_assert (frame != NULL);
-  /* If we're using generic dummy frames, we'd better not be in a call
-     dummy.  (generic_call_dummy_register_unwind ought to have been called
-     instead.)  */
-  gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-		&& (get_frame_type (frame) == DUMMY_FRAME)));
 
   /* Only (older) architectures that implement the
      DEPRECATED_FRAME_INIT_SAVED_REGS method should be using this
@@ -690,13 +694,13 @@
 #if 1
 	      /* Save each register value, as it is read in, in a
                  frame based cache.  */
-	      void **regs = (*cache);
+	      void **regs = (*this_prologue_cache);
 	      if (regs == NULL)
 		{
 		  int sizeof_cache = ((NUM_REGS + NUM_PSEUDO_REGS)
 				      * sizeof (void *));
 		  regs = frame_obstack_zalloc (sizeof_cache);
-		  (*cache) = regs;
+		  (*this_prologue_cache) = regs;
 		}
 	      if (regs[regnum] == NULL)
 		{
@@ -716,22 +720,33 @@
       return;
     }
 
-  /* No luck, assume this and the next frame have the same register
-     value.  Pass the request down the frame chain to the next frame.
-     Hopefully that will find the register's location, either in a
-     register or in memory.  */
-  frame_register (frame, regnum, optimizedp, lvalp, addrp, realnump,
-		  bufferp);
+  /* No luck.  Assume this and the next frame have the same register
+     value.  Pass the unwind request down the frame chain to the next
+     frame.  Hopefully that frame will find the register's location.  */
+  frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp,
+			 realnump, bufferp);
 }
 
 static void
-frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache,
-			    struct frame_id *id)
+legacy_saved_regs_this_id (struct frame_info *next_frame,
+			   void **this_prologue_cache,
+			   struct frame_id *id)
 {
   int fromleaf;
   CORE_ADDR base;
   CORE_ADDR pc;
 
+  if (frame_relative_level (next_frame) < 0)
+    {
+      /* FIXME: cagney/2003-03-14: We've got the extra special case of
+	 unwinding a sentinel frame, the PC of which is pointing at a
+	 stack dummy.  Fake up the dummy frame's ID using the same
+	 sequence as is found a traditional unwinder.  */
+      (*id).base = read_fp ();
+      (*id).pc = read_pc ();
+      return;
+    }
+
   /* Start out by assuming it's NULL.  */
   (*id) = null_frame_id;
 
@@ -785,15 +800,14 @@
   id->base = base;
 }
 	
-const struct frame_unwind trad_frame_unwinder = {
-  frame_saved_regs_id_unwind,
-  frame_saved_regs_register_unwind
+const struct frame_unwind legacy_saved_regs_unwinder = {
+  legacy_saved_regs_this_id,
+  legacy_saved_regs_prev_register
 };
-const struct frame_unwind *trad_frame_unwind = &trad_frame_unwinder;
+const struct frame_unwind *legacy_saved_regs_unwind = &legacy_saved_regs_unwinder;
 
 
 /* Function: deprecated_generic_get_saved_register
-
    Find register number REGNUM relative to FRAME and put its (raw,
    target format) contents in *RAW_BUFFER.
 
@@ -1489,62 +1503,56 @@
 						prev_frame->pc);
 
   /* Find the prev's frame's ID.  */
-  switch (prev_frame->type)
+
+  /* The callee expects to be invoked with:
+
+     this->unwind->this_id (this->next, &this->cache, &this->id);
+
+     The below is carefully shifted one frame `to the left' so that
+     both the unwind->this_id and unwind->prev_register methods are
+     consistently invoked with NEXT_FRAME and THIS_PROLOGUE_CACHE.
+       
+     Also note that, while the PC for this new previous frame was
+     unwound first (see above), the below is the first call that
+     [potentially] requires analysis of the new previous frame's
+     prologue.  Consequently, it is this call, that typically ends up
+     initializing the previous frame's prologue cache.  */
+  prev_frame->unwind->this_id (this_frame,
+			       &prev_frame->prologue_cache,
+			       &prev_frame->id);
+
+  /* Check that the unwound ID is valid.  */
+  if (!frame_id_p (prev_frame->id))
     {
-    case DUMMY_FRAME:
-      /* When unwinding a normal frame, the stack structure is
-	 determined by analyzing the frame's function's code (be it
-	 using brute force prologue analysis, or the dwarf2 CFI).  In
-	 the case of a dummy frame, that simply isn't possible.  The
-	 The PC is either the program entry point, or some random
-	 address on the stack.  Trying to use that PC to apply
-	 standard frame ID unwind techniques is just asking for
-	 trouble.  */
-      gdb_assert (gdbarch_unwind_dummy_id_p (current_gdbarch));
-	/* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS,
-	   previously saved the dummy frame's ID.  Things only work if
-	   the two return the same value.  */
-      gdb_assert (SAVE_DUMMY_FRAME_TOS_P ());
-      /* Use an architecture specific method to extract the prev's
-	 dummy ID from the next frame.  Note that this method uses
-	 frame_register_unwind to obtain the register values needed to
-	 determine the dummy frame's ID.  */
-      prev_frame->id = gdbarch_unwind_dummy_id (current_gdbarch, this_frame);
-      break;
-    case NORMAL_FRAME:
-    case SIGTRAMP_FRAME:
-      /* FIXME: cagney/2003-03-04: The below call isn't right.  It
-	 should instead be doing something like "prev_frame -> unwind
-	 -> id (this_frame, & prev_frame -> unwind_cache, & prev_frame
-	 -> id)" but that requires more extensive (pending) changes.  */
-      this_frame->unwind->id (this_frame, &this_frame->unwind_cache,
-			      &prev_frame->id);
-      /* Check that the unwound ID is valid.  */
-      if (!frame_id_p (prev_frame->id))
-	{
-	  if (frame_debug)
-	    fprintf_unfiltered (gdb_stdlog,
-				"Outermost frame - unwound frame ID invalid\n");
-	  return NULL;
-	}
-      /* Check that the new frame isn't inner to (younger, below,
-	 next) the old frame.  If that happens the frame unwind is
-	 going backwards.  */
-      /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since
-	 that doesn't have a valid frame ID.  Should instead set the
-	 sentinel frame's frame ID to a `sentinel'.  Leave it until
-	 after the switch to storing the frame ID, instead of the
-	 frame base, in the frame object.  */
-      if (this_frame->level >= 0
-	  && frame_id_inner (prev_frame->id, get_frame_id (this_frame)))
-	error ("Unwound frame inner-to selected frame (corrupt stack?)");
-      /* Note that, due to frameless functions, the stronger test of
-	 the new frame being outer to the old frame can't be used -
-	 frameless functions differ by only their PC value.  */
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, "bad switch");
+      if (frame_debug)
+	fprintf_unfiltered (gdb_stdlog,
+			    "Outermost frame - unwound frame ID invalid\n");
+      return NULL;
     }
+
+  /* Check that the new frame isn't inner to (younger, below, next)
+     the old frame.  If that happens the frame unwind is going
+     backwards.  */
+  /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since that
+     doesn't have a valid frame ID.  Should instead set the sentinel
+     frame's frame ID to a true `sentinel'.  Leave it until after the
+     switch to storing the frame ID, instead of the frame base, in the
+     frame object.  */
+  if (this_frame->level >= 0
+      && frame_id_inner (prev_frame->id, get_frame_id (this_frame)))
+    error ("Unwound frame inner-to selected frame (corrupt stack?)");
+
+  /* FIXME: cagney/2003-03-14: Should check that this and next frame's
+     IDs are different (i.e., !frame_id_eq()).  Can't yet do that as
+     the EQ function doesn't yet compare PC values.  */
+
+  /* FIXME: cagney/2003-03-14: Should delay the evaluation of the
+     frame ID until when it is needed.  That way the inner most frame
+     can be created without needing to do prologue analysis.  */
+
+  /* Note that, due to frameless functions, the stronger test of the
+     new frame being outer to the old frame can't be used - frameless
+     functions differ by only their PC value.  */
 
   /* FIXME: cagney/2002-12-18: Instead of this hack, should only store
      the frame ID in PREV_FRAME.  Unfortunatly, some architectures
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.74
diff -u -r1.74 frame.h
--- frame.h	14 Mar 2003 17:07:00 -0000	1.74
+++ frame.h	14 Mar 2003 23:49:53 -0000
@@ -27,8 +27,9 @@
 struct frame_unwind;
 struct block;
 
-/* The traditional frame unwinder.  */
-extern const struct frame_unwind *trad_frame_unwind;
+/* A legacy unwinder to prop up architectures using the old style
+   saved regs array.  */
+extern const struct frame_unwind *legacy_saved_regs_unwind;
 
 /* The frame object.  */
 
@@ -397,9 +398,9 @@
        related unwind data.  */
     struct context *context;
 
-    /* Unwind cache shared between the unwind functions - they had
-       better all agree as to the contents.  */
-    void *unwind_cache;
+    /* Prologue cache shared between the unwind functions.  See
+       "frame-unwind.h" for more information.  */
+    void *prologue_cache;
 
     /* The frame's unwinder.  */
     const struct frame_unwind *unwind;
Index: sentinel-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/sentinel-frame.c,v
retrieving revision 1.4
diff -u -r1.4 sentinel-frame.c
--- sentinel-frame.c	12 Mar 2003 15:39:30 -0000	1.4
+++ sentinel-frame.c	14 Mar 2003 23:49:54 -0000
@@ -45,13 +45,13 @@
 /* Here the register value is taken direct from the register cache.  */
 
 void
-sentinel_frame_register_unwind (struct frame_info *frame,
-				void **unwind_cache,
-				int regnum, int *optimized,
-				enum lval_type *lvalp, CORE_ADDR *addrp,
-				int *realnum, void *bufferp)
+sentinel_frame_prev_register (struct frame_info *next_frame,
+			      void **this_prologue_cache,
+			      int regnum, int *optimized,
+			      enum lval_type *lvalp, CORE_ADDR *addrp,
+			      int *realnum, void *bufferp)
 {
-  struct frame_unwind_cache *cache = *unwind_cache;
+  struct frame_unwind_cache *cache = *this_prologue_cache;
   /* Describe the register's location.  A reg-frame maps all registers
      onto the corresponding hardware register.  */
   *optimized = 0;
@@ -71,22 +71,20 @@
 }
 
 void
-sentinel_frame_id_unwind (struct frame_info *frame,
-			  void **cache,
-			  struct frame_id *id)
+sentinel_frame_this_id (struct frame_info *next_frame,
+			void **this_prologue_cache,
+			struct frame_id *this_id)
 {
-  /* FIXME: cagney/2003-01-08: This should be using a per-architecture
-     method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
-     Such a method would take unwind_cache, regcache and stop reason
-     parameters.  */
-  id->base = read_fp ();
-  id->pc = read_pc ();
+  /* The sentinel frame is used as a starting point for creating the
+     previous (inner most) frame.  That frame's THIS_ID method will be
+     called to determine the inner most frame's ID.  Not this one.  */
+  internal_error (__FILE__, __LINE__, "sentinel_frame_this_id called");
 }
 
 const struct frame_unwind sentinel_frame_unwinder =
 {
-  sentinel_frame_id_unwind,
-  sentinel_frame_register_unwind
+  sentinel_frame_this_id,
+  sentinel_frame_prev_register
 };
 
 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]