Teach the testsuite that GDBserver reliably reports program exits.
[deliverable/binutils-gdb.git] / gdb / frame.c
index 3c5c7af3512935070033e51704f91f306e0a1cac..eace738903fedb47d857f73c9652880d5fff673e 100644 (file)
@@ -1,8 +1,6 @@
 /* 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, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1986-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -44,7 +42,8 @@
 #include "gdbthread.h"
 #include "block.h"
 #include "inline-frame.h"
-#include  "tracepoint.h"
+#include "tracepoint.h"
+#include "hashtab.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);
@@ -130,43 +129,112 @@ struct frame_info
   enum unwind_stop_reason stop_reason;
 };
 
-/* A frame stash used to speed up frame lookups.  */
+/* A frame stash used to speed up frame lookups.  Create a hash table
+   to stash frames previously accessed from the frame cache for
+   quicker subsequent retrieval.  The hash table is emptied whenever
+   the frame cache is invalidated.  */
 
-/* We currently only stash one frame at a time, as this seems to be
-   sufficient for now.  */
-static struct frame_info *frame_stash = NULL;
+static htab_t frame_stash;
 
-/* Add the following FRAME to the frame stash.  */
+/* Internal function to calculate a hash from the frame_id addresses,
+   using as many valid addresses as possible.  Frames below level 0
+   are not stored in the hash table.  */
+
+static hashval_t
+frame_addr_hash (const void *ap)
+{
+  const struct frame_info *frame = ap;
+  const struct frame_id f_id = frame->this_id.value;
+  hashval_t hash = 0;
+
+  gdb_assert (f_id.stack_addr_p || f_id.code_addr_p
+             || f_id.special_addr_p);
+
+  if (f_id.stack_addr_p)
+    hash = iterative_hash (&f_id.stack_addr,
+                          sizeof (f_id.stack_addr), hash);
+  if (f_id.code_addr_p)
+    hash = iterative_hash (&f_id.code_addr,
+                          sizeof (f_id.code_addr), hash);
+  if (f_id.special_addr_p)
+    hash = iterative_hash (&f_id.special_addr,
+                          sizeof (f_id.special_addr), hash);
+
+  return hash;
+}
+
+/* Internal equality function for the hash table.  This function
+   defers equality operations to frame_id_eq.  */
+
+static int
+frame_addr_hash_eq (const void *a, const void *b)
+{
+  const struct frame_info *f_entry = a;
+  const struct frame_info *f_element = b;
+
+  return frame_id_eq (f_entry->this_id.value,
+                     f_element->this_id.value);
+}
+
+/* Internal function to create the frame_stash hash table.  100 seems
+   to be a good compromise to start the hash table at.  */
+
+static void
+frame_stash_create (void)
+{
+  frame_stash = htab_create (100,
+                            frame_addr_hash,
+                            frame_addr_hash_eq,
+                            NULL);
+}
+
+/* Internal function to add a frame to the frame_stash hash table.  Do
+   not store frames below 0 as they may not have any addresses to
+   calculate a hash.  */
 
 static void
 frame_stash_add (struct frame_info *frame)
 {
-  frame_stash = frame;
+  /* Do not stash frames below level 0.  */
+  if (frame->level >= 0)
+    {
+      struct frame_info **slot;
+
+      slot = (struct frame_info **) htab_find_slot (frame_stash,
+                                                   frame,
+                                                   INSERT);
+      *slot = frame;
+    }
 }
 
-/* Search the frame stash for an entry with the given frame ID.
-   If found, return that frame.  Otherwise return NULL.  */
+/* Internal function to 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;
+  struct frame_info dummy;
+  struct frame_info *frame;
 
-  return NULL;
+  dummy.this_id.value = id;
+  frame = htab_find (frame_stash, &dummy);
+  return frame;
 }
 
-/* Invalidate the frame stash by removing all entries in it.  */
+/* Internal function to invalidate the frame stash by removing all
+   entries in it.  This only occurs when the frame cache is
+   invalidated.  */
 
 static void
 frame_stash_invalidate (void)
 {
-  frame_stash = NULL;
+  htab_empty (frame_stash);
 }
 
 /* Flag to control debugging.  */
 
-int frame_debug;
+unsigned int frame_debug;
 static void
 show_frame_debug (struct ui_file *file, int from_tty,
                  struct cmd_list_element *c, const char *value)
@@ -197,7 +265,7 @@ show_backtrace_past_entry (struct ui_file *file, int from_tty,
                    value);
 }
 
-static int backtrace_limit = INT_MAX;
+static unsigned int backtrace_limit = UINT_MAX;
 static void
 show_backtrace_limit (struct ui_file *file, int from_tty,
                      struct cmd_list_element *c, const char *value)
@@ -227,8 +295,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);
+  if (id.artificial_depth)
+    fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth);
   fprintf_unfiltered (file, "}");
 }
 
@@ -246,8 +314,8 @@ fprint_frame_type (struct ui_file *file, enum frame_type type)
     case INLINE_FRAME:
       fprintf_unfiltered (file, "INLINE_FRAME");
       return;
-    case SENTINEL_FRAME:
-      fprintf_unfiltered (file, "SENTINEL_FRAME");
+    case TAILCALL_FRAME:
+      fprintf_unfiltered (file, "TAILCALL_FRAME");
       return;
     case SIGTRAMP_FRAME:
       fprintf_unfiltered (file, "SIGTRAMP_FRAME");
@@ -255,6 +323,9 @@ fprint_frame_type (struct ui_file *file, enum frame_type type)
     case ARCH_FRAME:
       fprintf_unfiltered (file, "ARCH_FRAME");
       return;
+    case SENTINEL_FRAME:
+      fprintf_unfiltered (file, "SENTINEL_FRAME");
+      return;
     default:
       fprintf_unfiltered (file, "<unknown type>");
       return;
@@ -304,13 +375,15 @@ fprint_frame (struct ui_file *file, struct frame_info *fi)
   fprintf_unfiltered (file, "}");
 }
 
-/* Given FRAME, return the enclosing normal frame for inlined
-   function frames.  Otherwise return the original frame.  */
+/* Given FRAME, return the enclosing frame as found in real frames read-in from
+   inferior memory.  Skip any previous frames which were made up by GDB.
+   Return the original frame if no immediate previous frames exist.  */
 
 static struct frame_info *
-skip_inlined_frames (struct frame_info *frame)
+skip_artificial_frames (struct frame_info *frame)
 {
-  while (get_frame_type (frame) == INLINE_FRAME)
+  while (get_frame_type (frame) == INLINE_FRAME
+        || get_frame_type (frame) == TAILCALL_FRAME)
     frame = get_prev_frame (frame);
 
   return frame;
@@ -345,17 +418,16 @@ get_frame_id (struct frame_info *fi)
          fprint_frame_id (gdb_stdlog, fi->this_id.value);
          fprintf_unfiltered (gdb_stdlog, " }\n");
        }
+      frame_stash_add (fi);
     }
 
-  frame_stash_add (fi);
-
   return fi->this_id.value;
 }
 
 struct frame_id
 get_stack_frame_id (struct frame_info *next_frame)
 {
-  return get_frame_id (skip_inlined_frames (next_frame));
+  return get_frame_id (skip_artificial_frames (next_frame));
 }
 
 struct frame_id
@@ -368,10 +440,10 @@ frame_unwind_caller_id (struct frame_info *next_frame)
      returning a null_frame_id (e.g., when a caller requests the frame
      ID of "main()"s caller.  */
 
-  next_frame = skip_inlined_frames (next_frame);
+  next_frame = skip_artificial_frames (next_frame);
   this_frame = get_prev_frame_1 (next_frame);
   if (this_frame)
-    return get_frame_id (skip_inlined_frames (this_frame));
+    return get_frame_id (skip_artificial_frames (this_frame));
   else
     return null_frame_id;
 }
@@ -436,12 +508,12 @@ frame_id_p (struct frame_id l)
 }
 
 int
-frame_id_inlined_p (struct frame_id l)
+frame_id_artificial_p (struct frame_id l)
 {
   if (!frame_id_p (l))
     return 0;
 
-  return (l.inline_depth != 0);
+  return (l.artificial_depth != 0);
 }
 
 int
@@ -473,8 +545,8 @@ frame_id_eq (struct frame_id l, struct frame_id r)
     /* 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.  */
+  else if (l.artificial_depth != r.artificial_depth)
+    /* If artifical depths are different, the frames must be different.  */
     eq = 0;
   else
     /* Frames are equal.  */
@@ -499,7 +571,7 @@ 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. Assuming that NEXT is the immediate
+   IDs in certain circumstances.  Assuming that NEXT is the immediate
    inner frame to THIS and that NEXT and THIS are both NORMAL frames:
 
    * The stack address of NEXT must be inner-than-or-equal to the stack
@@ -519,7 +591,7 @@ frame_id_eq (struct frame_id l, struct frame_id r)
    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
+   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.  */
 
@@ -531,7 +603,7 @@ 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
+  else if (l.artificial_depth > r.artificial_depth
           && l.stack_addr == r.stack_addr
           && l.code_addr_p == r.code_addr_p
           && l.special_addr_p == r.special_addr_p
@@ -619,15 +691,17 @@ frame_find_by_id (struct frame_id id)
   return NULL;
 }
 
-static CORE_ADDR
-frame_unwind_pc (struct frame_info *this_frame)
+static int
+frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
 {
   if (!this_frame->prev_pc.p)
     {
-      CORE_ADDR pc;
-
       if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame)))
        {
+         volatile struct gdb_exception ex;
+         struct gdbarch *prev_gdbarch;
+         CORE_ADDR pc = 0;
+
          /* The right way.  The `pure' way.  The one true way.  This
             method depends solely on the register-unwind code to
             determine the value of registers in THIS frame, and hence
@@ -644,53 +718,139 @@ frame_unwind_pc (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 (frame_unwind_arch (this_frame), this_frame);
+         prev_gdbarch = frame_unwind_arch (this_frame);
+
+         TRY_CATCH (ex, RETURN_MASK_ERROR)
+           {
+             pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
+           }
+         if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+           {
+             this_frame->prev_pc.p = -1;
+
+             if (frame_debug)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "{ frame_unwind_pc (this_frame=%d)"
+                                   " -> <unavailable> }\n",
+                                   this_frame->level);
+           }
+         else if (ex.reason < 0)
+           {
+             throw_exception (ex);
+           }
+         else
+           {
+             this_frame->prev_pc.value = pc;
+             this_frame->prev_pc.p = 1;
+             if (frame_debug)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "{ frame_unwind_pc (this_frame=%d) "
+                                   "-> %s }\n",
+                                   this_frame->level,
+                                   hex_string (this_frame->prev_pc.value));
+           }
        }
       else
        internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
-      this_frame->prev_pc.value = pc;
-      this_frame->prev_pc.p = 1;
-      if (frame_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "{ frame_unwind_caller_pc "
-                           "(this_frame=%d) -> %s }\n",
-                           this_frame->level,
-                           hex_string (this_frame->prev_pc.value));
     }
-  return this_frame->prev_pc.value;
+  if (this_frame->prev_pc.p < 0)
+    {
+      *pc = -1;
+      return 0;
+    }
+  else
+    {
+      *pc = this_frame->prev_pc.value;
+      return 1;
+    }
+}
+
+static CORE_ADDR
+frame_unwind_pc (struct frame_info *this_frame)
+{
+  CORE_ADDR pc;
+
+  if (!frame_unwind_pc_if_available (this_frame, &pc))
+    throw_error (NOT_AVAILABLE_ERROR, _("PC not available"));
+  else
+    return pc;
 }
 
 CORE_ADDR
 frame_unwind_caller_pc (struct frame_info *this_frame)
 {
-  return frame_unwind_pc (skip_inlined_frames (this_frame));
+  return frame_unwind_pc (skip_artificial_frames (this_frame));
 }
 
-CORE_ADDR
-get_frame_func (struct frame_info *this_frame)
+int
+frame_unwind_caller_pc_if_available (struct frame_info *this_frame,
+                                    CORE_ADDR *pc)
+{
+  return frame_unwind_pc_if_available (skip_artificial_frames (this_frame), pc);
+}
+
+int
+get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
 {
   struct frame_info *next_frame = this_frame->next;
 
   if (!next_frame->prev_func.p)
     {
+      CORE_ADDR addr_in_block;
+
       /* Make certain that this, and not the adjacent, function is
          found.  */
-      CORE_ADDR addr_in_block = get_frame_address_in_block (this_frame);
-      next_frame->prev_func.p = 1;
-      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) -> %s }\n",
-                           this_frame->level,
-                           hex_string (next_frame->prev_func.addr));
+      if (!get_frame_address_in_block_if_available (this_frame, &addr_in_block))
+       {
+         next_frame->prev_func.p = -1;
+         if (frame_debug)
+           fprintf_unfiltered (gdb_stdlog,
+                               "{ get_frame_func (this_frame=%d)"
+                               " -> unavailable }\n",
+                               this_frame->level);
+       }
+      else
+       {
+         next_frame->prev_func.p = 1;
+         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) -> %s }\n",
+                               this_frame->level,
+                               hex_string (next_frame->prev_func.addr));
+       }
+    }
+
+  if (next_frame->prev_func.p < 0)
+    {
+      *pc = -1;
+      return 0;
+    }
+  else
+    {
+      *pc = next_frame->prev_func.addr;
+      return 1;
     }
-  return next_frame->prev_func.addr;
 }
 
-static int
+CORE_ADDR
+get_frame_func (struct frame_info *this_frame)
+{
+  CORE_ADDR pc;
+
+  if (!get_frame_func_if_available (this_frame, &pc))
+    throw_error (NOT_AVAILABLE_ERROR, _("PC not available"));
+
+  return pc;
+}
+
+static enum register_status
 do_frame_register_read (void *src, int regnum, gdb_byte *buf)
 {
-  return frame_register_read (src, regnum, buf);
+  if (!deprecated_frame_register_read (src, regnum, buf))
+    return REG_UNAVAILABLE;
+  else
+    return REG_VALID;
 }
 
 struct regcache *
@@ -727,6 +887,11 @@ frame_pop (struct frame_info *this_frame)
   if (!prev_frame)
     error (_("Cannot pop the initial frame."));
 
+  /* Ignore TAILCALL_FRAME type frames, they were executed already before
+     entering THISFRAME.  */
+  while (get_frame_type (prev_frame) == TAILCALL_FRAME)
+    prev_frame = get_prev_frame (prev_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 between
      trying to extract the old values from the current regcache while
@@ -754,8 +919,9 @@ frame_pop (struct frame_info *this_frame)
 
 void
 frame_register_unwind (struct frame_info *frame, int regnum,
-                      int *optimizedp, enum lval_type *lvalp,
-                      CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp)
+                      int *optimizedp, int *unavailablep,
+                      enum lval_type *lvalp, CORE_ADDR *addrp,
+                      int *realnump, gdb_byte *bufferp)
 {
   struct value *value;
 
@@ -772,13 +938,19 @@ frame_register_unwind (struct frame_info *frame, int regnum,
   gdb_assert (value != NULL);
 
   *optimizedp = value_optimized_out (value);
+  *unavailablep = !value_entirely_available (value);
   *lvalp = VALUE_LVAL (value);
   *addrp = value_address (value);
   *realnump = VALUE_REGNUM (value);
 
-  if (bufferp && !*optimizedp)
-    memcpy (bufferp, value_contents_all (value),
-           TYPE_LENGTH (value_type (value)));
+  if (bufferp)
+    {
+      if (!*optimizedp && !*unavailablep)
+       memcpy (bufferp, value_contents_all (value),
+               TYPE_LENGTH (value_type (value)));
+      else
+       memset (bufferp, 0, TYPE_LENGTH (value_type (value)));
+    }
 
   /* Dispose of the new value.  This prevents watchpoints from
      trying to watch the saved frame pointer.  */
@@ -788,7 +960,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
 
 void
 frame_register (struct frame_info *frame, int regnum,
-               int *optimizedp, enum lval_type *lvalp,
+               int *optimizedp, int *unavailablep, enum lval_type *lvalp,
                CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp)
 {
   /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
@@ -802,20 +974,27 @@ frame_register (struct frame_info *frame, int regnum,
   /* Obtain the register value by unwinding the register from the next
      (more inner frame).  */
   gdb_assert (frame != NULL && frame->next != NULL);
-  frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
-                        realnump, bufferp);
+  frame_register_unwind (frame->next, regnum, optimizedp, unavailablep,
+                        lvalp, addrp, realnump, bufferp);
 }
 
 void
 frame_unwind_register (struct frame_info *frame, int regnum, gdb_byte *buf)
 {
   int optimized;
+  int unavailable;
   CORE_ADDR addr;
   int realnum;
   enum lval_type lval;
 
-  frame_register_unwind (frame, regnum, &optimized, &lval, &addr,
-                        &realnum, buf);
+  frame_register_unwind (frame, regnum, &optimized, &unavailable,
+                        &lval, &addr, &realnum, buf);
+
+  if (optimized)
+    error (_("Register %d was optimized out"), regnum);
+  if (unavailable)
+    throw_error (NOT_AVAILABLE_ERROR,
+                _("Register %d is not available"), regnum);
 }
 
 void
@@ -930,6 +1109,26 @@ get_frame_register_unsigned (struct frame_info *frame, int regnum)
   return frame_unwind_register_unsigned (frame->next, regnum);
 }
 
+int
+read_frame_register_unsigned (struct frame_info *frame, int regnum,
+                             ULONGEST *val)
+{
+  struct value *regval = get_frame_register_value (frame, regnum);
+
+  if (!value_optimized_out (regval)
+      && value_entirely_available (regval))
+    {
+      struct gdbarch *gdbarch = get_frame_arch (frame);
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      int size = register_size (gdbarch, VALUE_REGNUM (regval));
+
+      *val = extract_unsigned_integer (value_contents (regval), size, byte_order);
+      return 1;
+    }
+
+  return 0;
+}
+
 void
 put_frame_register (struct frame_info *frame, int regnum,
                    const gdb_byte *buf)
@@ -937,22 +1136,19 @@ put_frame_register (struct frame_info *frame, int regnum,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int realnum;
   int optim;
+  int unavail;
   enum lval_type lval;
   CORE_ADDR addr;
 
-  frame_register (frame, regnum, &optim, &lval, &addr, &realnum, NULL);
+  frame_register (frame, regnum, &optim, &unavail,
+                 &lval, &addr, &realnum, NULL);
   if (optim)
     error (_("Attempt to assign to a value that was optimized out."));
   switch (lval)
     {
     case lval_memory:
       {
-       /* FIXME: write_memory doesn't yet take constant buffers.
-           Arrrg!  */
-       gdb_byte tmp[MAX_REGISTER_SIZE];
-
-       memcpy (tmp, buf, register_size (gdbarch, regnum));
-       write_memory (addr, tmp, register_size (gdbarch, regnum));
+       write_memory (addr, buf, register_size (gdbarch, regnum));
        break;
       }
     case lval_register:
@@ -963,7 +1159,8 @@ put_frame_register (struct frame_info *frame, int regnum,
     }
 }
 
-/* frame_register_read ()
+/* This function is deprecated.  Use get_frame_register_value instead,
+   which provides more accurate information.
 
    Find and return the value of REGNUM for the specified stack frame.
    The number of bytes copied is REGISTER_SIZE (REGNUM).
@@ -971,22 +1168,25 @@ put_frame_register (struct frame_info *frame, int regnum,
    Returns 0 if the register value could not be found.  */
 
 int
-frame_register_read (struct frame_info *frame, int regnum,
+deprecated_frame_register_read (struct frame_info *frame, int regnum,
                     gdb_byte *myaddr)
 {
   int optimized;
+  int unavailable;
   enum lval_type lval;
   CORE_ADDR addr;
   int realnum;
 
-  frame_register (frame, regnum, &optimized, &lval, &addr, &realnum, myaddr);
+  frame_register (frame, regnum, &optimized, &unavailable,
+                 &lval, &addr, &realnum, myaddr);
 
-  return !optimized;
+  return !optimized && !unavailable;
 }
 
 int
 get_frame_register_bytes (struct frame_info *frame, int regnum,
-                         CORE_ADDR offset, int len, gdb_byte *myaddr)
+                         CORE_ADDR offset, int len, gdb_byte *myaddr,
+                         int *optimizedp, int *unavailablep)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int i;
@@ -1013,11 +1213,8 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
       maxsize += thissize;
     }
   if (len > maxsize)
-    {
-      warning (_("Bad debug information detected: "
-                "Attempt to read %d bytes from registers."), len);
-      return 0;
-    }
+    error (_("Bad debug information detected: "
+            "Attempt to read %d bytes from registers."), len);
 
   /* Copy the data.  */
   while (len > 0)
@@ -1029,14 +1226,25 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
 
       if (curr_len == register_size (gdbarch, regnum))
        {
-         if (!frame_register_read (frame, regnum, myaddr))
+         enum lval_type lval;
+         CORE_ADDR addr;
+         int realnum;
+
+         frame_register (frame, regnum, optimizedp, unavailablep,
+                         &lval, &addr, &realnum, myaddr);
+         if (*optimizedp || *unavailablep)
            return 0;
        }
       else
        {
          gdb_byte buf[MAX_REGISTER_SIZE];
+         enum lval_type lval;
+         CORE_ADDR addr;
+         int realnum;
 
-         if (!frame_register_read (frame, regnum, buf))
+         frame_register (frame, regnum, optimizedp, unavailablep,
+                         &lval, &addr, &realnum, buf);
+         if (*optimizedp || *unavailablep)
            return 0;
          memcpy (myaddr, buf + offset, curr_len);
        }
@@ -1047,6 +1255,8 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
       regnum++;
     }
 
+  *optimizedp = 0;
+  *unavailablep = 0;
   return 1;
 }
 
@@ -1079,7 +1289,7 @@ put_frame_register_bytes (struct frame_info *frame, int regnum,
        {
          gdb_byte buf[MAX_REGISTER_SIZE];
 
-         frame_register_read (frame, regnum, buf);
+         deprecated_frame_register_read (frame, regnum, buf);
          memcpy (buf + offset, myaddr, curr_len);
          put_frame_register (frame, regnum, buf);
        }
@@ -1123,7 +1333,7 @@ create_sentinel_frame (struct program_space *pspace, struct regcache *regcache)
   return frame;
 }
 
-/* Info about the innermost stack frame (contents of FP register) */
+/* Info about the innermost stack frame (contents of FP register) */
 
 static struct frame_info *current_frame;
 
@@ -1189,8 +1399,8 @@ get_current_frame (void)
     {
       struct frame_info *sentinel_frame =
        create_sentinel_frame (current_program_space, get_current_regcache ());
-      if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
-                           RETURN_MASK_ERROR) != 0)
+      if (catch_exceptions (current_uiout, unwind_to_current_frame,
+                           sentinel_frame, RETURN_MASK_ERROR) != 0)
        {
          /* Oops! Fake a current frame?  Is this useful?  It has a PC
              of zero, for instance.  */
@@ -1211,17 +1421,21 @@ has_stack_frames (void)
   if (!target_has_registers || !target_has_stack || !target_has_memory)
     return 0;
 
-  /* No current inferior, no frame.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return 0;
+  /* Traceframes are effectively a substitute for the live inferior.  */
+  if (get_traceframe_number () < 0)
+    {
+      /* 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;
+      /* 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;
+      /* ... or from a spinning thread.  */
+      if (is_executing (inferior_ptid))
+       return 0;
+    }
 
   return 1;
 }
@@ -1247,6 +1461,14 @@ get_selected_frame (const char *message)
   return selected_frame;
 }
 
+/* If there is a selected frame, return it.  Otherwise, return NULL.  */
+
+struct frame_info *
+get_selected_frame_if_set (void)
+{
+  return 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().  */
@@ -1264,8 +1486,6 @@ deprecated_safe_get_selected_frame (void)
 void
 select_frame (struct frame_info *fi)
 {
-  struct symtab *s;
-
   selected_frame = fi;
   /* NOTE: cagney/2002-05-04: FI can be NULL.  This occurs when the
      frame is being invalidated.  */
@@ -1279,29 +1499,34 @@ select_frame (struct frame_info *fi)
 
      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 user's 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)
     {
-      /* 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
-         && language_mode == language_mode_auto)
+      CORE_ADDR pc;
+
+      /* 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.  */
+      if (get_frame_address_in_block_if_available (fi, &pc))
        {
-         set_language (s->language);
+         struct symtab *s = find_pc_symtab (pc);
+
+         if (s
+             && s->language != current_language->la_language
+             && s->language != language_unknown
+             && language_mode == language_mode_auto)
+           set_language (s->language);
        }
     }
 }
-       
+
 /* Create an arbitrary (i.e. address specified by user) or innermost frame.
    Always returns a non-NULL value.  */
 
@@ -1387,7 +1612,7 @@ reinit_frame_cache (void)
        fi->base->unwind->dealloc_cache (fi, fi->base_cache);
     }
 
-  /* Since we can't really be sure what the first object allocated was */
+  /* Since we can't really be sure what the first object allocated was */
   obstack_free (&frame_cache_obstack, 0);
   obstack_init (&frame_cache_obstack);
 
@@ -1414,8 +1639,10 @@ frame_register_unwind_location (struct frame_info *this_frame, int regnum,
 
   while (this_frame != NULL)
     {
-      frame_register_unwind (this_frame, regnum, optimizedp, lvalp,
-                            addrp, realnump, NULL);
+      int unavailable;
+
+      frame_register_unwind (this_frame, regnum, optimizedp, &unavailable,
+                            lvalp, addrp, realnump, NULL);
 
       if (*optimizedp)
        break;
@@ -1483,6 +1710,15 @@ get_prev_frame_1 (struct frame_info *this_frame)
   if (get_frame_type (this_frame) == INLINE_FRAME)
     return get_prev_frame_raw (this_frame);
 
+  /* Check that this frame is unwindable.  If it isn't, don't try to
+     unwind to the prev frame.  */
+  this_frame->stop_reason
+    = this_frame->unwind->stop_reason (this_frame,
+                                      &this_frame->prologue_cache);
+
+  if (this_frame->stop_reason != UNWIND_NO_REASON)
+    return NULL;
+
   /* 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.  */
@@ -1514,7 +1750,7 @@ get_prev_frame_1 (struct frame_info *this_frame)
       
       /* gcc -fsplit-stack __morestack can continue the stack anywhere.  */
       this_pc_in_block = get_frame_address_in_block (this_frame);
-      morestack_msym = lookup_minimal_symbol_by_pc (this_pc_in_block);
+      morestack_msym = lookup_minimal_symbol_by_pc (this_pc_in_block).minsym;
       if (morestack_msym)
        morestack_name = SYMBOL_LINKAGE_NAME (morestack_msym);
       if (!morestack_name || strcmp (morestack_name, "__morestack") != 0)
@@ -1719,10 +1955,14 @@ inside_entry_func (struct frame_info *this_frame)
 struct frame_info *
 get_prev_frame (struct frame_info *this_frame)
 {
+  CORE_ADDR frame_pc;
+  int frame_pc_p;
+
   /* 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);
+  frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
 
   /* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much
      sense to stop unwinding at a dummy frame.  One place where a dummy
@@ -1737,6 +1977,7 @@ get_prev_frame (struct frame_info *this_frame)
   if (this_frame->level >= 0
       && get_frame_type (this_frame) == NORMAL_FRAME
       && !backtrace_past_main
+      && frame_pc_p
       && inside_main_func (this_frame))
     /* Don't unwind past main().  Note, this is done _before_ the
        frame has been marked as previously unwound.  That way if the
@@ -1783,6 +2024,7 @@ get_prev_frame (struct frame_info *this_frame)
   if (this_frame->level >= 0
       && get_frame_type (this_frame) == NORMAL_FRAME
       && !backtrace_past_entry
+      && frame_pc_p
       && inside_entry_func (this_frame))
     {
       frame_debug_got_null_frame (this_frame, "inside entry func");
@@ -1796,7 +2038,7 @@ get_prev_frame (struct frame_info *this_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_pc_p && frame_pc == 0)
     {
       frame_debug_got_null_frame (this_frame, "zero PC");
       return NULL;
@@ -1812,6 +2054,28 @@ get_frame_pc (struct frame_info *frame)
   return frame_unwind_pc (frame->next);
 }
 
+int
+get_frame_pc_if_available (struct frame_info *frame, CORE_ADDR *pc)
+{
+  volatile struct gdb_exception ex;
+
+  gdb_assert (frame->next != NULL);
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      *pc = frame_unwind_pc (frame->next);
+    }
+  if (ex.reason < 0)
+    {
+      if (ex.error == NOT_AVAILABLE_ERROR)
+       return 0;
+      else
+       throw_exception (ex);
+    }
+
+  return 1;
+}
+
 /* Return an address that falls within THIS_FRAME's code block.  */
 
 CORE_ADDR
@@ -1864,19 +2128,40 @@ get_frame_address_in_block (struct frame_info *this_frame)
   while (get_frame_type (next_frame) == INLINE_FRAME)
     next_frame = next_frame->next;
 
-  if (get_frame_type (next_frame) == NORMAL_FRAME
+  if ((get_frame_type (next_frame) == NORMAL_FRAME
+       || get_frame_type (next_frame) == TAILCALL_FRAME)
       && (get_frame_type (this_frame) == NORMAL_FRAME
+         || get_frame_type (this_frame) == TAILCALL_FRAME
          || get_frame_type (this_frame) == INLINE_FRAME))
     return pc - 1;
 
   return pc;
 }
 
+int
+get_frame_address_in_block_if_available (struct frame_info *this_frame,
+                                        CORE_ADDR *pc)
+{
+  volatile struct gdb_exception ex;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      *pc = get_frame_address_in_block (this_frame);
+    }
+  if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+    return 0;
+  else if (ex.reason < 0)
+    throw_exception (ex);
+  else
+    return 1;
+}
+
 void
 find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
 {
   struct frame_info *next_frame;
   int notcurrent;
+  CORE_ADDR pc;
 
   /* If the next frame represents an inlined function call, this frame's
      sal is the "call site" of that inlined function, which can not
@@ -1891,6 +2176,8 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
       else
        sym = inline_skipped_symbol (inferior_ptid);
 
+      /* If frame is inline, it certainly has symbols.  */
+      gdb_assert (sym);
       init_sal (sal);
       if (SYMBOL_LINE (sym) != 0)
        {
@@ -1903,6 +2190,8 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
           we can't do much better.  */
        sal->pc = get_frame_pc (frame);
 
+      sal->pspace = get_frame_program_space (frame);
+
       return;
     }
 
@@ -1915,8 +2204,14 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
      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.  */
-  notcurrent = (get_frame_pc (frame) != get_frame_address_in_block (frame));
-  (*sal) = find_pc_line (get_frame_pc (frame), notcurrent);
+  if (!get_frame_pc_if_available (frame, &pc))
+    {
+      init_sal (sal);
+      return;
+    }
+
+  notcurrent = (pc != get_frame_address_in_block (frame));
+  (*sal) = find_pc_line (pc, notcurrent);
 }
 
 /* Per "frame.h", return the ``address'' of the frame.  Code should
@@ -2105,7 +2400,7 @@ frame_unwind_arch (struct frame_info *next_frame)
 struct gdbarch *
 frame_unwind_caller_arch (struct frame_info *next_frame)
 {
-  return frame_unwind_arch (skip_inlined_frames (next_frame));
+  return frame_unwind_arch (skip_artificial_frames (next_frame));
 }
 
 /* Stack pointer methods.  */
@@ -2151,20 +2446,11 @@ frame_stop_reason_string (enum unwind_stop_reason reason)
 {
   switch (reason)
     {
-    case UNWIND_NULL_ID:
-      return _("unwinder did not report frame ID");
-
-    case UNWIND_INNER_ID:
-      return _("previous frame inner to this frame (corrupt stack?)");
+#define SET(name, description) \
+    case name: return _(description);
+#include "unwind_stop_reasons.def"
+#undef SET
 
-    case UNWIND_SAME_ID:
-      return _("previous frame identical to this frame (corrupt stack?)");
-
-    case UNWIND_NO_SAVED_PC:
-      return _("frame did not save the PC");
-
-    case UNWIND_NO_REASON:
-    case UNWIND_FIRST_ERROR:
     default:
       internal_error (__FILE__, __LINE__,
                      "Invalid frame stop reason");
@@ -2237,6 +2523,8 @@ _initialize_frame (void)
 {
   obstack_init (&frame_cache_obstack);
 
+  frame_stash_create ();
+
   observer_attach_target_changed (frame_observer_target_changed);
 
   add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, _("\
@@ -2276,23 +2564,23 @@ the rest of the stack trace."),
                           &set_backtrace_cmdlist,
                           &show_backtrace_cmdlist);
 
-  add_setshow_integer_cmd ("limit", class_obscure,
-                          &backtrace_limit, _("\
+  add_setshow_uinteger_cmd ("limit", class_obscure,
+                           &backtrace_limit, _("\
 Set an upper bound on the number of backtrace levels."), _("\
 Show the upper bound on the number of backtrace levels."), _("\
 No more than the specified number of frames can be displayed or examined.\n\
-Zero is unlimited."),
-                          NULL,
-                          show_backtrace_limit,
-                          &set_backtrace_cmdlist,
-                          &show_backtrace_cmdlist);
+Literal \"unlimited\" or zero means no limit."),
+                           NULL,
+                           show_backtrace_limit,
+                           &set_backtrace_cmdlist,
+                           &show_backtrace_cmdlist);
 
-  /* Debug this files internals. */
-  add_setshow_zinteger_cmd ("frame", class_maintenance, &frame_debug,  _("\
+  /* Debug this files internals.  */
+  add_setshow_zuinteger_cmd ("frame", class_maintenance, &frame_debug,  _("\
 Set frame debugging."), _("\
 Show frame debugging."), _("\
 When non-zero, frame specific internal debugging is enabled."),
-                           NULL,
-                           show_frame_debug,
-                           &setdebuglist, &showdebuglist);
+                            NULL,
+                            show_frame_debug,
+                            &setdebuglist, &showdebuglist);
 }
This page took 0.045594 seconds and 4 git commands to generate.