]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2003-03-06 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Thu, 6 Mar 2003 19:21:30 +0000 (19:21 +0000)
committerAndrew Cagney <cagney@redhat.com>
Thu, 6 Mar 2003 19:21:30 +0000 (19:21 +0000)
* gdbarch.sh (gdbarch_unwind_pc): New method.
* gdbarch.h, gdbarch.c: Regenerate.
* frame.c (frame_pc_unwind): Rewrite.  Prefer gdbarch_unwind_pc,
but use read_pc and FRAME_SAVED_PC as fall backs.
(frame_saved_regs_pc_unwind): Delete function.
(trad_frame_unwinder): Update.
* frame-unwind.h (frame_unwind_pc_ftype): Delete declaration.
(struct frame_unwind): Update.
* dummy-frame.c (dummy_frame_pc_unwind): Delete function.
(dummy_frame_unwind): Update.
* sentinel-frame.c (sentinel_frame_pc_unwind): Delete function.
(sentinel_frame_unwinder): Update.
* d10v-tdep.c (d10v_frame_pc_unwind): Delete function.
(d10v_frame_unwind): Update.
(d10v_unwind_pc): New function.
(d10v_gdbarch_init): Set unwind_pc.

2003-03-05  Andrew Cagney  <cagney@redhat.com>

* dummy-frame.c (dummy_frame_id_unwind): Abort if called.
(cached_find_dummy_frame): Add hack to obtain this thread's id
without calling id unwind.
* frame.h: Merge with mainline.
* d10v-tdep.c: Merge with mainline.
* frame.c: Merge with mainline.

gdb/ChangeLog
gdb/d10v-tdep.c
gdb/dummy-frame.c
gdb/frame-unwind.h
gdb/frame.c
gdb/frame.h
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/sentinel-frame.c

index 8ac3ae9487cf274449ed4555109bf1d0f10376f8..b2510c3a36d37e26a2bd45d257634077feb959ee 100644 (file)
@@ -1,3 +1,31 @@
+2003-03-06  Andrew Cagney  <cagney@redhat.com>
+
+       * gdbarch.sh (gdbarch_unwind_pc): New method.
+       * gdbarch.h, gdbarch.c: Regenerate.
+       * frame.c (frame_pc_unwind): Rewrite.  Prefer gdbarch_unwind_pc,
+       but use read_pc and FRAME_SAVED_PC as fall backs.
+       (frame_saved_regs_pc_unwind): Delete function.
+       (trad_frame_unwinder): Update.
+       * frame-unwind.h (frame_unwind_pc_ftype): Delete declaration.
+       (struct frame_unwind): Update.
+       * dummy-frame.c (dummy_frame_pc_unwind): Delete function.
+       (dummy_frame_unwind): Update.
+       * sentinel-frame.c (sentinel_frame_pc_unwind): Delete function.
+       (sentinel_frame_unwinder): Update.
+       * d10v-tdep.c (d10v_frame_pc_unwind): Delete function.
+       (d10v_frame_unwind): Update.
+       (d10v_unwind_pc): New function.
+       (d10v_gdbarch_init): Set unwind_pc.
+
+2003-03-05  Andrew Cagney  <cagney@redhat.com>
+
+       * dummy-frame.c (dummy_frame_id_unwind): Abort if called.
+       (cached_find_dummy_frame): Add hack to obtain this thread's id
+       without calling id unwind.
+       * frame.h: Merge with mainline.
+       * d10v-tdep.c: Merge with mainline.
+       * frame.c: Merge with mainline.
+
 2003-03-04  Andrew Cagney  <cagney@redhat.com>
 
        * d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr",
index 5cbdddcdce55bbb1c63357f6c0ec5604f157b5aa..0fe222ec2fe26a431f1ef7bacfb8ebd4ce158ec4 100644 (file)
@@ -616,8 +616,11 @@ struct d10v_unwind_cache
   CORE_ADDR base;
   int size;
   CORE_ADDR *saved_regs;
-  LONGEST next_addr;
-  LONGEST r11_addr;
+  /* How far the SP and r11 (FP) have been offset from the start of
+     the stack frame (as defined by the previous frame's stack
+     pointer).  */
+  LONGEST sp_offset;
+  LONGEST r11_offset;
   int uses_frame;
   void **regs;
 };
@@ -632,8 +635,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   if ((op & 0x7E1F) == 0x6C1F)
     {
       n = (op & 0x1E0) >> 5;
-      info->next_addr -= 2;
-      info->saved_regs[n] = info->next_addr;
+      info->sp_offset -= 2;
+      info->saved_regs[n] = info->sp_offset;
       return 1;
     }
 
@@ -641,9 +644,9 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   else if ((op & 0x7E3F) == 0x6E1F)
     {
       n = (op & 0x1E0) >> 5;
-      info->next_addr -= 4;
-      info->saved_regs[n] = info->next_addr;
-      info->saved_regs[n + 1] = info->next_addr + 2;
+      info->sp_offset -= 4;
+      info->saved_regs[n] = info->sp_offset;
+      info->saved_regs[n + 1] = info->sp_offset + 2;
       return 1;
     }
 
@@ -653,7 +656,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
       n = (op & 0x1E) >> 1;
       if (n == 0)
        n = 16;
-      info->next_addr -= n;
+      info->sp_offset -= n;
       return 1;
     }
 
@@ -661,7 +664,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   if (op == 0x417E)
     {
       info->uses_frame = 1;
-      info->r11_addr = info->next_addr;
+      info->r11_offset = info->sp_offset;
       return 1;
     }
 
@@ -669,7 +672,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   if ((op & 0x7E1F) == 0x6816)
     {
       n = (op & 0x1E0) >> 5;
-      info->saved_regs[n] = info->r11_addr;
+      info->saved_regs[n] = info->r11_offset;
       return 1;
     }
 
@@ -681,7 +684,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   if ((op & 0x7E1F) == 0x681E)
     {
       n = (op & 0x1E0) >> 5;
-      info->saved_regs[n] = info->next_addr;
+      info->saved_regs[n] = info->sp_offset;
       return 1;
     }
 
@@ -689,8 +692,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   if ((op & 0x7E3F) == 0x3A1E)
     {
       n = (op & 0x1E0) >> 5;
-      info->saved_regs[n] = info->next_addr;
-      info->saved_regs[n + 1] = info->next_addr + 2;
+      info->saved_regs[n] = info->sp_offset;
+      info->saved_regs[n + 1] = info->sp_offset + 2;
       return 1;
     }
 
@@ -708,8 +711,8 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
                         void **this_cache)
 {
   CORE_ADDR pc;
-  ULONGEST sp;
-  ULONGEST base;
+  ULONGEST prev_sp;
+  ULONGEST this_base;
   unsigned long op;
   unsigned short op1, op2;
   int i;
@@ -724,7 +727,7 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
 
   info->size = 0;
 
-  info->next_addr = 0;
+  info->sp_offset = 0;
 
   pc = get_pc_function_start (frame_pc_unwind (next_frame));
 
@@ -739,22 +742,22 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
            {
              /* add3 sp,sp,n */
              short n = op & 0xFFFF;
-             info->next_addr += n;
+             info->sp_offset += n;
            }
          else if ((op & 0x3F0F0000) == 0x340F0000)
            {
              /* st  rn, @(offset,sp) */
              short offset = op & 0xFFFF;
              short n = (op >> 20) & 0xF;
-             info->saved_regs[n] = info->next_addr + offset;
+             info->saved_regs[n] = info->sp_offset + offset;
            }
          else if ((op & 0x3F1F0000) == 0x350F0000)
            {
              /* st2w  rn, @(offset,sp) */
              short offset = op & 0xFFFF;
              short n = (op >> 20) & 0xF;
-             info->saved_regs[n] = info->next_addr + offset;
-             info->saved_regs[n + 1] = info->next_addr + offset + 2;
+             info->saved_regs[n] = info->sp_offset + offset;
+             info->saved_regs[n + 1] = info->sp_offset + offset + 2;
            }
          else
            break;
@@ -779,52 +782,50 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
       pc += 4;
     }
 
-  info->size = -info->next_addr;
+  info->size = -info->sp_offset;
 
-  /* Compute the frame's base.  */
+  /* Compute the frame's base, and the previous frame's SP.  */
   if (info->uses_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 SP was moved to 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, &this_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;
+      prev_sp = this_base + info->size;
     }
   else if (info->saved_regs[SP_REGNUM])
     {
       /* 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));
-      sp = base;
+      this_base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], 
+                                               register_size (current_gdbarch,
+                                                              SP_REGNUM));
+      prev_sp = this_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);
-      sp = base + info->size;
+      frame_unwind_unsigned_register (next_frame, SP_REGNUM, &this_base);
+      prev_sp = this_base + info->size;
     }
 
-  info->base = d10v_make_daddr (base);
-  sp = d10v_make_daddr (sp);
+  info->base = d10v_make_daddr (this_base);
+  prev_sp = d10v_make_daddr (prev_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]);
-       }
-    }
+    if (info->saved_regs[i])
+      {
+       info->saved_regs[i] = (prev_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;
+  info->saved_regs[SP_REGNUM] = prev_sp;
 
   return info;
 }
@@ -1432,22 +1433,12 @@ display_trace (int low, int high)
     }
 }
 
-
 static CORE_ADDR
-d10v_frame_pc_unwind (struct frame_info *next_frame,
-                     void **this_cache)
+d10v_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  /* 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));
-  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);
-                       
+  ULONGEST pc;
+  frame_unwind_unsigned_register (next_frame, PC_REGNUM, &pc);
+  return d10v_make_iaddr (pc);
 }
 
 /* Given the next frame, determine the address of this function's
@@ -1587,18 +1578,6 @@ d10v_frame_register_unwind (struct frame_info *next_frame,
                         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 *next_frame, void **this_cache,
                struct regcache *regcache)
@@ -1635,7 +1614,6 @@ d10v_frame_pop (struct frame_info *next_frame, void **this_cache,
 
 static struct frame_unwind d10v_frame_unwind = {
   d10v_frame_pop,
-  d10v_frame_pc_unwind,
   d10v_frame_id_unwind,
   d10v_frame_register_unwind
 };
@@ -1646,6 +1624,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 *
@@ -1782,9 +1776,14 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   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 the unwound PC value.  */
+  set_gdbarch_unwind_pc (gdbarch, d10v_unwind_pc);
+
   return gdbarch;
 }
 
index 6812ed92d1e769ee40523a19fbe668b4a2d7c017..a44f4510dbccd1f6e8544405ade90e1194384b38 100644 (file)
@@ -108,8 +108,13 @@ struct dummy_frame *
 cached_find_dummy_frame (struct frame_info *next_frame, void **this_cache)
 {
   if ((*this_cache) == NULL)
-    (*this_cache) = find_dummy_frame (frame_pc_unwind (next_frame),
-                                     frame_id_unwind (next_frame).base);
+    {
+      /* FIXME: hack to find the frame ID of this frame.  Need to do
+        this better.  */
+      gdb_assert (next_frame->prev != NULL);
+      (*this_cache) = find_dummy_frame (frame_pc_unwind (next_frame),
+                                       next_frame->prev->frame);
+    }
   return (*this_cache);
 }
 
@@ -371,23 +376,6 @@ dummy_frame_register_unwind (struct frame_info *next_frame, void **this_cache,
     }
 }
 
-/* Assuming that FRAME is a dummy, return the resume address for the
-   previous frame.  */
-
-static CORE_ADDR
-dummy_frame_pc_unwind (struct frame_info *next_frame,
-                      void **this_cache)
-{
-  struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache);
-  /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
-     that the frame doesn't unwind.  Should this function instead
-     return a has-no-caller indication?  */
-  if (dummy == NULL)
-    return 0;
-  return dummy->pc;
-}
-
-
 /* Assuming that FRAME is a dummy, return the ID of the calling frame
    (the frame that the dummy has the saved state of).  */
 
@@ -396,6 +384,7 @@ dummy_frame_id_unwind (struct frame_info *next_frame,
                       void **this_cache,
                       struct frame_id *this_id)
 {
+#if 0
   struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache);
   /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
      that the frame doesn't unwind.  Should this function instead
@@ -404,12 +393,19 @@ dummy_frame_id_unwind (struct frame_info *next_frame,
     (*this_id) = null_frame_id;
   else
     (*this_id) = dummy->id;
+#else
+  /* FIXME - with all the frames shuffled by one, it becomes possible
+     to move the dummy frame unwind code to here.  This is because,
+     unlike the mainline, this function is called when determining the
+     ID of the dummy, and not the ID of the dummy's caller.  For the
+     moment, this function is never called.  */
+  internal_error (__FILE__, __LINE__, "dummy_frame_pc_unwind called");
+#endif
 }
 
 static struct frame_unwind dummy_frame_unwind =
 {
   dummy_frame_pop,
-  dummy_frame_pc_unwind,
   dummy_frame_id_unwind,
   dummy_frame_register_unwind
 };
index 0ee0bc366d632bbd474510bad5736ee005d6ced6..4d00b2f5e19f8f6fb4cda99e0a42934836ea50b2 100644 (file)
@@ -102,26 +102,6 @@ typedef void (frame_unwind_reg_ftype) (struct frame_info *next_frame,
                                       CORE_ADDR *addrp,
                                       int *realnump, void *valuep);
 
-/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
-   use the NEXT frame, and its register unwind method, to unwind THIS
-   frame's PC, returning the value of PC (the return address) in PREV
-   frame.
-
-   Traditionally, THIS frame's PC was unwound by examining THIS
-   frame's function prolog and identifying where (in a register or on
-   the stack) that return address was saved.
-
-   Please note that this per-frame method may be superseeded by an
-   architecture specific method that determines the unwound PC (aka
-   return address) using just the register unwind methods.
-
-   THIS_CACHE can be used to share any prologue analysis data with the
-   other unwind methods.  Memory for that cache should be allocated
-   using frame_obstack_zalloc().  */
-
-typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info *next_frame,
-                                          void **this_cache);
-
 /* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
    use the NEXT frame, and its register unwind method, to unwind THIS
    frame's entire stack, writing PREV's frames register values into
@@ -151,7 +131,6 @@ struct frame_unwind
   /* Should an attribute indicating the frame's address-in-block go
      here?  */
   frame_unwind_pop_ftype *pop;
-  frame_unwind_pc_ftype *pc;
   frame_unwind_id_ftype *id;
   frame_unwind_reg_ftype *reg;
 };
index dd3cd68aad7c8aa86d3add195e9f423bf8be5373..d61ec08ee8c0b1f95dc91b9b695c530a15d79a99 100644 (file)
@@ -135,27 +135,54 @@ frame_find_by_id (struct frame_id id)
 }
 
 CORE_ADDR
-frame_pc_unwind (struct frame_info *this_frame)
+frame_pc_unwind (struct frame_info *next_frame)
 {
-  if (!this_frame->pc_unwind_cache_p)
+  if (!next_frame->pc_unwind_cache_p)
     {
-      this_frame->pc_unwind_cache
-       = this_frame->unwind->pc (this_frame->next, &this_frame->unwind_cache);
-      this_frame->pc_unwind_cache_p = 1;
-    }
-  return this_frame->pc_unwind_cache;
-}
-
-struct frame_id
-frame_id_unwind (struct frame_info *this_frame)
-{
-  if (!this_frame->id_unwind_cache_p)
-    {
-      this_frame->unwind->id (this_frame->next, &this_frame->unwind_cache,
-                             &this_frame->id_unwind_cache);
-      this_frame->id_unwind_cache_p = 1;
+      CORE_ADDR pc;
+      if (gdbarch_unwind_pc_p (current_gdbarch))
+       {
+         /* The right way.  The `pure' way.  The one true way.  This
+            method depends solely on the register-unwind code to
+            determine the value of registers in THIS frame, and hence
+            the value of this frame's PC (resume address).  A typical
+            implementation is no more than:
+          
+            frame_unwind_register (next_frame, ISA_PC_REGNUM, buf);
+            return extract_address (buf, size of ISA_PC_REGNUM);
+
+            Note: this method is very heavily dependent on a correct
+            register-unwind implementation, it pays to fix that
+            method first; this method is frame type agnostic, since
+            it only deals with register values, it works with any
+            frame.  This is all in stark contrast to the old
+            FRAME_SAVED_PC which would try to directly handle all the
+            different ways that a PC could be unwound.  */
+         pc = gdbarch_unwind_pc (current_gdbarch, next_frame);
+       }
+      else if (next_frame->level < 0)
+       {
+         /* FIXME: cagney/2003-03-06: Old code and and a sentinel
+             frame.  Do like was always done.  Fetch the PC's value
+             direct from the global registers array (via read_pc).
+             This assumes that this frame belongs to the current
+             global register cache.  The assumption is dangerous.  */
+         pc = read_pc ();
+       }
+      else if (FRAME_SAVED_PC_P ())
+       {
+         /* FIXME: cagney/2003-03-06: Old code, but not a sentinel
+             frame.  Do like was always done.  Note that this method,
+             unlike unwind_pc(), tries to handle all the different
+             frame cases directly.  It fails.  */
+         pc = FRAME_SAVED_PC (next_frame);
+       }
+      else
+       internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method");
+      next_frame->pc_unwind_cache = pc;
+      next_frame->pc_unwind_cache_p = 1;
     }
-  return this_frame->id_unwind_cache;
+  return next_frame->pc_unwind_cache;
 }
 
 void
@@ -682,13 +709,6 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache,
                  bufferp);
 }
 
-static CORE_ADDR
-frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache)
-{
-  gdb_assert (FRAME_SAVED_PC_P ());
-  return FRAME_SAVED_PC (frame);
-}
-       
 static void
 frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache,
                            struct frame_id *id)
@@ -760,7 +780,6 @@ frame_saved_regs_pop (struct frame_info *fi, void **cache,
 
 const struct frame_unwind trad_frame_unwinder = {
   frame_saved_regs_pop,
-  frame_saved_regs_pc_unwind,
   frame_saved_regs_id_unwind,
   frame_saved_regs_register_unwind
 };
@@ -1346,83 +1365,87 @@ get_prev_frame (struct frame_info *next_frame)
                                                prev_frame->pc);
 
   /* Find the prev's frame's ID.  */
-  {
-    switch (prev_frame->type)
-      {
-      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__,
+  switch (prev_frame->type)
+    {
+    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");
-         }
-       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");
-      }
-    /* 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;
-  }
+         return NULL;
+       }
+      break;
+    case NORMAL_FRAME:
+    case SIGTRAMP_FRAME:
+      prev_frame->unwind->id (next_frame, &prev_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");
+    }
+
+  /* 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->frame = prev_frame->id.base;
 
   /* Link it in.  */
   next_frame->prev = prev_frame;
@@ -1557,11 +1580,11 @@ void
 deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
 {
   /* 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.  */
+  /* While we're at it, update this frame's cached PC value, found in
+     the next frame.  Oh, for the day when "struct frame_info" is
+     opaque and this hack on hack can go.  */
+  gdb_assert (frame->next != NULL);
   frame->next->pc_unwind_cache = pc;
   frame->next->pc_unwind_cache_p = 1;
 }
index bd20ba7aec1ba101d151359e733a4165d422bc9f..18c4df4397fb26a616cca0867432267e6e618ccb 100644 (file)
@@ -310,10 +310,6 @@ extern const char *frame_map_regnum_to_name (int regnum);
 
 extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
 
-/* Unwind the frame ID.  Return an ID that uniquely identifies the
-   caller's frame.  */
-extern struct frame_id frame_id_unwind (struct frame_info *frame);
-
 /* Discard the specified frame.  Restoring the registers to the state
    of the caller.  */
 extern void frame_pop (struct frame_info *frame);
@@ -412,9 +408,9 @@ struct frame_info
     int pc_unwind_cache_p;
     CORE_ADDR pc_unwind_cache;
 
-    /* Cached copy of the previous frame's ID.  */
-    int id_unwind_cache_p;
-    struct frame_id id_unwind_cache;
+    /* This frame's ID.  Note that the frame's ID, base and PC contain
+       redundant information.  */
+    struct frame_id id;
 
     /* Pointers to the next (down, inner, younger) and previous (up,
        outer, older) frame_info's in the frame cache.  */
index 636349c7be2aa3cc0c57e148b58950750f14e18a..8b5a475375ccd9956144c34fb31a4421ce6c01c4 100644 (file)
@@ -242,6 +242,7 @@ struct gdbarch
   gdbarch_frame_chain_ftype *frame_chain;
   gdbarch_frame_chain_valid_ftype *frame_chain_valid;
   gdbarch_frame_saved_pc_ftype *frame_saved_pc;
+  gdbarch_unwind_pc_ftype *unwind_pc;
   gdbarch_frame_args_address_ftype *frame_args_address;
   gdbarch_frame_locals_address_ftype *frame_locals_address;
   gdbarch_saved_pc_after_call_ftype *saved_pc_after_call;
@@ -433,6 +434,7 @@ struct gdbarch startup_gdbarch =
   0,
   0,
   0,
+  0,
   generic_in_function_epilogue_p,
   construct_inferior_arguments,
   0,
@@ -759,6 +761,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of frame_chain, has predicate */
   /* Skip verify of frame_chain_valid, has predicate */
   /* Skip verify of frame_saved_pc, has predicate */
+  /* Skip verify of unwind_pc, has predicate */
   /* Skip verify of frame_args_address, invalid_p == 0 */
   /* Skip verify of frame_locals_address, invalid_p == 0 */
   if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
@@ -2578,6 +2581,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
     fprintf_unfiltered (file,
                         "gdbarch_dump: unwind_dummy_id = 0x%08lx\n",
                         (long) current_gdbarch->unwind_dummy_id);
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
+                        gdbarch_unwind_pc_p (current_gdbarch));
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: unwind_pc = 0x%08lx\n",
+                        (long) current_gdbarch->unwind_pc);
 #ifdef USE_STRUCT_CONVENTION
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
@@ -4845,6 +4856,32 @@ set_gdbarch_frame_saved_pc (struct gdbarch *gdbarch,
   gdbarch->frame_saved_pc = frame_saved_pc;
 }
 
+int
+gdbarch_unwind_pc_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->unwind_pc != 0;
+}
+
+CORE_ADDR
+gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  gdb_assert (gdbarch != NULL);
+  if (gdbarch->unwind_pc == 0)
+    internal_error (__FILE__, __LINE__,
+                    "gdbarch: gdbarch_unwind_pc invalid");
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_pc called\n");
+  return gdbarch->unwind_pc (gdbarch, next_frame);
+}
+
+void
+set_gdbarch_unwind_pc (struct gdbarch *gdbarch,
+                       gdbarch_unwind_pc_ftype unwind_pc)
+{
+  gdbarch->unwind_pc = unwind_pc;
+}
+
 CORE_ADDR
 gdbarch_frame_args_address (struct gdbarch *gdbarch, struct frame_info *fi)
 {
index b1cb72bd18583c1adf510a4bd14b26433452faa9..ee77461cf13d49eb5c4063fb44da418832ee7928 100644 (file)
@@ -2230,6 +2230,8 @@ extern void set_gdbarch_frame_chain_valid (struct gdbarch *gdbarch, gdbarch_fram
 #endif
 #endif
 
+/* NOTE: FRAME_SAVED_PC is replaced by UNWIND_PC */
+
 #if defined (FRAME_SAVED_PC)
 /* Legacy for systems yet to multi-arch FRAME_SAVED_PC */
 #if !defined (FRAME_SAVED_PC_P)
@@ -2267,6 +2269,12 @@ extern void set_gdbarch_frame_saved_pc (struct gdbarch *gdbarch, gdbarch_frame_s
 #endif
 #endif
 
+extern int gdbarch_unwind_pc_p (struct gdbarch *gdbarch);
+
+typedef CORE_ADDR (gdbarch_unwind_pc_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame);
+extern CORE_ADDR gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame);
+extern void set_gdbarch_unwind_pc (struct gdbarch *gdbarch, gdbarch_unwind_pc_ftype *unwind_pc);
+
 /* Default (function) for non- multi-arch platforms. */
 #if (!GDB_MULTI_ARCH) && !defined (FRAME_ARGS_ADDRESS)
 #define FRAME_ARGS_ADDRESS(fi) (get_frame_base (fi))
index b367fda7b7fdb83fc4405da867c76581bf54add1..8380a601820a288505d2698b2e7512a3fb1205dc 100755 (executable)
@@ -591,7 +591,9 @@ v:2:FRAME_ARGS_SKIP:CORE_ADDR:frame_args_skip::::0:-1
 f:2:FRAMELESS_FUNCTION_INVOCATION:int:frameless_function_invocation:struct frame_info *fi:fi:::generic_frameless_function_invocation_not::0
 F:2:FRAME_CHAIN:CORE_ADDR:frame_chain:struct frame_info *frame:frame::0:0
 F:2:FRAME_CHAIN_VALID:int:frame_chain_valid:CORE_ADDR chain, struct frame_info *thisframe:chain, thisframe::0:0
+# NOTE: FRAME_SAVED_PC is replaced by UNWIND_PC
 F:2:FRAME_SAVED_PC:CORE_ADDR:frame_saved_pc:struct frame_info *fi:fi::0:0
+M::UNWIND_PC:CORE_ADDR:unwind_pc:struct frame_info *next_frame:next_frame:
 f:2:FRAME_ARGS_ADDRESS:CORE_ADDR:frame_args_address:struct frame_info *fi:fi::0:get_frame_base::0
 f:2:FRAME_LOCALS_ADDRESS:CORE_ADDR:frame_locals_address:struct frame_info *fi:fi::0:get_frame_base::0
 f:2:SAVED_PC_AFTER_CALL:CORE_ADDR:saved_pc_after_call:struct frame_info *frame:frame::0:0
index ef8113da4e4204119105f49d785a76dcdd58621b..046655f068748f42779ddc51a977c9c0f4879e70 100644 (file)
@@ -76,17 +76,6 @@ sentinel_frame_register_unwind (struct frame_info *next_frame,
     }
 }
 
-CORE_ADDR
-sentinel_frame_pc_unwind (struct frame_info *next_frame,
-                         void **this_cache)
-{
-  /* FIXME: cagney/2003-01-08: This should be using a per-architecture
-     method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
-     Such a method would take unwind_cache, regcache and stop reason
-     parameters.  */
-  return read_pc ();
-}
-
 void
 sentinel_frame_id_unwind (struct frame_info *next_frame,
                          void **this_cache,
@@ -106,7 +95,6 @@ sentinel_frame_pop (struct frame_info *next_frame,
 const struct frame_unwind sentinel_frame_unwinder =
 {
   sentinel_frame_pop,
-  sentinel_frame_pc_unwind,
   sentinel_frame_id_unwind,
   sentinel_frame_register_unwind
 };