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] Was: [rfc] unwind_dummy_id


http://sources.redhat.com/ml/gdb/2003-02/msg00549.html

This patch adds such a mechanism. I'm going to table this until someone comes up with evidence that it actually fixes a bug :-)

I've found my evidence. The d10v's stack pointer and frame base sit at oposite ends of a d10v frame. Consequently, when unwinding interleaved frameless functions and dummy frames, the dummy-frame code can mis-locate a dummy frame (one dummy's sp matches the other dummy's fp). Using save_dummy_frame_tos() and unwind_dummy_id() ensures that each dummy frame is identified by a single unique value.


> Anyway. Eli, does the doco look ok?
Yes, thanks.

I've commited the attached. It's been updated to work with current sources. It also gained a few more comments and, when the new code, an extra sanity check.


Andrew

2003-03-05  Andrew Cagney  <cagney at redhat dot com>

	* d10v-tdep.c (d10v_unwind_dummy_id): New function.
	(d10v_gdbarch_init): Set unwind_dummy_id and save_dummy_frame_tos.
	* frame.c (get_prev_frame): Restructure the frame ID unwind code
	to use unwind_dummy_id when a dummy frame.
	* gdbarch.sh (unwind_dummy_id): New multi-arch method with
	predicate.
	* gdbarch.h, gdbarch.c: Regneerate.
	
Index: doc/ChangeLog
2003-03-05  Andrew Cagney  <cagney at redhat dot com>

	* gdbint.texinfo (Target Architecture Definition): Document
	unwind_dummy_id.  Cross reference unwind_dummy_id and
	SAVE_DUMMY_FRAME_TOS.

Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.82
diff -u -r1.82 d10v-tdep.c
--- d10v-tdep.c	5 Mar 2003 22:54:22 -0000	1.82
+++ d10v-tdep.c	5 Mar 2003 23:12:22 -0000
@@ -1612,6 +1612,22 @@
   return &d10v_frame_unwind;
 }
 
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+   dummy frame.  The frame ID's base needs to match the TOS value
+   saved by save_dummy_frame_tos(), and the PC match the dummy frame's
+   breakpoint.  */
+
+static struct frame_id
+d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  ULONGEST base;
+  struct frame_id id;
+  id.pc = frame_pc_unwind (next_frame);
+  frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base);
+  id.base = d10v_make_daddr (base);
+  return id;
+}
+
 static gdbarch_init_ftype d10v_gdbarch_init;
 
 static struct gdbarch *
@@ -1748,6 +1764,10 @@
   set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info);
 
   frame_unwind_append_predicate (gdbarch, d10v_frame_p);
+
+  /* Methods for saving / extracting a dummy frame's ID.  */
+  set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id);
+  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
 
   return gdbarch;
 }
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.73
diff -u -r1.73 frame.c
--- frame.c	5 Mar 2003 20:26:46 -0000	1.73
+++ frame.c	5 Mar 2003 23:12:22 -0000
@@ -1330,39 +1330,86 @@
   prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
 						prev_frame->pc);
 
-  /* FIXME: cagney/2003-01-13: A dummy frame doesn't need to unwind
-     the frame ID because the frame ID comes from the previous frame.
-     The other frames do though.  True?  */
-  /* FIXME: cagney/2003-03-04: The below call isn't right.  It should
-     instead be doing something like "prev_frame -> unwind -> id
-     (next_frame, & prev_frame -> unwind_cache, & prev_frame -> id)"
-     but that requires more extensive (pending) changes.  */
-  next_frame->unwind->id (next_frame, &next_frame->unwind_cache,
-			  &prev_frame->id);
-  /* Check that the unwound ID is valid.  As of 2003-02-24 the x86-64
-     was returning an invalid frame ID when trying to do an unwind a
-     sentinel frame that belonged to a frame dummy.  */
-  if (!frame_id_p (prev_frame->id))
+  /* Find the prev's frame's ID.  */
+  switch (prev_frame->type)
     {
-      if (frame_debug)
-	fprintf_unfiltered (gdb_stdlog,
-			    "Outermost frame - unwound frame ID invalid\n");
-      return NULL;
+    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,
+						    next_frame);
+	}
+      else if (next_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:
+      /* FIXME: cagney/2003-03-04: The below call isn't right.  It
+	 should instead be doing something like "prev_frame -> unwind
+	 -> id (next_frame, & prev_frame -> unwind_cache, & prev_frame
+	 -> id)" but that requires more extensive (pending) changes.  */
+      next_frame->unwind->id (next_frame, &next_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 (next_frame->level >= 0
+	  && frame_id_inner (prev_frame->id, get_frame_id (next_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");
     }
-  /* 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 (next_frame->level >= 0
-      && frame_id_inner (prev_frame->id, get_frame_id (next_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: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.199
diff -u -r1.199 gdbarch.sh
--- gdbarch.sh	3 Mar 2003 20:50:18 -0000	1.199
+++ gdbarch.sh	5 Mar 2003 23:12:23 -0000
@@ -602,6 +602,7 @@
 v:2:EXTRA_STACK_ALIGNMENT_NEEDED:int:extra_stack_alignment_needed::::0:1::0:::
 F:2:REG_STRUCT_HAS_ADDR:int:reg_struct_has_addr:int gcc_p, struct type *type:gcc_p, type::0:0
 F:2:SAVE_DUMMY_FRAME_TOS:void:save_dummy_frame_tos:CORE_ADDR sp:sp::0:0
+M::UNWIND_DUMMY_ID:struct frame_id:unwind_dummy_id:struct frame_info *info:info::0:0
 v:2:PARM_BOUNDARY:int:parm_boundary
 #
 v:2:TARGET_FLOAT_FORMAT:const struct floatformat *:float_format::::::default_float_format (gdbarch)::%s:(TARGET_FLOAT_FORMAT)->name
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.126
diff -u -r1.126 gdbint.texinfo
--- doc/gdbint.texinfo	3 Mar 2003 23:28:55 -0000	1.126
+++ doc/gdbint.texinfo	5 Mar 2003 23:12:23 -0000
@@ -3697,10 +3697,11 @@
 
 @item SAVE_DUMMY_FRAME_TOS (@var{sp})
 @findex SAVE_DUMMY_FRAME_TOS
-Used in @samp{call_function_by_hand} to notify the target dependent code
-of the top-of-stack value that will be passed to the the inferior code.
-This is the value of the @code{SP} after both the dummy frame and space
-for parameters/results have been allocated on the stack.
+ at anchor{SAVE_DUMMY_FRAME_TOS} Used in @samp{call_function_by_hand} to
+notify the target dependent code of the top-of-stack value that will be
+passed to the the inferior code.  This is the value of the @code{SP}
+after both the dummy frame and space for parameters/results have been
+allocated on the stack.  @xref{unwind_dummy_id}.
 
 @item SDB_REG_TO_REGNUM
 @findex SDB_REG_TO_REGNUM
@@ -3883,6 +3884,14 @@
 Libraries, ,Opcodes}).  @var{info} is a structure (of type
 @code{disassemble_info}) defined in @file{include/dis-asm.h} used to
 pass information to the instruction decoding routine.
+
+ at item struct frame_id unwind_dummy_id (struct frame_info * at var{frame})
+ at findex unwind_dummy_id
+ at anchor{unwind_dummy_id} Given @var{frame} return a @code{struct
+frame_id} that uniquely identifies an inferior function call's dummy
+frame.  The value returned must match the dummy frame stack value
+previously saved using @code{SAVE_DUMMY_FRAME_TOS}.
+ at xref{SAVE_DUMMY_FRAME_TOS} dot 
 
 @item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
 @findex USE_STRUCT_CONVENTION

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