2004-07-26 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / frame.c
index 55e9dc580b535d4454299ae39d8974e8534bb969..bfc5ae84155a7504ac01e8ae0eb3db32c10f4641 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 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -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"
@@ -39,6 +39,9 @@
 #include "frame-base.h"
 #include "command.h"
 #include "gdbcmd.h"
+#include "observer.h"
+
+static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
 
 /* We keep a cache of stack frames, each of which is a "struct
    frame_info".  The innermost one gets allocated (in
@@ -57,17 +60,17 @@ struct frame_info
      increases.  This is a cached value.  It could just as easily be
      computed by counting back from the selected frame to the inner
      most frame.  */
-  /* NOTE: cagney/2002-04-05: Perhaphs a level of ``-1'' should be
+  /* NOTE: cagney/2002-04-05: Perhaps a level of ``-1'' should be
      reserved to indicate a bogus frame - one that has been created
      just to keep GDB happy (GDB always needs a frame).  For the
      moment leave this as speculation.  */
   int level;
 
   /* The frame's type.  */
-  /* FIXME: cagney/2003-04-02: Should instead be returning
-     ->unwind->type.  Unfortunatly, legacy code is still explicitly
-     setting the type using the method deprecated_set_frame_type.
-     Eliminate that method and this field can be eliminated.  */
+  /* FIXME: cagney/2004-05-01: Should instead just use ->unwind->type.
+     Unfortunately, legacy_get_prev_frame is still explicitly setting
+     the type.  Eliminate that method and this field can be
+     eliminated.  */
   enum frame_type type;
 
   /* For each register, address of where it was saved on entry to the
@@ -86,14 +89,10 @@ struct frame_info
      initialized by DEPRECATED_INIT_EXTRA_FRAME_INFO */
   struct frame_extra_info *extra_info;
 
-  /* If dwarf2 unwind frame informations is used, this structure holds
-     all related unwind data.  */
-  struct context *context;
-
   /* 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
-     selected based on the presence, or otherwize, of register unwind
+     selected based on the presence, or otherwise, of register unwind
      information such as CFI.  */
   void *prologue_cache;
   const struct frame_unwind *unwind;
@@ -135,16 +134,30 @@ 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;
+static void
+fprint_field (struct ui_file *file, const char *name, int p, CORE_ADDR addr)
+{
+  if (p)
+    fprintf_unfiltered (file, "%s=0x%s", name, paddr_nz (addr));
+  else
+    fprintf_unfiltered (file, "!%s", name);
+}
 
 void
 fprint_frame_id (struct ui_file *file, struct frame_id id)
 {
-  fprintf_unfiltered (file, "{stack=0x%s,code=0x%s}",
-                     paddr_nz (id.stack_addr),
-                     paddr_nz (id.code_addr));
+  fprintf_unfiltered (file, "{");
+  fprint_field (file, "stack", id.stack_addr_p, id.stack_addr);
+  fprintf_unfiltered (file, ",");
+  fprint_field (file, "code", id.code_addr_p, id.code_addr);
+  fprintf_unfiltered (file, ",");
+  fprint_field (file, "special", id.special_addr_p, id.special_addr);
+  fprintf_unfiltered (file, "}");
 }
 
 static void
@@ -229,14 +242,12 @@ 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));
-         /* 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().  */
-         gdb_assert (fi->unwind->type != UNKNOWN_FRAME);
+         fi->unwind = frame_unwind_find_by_frame (fi->next,
+                                                  &fi->prologue_cache);
+         /* FIXME: cagney/2004-05-01: Should instead just use
+            ->unwind->type.  Unfortunately, legacy_get_prev_frame is
+            still explicitly setting the type.  Eliminate that method
+            and this field can be eliminated.  */
          fi->type = fi->unwind->type;
        }
       /* Find THIS frame's ID.  */
@@ -252,14 +263,49 @@ get_frame_id (struct frame_info *fi)
   return fi->this_id.value;
 }
 
+struct frame_id
+frame_unwind_id (struct frame_info *next_frame)
+{
+  /* Use prev_frame, and not get_prev_frame.  The latter will truncate
+     the frame chain, leading to this function unintentionally
+     returning a null_frame_id (e.g., when a caller requests the frame
+     ID of "main()"s caller.  */
+  return get_frame_id (get_prev_frame_1 (next_frame));
+}
+
 const struct frame_id null_frame_id; /* All zeros.  */
 
+struct frame_id
+frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
+                        CORE_ADDR special_addr)
+{
+  struct frame_id id = null_frame_id;
+  id.stack_addr = stack_addr;
+  id.stack_addr_p = 1;
+  id.code_addr = code_addr;
+  id.code_addr_p = 1;
+  id.special_addr = special_addr;
+  id.special_addr_p = 1;
+  return id;
+}
+
 struct frame_id
 frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr)
 {
-  struct frame_id id;
+  struct frame_id id = null_frame_id;
   id.stack_addr = stack_addr;
+  id.stack_addr_p = 1;
   id.code_addr = code_addr;
+  id.code_addr_p = 1;
+  return id;
+}
+
+struct frame_id
+frame_id_build_wild (CORE_ADDR stack_addr)
+{
+  struct frame_id id = null_frame_id;
+  id.stack_addr = stack_addr;
+  id.stack_addr_p = 1;
   return id;
 }
 
@@ -267,8 +313,8 @@ int
 frame_id_p (struct frame_id l)
 {
   int p;
-  /* The .code can be NULL but the .stack cannot.  */
-  p = (l.stack_addr != 0);
+  /* The frame is valid iff it has a valid stack address.  */
+  p = l.stack_addr_p;
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l=");
@@ -282,17 +328,24 @@ int
 frame_id_eq (struct frame_id l, struct frame_id r)
 {
   int eq;
-  if (l.stack_addr == 0 || r.stack_addr == 0)
-    /* Like a NaN, if either ID is invalid, the result is false.  */
+  if (!l.stack_addr_p || !r.stack_addr_p)
+    /* Like a NaN, if either ID is invalid, the result is false.
+       Note that a frame ID is invalid iff it is the null frame ID.  */
     eq = 0;
   else if (l.stack_addr != r.stack_addr)
     /* If .stack addresses are different, the frames are different.  */
     eq = 0;
-  else if (l.code_addr == 0 || r.code_addr == 0)
-    /* A zero code addr is a wild card, always succeed.  */
+  else if (!l.code_addr_p || !r.code_addr_p)
+    /* An invalid code addr is a wild card, always succeed.  */
+    eq = 1;
+  else if (l.code_addr != r.code_addr)
+    /* If .code addresses are different, the frames are different.  */
+    eq = 0;
+  else if (!l.special_addr_p || !r.special_addr_p)
+    /* An invalid special addr is a wild card (or unused), always succeed.  */
     eq = 1;
-  else if (l.code_addr == r.code_addr)
-    /* The .stack and .code are identical, the ID's are identical.  */
+  else if (l.special_addr == r.special_addr)
+    /* Frames are equal.  */
     eq = 1;
   else
     /* No luck.  */
@@ -312,14 +365,14 @@ int
 frame_id_inner (struct frame_id l, struct frame_id r)
 {
   int inner;
-  if (l.stack_addr == 0 || r.stack_addr == 0)
+  if (!l.stack_addr_p || !r.stack_addr_p)
     /* Like NaN, any operation involving an invalid ID always fails.  */
     inner = 0;
   else
     /* Only return non-zero when strictly inner than.  Note that, per
        comment in "frame.h", there is some fuzz here.  Frameless
        functions are not strictly inner than (same .stack but
-       different .code).  */
+       different .code and/or .special address).  */
     inner = INNER_THAN (l.stack_addr, r.stack_addr);
   if (frame_debug)
     {
@@ -353,8 +406,8 @@ frame_find_by_id (struct frame_id id)
       if (frame_id_inner (id, this))
        /* Gone to far.  */
        return NULL;
-      /* Either, we're not yet gone far enough out along the frame
-         chain (inner(this,id), or we're comparing frameless functions
+      /* Either we're not yet gone far enough out along the frame
+         chain (inner(this,id)), or we're comparing frameless functions
          (same .base, different .func, no test available).  Struggle
          on until we've definitly gone to far.  */
     }
@@ -389,9 +442,9 @@ frame_pc_unwind (struct frame_info *this_frame)
        }
       else if (this_frame->level < 0)
        {
-         /* FIXME: cagney/2003-03-06: Old code and and a sentinel
+         /* FIXME: cagney/2003-03-06: Old code and a sentinel
              frame.  Do like was always done.  Fetch the PC's value
-             direct from the global registers array (via read_pc).
+             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 ();
@@ -422,8 +475,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",
@@ -462,8 +518,8 @@ frame_pop (struct frame_info *this_frame)
     {
       /* Make a copy of all the register values unwound from this
         frame.  Save them in a scratch buffer so that there isn't a
-        race betweening trying to extract the old values from the
-        current_regcache while, at the same time writing new values
+        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 cleanup *cleanups = make_cleanup_regcache_xfree (scratch);
@@ -473,7 +529,7 @@ frame_pop (struct frame_info *this_frame)
          burst register transfer and that the sequence of register
          writes should be batched.  The pair target_prepare_to_store()
          and target_store_registers() kind of suggest this
-         functionality.  Unfortunatly, they don't implement it.  Their
+         functionality.  Unfortunately, they don't implement it.  Their
          lack of a formal definition can lead to targets writing back
          bogus values (arguably a bug in the target code mind).  */
       /* Now copy those saved registers into the current regcache.
@@ -495,9 +551,10 @@ frame_register_unwind (struct frame_info *frame, int regnum,
 
   if (frame_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "{ frame_register_unwind (frame=%d,regnum=\"%s\",...) ",
-                         frame->level, frame_map_regnum_to_name (regnum));
+      fprintf_unfiltered (gdb_stdlog, "\
+{ frame_register_unwind (frame=%d,regnum=%d(%s),...) ",
+                         frame->level, regnum,
+                         frame_map_regnum_to_name (frame, regnum));
     }
 
   /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
@@ -510,26 +567,24 @@ frame_register_unwind (struct frame_info *frame, int regnum,
 
   /* NOTE: cagney/2002-11-27: A program trying to unwind a NULL frame
      is broken.  There is always a frame.  If there, for some reason,
-     isn't, there is some pretty busted code as it should have
+     isn't a frame, there is some pretty busted code as it should have
      detected the problem before calling here.  */
   gdb_assert (frame != NULL);
 
   /* Find the unwinder.  */
   if (frame->unwind == NULL)
     {
-      frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                              get_frame_pc (frame));
-      /* 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().  */
-      gdb_assert (frame->unwind->type != UNKNOWN_FRAME);
+      frame->unwind = frame_unwind_find_by_frame (frame->next,
+                                                 &frame->prologue_cache);
+      /* FIXME: cagney/2004-05-01: Should instead just use ->unwind->type.
+        Unfortunately, legacy_get_prev_frame is still explicitly setting
+        the type.  Eliminate that method and this field can be
+        eliminated.  */
       frame->type = frame->unwind->type;
     }
 
   /* Ask this frame to unwind its register.  See comment in
-     "frame-unwind.h" for why NEXT frame and this unwind cace are
+     "frame-unwind.h" for why NEXT frame and this unwind cache are
      passed in.  */
   frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum,
                                optimizedp, lvalp, addrp, realnump, bufferp);
@@ -546,7 +601,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,62 +670,47 @@ 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)
 {
-  char buf[MAX_REGISTER_SIZE];
-  frame_unwind_register (frame, regnum, buf);
-  (*val) = extract_signed_integer (buf, REGISTER_VIRTUAL_SIZE (regnum));
+  frame_unwind_register (frame->next, regnum, buf);
 }
 
-void
-frame_unwind_unsigned_register (struct frame_info *frame, int regnum,
-                               ULONGEST *val)
+LONGEST
+frame_unwind_register_signed (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_signed_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
 }
 
-void
-frame_read_register (struct frame_info *frame, int regnum, void *buf)
+LONGEST
+get_frame_register_signed (struct frame_info *frame, int regnum)
 {
-  gdb_assert (frame != NULL && frame->next != NULL);
-  frame_unwind_register (frame->next, regnum, buf);
+  return frame_unwind_register_signed (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);
+ULONGEST
+frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
+{
+  char buf[MAX_REGISTER_SIZE];
+  frame_unwind_register (frame, regnum, buf);
+  return extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum));
+}
+
+ULONGEST
+get_frame_register_unsigned (struct frame_info *frame, int regnum)
+{
+  return frame_unwind_register_unsigned (frame->next, 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
@@ -703,40 +743,11 @@ put_frame_register (struct frame_info *frame, int regnum, const void *buf)
     }
 }
 
-void
-deprecated_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);
-}
-
 /* frame_register_read ()
 
    Find and return the value of REGNUM for the specified stack frame.
-   The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
+   The number of bytes copied is DEPRECATED_REGISTER_RAW_SIZE
+   (REGNUM).
 
    Returns 0 if the register value could not be found.  */
 
@@ -749,7 +760,7 @@ frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
   int realnum;
   frame_register (frame, regnum, &optimized, &lval, &addr, &realnum, myaddr);
 
-  /* FIXME: cagney/2002-05-15: This test, is just bogus.
+  /* FIXME: cagney/2002-05-15: This test is just bogus.
 
      It indicates that the target failed to supply a value for a
      register because it was "not available" at this time.  Problem
@@ -768,42 +779,15 @@ 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.  */
@@ -812,7 +796,7 @@ static struct frame_info *
 create_sentinel_frame (struct regcache *regcache)
 {
   struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
-  frame->type = NORMAL_FRAME;
+  frame->type = SENTINEL_FRAME;
   frame->level = -1;
   /* Explicitly initialize the sentinel frame's cache.  Provide it
      with the underlying regcache.  In the future additional
@@ -863,7 +847,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;
 }
@@ -877,7 +861,7 @@ static int
 unwind_to_current_frame (struct ui_out *ui_out, void *args)
 {
   struct frame_info *frame = get_prev_frame (args);
-  /* A sentinel frame can fail to unwind, eg, because it's PC value
+  /* A sentinel frame can fail to unwind, e.g., because its PC value
      lands in somewhere like start.  */
   if (frame == NULL)
     return 1;
@@ -919,7 +903,7 @@ get_current_frame (void)
 
 struct frame_info *deprecated_selected_frame;
 
-/* Return the selected frame.  Always non-null (unless there isn't an
+/* Return the selected frame.  Always non-NULL (unless there isn't an
    inferior sufficient for creating a frame) in which case an error is
    thrown.  */
 
@@ -936,33 +920,51 @@ 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
+  /* NOTE: cagney/2002-05-04: FI can be NULL.  This occurs when the
      frame is being invalidated.  */
-  if (selected_frame_level_changed_hook)
-    selected_frame_level_changed_hook (frame_relative_level (fi));
+  if (deprecated_selected_frame_level_changed_hook)
+    deprecated_selected_frame_level_changed_hook (frame_relative_level (fi));
 
   /* FIXME: kseitz/2002-08-28: It would be nice to call
-     selected_frame_level_changed_event right here, but due to limitations
+     selected_frame_level_changed_event() right here, but due to limitations
      in the current interfaces, we would end up flooding UIs with events
-     because select_frame is used extensively internally.
+     because select_frame() is used extensively internally.
 
      Once we have frame-parameterized frame (and frame-related) commands,
      the event notification can be moved here, since this function will only
-     be called when the users selected frame is being changed. */
+     be called when the user's selected frame is being changed. */
 
   /* Ensure that symbols for this frame are read in.  Also, determine the
      source language of this frame, and switch to it if desired.  */
   if (fi)
     {
-      s = find_pc_symtab (get_frame_pc (fi));
+      /* We retrieve the frame's symtab by using the frame PC.  However
+         we cannot use the frame PC as-is, because it usually points to
+         the instruction following the "call", which is sometimes the
+         first instruction of another function.  So we rely on
+         get_frame_address_in_block() which provides us with a PC which
+         is guaranteed to be inside the frame's code block.  */
+      s = find_pc_symtab (get_frame_address_in_block (fi));
       if (s
          && s->language != current_language->la_language
          && s->language != language_unknown
@@ -985,7 +987,7 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
                                 int *realnump, void *bufferp)
 {
   /* HACK: New code is passed the next frame and this cache.
-     Unfortunatly, old code expects this frame.  Since this is a
+     Unfortunately, old code expects this frame.  Since this is a
      backward compatibility hack, cheat by walking one level along the
      prologue chain to the frame the old code expects.
 
@@ -993,16 +995,16 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
   struct frame_info *frame = next_frame->prev;
   gdb_assert (frame != NULL);
 
-  if (get_frame_saved_regs (frame) == NULL)
+  if (deprecated_get_frame_saved_regs (frame) == NULL)
     {
-      /* If nothing's initialized the saved regs, do it now.  */
+      /* If nothing has initialized the saved regs, do it now.  */
       gdb_assert (DEPRECATED_FRAME_INIT_SAVED_REGS_P ());
       DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
-      gdb_assert (get_frame_saved_regs (frame) != NULL);
+      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)
        {
@@ -1012,10 +1014,10 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
          *addrp = 0;
          *realnump = -1;
          if (bufferp != NULL)
-           /* 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]);
+           /* NOTE: cagney/2003-05-09: In-lined store_address() with
+               it's body - store_unsigned_integer().  */
+           store_unsigned_integer (bufferp, DEPRECATED_REGISTER_RAW_SIZE (regnum),
+                                   deprecated_get_frame_saved_regs (frame)[regnum]);
        }
       else
        {
@@ -1023,7 +1025,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)
            {
@@ -1041,15 +1043,15 @@ legacy_saved_regs_prev_register (struct frame_info *next_frame,
              if (regs[regnum] == NULL)
                {
                  regs[regnum]
-                   = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum));
-                 read_memory (get_frame_saved_regs (frame)[regnum], regs[regnum],
-                              REGISTER_RAW_SIZE (regnum));
+                   = frame_obstack_zalloc (DEPRECATED_REGISTER_RAW_SIZE (regnum));
+                 read_memory (deprecated_get_frame_saved_regs (frame)[regnum], regs[regnum],
+                              DEPRECATED_REGISTER_RAW_SIZE (regnum));
                }
-             memcpy (bufferp, regs[regnum], REGISTER_RAW_SIZE (regnum));
+             memcpy (bufferp, regs[regnum], DEPRECATED_REGISTER_RAW_SIZE (regnum));
 #else
              /* Read the value in from memory.  */
-             read_memory (get_frame_saved_regs (frame)[regnum], bufferp,
-                          REGISTER_RAW_SIZE (regnum));
+             read_memory (deprecated_get_frame_saved_regs (frame)[regnum], bufferp,
+                          DEPRECATED_REGISTER_RAW_SIZE (regnum));
 #endif
            }
        }
@@ -1068,143 +1070,33 @@ legacy_saved_regs_this_id (struct frame_info *next_frame,
                           void **this_prologue_cache,
                           struct frame_id *id)
 {
-  /* legacy_get_prev_frame() always sets ->this_id.p, hence this is
-     never needed.  */
-  internal_error (__FILE__, __LINE__, "legacy_saved_regs_this_id() called");
+  /* A developer is trying to bring up a new architecture, help them
+     by providing a default unwinder that refuses to unwind anything
+     (the ID is always NULL).  In the case of legacy code,
+     legacy_get_prev_frame() will have previously set ->this_id.p, so
+     this code won't be called.  */
+  (*id) = null_frame_id;
 }
        
 const struct frame_unwind legacy_saved_regs_unwinder = {
-  /* Not really.  It gets overridden by legacy_get_prev_frame.  */
+  /* Not really.  It gets overridden by legacy_get_prev_frame().  */
   UNKNOWN_FRAME,
   legacy_saved_regs_this_id,
   legacy_saved_regs_prev_register
 };
 const struct frame_unwind *legacy_saved_regs_unwind = &legacy_saved_regs_unwinder;
 
-
-/* Function: deprecated_generic_get_saved_register
-   Find register number REGNUM relative to FRAME and put its (raw,
-   target format) contents in *RAW_BUFFER.
-
-   Set *OPTIMIZED if the variable was optimized out (and thus can't be
-   fetched).  Note that this is never set to anything other than zero
-   in this implementation.
-
-   Set *LVAL to lval_memory, lval_register, or not_lval, depending on
-   whether the value was fetched from memory, from a register, or in a
-   strange and non-modifiable way (e.g. a frame pointer which was
-   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.
-
-   The argument RAW_BUFFER must point to aligned memory.  */
-
-void
-deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
-                                      CORE_ADDR *addrp,
-                                      struct frame_info *frame, int regnum,
-                                      enum lval_type *lval)
-{
-  if (!target_has_registers)
-    error ("No registers.");
-
-  /* Normal systems don't optimize out things with register numbers.  */
-  if (optimized != NULL)
-    *optimized = 0;
-
-  if (addrp)                   /* default assumption: not found in memory */
-    *addrp = 0;
-
-  /* Note: since the current frame's registers could only have been
-     saved by frames INTERIOR TO the current frame, we skip examining
-     the current frame itself: otherwise, we would be getting the
-     previous frame's registers which were saved by the current frame.  */
-
-  if (frame != NULL)
-    {
-      for (frame = get_next_frame (frame);
-          frame_relative_level (frame) >= 0;
-          frame = get_next_frame (frame))
-       {
-         if (get_frame_type (frame) == DUMMY_FRAME)
-           {
-             if (lval)         /* found it in a CALL_DUMMY frame */
-               *lval = not_lval;
-             if (raw_buffer)
-               /* FIXME: cagney/2002-06-26: This should be via the
-                  gdbarch_register_read() method so that it, on the
-                  fly, constructs either a raw or pseudo register
-                  from the raw register cache.  */
-               regcache_raw_read
-                 (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 (lval)         /* found it saved on the stack */
-               *lval = lval_memory;
-             if (regnum == SP_REGNUM)
-               {
-                 if (raw_buffer)       /* SP register treated specially */
-                   /* NOTE: cagney/2003-05-09: In-line store_address
-                       with it's body - store_unsigned_integer.  */
-                   store_unsigned_integer (raw_buffer,
-                                           REGISTER_RAW_SIZE (regnum),
-                                           get_frame_saved_regs (frame)[regnum]);
-               }
-             else
-               {
-                 if (addrp)    /* any other register */
-                   *addrp = get_frame_saved_regs (frame)[regnum];
-                 if (raw_buffer)
-                   read_memory (get_frame_saved_regs (frame)[regnum], raw_buffer,
-                                REGISTER_RAW_SIZE (regnum));
-               }
-             return;
-           }
-       }
-    }
-
-  /* If we get thru the loop to this point, it means the register was
-     not saved in any frame.  Return the actual live-register value.  */
-
-  if (lval)                    /* found it in a live register */
-    *lval = lval_register;
-  if (addrp)
-    *addrp = REGISTER_BYTE (regnum);
-  if (raw_buffer)
-    deprecated_read_register_gen (regnum, raw_buffer);
-}
-
 /* Determine the frame's type based on its PC.  */
 
 static enum frame_type
 frame_type_from_pc (CORE_ADDR pc)
 {
-  /* FIXME: cagney/2002-11-24: Can't yet directly call
-     pc_in_dummy_frame() as some architectures don't set
-     PC_IN_CALL_DUMMY() to generic_pc_in_call_dummy() (remember the
-     latter is implemented by simply calling pc_in_dummy_frame).  */
-  if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-      && DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
+  /* NOTE: cagney/2004-05-08: Eliminating this function depends on all
+     architectures being forced to use the frame-unwind code.  */
+  if (deprecated_pc_in_call_dummy (pc))
     return DUMMY_FRAME;
   else
-    {
-      char *name;
-      find_pc_partial_function (pc, &name, NULL, NULL);
-      if (PC_IN_SIGTRAMP (pc, name))
-       return SIGTRAMP_FRAME;
-      else
-       return NORMAL_FRAME;
-    }
+    return NORMAL_FRAME;
 }
 
 /* Create an arbitrary (i.e. address specified by user) or innermost frame.
@@ -1228,7 +1120,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, &fi->prologue_cache);
   if (fi->unwind->type != UNKNOWN_FRAME)
     fi->type = fi->unwind->type;
   else
@@ -1264,10 +1156,12 @@ get_next_frame (struct frame_info *this_frame)
     return NULL;
 }
 
-struct frame_info *
-deprecated_get_next_frame_hack (struct frame_info *this_frame)
+/* Observer for the target_changed event.  */
+
+void
+frame_observer_target_changed (struct target_ops *target)
 {
-  return this_frame->next;
+  flush_cached_frames ();
 }
 
 /* Flush the entire frame cache.  */
@@ -1301,7 +1195,7 @@ reinit_frame_cache (void)
 }
 
 /* Create the previous frame using the deprecated methods
-   INIT_EXTRA_INFO, INIT_FRAME_PC and INIT_FRAME_PC_FIRST.  */
+   INIT_EXTRA_INFO, and INIT_FRAME_PC.  */
 
 static struct frame_info *
 legacy_get_prev_frame (struct frame_info *this_frame)
@@ -1318,12 +1212,12 @@ legacy_get_prev_frame (struct frame_info *this_frame)
      There is no reason to worry about memory leaks, should the
      remainder of the function fail.  The allocated memory will be
      quickly reclaimed when the frame cache is flushed, and the `we've
-     been here before' check, in get_prev_frame will stop repeated
+     been here before' check, in get_prev_frame() will stop repeated
      memory allocation calls.  */
   prev = FRAME_OBSTACK_ZALLOC (struct frame_info);
   prev->level = this_frame->level + 1;
 
-  /* Do not completly wire it in to the frame chain.  Some (bad) code
+  /* Do not completely wire it in to the frame chain.  Some (bad) code
      in INIT_FRAME_EXTRA_INFO tries to look along frame->prev to pull
      some fancy tricks (of course such code is, by definition,
      recursive).
@@ -1337,11 +1231,10 @@ legacy_get_prev_frame (struct frame_info *this_frame)
   /* NOTE: cagney/2002-11-18: Should have been correctly setting the
      frame's type here, before anything else, and not last, at the
      bottom of this function.  The various
-     DEPRECATED_INIT_EXTRA_FRAME_INFO, DEPRECATED_INIT_FRAME_PC,
-     DEPRECATED_INIT_FRAME_PC_FIRST and
+     DEPRECATED_INIT_EXTRA_FRAME_INFO, DEPRECATED_INIT_FRAME_PC, and
      DEPRECATED_FRAME_INIT_SAVED_REGS methods are full of work-arounds
      that handle the frame not being correctly set from the start.
-     Unfortunatly those same work-arounds rely on the type defaulting
+     Unfortunately those same work-arounds rely on the type defaulting
      to NORMAL_FRAME.  Ulgh!  The new frame code does not have this
      problem.  */
   prev->type = UNKNOWN_FRAME;
@@ -1359,7 +1252,7 @@ legacy_get_prev_frame (struct frame_info *this_frame)
 
         Note that the pc-unwind is intentionally performed before the
         frame chain.  This is ok since, for old targets, both
-        frame_pc_unwind (nee, DEPRECATED_FRAME_SAVED_PC) and
+        frame_pc_unwind() (nee, DEPRECATED_FRAME_SAVED_PC) and
         DEPRECATED_FRAME_CHAIN()) assume THIS_FRAME's data structures
         have already been initialized (using
         DEPRECATED_INIT_EXTRA_FRAME_INFO) and hence the call order
@@ -1387,8 +1280,8 @@ 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,
+                                                &prev->prologue_cache);
       if (prev->unwind->type == UNKNOWN_FRAME)
        prev->type = frame_type_from_pc (get_frame_pc (prev));
       else
@@ -1452,7 +1345,7 @@ legacy_get_prev_frame (struct frame_info *this_frame)
       /* FIXME: cagney/2002-01-19: This call will go away.  Instead of
         initializing extra info, all frames will use the frame_cache
         (passed to the unwind functions) to store additional frame
-        info.  Unfortunatly legacy targets can't use
+        info.  Unfortunately legacy targets can't use
         legacy_get_prev_frame() to unwind the sentinel frame and,
         consequently, are forced to take this code path and rely on
         the below call to DEPRECATED_INIT_EXTRA_FRAME_INFO to
@@ -1489,11 +1382,12 @@ legacy_get_prev_frame (struct frame_info *this_frame)
      frame.  This macro will set FROMLEAF if THIS_FRAME is a frameless
      function invocation.  */
   if (this_frame->level == 0)
-    /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
+    /* FIXME: 2002-11-09: Frameless functions can occur anywhere in
        the frame chain, not just the inner most frame!  The generic,
        per-architecture, frame code should handle this and the below
        should simply be removed.  */
-    fromleaf = FRAMELESS_FUNCTION_INVOCATION (this_frame);
+    fromleaf = (DEPRECATED_FRAMELESS_FUNCTION_INVOCATION_P ()
+               && DEPRECATED_FRAMELESS_FUNCTION_INVOCATION (this_frame));
   else
     fromleaf = 0;
 
@@ -1502,7 +1396,7 @@ legacy_get_prev_frame (struct frame_info *this_frame)
        architecture frame-pointer register!) of the caller is the same
        as the callee.  */
     /* FIXME: 2002-11-09: There isn't any reason to special case this
-       edge condition.  Instead the per-architecture code should hande
+       edge condition.  Instead the per-architecture code should handle
        it locally.  */
     /* FIXME: cagney/2003-06-16: This returns the inner most stack
        address for the previous frame, that, however, is wrong.  It
@@ -1536,13 +1430,12 @@ legacy_get_prev_frame (struct frame_info *this_frame)
              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_pc (current_gdbarch,
-                                                 frame_pc_unwind (this_frame));
-         /* 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->unwind = frame_unwind_find_by_frame (this_frame,
+                                                    &prev->prologue_cache);
+         /* FIXME: cagney/2004-05-01: Should instead just use
+            ->unwind->type.  Unfortunately, legacy_get_prev_frame is
+            still explicitly setting the type.  Eliminate that method
+            and this field can be eliminated.  */
          prev->type = prev->unwind->type;
          /* Find PREV frame's ID.  */
          prev->unwind->this_id (this_frame,
@@ -1595,10 +1488,6 @@ legacy_get_prev_frame (struct frame_info *this_frame)
      machines appear to require DEPRECATED_INIT_EXTRA_FRAME_INFO
      before they can do DEPRECATED_INIT_FRAME_PC.  Phoo.
 
-     We shouldn't need DEPRECATED_INIT_FRAME_PC_FIRST to add more
-     complication to an already overcomplicated part of GDB.
-     gnu@cygnus.com, 15Sep92.
-
      Assuming that some machines need DEPRECATED_INIT_FRAME_PC after
      DEPRECATED_INIT_EXTRA_FRAME_INFO, one possible scheme:
 
@@ -1632,10 +1521,10 @@ legacy_get_prev_frame (struct frame_info *this_frame)
      reason for things to be this complicated.
 
      The trick is to assume that there is always a frame.  Instead of
-     special casing the inner-most frame, create fake frame
+     special casing the inner-most frame, create fake frame
      (containing the hardware registers) that is inner to the
      user-visible inner-most frame (...) and then unwind from that.
-     That way architecture code can use use the standard
+     That way architecture code can use the standard
      frame_XX_unwind() functions and not differentiate between the
      inner most and any other case.
 
@@ -1650,21 +1539,16 @@ legacy_get_prev_frame (struct frame_info *this_frame)
      FRAME_SAVED_PC(), and FRAME_SAVED_PC() computes the PC but
      without first needing the frame!  Instead of the convolution
      below, we could have simply called FRAME_SAVED_PC() and been done
-     with it!  Note that FRAME_SAVED_PC() is being superseed by
+     with it!  Note that FRAME_SAVED_PC() is being superseded by
      frame_pc_unwind() and that function does have somewhere to cache
      that PC value.  */
 
-  if (DEPRECATED_INIT_FRAME_PC_FIRST_P ())
-    deprecated_update_frame_pc_hack (prev,
-                                    DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf,
-                                                                    prev));
-
   if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
     DEPRECATED_INIT_EXTRA_FRAME_INFO (fromleaf, prev);
 
   /* This entry is in the frame queue now, which is good since
      FRAME_SAVED_PC may use that queue to figure out its value (see
-     tm-sparc.h).  We want the pc saved in the inferior frame. */
+     tm-sparc.h).  We want the PC saved in the inferior frame. */
   if (DEPRECATED_INIT_FRAME_PC_P ())
     deprecated_update_frame_pc_hack (prev,
                                     DEPRECATED_INIT_FRAME_PC (fromleaf,
@@ -1698,10 +1582,10 @@ legacy_get_prev_frame (struct frame_info *this_frame)
      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_pc (current_gdbarch,
-                                           get_frame_pc (prev));
+    prev->unwind = frame_unwind_find_by_frame (prev->next,
+                                              &prev->prologue_cache);
 
-  /* If the unwinder provides a frame type, use it.  Otherwize
+  /* If the unwinder provides a frame type, use it.  Otherwise
      continue on to that heuristic mess.  */
   if (prev->unwind->type != UNKNOWN_FRAME)
     {
@@ -1720,37 +1604,15 @@ legacy_get_prev_frame (struct frame_info *this_frame)
     }
 
   /* NOTE: cagney/2002-11-18: The code segments, found in
-     create_new_frame and get_prev_frame(), that initializes the
-     frames type is subtly different.  The latter only updates ->type
+     create_new_frame() and get_prev_frame(), that initialize the
+     frame's type is subtly different.  The latter only updates ->type
      when it encounters a SIGTRAMP_FRAME or DUMMY_FRAME.  This stops
      get_prev_frame() overriding the frame's type when the INIT code
      has previously set it.  This is really somewhat bogus.  The
      initialization, as seen in create_new_frame(), should occur
      before the INIT function has been called.  */
-  if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-      && (DEPRECATED_PC_IN_CALL_DUMMY_P ()
-         ? DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (prev), 0, 0)
-         : pc_in_dummy_frame (get_frame_pc (prev))))
+  if (deprecated_pc_in_call_dummy (get_frame_pc (prev)))
     prev->type = DUMMY_FRAME;
-  else
-    {
-      /* FIXME: cagney/2002-11-10: This should be moved to before the
-        INIT code above so that the INIT code knows what the frame's
-        type is (in fact, for a [generic] dummy-frame, the type can
-        be set and then the entire initialization can be skipped.
-        Unforunatly, its the INIT code that sets the PC (Hmm, catch
-        22).  */
-      char *name;
-      find_pc_partial_function (get_frame_pc (prev), &name, NULL, NULL);
-      if (PC_IN_SIGTRAMP (get_frame_pc (prev), name))
-       prev->type = SIGTRAMP_FRAME;
-      /* FIXME: cagney/2002-11-11: Leave prev->type alone.  Some
-         architectures are forcing the frame's type in INIT so we
-         don't want to override it here.  Remember, NORMAL_FRAME == 0,
-         so it all works (just :-/).  Once this initialization is
-         moved to the start of this function, all this nastness will
-         go away.  */
-    }
 
   if (prev->type == NORMAL_FRAME)
     prev->this_id.value.code_addr
@@ -1766,18 +1628,23 @@ legacy_get_prev_frame (struct frame_info *this_frame)
   return prev;
 }
 
-/* Return a structure containing various interesting information
-   about the frame that called THIS_FRAME.  Returns NULL
-   if there is no such frame.  */
+/* Return a "struct frame_info" corresponding to the frame that called
+   THIS_FRAME.  Returns NULL if there is no such frame.
 
-struct frame_info *
-get_prev_frame (struct frame_info *this_frame)
+   Unlike get_prev_frame, this function always tries to unwind the
+   frame.  */
+
+static struct frame_info *
+get_prev_frame_1 (struct frame_info *this_frame)
 {
   struct frame_info *prev_frame;
+  struct frame_id this_id;
+
+  gdb_assert (this_frame != NULL);
 
   if (frame_debug)
     {
-      fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame=");
+      fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_1 (this_frame=");
       if (this_frame != NULL)
        fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level);
       else
@@ -1785,59 +1652,6 @@ get_prev_frame (struct frame_info *this_frame)
       fprintf_unfiltered (gdb_stdlog, ") ");
     }
 
-  /* Return the inner-most frame, when the caller passes in NULL.  */
-  /* NOTE: cagney/2002-11-09: Not sure how this would happen.  The
-     caller should have previously obtained a valid frame using
-     get_selected_frame() and then called this code - only possibility
-     I can think of is code behaving badly.
-
-     NOTE: cagney/2003-01-10: Talk about code behaving badly.  Check
-     block_innermost_frame().  It does the sequence: frame = NULL;
-     while (1) { frame = get_prev_frame (frame); .... }.  Ulgh!  Why
-     it couldn't be written better, I don't know.
-
-     NOTE: cagney/2003-01-11: I suspect what is happening is
-     block_innermost_frame() is, when the target has no state
-     (registers, memory, ...), still calling this function.  The
-     assumption being that this function will return NULL indicating
-     that a frame isn't possible, rather than checking that the target
-     has state and then calling get_current_frame() and
-     get_prev_frame().  This is a guess mind.  */
-  if (this_frame == NULL)
-    {
-      /* NOTE: cagney/2002-11-09: There was a code segment here that
-        would error out when CURRENT_FRAME was NULL.  The comment
-        that went with it made the claim ...
-
-        ``This screws value_of_variable, which just wants a nice
-        clean NULL return from block_innermost_frame if there are no
-        frames.  I don't think I've ever seen this message happen
-        otherwise.  And returning NULL here is a perfectly legitimate
-        thing to do.''
-
-         Per the above, this code shouldn't even be called with a NULL
-         THIS_FRAME.  */
-      return current_frame;
-    }
-
-  /* There is always a frame.  If this assertion fails, suspect that
-     something should be calling get_selected_frame() or
-     get_current_frame().  */
-  gdb_assert (this_frame != NULL);
-
-  if (this_frame->level >= 0
-      && !backtrace_below_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
-       previously unwound.  That way if the user later decides to
-       allow unwinds past main(), that just happens.  */
-    {
-      if (frame_debug)
-       fprintf_unfiltered (gdb_stdlog, "-> NULL // inside main func }\n");
-      return NULL;
-    }
-
   /* Only try to do the unwind once.  */
   if (this_frame->prev_p)
     {
@@ -1851,62 +1665,8 @@ 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.
-     Sentinel frames should always be allowed to unwind.  */
-  /* NOTE: drow/2002-12-25: should there be a way to disable this
-     check?  It assumes a single small entry file, and the way some
-     debug readers (e.g.  dbxread) figure out which object is the
-     entry file is somewhat hokey.  */
-  /* 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.  */
-  if (0
-      && 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;
-    }
-
   /* If any of the old frame initialization methods are around, use
-     the legacy get_prev_frame method.  */
+     the legacy get_prev_frame() method.  */
   if (legacy_frame_p (current_gdbarch))
     {
       prev_frame = legacy_get_prev_frame (this_frame);
@@ -1916,7 +1676,8 @@ get_prev_frame (struct frame_info *this_frame)
   /* 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
      the sentinel frame.  */
-  if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame)))
+  this_id = get_frame_id (this_frame);
+  if (this_frame->level >= 0 && !frame_id_p (this_id))
     {
       if (frame_debug)
        {
@@ -1928,25 +1689,20 @@ 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 a frame unwind goes backwards.
+     Exclude signal trampolines (due to sigaltstack the frame ID can
+     go backwards) and sentinel frames (the test is meaningless).  */
+  if (this_frame->next->level >= 0
+      && this_frame->next->type != SIGTRAMP_FRAME
+      && frame_id_inner (this_id, get_frame_id (this_frame->next)))
+    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_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
-      && frame_id_eq (get_frame_id (this_frame),
-                     get_frame_id (this_frame->next)))
-    error ("This frame identical to next frame (corrupt stack?)");
+      && frame_id_eq (this_id, get_frame_id (this_frame->next)))
+    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
@@ -1961,37 +1717,6 @@ get_prev_frame (struct frame_info *this_frame)
   prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
   prev_frame->level = this_frame->level + 1;
 
-  /* Try to unwind the PC.  If that doesn't work, assume we've reached
-     the oldest frame and simply return.  Is there a better sentinal
-     value?  The unwound PC value is then used to initialize the new
-     previous frame's type.
-
-     Note that the pc-unwind is intentionally performed before the
-     frame chain.  This is ok since, for old targets, both
-     frame_pc_unwind (nee, FRAME_SAVED_PC) and
-     DEPRECATED_FRAME_CHAIN()) assume THIS_FRAME's data structures
-     have already been initialized (using
-     DEPRECATED_INIT_EXTRA_FRAME_INFO) and hence the call order
-     doesn't matter.
-
-     By unwinding the PC first, it becomes possible to, in the case of
-     a dummy frame, avoid also unwinding the frame ID.  This is
-     because (well ignoring the PPC) a dummy frame can be located
-     using THIS_FRAME's frame ID.  */
-
-  if (frame_pc_unwind (this_frame) == 0)
-    {
-      /* The allocated PREV_FRAME will be reclaimed when the frame
-        obstack is next purged.  */
-      if (frame_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "-> ");
-         fprint_frame (gdb_stdlog, NULL);
-         fprintf_unfiltered (gdb_stdlog, " // unwound PC zero }\n");
-       }
-      return NULL;
-    }
-
   /* Don't yet compute ->unwind (and hence ->type).  It is computed
      on-demand in get_frame_type, frame_register_unwind, and
      get_frame_id.  */
@@ -2025,6 +1750,136 @@ get_prev_frame (struct frame_info *this_frame)
   return prev_frame;
 }
 
+/* Debug routine to print a NULL frame being returned.  */
+
+static void
+frame_debug_got_null_frame (struct ui_file *file,
+                           struct frame_info *this_frame,
+                           const char *reason)
+{
+  if (frame_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame=");
+      if (this_frame != NULL)
+       fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level);
+      else
+       fprintf_unfiltered (gdb_stdlog, "<NULL>");
+      fprintf_unfiltered (gdb_stdlog, ") -> // %s}\n", reason);
+    }
+}
+
+/* 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
+   condition that should terminate the frame chain (e.g., as unwinding
+   past main()).
+
+   This function should not contain target-dependent tests, such as
+   checking whether the program-counter is zero.  */
+
+struct frame_info *
+get_prev_frame (struct frame_info *this_frame)
+{
+  struct frame_info *prev_frame;
+
+  /* Return the inner-most frame, when the caller passes in NULL.  */
+  /* NOTE: cagney/2002-11-09: Not sure how this would happen.  The
+     caller should have previously obtained a valid frame using
+     get_selected_frame() and then called this code - only possibility
+     I can think of is code behaving badly.
+
+     NOTE: cagney/2003-01-10: Talk about code behaving badly.  Check
+     block_innermost_frame().  It does the sequence: frame = NULL;
+     while (1) { frame = get_prev_frame (frame); .... }.  Ulgh!  Why
+     it couldn't be written better, I don't know.
+
+     NOTE: cagney/2003-01-11: I suspect what is happening in
+     block_innermost_frame() is, when the target has no state
+     (registers, memory, ...), it is still calling this function.  The
+     assumption being that this function will return NULL indicating
+     that a frame isn't possible, rather than checking that the target
+     has state and then calling get_current_frame() and
+     get_prev_frame().  This is a guess mind.  */
+  if (this_frame == NULL)
+    {
+      /* NOTE: cagney/2002-11-09: There was a code segment here that
+        would error out when CURRENT_FRAME was NULL.  The comment
+        that went with it made the claim ...
+
+        ``This screws value_of_variable, which just wants a nice
+        clean NULL return from block_innermost_frame if there are no
+        frames.  I don't think I've ever seen this message happen
+        otherwise.  And returning NULL here is a perfectly legitimate
+        thing to do.''
+
+         Per the above, this code shouldn't even be called with a NULL
+         THIS_FRAME.  */
+      frame_debug_got_null_frame (gdb_stdlog, this_frame, "this_frame NULL");
+      return current_frame;
+    }
+
+  /* There is always a frame.  If this assertion fails, suspect that
+     something should be calling get_selected_frame() or
+     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().  */
+  if (this_frame->level >= 0
+      && !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.  */
+    {
+      frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside main func");
+      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 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
+     backtrace in weird and wonderful ways somewhere inside the entry
+     file.  Suspect that tests for inside the entry file/func 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 (this_frame))
+    {
+      frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry func");
+      return NULL;
+    }
+
+  return get_prev_frame_1 (this_frame);
+}
+
 CORE_ADDR
 get_frame_pc (struct frame_info *frame)
 {
@@ -2032,6 +1887,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)
 {
@@ -2071,7 +1953,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)
@@ -2087,7 +1969,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)
@@ -2105,7 +1987,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)
@@ -2130,28 +2012,20 @@ frame_relative_level (struct frame_info *fi)
 enum frame_type
 get_frame_type (struct frame_info *frame)
 {
-  /* Some targets still don't use [generic] dummy frames.  Catch them
-     here.  */
-  if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-      && deprecated_frame_in_dummy (frame))
-    return DUMMY_FRAME;
-
   /* Some legacy code, e.g, mips_init_extra_frame_info() wants
      to determine the frame's type prior to it being completely
      initialized.  Don't attempt to lazily initialize ->unwind for
      legacy code.  It will be initialized in legacy_get_prev_frame().  */
   if (frame->unwind == NULL && !legacy_frame_p (current_gdbarch))
     {
-      /* Initialize the frame's unwinder because it is that which
+      /* Initialize the frame's unwinder because that's what
          provides the frame's type.  */
-      frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
-                                              get_frame_pc (frame));
-      /* 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().  */
-      gdb_assert (frame->unwind->type != UNKNOWN_FRAME);
+      frame->unwind = frame_unwind_find_by_frame (frame->next, 
+                                                 &frame->prologue_cache);
+      /* FIXME: cagney/2004-05-01: Should instead just use
+        ->unwind->type.  Unfortunately, legacy_get_prev_frame is
+        still explicitly setting the type.  Eliminate that method and
+        this field can be eliminated.  */
       frame->type = frame->unwind->type;
     }
   if (frame->type == UNKNOWN_FRAME)
@@ -2160,13 +2034,6 @@ get_frame_type (struct frame_info *frame)
     return frame->type;
 }
 
-void
-deprecated_set_frame_type (struct frame_info *frame, enum frame_type type)
-{
-  /* Arrrg!  See comment in "frame.h".  */
-  frame->type = type;
-}
-
 struct frame_extra_info *
 get_frame_extra_info (struct frame_info *fi)
 {
@@ -2188,7 +2055,7 @@ deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
                        "{ deprecated_update_frame_pc_hack (frame=%d,pc=0x%s) }\n",
                        frame->level, paddr_nz (pc));
   /* NOTE: cagney/2003-03-11: Some architectures (e.g., Arm) are
-     maintaining a locally allocated frame object.  Since such frame's
+     maintaining a locally allocated frame object.  Since such frames
      are not in the frame chain, it isn't possible to assume that the
      frame has a next.  Sigh.  */
   if (frame->next != NULL)
@@ -2212,60 +2079,13 @@ deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
   frame->this_id.value.stack_addr = base;
 }
 
-void
-deprecated_set_frame_saved_regs_hack (struct frame_info *frame,
-                                     CORE_ADDR *saved_regs)
-{
-  frame->saved_regs = saved_regs;
-}
-
-void
-deprecated_set_frame_extra_info_hack (struct frame_info *frame,
-                                     struct frame_extra_info *extra_info)
-{
-  frame->extra_info = extra_info;
-}
-
-void
-deprecated_set_frame_next_hack (struct frame_info *fi,
-                               struct frame_info *next)
-{
-  fi->next = next;
-}
-
-void
-deprecated_set_frame_prev_hack (struct frame_info *fi,
-                               struct frame_info *prev)
-{
-  fi->prev = prev;
-}
-
-struct context *
-deprecated_get_frame_context (struct frame_info *fi)
-{
-  return fi->context;
-}
-
-void
-deprecated_set_frame_context (struct frame_info *fi,
-                             struct context *context)
-{
-  fi->context = context;
-}
-
-struct frame_info *
-deprecated_frame_xmalloc (void)
-{
-  struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
-  frame->this_id.p = 1;
-  return frame;
-}
-
 struct frame_info *
 deprecated_frame_xmalloc_with_cleanup (long sizeof_saved_regs,
                                       long sizeof_extra_info)
 {
-  struct frame_info *frame = deprecated_frame_xmalloc ();
+  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)
     {
@@ -2303,6 +2123,14 @@ get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr,
   return read_memory_unsigned_integer (addr, len);
 }
 
+int
+safe_frame_unwind_memory (struct frame_info *this_frame,
+                         CORE_ADDR addr, void *buf, int len)
+{
+  /* NOTE: deprecated_read_memory_nobpt returns zero on success!  */
+  return !deprecated_read_memory_nobpt (addr, buf, len);
+}
+
 /* Architecture method.  */
 
 struct gdbarch *
@@ -2322,12 +2150,12 @@ get_frame_sp (struct frame_info *this_frame)
 CORE_ADDR
 frame_sp_unwind (struct frame_info *next_frame)
 {
-  /* Normality, an architecture that provides a way of obtaining any
+  /* 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.  */
+     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
@@ -2345,27 +2173,66 @@ frame_sp_unwind (struct frame_info *next_frame)
 int
 legacy_frame_p (struct gdbarch *current_gdbarch)
 {
-  return (DEPRECATED_INIT_FRAME_PC_P ()
-         || DEPRECATED_INIT_FRAME_PC_FIRST_P ()
-         || DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()
-         || DEPRECATED_FRAME_CHAIN_P ()
-         || !gdbarch_unwind_dummy_id_p (current_gdbarch));
+  if (DEPRECATED_INIT_FRAME_PC_P ()
+      || DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()
+      || DEPRECATED_FRAME_CHAIN_P ())
+    /* No question, it's a legacy frame.  */
+    return 1;
+  if (gdbarch_unwind_dummy_id_p (current_gdbarch))
+    /* No question, it's not a legacy frame (provided none of the
+       deprecated methods checked above are present that is).  */
+    return 0;
+  if (DEPRECATED_TARGET_READ_FP_P ()
+      || DEPRECATED_FP_REGNUM >= 0)
+    /* Assume it's legacy.  If you're trying to convert a legacy frame
+       target to the new mechanism, get rid of these.  legacy
+       get_prev_frame() requires these when unwind_frame_id() isn't
+       available.  */
+    return 1;
+  /* Default to assuming that it's brand new code, and hence not
+     legacy.  Force it down the non-legacy path so that the new code
+     uses the new frame mechanism from day one.  Dummy frames won't
+     work very well but we can live with that.  */
+  return 0;
 }
 
 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
 _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, "\
+  observer_attach_target_changed (frame_observer_target_changed);
+
+  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\
@@ -2374,12 +2241,22 @@ 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,
-                                 &frame_debug, "Set frame debugging.\n\
+  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);
+     &showdebuglist);
 }
This page took 0.046728 seconds and 4 git commands to generate.