gdb: set only inferior_ptid in sparc_{fetch,store}_inferior_registers
[binutils-gdb.git] / gdb / frame.c
index bb835e2dbac7f8473a972a689bb294a925dff7e8..d2e14c831a09a3e03333ed7b75ad8bdcc3f4cd2f 100644 (file)
@@ -1,6 +1,6 @@
 /* Cache and manage frames for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2020 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -373,43 +373,44 @@ show_backtrace_limit (struct ui_file *file, int from_tty,
                    value);
 }
 
+/* See frame.h.  */
 
-static void
-fprint_field (struct ui_file *file, const char *name, int p, CORE_ADDR addr)
+std::string
+frame_id::to_string () const
 {
-  if (p)
-    fprintf_unfiltered (file, "%s=%s", name, hex_string (addr));
-  else
-    fprintf_unfiltered (file, "!%s", name);
-}
+  const struct frame_id &id = *this;
 
-void
-fprint_frame_id (struct ui_file *file, struct frame_id id)
-{
-  fprintf_unfiltered (file, "{");
+  std::string res = "{";
 
   if (id.stack_status == FID_STACK_INVALID)
-    fprintf_unfiltered (file, "!stack");
+    res += "!stack";
   else if (id.stack_status == FID_STACK_UNAVAILABLE)
-    fprintf_unfiltered (file, "stack=<unavailable>");
+    res += "stack=<unavailable>";
   else if (id.stack_status == FID_STACK_SENTINEL)
-    fprintf_unfiltered (file, "stack=<sentinel>");
+    res += "stack=<sentinel>";
   else if (id.stack_status == FID_STACK_OUTER)
-    fprintf_unfiltered (file, "stack=<outer>");
+    res += "stack=<outer>";
   else
-    fprintf_unfiltered (file, "stack=%s", hex_string (id.stack_addr));
-
-  fprintf_unfiltered (file, ",");
+    res += std::string ("stack=") + hex_string (id.stack_addr);
 
-  fprint_field (file, "code", id.code_addr_p, id.code_addr);
-  fprintf_unfiltered (file, ",");
+  /* Helper function to format 'N=A' if P is true, otherwise '!N'.  */
+  auto field_to_string = [] (const char *n, bool p, CORE_ADDR a) -> std::string
+  {
+    if (p)
+      return std::string (n) + "=" + core_addr_to_string (a);
+    else
+      return std::string ("!") + std::string (n);
+  };
 
-  fprint_field (file, "special", id.special_addr_p, id.special_addr);
+  res += (std::string (",")
+         + field_to_string ("code", id.code_addr_p, id.code_addr)
+         + std::string (",")
+         + field_to_string ("special", id.special_addr_p, id.special_addr));
 
   if (id.artificial_depth)
-    fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth);
-
-  fprintf_unfiltered (file, "}");
+    res += ",artificial=" + std::to_string (id.artificial_depth);
+  res += "}";
+  return res;
 }
 
 static void
@@ -492,7 +493,7 @@ fprint_frame (struct ui_file *file, struct frame_info *fi)
   else if (fi->this_id.p == frame_id_status::COMPUTING)
     fprintf_unfiltered (file, "<computing>");
   else
-    fprint_frame_id (file, fi->this_id.value);
+    fprintf_unfiltered (file, "%s", fi->this_id.value.to_string ().c_str ());
   fprintf_unfiltered (file, ",");
 
   fprintf_unfiltered (file, "func=");
@@ -592,16 +593,13 @@ compute_frame_id (struct frame_info *fi)
       fi->this_id.p = frame_id_status::COMPUTED;
 
       if (frame_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "-> ");
-         fprint_frame_id (gdb_stdlog, fi->this_id.value);
-         fprintf_unfiltered (gdb_stdlog, " }\n");
-       }
+       fprintf_unfiltered (gdb_stdlog, "-> %s }\n",
+                           fi->this_id.value.to_string ().c_str ());
     }
   catch (const gdb_exception &ex)
     {
       /* On error, revert the frame id status to not computed.  If the frame
-         cache generation changed, the frame object doesn't exist anymore, so
+        cache generation changed, the frame object doesn't exist anymore, so
         don't touch it.  */
       if (get_frame_cache_generation () == entry_generation)
        fi->this_id.p = frame_id_status::NOT_COMPUTED;
@@ -677,7 +675,7 @@ const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_OUTER, 0, 1, 0 };
 
 struct frame_id
 frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
-                        CORE_ADDR special_addr)
+                       CORE_ADDR special_addr)
 {
   struct frame_id id = null_frame_id;
 
@@ -748,11 +746,8 @@ frame_id_p (frame_id l)
   bool p = l.stack_status != FID_STACK_INVALID;
 
   if (frame_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l=");
-      fprint_frame_id (gdb_stdlog, l);
-      fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", p);
-    }
+    fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l=%s) -> %d }\n",
+                       l.to_string ().c_str (), p);
 
   return p;
 }
@@ -796,13 +791,8 @@ frame_id_eq (frame_id l, frame_id r)
     eq = true;
 
   if (frame_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l=");
-      fprint_frame_id (gdb_stdlog, l);
-      fprintf_unfiltered (gdb_stdlog, ",r=");
-      fprint_frame_id (gdb_stdlog, r);
-      fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", eq);
-    }
+    fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l=%s,r=%s) -> %d }\n",
+                       l.to_string ().c_str (), r.to_string ().c_str (), eq);
 
   return eq;
 }
@@ -879,13 +869,9 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r)
     inner = gdbarch_inner_than (gdbarch, l.stack_addr, r.stack_addr);
 
   if (frame_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l=");
-      fprint_frame_id (gdb_stdlog, l);
-      fprintf_unfiltered (gdb_stdlog, ",r=");
-      fprint_frame_id (gdb_stdlog, r);
-      fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", inner);
-    }
+    fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l=%s,r=%s) -> %d }\n",
+                       l.to_string ().c_str (), r.to_string ().c_str (),
+                       inner);
 
   return inner;
 }
@@ -1048,7 +1034,7 @@ get_frame_func_if_available (frame_info *this_frame, CORE_ADDR *pc)
       CORE_ADDR addr_in_block;
 
       /* Make certain that this, and not the adjacent, function is
-         found.  */
+        found.  */
       if (!get_frame_address_in_block_if_available (this_frame, &addr_in_block))
        {
          next_frame->prev_func.status = CC_UNAVAILABLE;
@@ -1469,7 +1455,8 @@ deprecated_frame_register_read (frame_info *frame, int regnum,
 
 bool
 get_frame_register_bytes (frame_info *frame, int regnum,
-                         CORE_ADDR offset, int len, gdb_byte *myaddr,
+                         CORE_ADDR offset,
+                         gdb::array_view<gdb_byte> buffer,
                          int *optimizedp, int *unavailablep)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -1496,6 +1483,8 @@ get_frame_register_bytes (frame_info *frame, int regnum,
        break;  /* This register is not available on this architecture.  */
       maxsize += thissize;
     }
+
+  int len = buffer.size ();
   if (len > maxsize)
     error (_("Bad debug information detected: "
             "Attempt to read %d bytes from registers."), len);
@@ -1508,6 +1497,8 @@ get_frame_register_bytes (frame_info *frame, int regnum,
       if (curr_len > len)
        curr_len = len;
 
+      gdb_byte *myaddr = buffer.data ();
+
       if (curr_len == register_size (gdbarch, regnum))
        {
          enum lval_type lval;
@@ -1551,7 +1542,8 @@ get_frame_register_bytes (frame_info *frame, int regnum,
 
 void
 put_frame_register_bytes (struct frame_info *frame, int regnum,
-                         CORE_ADDR offset, int len, const gdb_byte *myaddr)
+                         CORE_ADDR offset,
+                         gdb::array_view<const gdb_byte> buffer)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
 
@@ -1562,6 +1554,7 @@ put_frame_register_bytes (struct frame_info *frame, int regnum,
       regnum++;
     }
 
+  int len = buffer.size ();
   /* Copy the data.  */
   while (len > 0)
     {
@@ -1570,6 +1563,7 @@ put_frame_register_bytes (struct frame_info *frame, int regnum,
       if (curr_len > len)
        curr_len = len;
 
+      const gdb_byte *myaddr = buffer.data ();
       if (curr_len == register_size (gdbarch, regnum))
        {
          put_frame_register (frame, regnum, myaddr);
@@ -1740,6 +1734,72 @@ restore_selected_frame (frame_id frame_id, int frame_level)
   selected_frame = nullptr;
 }
 
+/* See frame.h.  */
+
+void
+lookup_selected_frame (struct frame_id a_frame_id, int frame_level)
+{
+  struct frame_info *frame = NULL;
+  int count;
+
+  /* This either means there was no selected frame, or the selected
+     frame was the current frame.  In either case, select the current
+     frame.  */
+  if (frame_level == -1)
+    {
+      select_frame (get_current_frame ());
+      return;
+    }
+
+  /* select_frame never saves 0 in SELECTED_FRAME_LEVEL, so we
+     shouldn't see it here.  */
+  gdb_assert (frame_level > 0);
+
+  /* Restore by level first, check if the frame id is the same as
+     expected.  If that fails, try restoring by frame id.  If that
+     fails, nothing to do, just warn the user.  */
+
+  count = frame_level;
+  frame = find_relative_frame (get_current_frame (), &count);
+  if (count == 0
+      && frame != NULL
+      /* The frame ids must match - either both valid or both
+        outer_frame_id.  The latter case is not failsafe, but since
+        it's highly unlikely the search by level finds the wrong
+        frame, it's 99.9(9)% of the time (for all practical purposes)
+        safe.  */
+      && frame_id_eq (get_frame_id (frame), a_frame_id))
+    {
+      /* Cool, all is fine.  */
+      select_frame (frame);
+      return;
+    }
+
+  frame = frame_find_by_id (a_frame_id);
+  if (frame != NULL)
+    {
+      /* Cool, refound it.  */
+      select_frame (frame);
+      return;
+    }
+
+  /* Nothing else to do, the frame layout really changed.  Select the
+     innermost stack frame.  */
+  select_frame (get_current_frame ());
+
+  /* Warn the user.  */
+  if (frame_level > 0 && !current_uiout->is_mi_like_p ())
+    {
+      warning (_("Couldn't restore frame #%d in "
+                "current thread.  Bottom (innermost) frame selected:"),
+              frame_level);
+      /* For MI, we should probably have a notification about current
+        frame change.  But this error is not very likely, so don't
+        bother for now.  */
+      print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
+    }
+}
+
 bool
 has_stack_frames ()
 {
@@ -2134,6 +2194,23 @@ get_prev_frame_always_1 (struct frame_info *this_frame)
   if (get_frame_type (this_frame) == INLINE_FRAME)
     return get_prev_frame_if_no_cycle (this_frame);
 
+  /* If this_frame is the current frame, then compute and stash its
+     frame id prior to fetching and computing the frame id of the
+     previous frame.  Otherwise, the cycle detection code in
+     get_prev_frame_if_no_cycle() will not work correctly.  When
+     get_frame_id() is called later on, an assertion error will be
+     triggered in the event of a cycle between the current frame and
+     its previous frame.
+
+     Note we do this after the INLINE_FRAME check above.  That is
+     because the inline frame's frame id computation needs to fetch
+     the frame id of its previous real stack frame.  I.e., we need to
+     avoid recursion in that case.  This is OK since we're sure the
+     inline frame won't create a cycle with the real stack frame.  See
+     inline_frame_this_id.  */
+  if (this_frame->level == 0)
+    get_frame_id (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
@@ -2167,7 +2244,7 @@ get_prev_frame_always_1 (struct frame_info *this_frame)
       CORE_ADDR this_pc_in_block;
       struct minimal_symbol *morestack_msym;
       const char *morestack_name = NULL;
-      
+
       /* 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).minsym;
@@ -2263,9 +2340,9 @@ get_prev_frame_always (struct frame_info *this_frame)
              size_t size;
 
              /* The error needs to live as long as the frame does.
-                Allocate using stack local STOP_STRING then assign the
-                pointer to the frame, this allows the STOP_STRING on the
-                frame to be of type 'const char *'.  */
+                Allocate using stack local STOP_STRING then assign the
+                pointer to the frame, this allows the STOP_STRING on the
+                frame to be of type 'const char *'.  */
              size = ex.message->size () + 1;
              stop_string = (char *) frame_obstack_zalloc (size);
              memcpy (stop_string, ex.what (), size);
@@ -2387,9 +2464,8 @@ inside_main_func (frame_info *this_frame)
 
   /* Convert any function descriptor addresses into the actual function
      code address.  */
-  sym_addr
-    = gdbarch_convert_from_func_ptr_addr (get_frame_arch (this_frame),
-                                         sym_addr, current_top_target ());
+  sym_addr = gdbarch_convert_from_func_ptr_addr
+    (get_frame_arch (this_frame), sym_addr, current_inferior ()->top_target ());
 
   return sym_addr == get_frame_func (this_frame);
 }
@@ -2426,16 +2502,6 @@ get_prev_frame (struct frame_info *this_frame)
      something should be calling get_selected_frame() or
      get_current_frame().  */
   gdb_assert (this_frame != NULL);
-  
-  /* If this_frame is the current frame, then compute and stash
-     its frame id prior to fetching and computing the frame id of the
-     previous frame.  Otherwise, the cycle detection code in
-     get_prev_frame_if_no_cycle() will not work correctly.  When
-     get_frame_id() is called later on, an assertion error will
-     be triggered in the event of a cycle between the current
-     frame and its previous frame.  */
-  if (this_frame->level == 0)
-    get_frame_id (this_frame);
 
   frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
 
@@ -2445,9 +2511,9 @@ get_prev_frame (struct frame_info *this_frame)
      pcsqh register (space register for the instruction at the head of the
      instruction queue) cannot be written directly; the only way to set it
      is to branch to code that is in the target space.  In order to implement
-     frame dummies on HPUX, the called function is made to jump back to where 
-     the inferior was when the user function was called.  If gdb was inside 
-     the main function when we created the dummy frame, the dummy frame will 
+     frame dummies on HPUX, the called function is made to jump back to where
+     the inferior was when the user function was called.  If gdb was inside
+     the main function when we created the dummy frame, the dummy frame will
      point inside the main function.  */
   if (this_frame->level >= 0
       && get_frame_type (this_frame) == NORMAL_FRAME
@@ -2492,7 +2558,7 @@ get_prev_frame (struct frame_info *this_frame)
      That should provide a far better stopper than the current
      heuristics.  */
   /* NOTE: tausq/2004-10-09: this is needed if, for example, the compiler
-     applied tail-call optimizations to main so that a function called 
+     applied tail-call optimizations to main so that a function called
      from main returns directly to the caller of main.  Since we don't
      stop at main, we should at least stop at the entry point of the
      application.  */
@@ -2527,7 +2593,7 @@ get_prev_frame_id_by_id (struct frame_id id)
 {
   struct frame_id prev_id;
   struct frame_info *frame;
-  
+
   frame = frame_find_by_id (id);
 
   if (frame != NULL)
@@ -2818,9 +2884,9 @@ get_frame_address_space (struct frame_info *frame)
 
 void
 get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr,
-                 gdb_byte *buf, int len)
+                 gdb::array_view<gdb_byte> buffer)
 {
-  read_memory (addr, buf, len);
+  read_memory (addr, buffer.data (), buffer.size ());
 }
 
 LONGEST
@@ -2845,10 +2911,10 @@ get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr,
 
 bool
 safe_frame_unwind_memory (struct frame_info *this_frame,
-                         CORE_ADDR addr, gdb_byte *buf, int len)
+                         CORE_ADDR addr, gdb::array_view<gdb_byte> buffer)
 {
   /* NOTE: target_read_memory returns zero on success!  */
-  return target_read_memory (addr, buf, len) == 0;
+  return target_read_memory (addr, buffer.data (), buffer.size ()) == 0;
 }
 
 /* Architecture methods.  */
@@ -3099,17 +3165,18 @@ _initialize_frame ()
 
   frame_stash_create ();
 
-  gdb::observers::target_changed.attach (frame_observer_target_changed);
+  gdb::observers::target_changed.attach (frame_observer_target_changed,
+                                        "frame");
 
   add_basic_prefix_cmd ("backtrace", class_maintenance, _("\
 Set backtrace specific variables.\n\
 Configure backtrace variables such as the backtrace limit"),
-                       &set_backtrace_cmdlist, "set backtrace ",
+                       &set_backtrace_cmdlist,
                        0/*allow-unknown*/, &setlist);
   add_show_prefix_cmd ("backtrace", class_maintenance, _("\
 Show backtrace specific variables.\n\
 Show backtrace variables such as the backtrace limit."),
-                      &show_backtrace_cmdlist, "show backtrace ",
+                      &show_backtrace_cmdlist,
                       0/*allow-unknown*/, &showlist);
 
   add_setshow_uinteger_cmd ("limit", class_obscure,