gdb/mi: remove warning about mi1
[binutils-gdb.git] / gdb / solib-svr4.c
index ca98a812f3654acaceff7ecad8ff8841457d7e89..f5fdbc742e7ee8e8f0261bf6bba99f19d05210ab 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 1990-2022 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    This file is part of GDB.
 
 #include "gdb_bfd.h"
 #include "probe.h"
 
 #include "gdb_bfd.h"
 #include "probe.h"
 
+#include <map>
+
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
 static void svr4_relocate_main_executable (void);
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
 static void svr4_relocate_main_executable (void);
-static void svr4_free_library_list (void *p_list);
+static void svr4_free_library_list (so_list *solist);
 static void probes_table_remove_objfile_probes (struct objfile *objfile);
 static void probes_table_remove_objfile_probes (struct objfile *objfile);
-static void svr4_iterate_over_objfiles_in_search_order (
-  struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype *cb,
-  void *cb_data, struct objfile *objfile);
+static void svr4_iterate_over_objfiles_in_search_order
+  (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
+   objfile *current_objfile);
 
 
 /* On SVR4 systems, a list of symbols in the dynamic linker where
 
 
 /* On SVR4 systems, a list of symbols in the dynamic linker where
@@ -174,7 +176,16 @@ svr4_same_1 (const char *gdb_so_name, const char *inferior_so_name)
 static int
 svr4_same (struct so_list *gdb, struct so_list *inferior)
 {
 static int
 svr4_same (struct so_list *gdb, struct so_list *inferior)
 {
-  return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
+  if (!svr4_same_1 (gdb->so_original_name, inferior->so_original_name))
+    return false;
+
+  /* There may be different instances of the same library, in different
+     namespaces.  Each instance, however, must have been loaded at a
+     different address so its relocation offset would be different.  */
+  const lm_info_svr4 *lmg = (const lm_info_svr4 *) gdb->lm_info;
+  const lm_info_svr4 *lmi = (const lm_info_svr4 *) inferior->lm_info;
+
+  return (lmg->l_addr_inferior == lmi->l_addr_inferior);
 }
 
 static std::unique_ptr<lm_info_svr4>
 }
 
 static std::unique_ptr<lm_info_svr4>
@@ -329,7 +340,7 @@ struct svr4_info
   svr4_info () = default;
   ~svr4_info ();
 
   svr4_info () = default;
   ~svr4_info ();
 
-  /* Base of dynamic linker structures.  */
+  /* Base of dynamic linker structures in default namespace.  */
   CORE_ADDR debug_base = 0;
 
   /* Validity flag for debug_loader_offset.  */
   CORE_ADDR debug_base = 0;
 
   /* Validity flag for debug_loader_offset.  */
@@ -341,7 +352,7 @@ struct svr4_info
   /* Name of the dynamic linker, valid if debug_loader_offset_p.  */
   char *debug_loader_name = nullptr;
 
   /* Name of the dynamic linker, valid if debug_loader_offset_p.  */
   char *debug_loader_name = nullptr;
 
-  /* Load map address for the main executable.  */
+  /* Load map address for the main executable in default namespace.  */
   CORE_ADDR main_lm_addr = 0;
 
   CORE_ADDR interp_text_sect_low = 0;
   CORE_ADDR main_lm_addr = 0;
 
   CORE_ADDR interp_text_sect_low = 0;
@@ -349,9 +360,9 @@ struct svr4_info
   CORE_ADDR interp_plt_sect_low = 0;
   CORE_ADDR interp_plt_sect_high = 0;
 
   CORE_ADDR interp_plt_sect_low = 0;
   CORE_ADDR interp_plt_sect_high = 0;
 
-  /* Nonzero if the list of objects was last obtained from the target
+  /* True if the list of objects was last obtained from the target
      via qXfer:libraries-svr4:read.  */
      via qXfer:libraries-svr4:read.  */
-  int using_xfer = 0;
+  bool using_xfer = false;
 
   /* Table of struct probe_and_action instances, used by the
      probes-based interface to map breakpoint addresses to probes
 
   /* Table of struct probe_and_action instances, used by the
      probes-based interface to map breakpoint addresses to probes
@@ -359,13 +370,34 @@ struct svr4_info
      probe_and_action->prob->address.  */
   htab_up probes_table;
 
      probe_and_action->prob->address.  */
   htab_up probes_table;
 
-  /* List of objects loaded into the inferior, used by the probes-
-     based interface.  */
-  struct so_list *solib_list = nullptr;
+  /* List of objects loaded into the inferior per namespace, used by the
+     probes-based interface.
+
+     The namespace is represented by the address of its corresponding
+     r_debug[_ext] object.  We get the namespace id as argument to the
+     'reloc_complete' probe but we don't get it when scanning the load map
+     on attach.
+
+     The r_debug[_ext] objects may move when ld.so itself moves.  In that
+     case, we expect also the global _r_debug to move so we can detect
+     this and reload everything.  The r_debug[_ext] objects are not
+     expected to move individually.
+
+     The special entry zero is reserved for a linear list to support
+     gdbstubs that do not support namespaces.  */
+  std::map<CORE_ADDR, so_list *> solib_lists;
 };
 
 /* Per-program-space data key.  */
 };
 
 /* Per-program-space data key.  */
-static const struct program_space_key<svr4_info> solib_svr4_pspace_data;
+static const registry<program_space>::key<svr4_info> solib_svr4_pspace_data;
+
+/* Return whether DEBUG_BASE is the default namespace of INFO.  */
+
+static bool
+svr4_is_default_namespace (const svr4_info *info, CORE_ADDR debug_base)
+{
+  return (debug_base == info->debug_base);
+}
 
 /* Free the probes table.  */
 
 
 /* Free the probes table.  */
 
@@ -375,18 +407,21 @@ free_probes_table (struct svr4_info *info)
   info->probes_table.reset (nullptr);
 }
 
   info->probes_table.reset (nullptr);
 }
 
-/* Free the solib list.  */
+/* Free the solib lists for all namespaces.  */
 
 static void
 
 static void
-free_solib_list (struct svr4_info *info)
+free_solib_lists (svr4_info *info)
 {
 {
-  svr4_free_library_list (&info->solib_list);
-  info->solib_list = NULL;
+  for (const std::pair<CORE_ADDR, so_list *> tuple
+        : info->solib_lists)
+    svr4_free_library_list (tuple.second);
+
+  info->solib_lists.clear ();
 }
 
 svr4_info::~svr4_info ()
 {
 }
 
 svr4_info::~svr4_info ()
 {
-  free_solib_list (this);
+  free_solib_lists (this);
 }
 
 /* Get the svr4 data for program space PSPACE.  If none is found yet, add it now.
 }
 
 /* Get the svr4 data for program space PSPACE.  If none is found yet, add it now.
@@ -428,14 +463,11 @@ read_program_header (int type, int *p_arch_size, CORE_ADDR *base_addr)
   int pt_phdr_p = 0;
 
   /* Get required auxv elements from target.  */
   int pt_phdr_p = 0;
 
   /* Get required auxv elements from target.  */
-  if (target_auxv_search (current_inferior ()->top_target (),
-                         AT_PHDR, &at_phdr) <= 0)
+  if (target_auxv_search (AT_PHDR, &at_phdr) <= 0)
     return {};
     return {};
-  if (target_auxv_search (current_inferior ()->top_target (),
-                         AT_PHENT, &at_phent) <= 0)
+  if (target_auxv_search (AT_PHENT, &at_phent) <= 0)
     return {};
     return {};
-  if (target_auxv_search (current_inferior ()->top_target (),
-                         AT_PHNUM, &at_phnum) <= 0)
+  if (target_auxv_search (AT_PHNUM, &at_phnum) <= 0)
     return {};
   if (!at_phdr || !at_phnum)
     return {};
     return {};
   if (!at_phdr || !at_phnum)
     return {};
@@ -571,9 +603,11 @@ find_program_interpreter (void)
        int sect_size = bfd_section_size (interp_sect);
 
        gdb::byte_vector buf (sect_size);
        int sect_size = bfd_section_size (interp_sect);
 
        gdb::byte_vector buf (sect_size);
-       bfd_get_section_contents (current_program_space->exec_bfd (),
-                                 interp_sect, buf.data (), 0, sect_size);
-       return buf;
+       bool res
+         = bfd_get_section_contents (current_program_space->exec_bfd (),
+                                     interp_sect, buf.data (), 0, sect_size);
+       if (res)
+         return buf;
       }
    }
 
       }
    }
 
@@ -662,6 +696,9 @@ elf_locate_base (void)
   struct bound_minimal_symbol msymbol;
   CORE_ADDR dyn_ptr, dyn_ptr_addr;
 
   struct bound_minimal_symbol msymbol;
   CORE_ADDR dyn_ptr, dyn_ptr_addr;
 
+  if (!svr4_have_link_map_offsets ())
+    return 0;
+
   /* Look for DT_MIPS_RLD_MAP first.  MIPS executables use this
      instead of DT_DEBUG, although they sometimes contain an unused
      DT_DEBUG.  */
   /* Look for DT_MIPS_RLD_MAP first.  MIPS executables use this
      instead of DT_DEBUG, although they sometimes contain an unused
      DT_DEBUG.  */
@@ -672,7 +709,7 @@ elf_locate_base (void)
     {
       struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
       gdb_byte *pbuf;
     {
       struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
       gdb_byte *pbuf;
-      int pbuf_size = TYPE_LENGTH (ptr_type);
+      int pbuf_size = ptr_type->length ();
 
       pbuf = (gdb_byte *) alloca (pbuf_size);
       /* DT_MIPS_RLD_MAP contains a pointer to the address
 
       pbuf = (gdb_byte *) alloca (pbuf_size);
       /* DT_MIPS_RLD_MAP contains a pointer to the address
@@ -692,7 +729,7 @@ elf_locate_base (void)
     {
       struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
       gdb_byte *pbuf;
     {
       struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
       gdb_byte *pbuf;
-      int pbuf_size = TYPE_LENGTH (ptr_type);
+      int pbuf_size = ptr_type->length ();
 
       pbuf = (gdb_byte *) alloca (pbuf_size);
       /* DT_MIPS_RLD_MAP_REL contains an offset from the address of the
 
       pbuf = (gdb_byte *) alloca (pbuf_size);
       /* DT_MIPS_RLD_MAP_REL contains an offset from the address of the
@@ -713,51 +750,12 @@ elf_locate_base (void)
   msymbol = lookup_minimal_symbol ("_r_debug", NULL,
                                   current_program_space->symfile_object_file);
   if (msymbol.minsym != NULL)
   msymbol = lookup_minimal_symbol ("_r_debug", NULL,
                                   current_program_space->symfile_object_file);
   if (msymbol.minsym != NULL)
-    return BMSYMBOL_VALUE_ADDRESS (msymbol);
+    return msymbol.value_address ();
 
   /* DT_DEBUG entry not found.  */
   return 0;
 }
 
 
   /* DT_DEBUG entry not found.  */
   return 0;
 }
 
-/* Locate the base address of dynamic linker structs.
-
-   For both the SunOS and SVR4 shared library implementations, if the
-   inferior executable has been linked dynamically, there is a single
-   address somewhere in the inferior's data space which is the key to
-   locating all of the dynamic linker's runtime structures.  This
-   address is the value of the debug base symbol.  The job of this
-   function is to find and return that address, or to return 0 if there
-   is no such address (the executable is statically linked for example).
-
-   For SunOS, the job is almost trivial, since the dynamic linker and
-   all of it's structures are statically linked to the executable at
-   link time.  Thus the symbol for the address we are looking for has
-   already been added to the minimal symbol table for the executable's
-   objfile at the time the symbol file's symbols were read, and all we
-   have to do is look it up there.  Note that we explicitly do NOT want
-   to find the copies in the shared library.
-
-   The SVR4 version is a bit more complicated because the address
-   is contained somewhere in the dynamic info section.  We have to go
-   to a lot more work to discover the address of the debug base symbol.
-   Because of this complexity, we cache the value we find and return that
-   value on subsequent invocations.  Note there is no copy in the
-   executable symbol tables.  */
-
-static CORE_ADDR
-locate_base (struct svr4_info *info)
-{
-  /* Check to see if we have a currently valid address, and if so, avoid
-     doing all this work again and just return the cached address.  If
-     we have no cached address, try to locate it in the dynamic info
-     section for ELF executables.  There's no point in doing any of this
-     though if we don't have some link map offsets to work with.  */
-
-  if (info->debug_base == 0 && svr4_have_link_map_offsets ())
-    info->debug_base = elf_locate_base ();
-  return info->debug_base;
-}
-
 /* Find the first element in the inferior's dynamic link map, and
    return its address in the inferior.  Return zero if the address
    could not be determined.
 /* Find the first element in the inferior's dynamic link map, and
    return its address in the inferior.  Return zero if the address
    could not be determined.
@@ -767,7 +765,7 @@ locate_base (struct svr4_info *info)
    RT_CONSISTENT.  */
 
 static CORE_ADDR
    RT_CONSISTENT.  */
 
 static CORE_ADDR
-solib_svr4_r_map (struct svr4_info *info)
+solib_svr4_r_map (CORE_ADDR debug_base)
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
@@ -775,7 +773,7 @@ solib_svr4_r_map (struct svr4_info *info)
 
   try
     {
 
   try
     {
-      addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
+      addr = read_memory_typed_address (debug_base + lmo->r_map_offset,
                                        ptr_type);
     }
   catch (const gdb_exception_error &ex)
                                        ptr_type);
     }
   catch (const gdb_exception_error &ex)
@@ -829,6 +827,35 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
                                    ptr_type);
 }
 
                                    ptr_type);
 }
 
+/* Find the next namespace from the r_next field.  */
+
+static CORE_ADDR
+solib_svr4_r_next (CORE_ADDR debug_base)
+{
+  link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+  type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+  bfd_endian byte_order = type_byte_order (ptr_type);
+  ULONGEST version = 0;
+
+  try
+    {
+      version
+       = read_memory_unsigned_integer (debug_base + lmo->r_version_offset,
+                                       lmo->r_version_size, byte_order);
+    }
+  catch (const gdb_exception_error &ex)
+    {
+      exception_print (gdb_stderr, ex);
+    }
+
+  /* The r_next field is added with r_version == 2.  */
+  if (version < 2 || lmo->r_next_offset == -1)
+    return 0;
+
+  return read_memory_typed_address (debug_base + lmo->r_next_offset,
+                                   ptr_type);
+}
+
 /* On Solaris systems with some versions of the dynamic linker,
    ld.so's l_name pointer points to the SONAME in the string table
    rather than into writable memory.  So that GDB can find shared
 /* On Solaris systems with some versions of the dynamic linker,
    ld.so's l_name pointer points to the SONAME in the string table
    rather than into writable memory.  So that GDB can find shared
@@ -845,9 +872,8 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
 
   info = get_svr4_info (current_program_space);
 
 
   info = get_svr4_info (current_program_space);
 
-  info->debug_base = 0;
-  locate_base (info);
-  if (!info->debug_base)
+  info->debug_base = elf_locate_base ();
+  if (info->debug_base == 0)
     return 0;
 
   ldsomap = solib_svr4_r_ldsomap (info);
     return 0;
 
   ldsomap = solib_svr4_r_ldsomap (info);
@@ -868,7 +894,7 @@ open_symbol_file_object (int from_tty)
   CORE_ADDR lm, l_name;
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
   CORE_ADDR lm, l_name;
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
-  int l_name_size = TYPE_LENGTH (ptr_type);
+  int l_name_size = ptr_type->length ();
   gdb::byte_vector l_name_buf (l_name_size);
   struct svr4_info *info = get_svr4_info (current_program_space);
   symfile_add_flags add_flags = 0;
   gdb::byte_vector l_name_buf (l_name_size);
   struct svr4_info *info = get_svr4_info (current_program_space);
   symfile_add_flags add_flags = 0;
@@ -881,12 +907,12 @@ open_symbol_file_object (int from_tty)
       return 0;
 
   /* Always locate the debug struct, in case it has moved.  */
       return 0;
 
   /* Always locate the debug struct, in case it has moved.  */
-  info->debug_base = 0;
-  if (locate_base (info) == 0)
+  info->debug_base = elf_locate_base ();
+  if (info->debug_base == 0)
     return 0;  /* failed somehow...  */
 
   /* First link map member should be the executable.  */
     return 0;  /* failed somehow...  */
 
   /* First link map member should be the executable.  */
-  lm = solib_svr4_r_map (info);
+  lm = solib_svr4_r_map (info->debug_base);
   if (lm == 0)
     return 0;  /* failed somehow...  */
 
   if (lm == 0)
     return 0;  /* failed somehow...  */
 
@@ -920,11 +946,19 @@ open_symbol_file_object (int from_tty)
 
 struct svr4_library_list
 {
 
 struct svr4_library_list
 {
-  struct so_list *head, **tailp;
+  /* The tail pointer of the current namespace.  This is internal to XML
+     parsing.  */
+  so_list **tailp;
 
   /* Inferior address of struct link_map used for the main executable.  It is
      NULL if not known.  */
   CORE_ADDR main_lm;
 
   /* Inferior address of struct link_map used for the main executable.  It is
      NULL if not known.  */
   CORE_ADDR main_lm;
+
+  /* List of objects loaded into the inferior per namespace.  This does
+     not include any default sos.
+
+     See comment on struct svr4_info.solib_lists.  */
+  std::map<CORE_ADDR, so_list *> solib_lists;
 };
 
 /* This module's 'free_objfile' observer.  */
 };
 
 /* This module's 'free_objfile' observer.  */
@@ -956,13 +990,11 @@ svr4_clear_so (struct so_list *so)
     li->l_addr_p = 0;
 }
 
     li->l_addr_p = 0;
 }
 
-/* Free so_list built so far (called via cleanup).  */
+/* Free so_list built so far.  */
 
 static void
 
 static void
-svr4_free_library_list (void *p_list)
+svr4_free_library_list (so_list *list)
 {
 {
-  struct so_list *list = *(struct so_list **) p_list;
-
   while (list != NULL)
     {
       struct so_list *next = list->next;
   while (list != NULL)
     {
       struct so_list *next = list->next;
@@ -1035,8 +1067,37 @@ library_list_start_library (struct gdb_xml_parser *parser,
   new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0;
   strcpy (new_elem->so_original_name, new_elem->so_name);
 
   new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0;
   strcpy (new_elem->so_original_name, new_elem->so_name);
 
-  *list->tailp = new_elem;
-  list->tailp = &new_elem->next;
+  /* Older versions did not supply lmid.  Put the element into the flat
+     list of the special namespace zero in that case.  */
+  gdb_xml_value *at_lmid = xml_find_attribute (attributes, "lmid");
+  if (at_lmid == nullptr)
+    {
+      *list->tailp = new_elem;
+      list->tailp = &new_elem->next;
+    }
+  else
+    {
+      ULONGEST lmid = *(ULONGEST *) at_lmid->value.get ();
+
+      /* Ensure that the element is actually initialized.  */
+      if (list->solib_lists.find (lmid) == list->solib_lists.end ())
+       list->solib_lists[lmid] = nullptr;
+
+      so_list **psolist = &list->solib_lists[lmid];
+      so_list **pnext = psolist;
+
+      /* Walk to the end of the list if we have one.  */
+      so_list *solist = *psolist;
+      if (solist != nullptr)
+       {
+         for (; solist->next != nullptr; solist = solist->next)
+           /* Nothing.  */;
+
+         pnext = &solist->next;
+       }
+
+      *pnext = new_elem;
+    }
 }
 
 /* Handle the start of a <library-list-svr4> element.  */
 }
 
 /* Handle the start of a <library-list-svr4> element.  */
@@ -1059,6 +1120,12 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser,
 
   if (main_lm)
     list->main_lm = *(ULONGEST *) main_lm->value.get ();
 
   if (main_lm)
     list->main_lm = *(ULONGEST *) main_lm->value.get ();
+
+  /* Older gdbserver do not support namespaces.  We use the special
+     namespace zero for a linear list of libraries.  */
+  so_list **solist = &list->solib_lists[0];
+  *solist = nullptr;
+  list->tailp = solist;
 }
 
 /* The allowed elements and attributes for an XML library list.
 }
 
 /* The allowed elements and attributes for an XML library list.
@@ -1070,6 +1137,7 @@ static const struct gdb_xml_attribute svr4_library_attributes[] =
   { "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { "lmid", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
@@ -1106,13 +1174,16 @@ static const struct gdb_xml_element svr4_library_list_elements[] =
 static int
 svr4_parse_libraries (const char *document, struct svr4_library_list *list)
 {
 static int
 svr4_parse_libraries (const char *document, struct svr4_library_list *list)
 {
-  auto cleanup = make_scope_exit ([&] ()
+  auto cleanup = make_scope_exit ([list] ()
     {
     {
-      svr4_free_library_list (&list->head);
+      for (const std::pair<CORE_ADDR, so_list *> tuple
+            : list->solib_lists)
+       svr4_free_library_list (tuple.second);
     });
 
     });
 
-  memset (list, 0, sizeof (*list));
-  list->tailp = &list->head;
+  list->tailp = nullptr;
+  list->main_lm = 0;
+  list->solib_lists.clear ();
   if (gdb_xml_parse_quick (_("target library list"), "library-list-svr4.dtd",
                           svr4_library_list_elements, document, list) == 0)
     {
   if (gdb_xml_parse_quick (_("target library list"), "library-list-svr4.dtd",
                           svr4_library_list_elements, document, list) == 0)
     {
@@ -1178,7 +1249,7 @@ svr4_default_sos (svr4_info *info)
   newobj->lm_info = li;
 
   /* Nothing will ever check the other fields if we set l_addr_p.  */
   newobj->lm_info = li;
 
   /* Nothing will ever check the other fields if we set l_addr_p.  */
-  li->l_addr = info->debug_loader_offset;
+  li->l_addr = li->l_addr_inferior = info->debug_loader_offset;
   li->l_addr_p = 1;
 
   strncpy (newobj->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
   li->l_addr_p = 1;
 
   strncpy (newobj->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
@@ -1269,17 +1340,18 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
 /* Read the full list of currently loaded shared objects directly
    from the inferior, without referring to any libraries read and
    stored by the probes interface.  Handle special cases relating
 /* Read the full list of currently loaded shared objects directly
    from the inferior, without referring to any libraries read and
    stored by the probes interface.  Handle special cases relating
-   to the first elements of the list.  */
+   to the first elements of the list in default namespace.  */
 
 
-static struct so_list *
+static void
 svr4_current_sos_direct (struct svr4_info *info)
 {
   CORE_ADDR lm;
 svr4_current_sos_direct (struct svr4_info *info)
 {
   CORE_ADDR lm;
-  struct so_list *head = NULL;
-  struct so_list **link_ptr = &head;
-  int ignore_first;
+  bool ignore_first;
   struct svr4_library_list library_list;
 
   struct svr4_library_list library_list;
 
+  /* Remove any old libraries.  We're going to read them back in again.  */
+  free_solib_lists (info);
+
   /* Fall back to manual examination of the target if the packet is not
      supported or gdbserver failed to find DT_DEBUG.  gdb.server/solib-list.exp
      tests a case where gdbserver cannot find the shared libraries list while
   /* Fall back to manual examination of the target if the packet is not
      supported or gdbserver failed to find DT_DEBUG.  gdb.server/solib-list.exp
      tests a case where gdbserver cannot find the shared libraries list while
@@ -1295,52 +1367,114 @@ svr4_current_sos_direct (struct svr4_info *info)
       if (library_list.main_lm)
        info->main_lm_addr = library_list.main_lm;
 
       if (library_list.main_lm)
        info->main_lm_addr = library_list.main_lm;
 
-      return library_list.head ? library_list.head : svr4_default_sos (info);
+      /* Remove an empty special zero namespace so we know that when there
+        is one, it is actually used, and we have a flat list without
+        namespace information.  */
+      if ((library_list.solib_lists.find (0)
+          != library_list.solib_lists.end ())
+         && (library_list.solib_lists[0] == nullptr))
+       library_list.solib_lists.erase (0);
+
+      /* Replace the (empty) solib_lists in INFO with the one generated
+        from the target.  We don't want to copy it on assignment and then
+        delete the original afterwards, so let's just swap the
+        internals.  */
+      std::swap (info->solib_lists, library_list.solib_lists);
+      return;
     }
 
     }
 
-  /* Always locate the debug struct, in case it has moved.  */
-  info->debug_base = 0;
-  locate_base (info);
-
   /* If we can't find the dynamic linker's base structure, this
      must not be a dynamically linked executable.  Hmm.  */
   /* If we can't find the dynamic linker's base structure, this
      must not be a dynamically linked executable.  Hmm.  */
-  if (! info->debug_base)
-    return svr4_default_sos (info);
+  info->debug_base = elf_locate_base ();
+  if (info->debug_base == 0)
+    return;
 
   /* Assume that everything is a library if the dynamic loader was loaded
      late by a static executable.  */
   if (current_program_space->exec_bfd ()
       && bfd_get_section_by_name (current_program_space->exec_bfd (),
                                  ".dynamic") == NULL)
 
   /* Assume that everything is a library if the dynamic loader was loaded
      late by a static executable.  */
   if (current_program_space->exec_bfd ()
       && bfd_get_section_by_name (current_program_space->exec_bfd (),
                                  ".dynamic") == NULL)
-    ignore_first = 0;
+    ignore_first = false;
   else
   else
-    ignore_first = 1;
+    ignore_first = true;
 
 
-  auto cleanup = make_scope_exit ([&] ()
+  auto cleanup = make_scope_exit ([info] ()
     {
     {
-      svr4_free_library_list (&head);
+      free_solib_lists (info);
     });
 
     });
 
-  /* Walk the inferior's link map list, and build our list of
-     `struct so_list' nodes.  */
-  lm = solib_svr4_r_map (info);
-  if (lm)
-    svr4_read_so_list (info, lm, 0, &link_ptr, ignore_first);
+  /* Collect the sos in each namespace.  */
+  CORE_ADDR debug_base = info->debug_base;
+  for (; debug_base != 0;
+       ignore_first = false, debug_base = solib_svr4_r_next (debug_base))
+    {
+      /* Walk the inferior's link map list, and build our so_list list.  */
+      lm = solib_svr4_r_map (debug_base);
+      if (lm != 0)
+       {
+         so_list **sos = &info->solib_lists[debug_base];
+         *sos = nullptr;
+
+         svr4_read_so_list (info, lm, 0, &sos, ignore_first);
+       }
+    }
 
   /* On Solaris, the dynamic linker is not in the normal list of
      shared objects, so make sure we pick it up too.  Having
      symbol information for the dynamic linker is quite crucial
 
   /* On Solaris, the dynamic linker is not in the normal list of
      shared objects, so make sure we pick it up too.  Having
      symbol information for the dynamic linker is quite crucial
-     for skipping dynamic linker resolver code.  */
-  lm = solib_svr4_r_ldsomap (info);
-  if (lm)
-    svr4_read_so_list (info, lm, 0, &link_ptr, 0);
+     for skipping dynamic linker resolver code.
+
+     Note that we interpret the ldsomap load map address as 'virtual'
+     r_debug object.  If we added it to the default namespace (as it was),
+     we would probably run into inconsistencies with the load map's
+     prev/next links (I wonder if we did).  */
+  debug_base = solib_svr4_r_ldsomap (info);
+  if (debug_base != 0)
+    {
+      /* Add the dynamic linker's namespace unless we already did.  */
+      if (info->solib_lists.find (debug_base) == info->solib_lists.end ())
+       {
+         so_list **sos = &info->solib_lists[debug_base];
+         *sos = nullptr;
+         svr4_read_so_list (info, debug_base, 0, &sos, 0);
+       }
+    }
 
   cleanup.release ();
 
   cleanup.release ();
+}
+
+/* Collect sos read and stored by the probes interface.  */
 
 
-  if (head == NULL)
-    return svr4_default_sos (info);
+static so_list *
+svr4_collect_probes_sos (svr4_info *info)
+{
+  so_list *sos = nullptr;
+  so_list **pnext = &sos;
+
+  for (const std::pair<CORE_ADDR, so_list *> tuple
+        : info->solib_lists)
+    {
+      so_list *solist = tuple.second;
+
+      /* Allow the linker to report empty namespaces.  */
+      if (solist == nullptr)
+       continue;
+
+      *pnext = svr4_copy_library_list (solist);
+
+      /* Update PNEXT to point to the next member of the last element.  */
+      gdb_assert (*pnext != nullptr);
+      for (;;)
+       {
+         so_list *next = *pnext;
+         if (next == nullptr)
+           break;
+
+         pnext = &next->next;
+       }
+    }
 
 
-  return head;
+  return sos;
 }
 
 /* Implement the main part of the "current_sos" target_so_ops
 }
 
 /* Implement the main part of the "current_sos" target_so_ops
@@ -1349,13 +1483,26 @@ svr4_current_sos_direct (struct svr4_info *info)
 static struct so_list *
 svr4_current_sos_1 (svr4_info *info)
 {
 static struct so_list *
 svr4_current_sos_1 (svr4_info *info)
 {
-  /* If the solib list has been read and stored by the probes
-     interface then we return a copy of the stored list.  */
-  if (info->solib_list != NULL)
-    return svr4_copy_library_list (info->solib_list);
+  so_list *sos = nullptr;
 
 
-  /* Otherwise obtain the solib list directly from the inferior.  */
-  return svr4_current_sos_direct (info);
+  /* If we're using the probes interface, we can use the cache as it will
+     be maintained by probe update/reload actions.  */
+  if (info->probes_table != nullptr)
+    sos = svr4_collect_probes_sos (info);
+
+  /* If we're not using the probes interface or if we didn't cache
+     anything, read the sos to fill the cache, then collect them from the
+     cache.  */
+  if (sos == nullptr)
+    {
+      svr4_current_sos_direct (info);
+
+      sos = svr4_collect_probes_sos (info);
+      if (sos == nullptr)
+       sos = svr4_default_sos (info);
+    }
+
+  return sos;
 }
 
 /* Implement the "current_sos" target_so_ops method.  */
 }
 
 /* Implement the "current_sos" target_so_ops method.  */
@@ -1645,7 +1792,7 @@ solib_event_probe_action (struct probe_and_action *pa)
 {
   enum probe_action action;
   unsigned probe_argc = 0;
 {
   enum probe_action action;
   unsigned probe_argc = 0;
-  struct frame_info *frame = get_current_frame ();
+  frame_info_ptr frame = get_current_frame ();
 
   action = pa->action;
   if (action == DO_NOTHING || action == PROBES_INTERFACE_FAILED)
 
   action = pa->action;
   if (action == DO_NOTHING || action == PROBES_INTERFACE_FAILED)
@@ -1689,8 +1836,7 @@ solib_event_probe_action (struct probe_and_action *pa)
 static int
 solist_update_full (struct svr4_info *info)
 {
 static int
 solist_update_full (struct svr4_info *info)
 {
-  free_solib_list (info);
-  info->solib_list = svr4_current_sos_direct (info);
+  svr4_current_sos_direct (info);
 
   return 1;
 }
 
   return 1;
 }
@@ -1701,29 +1847,51 @@ solist_update_full (struct svr4_info *info)
    failure.  */
 
 static int
    failure.  */
 
 static int
-solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
+solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
+                          CORE_ADDR lm)
 {
 {
-  struct so_list *tail;
-  CORE_ADDR prev_lm;
-
-  /* svr4_current_sos_direct contains logic to handle a number of
-     special cases relating to the first elements of the list.  To
-     avoid duplicating this logic we defer to solist_update_full
-     if the list is empty.  */
-  if (info->solib_list == NULL)
-    return 0;
-
   /* Fall back to a full update if we are using a remote target
      that does not support incremental transfers.  */
   if (info->using_xfer && !target_augmented_libraries_svr4_read ())
     return 0;
 
   /* Fall back to a full update if we are using a remote target
      that does not support incremental transfers.  */
   if (info->using_xfer && !target_augmented_libraries_svr4_read ())
     return 0;
 
-  /* Walk to the end of the list.  */
-  for (tail = info->solib_list; tail->next != NULL; tail = tail->next)
-    /* Nothing.  */;
+  /* Fall back to a full update if we used the special namespace zero.  We
+     wouldn't be able to find the last item in the DEBUG_BASE namespace
+     and hence get the prev link wrong.  */
+  if (info->solib_lists.find (0) != info->solib_lists.end ())
+    return 0;
+
+  /* Ensure that the element is actually initialized.  */
+  if (info->solib_lists.find (debug_base) == info->solib_lists.end ())
+    info->solib_lists[debug_base] = nullptr;
 
 
-  lm_info_svr4 *li = (lm_info_svr4 *) tail->lm_info;
-  prev_lm = li->lm_addr;
+  so_list **psolist = &info->solib_lists[debug_base];
+  so_list **pnext = nullptr;
+  so_list *solist = *psolist;
+  CORE_ADDR prev_lm;
+
+  if (solist == nullptr)
+    {
+      /* svr4_current_sos_direct contains logic to handle a number of
+        special cases relating to the first elements of the list in
+        default namespace.  To avoid duplicating this logic we defer to
+        solist_update_full in this case.  */
+      if (svr4_is_default_namespace (info, debug_base))
+       return 0;
+
+      prev_lm = 0;
+      pnext = psolist;
+    }
+  else
+    {
+      /* Walk to the end of the list.  */
+      for (; solist->next != nullptr; solist = solist->next)
+       /* Nothing.  */;
+
+      lm_info_svr4 *li = (lm_info_svr4 *) solist->lm_info;
+      prev_lm = li->lm_addr;
+      pnext = &solist->next;
+    }
 
   /* Read the new objects.  */
   if (info->using_xfer)
 
   /* Read the new objects.  */
   if (info->using_xfer)
@@ -1731,23 +1899,46 @@ solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
       struct svr4_library_list library_list;
       char annex[64];
 
       struct svr4_library_list library_list;
       char annex[64];
 
-      xsnprintf (annex, sizeof (annex), "start=%s;prev=%s",
+      /* Unknown key=value pairs are ignored by the gdbstub.  */
+      xsnprintf (annex, sizeof (annex), "lmid=%s;start=%s;prev=%s",
+                phex_nz (debug_base, sizeof (debug_base)),
                 phex_nz (lm, sizeof (lm)),
                 phex_nz (prev_lm, sizeof (prev_lm)));
       if (!svr4_current_sos_via_xfer_libraries (&library_list, annex))
        return 0;
 
                 phex_nz (lm, sizeof (lm)),
                 phex_nz (prev_lm, sizeof (prev_lm)));
       if (!svr4_current_sos_via_xfer_libraries (&library_list, annex))
        return 0;
 
-      tail->next = library_list.head;
+      /* Get the so list from the target.  We replace the list in the
+        target response so we can easily check that the response only
+        covers one namespace.
+
+        We expect gdbserver to provide updates for the namespace that
+        contains LM, which would be this namespace...  */
+      so_list *sos = nullptr;
+      if (library_list.solib_lists.find (debug_base)
+         != library_list.solib_lists.end ())
+       std::swap (sos, library_list.solib_lists[debug_base]);
+      if (sos == nullptr)
+       {
+         /* ...or for the special zero namespace for earlier versions...  */
+         if (library_list.solib_lists.find (0)
+             != library_list.solib_lists.end ())
+           std::swap (sos, library_list.solib_lists[0]);
+       }
+
+      /* ...but nothing else.  */
+      for (const std::pair<CORE_ADDR, so_list *> tuple
+            : library_list.solib_lists)
+       gdb_assert (tuple.second == nullptr);
+
+      *pnext = sos;
     }
   else
     {
     }
   else
     {
-      struct so_list **link = &tail->next;
-
       /* IGNORE_FIRST may safely be set to zero here because the
         above check and deferral to solist_update_full ensures
         that this call to svr4_read_so_list will never see the
         first element.  */
       /* IGNORE_FIRST may safely be set to zero here because the
         above check and deferral to solist_update_full ensures
         that this call to svr4_read_so_list will never see the
         first element.  */
-      if (!svr4_read_so_list (info, lm, prev_lm, &link, 0))
+      if (!svr4_read_so_list (info, lm, prev_lm, &pnext, 0))
        return 0;
     }
 
        return 0;
     }
 
@@ -1765,7 +1956,7 @@ disable_probes_interface (svr4_info *info)
             "Reverting to original interface."));
 
   free_probes_table (info);
             "Reverting to original interface."));
 
   free_probes_table (info);
-  free_solib_list (info);
+  free_solib_lists (info);
 }
 
 /* Update the solib list as appropriate when using the
 }
 
 /* Update the solib list as appropriate when using the
@@ -1780,12 +1971,22 @@ svr4_handle_solib_event (void)
   enum probe_action action;
   struct value *val = NULL;
   CORE_ADDR pc, debug_base, lm = 0;
   enum probe_action action;
   struct value *val = NULL;
   CORE_ADDR pc, debug_base, lm = 0;
-  struct frame_info *frame = get_current_frame ();
+  frame_info_ptr frame = get_current_frame ();
 
   /* Do nothing if not using the probes interface.  */
   if (info->probes_table == NULL)
     return;
 
 
   /* Do nothing if not using the probes interface.  */
   if (info->probes_table == NULL)
     return;
 
+  pc = regcache_read_pc (get_current_regcache ());
+  pa = solib_event_probe_at (info, pc);
+  if (pa == nullptr)
+    {
+      /* When some solib ops sits above us, it can respond to a solib event
+        by calling in here.  This is done assuming that if the current event
+        is not an SVR4 solib event, calling here should be a no-op.  */
+      return;
+    }
+
   /* If anything goes wrong we revert to the original linker
      interface.  */
   auto cleanup = make_scope_exit ([info] ()
   /* If anything goes wrong we revert to the original linker
      interface.  */
   auto cleanup = make_scope_exit ([info] ()
@@ -1793,11 +1994,6 @@ svr4_handle_solib_event (void)
       disable_probes_interface (info);
     });
 
       disable_probes_interface (info);
     });
 
-  pc = regcache_read_pc (get_current_regcache ());
-  pa = solib_event_probe_at (info, pc);
-  if (pa == NULL)
-    return;
-
   action = solib_event_probe_action (pa);
   if (action == PROBES_INTERFACE_FAILED)
     return;
   action = solib_event_probe_action (pa);
   if (action == PROBES_INTERFACE_FAILED)
     return;
@@ -1839,9 +2035,17 @@ svr4_handle_solib_event (void)
     if (debug_base == 0)
       return;
 
     if (debug_base == 0)
       return;
 
-    /* Always locate the debug struct, in case it moved.  */
-    info->debug_base = 0;
-    if (locate_base (info) == 0)
+    /* If the global _r_debug object moved, we need to reload everything
+       since we cannot identify namespaces (by the location of their
+       r_debug_ext object) anymore.  */
+    CORE_ADDR global_debug_base = elf_locate_base ();
+    if (global_debug_base != info->debug_base)
+      {
+       info->debug_base = global_debug_base;
+       action = FULL_RELOAD;
+      }
+
+    if (info->debug_base == 0)
       {
        /* It's possible for the reloc_complete probe to be triggered before
           the linker has set the DT_DEBUG pointer (for example, when the
       {
        /* It's possible for the reloc_complete probe to be triggered before
           the linker has set the DT_DEBUG pointer (for example, when the
@@ -1864,13 +2068,6 @@ svr4_handle_solib_event (void)
          return;
       }
 
          return;
       }
 
-    /* GDB does not currently support libraries loaded via dlmopen
-       into namespaces other than the initial one.  We must ignore
-       any namespace other than the initial namespace here until
-       support for this is added to GDB.  */
-    if (debug_base != info->debug_base)
-      action = DO_NOTHING;
-
     if (action == UPDATE_OR_RELOAD)
       {
        try
     if (action == UPDATE_OR_RELOAD)
       {
        try
@@ -1896,7 +2093,7 @@ svr4_handle_solib_event (void)
 
   if (action == UPDATE_OR_RELOAD)
     {
 
   if (action == UPDATE_OR_RELOAD)
     {
-      if (!solist_update_incremental (info, lm))
+      if (!solist_update_incremental (info, debug_base, lm))
        action = FULL_RELOAD;
     }
 
        action = FULL_RELOAD;
     }
 
@@ -1920,16 +2117,16 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
       return false;
     }
 
       return false;
     }
 
-  for (bp_location *loc : b->locations ())
+  for (bp_location &loc : b->locations ())
     {
       struct svr4_info *info;
       struct probe_and_action *pa;
 
     {
       struct svr4_info *info;
       struct probe_and_action *pa;
 
-      info = solib_svr4_pspace_data.get (loc->pspace);
+      info = solib_svr4_pspace_data.get (loc.pspace);
       if (info == NULL || info->probes_table == NULL)
        continue;
 
       if (info == NULL || info->probes_table == NULL)
        continue;
 
-      pa = solib_event_probe_at (info, loc->address);
+      pa = solib_event_probe_at (info, loc.address);
       if (pa == NULL)
        continue;
 
       if (pa == NULL)
        continue;
 
@@ -1954,8 +2151,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
 static void
 svr4_update_solib_event_breakpoints (void)
 {
 static void
 svr4_update_solib_event_breakpoints (void)
 {
-  for (breakpoint *bp : all_breakpoints_safe ())
-    svr4_update_solib_event_breakpoint (bp);
+  for (breakpoint &bp : all_breakpoints_safe ())
+    svr4_update_solib_event_breakpoint (&bp);
 }
 
 /* Create and register solib event breakpoints.  PROBES is an array
 }
 
 /* Create and register solib event breakpoints.  PROBES is an array
@@ -1976,6 +2173,9 @@ svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
        {
          CORE_ADDR address = p->get_relocated_address (objfile);
 
        {
          CORE_ADDR address = p->get_relocated_address (objfile);
 
+         solib_debug_printf ("name=%s, addr=%s", probe_info[i].name,
+                             paddress (gdbarch, address));
+
          create_solib_event_breakpoint (gdbarch, address);
          register_solib_event_probe (info, objfile, p, address, action);
        }
          create_solib_event_breakpoint (gdbarch, address);
          register_solib_event_probe (info, objfile, p, address, action);
        }
@@ -1993,6 +2193,9 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
                                        struct obj_section *os,
                                        bool with_prefix)
 {
                                        struct obj_section *os,
                                        bool with_prefix)
 {
+  SOLIB_SCOPED_DEBUG_START_END ("objfile=%s, with_prefix=%d",
+                               os->objfile->original_name, with_prefix);
+
   std::vector<probe *> probes[NUM_PROBES];
 
   for (int i = 0; i < NUM_PROBES; i++)
   std::vector<probe *> probes[NUM_PROBES];
 
   for (int i = 0; i < NUM_PROBES; i++)
@@ -2012,16 +2215,36 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
        }
 
       probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
        }
 
       probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
-
-      /* The "map_failed" probe did not exist in early
-        versions of the probes code in which the probes'
-        names were prefixed with "rtld_".  */
-      if (with_prefix && streq (name, "rtld_map_failed"))
-       continue;
+      solib_debug_printf ("probe=%s, num found=%zu", name, probes[i].size ());
 
       /* Ensure at least one probe for the current name was found.  */
       if (probes[i].empty ())
 
       /* Ensure at least one probe for the current name was found.  */
       if (probes[i].empty ())
-       return false;
+       {
+         /* The "map_failed" probe did not exist in early versions of the
+            probes code in which the probes' names were prefixed with
+            "rtld_".
+
+            Additionally, the "map_failed" probe was accidentally removed
+            from glibc 2.35 and 2.36, when changes in glibc meant the
+            probe could no longer be reached, and the compiler optimized
+            the probe away.  In this case the probe name doesn't have the
+            "rtld_" prefix.
+
+            To handle this, and give GDB as much flexibility as possible,
+            we make the rule that, if a probe isn't required for the
+            correct operation of GDB (i.e. its action is DO_NOTHING), then
+            we will still use the probes interface, even if that probe is
+            missing.
+
+            The only (possible) downside of this is that, if the user has
+            'set stop-on-solib-events on' in effect, then they might get
+            fewer events using the probes interface than with the classic
+            non-probes interface.  */
+         if (probe_info[i].action == DO_NOTHING)
+           continue;
+         else
+           return false;
+       }
 
       /* Ensure probe arguments can be evaluated.  */
       for (probe *p : probes[i])
 
       /* Ensure probe arguments can be evaluated.  */
       for (probe *p : probes[i])
@@ -2045,6 +2268,7 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
     }
 
   /* All probes found.  Now create them.  */
     }
 
   /* All probes found.  Now create them.  */
+  solib_debug_printf ("using probes interface");
   svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
   return true;
 }
   svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
   return true;
 }
@@ -2070,17 +2294,13 @@ svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
   if (os == nullptr
       || (!svr4_find_and_create_probe_breakpoints (info, gdbarch, os, false)
          && !svr4_find_and_create_probe_breakpoints (info, gdbarch, os, true)))
   if (os == nullptr
       || (!svr4_find_and_create_probe_breakpoints (info, gdbarch, os, false)
          && !svr4_find_and_create_probe_breakpoints (info, gdbarch, os, true)))
-    create_solib_event_breakpoint (gdbarch, address);
+    {
+      solib_debug_printf ("falling back to r_brk breakpoint: addr=%s",
+                         paddress (gdbarch, address));
+      create_solib_event_breakpoint (gdbarch, address);
+    }
 }
 
 }
 
-/* Helper function for gdb_bfd_lookup_symbol.  */
-
-static int
-cmp_name_and_sec_flags (const asymbol *sym, const void *data)
-{
-  return (strcmp (sym->name, (const char *) data) == 0
-         && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0);
-}
 /* Arrange for dynamic linker to hit breakpoint.
 
    Both the SunOS and the SVR4 dynamic linkers have, as part of their
 /* Arrange for dynamic linker to hit breakpoint.
 
    Both the SunOS and the SVR4 dynamic linkers have, as part of their
@@ -2092,7 +2312,7 @@ cmp_name_and_sec_flags (const asymbol *sym, const void *data)
    set to 1.  When the dynamic linker sees this flag set, it will set
    a breakpoint at a location known only to itself, after saving the
    original contents of that place and the breakpoint address itself,
    set to 1.  When the dynamic linker sees this flag set, it will set
    a breakpoint at a location known only to itself, after saving the
    original contents of that place and the breakpoint address itself,
-   in it's own internal structures.  When we resume the inferior, it
+   in its own internal structures.  When we resume the inferior, it
    will eventually take a SIGTRAP when it runs into the breakpoint.
    We handle this (in a different place) by restoring the contents of
    the breakpointed location (which is only known after it stops),
    will eventually take a SIGTRAP when it runs into the breakpoint.
    We handle this (in a different place) by restoring the contents of
    the breakpointed location (which is only known after it stops),
@@ -2131,7 +2351,7 @@ enable_break (struct svr4_info *info, int from_tty)
 
   solib_add (NULL, from_tty, auto_solib_add);
   sym_addr = 0;
 
   solib_add (NULL, from_tty, auto_solib_add);
   sym_addr = 0;
-  if (info->debug_base && solib_svr4_r_map (info) != 0)
+  if (info->debug_base && solib_svr4_r_map (info->debug_base) != 0)
     sym_addr = solib_svr4_r_brk (info);
 
   if (sym_addr != 0)
     sym_addr = solib_svr4_r_brk (info);
 
   if (sym_addr != 0)
@@ -2170,7 +2390,7 @@ enable_break (struct svr4_info *info, int from_tty)
          bfd *tmp_bfd;
          CORE_ADDR load_addr;
 
          bfd *tmp_bfd;
          CORE_ADDR load_addr;
 
-         tmp_bfd = os->objfile->obfd;
+         tmp_bfd = os->objfile->obfd.get ();
          load_addr = os->objfile->text_section_offset ();
 
          interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
          load_addr = os->objfile->text_section_offset ();
 
          interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
@@ -2205,7 +2425,7 @@ enable_break (struct svr4_info *info, int from_tty)
       CORE_ADDR load_addr = 0;
       int load_addr_found = 0;
       int loader_found_in_list = 0;
       CORE_ADDR load_addr = 0;
       int load_addr_found = 0;
       int loader_found_in_list = 0;
-      struct target_ops *tmp_bfd_target;
+      target_ops_up tmp_bfd_target;
 
       sym_addr = 0;
 
 
       sym_addr = 0;
 
@@ -2250,8 +2470,7 @@ enable_break (struct svr4_info *info, int from_tty)
       /* If we were not able to find the base address of the loader
         from our so_list, then try using the AT_BASE auxilliary entry.  */
       if (!load_addr_found)
       /* If we were not able to find the base address of the loader
         from our so_list, then try using the AT_BASE auxilliary entry.  */
       if (!load_addr_found)
-       if (target_auxv_search (current_inferior ()->top_target (),
-                               AT_BASE, &load_addr) > 0)
+       if (target_auxv_search (AT_BASE, &load_addr) > 0)
          {
            int addr_bit = gdbarch_addr_bit (target_gdbarch ());
 
          {
            int addr_bit = gdbarch_addr_bit (target_gdbarch ());
 
@@ -2263,8 +2482,8 @@ enable_break (struct svr4_info *info, int from_tty)
            if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
              {
                CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
            if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
              {
                CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
-               CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd.get (),
-                                                             tmp_bfd_target);
+               CORE_ADDR tmp_entry_point
+                 = exec_entry_point (tmp_bfd.get (), tmp_bfd_target.get ());
 
                gdb_assert (load_addr < space_size);
 
 
                gdb_assert (load_addr < space_size);
 
@@ -2293,7 +2512,8 @@ enable_break (struct svr4_info *info, int from_tty)
                                        inferior_ptid, target_gdbarch ());
 
          load_addr = (regcache_read_pc (regcache)
                                        inferior_ptid, target_gdbarch ());
 
          load_addr = (regcache_read_pc (regcache)
-                      - exec_entry_point (tmp_bfd.get (), tmp_bfd_target));
+                      - exec_entry_point (tmp_bfd.get (),
+                                          tmp_bfd_target.get ()));
        }
 
       if (!loader_found_in_list)
        }
 
       if (!loader_found_in_list)
@@ -2326,9 +2546,15 @@ enable_break (struct svr4_info *info, int from_tty)
       /* Now try to set a breakpoint in the dynamic linker.  */
       for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
        {
       /* Now try to set a breakpoint in the dynamic linker.  */
       for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
        {
-         sym_addr = gdb_bfd_lookup_symbol (tmp_bfd.get (),
-                                           cmp_name_and_sec_flags,
-                                           *bkpt_namep);
+         sym_addr
+           = (gdb_bfd_lookup_symbol
+              (tmp_bfd.get (),
+               [=] (const asymbol *sym)
+               {
+                 return (strcmp (sym->name, *bkpt_namep) == 0
+                         && ((sym->section->flags & (SEC_CODE | SEC_DATA))
+                             != 0));
+               }));
          if (sym_addr != 0)
            break;
        }
          if (sym_addr != 0)
            break;
        }
@@ -2339,12 +2565,7 @@ enable_break (struct svr4_info *info, int from_tty)
           target, this will always produce an unrelocated value.  */
        sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
                                                       sym_addr,
           target, this will always produce an unrelocated value.  */
        sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
                                                       sym_addr,
-                                                      tmp_bfd_target);
-
-      /* We're done with both the temporary bfd and target.  Closing
-        the target closes the underlying bfd, because it holds the
-        only remaining reference.  */
-      target_close (tmp_bfd_target);
+                                                      tmp_bfd_target.get ());
 
       if (sym_addr != 0)
        {
 
       if (sym_addr != 0)
        {
@@ -2369,9 +2590,9 @@ enable_break (struct svr4_info *info, int from_tty)
     {
       msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objf);
       if ((msymbol.minsym != NULL)
     {
       msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objf);
       if ((msymbol.minsym != NULL)
-         && (BMSYMBOL_VALUE_ADDRESS (msymbol) != 0))
+         && (msymbol.value_address () != 0))
        {
        {
-         sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
+         sym_addr = msymbol.value_address ();
          sym_addr = gdbarch_convert_from_func_ptr_addr
            (target_gdbarch (), sym_addr, current_inferior ()->top_target ());
          svr4_create_solib_event_breakpoints (info, target_gdbarch (),
          sym_addr = gdbarch_convert_from_func_ptr_addr
            (target_gdbarch (), sym_addr, current_inferior ()->top_target ());
          svr4_create_solib_event_breakpoints (info, target_gdbarch (),
@@ -2386,9 +2607,9 @@ enable_break (struct svr4_info *info, int from_tty)
        {
          msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objf);
          if ((msymbol.minsym != NULL)
        {
          msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objf);
          if ((msymbol.minsym != NULL)
-             && (BMSYMBOL_VALUE_ADDRESS (msymbol) != 0))
+             && (msymbol.value_address () != 0))
            {
            {
-             sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
+             sym_addr = msymbol.value_address ();
              sym_addr = gdbarch_convert_from_func_ptr_addr
                (target_gdbarch (), sym_addr,
                 current_inferior ()->top_target ());
              sym_addr = gdbarch_convert_from_func_ptr_addr
                (target_gdbarch (), sym_addr,
                 current_inferior ()->top_target ());
@@ -2413,7 +2634,7 @@ read_program_headers_from_bfd (bfd *abfd)
 
   gdb::byte_vector buf (phdrs_size);
   if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
 
   gdb::byte_vector buf (phdrs_size);
   if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
-      || bfd_bread (buf.data (), phdrs_size, abfd) != phdrs_size)
+      || bfd_read (buf.data (), phdrs_size, abfd) != phdrs_size)
     return {};
 
   return buf;
     return {};
 
   return buf;
@@ -2459,7 +2680,7 @@ read_program_headers_from_bfd (bfd *abfd)
      whose e_type member in the ELF header is not ET_DYN.  There may
      be a time in the future when it is desirable to do relocations
      on other types of files as well in which case this condition
      whose e_type member in the ELF header is not ET_DYN.  There may
      be a time in the future when it is desirable to do relocations
      on other types of files as well in which case this condition
-     should either be removed or modified to accomodate the new file
+     should either be removed or modified to accommodate the new file
      type.  - Kevin, Nov 2000. ]  */
 
 static int
      type.  - Kevin, Nov 2000. ]  */
 
 static int
@@ -2479,8 +2700,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
   if ((bfd_get_file_flags (current_program_space->exec_bfd ()) & DYNAMIC) == 0)
     return 0;
 
   if ((bfd_get_file_flags (current_program_space->exec_bfd ()) & DYNAMIC) == 0)
     return 0;
 
-  if (target_auxv_search (current_inferior ()->top_target (),
-                         AT_ENTRY, &entry_point) <= 0)
+  if (target_auxv_search (AT_ENTRY, &entry_point) <= 0)
     return 0;
 
   exec_displacement
     return 0;
 
   exec_displacement
@@ -2927,7 +3147,7 @@ svr4_solib_create_inferior_hook (int from_tty)
 
   /* Clear the probes-based interface's state.  */
   free_probes_table (info);
 
   /* Clear the probes-based interface's state.  */
   free_probes_table (info);
-  free_solib_list (info);
+  free_solib_lists (info);
 
   /* Relocate the main executable if necessary.  */
   svr4_relocate_main_executable ();
 
   /* Relocate the main executable if necessary.  */
   svr4_relocate_main_executable ();
@@ -2995,24 +3215,23 @@ svr4_relocate_section_addresses (struct so_list *so,
 
 /* Architecture-specific operations.  */
 
 
 /* Architecture-specific operations.  */
 
-/* Per-architecture data key.  */
-static struct gdbarch_data *solib_svr4_data;
-
 struct solib_svr4_ops
 {
   /* Return a description of the layout of `struct link_map'.  */
 struct solib_svr4_ops
 {
   /* Return a description of the layout of `struct link_map'.  */
-  struct link_map_offsets *(*fetch_link_map_offsets)(void);
+  struct link_map_offsets *(*fetch_link_map_offsets)(void) = nullptr;
 };
 
 };
 
+/* Per-architecture data key.  */
+static const registry<gdbarch>::key<struct solib_svr4_ops> solib_svr4_data;
+
 /* Return a default for the architecture-specific operations.  */
 
 /* Return a default for the architecture-specific operations.  */
 
-static void *
-solib_svr4_init (struct obstack *obstack)
+static struct solib_svr4_ops *
+get_ops (struct gdbarch *gdbarch)
 {
 {
-  struct solib_svr4_ops *ops;
-
-  ops = OBSTACK_ZALLOC (obstack, struct solib_svr4_ops);
-  ops->fetch_link_map_offsets = NULL;
+  struct solib_svr4_ops *ops = solib_svr4_data.get (gdbarch);
+  if (ops == nullptr)
+    ops = solib_svr4_data.emplace (gdbarch);
   return ops;
 }
 
   return ops;
 }
 
@@ -3023,12 +3242,11 @@ void
 set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
                                       struct link_map_offsets *(*flmo) (void))
 {
 set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
                                       struct link_map_offsets *(*flmo) (void))
 {
-  struct solib_svr4_ops *ops
-    = (struct solib_svr4_ops *) gdbarch_data (gdbarch, solib_svr4_data);
+  struct solib_svr4_ops *ops = get_ops (gdbarch);
 
   ops->fetch_link_map_offsets = flmo;
 
 
   ops->fetch_link_map_offsets = flmo;
 
-  set_solib_ops (gdbarch, &svr4_so_ops);
+  set_gdbarch_so_ops (gdbarch, &svr4_so_ops);
   set_gdbarch_iterate_over_objfiles_in_search_order
     (gdbarch, svr4_iterate_over_objfiles_in_search_order);
 }
   set_gdbarch_iterate_over_objfiles_in_search_order
     (gdbarch, svr4_iterate_over_objfiles_in_search_order);
 }
@@ -3039,9 +3257,7 @@ set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
 static struct link_map_offsets *
 svr4_fetch_link_map_offsets (void)
 {
 static struct link_map_offsets *
 svr4_fetch_link_map_offsets (void)
 {
-  struct solib_svr4_ops *ops
-    = (struct solib_svr4_ops *) gdbarch_data (target_gdbarch (),
-                                             solib_svr4_data);
+  struct solib_svr4_ops *ops = get_ops (target_gdbarch ());
 
   gdb_assert (ops->fetch_link_map_offsets);
   return ops->fetch_link_map_offsets ();
 
   gdb_assert (ops->fetch_link_map_offsets);
   return ops->fetch_link_map_offsets ();
@@ -3052,9 +3268,7 @@ svr4_fetch_link_map_offsets (void)
 static int
 svr4_have_link_map_offsets (void)
 {
 static int
 svr4_have_link_map_offsets (void)
 {
-  struct solib_svr4_ops *ops
-    = (struct solib_svr4_ops *) gdbarch_data (target_gdbarch (),
-                                             solib_svr4_data);
+  struct solib_svr4_ops *ops = get_ops (target_gdbarch ());
 
   return (ops->fetch_link_map_offsets != NULL);
 }
 
   return (ops->fetch_link_map_offsets != NULL);
 }
@@ -3082,6 +3296,7 @@ svr4_ilp32_fetch_link_map_offsets (void)
       lmo.r_map_offset = 4;
       lmo.r_brk_offset = 8;
       lmo.r_ldsomap_offset = 20;
       lmo.r_map_offset = 4;
       lmo.r_brk_offset = 8;
       lmo.r_ldsomap_offset = 20;
+      lmo.r_next_offset = -1;
 
       /* Everything we need is in the first 20 bytes.  */
       lmo.link_map_size = 20;
 
       /* Everything we need is in the first 20 bytes.  */
       lmo.link_map_size = 20;
@@ -3113,6 +3328,7 @@ svr4_lp64_fetch_link_map_offsets (void)
       lmo.r_map_offset = 8;
       lmo.r_brk_offset = 16;
       lmo.r_ldsomap_offset = 40;
       lmo.r_map_offset = 8;
       lmo.r_brk_offset = 16;
       lmo.r_ldsomap_offset = 40;
+      lmo.r_next_offset = -1;
 
       /* Everything we need is in the first 40 bytes.  */
       lmo.link_map_size = 40;
 
       /* Everything we need is in the first 40 bytes.  */
       lmo.link_map_size = 40;
@@ -3127,17 +3343,65 @@ svr4_lp64_fetch_link_map_offsets (void)
 }
 \f
 
 }
 \f
 
-struct target_so_ops svr4_so_ops;
+/* Return the DSO matching OBJFILE or nullptr if none can be found.  */
+
+static so_list *
+find_solib_for_objfile (struct objfile *objfile)
+{
+  if (objfile == nullptr)
+    return nullptr;
+
+  /* If OBJFILE is a separate debug object file, look for the original
+     object file.  */
+  if (objfile->separate_debug_objfile_backlink != nullptr)
+    objfile = objfile->separate_debug_objfile_backlink;
+
+  for (so_list *so : current_program_space->solibs ())
+    if (so->objfile == objfile)
+      return so;
+
+  return nullptr;
+}
+
+/* Return the address of the r_debug object for the namespace containing
+   SOLIB or zero if it cannot be found.  This may happen when symbol files
+   are added manually, for example, or with the main executable.
+
+   Current callers treat zero as initial namespace so they are doing the
+   right thing for the main executable.  */
+
+static CORE_ADDR
+find_debug_base_for_solib (so_list *solib)
+{
+  if (solib == nullptr)
+    return 0;
+
+  svr4_info *info = get_svr4_info (current_program_space);
+  gdb_assert (info != nullptr);
+  for (const std::pair<CORE_ADDR, so_list *> tuple
+        : info->solib_lists)
+    {
+      CORE_ADDR debug_base = tuple.first;
+      so_list *solist = tuple.second;
+
+      for (; solist != nullptr; solist = solist->next)
+       if (svr4_same (solib, solist))
+         return debug_base;
+    }
+
+  return 0;
+}
 
 /* Search order for ELF DSOs linked with -Bsymbolic.  Those DSOs have a
 
 /* Search order for ELF DSOs linked with -Bsymbolic.  Those DSOs have a
-   different rule for symbol lookup.  The lookup begins here in the DSO, not in
-   the main executable.  */
+   different rule for symbol lookup.  The lookup begins here in the DSO,
+   not in the main executable.  When starting from CURRENT_OBJFILE, we
+   stay in the same namespace as that file.  Otherwise, we only consider
+   the initial namespace.  */
 
 static void
 svr4_iterate_over_objfiles_in_search_order
 
 static void
 svr4_iterate_over_objfiles_in_search_order
-  (struct gdbarch *gdbarch,
-   iterate_over_objfiles_in_search_order_cb_ftype *cb,
-   void *cb_data, struct objfile *current_objfile)
+  (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
+   objfile *current_objfile)
 {
   bool checked_current_objfile = false;
   if (current_objfile != nullptr)
 {
   bool checked_current_objfile = false;
   if (current_objfile != nullptr)
@@ -3150,46 +3414,71 @@ svr4_iterate_over_objfiles_in_search_order
       if (current_objfile == current_program_space->symfile_object_file)
        abfd = current_program_space->exec_bfd ();
       else
       if (current_objfile == current_program_space->symfile_object_file)
        abfd = current_program_space->exec_bfd ();
       else
-       abfd = current_objfile->obfd;
+       abfd = current_objfile->obfd.get ();
 
       if (abfd != nullptr
          && gdb_bfd_scan_elf_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
        {
          checked_current_objfile = true;
 
       if (abfd != nullptr
          && gdb_bfd_scan_elf_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
        {
          checked_current_objfile = true;
-         if (cb (current_objfile, cb_data) != 0)
+         if (cb (current_objfile))
            return;
        }
     }
 
            return;
        }
     }
 
+  /* The linker namespace to iterate identified by the address of its
+     r_debug object, defaulting to the initial namespace.  */
+  CORE_ADDR initial = elf_locate_base ();
+  so_list *curr_solib = find_solib_for_objfile (current_objfile);
+  CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib);
+  if (debug_base == 0)
+    debug_base = initial;
+
   for (objfile *objfile : current_program_space->objfiles ())
     {
       if (checked_current_objfile && objfile == current_objfile)
        continue;
   for (objfile *objfile : current_program_space->objfiles ())
     {
       if (checked_current_objfile && objfile == current_objfile)
        continue;
-      if (cb (objfile, cb_data) != 0)
+
+      /* Try to determine the namespace into which objfile was loaded.
+
+        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.  */
+      so_list *solib = find_solib_for_objfile (objfile);
+      CORE_ADDR solib_base = find_debug_base_for_solib (solib);
+      if (solib_base == 0)
+       solib_base = initial;
+
+      /* Ignore objfiles that were added to a different namespace.  */
+      if (solib_base != debug_base)
+       continue;
+
+      if (cb (objfile))
        return;
     }
 }
 
        return;
     }
 }
 
+const struct target_so_ops svr4_so_ops =
+{
+  svr4_relocate_section_addresses,
+  svr4_free_so,
+  svr4_clear_so,
+  svr4_clear_solib,
+  svr4_solib_create_inferior_hook,
+  svr4_current_sos,
+  open_symbol_file_object,
+  svr4_in_dynsym_resolve_code,
+  solib_bfd_open,
+  nullptr,
+  svr4_same,
+  svr4_keep_data_in_core,
+  svr4_update_solib_event_breakpoints,
+  svr4_handle_solib_event,
+};
+
 void _initialize_svr4_solib ();
 void
 _initialize_svr4_solib ()
 {
 void _initialize_svr4_solib ();
 void
 _initialize_svr4_solib ()
 {
-  solib_svr4_data = gdbarch_data_register_pre_init (solib_svr4_init);
-
-  svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses;
-  svr4_so_ops.free_so = svr4_free_so;
-  svr4_so_ops.clear_so = svr4_clear_so;
-  svr4_so_ops.clear_solib = svr4_clear_solib;
-  svr4_so_ops.solib_create_inferior_hook = svr4_solib_create_inferior_hook;
-  svr4_so_ops.current_sos = svr4_current_sos;
-  svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
-  svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
-  svr4_so_ops.bfd_open = solib_bfd_open;
-  svr4_so_ops.same = svr4_same;
-  svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
-  svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
-  svr4_so_ops.handle_event = svr4_handle_solib_event;
-
   gdb::observers::free_objfile.attach (svr4_free_objfile_observer,
                                       "solib-svr4");
 }
   gdb::observers::free_objfile.attach (svr4_free_objfile_observer,
                                       "solib-svr4");
 }