[binutils-gdb] gdb/solib: use owning_intrusive_list for solib list

Simon Marchi simark@sourceware.org
Fri Sep 13 11:44:50 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=edb09798f2cd60b72591da9fe5f2e1bee50c5d83

commit edb09798f2cd60b72591da9fe5f2e1bee50c5d83
Author: Simon Marchi <simon.marchi@efficios.com>
Date:   Mon Aug 12 13:09:05 2024 -0400

    gdb/solib: use owning_intrusive_list for solib list
    
    Functions implementing `solib_ops::current_sos` return a list of solib
    object, transferring the ownership to their callers.  However, the
    return type, `intrusive_list<solib>`, does not reflect that.
    
    Also, some of these functions build these lists incrementally, reading
    this from the target for each solib.  If a target read were to throw,
    for instance, the already created solibs would just be leaked.
    
    Change `solib_ops::current_sos` to return an owning_intrusive_list to
    address that.  Change `program_space::so_list` to be an
    owning_intrusive_list as well.  This also saves us doing a few manual
    deletes.
    
    Change-Id: I6e4071d49744874491625075136c59cce8e608d4
    Reviewed-by: Keith Seitz <keiths@redhat.com>

Diff:
---
 gdb/progspace.h    |  4 ++--
 gdb/solib-aix.c    | 14 ++++++--------
 gdb/solib-darwin.c | 13 ++++++-------
 gdb/solib-dsbt.c   | 13 ++++++-------
 gdb/solib-frv.c    | 14 ++++++--------
 gdb/solib-rocm.c   | 20 +++++++++-----------
 gdb/solib-svr4.c   | 43 +++++++++++++++++++------------------------
 gdb/solib-target.c | 15 ++++++---------
 gdb/solib.c        | 23 ++++++++++-------------
 gdb/solist.h       |  4 +++-
 10 files changed, 73 insertions(+), 90 deletions(-)

diff --git a/gdb/progspace.h b/gdb/progspace.h
index 82c0a743f32..999e7a39182 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -289,7 +289,7 @@ struct program_space
   struct objfile *objfile_for_address (CORE_ADDR address);
 
   /* Return the list of  all the solibs in this program space.  */
-  intrusive_list<solib> &solibs ()
+  owning_intrusive_list<solib> &solibs ()
   { return so_list; }
 
   /* Similar to `bfd_get_filename (exec_bfd ())` but in original form given
@@ -399,7 +399,7 @@ struct program_space
 
   /* List of shared objects mapped into this space.  Managed by
      solib.c.  */
-  intrusive_list<solib> so_list;
+  owning_intrusive_list<solib> so_list;
 
   /* Number of calls to solib_add.  */
   unsigned int solib_add_generation = 0;
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index 1c319c22223..926f1ed766d 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -444,7 +444,7 @@ solib_aix_solib_create_inferior_hook (int from_tty)
 
 /* Implement the "current_sos" solib_ops method.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 solib_aix_current_sos ()
 {
   std::optional<std::vector<lm_info_aix>> &library_list
@@ -452,14 +452,13 @@ solib_aix_current_sos ()
   if (!library_list.has_value ())
     return {};
 
-  intrusive_list<solib> sos;
+  owning_intrusive_list<solib> sos;
 
   /* Build a struct solib for each entry on the list.
      We skip the first entry, since this is the entry corresponding
      to the main executable, not a shared library.  */
   for (int ix = 1; ix < library_list->size (); ix++)
     {
-      solib *new_solib = new solib;
       std::string so_name;
 
       lm_info_aix &info = (*library_list)[ix];
@@ -481,12 +480,11 @@ solib_aix_current_sos ()
 				  info.member_name.c_str ());
 	}
 
-      new_solib->so_original_name = so_name;
-      new_solib->so_name = so_name;
-      new_solib->lm_info = std::make_unique<lm_info_aix> (info);
-
       /* Add it to the list.  */
-      sos.push_back (*new_solib);
+      auto &new_solib = sos.emplace_back ();
+      new_solib.so_original_name = so_name;
+      new_solib.so_name = so_name;
+      new_solib.lm_info = std::make_unique<lm_info_aix> (info);
     }
 
   return sos;
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index c7a7f624102..6c7d9065a65 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -212,7 +212,7 @@ open_symbol_file_object (int from_tty)
 
 /* Build a list of currently loaded shared objects.  See solib-svr4.c.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 darwin_current_sos ()
 {
   type *ptr_type
@@ -230,7 +230,7 @@ darwin_current_sos ()
 
   image_info_size = ptr_len * 3;
 
-  intrusive_list<solib> sos;
+  owning_intrusive_list<solib> sos;
 
   /* Read infos for each solib.
      The first entry was rumored to be the executable itself, but this is not
@@ -272,16 +272,15 @@ darwin_current_sos ()
 	break;
 
       /* Create and fill the new struct solib element.  */
-      solib *newobj = new solib;
+      auto &newobj = sos.emplace_back ();
 
       auto li = std::make_unique<lm_info_darwin> ();
 
-      newobj->so_name = file_path.get ();
-      newobj->so_original_name = newobj->so_name;
+      newobj.so_name = file_path.get ();
+      newobj.so_original_name = newobj.so_name;
       li->lm_addr = load_addr;
 
-      newobj->lm_info = std::move (li);
-      sos.push_back (*newobj);
+      newobj.lm_info = std::move (li);
     }
 
   return sos;
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index 2751ded40c5..360aede8f30 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -512,13 +512,13 @@ lm_base (void)
    themselves.  The declaration of `struct solib' says which fields
    we provide values for.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 dsbt_current_sos (void)
 {
   bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
   CORE_ADDR lm_addr;
   dsbt_info *info = get_dsbt_info (current_program_space);
-  intrusive_list<solib> sos;
+  owning_intrusive_list<solib> sos;
 
   /* Make sure that the main executable has been relocated.  This is
      required in order to find the address of the global offset table,
@@ -594,7 +594,7 @@ dsbt_current_sos (void)
 	      break;
 	    }
 
-	  solib *sop = new solib;
+	  auto &sop = sos.emplace_back ();
 	  auto li = std::make_unique<lm_info_dsbt> ();
 	  li->map = loadmap;
 	  /* Fetch the name.  */
@@ -612,12 +612,11 @@ dsbt_current_sos (void)
 		gdb_printf (gdb_stdlog, "current_sos: name = %s\n",
 			    name_buf.get ());
 
-	      sop->so_name = name_buf.get ();
-	      sop->so_original_name = sop->so_name;
+	      sop.so_name = name_buf.get ();
+	      sop.so_original_name = sop.so_name;
 	    }
 
-	  sop->lm_info = std::move (li);
-	  sos.push_back (*sop);
+	  sop.lm_info = std::move (li);
 	}
       else
 	{
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index 2ce35c4bc28..25873e6df60 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -306,12 +306,12 @@ lm_base (void)
 
 /* Implement the "current_sos" solib_ops method.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 frv_current_sos ()
 {
   bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
   CORE_ADDR lm_addr, mgot;
-  intrusive_list<solib> sos;
+  owning_intrusive_list<solib> sos;
 
   /* Make sure that the main executable has been relocated.  This is
      required in order to find the address of the global offset table,
@@ -377,12 +377,12 @@ frv_current_sos ()
 	      break;
 	    }
 
-	  solib *sop = new solib;
+	  auto &sop = sos.emplace_back ();
 	  auto li = std::make_unique<lm_info_frv> ();
 	  li->map = loadmap;
 	  li->got_value = got_addr;
 	  li->lm_addr = lm_addr;
-	  sop->lm_info = std::move (li);
+	  sop.lm_info = std::move (li);
 
 	  /* Fetch the name.  */
 	  addr = extract_unsigned_integer (lm_buf.l_name,
@@ -397,11 +397,9 @@ frv_current_sos ()
 	    warning (_("Can't read pathname for link map entry."));
 	  else
 	    {
-	      sop->so_name = name_buf.get ();
-	      sop->so_original_name = sop->so_name;
+	      sop.so_name = name_buf.get ();
+	      sop.so_original_name = sop.so_name;
 	    }
-
-	  sos.push_back (*sop);
 	}
       else
 	{
diff --git a/gdb/solib-rocm.c b/gdb/solib-rocm.c
index 9b995c7a3ab..156b36a4263 100644
--- a/gdb/solib-rocm.c
+++ b/gdb/solib-rocm.c
@@ -204,20 +204,18 @@ rocm_solib_handle_event ()
 
 /* Create so_list objects from rocm_so objects in SOS.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
 {
-  intrusive_list<solib> dst;
+  owning_intrusive_list<solib> dst;
 
   for (const rocm_so &so : sos)
     {
-      solib *newobj = new solib;
-      newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
+      auto &newobj = dst.emplace_back ();
 
-      newobj->so_name = so.name;
-      newobj->so_original_name = so.unique_name;
-
-      dst.push_back (*newobj);
+      newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
+      newobj.so_name = so.name;
+      newobj.so_original_name = so.unique_name;
     }
 
   return dst;
@@ -226,11 +224,11 @@ so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
 /* Build a list of `struct solib' objects describing the shared
    objects currently loaded in the inferior.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 rocm_solib_current_sos ()
 {
   /* First, retrieve the host-side shared library list.  */
-  intrusive_list<solib> sos = svr4_so_ops.current_sos ();
+  owning_intrusive_list<solib> sos = svr4_so_ops.current_sos ();
 
   /* Then, the device-side shared library list.  */
   std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;
@@ -238,7 +236,7 @@ rocm_solib_current_sos ()
   if (dev_sos.empty ())
     return sos;
 
-  intrusive_list<solib> dev_so_list = so_list_from_rocm_sos (dev_sos);
+  owning_intrusive_list<solib> dev_so_list = so_list_from_rocm_sos (dev_sos);
 
   if (sos.empty ())
     return dev_so_list;
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 5d232051403..928d6547a32 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -991,20 +991,18 @@ svr4_clear_so (const solib &so)
 
 /* Create the so_list objects equivalent to the svr4_sos in SOS.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
 {
-  intrusive_list<solib> dst;
+  owning_intrusive_list<solib> dst;
 
   for (const svr4_so &so : sos)
     {
-      struct solib *newobj = new struct solib;
+      auto &newobj = dst.emplace_back ();
 
-      newobj->so_name = so.name;
-      newobj->so_original_name = so.name;
-      newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
-
-      dst.push_back (*newobj);
+      newobj.so_name = so.name;
+      newobj.so_original_name = so.name;
+      newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
     }
 
   return dst;
@@ -1184,25 +1182,24 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
 /* If no shared library information is available from the dynamic
    linker, build a fallback list from other sources.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 svr4_default_sos (svr4_info *info)
 {
   if (!info->debug_loader_offset_p)
     return {};
 
-  solib *newobj = new solib;
   auto li = std::make_unique<lm_info_svr4> ();
 
   /* Nothing will ever check the other fields if we set l_addr_p.  */
   li->l_addr = li->l_addr_inferior = info->debug_loader_offset;
   li->l_addr_p = 1;
 
-  newobj->lm_info = std::move (li);
-  newobj->so_name = info->debug_loader_name;
-  newobj->so_original_name = newobj->so_name;
+  owning_intrusive_list<solib> sos;
+  auto &newobj = sos.emplace_back ();
 
-  intrusive_list<solib> sos;
-  sos.push_back (*newobj);
+  newobj.lm_info = std::move (li);
+  newobj.so_name = info->debug_loader_name;
+  newobj.so_original_name = newobj.so_name;
 
   return sos;
 }
@@ -1373,10 +1370,10 @@ svr4_current_sos_direct (struct svr4_info *info)
 
 /* Collect sos read and stored by the probes interface.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 svr4_collect_probes_sos (svr4_info *info)
 {
-  intrusive_list<solib> res;
+  owning_intrusive_list<solib> res;
 
   for (const auto &tuple : info->solib_lists)
     {
@@ -1390,10 +1387,10 @@ svr4_collect_probes_sos (svr4_info *info)
 /* Implement the main part of the "current_sos" solib_ops
    method.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 svr4_current_sos_1 (svr4_info *info)
 {
-  intrusive_list<solib> sos;
+  owning_intrusive_list<solib> sos;
 
   /* If we're using the probes interface, we can use the cache as it will
      be maintained by probe update/reload actions.  */
@@ -1417,11 +1414,11 @@ svr4_current_sos_1 (svr4_info *info)
 
 /* Implement the "current_sos" solib_ops method.  */
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 svr4_current_sos ()
 {
   svr4_info *info = get_svr4_info (current_program_space);
-  intrusive_list<solib> sos = svr4_current_sos_1 (info);
+  owning_intrusive_list<solib> sos = svr4_current_sos_1 (info);
   struct mem_range vsyscall_range;
 
   /* Filter out the vDSO module, if present.  Its symbol file would
@@ -1478,9 +1475,7 @@ svr4_current_sos ()
 
 	  if (vsyscall_range.contains (li->l_ld))
 	    {
-	      auto next = sos.erase (so);
-	      delete &*so;
-	      so = next;
+	      so = sos.erase (so);
 	      break;
 	    }
 
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 3fffa7c2595..8f73d5df55b 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -226,10 +226,10 @@ solib_target_parse_libraries (const char *library)
 }
 #endif
 
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
 solib_target_current_sos (void)
 {
-  intrusive_list<solib> sos;
+  owning_intrusive_list<solib> sos;
 
   /* Fetch the list of shared libraries.  */
   std::optional<gdb::char_vector> library_document
@@ -245,15 +245,12 @@ solib_target_current_sos (void)
   /* Build a struct solib for each entry on the list.  */
   for (lm_info_target_up &info : library_list)
     {
-      solib *new_solib = new solib;
+      auto &new_solib = sos.emplace_back ();
 
       /* We don't need a copy of the name in INFO anymore.  */
-      new_solib->so_name = std::move (info->name);
-      new_solib->so_original_name = new_solib->so_name;
-      new_solib->lm_info = std::move (info);
-
-      /* Add it to the list.  */
-      sos.push_back (*new_solib);
+      new_solib.so_name = std::move (info->name);
+      new_solib.so_original_name = new_solib.so_name;
+      new_solib.lm_info = std::move (info);
     }
 
   return sos;
diff --git a/gdb/solib.c b/gdb/solib.c
index b123be302bc..5c926def715 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -755,8 +755,8 @@ update_solib_list (int from_tty)
      the time we're done walking GDB's list, the inferior's list
      contains only the new shared objects, which we then add.  */
 
-  intrusive_list<solib> inferior = ops->current_sos ();
-  intrusive_list<solib>::iterator gdb_iter
+  owning_intrusive_list<solib> inferior = ops->current_sos ();
+  owning_intrusive_list<solib>::iterator gdb_iter
     = current_program_space->so_list.begin ();
   while (gdb_iter != current_program_space->so_list.end ())
     {
@@ -785,7 +785,6 @@ update_solib_list (int from_tty)
       if (inferior_iter != inferior.end ())
 	{
 	  inferior.erase (inferior_iter);
-	  delete &*inferior_iter;
 	  ++gdb_iter;
 	}
 
@@ -798,9 +797,6 @@ update_solib_list (int from_tty)
 
 	  current_program_space->deleted_solibs.push_back (gdb_iter->so_name);
 
-	  intrusive_list<solib>::iterator gdb_iter_next
-	    = current_program_space->so_list.erase (gdb_iter);
-
 	  /* Unless the user loaded it explicitly, free SO's objfile.  */
 	  if (gdb_iter->objfile != nullptr
 	      && !(gdb_iter->objfile->flags & OBJF_USERLOADED)
@@ -811,8 +807,7 @@ update_solib_list (int from_tty)
 	     sections from so.abfd; remove them.  */
 	  current_program_space->remove_target_sections (&*gdb_iter);
 
-	  delete &*gdb_iter;
-	  gdb_iter = gdb_iter_next;
+	  gdb_iter = current_program_space->so_list.erase (gdb_iter);
 	}
     }
 
@@ -1151,11 +1146,13 @@ clear_solib (program_space *pspace)
 
   disable_breakpoints_in_shlibs (pspace);
 
-  pspace->so_list.clear_and_dispose ([pspace] (solib *so) {
-    notify_solib_unloaded (pspace, *so);
-    pspace->remove_target_sections (so);
-    delete so;
-  });
+  for (solib &so : pspace->so_list)
+    {
+      notify_solib_unloaded (pspace, so);
+      pspace->remove_target_sections (&so);
+    };
+
+  pspace->so_list.clear ();
 
   if (ops->clear_solib != nullptr)
     ops->clear_solib (pspace);
diff --git a/gdb/solist.h b/gdb/solist.h
index b898ae31899..336bb011b2e 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -20,9 +20,11 @@
 #define SOLIST_H
 
 #define SO_NAME_MAX_PATH_SIZE 512	/* FIXME: Should be dynamic */
+
 /* For domain_enum domain.  */
 #include "symtab.h"
 #include "gdb_bfd.h"
+#include "gdbsupport/owning_intrusive_list.h"
 #include "target-section.h"
 
 /* Base class for target-specific link map information.  */
@@ -119,7 +121,7 @@ struct solib_ops
      inferior --- we don't examine any of the shared library files
      themselves.  The declaration of `struct solib' says which fields
      we provide values for.  */
-  intrusive_list<solib> (*current_sos) ();
+  owning_intrusive_list<solib> (*current_sos) ();
 
   /* Find, open, and read the symbols for the main executable.  If
      FROM_TTY is non-zero, allow messages to be printed.  */


More information about the Gdb-cvs mailing list