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-branch] Fix d10v


Hello,

The attached gets the d10v, on the offbyone-branch, working again. Most of it is `uneventful'. There is one nasty bit of work though:

 {
   /* See comment in "frame.h".  */
   gdb_assert (frame->next != NULL);
+  /* Fix up this PC's value.  */
   frame->pc = pc;
+  /* While we're at it, also update the cache, in NEXT, that also
+     contains that value.  */
+  frame->next->pc_unwind_cache = pc;
+  frame->next->pc_unwind_cache_p = 1;
 }

The d10v is a decr-pc-after break target and hence relies on deprecated_update_frame_pc_hack to fix the frame's PC. Turns out that the hack has to also fix the cached copy of that PC in the previous frame (the information is redundently stored). Ulgh.

A follow-on is to eliminate the d10v's reliance on that hack.

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

	* d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr",
	change type of "next_addr" to LONGEST.  Delete member "frameless".
	(prologue_find_regs): Parse "st rn, @r11", save r11's offset.
	(d10v_frame_unwind_cache): Compute both the frame base and the
	previous stack pointer.  Store the previous SP's value in the
	saved_regs array.
	(d10v_frame_id_unwind): Remove commented out code.  Check for
	circular stack.
	(saved_regs_unwinder): When SP_REGNUM, extract the value from the
	saved_regs array.
	(d10v_unwind_dummy_id): New function.
	(d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and
	save_dummy_frame_tos.
	(struct frame_extra_info): Delete.
	(saved_regs_unwind): New function.
	(d10v_frame_pop): Update to match current code.
	(d10v_frame_register_unwind): Don't unwind LR_REGNUM.  Unwind the
	PC_REGNUM by returning the saved LR_REGNUM.
	* frame.c (get_prev_frame): Store this frame's ID in the next
	frame's unwound ID cache.
	(deprecated_update_frame_pc_hack): Update the cached value in NEXT
	as well.

	2003-02-27  Andrew Cagney  <cagney at redhat dot com>
	* frame.c (get_prev_frame): Rewrite the frame ID unwind code to
	use unwind_dummy_id when available.
	* gdbarch.sh (get_dummy_frame_id): New multi-arch method with
	predicate.
	* gdbarch.h, gdbarch.c: Regneerate.
	
Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.80.2.1
diff -u -r1.80.2.1 d10v-tdep.c
--- d10v-tdep.c	4 Mar 2003 23:15:23 -0000	1.80.2.1
+++ d10v-tdep.c	5 Mar 2003 04:59:02 -0000
@@ -45,20 +45,9 @@
 
 #include "gdb_assert.h"
 
-static void d10v_frame_register_unwind (struct frame_info *next_frame,
-					void **this_cache,
-					int prev_regnum, int *optimizedp,
-					enum lval_type *lvalp,
-					CORE_ADDR *addrp,
-					int *realnump, void *bufferp);
-
-
-struct frame_extra_info
-  {
-    CORE_ADDR return_pc;
-    int frameless;
-    int size;
-  };
+static void saved_regs_unwind (struct frame_info *next_frame,
+			       CORE_ADDR *saved_regs, int prev_regnum,
+			       void *bufferp);
 
 struct gdbarch_tdep
   {
@@ -625,10 +614,10 @@
 struct d10v_unwind_cache
 {
   CORE_ADDR base;
-  int frameless;
   int size;
   CORE_ADDR *saved_regs;
-  CORE_ADDR next_addr;
+  LONGEST next_addr;
+  LONGEST r11_addr;
   int uses_frame;
   void **regs;
 };
@@ -672,6 +661,15 @@
   if (op == 0x417E)
     {
       info->uses_frame = 1;
+      info->r11_addr = info->next_addr;
+      return 1;
+    }
+
+  /* st  rn, @r11 */
+  if ((op & 0x7E1F) == 0x6816)
+    {
+      n = (op & 0x1E0) >> 5;
+      info->saved_regs[n] = info->r11_addr;
       return 1;
     }
 
@@ -724,7 +722,6 @@
   (*this_cache) = info;
   info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
 
-  info->frameless = 0;
   info->size = 0;
 
   info->next_addr = 0;
@@ -784,40 +781,51 @@
 
   info->size = -info->next_addr;
 
-  /* Start out with the frame's stack top.  */
-  frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
-  sp = d10v_make_daddr (sp);
-
-  for (i = 0; i < NUM_REGS - 1; i++)
-    if (info->saved_regs[i])
-      {
-	info->saved_regs[i] = sp - (info->next_addr - info->saved_regs[i]);
-      }
-
   /* Compute the frame's base.  */
-  if (info->saved_regs[FP_REGNUM])
+  if (info->uses_frame)
     {
-      /* The FP was saved, which means that the current FP is live.
-         Unwind its value from the NEXT frame.  */
+      /* The SP was moved into the FP.  This indicates that a new
+         frame was created.  Get THIS frame's FP value by unwinding it
+         from the next frame.  */
       frame_unwind_unsigned_register (next_frame, FP_REGNUM, &base);
+      /* The FP points at the last saved register.  Adjust the FP back
+         to before the first saved register giving the SP.  */
+      sp = base + info->size;
     }
   else if (info->saved_regs[SP_REGNUM])
     {
-      /* The SP was saved (this is very unusual), the frame base is
+      /* The SP was saved (which is very unusual), the frame base is
 	 just the PREV's frame's TOP-OF-STACK.  */
       base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], 
 					   register_size (current_gdbarch,
 							  SP_REGNUM));
-      info->frameless = 1;
+      sp = base;
     }
   else
     {
       /* Assume that the FP is this frame's SP but with that pushed
          stack space added back.  */
       frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base);
-      base += info->size;
+      sp = base + info->size;
     }
+
   info->base = d10v_make_daddr (base);
+  sp = d10v_make_daddr (sp);
+
+  /* Adjust all the saved registers so that they contain addresses and
+     not offsets.  */
+  for (i = 0; i < NUM_REGS - 1; i++)
+    {
+      if (info->saved_regs[i])
+	{
+	  info->saved_regs[i] = (sp + info->saved_regs[i]);
+	}
+    }
+
+  /* The SP_REGNUM is special.  Instead of the address of the SP, the
+     previous frame's SP value is saved.  */
+  info->saved_regs[SP_REGNUM] = sp;
+
   return info;
 }
 
@@ -1429,17 +1437,13 @@
 d10v_frame_pc_unwind (struct frame_info *next_frame,
 		      void **this_cache)
 {
-  /* FIXME: This shouldn't be needed.  Instead a per-architecture
-     method should be called.  */
-  int optimized;
-  enum lval_type lval;
-  CORE_ADDR addr;
-  int realnum;
-  ULONGEST lr;
+  /* FIXME: This shouldn't be needed.  Instead single per-architecture
+     method should be called for all frames.  */
+  CORE_ADDR lr;
+  struct d10v_unwind_cache *info
+    = d10v_frame_unwind_cache (next_frame, this_cache);
   void *buffer = alloca (max_register_size (current_gdbarch));
-  d10v_frame_register_unwind (next_frame, this_cache, LR_REGNUM, 
-			      &optimized, &lval, &addr, &realnum,
-			      buffer);
+  saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, buffer);
   lr = extract_unsigned_integer (buffer, register_size (current_gdbarch,
 							LR_REGNUM));
   return d10v_make_iaddr (lr);
@@ -1472,26 +1476,24 @@
       return;
     }
 
-#if 0
-  if (!info->saved_regs[FP_REGNUM])
-    {
-      if (!info->saved_regs[SP_REGNUM]
-	  || info->saved_regs[SP_REGNUM] == STACK_START)
-	return;
-
-      this_id->base = info->saved_regs[SP_REGNUM];
-      this_id->pc = info->return_pc;
-    }
+  /* Hopefully the prologue analysis either correctly determined the
+     frame's base (which is the SP from the previous frame), or set
+     that base to "NULL".  */
+  base = info->base;
+  if (base == STACK_START || base == 0)
+    return;
 
-  addr = read_memory_unsigned_integer (info->saved_regs[FP_REGNUM],
-				       register_size (current_gdbarch, FP_REGNUM));
-  if (addr == 0)
+  /* Check that we're not going round in circles on the same frame ID.
+     Be careful to avoid applying the test to sentinel frames (which
+     do go round in circles).  Can't use ID_EQ as that doesn't yet
+     compare PC values.  */
+  if (frame_relative_level (next_frame) >= 0
+      && get_frame_type (next_frame) != DUMMY_FRAME
+      && get_frame_id (next_frame).pc == pc
+      && get_frame_id (next_frame).base == base)
     return;
-#endif
 
-  /* Hopefully the prolog analysis has correctly determined the
-     frame's base.  */
-  this_id->base = info->base;
+  this_id->base = base;
   this_id->pc = pc;
 }
 
@@ -1504,15 +1506,30 @@
 {
   if (saved_regs[prev_regnum] != 0)
     {
-      *optimizedp = 0;
-      *lvalp = lval_memory;
-      *addrp = saved_regs[prev_regnum];
-      *realnump = -1;
-      if (bufferp != NULL)
+      if (prev_regnum == SP_REGNUM)
+	{
+	  /* SP register treated specially.  */
+	  *optimizedp = 0;
+	  *lvalp = not_lval;
+	  *addrp = 0;
+	  *realnump = -1;
+	  if (bufferp != NULL)
+	    store_address (bufferp,
+			   register_size (current_gdbarch, SP_REGNUM),
+			   saved_regs[SP_REGNUM]);
+	}
+      else
 	{
-	  /* Read the value in from memory.  */
-	  read_memory (saved_regs[prev_regnum], bufferp,
-		       register_size (current_gdbarch, prev_regnum));
+	  *optimizedp = 0;
+	  *lvalp = lval_memory;
+	  *addrp = saved_regs[prev_regnum];
+	  *realnump = -1;
+	  if (bufferp != NULL)
+	    {
+	      /* Read the value in from memory.  */
+	      read_memory (saved_regs[prev_regnum], bufferp,
+			   register_size (current_gdbarch, prev_regnum));
+	    }
 	}
       return;
     }
@@ -1525,6 +1542,20 @@
 			 realnump, bufferp);
 }
 
+/* Wrapper so that local code can unwind register values.  */
+
+static void
+saved_regs_unwind (struct frame_info *next_frame, CORE_ADDR *saved_regs,
+		   int prev_regnum, void *bufferp)
+{
+  int optimized;
+  enum lval_type lval;
+  CORE_ADDR addr;
+  int realnum;
+  saved_regs_unwinder (next_frame, saved_regs, prev_regnum,
+		       &optimized, &lval, &addr, &realnum, bufferp);
+}
+
 
 static void
 d10v_frame_register_unwind (struct frame_info *next_frame,
@@ -1535,44 +1566,67 @@
 {
   struct d10v_unwind_cache *info
     = d10v_frame_unwind_cache (next_frame, this_cache);
-  if (prev_regnum == PC_REGNUM)
-    prev_regnum = LR_REGNUM;
-  saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp,
-		       lvalp, addrp, realnump, bufferp);
+  if (prev_regnum == LR_REGNUM)
+    /* Unwinding the LR isn't possible.  It's value is trashed by the
+       call instruction.  Mark the value as optimized away.  */
+    {
+      *optimizedp = 1;
+      *lvalp = lval_register;
+      *addrp = 0;
+      *realnump = LR_REGNUM;
+      if (bufferp != NULL)
+	memset (bufferp, 0, register_size (current_gdbarch, LR_REGNUM));
+    }
+  else if (prev_regnum == PC_REGNUM)
+    /* The caller's PC is saved in LR_REGNUM.  Find/return the
+       LR_REGNUM.  */
+    saved_regs_unwinder (next_frame, info->saved_regs, LR_REGNUM, optimizedp,
+			 lvalp, addrp, realnump, bufferp);
+  else
+    saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp,
+			 lvalp, addrp, realnump, bufferp);
 }
 
 
+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 void
-d10v_frame_pop (struct frame_info *fi, void **unwind_cache,
+d10v_frame_pop (struct frame_info *next_frame, void **this_cache,
 		struct regcache *regcache)
 {
-  struct d10v_unwind_cache *info = d10v_frame_unwind_cache (fi, unwind_cache);
+  struct d10v_unwind_cache *info
+    = d10v_frame_unwind_cache (next_frame, this_cache);
   CORE_ADDR fp;
   int regnum;
   char raw_buffer[8];
 
-  fp = get_frame_base (fi);
-
   /* now update the current registers with the old values */
   for (regnum = A0_REGNUM; regnum < A0_REGNUM + NR_A_REGS; regnum++)
     {
-      frame_unwind_register (fi, regnum, raw_buffer);
+      saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer);
       regcache_cooked_write (regcache, regnum, raw_buffer);
     }
   for (regnum = 0; regnum < SP_REGNUM; regnum++)
     {
-      frame_unwind_register (fi, regnum, raw_buffer);
+      saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer);
       regcache_cooked_write (regcache, regnum, raw_buffer);
     }
-  frame_unwind_register (fi, PSW_REGNUM, raw_buffer);
+  saved_regs_unwind (next_frame, info->saved_regs, PSW_REGNUM, raw_buffer);
   regcache_cooked_write (regcache, PSW_REGNUM, raw_buffer);
 
-  frame_unwind_register (fi, LR_REGNUM, raw_buffer);
+  saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, raw_buffer);
   regcache_cooked_write (regcache, PC_REGNUM, raw_buffer);
 
-  store_unsigned_integer (raw_buffer,
-			  register_size (current_gdbarch, SP_REGNUM),
-			  fp + info->size);
+  saved_regs_unwind (next_frame, info->saved_regs, SP_REGNUM, raw_buffer);
   regcache_cooked_write (regcache, SP_REGNUM, raw_buffer);
 
   target_store_registers (-1);
@@ -1728,6 +1782,8 @@
   set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info);
 
   frame_unwind_append_predicate (gdbarch, d10v_frame_p);
+  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.71.2.2
diff -u -r1.71.2.2 frame.c
--- frame.c	4 Mar 2003 23:15:23 -0000	1.71.2.2
+++ frame.c	5 Mar 2003 04:59:02 -0000
@@ -1345,39 +1345,83 @@
   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?  */
+  /* Find the prev's frame's ID.  */
   {
-    /* FIXME: cagney/2002-12-18: Instead of this hack, should just
-       save the frame ID directly.  */
-    struct frame_id id;
-    prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, &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 (id))
+    switch (prev_frame->type)
       {
-	if (frame_debug)
-	  fprintf_unfiltered (gdb_stdlog,
-			      "Outermost frame - unwound frame ID invalid\n");
-	return NULL;
+      case DUMMY_FRAME:
+	/* A dummy doesn't have anything resembling either a sane
+	   frame or PC.  The PC is sitting in the entry code and the
+	   stack, which has nothing to do with that entry address, is
+	   a down right mess.  Trying to use the standard frame ID
+	   unwind code to get the previous frame ID 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 ID that is being obtained
+               here.  Things only work if the two match.  */
+	    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 typically uses frame_register_unwind to obtain
+	       register values needed to determine the dummy ID.  */
+	    next_frame->id_unwind_cache =
+	      gdbarch_unwind_dummy_id (current_gdbarch, next_frame);
+	  }
+	else if (next_frame->level == 0)
+	  {
+	    /* We're `unwinding' the sentinel frame.  Just fake up the
+               ID the same way that the traditional hacks did it.  */
+	    next_frame->id_unwind_cache.pc = read_pc ();
+	    next_frame->id_unwind_cache.pc = read_fp ();
+	  }
+	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.  */
+	    internal_error (__FILE__, __LINE__,
+			    "Missing unwind_dummy_id architecture method");
+	  }
+	break;
+      case NORMAL_FRAME:
+      case SIGTRAMP_FRAME:
+	prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache,
+				&next_frame->id_unwind_cache);
+	/* Check that the unwound ID is valid.  */
+	if (!frame_id_p (next_frame->id_unwind_cache))
+	  {
+	    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 (next_frame->id_unwind_cache,
+			       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 (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.  */
-    prev_frame->frame = id.base;
+    /* FIXME: cagney/2002-12-18: Instead of this hack, the frame ID
+       should be directly stored in the `struct frame_info'.
+       Unfortunatly, GDB isn't quite ready for this, need to get HP/UX
+       multi-arch and make 'struct frame_info' opaque.  */
+    next_frame->id_unwind_cache_p = 1;
+    prev_frame->frame = next_frame->id_unwind_cache.base;
   }
 
   /* Link it in.  */
@@ -1514,7 +1558,12 @@
 {
   /* See comment in "frame.h".  */
   gdb_assert (frame->next != NULL);
+  /* Fix up this PC's value.  */
   frame->pc = pc;
+  /* While we're at it, also update the cache, in NEXT, that also
+     contains that value.  */
+  frame->next->pc_unwind_cache = pc;
+  frame->next->pc_unwind_cache_p = 1;
 }
 
 void
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.186
diff -u -r1.186 gdbarch.c
--- gdbarch.c	3 Mar 2003 20:50:18 -0000	1.186
+++ gdbarch.c	5 Mar 2003 04:59:02 -0000
@@ -251,6 +251,7 @@
   int extra_stack_alignment_needed;
   gdbarch_reg_struct_has_addr_ftype *reg_struct_has_addr;
   gdbarch_save_dummy_frame_tos_ftype *save_dummy_frame_tos;
+  gdbarch_unwind_dummy_id_ftype *unwind_dummy_id;
   int parm_boundary;
   const struct floatformat * float_format;
   const struct floatformat * double_format;
@@ -431,6 +432,7 @@
   0,
   0,
   0,
+  0,
   generic_in_function_epilogue_p,
   construct_inferior_arguments,
   0,
@@ -770,6 +772,7 @@
   /* Skip verify of extra_stack_alignment_needed, invalid_p == 0 */
   /* Skip verify of reg_struct_has_addr, has predicate */
   /* Skip verify of save_dummy_frame_tos, has predicate */
+  /* Skip verify of unwind_dummy_id, has predicate */
   if (gdbarch->float_format == 0)
     gdbarch->float_format = default_float_format (gdbarch);
   if (gdbarch->double_format == 0)
@@ -2567,6 +2570,14 @@
                         (long) current_gdbarch->write_sp
                         /*TARGET_WRITE_SP ()*/);
 #endif
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: gdbarch_unwind_dummy_id_p() = %d\n",
+                        gdbarch_unwind_dummy_id_p (current_gdbarch));
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: unwind_dummy_id = 0x%08lx\n",
+                        (long) current_gdbarch->unwind_dummy_id);
 #ifdef USE_STRUCT_CONVENTION
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
@@ -5029,6 +5040,32 @@
                                   gdbarch_save_dummy_frame_tos_ftype save_dummy_frame_tos)
 {
   gdbarch->save_dummy_frame_tos = save_dummy_frame_tos;
+}
+
+int
+gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->unwind_dummy_id != 0;
+}
+
+struct frame_id
+gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info)
+{
+  gdb_assert (gdbarch != NULL);
+  if (gdbarch->unwind_dummy_id == 0)
+    internal_error (__FILE__, __LINE__,
+                    "gdbarch: gdbarch_unwind_dummy_id invalid");
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_dummy_id called\n");
+  return gdbarch->unwind_dummy_id (gdbarch, info);
+}
+
+void
+set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch,
+                             gdbarch_unwind_dummy_id_ftype unwind_dummy_id)
+{
+  gdbarch->unwind_dummy_id = unwind_dummy_id;
 }
 
 int
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.147
diff -u -r1.147 gdbarch.h
--- gdbarch.h	3 Mar 2003 20:50:18 -0000	1.147
+++ gdbarch.h	5 Mar 2003 04:59:03 -0000
@@ -2458,6 +2458,12 @@
 #endif
 #endif
 
+extern int gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch);
+
+typedef struct frame_id (gdbarch_unwind_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *info);
+extern struct frame_id gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info);
+extern void set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, gdbarch_unwind_dummy_id_ftype *unwind_dummy_id);
+
 extern int gdbarch_parm_boundary (struct gdbarch *gdbarch);
 extern void set_gdbarch_parm_boundary (struct gdbarch *gdbarch, int parm_boundary);
 #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (PARM_BOUNDARY)
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 04:59:03 -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/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/doc/ChangeLog,v
retrieving revision 1.277
diff -u -r1.277 ChangeLog
--- doc/ChangeLog	3 Mar 2003 03:59:16 -0000	1.277
+++ doc/ChangeLog	5 Mar 2003 04:59:03 -0000
@@ -1,3 +1,10 @@
+2003-03-04  Andrew Cagney  <cagney at redhat dot com>
+
+	2003-02-27  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.
+
 2003-03-02  Daniel Jacobowitz  <drow at mvista dot com>
 
 	* Makefile.in (distclean): Remove config.log.
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.125
diff -u -r1.125 gdbint.texinfo
--- doc/gdbint.texinfo	2 Mar 2003 04:02:25 -0000	1.125
+++ doc/gdbint.texinfo	5 Mar 2003 04:59:04 -0000
@@ -3691,10 +3691,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
@@ -3877,6 +3878,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]