[PATCHv6,4/4] gdb: cache program space entry point information

Message ID aec2d2a625b517cda11fa79fc8ca84c7cd3a64cf.1783693321.git.aburgess@redhat.com
State New
Headers
Series gdb: allow 'until' to work in outermost frame |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm fail Test failed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed

Commit Message

Andrew Burgess July 10, 2026, 2:24 p.m. UTC
  After the previous two patches, every time that GDB unwinds a frame
there are now two places where we check if the frame is an entry point
frame, these are in get_prev_frame and get_prev_frame_always, look for
the calls to `inside_entry_func`, which then calls
program_space::get_entry_point_info.

The calls to program_space::get_entry_point_info are not crazy
expensive, but they are not free either, there are reads from target
memory to read the auxv vector and the entry address offset, so on
remote targets this could introduce a small delay, especially as this
occurs twice per frame now.

However, the information returned by
program_space::get_entry_point_info is not expected to change from one
call to the next.  This information should be a property of the
executable and libraries, so we really only need to figure it out
once.

This commit caches the entry point information within program_space,
clearing it whenever an inferior starts or exits, or whenever the
executable is updated.  After clearing GDB will compute, and cache the
updated information the next time it is needed, which will be whenever
GDB needs to unwind a frame.

It will be possible to observe this change by, for example, monitoring
the remote target packets, but as far as the normal GDB output is
concerned, there should be no user visible changes after this commit.
---
 gdb/progspace.c | 34 +++++++++++++++++++++++++++++++---
 gdb/progspace.h |  9 ++++++++-
 2 files changed, 39 insertions(+), 4 deletions(-)
  

Comments

Simon Marchi July 10, 2026, 5:07 p.m. UTC | #1
On 7/10/26 10:24 AM, Andrew Burgess wrote:
>  void
>  initialize_progspace ()
>  {
> +  gdb::observers::inferior_created.attach
> +    (clear_cached_entry_point_info_for_inferior, "program-space");
> +  gdb::observers::inferior_exit.attach
> +    (clear_cached_entry_point_info_for_inferior, "program-space");
> +  gdb::observers::executable_changed.attach
> +    (clear_cached_entry_point_info_for_pspace, "program-space");

inferior_execd too?

Simon
  

Patch

diff --git a/gdb/progspace.c b/gdb/progspace.c
index 26e16cae8d0..c1f3044f4c5 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -289,9 +289,12 @@  program_space::exec_entry_point_address () const
 
 /* See progspace.h.  */
 
-program_space::entry_point_info
+const program_space::entry_point_info &
 program_space::get_entry_point_info () const
 {
+  if (m_entry_point_info.has_value ())
+    return m_entry_point_info.value ();
+
   std::optional<CORE_ADDR> exec_entry_address
     = this->exec_entry_point_address_if_available ();
 
@@ -299,8 +302,9 @@  program_space::get_entry_point_info () const
   if (m_solib_ops != nullptr)
     inferior_entry_address = m_solib_ops->inferior_entry_point_address ();
 
-  return entry_point_info (std::move (inferior_entry_address),
-			   std::move (exec_entry_address));
+  m_entry_point_info.emplace (std::move (inferior_entry_address),
+			      std::move (exec_entry_address));
+  return m_entry_point_info.value ();
 }
 
 /* Implement the 'maint info entry-address' command.  */
@@ -538,11 +542,35 @@  program_space::clear_solib_cache ()
   deleted_solibs.clear ();
 }
 
+/* Clear cached entry point information in the program space of INF.  */
+
+static void
+clear_cached_entry_point_info_for_inferior (inferior *inf)
+{
+  inf->pspace->clear_cached_entry_point_info ();
+}
+
+/* Clear cached entry point information in the program space PSPACE.  */
+
+static void
+clear_cached_entry_point_info_for_pspace (program_space *pspace,
+					  bool /* reload */)
+{
+  pspace->clear_cached_entry_point_info ();
+}
+
 /* See progspace.h.  */
 
 void
 initialize_progspace ()
 {
+  gdb::observers::inferior_created.attach
+    (clear_cached_entry_point_info_for_inferior, "program-space");
+  gdb::observers::inferior_exit.attach
+    (clear_cached_entry_point_info_for_inferior, "program-space");
+  gdb::observers::executable_changed.attach
+    (clear_cached_entry_point_info_for_pspace, "program-space");
+
   add_cmd ("program-spaces", class_maintenance,
 	   maintenance_info_program_spaces_command,
 	   _("Info about currently known program spaces."),
diff --git a/gdb/progspace.h b/gdb/progspace.h
index d75379fe621..407d2595136 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -369,7 +369,11 @@  struct program_space
   /* Return information about the entry point in the main executable, and
      the entry point for the inferior, which might be different from the
      main executable.  */
-  entry_point_info get_entry_point_info () const;
+  const entry_point_info &get_entry_point_info () const;
+
+  /* Clear any cached entry point information.  */
+  void clear_cached_entry_point_info ()
+  { m_entry_point_info.reset (); }
 
   /* If there is a valid and known entry point in the main executable of
      this program space, return it.  Otherwise return an empty optional.  */
@@ -462,6 +466,9 @@  struct program_space
 
   /* See `exec_filename`.  */
   gdb::unique_xmalloc_ptr<char> m_exec_filename;
+
+  /* Cached entry point information.  See get_entry_point_info.  */
+  mutable std::optional<entry_point_info> m_entry_point_info;
 };
 
 /* The list of all program spaces.  There's always at least one.  */