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] Move all legacy get-prev-frame code legacy-...


Hello,

This patch copies the code that does a get-prev-frame (sentinel_frame), when a legacy target, to legacy_get_prev_frame(). Since it's a mechanical change, I think it is straight forward.

It then simplifies get_prev_frame() since that doesn't need to handle legacy frames.

Tested on ppc and i386 (legacy), and d10v (new).  Committed,
Andrew
2003-03-14  Andrew Cagney  <cagney at redhat dot com>

	* frame.c (get_prev_frame): When a legacy frame, always call
	legacy_get_prev_frame.  Simplify unwind code using assumption that
	the unwinder is new.
	(legacy_get_prev_frame): Handle legacy sentinel frame unwind here.
	(legacy_frame_p): When no gdbarch_unwind_dummy_id, or
	SAVED_DUMMY_FRAME_TOS, assume a legacy frame.

Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.81
diff -u -r1.81 frame.c
--- frame.c	13 Mar 2003 18:09:29 -0000	1.81
+++ frame.c	14 Mar 2003 20:20:21 -0000
@@ -1011,6 +1011,142 @@
   struct frame_info *prev;
   int fromleaf;
 
+  /* Allocate the new frame but do not wire it in to the frame chain.
+     Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along
+     frame->next to pull some fancy tricks (of course such code is, by
+     definition, recursive).  Try to prevent it.
+
+     There is no reason to worry about memory leaks, should the
+     remainder of the function fail.  The allocated memory will be
+     quickly reclaimed when the frame cache is flushed, and the `we've
+     been here before' check, in get_prev_frame will stop repeated
+     memory allocation calls.  */
+  prev = FRAME_OBSTACK_ZALLOC (struct frame_info);
+  prev->level = this_frame->level + 1;
+
+  /* NOTE: cagney/2002-11-18: Should have been correctly setting the
+     frame's type here, before anything else, and not last, at the
+     bottom of this function.  The various
+     DEPRECATED_INIT_EXTRA_FRAME_INFO, DEPRECATED_INIT_FRAME_PC,
+     DEPRECATED_INIT_FRAME_PC_FIRST and
+     DEPRECATED_FRAME_INIT_SAVED_REGS methods are full of work-arounds
+     that handle the frame not being correctly set from the start.
+     Unfortunatly those same work-arounds rely on the type defaulting
+     to NORMAL_FRAME.  Ulgh!  The new frame code does not have this
+     problem.  */
+  prev->type = NORMAL_FRAME;
+
+  /* Handle sentinel frame unwind as a special case.  */
+  if (this_frame->level < 0)
+    {
+      /* Try to unwind the PC.  If that doesn't work, assume we've reached
+	 the oldest frame and simply return.  Is there a better sentinal
+	 value?  The unwound PC value is then used to initialize the new
+	 previous frame's type.
+
+	 Note that the pc-unwind is intentionally performed before the
+	 frame chain.  This is ok since, for old targets, both
+	 frame_pc_unwind (nee, FRAME_SAVED_PC) and FRAME_CHAIN()) assume
+	 THIS_FRAME's data structures have already been initialized (using
+	 DEPRECATED_INIT_EXTRA_FRAME_INFO) and hence the call order
+	 doesn't matter.
+	 
+	 By unwinding the PC first, it becomes possible to, in the case of
+	 a dummy frame, avoid also unwinding the frame ID.  This is
+	 because (well ignoring the PPC) a dummy frame can be located
+	 using THIS_FRAME's frame ID.  */
+      
+      prev->pc = frame_pc_unwind (this_frame);
+      if (prev->pc == 0)
+	{
+	  /* The allocated PREV_FRAME will be reclaimed when the frame
+	     obstack is next purged.  */
+	  if (frame_debug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"Outermost frame - unwound PC zero\n");
+	  return NULL;
+	}
+      prev->type = frame_type_from_pc (prev->pc);
+
+      /* Set the unwind functions based on that identified PC.  */
+      prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc);
+
+      /* Find the prev's frame's ID.  */
+      if (prev->type == DUMMY_FRAME
+	  && gdbarch_unwind_dummy_id_p (current_gdbarch))
+	{
+	  /* 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.  */
+	  /* 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->id = gdbarch_unwind_dummy_id (current_gdbarch, this_frame);
+	}
+      else
+	{
+	  /* 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->id.base = read_fp ();
+	  prev->id.pc = read_pc ();
+	}
+
+      /* Check that the unwound ID is valid.  */
+      if (!frame_id_p (prev->id))
+	{
+	  if (frame_debug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"Outermost legacy sentinel 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.  */
+
+      /* FIXME: cagney/2002-12-18: Instead of this hack, should only
+	 store the frame ID in PREV_FRAME.  Unfortunatly, some
+	 architectures (HP/UX) still reply on EXTRA_FRAME_INFO and,
+	 hence, still poke at the "struct frame_info" object directly.  */
+      prev->frame = prev->id.base;
+
+      /* Link it in.  */
+      this_frame->prev = prev;
+      prev->next = this_frame;
+
+      /* FIXME: cagney/2002-01-19: This call will go away.  Instead of
+	 initializing extra info, all frames will use the frame_cache
+	 (passed to the unwind functions) to store additional frame
+	 info.  Unfortunatly legacy targets can't use
+	 legacy_get_prev_frame() to unwind the sentinel frame and,
+	 consequently, are forced to take this code path and rely on
+	 the below call to DEPRECATED_INIT_EXTRA_FRAME_INFO to
+	 initialize the inner-most frame.  */
+      if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
+	{
+	  DEPRECATED_INIT_EXTRA_FRAME_INFO (0, prev);
+	}
+      return prev;
+    }
+
   /* This code only works on normal frames.  A sentinel frame, where
      the level is -1, should never reach this code.  */
   gdb_assert (this_frame->level >= 0);
@@ -1067,19 +1203,10 @@
   if (address == 0)
     return 0;
 
-  /* Create an initially zero previous frame.  */
-  prev = frame_obstack_zalloc (sizeof (struct frame_info));
-
-  /* Link it in.  */
+  /* Link in the already allocated prev frame.  */
   this_frame->prev = prev;
   prev->next = this_frame;
   prev->frame = address;
-  prev->level = this_frame->level + 1;
-  /* FIXME: cagney/2002-11-18: Should be setting the frame's type
-     here, before anything else, and not last.  Various INIT functions
-     are full of work-arounds for the frames type not being set
-     correctly from the word go.  Ulgh!  */
-  prev->type = NORMAL_FRAME;
 
   /* This change should not be needed, FIXME!  We should determine
      whether any targets *need* DEPRECATED_INIT_FRAME_PC to happen
@@ -1324,11 +1451,8 @@
     }
 
   /* If any of the old frame initialization methods are around, use
-     the legacy get_prev_frame method.  Just don't try to unwind a
-     sentinel frame using that method - it doesn't work.  All sentinal
-     frames use the new unwind code.  */
-  if (legacy_frame_p (current_gdbarch)
-      && this_frame->level >= 0)
+     the legacy get_prev_frame method.  */
+  if (legacy_frame_p (current_gdbarch))
     {
       prev_frame = legacy_get_prev_frame (this_frame);
       if (frame_debug && prev_frame == NULL)
@@ -1395,39 +1519,16 @@
 	 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;
-	}
+      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:
@@ -1474,20 +1575,6 @@
   this_frame->prev = prev_frame;
   prev_frame->next = this_frame;
 
-  /* FIXME: cagney/2002-01-19: This call will go away.  Instead of
-     initializing extra info, all frames will use the frame_cache
-     (passed to the unwind functions) to store additional frame info.
-     Unfortunatly legacy targets can't use legacy_get_prev_frame() to
-     unwind the sentinel frame and, consequently, are forced to take
-     this code path and rely on the below call to
-     DEPRECATED_INIT_EXTRA_FRAME_INFO to initialize the inner-most
-     frame.  */
-  if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
-    {
-      gdb_assert (prev_frame->level == 0);
-      DEPRECATED_INIT_EXTRA_FRAME_INFO (0, prev_frame);
-    }
-
   return prev_frame;
 }
 
@@ -1699,7 +1786,9 @@
   return (DEPRECATED_INIT_FRAME_PC_P ()
 	  || DEPRECATED_INIT_FRAME_PC_FIRST_P ()
 	  || DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()
-	  || FRAME_CHAIN_P ());
+	  || FRAME_CHAIN_P ()
+	  || !gdbarch_unwind_dummy_id_p (current_gdbarch)
+	  || !SAVE_DUMMY_FRAME_TOS_P ());
 }
 
 void

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