OSDN Git Service

2009-10-23 Tristan Gingold <gingold@adacore.com>
[pf3gnuchains/pf3gnuchains3x.git] / gdb / frame.c
index dd3e341..02a9bd1 100644 (file)
@@ -1,7 +1,7 @@
 /* Cache and manage frames for GDB, the GNU debugger.
 
    Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001,
-   2002, 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "objfiles.h"
 #include "exceptions.h"
 #include "gdbthread.h"
+#include "block.h"
+#include "inline-frame.h"
 
 static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
+static struct frame_info *get_prev_frame_raw (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
@@ -67,6 +70,12 @@ struct frame_info
      moment leave this as speculation.  */
   int level;
 
+  /* The frame's program space.  */
+  struct program_space *pspace;
+
+  /* The frame's address space.  */
+  struct address_space *aspace;
+
   /* 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
@@ -75,6 +84,13 @@ struct frame_info
   void *prologue_cache;
   const struct frame_unwind *unwind;
 
+  /* Cached copy of the previous frame's architecture.  */
+  struct
+  {
+    int p;
+    struct gdbarch *arch;
+  } prev_arch;
+
   /* Cached copy of the previous frame's resume address.  */
   struct {
     int p;
@@ -112,6 +128,40 @@ struct frame_info
   enum unwind_stop_reason stop_reason;
 };
 
+/* A frame stash used to speed up frame lookups.  */
+
+/* We currently only stash one frame at a time, as this seems to be
+   sufficient for now.  */
+static struct frame_info *frame_stash = NULL;
+
+/* Add the following FRAME to the frame stash.  */
+
+static void
+frame_stash_add (struct frame_info *frame)
+{
+  frame_stash = frame;
+}
+
+/* Search the frame stash for an entry with the given frame ID.
+   If found, return that frame.  Otherwise return NULL.  */
+
+static struct frame_info *
+frame_stash_find (struct frame_id id)
+{
+  if (frame_stash && frame_id_eq (frame_stash->this_id.value, id))
+    return frame_stash;
+
+  return NULL;
+}
+
+/* Invalidate the frame stash by removing all entries in it.  */
+
+static void
+frame_stash_invalidate (void)
+{
+  frame_stash = NULL;
+}
+
 /* Flag to control debugging.  */
 
 int frame_debug;
@@ -159,7 +209,7 @@ 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));
+    fprintf_unfiltered (file, "%s=%s", name, hex_string (addr));
   else
     fprintf_unfiltered (file, "!%s", name);
 }
@@ -173,6 +223,8 @@ fprint_frame_id (struct ui_file *file, struct frame_id id)
   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);
+  if (id.inline_depth)
+    fprintf_unfiltered (file, ",inlined=%d", id.inline_depth);
   fprintf_unfiltered (file, "}");
 }
 
@@ -187,9 +239,18 @@ fprint_frame_type (struct ui_file *file, enum frame_type type)
     case DUMMY_FRAME:
       fprintf_unfiltered (file, "DUMMY_FRAME");
       return;
+    case INLINE_FRAME:
+      fprintf_unfiltered (file, "INLINE_FRAME");
+      return;
+    case SENTINEL_FRAME:
+      fprintf_unfiltered (file, "SENTINEL_FRAME");
+      return;
     case SIGTRAMP_FRAME:
       fprintf_unfiltered (file, "SIGTRAMP_FRAME");
       return;
+    case ARCH_FRAME:
+      fprintf_unfiltered (file, "ARCH_FRAME");
+      return;
     default:
       fprintf_unfiltered (file, "<unknown type>");
       return;
@@ -221,7 +282,7 @@ fprint_frame (struct ui_file *file, struct frame_info *fi)
   fprintf_unfiltered (file, ",");
   fprintf_unfiltered (file, "pc=");
   if (fi->next != NULL && fi->next->prev_pc.p)
-    fprintf_unfiltered (file, "0x%s", paddr_nz (fi->next->prev_pc.value));
+    fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value));
   else
     fprintf_unfiltered (file, "<unknown>");
   fprintf_unfiltered (file, ",");
@@ -233,12 +294,24 @@ fprint_frame (struct ui_file *file, struct frame_info *fi)
   fprintf_unfiltered (file, ",");
   fprintf_unfiltered (file, "func=");
   if (fi->next != NULL && fi->next->prev_func.p)
-    fprintf_unfiltered (file, "0x%s", paddr_nz (fi->next->prev_func.addr));
+    fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_func.addr));
   else
     fprintf_unfiltered (file, "<unknown>");
   fprintf_unfiltered (file, "}");
 }
 
+/* Given FRAME, return the enclosing normal frame for inlined
+   function frames.  Otherwise return the original frame.  */
+
+static struct frame_info *
+skip_inlined_frames (struct frame_info *frame)
+{
+  while (get_frame_type (frame) == INLINE_FRAME)
+    frame = get_prev_frame (frame);
+
+  return frame;
+}
+
 /* Return a frame uniq ID that can be used to, later, re-find the
    frame.  */
 
@@ -246,9 +319,8 @@ struct frame_id
 get_frame_id (struct frame_info *fi)
 {
   if (fi == NULL)
-    {
-      return null_frame_id;
-    }
+    return null_frame_id;
+
   if (!fi->this_id.p)
     {
       if (frame_debug)
@@ -258,7 +330,10 @@ get_frame_id (struct frame_info *fi)
       if (fi->unwind == NULL)
        fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
       /* Find THIS frame's ID.  */
+      /* Default to outermost if no ID is found.  */
+      fi->this_id.value = outer_frame_id;
       fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value);
+      gdb_assert (frame_id_p (fi->this_id.value));
       fi->this_id.p = 1;
       if (frame_debug)
        {
@@ -267,20 +342,38 @@ get_frame_id (struct frame_info *fi)
          fprintf_unfiltered (gdb_stdlog, " }\n");
        }
     }
+
+  frame_stash_add (fi);
+
   return fi->this_id.value;
 }
 
 struct frame_id
-frame_unwind_id (struct frame_info *next_frame)
+get_stack_frame_id (struct frame_info *next_frame)
 {
-  /* Use prev_frame, and not get_prev_frame.  The latter will truncate
+  return get_frame_id (skip_inlined_frames (next_frame));
+}
+
+struct frame_id
+frame_unwind_caller_id (struct frame_info *next_frame)
+{
+  struct frame_info *this_frame;
+
+  /* Use get_prev_frame_1, 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));
+
+  next_frame = skip_inlined_frames (next_frame);
+  this_frame = get_prev_frame_1 (next_frame);
+  if (this_frame)
+    return get_frame_id (skip_inlined_frames (this_frame));
+  else
+    return null_frame_id;
 }
 
 const struct frame_id null_frame_id; /* All zeros.  */
+const struct frame_id outer_frame_id = { 0, 0, 0, 0, 0, 1, 0 };
 
 struct frame_id
 frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
@@ -322,6 +415,9 @@ frame_id_p (struct frame_id l)
   int p;
   /* The frame is valid iff it has a valid stack address.  */
   p = l.stack_addr_p;
+  /* outer_frame_id is also valid.  */
+  if (!p && memcmp (&l, &outer_frame_id, sizeof (l)) == 0)
+    p = 1;
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l=");
@@ -332,31 +428,48 @@ frame_id_p (struct frame_id l)
 }
 
 int
+frame_id_inlined_p (struct frame_id l)
+{
+  if (!frame_id_p (l))
+    return 0;
+
+  return (l.inline_depth != 0);
+}
+
+int
 frame_id_eq (struct frame_id l, struct frame_id r)
 {
   int eq;
-  if (!l.stack_addr_p || !r.stack_addr_p)
+  if (!l.stack_addr_p && l.special_addr_p && !r.stack_addr_p && r.special_addr_p)
+    /* The outermost frame marker is equal to itself.  This is the
+       dodgy thing about outer_frame_id, since between execution steps
+       we might step into another function - from which we can't
+       unwind either.  More thought required to get rid of
+       outer_frame_id.  */
+    eq = 1;
+  else 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_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.  */
+  else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr)
+    /* An invalid code addr is a wild card.  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.special_addr == r.special_addr)
+  else if (l.special_addr_p && r.special_addr_p
+          && l.special_addr != r.special_addr)
+    /* An invalid special addr is a wild card (or unused).  Otherwise
+       if special addresses are different, the frames are different.  */
+    eq = 0;
+  else if (l.inline_depth != r.inline_depth)
+    /* If inline depths are different, the frames must be different.  */
+    eq = 0;
+  else
     /* Frames are equal.  */
     eq = 1;
-  else
-    /* No luck.  */
-    eq = 0;
+
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l=");
@@ -376,23 +489,29 @@ frame_id_eq (struct frame_id l, struct frame_id r)
    to sigaltstack).
 
    However, it can be used as safety net to discover invalid frame
-   IDs in certain circumstances.
+   IDs in certain circumstances. Assuming that NEXT is the immediate
+   inner frame to THIS and that NEXT and THIS are both NORMAL frames:
 
-   * If frame NEXT is the immediate inner frame to THIS, and NEXT
-     is a NORMAL frame, then the stack address of NEXT must be
-     inner-than-or-equal to the stack address of THIS.
+   * The stack address of NEXT must be inner-than-or-equal to the stack
+     address of THIS.
 
      Therefore, if frame_id_inner (THIS, NEXT) holds, some unwind
      error has occurred.
 
-   * If frame NEXT is the immediate inner frame to THIS, and NEXT
-     is a NORMAL frame, and NEXT and THIS have different stack
-     addresses, no other frame in the frame chain may have a stack
-     address in between.
+   * If NEXT and THIS have different stack addresses, no other frame
+     in the frame chain may have a stack address in between.
 
      Therefore, if frame_id_inner (TEST, THIS) holds, but
      frame_id_inner (TEST, NEXT) does not hold, TEST cannot refer
-     to a valid frame in the frame chain.   */
+     to a valid frame in the frame chain.
+
+   The sanity checks above cannot be performed when a SIGTRAMP frame
+   is involved, because signal handlers might be executed on a different
+   stack than the stack used by the routine that caused the signal
+   to be raised.  This can happen for instance when a thread exceeds
+   its maximum stack size. In this case, certain compilers implement
+   a stack overflow strategy that cause the handler to be run on a
+   different stack.  */
 
 static int
 frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r)
@@ -401,6 +520,29 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r)
   if (!l.stack_addr_p || !r.stack_addr_p)
     /* Like NaN, any operation involving an invalid ID always fails.  */
     inner = 0;
+  else if (l.inline_depth > r.inline_depth
+          && l.stack_addr == r.stack_addr
+          && l.code_addr_p == r.code_addr_p
+          && l.special_addr_p == r.special_addr_p
+          && l.special_addr == r.special_addr)
+    {
+      /* Same function, different inlined functions.  */
+      struct block *lb, *rb;
+
+      gdb_assert (l.code_addr_p && r.code_addr_p);
+
+      lb = block_for_pc (l.code_addr);
+      rb = block_for_pc (r.code_addr);
+
+      if (lb == NULL || rb == NULL)
+       /* Something's gone wrong.  */
+       inner = 0;
+      else
+       /* This will return true if LB and RB are the same block, or
+          if the block with the smaller depth lexically encloses the
+          block with the greater depth.  */
+       inner = contained_in (lb, rb);
+    }
   else
     /* Only return non-zero when strictly inner than.  Note that, per
        comment in "frame.h", there is some fuzz here.  Frameless
@@ -428,6 +570,18 @@ frame_find_by_id (struct frame_id id)
   if (!frame_id_p (id))
     return NULL;
 
+  /* Try using the frame stash first.  Finding it there removes the need
+     to perform the search by looping over all frames, which can be very
+     CPU-intensive if the number of frames is very high (the loop is O(n)
+     and get_prev_frame performs a series of checks that are relatively
+     expensive).  This optimization is particularly useful when this function
+     is called from another function (such as value_fetch_lazy, case
+     VALUE_LVAL (val) == lval_register) which already loops over all frames,
+     making the overall behavior O(n^2).  */
+  frame = frame_stash_find (id);
+  if (frame)
+    return frame;
+
   for (frame = get_current_frame (); ; frame = prev_frame)
     {
       struct frame_id this = get_frame_id (frame);
@@ -453,13 +607,13 @@ frame_find_by_id (struct frame_id id)
   return NULL;
 }
 
-CORE_ADDR
-frame_pc_unwind (struct frame_info *this_frame)
+static CORE_ADDR
+frame_unwind_pc (struct frame_info *this_frame)
 {
   if (!this_frame->prev_pc.p)
     {
       CORE_ADDR pc;
-      if (gdbarch_unwind_pc_p (get_frame_arch (this_frame)))
+      if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame)))
        {
          /* The right way.  The `pure' way.  The one true way.  This
             method depends solely on the register-unwind code to
@@ -477,7 +631,7 @@ frame_pc_unwind (struct frame_info *this_frame)
             frame.  This is all in stark contrast to the old
             FRAME_SAVED_PC which would try to directly handle all the
             different ways that a PC could be unwound.  */
-         pc = gdbarch_unwind_pc (get_frame_arch (this_frame), this_frame);
+         pc = gdbarch_unwind_pc (frame_unwind_arch (this_frame), this_frame);
        }
       else
        internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
@@ -485,14 +639,20 @@ frame_pc_unwind (struct frame_info *this_frame)
       this_frame->prev_pc.p = 1;
       if (frame_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "{ frame_pc_unwind (this_frame=%d) -> 0x%s }\n",
+                           "{ frame_unwind_caller_pc (this_frame=%d) -> %s }\n",
                            this_frame->level,
-                           paddr_nz (this_frame->prev_pc.value));
+                           hex_string (this_frame->prev_pc.value));
     }
   return this_frame->prev_pc.value;
 }
 
 CORE_ADDR
+frame_unwind_caller_pc (struct frame_info *this_frame)
+{
+  return frame_unwind_pc (skip_inlined_frames (this_frame));
+}
+
+CORE_ADDR
 get_frame_func (struct frame_info *this_frame)
 {
   struct frame_info *next_frame = this_frame->next;
@@ -506,9 +666,9 @@ get_frame_func (struct frame_info *this_frame)
       next_frame->prev_func.addr = get_pc_function_start (addr_in_block);
       if (frame_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "{ get_frame_func (this_frame=%d) -> 0x%s }\n",
+                           "{ get_frame_func (this_frame=%d) -> %s }\n",
                            this_frame->level,
-                           paddr_nz (next_frame->prev_func.addr));
+                           hex_string (next_frame->prev_func.addr));
     }
   return next_frame->prev_func.addr;
 }
@@ -536,6 +696,14 @@ frame_pop (struct frame_info *this_frame)
   struct regcache *scratch;
   struct cleanup *cleanups;
 
+  if (get_frame_type (this_frame) == DUMMY_FRAME)
+    {
+      /* Popping a dummy frame involves restoring more than just registers.
+        dummy_frame_pop does all the work.  */
+      dummy_frame_pop (get_frame_id (this_frame));
+      return;
+    }
+
   /* Ensure that we have a frame to pop to.  */
   prev_frame = get_prev_frame_1 (this_frame);
 
@@ -549,11 +717,6 @@ frame_pop (struct frame_info *this_frame)
   scratch = frame_save_as_regcache (prev_frame);
   cleanups = make_cleanup_regcache_xfree (scratch);
 
-  /* If we are popping a dummy frame, clean up the associated
-     data as well.  */
-  if (get_frame_type (this_frame) == DUMMY_FRAME)
-    dummy_frame_pop (get_frame_id (this_frame));
-
   /* FIXME: cagney/2003-03-16: It should be possible to tell the
      target's register cache that it is about to be hit with a burst
      register transfer and that the sequence of register writes should
@@ -593,7 +756,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
 
   *optimizedp = value_optimized_out (value);
   *lvalp = VALUE_LVAL (value);
-  *addrp = VALUE_ADDRESS (value);
+  *addrp = value_address (value);
   *realnump = VALUE_REGNUM (value);
 
   if (bufferp)
@@ -647,17 +810,18 @@ get_frame_register (struct frame_info *frame,
 struct value *
 frame_unwind_register_value (struct frame_info *frame, int regnum)
 {
+  struct gdbarch *gdbarch;
   struct value *value;
 
   gdb_assert (frame != NULL);
+  gdbarch = frame_unwind_arch (frame);
 
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "\
 { frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ",
                          frame->level, regnum,
-                         user_reg_map_regnum_to_name
-                           (get_frame_arch (frame), regnum));
+                         user_reg_map_regnum_to_name (gdbarch, regnum));
     }
 
   /* Find the unwinder.  */
@@ -678,8 +842,9 @@ frame_unwind_register_value (struct frame_info *frame, int regnum)
            fprintf_unfiltered (gdb_stdlog, " register=%d",
                                VALUE_REGNUM (value));
          else if (VALUE_LVAL (value) == lval_memory)
-           fprintf_unfiltered (gdb_stdlog, " address=0x%s",
-                               paddr_nz (VALUE_ADDRESS (value)));
+           fprintf_unfiltered (gdb_stdlog, " address=%s",
+                               paddress (gdbarch,
+                                         value_address (value)));
          else
            fprintf_unfiltered (gdb_stdlog, " computed");
 
@@ -692,7 +857,7 @@ frame_unwind_register_value (struct frame_info *frame, int regnum)
 
              fprintf_unfiltered (gdb_stdlog, " bytes=");
              fprintf_unfiltered (gdb_stdlog, "[");
-             for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++)
+             for (i = 0; i < register_size (gdbarch, regnum); i++)
                fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
              fprintf_unfiltered (gdb_stdlog, "]");
            }
@@ -713,10 +878,12 @@ get_frame_register_value (struct frame_info *frame, int regnum)
 LONGEST
 frame_unwind_register_signed (struct frame_info *frame, int regnum)
 {
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int size = register_size (gdbarch, regnum);
   gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  return extract_signed_integer (buf, register_size (get_frame_arch (frame),
-                                                    regnum));
+  return extract_signed_integer (buf, size, byte_order);
 }
 
 LONGEST
@@ -728,10 +895,12 @@ get_frame_register_signed (struct frame_info *frame, int regnum)
 ULONGEST
 frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
 {
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int size = register_size (gdbarch, regnum);
   gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  return extract_unsigned_integer (buf, register_size (get_frame_arch (frame),
-                                                      regnum));
+  return extract_unsigned_integer (buf, size, byte_order);
 }
 
 ULONGEST
@@ -798,6 +967,7 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int i;
   int maxsize;
+  int numregs;
 
   /* Skip registers wholly inside of OFFSET.  */
   while (offset >= register_size (gdbarch, regnum))
@@ -809,7 +979,8 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
   /* Ensure that we will not read beyond the end of the register file.
      This can only ever happen if the debug information is bad.  */
   maxsize = -offset;
-  for (i = regnum; i < gdbarch_num_regs (gdbarch); i++)
+  numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+  for (i = regnum; i < numregs; i++)
     {
       int thissize = register_size (gdbarch, i);
       if (thissize == 0)
@@ -894,10 +1065,12 @@ put_frame_register_bytes (struct frame_info *frame, int regnum,
 /* Create a sentinel frame.  */
 
 static struct frame_info *
-create_sentinel_frame (struct regcache *regcache)
+create_sentinel_frame (struct program_space *pspace, struct regcache *regcache)
 {
   struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
   frame->level = -1;
+  frame->pspace = pspace;
+  frame->aspace = get_regcache_aspace (regcache);
   /* Explicitly initialize the sentinel frame's cache.  Provide it
      with the underlying regcache.  In the future additional
      information, such as the frame's thread will be added.  */
@@ -969,13 +1142,17 @@ get_current_frame (void)
     error (_("No stack."));
   if (!target_has_memory)
     error (_("No memory."));
+  if (ptid_equal (inferior_ptid, null_ptid))
+    error (_("No selected thread."));
+  if (is_exited (inferior_ptid))
+    error (_("Invalid selected thread."));
   if (is_executing (inferior_ptid))
     error (_("Target is executing."));
 
   if (current_frame == NULL)
     {
       struct frame_info *sentinel_frame =
-       create_sentinel_frame (get_current_regcache ());
+       create_sentinel_frame (current_program_space, get_current_regcache ());
       if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
                            RETURN_MASK_ERROR) != 0)
        {
@@ -992,14 +1169,21 @@ get_current_frame (void)
 
 static struct frame_info *selected_frame;
 
-static int
+int
 has_stack_frames (void)
 {
   if (!target_has_registers || !target_has_stack || !target_has_memory)
     return 0;
 
-  /* If the current thread is executing, don't try to read from
-     it.  */
+  /* No current inferior, no frame.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
+  /* Don't try to read from a dead thread.  */
+  if (is_exited (inferior_ptid))
+    return 0;
+
+  /* ... or from a spinning thread.  */
   if (is_executing (inferior_ptid))
     return 0;
 
@@ -1093,21 +1277,31 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
-                         "{ create_new_frame (addr=0x%s, pc=0x%s) ",
-                         paddr_nz (addr), paddr_nz (pc));
+                         "{ create_new_frame (addr=%s, pc=%s) ",
+                         hex_string (addr), hex_string (pc));
     }
 
   fi = FRAME_OBSTACK_ZALLOC (struct frame_info);
 
-  fi->next = create_sentinel_frame (get_current_regcache ());
+  fi->next = create_sentinel_frame (current_program_space, get_current_regcache ());
+
+  /* Set/update this frame's cached PC value, found in the next frame.
+     Do this before looking for this frame's unwinder.  A sniffer is
+     very likely to read this, and the corresponding unwinder is
+     entitled to rely that the PC doesn't magically change.  */
+  fi->next->prev_pc.value = pc;
+  fi->next->prev_pc.p = 1;
+
+  /* We currently assume that frame chain's can't cross spaces.  */
+  fi->pspace = fi->next->pspace;
+  fi->aspace = fi->next->aspace;
 
   /* Select/initialize both the unwind function and the frame's type
      based on the PC.  */
   fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
 
   fi->this_id.p = 1;
-  deprecated_update_frame_base_hack (fi, addr);
-  deprecated_update_frame_pc_hack (fi, pc);
+  fi->this_id.value = frame_id_build (addr, pc);
 
   if (frame_debug)
     {
@@ -1134,7 +1328,7 @@ get_next_frame (struct frame_info *this_frame)
 
 /* Observer for the target_changed event.  */
 
-void
+static void
 frame_observer_target_changed (struct target_ops *target)
 {
   reinit_frame_cache ();
@@ -1165,6 +1359,7 @@ reinit_frame_cache (void)
 
   current_frame = NULL;                /* Invalidate cache */
   select_frame (NULL);
+  frame_stash_invalidate ();
   if (frame_debug)
     fprintf_unfiltered (gdb_stdlog, "{ reinit_frame_cache () }\n");
 }
@@ -1205,7 +1400,6 @@ frame_register_unwind_location (struct frame_info *this_frame, int regnum,
 static struct frame_info *
 get_prev_frame_1 (struct frame_info *this_frame)
 {
-  struct frame_info *prev_frame;
   struct frame_id this_id;
   struct gdbarch *gdbarch;
 
@@ -1245,11 +1439,19 @@ get_prev_frame_1 (struct frame_info *this_frame)
   this_frame->prev_p = 1;
   this_frame->stop_reason = UNWIND_NO_REASON;
 
+  /* If we are unwinding from an inline frame, all of the below tests
+     were already performed when we unwound from the next non-inline
+     frame.  We must skip them, since we can not get THIS_FRAME's ID
+     until we have unwound all the way down to the previous non-inline
+     frame.  */
+  if (get_frame_type (this_frame) == INLINE_FRAME)
+    return get_prev_frame_raw (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.  */
   this_id = get_frame_id (this_frame);
-  if (this_frame->level >= 0 && !frame_id_p (this_id))
+  if (this_frame->level >= 0 && frame_id_eq (this_id, outer_frame_id))
     {
       if (frame_debug)
        {
@@ -1263,9 +1465,10 @@ get_prev_frame_1 (struct frame_info *this_frame)
 
   /* Check that this frame's ID isn't inner to (younger, below, next)
      the next frame.  This happens when a frame unwind goes backwards.
-     This check is valid only if the next frame is NORMAL.  See the
-     comment at frame_id_inner for details.  */
-  if (this_frame->next->unwind->type == NORMAL_FRAME
+     This check is valid only if this frame and the next frame are NORMAL.
+     See the comment at frame_id_inner for details.  */
+  if (get_frame_type (this_frame) == NORMAL_FRAME
+      && this_frame->next->unwind->type == NORMAL_FRAME
       && frame_id_inner (get_frame_arch (this_frame->next), this_id,
                         get_frame_id (this_frame->next)))
     {
@@ -1312,7 +1515,8 @@ get_prev_frame_1 (struct frame_info *this_frame)
   if (this_frame->level > 0
       && gdbarch_pc_regnum (gdbarch) >= 0
       && get_frame_type (this_frame) == NORMAL_FRAME
-      && get_frame_type (this_frame->next) == NORMAL_FRAME)
+      && (get_frame_type (this_frame->next) == NORMAL_FRAME
+         || get_frame_type (this_frame->next) == INLINE_FRAME))
     {
       int optimized, realnum, nrealnum;
       enum lval_type lval, nlval;
@@ -1341,6 +1545,17 @@ get_prev_frame_1 (struct frame_info *this_frame)
        }
     }
 
+  return get_prev_frame_raw (this_frame);
+}
+
+/* Construct a new "struct frame_info" and link it previous to
+   this_frame.  */
+
+static struct frame_info *
+get_prev_frame_raw (struct frame_info *this_frame)
+{
+  struct frame_info *prev_frame;
+
   /* 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
      frame->next to pull some fancy tricks (of course such code is, by
@@ -1354,6 +1569,11 @@ get_prev_frame_1 (struct frame_info *this_frame)
   prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
   prev_frame->level = this_frame->level + 1;
 
+  /* For now, assume we don't have frame chains crossing address
+     spaces.  */
+  prev_frame->pspace = this_frame->pspace;
+  prev_frame->aspace = this_frame->aspace;
+
   /* Don't yet compute ->unwind (and hence ->type).  It is computed
      on-demand in get_frame_type, frame_register_unwind, and
      get_frame_id.  */
@@ -1390,8 +1610,7 @@ get_prev_frame_1 (struct frame_info *this_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,
+frame_debug_got_null_frame (struct frame_info *this_frame,
                            const char *reason)
 {
   if (frame_debug)
@@ -1448,42 +1667,6 @@ 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().  */
@@ -1500,7 +1683,7 @@ get_prev_frame (struct frame_info *this_frame)
      the main function when we created the dummy frame, the dummy frame will 
      point inside the main function.  */
   if (this_frame->level >= 0
-      && get_frame_type (this_frame) != DUMMY_FRAME
+      && get_frame_type (this_frame) == NORMAL_FRAME
       && !backtrace_past_main
       && inside_main_func (this_frame))
     /* Don't unwind past main().  Note, this is done _before_ the
@@ -1508,7 +1691,7 @@ get_prev_frame (struct frame_info *this_frame)
        user later decides to enable unwinds past main(), that will
        automatically happen.  */
     {
-      frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside main func");
+      frame_debug_got_null_frame (this_frame, "inside main func");
       return NULL;
     }
 
@@ -1519,8 +1702,7 @@ get_prev_frame (struct frame_info *this_frame)
      frame.  */
   if (this_frame->level + 2 > backtrace_limit)
     {
-      frame_debug_got_null_frame (gdb_stdlog, this_frame,
-                                 "backtrace limit exceeded");
+      frame_debug_got_null_frame (this_frame, "backtrace limit exceeded");
       return NULL;
     }
 
@@ -1546,11 +1728,12 @@ get_prev_frame (struct frame_info *this_frame)
      from main returns directly to the caller of main.  Since we don't
      stop at main, we should at least stop at the entry point of the
      application.  */
-  if (!backtrace_past_entry
-      && get_frame_type (this_frame) != DUMMY_FRAME && this_frame->level >= 0
+  if (this_frame->level >= 0
+      && get_frame_type (this_frame) == NORMAL_FRAME
+      && !backtrace_past_entry
       && inside_entry_func (this_frame))
     {
-      frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry func");
+      frame_debug_got_null_frame (this_frame, "inside entry func");
       return NULL;
     }
 
@@ -1558,11 +1741,12 @@ get_prev_frame (struct frame_info *this_frame)
      like a SIGSEGV or a dummy frame, and hence that NORMAL frames
      will never unwind a zero PC.  */
   if (this_frame->level > 0
-      && get_frame_type (this_frame) == NORMAL_FRAME
+      && (get_frame_type (this_frame) == NORMAL_FRAME
+         || get_frame_type (this_frame) == INLINE_FRAME)
       && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME
       && get_frame_pc (this_frame) == 0)
     {
-      frame_debug_got_null_frame (gdb_stdlog, this_frame, "zero PC");
+      frame_debug_got_null_frame (this_frame, "zero PC");
       return NULL;
     }
 
@@ -1573,7 +1757,7 @@ CORE_ADDR
 get_frame_pc (struct frame_info *frame)
 {
   gdb_assert (frame->next != NULL);
-  return frame_pc_unwind (frame->next);
+  return frame_unwind_pc (frame->next);
 }
 
 /* Return an address that falls within THIS_FRAME's code block.  */
@@ -1618,17 +1802,58 @@ get_frame_address_in_block (struct frame_info *this_frame)
      We check the type of NEXT_FRAME first, since it is already
      known; frame type is determined by the unwinder, and since
      we have THIS_FRAME we've already selected an unwinder for
-     NEXT_FRAME.  */
+     NEXT_FRAME.
+
+     If the next frame is inlined, we need to keep going until we find
+     the real function - for instance, if a signal handler is invoked
+     while in an inlined function, then the code address of the
+     "calling" normal function should not be adjusted either.  */
+
+  while (get_frame_type (next_frame) == INLINE_FRAME)
+    next_frame = next_frame->next;
+
   if (get_frame_type (next_frame) == NORMAL_FRAME
-      && get_frame_type (this_frame) == NORMAL_FRAME)
+      && (get_frame_type (this_frame) == NORMAL_FRAME
+         || get_frame_type (this_frame) == INLINE_FRAME))
     return pc - 1;
 
   return pc;
 }
 
-static int
-pc_notcurrent (struct frame_info *frame)
+void
+find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
 {
+  struct frame_info *next_frame;
+  int notcurrent;
+
+  /* If the next frame represents an inlined function call, this frame's
+     sal is the "call site" of that inlined function, which can not
+     be inferred from get_frame_pc.  */
+  next_frame = get_next_frame (frame);
+  if (frame_inlined_callees (frame) > 0)
+    {
+      struct symbol *sym;
+
+      if (next_frame)
+       sym = get_frame_function (next_frame);
+      else
+       sym = inline_skipped_symbol (inferior_ptid);
+
+      init_sal (sal);
+      if (SYMBOL_LINE (sym) != 0)
+       {
+         sal->symtab = SYMBOL_SYMTAB (sym);
+         sal->line = SYMBOL_LINE (sym);
+       }
+      else
+       /* If the symbol does not have a location, we don't know where
+          the call site is.  Do not pretend to.  This is jarring, but
+          we can't do much better.  */
+       sal->pc = get_frame_pc (frame);
+
+      return;
+    }
+
   /* If FRAME is not the innermost frame, that normally means that
      FRAME->pc points at the return instruction (which is *after* the
      call instruction), and we want to get the line containing the
@@ -1638,15 +1863,8 @@ pc_notcurrent (struct frame_info *frame)
      PC and such a PC indicates the current (rather than next)
      instruction/line, consequently, for such cases, want to get the
      line containing fi->pc.  */
-  struct frame_info *next = get_next_frame (frame);
-  int notcurrent = (next != NULL && get_frame_type (next) == NORMAL_FRAME);
-  return notcurrent;
-}
-
-void
-find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
-{
-  (*sal) = find_pc_line (get_frame_pc (frame), pc_notcurrent (frame));
+  notcurrent = (get_frame_pc (frame) != get_frame_address_in_block (frame));
+  (*sal) = find_pc_line (get_frame_pc (frame), notcurrent);
 }
 
 /* Per "frame.h", return the ``address'' of the frame.  Code should
@@ -1705,6 +1923,17 @@ get_frame_args_address (struct frame_info *fi)
   return fi->base->this_args (fi, &fi->base_cache);
 }
 
+/* Return true if the frame unwinder for frame FI is UNWINDER; false
+   otherwise.  */
+
+int
+frame_unwinder_is (struct frame_info *fi, const struct frame_unwind *unwinder)
+{
+  if (fi->unwind == NULL)
+    fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
+  return fi->unwind == unwinder;
+}
+
 /* Level of the selected frame: 0 for innermost, 1 for its caller, ...
    or -1 for a NULL frame.  */
 
@@ -1727,36 +1956,27 @@ get_frame_type (struct frame_info *frame)
   return frame->unwind->type;
 }
 
-void
-deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
+struct program_space *
+get_frame_program_space (struct frame_info *frame)
 {
-  if (frame_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "{ 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 frames
-     are not in the frame chain, it isn't possible to assume that the
-     frame has a next.  Sigh.  */
-  if (frame->next != NULL)
-    {
-      /* While we're at it, update this frame's cached PC value, found
-        in the next frame.  Oh for the day when "struct frame_info"
-        is opaque and this hack on hack can just go away.  */
-      frame->next->prev_pc.value = pc;
-      frame->next->prev_pc.p = 1;
-    }
+  return frame->pspace;
 }
 
-void
-deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
+struct program_space *
+frame_unwind_program_space (struct frame_info *this_frame)
 {
-  if (frame_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "{ deprecated_update_frame_base_hack (frame=%d,base=0x%s) }\n",
-                       frame->level, paddr_nz (base));
-  /* See comment in "frame.h".  */
-  frame->this_id.value.stack_addr = base;
+  gdb_assert (this_frame);
+
+  /* This is really a placeholder to keep the API consistent --- we
+     assume for now that we don't have frame chains crossing
+     spaces.  */
+  return this_frame->pspace;
+}
+
+struct address_space *
+get_frame_address_space (struct frame_info *frame)
+{
+  return frame->aspace;
 }
 
 /* Memory access methods.  */
@@ -1772,14 +1992,18 @@ LONGEST
 get_frame_memory_signed (struct frame_info *this_frame, CORE_ADDR addr,
                         int len)
 {
-  return read_memory_integer (addr, len);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  return read_memory_integer (addr, len, byte_order);
 }
 
 ULONGEST
 get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr,
                           int len)
 {
-  return read_memory_unsigned_integer (addr, len);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  return read_memory_unsigned_integer (addr, len, byte_order);
 }
 
 int
@@ -1790,12 +2014,48 @@ safe_frame_unwind_memory (struct frame_info *this_frame,
   return !target_read_memory (addr, buf, len);
 }
 
-/* Architecture method.  */
+/* Architecture methods.  */
 
 struct gdbarch *
 get_frame_arch (struct frame_info *this_frame)
 {
-  return current_gdbarch;
+  return frame_unwind_arch (this_frame->next);
+}
+
+struct gdbarch *
+frame_unwind_arch (struct frame_info *next_frame)
+{
+  if (!next_frame->prev_arch.p)
+    {
+      struct gdbarch *arch;
+
+      if (next_frame->unwind == NULL)
+       next_frame->unwind
+         = frame_unwind_find_by_frame (next_frame,
+                                       &next_frame->prologue_cache);
+
+      if (next_frame->unwind->prev_arch != NULL)
+       arch = next_frame->unwind->prev_arch (next_frame,
+                                             &next_frame->prologue_cache);
+      else
+       arch = get_frame_arch (next_frame);
+
+      next_frame->prev_arch.arch = arch;
+      next_frame->prev_arch.p = 1;
+      if (frame_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "{ frame_unwind_arch (next_frame=%d) -> %s }\n",
+                           next_frame->level,
+                           gdbarch_bfd_arch_info (arch)->printable_name);
+    }
+
+  return next_frame->prev_arch.arch;
+}
+
+struct gdbarch *
+frame_unwind_caller_arch (struct frame_info *next_frame)
+{
+  return frame_unwind_arch (skip_inlined_frames (next_frame));
 }
 
 /* Stack pointer methods.  */