Change how DWARF index writer finds address map
[deliverable/binutils-gdb.git] / gdb / frame.c
index 6bfa31e630e44d9c3efcb1243fcb5b1db220d951..4578b1acab3e21d4d10e6db6151d396d9bb1cf63 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.
 
@@ -317,17 +317,15 @@ frame_stash_invalidate (void)
 /* See frame.h  */
 scoped_restore_selected_frame::scoped_restore_selected_frame ()
 {
-  m_fid = get_frame_id (get_selected_frame (NULL));
+  m_lang = current_language->la_language;
+  save_selected_frame (&m_fid, &m_level);
 }
 
 /* See frame.h  */
 scoped_restore_selected_frame::~scoped_restore_selected_frame ()
 {
-  frame_info *frame = frame_find_by_id (m_fid);
-  if (frame == NULL)
-    warning (_("Unable to restore previously selected frame."));
-  else
-    select_frame (frame);
+  restore_selected_frame (m_fid, m_level);
+  set_language (m_lang);
 }
 
 /* Flag to control debugging.  */
@@ -603,7 +601,7 @@ compute_frame_id (struct frame_info *fi)
   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;
@@ -679,7 +677,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;
 
@@ -1050,7 +1048,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;
@@ -1471,7 +1469,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);
@@ -1498,6 +1497,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);
@@ -1510,6 +1511,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;
@@ -1553,7 +1556,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);
 
@@ -1564,6 +1568,7 @@ put_frame_register_bytes (struct frame_info *frame, int regnum,
       regnum++;
     }
 
+  int len = buffer.size ();
   /* Copy the data.  */
   while (len > 0)
     {
@@ -1572,6 +1577,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);
@@ -1685,10 +1691,129 @@ get_current_frame (void)
 }
 
 /* The "selected" stack frame is used by default for local and arg
-   access.  May be zero, for no selected frame.  */
-
+   access.
+
+   The "single source of truth" for the selected frame is the
+   SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL pair.
+
+   Frame IDs can be saved/restored across reinitializing the frame
+   cache, while frame_info pointers can't (frame_info objects are
+   invalidated).  If we know the corresponding frame_info object, it
+   is cached in SELECTED_FRAME.
+
+   If SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL are null_frame_id / -1,
+   and the target has stack and is stopped, the selected frame is the
+   current (innermost) frame.  This means that SELECTED_FRAME_LEVEL is
+   never 0 and SELECTED_FRAME_ID is never the ID of the innermost
+   frame.
+
+   If SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL are null_frame_id / -1,
+   and the target has no stack or is executing, then there's no
+   selected frame.  */
+static frame_id selected_frame_id = null_frame_id;
+static int selected_frame_level = -1;
+
+/* The cached frame_info object pointing to the selected frame.
+   Looked up on demand by get_selected_frame.  */
 static struct frame_info *selected_frame;
 
+/* See frame.h.  */
+
+void
+save_selected_frame (frame_id *frame_id, int *frame_level)
+  noexcept
+{
+  *frame_id = selected_frame_id;
+  *frame_level = selected_frame_level;
+}
+
+/* See frame.h.  */
+
+void
+restore_selected_frame (frame_id frame_id, int frame_level)
+  noexcept
+{
+  /* save_selected_frame never returns level == 0, so we shouldn't see
+     it here either.  */
+  gdb_assert (frame_level != 0);
+
+  /* FRAME_ID can be null_frame_id only IFF frame_level is -1.  */
+  gdb_assert ((frame_level == -1 && !frame_id_p (frame_id))
+             || (frame_level != -1 && frame_id_p (frame_id)));
+
+  selected_frame_id = frame_id;
+  selected_frame_level = frame_level;
+
+  /* Will be looked up later by get_selected_frame.  */
+  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 ()
 {
@@ -1716,9 +1841,7 @@ has_stack_frames ()
   return true;
 }
 
-/* Return the selected frame.  Always non-NULL (unless there isn't an
-   inferior sufficient for creating a frame) in which case an error is
-   thrown.  */
+/* See frame.h.  */
 
 struct frame_info *
 get_selected_frame (const char *message)
@@ -1727,24 +1850,14 @@ get_selected_frame (const char *message)
     {
       if (message != NULL && !has_stack_frames ())
        error (("%s"), message);
-      /* Hey!  Don't trust this.  It should really be re-finding the
-        last selected frame of the currently selected thread.  This,
-        though, is better than nothing.  */
-      select_frame (get_current_frame ());
+
+      lookup_selected_frame (selected_frame_id, selected_frame_level);
     }
   /* There is always a frame.  */
   gdb_assert (selected_frame != NULL);
   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().  */
@@ -1757,12 +1870,42 @@ deprecated_safe_get_selected_frame (void)
   return get_selected_frame (NULL);
 }
 
-/* Select frame FI (or NULL - to invalidate the current frame).  */
+/* Select frame FI (or NULL - to invalidate the selected frame).  */
 
 void
 select_frame (struct frame_info *fi)
 {
   selected_frame = fi;
+  selected_frame_level = frame_relative_level (fi);
+  if (selected_frame_level == 0)
+    {
+      /* Treat the current frame especially -- we want to always
+        save/restore it without warning, even if the frame ID changes
+        (see lookup_selected_frame).  E.g.:
+
+         // The current frame is selected, the target had just stopped.
+         {
+           scoped_restore_selected_frame restore_frame;
+           some_operation_that_changes_the_stack ();
+         }
+         // scoped_restore_selected_frame's dtor runs, but the
+         // original frame_id can't be found.  No matter whether it
+         // is found or not, we still end up with the now-current
+         // frame selected.  Warning in lookup_selected_frame in this
+         // case seems pointless.
+
+        Also get_frame_id may access the target's registers/memory,
+        and thus skipping get_frame_id optimizes the common case.
+
+        Saving the selected frame this way makes get_selected_frame
+        and restore_current_frame return/re-select whatever frame is
+        the innermost (current) then.  */
+      selected_frame_level = -1;
+      selected_frame_id = null_frame_id;
+    }
+  else
+    selected_frame_id = get_frame_id (fi);
+
   /* NOTE: cagney/2002-05-04: FI can be NULL.  This occurs when the
      frame is being invalidated.  */
 
@@ -2065,6 +2208,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
@@ -2098,7 +2258,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;
@@ -2194,9 +2354,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);
@@ -2292,13 +2452,14 @@ frame_debug_got_null_frame (struct frame_info *this_frame,
 static bool
 inside_main_func (frame_info *this_frame)
 {
-  if (symfile_objfile == nullptr)
+  if (current_program_space->symfile_object_file == nullptr)
     return false;
 
   CORE_ADDR sym_addr;
   const char *name = main_name ();
   bound_minimal_symbol msymbol
-    = lookup_minimal_symbol (name, NULL, symfile_objfile);
+    = lookup_minimal_symbol (name, NULL,
+                            current_program_space->symfile_object_file);
   if (msymbol.minsym == nullptr)
     {
       /* In some language (for example Fortran) there will be no minimal
@@ -2356,16 +2517,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);
 
@@ -2375,9 +2526,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
@@ -2422,7 +2573,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.  */
@@ -2457,7 +2608,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)
@@ -2748,9 +2899,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
@@ -2775,10 +2926,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.  */
This page took 0.02863 seconds and 4 git commands to generate.