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] Unwind the PC first when creating a frame


Hello,

This patch changes the frame creation code so that it can unwind the PC before doing anything else. By unwinding the PC first, it becomes possible to correctly set the frame from the outset. The old code would set the frame's type last (resulting in architecture code having to back patch it). It also (at least in theory) makes it possible to avoid certain frame unwinds.

Since, right now, all architectures currently specify a deprecated init frame pc method, the code isn't used by any architecture. A follow on will be to enable the code on at least one architecture.

I'll commit the attached in a few days,
enjoy,

Andrew
2002-12-10  Andrew Cagney  <ac131313@redhat.com>

	* frame.c (frame_type_from_pc): New function.
	(create_new_frame): Use frame_type_from_pc instead of custom code.
	(get_prev_frame): When neither DEPRECATED_INIT_FRAME_PC_P nor
	DEPRECATED_INIT_FRAME_PC_FIRST_P use frame_type_from_pc and
	frame_pc_unwind to set the frame's type at the point of frame
	creation.

Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.40
diff -u -r1.40 frame.c
--- frame.c	11 Dec 2002 02:26:35 -0000	1.40
+++ frame.c	11 Dec 2002 02:33:57 -0000
@@ -767,6 +767,29 @@
     }
 }
 
+/* Determine the frame's type based on its PC.  */
+
+static enum frame_type
+frame_type_from_pc (CORE_ADDR pc)
+{
+  /* FIXME: cagney/2002-11-24: Can't yet directly call
+     pc_in_dummy_frame() as some architectures don't set
+     PC_IN_CALL_DUMMY() to generic_pc_in_call_dummy() (remember the
+     latter is implemented by simply calling pc_in_dummy_frame).  */
+  if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
+      && PC_IN_CALL_DUMMY (pc, 0, 0))
+    return DUMMY_FRAME;
+  else
+    {
+      char *name;
+      find_pc_partial_function (pc, &name, NULL, NULL);
+      if (PC_IN_SIGTRAMP (pc, name))
+	return SIGTRAMP_FRAME;
+      else
+	return NORMAL_FRAME;
+    }
+}
+
 /* Create an arbitrary (i.e. address specified by user) or innermost frame.
    Always returns a non-NULL value.  */
 
@@ -785,30 +808,7 @@
 
   fi->frame = addr;
   fi->pc = pc;
-  /* NOTE: cagney/2002-11-18: The code segments, found in
-     create_new_frame and get_prev_frame(), that initializes the
-     frames type is subtly different.  The latter only updates ->type
-     when it encounters a SIGTRAMP_FRAME or DUMMY_FRAME.  This stops
-     get_prev_frame() overriding the frame's type when the INIT code
-     has previously set it.  This is really somewhat bogus.  The
-     initialization, as seen in create_new_frame(), should occur
-     before the INIT function has been called.  */
-  if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-      && (DEPRECATED_PC_IN_CALL_DUMMY_P ()
-	  ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
-	  : pc_in_dummy_frame (pc)))
-    /* NOTE: cagney/2002-11-11: Does this even occure?  */
-    type = DUMMY_FRAME;
-  else
-    {
-      char *name;
-      find_pc_partial_function (pc, &name, NULL, NULL);
-      if (PC_IN_SIGTRAMP (fi->pc, name))
-	type = SIGTRAMP_FRAME;
-      else
-	type = NORMAL_FRAME;
-    }
-  fi->type = type;
+  fi->type = frame_type_from_pc (pc);
 
   if (INIT_EXTRA_FRAME_INFO_P ())
     INIT_EXTRA_FRAME_INFO (0, fi);
@@ -867,6 +867,8 @@
   CORE_ADDR address = 0;
   struct frame_info *prev;
   int fromleaf;
+  CORE_ADDR pc;
+  enum frame_type type;
 
   /* Return the inner-most frame, when the caller passes in NULL.  */
   /* NOTE: cagney/2002-11-09: Not sure how this would happen.  The
@@ -895,6 +897,41 @@
     return next_frame->prev;
   next_frame->prev_p = 1;
 
+  /* 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 (well should be ok) since, for old targets,
+     both frame_pc_unwind (nee, FRAME_SAVED_PC) and FRAME_CHAIN())
+     assume NEXT_FRAME's data structures have already been initialized
+     (using 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 NEXT_FRAME's frame ID.
+
+     For the moment this is only done conditionally.  Some targets
+     (e.g., rs6000) appear to break when this change is enabled.  */
+  if (DEPRECATED_INIT_FRAME_PC_P ()
+      || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
+    {
+      /* Ulgh, old style target that still uses one of the
+         INIT_FRAME_PC methods.  */
+      pc = 0;
+      type = 0;
+    }
+  else
+    {
+      pc = frame_pc_unwind (next_frame);
+      if (pc == 0)
+	return NULL;
+      type = frame_type_from_pc (pc);
+    }
+
   /* On some machines it is possible to call a function without
      setting up a stack frame for it.  On these machines, we
      define this macro to take two args; a frameinfo pointer
@@ -1080,12 +1117,15 @@
      has previously set it.  This is really somewhat bogus.  The
      initialization, as seen in create_new_frame(), should occur
      before the INIT function has been called.  */
-  if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
+  if ((DEPRECATED_INIT_FRAME_PC_P ()
+       || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
+      && DEPRECATED_USE_GENERIC_DUMMY_FRAMES
       && (DEPRECATED_PC_IN_CALL_DUMMY_P ()
 	  ? DEPRECATED_PC_IN_CALL_DUMMY (prev->pc, 0, 0)
 	  : pc_in_dummy_frame (prev->pc)))
     prev->type = DUMMY_FRAME;
-  else
+  else if (DEPRECATED_INIT_FRAME_PC_P ()
+	   || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
     {
       /* FIXME: cagney/2002-11-10: This should be moved to before the
 	 INIT code above so that the INIT code knows what the frame's

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