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]

[offbyone] Fix i386


This patch gets the i386 working again. legacy_saved_regs_this_id() wasn't handling a backward compatibility edge case involving a sentinel frame.

It follows the fix with a cleanup of get-prev-frame.

committed,
Andrew
2003-03-13  Andrew Cagney  <cagney at redhat dot com>

	* frame.c (legacy_saved_regs_this_id): Handle a sentinel frame.
	(get_prev_frame): Simplify.  Frame ID logic moved to
	dummy_frame_this_id and legacy_saved_regs_this_id.

Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.80.2.1
diff -u -r1.80.2.1 frame.c
--- frame.c	13 Mar 2003 17:33:52 -0000	1.80.2.1
+++ frame.c	13 Mar 2003 21:35:58 -0000
@@ -745,30 +745,40 @@
 			   void **this_prologue_cache,
 			   struct frame_id *id)
 {
-  int fromleaf;
   CORE_ADDR base;
   CORE_ADDR pc;
 
   /* Start out by assuming it's NULL.  */
   (*id) = null_frame_id;
 
-  if (frame_relative_level (next_frame) <= 0)
-    /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
-       the frame chain, not just the inner most frame!  The generic,
-       per-architecture, frame code should handle this and the below
-       should simply be removed.  */
-    fromleaf = FRAMELESS_FUNCTION_INVOCATION (next_frame);
-  else
-    fromleaf = 0;
-
-  if (fromleaf)
-    /* A frameless inner-most frame.  The `FP' (which isn't an
-       architecture frame-pointer register!) of the caller is the same
-       as the callee.  */
-    /* FIXME: 2002-11-09: There isn't any reason to special case this
-       edge condition.  Instead the per-architecture code should hande
-       it locally.  */
-    base = get_frame_base (next_frame);
+  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.  */
+      base = read_fp ();
+      pc = read_pc ();
+    }
+  else if (frame_relative_level (next_frame) == 0
+	   && FRAMELESS_FUNCTION_INVOCATION (next_frame))
+    {
+      /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
+	 the frame chain, not just the inner most frame!  The generic,
+	 per-architecture, frame code should handle this and the below
+	 should simply be removed.  */
+      /* A frameless inner-most frame.  The `FP' (which isn't an
+	 architecture frame-pointer register!) of the caller is the
+	 same as the callee.  */
+      /* FIXME: 2002-11-09: There isn't any reason to special case
+	 this edge condition.  Instead the per-architecture code
+	 should hande it locally.  */
+      base = get_frame_base (next_frame);
+      /* FIXME: cagney/2002-06-08: This should probably return the frame's
+	 function and not the PC (a.k.a. resume address).  */
+      pc = frame_pc_unwind (next_frame);
+    }
   else
     {
       /* Two macros defined in tm.h specify the machine-dependent
@@ -788,16 +798,12 @@
          main.  */
       gdb_assert (FRAME_CHAIN_P ());
       base = FRAME_CHAIN (next_frame);
-
       if (!frame_chain_valid (base, next_frame))
 	return;
+      /* FIXME: cagney/2002-06-08: This should probably return the
+	 frame's function and not the PC (a.k.a. resume address).  */
+      pc = frame_pc_unwind (next_frame);
     }
-  if (base == 0)
-    return;
-
-  /* FIXME: cagney/2002-06-08: This should probably return the frame's
-     function and not the PC (a.k.a. resume address).  */
-  pc = frame_pc_unwind (next_frame);
   id->pc = pc;
   id->base = base;
 }
@@ -1385,96 +1391,48 @@
 						prev_frame->pc);
 
   /* Find the prev's frame's ID.  */
-  switch (prev_frame->type)
-    {
-    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.  */
-      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.  */
-	  prev_frame->id = gdbarch_unwind_dummy_id (current_gdbarch,
-						    this_frame);
-	}
-      else if (this_frame->level < 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.  */
-	  prev_frame->id.base = read_fp ();
-	  prev_frame->id.pc = read_pc ();
-	}
-      else
-	{
-	  /* Outch!  We're not on the innermost frame 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");
-	  return NULL;
-	}
-      break;
-    case NORMAL_FRAME:
-    case SIGTRAMP_FRAME:
-      /* 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.
+
+  /* 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))
-	{
-	  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");
+     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))
+    {
+      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?)");
+
+  /* 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]