2003-09-30 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / frame.c
index 3eac39057a6b6b5d42c523260b2a9d4a5b2576fc..02daf543a20e185585aab2159cf2e5f8fa70c6d7 100644 (file)
@@ -28,7 +28,7 @@
 #include "regcache.h"
 #include "gdb_assert.h"
 #include "gdb_string.h"
-#include "builtin-regs.h"
+#include "user-regs.h"
 #include "gdb_obstack.h"
 #include "dummy-frame.h"
 #include "sentinel-frame.h"
@@ -135,9 +135,11 @@ struct frame_info
 
 static int frame_debug;
 
-/* Flag to indicate whether backtraces should stop at main.  */
+/* Flag to indicate whether backtraces should stop at main et.al.  */
+
+static int backtrace_past_main;
+static unsigned int backtrace_limit = UINT_MAX;
 
-static int backtrace_below_main;
 
 void
 fprint_frame_id (struct ui_file *file, struct frame_id id)
@@ -229,8 +231,7 @@ get_frame_id (struct frame_info *fi)
       /* Find the unwinder.  */
       if (fi->unwind == NULL)
        {
-         fi->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                               get_frame_pc (fi));
+         fi->unwind = frame_unwind_find_by_frame (fi->next);
          /* FIXME: cagney/2003-04-02: Rather than storing the frame's
             type in the frame, the unwinder's type should be returned
             directly.  Unfortunatly, legacy code, called by
@@ -376,7 +377,7 @@ frame_pc_unwind (struct frame_info *this_frame)
             implementation is no more than:
           
             frame_unwind_register (this_frame, ISA_PC_REGNUM, buf);
-            return extract_address (buf, size of ISA_PC_REGNUM);
+            return extract_unsigned_integer (buf, size of ISA_PC_REGNUM);
 
             Note: this method is very heavily dependent on a correct
             register-unwind implementation, it pays to fix that
@@ -422,8 +423,11 @@ frame_func_unwind (struct frame_info *fi)
 {
   if (!fi->prev_func.p)
     {
+      /* Make certain that this, and not the adjacent, function is
+         found.  */
+      CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi);
       fi->prev_func.p = 1;
-      fi->prev_func.addr = get_pc_function_start (frame_pc_unwind (fi));
+      fi->prev_func.addr = get_pc_function_start (addr_in_block);
       if (frame_debug)
        fprintf_unfiltered (gdb_stdlog,
                            "{ frame_func_unwind (fi=%d) -> 0x%s }\n",
@@ -497,7 +501,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
     {
       fprintf_unfiltered (gdb_stdlog,
                          "{ frame_register_unwind (frame=%d,regnum=\"%s\",...) ",
-                         frame->level, frame_map_regnum_to_name (regnum));
+                         frame->level, frame_map_regnum_to_name (frame, regnum));
     }
 
   /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
@@ -517,8 +521,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
   /* Find the unwinder.  */
   if (frame->unwind == NULL)
     {
-      frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                              get_frame_pc (frame));
+      frame->unwind = frame_unwind_find_by_frame (frame->next);
       /* FIXME: cagney/2003-04-02: Rather than storing the frame's
         type in the frame, the unwinder's type should be returned
         directly.  Unfortunatly, legacy code, called by
@@ -546,7 +549,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
       else
        {
          int i;
-         const char *buf = bufferp;
+         const unsigned char *buf = bufferp;
          fprintf_unfiltered (gdb_stdlog, "[");
          for (i = 0; i < register_size (current_gdbarch, regnum); i++)
            fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
@@ -615,92 +618,86 @@ frame_unwind_register (struct frame_info *frame, int regnum, void *buf)
 }
 
 void
-frame_unwind_signed_register (struct frame_info *frame, int regnum,
-                             LONGEST *val)
+get_frame_register (struct frame_info *frame,
+                   int regnum, void *buf)
+{
+  frame_unwind_register (frame->next, regnum, buf);
+}
+
+LONGEST
+frame_unwind_register_signed (struct frame_info *frame, int regnum)
 {
   char buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  (*val) = extract_signed_integer (buf, REGISTER_VIRTUAL_SIZE (regnum));
+  return extract_signed_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
 }
 
-void
-frame_unwind_unsigned_register (struct frame_info *frame, int regnum,
-                               ULONGEST *val)
+LONGEST
+get_frame_register_signed (struct frame_info *frame, int regnum)
+{
+  return frame_unwind_register_signed (frame->next, regnum);
+}
+
+ULONGEST
+frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
 {
   char buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  (*val) = extract_unsigned_integer (buf, REGISTER_VIRTUAL_SIZE (regnum));
+  return extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
 }
 
-void
-frame_read_register (struct frame_info *frame, int regnum, void *buf)
+ULONGEST
+get_frame_register_unsigned (struct frame_info *frame, int regnum)
 {
-  gdb_assert (frame != NULL && frame->next != NULL);
-  frame_unwind_register (frame->next, regnum, buf);
+  return frame_unwind_register_unsigned (frame->next, regnum);
 }
 
 void
-frame_read_unsigned_register (struct frame_info *frame, int regnum,
-                             ULONGEST *val)
-{
-  /* NOTE: cagney/2002-10-31: There is a bit of dogma here - there is
-     always a frame.  Both this, and the equivalent
-     frame_read_signed_register() function, can only be called with a
-     valid frame.  If, for some reason, this function is called
-     without a frame then the problem isn't here, but rather in the
-     caller.  It should of first created a frame and then passed that
-     in.  */
-  /* NOTE: cagney/2002-10-31: As a side bar, keep in mind that the
-     ``current_frame'' should not be treated as a special case.  While
-     ``get_next_frame (current_frame) == NULL'' currently holds, it
-     should, as far as possible, not be relied upon.  In the future,
-     ``get_next_frame (current_frame)'' may instead simply return a
-     normal frame object that simply always gets register values from
-     the register cache.  Consequently, frame code should try to avoid
-     tests like ``if get_next_frame() == NULL'' and instead just rely
-     on recursive frame calls (like the below code) when manipulating
-     a frame chain.  */
-  gdb_assert (frame != NULL && frame->next != NULL);
-  frame_unwind_unsigned_register (frame->next, regnum, val);
+frame_unwind_signed_register (struct frame_info *frame, int regnum,
+                             LONGEST *val)
+{
+  char buf[MAX_REGISTER_SIZE];
+  frame_unwind_register (frame, regnum, buf);
+  (*val) = extract_signed_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
 }
 
 void
-frame_read_signed_register (struct frame_info *frame, int regnum,
-                           LONGEST *val)
+frame_unwind_unsigned_register (struct frame_info *frame, int regnum,
+                               ULONGEST *val)
 {
-  /* See note above in frame_read_unsigned_register().  */
-  gdb_assert (frame != NULL && frame->next != NULL);
-  frame_unwind_signed_register (frame->next, regnum, val);
+  char buf[MAX_REGISTER_SIZE];
+  frame_unwind_register (frame, regnum, buf);
+  (*val) = extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
 }
 
 void
-generic_unwind_get_saved_register (char *raw_buffer,
-                                  int *optimizedp,
-                                  CORE_ADDR *addrp,
-                                  struct frame_info *frame,
-                                  int regnum,
-                                  enum lval_type *lvalp)
-{
-  int optimizedx;
-  CORE_ADDR addrx;
-  int realnumx;
-  enum lval_type lvalx;
-
-  if (!target_has_registers)
-    error ("No registers.");
-
-  /* Keep things simple, ensure that all the pointers (except valuep)
-     are non NULL.  */
-  if (optimizedp == NULL)
-    optimizedp = &optimizedx;
-  if (lvalp == NULL)
-    lvalp = &lvalx;
-  if (addrp == NULL)
-    addrp = &addrx;
-
-  gdb_assert (frame != NULL && frame->next != NULL);
-  frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
-                        &realnumx, raw_buffer);
+put_frame_register (struct frame_info *frame, int regnum, const void *buf)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  int realnum;
+  int optim;
+  enum lval_type lval;
+  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.");
+  switch (lval)
+    {
+    case lval_memory:
+      {
+       /* FIXME: write_memory doesn't yet take constant buffers.
+           Arrrg!  */
+       char tmp[MAX_REGISTER_SIZE];
+       memcpy (tmp, buf, register_size (gdbarch, regnum));
+       write_memory (addr, tmp, register_size (gdbarch, regnum));
+       break;
+      }
+    case lval_register:
+      regcache_cooked_write (current_regcache, realnum, buf);
+      break;
+    default:
+      error ("Attempt to assign to an unmodifiable value.");
+    }
 }
 
 /* frame_register_read ()
@@ -738,47 +735,20 @@ frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
    includes builtin registers.  */
 
 int
-frame_map_name_to_regnum (const char *name, int len)
+frame_map_name_to_regnum (struct frame_info *frame, const char *name, int len)
 {
-  int i;
-
-  if (len < 0)
-    len = strlen (name);
-
-  /* Search register name space. */
-  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
-    if (REGISTER_NAME (i) && len == strlen (REGISTER_NAME (i))
-       && strncmp (name, REGISTER_NAME (i), len) == 0)
-      {
-       return i;
-      }
-
-  /* Try builtin registers.  */
-  i = builtin_reg_map_name_to_regnum (name, len);
-  if (i >= 0)
-    {
-      /* A builtin register doesn't fall into the architecture's
-         register range.  */
-      gdb_assert (i >= NUM_REGS + NUM_PSEUDO_REGS);
-      return i;
-    }
-
-  return -1;
+  return user_reg_map_name_to_regnum (get_frame_arch (frame), name, len);
 }
 
 const char *
-frame_map_regnum_to_name (int regnum)
+frame_map_regnum_to_name (struct frame_info *frame, int regnum)
 {
-  if (regnum < 0)
-    return NULL;
-  if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
-    return REGISTER_NAME (regnum);
-  return builtin_reg_map_regnum_to_name (regnum);
+  return user_reg_map_regnum_to_name (get_frame_arch (frame), regnum);
 }
 
 /* Create a sentinel frame.  */
 
-struct frame_info *
+static struct frame_info *
 create_sentinel_frame (struct regcache *regcache)
 {
   struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
@@ -833,7 +803,7 @@ frame_saved_regs_zalloc (struct frame_info *fi)
 }
 
 CORE_ADDR *
-get_frame_saved_regs (struct frame_info *fi)
+deprecated_get_frame_saved_regs (struct frame_info *fi)
 {
   return fi->saved_regs;
 }
@@ -906,12 +876,24 @@ get_selected_frame (void)
   return deprecated_selected_frame;
 }
 
+/* This is a variant of get_selected_frame which can be called when
+   the inferior does not have a frame; in that case it will return
+   NULL instead of calling error ().  */
+
+struct frame_info *
+deprecated_safe_get_selected_frame (void)
+{
+  if (!target_has_registers || !target_has_stack || !target_has_memory)
+    return NULL;
+  return get_selected_frame ();
+}
+
 /* Select frame FI (or NULL - to invalidate the current frame).  */
 
 void
 select_frame (struct frame_info *fi)
 {
-  register struct symtab *s;
+  struct symtab *s;
 
   deprecated_selected_frame = fi;
   /* NOTE: cagney/2002-05-04: FI can be NULL.  This occures when the
@@ -963,17 +945,16 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
   struct frame_info *frame = next_frame->prev;
   gdb_assert (frame != NULL);
 
-  /* Only (older) architectures that implement the
-     DEPRECATED_FRAME_INIT_SAVED_REGS method should be using this
-     function.  */
-  gdb_assert (DEPRECATED_FRAME_INIT_SAVED_REGS_P ());
-
-  /* Load the saved_regs register cache.  */
-  if (get_frame_saved_regs (frame) == NULL)
-    DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
+  if (deprecated_get_frame_saved_regs (frame) == NULL)
+    {
+      /* If nothing's initialized the saved regs, do it now.  */
+      gdb_assert (DEPRECATED_FRAME_INIT_SAVED_REGS_P ());
+      DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
+      gdb_assert (deprecated_get_frame_saved_regs (frame) != NULL);
+    }
 
-  if (get_frame_saved_regs (frame) != NULL
-      && get_frame_saved_regs (frame)[regnum] != 0)
+  if (deprecated_get_frame_saved_regs (frame) != NULL
+      && deprecated_get_frame_saved_regs (frame)[regnum] != 0)
     {
       if (regnum == SP_REGNUM)
        {
@@ -986,7 +967,7 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
            /* NOTE: cagney/2003-05-09: In-lined store_address with
                it's body - store_unsigned_integer.  */
            store_unsigned_integer (bufferp, REGISTER_RAW_SIZE (regnum),
-                                   get_frame_saved_regs (frame)[regnum]);
+                                   deprecated_get_frame_saved_regs (frame)[regnum]);
        }
       else
        {
@@ -994,7 +975,7 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
              a local copy of its value.  */
          *optimizedp = 0;
          *lvalp = lval_memory;
-         *addrp = get_frame_saved_regs (frame)[regnum];
+         *addrp = deprecated_get_frame_saved_regs (frame)[regnum];
          *realnump = -1;
          if (bufferp != NULL)
            {
@@ -1013,13 +994,13 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
                {
                  regs[regnum]
                    = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum));
-                 read_memory (get_frame_saved_regs (frame)[regnum], regs[regnum],
+                 read_memory (deprecated_get_frame_saved_regs (frame)[regnum], regs[regnum],
                               REGISTER_RAW_SIZE (regnum));
                }
              memcpy (bufferp, regs[regnum], REGISTER_RAW_SIZE (regnum));
 #else
              /* Read the value in from memory.  */
-             read_memory (get_frame_saved_regs (frame)[regnum], bufferp,
+             read_memory (deprecated_get_frame_saved_regs (frame)[regnum], bufferp,
                           REGISTER_RAW_SIZE (regnum));
 #endif
            }
@@ -1067,9 +1048,9 @@ const struct frame_unwind *legacy_saved_regs_unwind = &legacy_saved_regs_unwinde
    calculated rather than fetched).  We will use not_lval for values
    fetched from generic dummy frames.
 
-   Set *ADDRP to the address, either in memory or as a REGISTER_BYTE
-   offset into the registers array.  If the value is stored in a dummy
-   frame, set *ADDRP to zero.
+   Set *ADDRP to the address, either in memory or as a
+   DEPRECATED_REGISTER_BYTE offset into the registers array.  If the
+   value is stored in a dummy frame, set *ADDRP to zero.
 
    The argument RAW_BUFFER must point to aligned memory.  */
 
@@ -1082,8 +1063,6 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
   if (!target_has_registers)
     error ("No registers.");
 
-  gdb_assert (DEPRECATED_FRAME_INIT_SAVED_REGS_P ());
-
   /* Normal systems don't optimize out things with register numbers.  */
   if (optimized != NULL)
     *optimized = 0;
@@ -1112,15 +1091,15 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
                   fly, constructs either a raw or pseudo register
                   from the raw register cache.  */
                regcache_raw_read
-                 (generic_find_dummy_frame (get_frame_pc (frame),
-                                            get_frame_base (frame)),
+                 (deprecated_find_dummy_frame_regcache (get_frame_pc (frame),
+                                                        get_frame_base (frame)),
                   regnum, raw_buffer);
              return;
            }
 
          DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
-         if (get_frame_saved_regs (frame) != NULL
-             && get_frame_saved_regs (frame)[regnum] != 0)
+         if (deprecated_get_frame_saved_regs (frame) != NULL
+             && deprecated_get_frame_saved_regs (frame)[regnum] != 0)
            {
              if (lval)         /* found it saved on the stack */
                *lval = lval_memory;
@@ -1131,14 +1110,14 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
                        with it's body - store_unsigned_integer.  */
                    store_unsigned_integer (raw_buffer,
                                            REGISTER_RAW_SIZE (regnum),
-                                           get_frame_saved_regs (frame)[regnum]);
+                                           deprecated_get_frame_saved_regs (frame)[regnum]);
                }
              else
                {
                  if (addrp)    /* any other register */
-                   *addrp = get_frame_saved_regs (frame)[regnum];
+                   *addrp = deprecated_get_frame_saved_regs (frame)[regnum];
                  if (raw_buffer)
-                   read_memory (get_frame_saved_regs (frame)[regnum], raw_buffer,
+                   read_memory (deprecated_get_frame_saved_regs (frame)[regnum], raw_buffer,
                                 REGISTER_RAW_SIZE (regnum));
                }
              return;
@@ -1152,7 +1131,7 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
   if (lval)                    /* found it in a live register */
     *lval = lval_register;
   if (addrp)
-    *addrp = REGISTER_BYTE (regnum);
+    *addrp = DEPRECATED_REGISTER_BYTE (regnum);
   if (raw_buffer)
     deprecated_read_register_gen (regnum, raw_buffer);
 }
@@ -1201,7 +1180,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
 
   /* Select/initialize both the unwind function and the frame's type
      based on the PC.  */
-  fi->unwind = frame_unwind_find_by_pc (current_gdbarch, pc);
+  fi->unwind = frame_unwind_find_by_frame (fi->next);
   if (fi->unwind->type != UNKNOWN_FRAME)
     fi->type = fi->unwind->type;
   else
@@ -1237,6 +1216,12 @@ get_next_frame (struct frame_info *this_frame)
     return NULL;
 }
 
+struct frame_info *
+deprecated_get_next_frame_hack (struct frame_info *this_frame)
+{
+  return this_frame->next;
+}
+
 /* Flush the entire frame cache.  */
 
 void
@@ -1354,8 +1339,7 @@ legacy_get_prev_frame (struct frame_info *this_frame)
 
       /* Set the unwind functions based on that identified PC.  Ditto
          for the "type" but strongly prefer the unwinder's frame type.  */
-      prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                             get_frame_pc (prev));
+      prev->unwind = frame_unwind_find_by_frame (prev->next);
       if (prev->unwind->type == UNKNOWN_FRAME)
        prev->type = frame_type_from_pc (get_frame_pc (prev));
       else
@@ -1373,10 +1357,6 @@ legacy_get_prev_frame (struct frame_info *this_frame)
             or some random address on the stack.  Trying to use that
             PC to apply standard frame ID unwind techniques is just
             asking for trouble.  */
-         /* Assume call_function_by_hand(), 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
@@ -1475,6 +1455,12 @@ legacy_get_prev_frame (struct frame_info *this_frame)
     /* FIXME: 2002-11-09: There isn't any reason to special case this
        edge condition.  Instead the per-architecture code should hande
        it locally.  */
+    /* FIXME: cagney/2003-06-16: This returns the inner most stack
+       address for the previous frame, that, however, is wrong.  It
+       should be the inner most stack address for the previous to
+       previous frame.  This is because it is the previous to previous
+       frame's innermost stack address that is constant through out
+       the lifetime of the previous frame (trust me :-).  */
     address = get_frame_base (this_frame);
   else
     {
@@ -1493,8 +1479,28 @@ legacy_get_prev_frame (struct frame_info *this_frame)
          this to after the ffi test; I'd rather have backtraces from
          start go curfluy than have an abort called from main not show
          main.  */
-      gdb_assert (DEPRECATED_FRAME_CHAIN_P ());
-      address = DEPRECATED_FRAME_CHAIN (this_frame);
+      if (DEPRECATED_FRAME_CHAIN_P ())
+       address = DEPRECATED_FRAME_CHAIN (this_frame);
+      else
+       {
+         /* Someone is part way through coverting an old architecture
+             to the new frame code.  Implement FRAME_CHAIN the way the
+             new frame will.  */
+         /* Find PREV frame's unwinder.  */
+         prev->unwind = frame_unwind_find_by_frame (this_frame->next);
+         /* FIXME: cagney/2003-04-02: Rather than storing the frame's
+            type in the frame, the unwinder's type should be returned
+            directly.  Unfortunatly, legacy code, called by
+            legacy_get_prev_frame, explicitly set the frames type
+            using the method deprecated_set_frame_type().  */
+         prev->type = prev->unwind->type;
+         /* Find PREV frame's ID.  */
+         prev->unwind->this_id (this_frame,
+                                &prev->prologue_cache,
+                                &prev->this_id.value);
+         prev->this_id.p = 1;
+         address = prev->this_id.value.stack_addr;
+       }
 
       if (!legacy_frame_chain_valid (address, this_frame))
        {
@@ -1637,9 +1643,12 @@ legacy_get_prev_frame (struct frame_info *this_frame)
   /* Initialize the code used to unwind the frame PREV based on the PC
      (and probably other architectural information).  The PC lets you
      check things like the debug info at that point (dwarf2cfi?) and
-     use that to decide how the frame should be unwound.  */
-  prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                         get_frame_pc (prev));
+     use that to decide how the frame should be unwound.
+
+     If there isn't a FRAME_CHAIN, the code above will have already
+     done this.  */
+  if (prev->unwind == NULL)
+    prev->unwind = frame_unwind_find_by_frame (prev->next);
 
   /* If the unwinder provides a frame type, use it.  Otherwize
      continue on to that heuristic mess.  */
@@ -1647,6 +1656,7 @@ legacy_get_prev_frame (struct frame_info *this_frame)
     {
       prev->type = prev->unwind->type;
       if (prev->type == NORMAL_FRAME)
+       /* FIXME: cagney/2003-06-16: would get_frame_pc() be better?  */
        prev->this_id.value.code_addr
          = get_pc_function_start (prev->this_id.value.code_addr);
       if (frame_debug)
@@ -1765,7 +1775,7 @@ get_prev_frame (struct frame_info *this_frame)
   gdb_assert (this_frame != NULL);
 
   if (this_frame->level >= 0
-      && !backtrace_below_main
+      && !backtrace_past_main
       && inside_main_func (get_frame_pc (this_frame)))
     /* Don't unwind past main(), bug always unwind the sentinel frame.
        Note, this is done _before_ the frame has been marked as
@@ -1777,6 +1787,50 @@ get_prev_frame (struct frame_info *this_frame)
       return NULL;
     }
 
+  if (this_frame->level > backtrace_limit)
+    {
+      error ("Backtrace limit of %d exceeded", backtrace_limit);
+    }
+
+  /* If we're already inside the entry function for the main objfile,
+     then it isn't valid.  Don't apply this test to a dummy frame -
+     dummy frame PC's 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
+     backtrace in wierd and wonderful ways somewhere inside the entry
+     file.  Suspect that deprecated_inside_entry_file and
+     inside_entry_func tests were added to work around that (now
+     fixed) case.  */
+  /* NOTE: cagney/2003-07-15: danielj (if I'm reading it right)
+     suggested having the inside_entry_func test use the
+     inside_main_func msymbol trick (along with entry_point_address 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->type != DUMMY_FRAME && this_frame->level >= 0
+      && inside_entry_func (get_frame_pc (this_frame)))
+    {
+      if (frame_debug)
+       {
+         fprintf_unfiltered (gdb_stdlog, "-> ");
+         fprint_frame (gdb_stdlog, NULL);
+         fprintf_unfiltered (gdb_stdlog, "// inside entry func }\n");
+       }
+      return NULL;
+    }
+
   /* Only try to do the unwind once.  */
   if (this_frame->prev_p)
     {
@@ -1790,7 +1844,6 @@ get_prev_frame (struct frame_info *this_frame)
     }
   this_frame->prev_p = 1;
 
-#if 0
   /* If we're inside the entry file, it isn't valid.  Don't apply this
      test to a dummy frame - dummy frame PC's typically land in the
      entry file.  Don't apply this test to the sentinel frame.
@@ -1802,44 +1855,25 @@ get_prev_frame (struct frame_info *this_frame)
   /* NOTE: cagney/2003-01-10: If there is a way of disabling this test
      then it should probably be moved to before the ->prev_p test,
      above.  */
-  /* NOTE: vinschen/2003-04-01: Disabled.  It turns out that the call to
-     inside_entry_file destroys a meaningful backtrace under some
-     conditions.  E. g. the backtrace tests in the asm-source testcase
-     are broken for some targets.  In this test the functions are all
-     implemented as part of one file and the testcase is not necessarily
-     linked with a start file (depending on the target).  What happens is,
-     that the first frame is printed normaly and following frames are
-     treated as being inside the enttry file then.  This way, only the
-     #0 frame is printed in the backtrace output.  */
-  if (this_frame->type != DUMMY_FRAME && this_frame->level >= 0
-      && inside_entry_file (get_frame_pc (this_frame)))
-    {
-      if (frame_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "-> ");
-         fprint_frame (gdb_stdlog, NULL);
-         fprintf_unfiltered (gdb_stdlog, " // inside entry file }\n");
-       }
-      return NULL;
-    }
-#endif
-
-  /* If we're already inside the entry function for the main objfile,
-     then it isn't valid.  Don't apply this test to a dummy frame -
-     dummy frame PC's 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: vinschen/2003-04-01: Disabled.  It turns out that the call
+     to deprecated_inside_entry_file destroys a meaningful backtrace
+     under some conditions.  E. g. the backtrace tests in the
+     asm-source testcase are broken for some targets.  In this test
+     the functions are all implemented as part of one file and the
+     testcase is not necessarily linked with a start file (depending
+     on the target).  What happens is, that the first frame is printed
+     normaly and following frames are treated as being inside the
+     enttry file then.  This way, only the #0 frame is printed in the
+     backtrace output.  */
   if (0
       && this_frame->type != DUMMY_FRAME && this_frame->level >= 0
-      && inside_entry_func (get_frame_pc (this_frame)))
+      && deprecated_inside_entry_file (get_frame_pc (this_frame)))
     {
       if (frame_debug)
        {
          fprintf_unfiltered (gdb_stdlog, "-> ");
          fprint_frame (gdb_stdlog, NULL);
-         fprintf_unfiltered (gdb_stdlog, "// inside entry func }\n");
+         fprintf_unfiltered (gdb_stdlog, " // inside entry file }\n");
        }
       return NULL;
     }
@@ -1867,25 +1901,21 @@ get_prev_frame (struct frame_info *this_frame)
     }
 
   /* Check that this frame's ID isn't inner to (younger, below, next)
-     the next frame.  This happens when frame unwind goes backwards.
-     Since the sentinel frame isn't valid, don't apply this if this
-     frame is entier the inner-most or sentinel frame.  */
+     the next frame.  This happens when frame unwind goes backwards.
+     Since the sentinel frame doesn't really exist, don't compare the
+     inner-most against that sentinel.  */
   if (this_frame->level > 0
       && frame_id_inner (get_frame_id (this_frame),
                         get_frame_id (this_frame->next)))
-    error ("This frame inner-to next frame (corrupt stack?)");
-
-  /* Check that this and the next frame are different.  If they are
-     not, there is most likely a stack cycle.  As with the inner-than
-     test, avoid the inner-most and sentinel frames.  */
-  /* FIXME: cagney/2003-03-17: Can't yet enable this this check. The
-     frame_id_eq() method doesn't yet use function addresses when
-     comparing frame IDs.  */
-  if (0
-      && this_frame->level > 0
+    error ("Previous frame inner to this frame (corrupt stack?)");
+
+  /* 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 (get_frame_id (this_frame),
                      get_frame_id (this_frame->next)))
-    error ("This frame identical to next frame (corrupt stack?)");
+    error ("Previous frame identical to this frame (corrupt stack?)");
 
   /* 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
@@ -1944,11 +1974,11 @@ get_prev_frame (struct frame_info *this_frame)
      Doing this makes it possible for the user to examine a frame that
      has an invalid frame ID.
 
-     The very old VAX frame_args_address_correct() method noted: [...]
-     For the sake of argument, suppose that the stack is somewhat
-     trashed (which is one reason that "info frame" exists).  So,
-     return 0 (indicating we don't know the address of the arglist) if
-     we don't know what frame this frame calls.  */
+     Some very old VAX code noted: [...]  For the sake of argument,
+     suppose that the stack is somewhat trashed (which is one reason
+     that "info frame" exists).  So, return 0 (indicating we don't
+     know the address of the arglist) if we don't know what frame this
+     frame calls.  */
 
   /* Link it in.  */
   this_frame->prev = prev_frame;
@@ -1971,6 +2001,33 @@ get_frame_pc (struct frame_info *frame)
   return frame_pc_unwind (frame->next);
 }
 
+/* Return an address of that falls within the frame's code block.  */
+
+CORE_ADDR
+frame_unwind_address_in_block (struct frame_info *next_frame)
+{
+  /* A draft address.  */
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+
+  /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel),
+     and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS
+     frame's PC ends up pointing at the instruction fallowing the
+     "call".  Adjust that PC value so that it falls on the call
+     instruction (which, hopefully, falls within THIS frame's code
+     block.  So far it's proved to be a very good approximation.  See
+     get_frame_type for why ->type can't be used.  */
+  if (next_frame->level >= 0
+      && get_frame_type (next_frame) == NORMAL_FRAME)
+    --pc;
+  return pc;
+}
+
+CORE_ADDR
+get_frame_address_in_block (struct frame_info *this_frame)
+{
+  return frame_unwind_address_in_block (this_frame->next);
+}
+
 static int
 pc_notcurrent (struct frame_info *frame)
 {
@@ -2010,7 +2067,7 @@ get_frame_base_address (struct frame_info *fi)
   if (get_frame_type (fi) != NORMAL_FRAME)
     return 0;
   if (fi->base == NULL)
-    fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
+    fi->base = frame_base_find_by_frame (fi->next);
   /* Sneaky: If the low-level unwind and high-level base code share a
      common unwinder, let them share the prologue cache.  */
   if (fi->base->unwind == fi->unwind)
@@ -2026,7 +2083,7 @@ get_frame_locals_address (struct frame_info *fi)
     return 0;
   /* If there isn't a frame address method, find it.  */
   if (fi->base == NULL)
-    fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
+    fi->base = frame_base_find_by_frame (fi->next);
   /* Sneaky: If the low-level unwind and high-level base code share a
      common unwinder, let them share the prologue cache.  */
   if (fi->base->unwind == fi->unwind)
@@ -2044,7 +2101,7 @@ get_frame_args_address (struct frame_info *fi)
     return 0;
   /* If there isn't a frame address method, find it.  */
   if (fi->base == NULL)
-    fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
+    fi->base = frame_base_find_by_frame (fi->next);
   /* Sneaky: If the low-level unwind and high-level base code share a
      common unwinder, let them share the prologue cache.  */
   if (fi->base->unwind == fi->unwind)
@@ -2083,8 +2140,7 @@ get_frame_type (struct frame_info *frame)
     {
       /* Initialize the frame's unwinder because it is that which
          provides the frame's type.  */
-      frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                              get_frame_pc (frame));
+      frame->unwind = frame_unwind_find_by_frame (frame->next);
       /* FIXME: cagney/2003-04-02: Rather than storing the frame's
         type in the frame, the unwinder's type should be returned
         directly.  Unfortunatly, legacy code, called by
@@ -2195,7 +2251,8 @@ deprecated_set_frame_context (struct frame_info *fi,
 struct frame_info *
 deprecated_frame_xmalloc (void)
 {
-  struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
+  struct frame_info *frame = XMALLOC (struct frame_info);
+  memset (frame, 0, sizeof (*frame));
   frame->this_id.p = 1;
   return frame;
 }
@@ -2219,6 +2276,68 @@ deprecated_frame_xmalloc_with_cleanup (long sizeof_saved_regs,
   return frame;
 }
 
+/* Memory access methods.  */
+
+void
+get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr, void *buf,
+                 int len)
+{
+  read_memory (addr, buf, len);
+}
+
+LONGEST
+get_frame_memory_signed (struct frame_info *this_frame, CORE_ADDR addr,
+                        int len)
+{
+  return read_memory_integer (addr, len);
+}
+
+ULONGEST
+get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr,
+                          int len)
+{
+  return read_memory_unsigned_integer (addr, len);
+}
+
+/* Architecture method.  */
+
+struct gdbarch *
+get_frame_arch (struct frame_info *this_frame)
+{
+  return current_gdbarch;
+}
+
+/* Stack pointer methods.  */
+
+CORE_ADDR
+get_frame_sp (struct frame_info *this_frame)
+{
+  return frame_sp_unwind (this_frame->next);
+}
+
+CORE_ADDR
+frame_sp_unwind (struct frame_info *next_frame)
+{
+  /* Normality, an architecture that provides a way of obtaining any
+     frame inner-most address.  */
+  if (gdbarch_unwind_sp_p (current_gdbarch))
+    return gdbarch_unwind_sp (current_gdbarch, next_frame);
+  /* Things are looking grim.  If it's the inner-most frame and there
+     is a TARGET_READ_SP then that can be used.  */
+  if (next_frame->level < 0 && TARGET_READ_SP_P ())
+    return TARGET_READ_SP ();
+  /* Now things are really are grim.  Hope that the value returned by
+     the SP_REGNUM register is meaningful.  */
+  if (SP_REGNUM >= 0)
+    {
+      ULONGEST sp;
+      frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
+      return sp;
+    }
+  internal_error (__FILE__, __LINE__, "Missing unwind SP method");
+}
+
+
 int
 legacy_frame_p (struct gdbarch *current_gdbarch)
 {
@@ -2226,8 +2345,24 @@ legacy_frame_p (struct gdbarch *current_gdbarch)
          || DEPRECATED_INIT_FRAME_PC_FIRST_P ()
          || DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()
          || DEPRECATED_FRAME_CHAIN_P ()
-         || !gdbarch_unwind_dummy_id_p (current_gdbarch)
-         || !SAVE_DUMMY_FRAME_TOS_P ());
+         || !gdbarch_unwind_dummy_id_p (current_gdbarch));
+}
+
+extern initialize_file_ftype _initialize_frame; /* -Wmissing-prototypes */
+
+static struct cmd_list_element *set_backtrace_cmdlist;
+static struct cmd_list_element *show_backtrace_cmdlist;
+
+static void
+set_backtrace_cmd (char *args, int from_tty)
+{
+  help_list (set_backtrace_cmdlist, "set backtrace ", -1, gdb_stdout);
+}
+
+static void
+show_backtrace_cmd (char *args, int from_tty)
+{
+  cmd_show_list (show_backtrace_cmdlist, from_tty, "");
 }
 
 void
@@ -2235,13 +2370,19 @@ _initialize_frame (void)
 {
   obstack_init (&frame_cache_obstack);
 
-  /* FIXME: cagney/2003-01-19: This command needs a rename.  Suggest
-     `set backtrace {past,beyond,...}-main'.  Also suggest adding `set
-     backtrace ...-start' to control backtraces past start.  The
-     problem with `below' is that it stops the `up' command.  */
-
-  add_setshow_boolean_cmd ("backtrace-below-main", class_obscure,
-                          &backtrace_below_main, "\
+  add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, "\
+Set backtrace specific variables.\n\
+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, "\
+Show backtrace specific variables\n\
+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\".\n\
 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\
@@ -2250,8 +2391,17 @@ Show whether backtraces should continue past \"main\".\n\
 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.",
-                          NULL, NULL, &setlist, &showlist);
-
+                          NULL, NULL, &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.\n\
+No more than the specified number of frames can be displayed or examined.\n\
+Zero is unlimited.", "\
+Show the upper bound on the number of backtrace levels.",
+                           NULL, NULL, &set_backtrace_cmdlist,
+                           &show_backtrace_cmdlist);
 
   /* Debug this files internals. */
   add_show_from_set (add_set_cmd ("frame", class_maintenance, var_zinteger,
This page took 0.035872 seconds and 4 git commands to generate.