2003-03-05 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Wed, 5 Mar 2003 23:14:18 +0000 (23:14 +0000)
committerAndrew Cagney <cagney@redhat.com>
Wed, 5 Mar 2003 23:14:18 +0000 (23:14 +0000)
* 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@redhat.com>

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

gdb/ChangeLog
gdb/d10v-tdep.c
gdb/doc/ChangeLog
gdb/doc/gdbint.texinfo
gdb/frame.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh

index b3697187480da106d685175fd8c481ec0ea22619..f17fda082b1d6be6d2434a360d5306e122244b5e 100644 (file)
@@ -1,3 +1,13 @@
+2003-03-05  Andrew Cagney  <cagney@redhat.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.
+       
 2003-03-05  Andrew Cagney  <cagney@redhat.com>
 
        * d10v-tdep.c (struct d10v_unwind_cache): Add field "base".
 
        * f-lang.c (build_fortran_types): New function.
        (_initialize_f_language): Gdbarch-register built-in fortran types.
-
        * doublest.c (extract_floating): Fix warning text.
 
 2003-02-27  Andrew Cagney  <cagney@redhat.com>
index fc05e806edc526f8656b948f0ff06b5fdeca74a2..5f334e6a7ab53754bd3ecfbbfeb8a5ec6104540b 100644 (file)
@@ -1612,6 +1612,22 @@ d10v_frame_p (CORE_ADDR pc)
   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 *
@@ -1749,6 +1765,10 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   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 dbdd1ba948c87c51608e9645d56259c140e1ee7f..00935e27748e132a864f3892d9f806dc0e5d39ca 100644 (file)
@@ -1,3 +1,9 @@
+2003-03-05  Andrew Cagney  <cagney@redhat.com>
+
+       * gdbint.texinfo (Target Architecture Definition): Document
+       unwind_dummy_id.  Cross reference unwind_dummy_id and
+       SAVE_DUMMY_FRAME_TOS.
+
 2003-03-05  James Ingham <jingham@apple.com>
            Daniel Jacobowitz  <drow@mvista.com>
 
index 9776a3515bdf3517086c5557eb4a67d96cab0f6c..7deabfc6d3723e957e63a926fdeab7eaa4d4f843 100644 (file)
@@ -3697,10 +3697,11 @@ rather than directly.
 
 @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.
+@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
@@ -3884,6 +3885,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.
 
+@item struct frame_id unwind_dummy_id (struct frame_info *@var{frame})
+@findex unwind_dummy_id
+@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}.
+@xref{SAVE_DUMMY_FRAME_TOS}.
+
 @item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
 @findex USE_STRUCT_CONVENTION
 If defined, this must be an expression that is nonzero if a value of the
index 5d220c9f2bd1795976a4d04840189bae34349364..bf860fe2ccd03414341a8fbf8b0aaf34653097ac 100644 (file)
@@ -1330,39 +1330,86 @@ get_prev_frame (struct frame_info *next_frame)
   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 68247d6892d39bd0b4d784d4efac7313245f4c5a..636349c7be2aa3cc0c57e148b58950750f14e18a 100644 (file)
@@ -251,6 +251,7 @@ struct gdbarch
   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 @@ struct gdbarch startup_gdbarch =
   0,
   0,
   0,
+  0,
   generic_in_function_epilogue_p,
   construct_inferior_arguments,
   0,
@@ -770,6 +772,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* 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 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                         (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",
@@ -5031,6 +5042,32 @@ set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch,
   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
 gdbarch_parm_boundary (struct gdbarch *gdbarch)
 {
index 59dd3d60a0e01d7cf3ae58bd6707da7bc57fde29..b1cb72bd18583c1adf510a4bd14b26433452faa9 100644 (file)
@@ -2458,6 +2458,12 @@ extern void set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, gdbarch_s
 #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 12953c286d37a842c4d7f33fefc5b9ba21c3d8e0..b367fda7b7fdb83fc4405da867c76581bf54add1 100755 (executable)
@@ -602,6 +602,7 @@ M:::CORE_ADDR:frame_align:CORE_ADDR address:address
 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