add autom4te.cache to .cvsignore
[deliverable/binutils-gdb.git] / gdb / frame.c
index 956bb233ac06bc67397ea69753b83be67e6684ff..b32e0be112b0415505205c31e83dcddf06016605 100644 (file)
@@ -1,7 +1,7 @@
 /* Cache and manage frames for GDB, the GNU debugger.
 
-   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
-   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001,
+   2002, 2003, 2004, 2007 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -40,6 +40,8 @@
 #include "command.h"
 #include "gdbcmd.h"
 #include "observer.h"
+#include "objfiles.h"
+#include "exceptions.h"
 
 static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
 
@@ -66,22 +68,6 @@ struct frame_info
      moment leave this as speculation.  */
   int level;
 
-  /* For each register, address of where it was saved on entry to the
-     frame, or zero if it was not saved on entry to this frame.  This
-     includes special registers such as pc and fp saved in special
-     ways in the stack frame.  The SP_REGNUM is even more special, the
-     address here is the sp for the previous frame, not the address
-     where the sp was saved.  */
-  /* Allocated by frame_saved_regs_zalloc () which is called /
-     initialized by DEPRECATED_FRAME_INIT_SAVED_REGS(). */
-  CORE_ADDR *saved_regs;       /*NUM_REGS + NUM_PSEUDO_REGS*/
-
-  /* Anything extra for this structure that may have been defined in
-     the machine dependent files. */
-  /* Allocated by frame_extra_info_zalloc () which is called /
-     initialized by DEPRECATED_INIT_EXTRA_FRAME_INFO */
-  struct frame_extra_info *extra_info;
-
   /* The frame's low-level unwinder and corresponding cache.  The
      low-level unwinder is responsible for unwinding register values
      for the previous frame.  The low-level unwind methods are
@@ -121,16 +107,54 @@ struct frame_info
   struct frame_info *next; /* down, inner, younger */
   int prev_p;
   struct frame_info *prev; /* up, outer, older */
+
+  /* The reason why we could not set PREV, or UNWIND_NO_REASON if we
+     could.  Only valid when PREV_P is set.  */
+  enum unwind_stop_reason stop_reason;
 };
 
 /* Flag to control debugging.  */
 
 static int frame_debug;
+static void
+show_frame_debug (struct ui_file *file, int from_tty,
+                 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Frame debugging is %s.\n"), value);
+}
 
 /* Flag to indicate whether backtraces should stop at main et.al.  */
 
 static int backtrace_past_main;
-static unsigned int backtrace_limit = UINT_MAX;
+static void
+show_backtrace_past_main (struct ui_file *file, int from_tty,
+                         struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+Whether backtraces should continue past \"main\" is %s.\n"),
+                   value);
+}
+
+static int backtrace_past_entry;
+static void
+show_backtrace_past_entry (struct ui_file *file, int from_tty,
+                          struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+Whether backtraces should continue past the entry point of a program is %s.\n"),
+                   value);
+}
+
+static int backtrace_limit = INT_MAX;
+static void
+show_backtrace_limit (struct ui_file *file, int from_tty,
+                     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+An upper bound on the number of backtrace levels is %s.\n"),
+                   value);
+}
+
 
 static void
 fprint_field (struct ui_file *file, const char *name, int p, CORE_ADDR addr)
@@ -405,7 +429,15 @@ frame_pc_unwind (struct frame_info *this_frame)
   if (!this_frame->prev_pc.p)
     {
       CORE_ADDR pc;
-      if (gdbarch_unwind_pc_p (current_gdbarch))
+      if (this_frame->unwind == NULL)
+       this_frame->unwind
+         = frame_unwind_find_by_frame (this_frame->next,
+                                       &this_frame->prologue_cache);
+      if (this_frame->unwind->prev_pc != NULL)
+       /* A per-frame unwinder, prefer it.  */
+       pc = this_frame->unwind->prev_pc (this_frame->next,
+                                         &this_frame->prologue_cache);
+      else 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
@@ -425,25 +457,8 @@ frame_pc_unwind (struct frame_info *this_frame)
             different ways that a PC could be unwound.  */
          pc = gdbarch_unwind_pc (current_gdbarch, this_frame);
        }
-      else if (this_frame->level < 0)
-       {
-         /* FIXME: cagney/2003-03-06: Old code and a sentinel
-             frame.  Do like was always done.  Fetch the PC's value
-             directly 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 (DEPRECATED_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 = DEPRECATED_FRAME_SAVED_PC (this_frame);
-       }
       else
-       internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method");
+       internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
       this_frame->prev_pc.value = pc;
       this_frame->prev_pc.p = 1;
       if (frame_debug)
@@ -480,12 +495,22 @@ get_frame_func (struct frame_info *fi)
 }
 
 static int
-do_frame_unwind_register (void *src, int regnum, void *buf)
+do_frame_register_read (void *src, int regnum, gdb_byte *buf)
 {
-  frame_unwind_register (src, regnum, buf);
+  frame_register_read (src, regnum, buf);
   return 1;
 }
 
+struct regcache *
+frame_save_as_regcache (struct frame_info *this_frame)
+{
+  struct regcache *regcache = regcache_xmalloc (current_gdbarch);
+  struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache);
+  regcache_save (regcache, do_frame_register_read, this_frame);
+  discard_cleanups (cleanups);
+  return regcache;
+}
+
 void
 frame_pop (struct frame_info *this_frame)
 {
@@ -493,9 +518,9 @@ frame_pop (struct frame_info *this_frame)
      Save them in a scratch buffer so that there isn't a race between
      trying to extract the old values from the current_regcache while
      at the same time writing new values into that same cache.  */
-  struct regcache *scratch = regcache_xmalloc (current_gdbarch);
+  struct regcache *scratch
+    = frame_save_as_regcache (get_prev_frame_1 (this_frame));
   struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch);
-  regcache_save (scratch, do_frame_unwind_register, this_frame);
 
   /* FIXME: cagney/2003-03-16: It should be possible to tell the
      target's register cache that it is about to be hit with a burst
@@ -518,7 +543,7 @@ frame_pop (struct frame_info *this_frame)
 void
 frame_register_unwind (struct frame_info *frame, int regnum,
                       int *optimizedp, enum lval_type *lvalp,
-                      CORE_ADDR *addrp, int *realnump, void *bufferp)
+                      CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp)
 {
   struct frame_unwind_cache *cache;
 
@@ -580,7 +605,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
 void
 frame_register (struct frame_info *frame, int regnum,
                int *optimizedp, enum lval_type *lvalp,
-               CORE_ADDR *addrp, int *realnump, void *bufferp)
+               CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp)
 {
   /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
      that the value proper does not need to be fetched.  */
@@ -590,33 +615,6 @@ frame_register (struct frame_info *frame, int regnum,
   gdb_assert (realnump != NULL);
   /* gdb_assert (bufferp != NULL); */
 
-  /* Ulgh!  Old code that, for lval_register, sets ADDRP to the offset
-     of the register in the register cache.  It should instead return
-     the REGNUM corresponding to that register.  Translate the .  */
-  if (DEPRECATED_GET_SAVED_REGISTER_P ())
-    {
-      DEPRECATED_GET_SAVED_REGISTER (bufferp, optimizedp, addrp, frame,
-                                    regnum, lvalp);
-      /* Compute the REALNUM if the caller wants it.  */
-      if (*lvalp == lval_register)
-       {
-         int regnum;
-         for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
-           {
-             if (*addrp == register_offset_hack (current_gdbarch, regnum))
-               {
-                 *realnump = regnum;
-                 return;
-               }
-           }
-         internal_error (__FILE__, __LINE__,
-                         "Failed to compute the register number corresponding"
-                         " to 0x%s", paddr_d (*addrp));
-       }
-      *realnump = -1;
-      return;
-    }
-
   /* Obtain the register value by unwinding the register from the next
      (more inner frame).  */
   gdb_assert (frame != NULL && frame->next != NULL);
@@ -625,7 +623,7 @@ frame_register (struct frame_info *frame, int regnum,
 }
 
 void
-frame_unwind_register (struct frame_info *frame, int regnum, void *buf)
+frame_unwind_register (struct frame_info *frame, int regnum, gdb_byte *buf)
 {
   int optimized;
   CORE_ADDR addr;
@@ -637,7 +635,7 @@ frame_unwind_register (struct frame_info *frame, int regnum, void *buf)
 
 void
 get_frame_register (struct frame_info *frame,
-                   int regnum, void *buf)
+                   int regnum, gdb_byte *buf)
 {
   frame_unwind_register (frame->next, regnum, buf);
 }
@@ -645,9 +643,10 @@ get_frame_register (struct frame_info *frame,
 LONGEST
 frame_unwind_register_signed (struct frame_info *frame, int regnum)
 {
-  char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  return extract_signed_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
+  return extract_signed_integer (buf, register_size (get_frame_arch (frame),
+                                                    regnum));
 }
 
 LONGEST
@@ -659,9 +658,10 @@ get_frame_register_signed (struct frame_info *frame, int regnum)
 ULONGEST
 frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
 {
-  char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  return extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
+  return extract_unsigned_integer (buf, register_size (get_frame_arch (frame),
+                                                      regnum));
 }
 
 ULONGEST
@@ -674,13 +674,16 @@ void
 frame_unwind_unsigned_register (struct frame_info *frame, int regnum,
                                ULONGEST *val)
 {
-  char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  (*val) = extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
+  (*val) = extract_unsigned_integer (buf,
+                                    register_size (get_frame_arch (frame),
+                                                   regnum));
 }
 
 void
-put_frame_register (struct frame_info *frame, int regnum, const void *buf)
+put_frame_register (struct frame_info *frame, int regnum,
+                   const gdb_byte *buf)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int realnum;
@@ -689,14 +692,14 @@ put_frame_register (struct frame_info *frame, int regnum, const void *buf)
   CORE_ADDR addr;
   frame_register (frame, regnum, &optim, &lval, &addr, &realnum, NULL);
   if (optim)
-    error ("Attempt to assign to a value that was optimized out.");
+    error (_("Attempt to assign to a value that was optimized out."));
   switch (lval)
     {
     case lval_memory:
       {
        /* FIXME: write_memory doesn't yet take constant buffers.
            Arrrg!  */
-       char tmp[MAX_REGISTER_SIZE];
+       gdb_byte tmp[MAX_REGISTER_SIZE];
        memcpy (tmp, buf, register_size (gdbarch, regnum));
        write_memory (addr, tmp, register_size (gdbarch, regnum));
        break;
@@ -705,20 +708,20 @@ put_frame_register (struct frame_info *frame, int regnum, const void *buf)
       regcache_cooked_write (current_regcache, realnum, buf);
       break;
     default:
-      error ("Attempt to assign to an unmodifiable value.");
+      error (_("Attempt to assign to an unmodifiable value."));
     }
 }
 
 /* frame_register_read ()
 
    Find and return the value of REGNUM for the specified stack frame.
-   The number of bytes copied is DEPRECATED_REGISTER_RAW_SIZE
-   (REGNUM).
+   The number of bytes copied is REGISTER_SIZE (REGNUM).
 
    Returns 0 if the register value could not be found.  */
 
 int
-frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
+frame_register_read (struct frame_info *frame, int regnum,
+                    gdb_byte *myaddr)
 {
   int optimized;
   enum lval_type lval;
@@ -739,6 +742,86 @@ frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
   return !optimized;
 }
 
+int
+get_frame_register_bytes (struct frame_info *frame, int regnum,
+                         CORE_ADDR offset, int len, gdb_byte *myaddr)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  /* Skip registers wholly inside of OFFSET.  */
+  while (offset >= register_size (gdbarch, regnum))
+    {
+      offset -= register_size (gdbarch, regnum);
+      regnum++;
+    }
+
+  /* Copy the data.  */
+  while (len > 0)
+    {
+      int curr_len = register_size (gdbarch, regnum) - offset;
+      if (curr_len > len)
+       curr_len = len;
+
+      if (curr_len == register_size (gdbarch, regnum))
+       {
+         if (!frame_register_read (frame, regnum, myaddr))
+           return 0;
+       }
+      else
+       {
+         gdb_byte buf[MAX_REGISTER_SIZE];
+         if (!frame_register_read (frame, regnum, buf))
+           return 0;
+         memcpy (myaddr, buf + offset, curr_len);
+       }
+
+      myaddr += curr_len;
+      len -= curr_len;
+      offset = 0;
+      regnum++;
+    }
+
+  return 1;
+}
+
+void
+put_frame_register_bytes (struct frame_info *frame, int regnum,
+                         CORE_ADDR offset, int len, const gdb_byte *myaddr)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  /* Skip registers wholly inside of OFFSET.  */
+  while (offset >= register_size (gdbarch, regnum))
+    {
+      offset -= register_size (gdbarch, regnum);
+      regnum++;
+    }
+
+  /* Copy the data.  */
+  while (len > 0)
+    {
+      int curr_len = register_size (gdbarch, regnum) - offset;
+      if (curr_len > len)
+       curr_len = len;
+
+      if (curr_len == register_size (gdbarch, regnum))
+       {
+         put_frame_register (frame, regnum, myaddr);
+       }
+      else
+       {
+         gdb_byte buf[MAX_REGISTER_SIZE];
+         frame_register_read (frame, regnum, buf);
+         memcpy (buf + offset, myaddr, curr_len);
+         put_frame_register (frame, regnum, buf);
+       }
+
+      myaddr += curr_len;
+      len -= curr_len;
+      offset = 0;
+      regnum++;
+    }
+}
 
 /* Map between a frame register number and its name.  A frame register
    space is a superset of the cooked register space --- it also
@@ -803,20 +886,6 @@ frame_obstack_zalloc (unsigned long size)
   return data;
 }
 
-CORE_ADDR *
-frame_saved_regs_zalloc (struct frame_info *fi)
-{
-  fi->saved_regs = (CORE_ADDR *)
-    frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
-  return fi->saved_regs;
-}
-
-CORE_ADDR *
-deprecated_get_frame_saved_regs (struct frame_info *fi)
-{
-  return fi->saved_regs;
-}
-
 /* Return the innermost (currently executing) stack frame.  This is
    split into two functions.  The function unwind_to_current_frame()
    is wrapped in catch exceptions so that, even when the unwind of the
@@ -843,17 +912,17 @@ get_current_frame (void)
      explicitly checks that ``print $pc'' with no registers prints "No
      registers".  */
   if (!target_has_registers)
-    error ("No registers.");
+    error (_("No registers."));
   if (!target_has_stack)
-    error ("No stack.");
+    error (_("No stack."));
   if (!target_has_memory)
-    error ("No memory.");
+    error (_("No memory."));
   if (current_frame == NULL)
     {
       struct frame_info *sentinel_frame =
        create_sentinel_frame (current_regcache);
       if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
-                           NULL, RETURN_MASK_ERROR) != 0)
+                           RETURN_MASK_ERROR) != 0)
        {
          /* Oops! Fake a current frame?  Is this useful?  It has a PC
              of zero, for instance.  */
@@ -873,13 +942,19 @@ struct frame_info *deprecated_selected_frame;
    thrown.  */
 
 struct frame_info *
-get_selected_frame (void)
+get_selected_frame (const char *message)
 {
   if (deprecated_selected_frame == NULL)
-    /* Hey!  Don't trust this.  It should really be re-finding the
-       last selected frame of the currently selected thread.  This,
-       though, is better than nothing.  */
-    select_frame (get_current_frame ());
+    {
+      if (message != NULL && (!target_has_registers
+                             || !target_has_stack
+                             || !target_has_memory))
+       error (("%s"), message);
+      /* Hey!  Don't trust this.  It should really be re-finding the
+        last selected frame of the currently selected thread.  This,
+        though, is better than nothing.  */
+      select_frame (get_current_frame ());
+    }
   /* There is always a frame.  */
   gdb_assert (deprecated_selected_frame != NULL);
   return deprecated_selected_frame;
@@ -894,7 +969,7 @@ deprecated_safe_get_selected_frame (void)
 {
   if (!target_has_registers || !target_has_stack || !target_has_memory)
     return NULL;
-  return get_selected_frame ();
+  return get_selected_frame (NULL);
 }
 
 /* Select frame FI (or NULL - to invalidate the current frame).  */
@@ -955,7 +1030,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
                          paddr_nz (addr), paddr_nz (pc));
     }
 
-  fi = frame_obstack_zalloc (sizeof (struct frame_info));
+  fi = FRAME_OBSTACK_ZALLOC (struct frame_info);
 
   fi->next = create_sentinel_frame (current_regcache);
 
@@ -967,9 +1042,6 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
   deprecated_update_frame_base_hack (fi, addr);
   deprecated_update_frame_pc_hack (fi, pc);
 
-  if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
-    DEPRECATED_INIT_EXTRA_FRAME_INFO (0, fi);
-
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "-> ");
@@ -1031,6 +1103,33 @@ reinit_frame_cache (void)
     }
 }
 
+/* Find where a register is saved (in memory or another register).
+   The result of frame_register_unwind is just where it is saved
+   relative to this particular frame.  */
+
+static void
+frame_register_unwind_location (struct frame_info *this_frame, int regnum,
+                               int *optimizedp, enum lval_type *lvalp,
+                               CORE_ADDR *addrp, int *realnump)
+{
+  gdb_assert (this_frame == NULL || this_frame->level >= 0);
+
+  while (this_frame != NULL)
+    {
+      frame_register_unwind (this_frame, regnum, optimizedp, lvalp,
+                            addrp, realnump, NULL);
+
+      if (*optimizedp)
+       break;
+
+      if (*lvalp != lval_register)
+       break;
+
+      regnum = *realnump;
+      this_frame = get_next_frame (this_frame);
+    }
+}
+
 /* Return a "struct frame_info" corresponding to the frame that called
    THIS_FRAME.  Returns NULL if there is no such frame.
 
@@ -1067,6 +1166,7 @@ get_prev_frame_1 (struct frame_info *this_frame)
       return this_frame->prev;
     }
   this_frame->prev_p = 1;
+  this_frame->stop_reason = UNWIND_NO_REASON;
 
   /* Check that this frame's ID was valid.  If it wasn't, don't try to
      unwind to the prev frame.  Be careful to not apply this test to
@@ -1080,6 +1180,7 @@ get_prev_frame_1 (struct frame_info *this_frame)
          fprint_frame (gdb_stdlog, NULL);
          fprintf_unfiltered (gdb_stdlog, " // this ID is NULL }\n");
        }
+      this_frame->stop_reason = UNWIND_NULL_ID;
       return NULL;
     }
 
@@ -1090,14 +1191,75 @@ get_prev_frame_1 (struct frame_info *this_frame)
   if (this_frame->next->level >= 0
       && this_frame->next->unwind->type != SIGTRAMP_FRAME
       && frame_id_inner (this_id, get_frame_id (this_frame->next)))
-    error ("Previous frame inner to this frame (corrupt stack?)");
+    {
+      if (frame_debug)
+       {
+         fprintf_unfiltered (gdb_stdlog, "-> ");
+         fprint_frame (gdb_stdlog, NULL);
+         fprintf_unfiltered (gdb_stdlog, " // this frame ID is inner }\n");
+       }
+      this_frame->stop_reason = UNWIND_INNER_ID;
+      return NULL;
+    }
 
   /* Check that this and the next frame are not identical.  If they
      are, there is most likely a stack cycle.  As with the inner-than
      test above, avoid comparing the inner-most and sentinel frames.  */
   if (this_frame->level > 0
       && frame_id_eq (this_id, get_frame_id (this_frame->next)))
-    error ("Previous frame identical to this frame (corrupt stack?)");
+    {
+      if (frame_debug)
+       {
+         fprintf_unfiltered (gdb_stdlog, "-> ");
+         fprint_frame (gdb_stdlog, NULL);
+         fprintf_unfiltered (gdb_stdlog, " // this frame has same ID }\n");
+       }
+      this_frame->stop_reason = UNWIND_SAME_ID;
+      return NULL;
+    }
+
+  /* Check that this and the next frame do not unwind the PC register
+     to the same memory location.  If they do, then even though they
+     have different frame IDs, the new frame will be bogus; two
+     functions can't share a register save slot for the PC.  This can
+     happen when the prologue analyzer finds a stack adjustment, but
+     no PC save.
+
+     This check does assume that the "PC register" is roughly a
+     traditional PC, even if the gdbarch_unwind_pc method adjusts
+     it (we do not rely on the value, only on the unwound PC being
+     dependent on this value).  A potential improvement would be
+     to have the frame prev_pc method and the gdbarch unwind_pc
+     method set the same lval and location information as
+     frame_register_unwind.  */
+  if (this_frame->level > 0
+      && PC_REGNUM >= 0
+      && get_frame_type (this_frame) == NORMAL_FRAME
+      && get_frame_type (this_frame->next) == NORMAL_FRAME)
+    {
+      int optimized, realnum;
+      enum lval_type lval, nlval;
+      CORE_ADDR addr, naddr;
+
+      frame_register_unwind_location (this_frame, PC_REGNUM, &optimized,
+                                     &lval, &addr, &realnum);
+      frame_register_unwind_location (get_next_frame (this_frame), PC_REGNUM,
+                                     &optimized, &nlval, &naddr, &realnum);
+
+      if (lval == lval_memory && lval == nlval && addr == naddr)
+       {
+         if (frame_debug)
+           {
+             fprintf_unfiltered (gdb_stdlog, "-> ");
+             fprint_frame (gdb_stdlog, NULL);
+             fprintf_unfiltered (gdb_stdlog, " // no saved PC }\n");
+           }
+
+         this_frame->stop_reason = UNWIND_NO_SAVED_PC;
+         this_frame->prev = NULL;
+         return NULL;
+       }
+    }
 
   /* Allocate the new frame but do not wire it in to the frame chain.
      Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along
@@ -1163,6 +1325,35 @@ frame_debug_got_null_frame (struct ui_file *file,
     }
 }
 
+/* Is this (non-sentinel) frame in the "main"() function?  */
+
+static int
+inside_main_func (struct frame_info *this_frame)
+{
+  struct minimal_symbol *msymbol;
+  CORE_ADDR maddr;
+
+  if (symfile_objfile == 0)
+    return 0;
+  msymbol = lookup_minimal_symbol (main_name (), NULL, symfile_objfile);
+  if (msymbol == NULL)
+    return 0;
+  /* Make certain that the code, and not descriptor, address is
+     returned.  */
+  maddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+                                             SYMBOL_VALUE_ADDRESS (msymbol),
+                                             &current_target);
+  return maddr == get_frame_func (this_frame);
+}
+
+/* Test whether THIS_FRAME is inside the process entry point function.  */
+
+static int
+inside_entry_func (struct frame_info *this_frame)
+{
+  return (get_frame_func (this_frame) == entry_point_address ());
+}
+
 /* Return a structure containing various interesting information about
    the frame that called THIS_FRAME.  Returns NULL if there is entier
    no such frame or the frame fails any of a set of target-independent
@@ -1218,25 +1409,39 @@ get_prev_frame (struct frame_info *this_frame)
      get_current_frame().  */
   gdb_assert (this_frame != NULL);
 
-  /* Make sure we pass an address within THIS_FRAME's code block to
-     inside_main_func().  Otherwise, we might stop unwinding at a
-     function which has a call instruction as its last instruction if
-     that function immediately precedes main().  */
+  /* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much
+     sense to stop unwinding at a dummy frame.  One place where a dummy
+     frame may have an address "inside_main_func" is on HPUX.  On HPUX, the
+     pcsqh register (space register for the instruction at the head of the
+     instruction queue) cannot be written directly; the only way to set it
+     is to branch to code that is in the target space.  In order to implement
+     frame dummies on HPUX, the called function is made to jump back to where 
+     the inferior was when the user function was called.  If gdb was inside 
+     the main function when we created the dummy frame, the dummy frame will 
+     point inside the main function.  */
   if (this_frame->level >= 0
+      && get_frame_type (this_frame) != DUMMY_FRAME
       && !backtrace_past_main
-      && inside_main_func (get_frame_address_in_block (this_frame)))
-    /* Don't unwind past main(), but always unwind the sentinel frame.
-       Note, this is done _before_ the frame has been marked as
-       previously unwound.  That way if the user later decides to
-       allow unwinds past main(), that just happens.  */
+      && inside_main_func (this_frame))
+    /* Don't unwind past main().  Note, this is done _before_ the
+       frame has been marked as previously unwound.  That way if the
+       user later decides to enable unwinds past main(), that will
+       automatically happen.  */
     {
       frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside main func");
       return NULL;
     }
 
-  if (this_frame->level > backtrace_limit)
+  /* If the user's backtrace limit has been exceeded, stop.  We must
+     add two to the current level; one of those accounts for backtrace_limit
+     being 1-based and the level being 0-based, and the other accounts for
+     the level of the new frame instead of the level of the current
+     frame.  */
+  if (this_frame->level + 2 > backtrace_limit)
     {
-      error ("Backtrace limit of %d exceeded", backtrace_limit);
+      frame_debug_got_null_frame (gdb_stdlog, this_frame,
+                                 "backtrace limit exceeded");
+      return NULL;
     }
 
   /* If we're already inside the entry function for the main objfile,
@@ -1244,8 +1449,6 @@ get_prev_frame (struct frame_info *this_frame)
      dummy frame PCs typically land in the entry func.  Don't apply
      this test to the sentinel frame.  Sentinel frames should always
      be allowed to unwind.  */
-  /* NOTE: cagney/2003-02-25: Don't enable until someone has found
-     hard evidence that this is needed.  */
   /* NOTE: cagney/2003-07-07: Fixed a bug in inside_main_func() -
      wasn't checking for "main" in the minimal symbols.  With that
      fixed asm-source tests now stop in "main" instead of halting the
@@ -1258,20 +1461,31 @@ get_prev_frame (struct frame_info *this_frame)
      I guess) to determine the address range of the start function.
      That should provide a far better stopper than the current
      heuristics.  */
-  /* NOTE: cagney/2003-07-15: Need to add a "set backtrace
-     beyond-entry-func" command so that this can be selectively
-     disabled.  */
-  if (0
-#if 0
-      && backtrace_beyond_entry_func
-#endif
-      && this_frame->unwind->type != DUMMY_FRAME && this_frame->level >= 0
+  /* NOTE: tausq/2004-10-09: this is needed if, for example, the compiler
+     applied tail-call optimizations to main so that a function called 
+     from main returns directly to the caller of main.  Since we don't
+     stop at main, we should at least stop at the entry point of the
+     application.  */
+  if (!backtrace_past_entry
+      && get_frame_type (this_frame) != DUMMY_FRAME && this_frame->level >= 0
       && inside_entry_func (this_frame))
     {
       frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry func");
       return NULL;
     }
 
+  /* Assume that the only way to get a zero PC is through something
+     like a SIGSEGV or a dummy frame, and hence that NORMAL frames
+     will never unwind a zero PC.  */
+  if (this_frame->level > 0
+      && get_frame_type (this_frame) == NORMAL_FRAME
+      && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME
+      && get_frame_pc (this_frame) == 0)
+    {
+      frame_debug_got_null_frame (gdb_stdlog, this_frame, "zero PC");
+      return NULL;
+    }
+
   return get_prev_frame_1 (this_frame);
 }
 
@@ -1415,19 +1629,6 @@ get_frame_type (struct frame_info *frame)
   return frame->unwind->type;
 }
 
-struct frame_extra_info *
-get_frame_extra_info (struct frame_info *fi)
-{
-  return fi->extra_info;
-}
-
-struct frame_extra_info *
-frame_extra_info_zalloc (struct frame_info *fi, long size)
-{
-  fi->extra_info = frame_obstack_zalloc (size);
-  return fi->extra_info;
-}
-
 void
 deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
 {
@@ -1460,32 +1661,11 @@ deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
   frame->this_id.value.stack_addr = base;
 }
 
-struct frame_info *
-deprecated_frame_xmalloc_with_cleanup (long sizeof_saved_regs,
-                                      long sizeof_extra_info)
-{
-  struct frame_info *frame = XMALLOC (struct frame_info);
-  memset (frame, 0, sizeof (*frame));
-  frame->this_id.p = 1;
-  make_cleanup (xfree, frame);
-  if (sizeof_saved_regs > 0)
-    {
-      frame->saved_regs = xcalloc (1, sizeof_saved_regs);
-      make_cleanup (xfree, frame->saved_regs);
-    }
-  if (sizeof_extra_info > 0)
-    {
-      frame->extra_info = xcalloc (1, sizeof_extra_info);
-      make_cleanup (xfree, frame->extra_info);
-    }
-  return frame;
-}
-
 /* Memory access methods.  */
 
 void
-get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr, void *buf,
-                 int len)
+get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr,
+                 gdb_byte *buf, int len)
 {
   read_memory (addr, buf, len);
 }
@@ -1506,10 +1686,10 @@ get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr,
 
 int
 safe_frame_unwind_memory (struct frame_info *this_frame,
-                         CORE_ADDR addr, void *buf, int len)
+                         CORE_ADDR addr, gdb_byte *buf, int len)
 {
-  /* NOTE: deprecated_read_memory_nobpt returns zero on success!  */
-  return !deprecated_read_memory_nobpt (addr, buf, len);
+  /* NOTE: read_memory_nobpt returns zero on success!  */
+  return !read_memory_nobpt (addr, buf, len);
 }
 
 /* Architecture method.  */
@@ -1547,7 +1727,49 @@ frame_sp_unwind (struct frame_info *next_frame)
       frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
       return sp;
     }
-  internal_error (__FILE__, __LINE__, "Missing unwind SP method");
+  internal_error (__FILE__, __LINE__, _("Missing unwind SP method"));
+}
+
+/* Return the reason why we can't unwind past FRAME.  */
+
+enum unwind_stop_reason
+get_frame_unwind_stop_reason (struct frame_info *frame)
+{
+  /* If we haven't tried to unwind past this point yet, then assume
+     that unwinding would succeed.  */
+  if (frame->prev_p == 0)
+    return UNWIND_NO_REASON;
+
+  /* Otherwise, we set a reason when we succeeded (or failed) to
+     unwind.  */
+  return frame->stop_reason;
+}
+
+/* Return a string explaining REASON.  */
+
+const char *
+frame_stop_reason_string (enum unwind_stop_reason reason)
+{
+  switch (reason)
+    {
+    case UNWIND_NULL_ID:
+      return _("unwinder did not report frame ID");
+
+    case UNWIND_INNER_ID:
+      return _("previous frame inner to this frame (corrupt stack?)");
+
+    case UNWIND_SAME_ID:
+      return _("previous frame identical to this frame (corrupt stack?)");
+
+    case UNWIND_NO_SAVED_PC:
+      return _("frame did not save the PC");
+
+    case UNWIND_NO_REASON:
+    case UNWIND_FIRST_ERROR:
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "Invalid frame stop reason");
+    }
 }
 
 extern initialize_file_ftype _initialize_frame; /* -Wmissing-prototypes */
@@ -1574,42 +1796,60 @@ _initialize_frame (void)
 
   observer_attach_target_changed (frame_observer_target_changed);
 
-  add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, "\
+  add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, _("\
 Set backtrace specific variables.\n\
-Configure backtrace variables such as the backtrace limit",
+Configure backtrace variables such as the backtrace limit"),
                  &set_backtrace_cmdlist, "set backtrace ",
                  0/*allow-unknown*/, &setlist);
-  add_prefix_cmd ("backtrace", class_maintenance, show_backtrace_cmd, "\
+  add_prefix_cmd ("backtrace", class_maintenance, show_backtrace_cmd, _("\
 Show backtrace specific variables\n\
-Show backtrace variables such as the backtrace limit",
+Show backtrace variables such as the backtrace limit"),
                  &show_backtrace_cmdlist, "show backtrace ",
                  0/*allow-unknown*/, &showlist);
 
   add_setshow_boolean_cmd ("past-main", class_obscure,
-                          &backtrace_past_main, "\
-Set whether backtraces should continue past \"main\".""\
-Show whether backtraces should continue past \"main\".""\
+                          &backtrace_past_main, _("\
+Set whether backtraces should continue past \"main\"."), _("\
+Show whether backtraces should continue past \"main\"."), _("\
 Normally the caller of \"main\" is not of interest, so GDB will terminate\n\
 the backtrace at \"main\".  Set this variable if you need to see the rest\n\
-of the stack trace.", "\
-Whether backtraces should continue past \"main\" is %s.",
-                          NULL, NULL, &set_backtrace_cmdlist,
+of the stack trace."),
+                          NULL,
+                          show_backtrace_past_main,
+                          &set_backtrace_cmdlist,
                           &show_backtrace_cmdlist);
 
-  add_setshow_uinteger_cmd ("limit", class_obscure,
-                           &backtrace_limit, "\
-Set an upper bound on the number of backtrace levels.", "\
-Show the upper bound on the number of backtrace levels.", "\
+  add_setshow_boolean_cmd ("past-entry", class_obscure,
+                          &backtrace_past_entry, _("\
+Set whether backtraces should continue past the entry point of a program."),
+                          _("\
+Show whether backtraces should continue past the entry point of a program."),
+                          _("\
+Normally there are no callers beyond the entry point of a program, so GDB\n\
+will terminate the backtrace there.  Set this variable if you need to see \n\
+the rest of the stack trace."),
+                          NULL,
+                          show_backtrace_past_entry,
+                          &set_backtrace_cmdlist,
+                          &show_backtrace_cmdlist);
+
+  add_setshow_integer_cmd ("limit", class_obscure,
+                          &backtrace_limit, _("\
+Set an upper bound on the number of backtrace levels."), _("\
+Show the upper bound on the number of backtrace levels."), _("\
 No more than the specified number of frames can be displayed or examined.\n\
-Zero is unlimited.", "\
-An upper bound on the number of backtrace levels is %s.",
-                           NULL, NULL, &set_backtrace_cmdlist,
-                           &show_backtrace_cmdlist);
+Zero is unlimited."),
+                          NULL,
+                          show_backtrace_limit,
+                          &set_backtrace_cmdlist,
+                          &show_backtrace_cmdlist);
 
   /* Debug this files internals. */
-  deprecated_add_show_from_set
-    (add_set_cmd ("frame", class_maintenance, var_zinteger,
-                 &frame_debug, "Set frame debugging.\n\
-When non-zero, frame specific internal debugging is enabled.", &setdebuglist),
-     &showdebuglist);
+  add_setshow_zinteger_cmd ("frame", class_maintenance, &frame_debug,  _("\
+Set frame debugging."), _("\
+Show frame debugging."), _("\
+When non-zero, frame specific internal debugging is enabled."),
+                           NULL,
+                           show_frame_debug,
+                           &setdebuglist, &showdebuglist);
 }
This page took 0.042217 seconds and 4 git commands to generate.