[v3,2/3] gdb: factor out printing a table of solibs for info sharedlibrary

Message ID 20250411175022.2379494-3-guinevere@redhat.com
State New
Headers
Series Add some linker namespaces conveniences |

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 success Test passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed

Commit Message

Guinevere Larsen April 11, 2025, 5:50 p.m. UTC
  The next patch will add a new command that will print libraries in a
manner very similar to the existing "info sharedlibrary" command. To
make that patch simpler to review, this commit does the bulk of
refactoring work, since it ends up being a non-trivial diff to review.

No functional changes are expected after this commit.
---
 gdb/solib.c | 137 ++++++++++++++++++++++++++++------------------------
 1 file changed, 74 insertions(+), 63 deletions(-)
  

Patch

diff --git a/gdb/solib.c b/gdb/solib.c
index 1ba98137f5e..d641a24dc86 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1010,84 +1010,61 @@  solib_add (const char *pattern, int from_tty, int readsyms)
   }
 }
 
-/* Implement the "info sharedlibrary" command.  Walk through the
-   shared library list and print information about each attached
-   library matching PATTERN.  If PATTERN is elided, print them
-   all.  */
+/* Helper function for "info sharedlibrary" and "info namespace".
+   This receives a list of solibs to be printed, and prints a table
+   with all the relevant data.  If PRINT_NAMESPACE is true, figure out
+   the solib_ops of the current gdbarch, to calculate the namespace
+   that contains an solib.
+   Returns true if one or more solibs are missing debug information,
+   false otherwise.  */
 
 static void
-info_sharedlibrary_command (const char *pattern, int from_tty)
+print_solib_list_table (std::vector<const solib *> solib_list,
+			bool print_namespace)
 {
-  bool so_missing_debug_info = false;
-  int addr_width;
-  int nr_libs;
   gdbarch *gdbarch = current_inferior ()->arch ();
-  struct ui_out *uiout = current_uiout;
-
-  if (pattern)
-    {
-      char *re_err = re_comp (pattern);
-
-      if (re_err)
-	error (_ ("Invalid regexp: %s"), re_err);
-    }
-
   /* "0x", a little whitespace, and two hex digits per byte of pointers.  */
-  addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4);
-
-  update_solib_list (from_tty);
-
-  /* ui_out_emit_table table_emitter needs to know the number of rows,
-     so we need to make two passes over the libs.  */
+  int addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4);
+  const solib_ops *ops = gdbarch_so_ops (gdbarch);
+  struct ui_out *uiout = current_uiout;
+  bool so_missing_debug_info = false;
 
-  nr_libs = 0;
-  for (const solib &so : current_program_space->solibs ())
-    {
-      if (!so.so_name.empty ())
-	{
-	  if (pattern && !re_exec (so.so_name.c_str ()))
-	    continue;
-	  ++nr_libs;
-	}
-    }
+  /* There are 3 conditions for this command to print solib namespaces,
+     first PRINT_NAMESPACE has to be true, second the solib_ops has to
+     support multiple namespaces, and third there must be more than one
+     active namespace.  Fold all these into the PRINT_NAMESPACE condition.  */
+  print_namespace = print_namespace && ops->num_active_namespaces != nullptr
+		    && ops->num_active_namespaces () > 1;
 
-  /* How many columns the table should have.  If the inferior has
-     more than one namespace active, we need a column to show that.  */
   int num_cols = 4;
-  const solib_ops *ops = gdbarch_so_ops (gdbarch);
-  if (ops->num_active_namespaces != nullptr
-      && ops->num_active_namespaces () > 1)
+  if (print_namespace)
     num_cols++;
 
   {
-    ui_out_emit_table table_emitter (uiout, num_cols, nr_libs,
+    ui_out_emit_table table_emitter (uiout, num_cols, solib_list.size (),
 				     "SharedLibraryTable");
 
     /* The "- 1" is because ui_out adds one space between columns.  */
     uiout->table_header (addr_width - 1, ui_left, "from", "From");
     uiout->table_header (addr_width - 1, ui_left, "to", "To");
-    if (ops->num_active_namespaces != nullptr
-	&& ops->num_active_namespaces () > 1)
+    if (print_namespace)
       uiout->table_header (5, ui_left, "namespace", "NS");
     uiout->table_header (12 - 1, ui_left, "syms-read", "Syms Read");
     uiout->table_header (0, ui_noalign, "name", "Shared Object Library");
 
     uiout->table_body ();
 
-    for (const solib &so : current_program_space->solibs ())
+    for (const solib *so : solib_list)
       {
-	if (so.so_name.empty ())
-	  continue;
-
-	if (pattern && !re_exec (so.so_name.c_str ()))
+	if (so->so_name.empty ())
 	  continue;
 
 	ui_out_emit_tuple tuple_emitter (uiout, "lib");
 
-	if (so.addr_high != 0)
+	if (so->addr_high != 0)
 	  {
-	    uiout->field_core_addr ("from", gdbarch, so.addr_low);
-	    uiout->field_core_addr ("to", gdbarch, so.addr_high);
+	    uiout->field_core_addr ("from", gdbarch, so->addr_low);
+	    uiout->field_core_addr ("to", gdbarch, so->addr_high);
 	  }
 	else
 	  {
@@ -1095,12 +1072,11 @@  info_sharedlibrary_command (const char *pattern, int from_tty)
 	    uiout->field_skip ("to");
 	  }
 
-	if (ops->num_active_namespaces != nullptr
-	    && ops->num_active_namespaces ()> 1)
+	if (print_namespace)
 	  {
 	    try
 	      {
-		uiout->field_fmt ("namespace", "[[%d]]", ops->find_solib_ns (so));
+		uiout->field_fmt ("namespace", "[[%d]]", ops->find_solib_ns (*so));
 	      }
 	    catch (const gdb_exception_error &er)
 	      {
@@ -1109,33 +1085,68 @@  info_sharedlibrary_command (const char *pattern, int from_tty)
 	  }
 
 	if (!top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ()
-	    && so.symbols_loaded && !objfile_has_symbols (so.objfile))
+	    && so->symbols_loaded && !objfile_has_symbols (so->objfile))
 	  {
 	    so_missing_debug_info = true;
 	    uiout->field_string ("syms-read", "Yes (*)");
 	  }
 	else
-	  uiout->field_string ("syms-read", so.symbols_loaded ? "Yes" : "No");
+	  uiout->field_string ("syms-read", so->symbols_loaded ? "Yes" : "No");
 
-	uiout->field_string ("name", so.so_name, file_name_style.style ());
+	uiout->field_string ("name", so->so_name, file_name_style.style ());
 
 	uiout->text ("\n");
       }
   }
 
-  if (nr_libs == 0)
+  if (so_missing_debug_info)
+    uiout->message (_ ("(*): Shared library is missing "
+		       "debugging information.\n"));
+}
+
+/* Implement the "info sharedlibrary" command.  Walk through the
+   shared library list and print information about each attached
+   library matching PATTERN.  If PATTERN is elided, print them
+   all.  */
+
+static void
+info_sharedlibrary_command (const char *pattern, int from_tty)
+{
+  struct ui_out *uiout = current_uiout;
+
+  if (pattern)
+    {
+      char *re_err = re_comp (pattern);
+
+      if (re_err)
+	error (_ ("Invalid regexp: %s"), re_err);
+    }
+
+  update_solib_list (from_tty);
+
+  /* ui_out_emit_table table_emitter needs to know the number of rows,
+     so we need to make two passes over the libs.  */
+
+  std::vector<const solib *> print_libs;
+  for (const solib &so : current_program_space->solibs ())
+    {
+      if (!so.so_name.empty ())
+	{
+	  if (pattern && !re_exec (so.so_name.c_str ()))
+	    continue;
+	  print_libs.push_back (&so);
+	}
+    }
+
+  print_solib_list_table (print_libs, true);
+
+  if (print_libs.size () == 0)
     {
       if (pattern)
 	uiout->message (_ ("No shared libraries matched.\n"));
       else
 	uiout->message (_ ("No shared libraries loaded at this time.\n"));
     }
-  else
-    {
-      if (so_missing_debug_info)
-	uiout->message (_ ("(*): Shared library is missing "
-			   "debugging information.\n"));
-    }
 }
 
 /* See solib.h.  */