[PATCH v4 08/10] gdb: add objfile -> solib backlink

Simon Marchi <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
From: Simon Marchi <[email protected]>

The following "multiple solib_ops" patch will require accessing the
solib(s) related to an objfile fairly often.  To make that easier, add
an objfile to solib backlink.

However, I learned that there may be more than one solib linked to one
objfile.  The only case I am aware of is the dynamic linker itself
(ld-linux.so), where the same instance (same load address) appears in
all namespaces.  We get one solib per "view" of that library, but they
all point to the same objfile.  So this backlink is actually a vector.

Rename find_solib_for_objfile to find_one_solib_for_objfile to reflect
that this function returns just one of possible multiple solibs for the
given objfile (if that ever matters).  To be clear, this doesn't change
its behavior, this is what it was doing before this patch.

Change-Id: I427d19407fdbc274b1790e0cae3004ee5fdbea72
---
 gdb/objfiles.h   | 25 +++++++++++++++++++++++++
 gdb/solib-svr4.c | 16 ++++++----------
 gdb/solib.c      | 13 +++++++++----
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 406ab36b39d6..fa265f83b792 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -450,6 +450,27 @@ struct objfile : intrusive_list_node<objfile>
   /* Return the program space associated with this objfile.  */
   program_space *pspace () { return m_pspace; }
 
+  /* Return the first solib associated to this objfile, or nullptr if there are
+     none.  */
+  solib *first_solib ()
+  { return !m_solibs.empty () ? m_solibs[0] : nullptr; }
+
+  /* Add SOLIB to the list of solibs associated to this objfile.  */
+  void add_solib (solib &solib)
+  {
+    gdb_assert (std::find (m_solibs.begin (), m_solibs.end (), &solib)
+		== m_solibs.end ());
+    m_solibs.emplace_back (&solib);
+  }
+
+  /* Remove SOLIB from the list of solibs associated to this objfile.  */
+  void remove_solib (solib &solib)
+  {
+    auto it = std::find (m_solibs.begin (), m_solibs.end (), &solib);
+    gdb_assert (it != m_solibs.end ());
+    m_solibs.erase (it);
+  }
+
   using compunit_symtab_iterator
     = owning_intrusive_list<compunit_symtab>::iterator;
   using compunit_symtab_range = iterator_range<compunit_symtab_iterator>;
@@ -702,6 +723,10 @@ struct objfile : intrusive_list_node<objfile>
 
   program_space *m_pspace;
 
+  /* The solibs associated to this objfile.  This is a 1 objfile to N solibs
+     relationship (see solib.c for details).  */
+  std::vector<solib *> m_solibs;
+
 public:
   /* The object file's BFD.  Can be null if the objfile contains only
      minimal symbols (e.g. the run time common symbols for SunOS4) or
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 35c81000b10a..8b61517c326f 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -3592,10 +3592,10 @@ lp64_svr4_solib_ops::fetch_link_map_offsets () const
 }
 
 
-/* Return the DSO matching OBJFILE or nullptr if none can be found.  */
+/* Return one solib matching OBJFILE or nullptr if none can be found.  */
 
-static const solib *
-find_solib_for_objfile (struct objfile *objfile)
+static solib *
+find_one_solib_for_objfile (struct objfile *objfile)
 {
   if (objfile == nullptr)
     return nullptr;
@@ -3605,11 +3605,7 @@ find_solib_for_objfile (struct objfile *objfile)
   if (objfile->separate_debug_objfile_backlink != nullptr)
     objfile = objfile->separate_debug_objfile_backlink;
 
-  for (const solib &so : current_program_space->solibs ())
-    if (so.objfile == objfile)
-      return &so;
-
-  return nullptr;
+  return objfile->first_solib ();
 }
 
 /* Return the address of the r_debug object for the namespace containing
@@ -3676,7 +3672,7 @@ svr4_solib_ops::iterate_over_objfiles_in_search_order
      r_debug object, defaulting to the initial namespace.  */
   svr4_info *info = get_svr4_info (current_program_space);
   CORE_ADDR default_debug_base = this->default_debug_base (info);
-  const solib *curr_solib = find_solib_for_objfile (current_objfile);
+  const solib *curr_solib = find_one_solib_for_objfile (current_objfile);
   CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib);
   if (debug_base == 0)
     debug_base = default_debug_base;
@@ -3691,7 +3687,7 @@ svr4_solib_ops::iterate_over_objfiles_in_search_order
 	 If we fail, e.g. for manually added symbol files or for the main
 	 executable, we assume that they were added to the initial
 	 namespace.  */
-      const solib *solib = find_solib_for_objfile (&objfile);
+      const solib *solib = find_one_solib_for_objfile (&objfile);
       CORE_ADDR solib_base = find_debug_base_for_solib (solib);
       if (solib_base == 0)
 	solib_base = default_debug_base;
diff --git a/gdb/solib.c b/gdb/solib.c
index 6afa97e1aed5..b9b0f11cb477 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -650,6 +650,7 @@ solib_read_symbols (solib &so, symfile_add_flags flags)
 	  so.objfile->addr_low = so.addr_low;
 	}
 
+      so.objfile->add_solib (so);
       so.symbols_loaded = true;
     }
   catch (const gdb_exception_error &e)
@@ -715,10 +716,14 @@ remove_solib (program_space *pspace,
   notify_solib_unloaded (pspace, *solib_it, still_in_use, false);
 
   /* Unless the user loaded it explicitly, free SO's objfile.  */
-  if (solib_it->objfile != nullptr
-      && !(solib_it->objfile->flags & OBJF_USERLOADED)
-      && !still_in_use)
-    solib_it->objfile->unlink ();
+  if (solib_it->objfile != nullptr)
+    {
+      /* Remove the objfile -> solib backlink.  */
+      solib_it->objfile->remove_solib (*solib_it);
+
+      if (!(solib_it->objfile->flags & OBJF_USERLOADED) && !still_in_use)
+	solib_it->objfile->unlink ();
+    }
 
   pspace->deleted_solibs.push_back (solib_it->name);
 
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.