]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2003-03-04 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Wed, 5 Mar 2003 05:00:04 +0000 (05:00 +0000)
committerAndrew Cagney <cagney@redhat.com>
Wed, 5 Mar 2003 05:00:04 +0000 (05:00 +0000)
* 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@redhat.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.

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 32b799017e5ce77cf2e6b6163e89086edd3f10d2..8ac3ae9487cf274449ed4555109bf1d0f10376f8 100644 (file)
@@ -1,3 +1,35 @@
+2003-03-04  Andrew Cagney  <cagney@redhat.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@redhat.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.
+       
 2003-03-04  Andrew Cagney  <cagney@redhat.com>
 
        * d10v-tdep.c (d10v_frame_unwind_cache): Update to work with
index 9111aa318d5438955095f64040ec9f8c9f619d7c..5cbdddcdce55bbb1c63357f6c0ec5604f157b5aa 100644 (file)
 
 #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 @@ d10v_skip_prologue (CORE_ADDR pc)
 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 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
   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 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
   (*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 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
 
   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 @@ static CORE_ADDR
 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 @@ d10v_frame_id_unwind (struct frame_info *next_frame,
       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 @@ saved_regs_unwinder (struct frame_info *next_frame,
 {
   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 @@ saved_regs_unwinder (struct frame_info *next_frame,
                         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 @@ d10v_frame_register_unwind (struct frame_info *next_frame,
 {
   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 @@ 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);
+  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 013e8ca7569302540a79c8ddc8b47ff8a3beb946..c1f5206597c3fa41134e4e5837a3cbd7db6b3eec 100644 (file)
@@ -1,3 +1,10 @@
+2003-03-04  Andrew Cagney  <cagney@redhat.com>
+
+       2003-02-27  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-02  Daniel Jacobowitz  <drow@mvista.com>
 
        * Makefile.in (distclean): Remove config.log.
index 35acd14e02265d8deecf475f618f6c21e523a8c2..eba00ca6826825a17cc5ed4d5217bdd6e9116e5e 100644 (file)
@@ -3691,10 +3691,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
@@ -3878,6 +3879,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 d70ac9653deebfefb4725bad36706dc8a2d1772e..dd3cd68aad7c8aa86d3add195e9f423bf8be5373 100644 (file)
@@ -1345,39 +1345,83 @@ 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?  */
+  /* 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 @@ 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.  */
+  frame->next->pc_unwind_cache = pc;
+  frame->next->pc_unwind_cache_p = 1;
 }
 
 void
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