gdb/mi: remove warning about mi1
[binutils-gdb.git] / gdb / solib-svr4.c
index 3122f06939f5f88f01fe8fc515a0e8fcbbea5964..f5fdbc742e7ee8e8f0261bf6bba99f19d05210ab 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 1990-2020 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #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 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 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
@@ -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)
 {
-  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>
@@ -292,10 +303,10 @@ lm_addr_check (const struct so_list *so, bfd *abfd)
              && (l_addr & align) == ((l_dynaddr - dynaddr) & align))
            {
              if (info_verbose)
-               printf_unfiltered (_("Using PIC (Position Independent Code) "
-                                    "prelink displacement %s for \"%s\".\n"),
-                                  paddress (target_gdbarch (), l_addr),
-                                  so->so_name);
+               gdb_printf (_("Using PIC (Position Independent Code) "
+                             "prelink displacement %s for \"%s\".\n"),
+                           paddress (target_gdbarch (), l_addr),
+                           so->so_name);
            }
          else
            {
@@ -329,7 +340,7 @@ struct 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.  */
@@ -341,7 +352,7 @@ struct svr4_info
   /* 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;
@@ -349,9 +360,9 @@ struct svr4_info
   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.  */
-  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
@@ -359,13 +370,34 @@ struct svr4_info
      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.  */
-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.  */
 
@@ -375,18 +407,21 @@ free_probes_table (struct svr4_info *info)
   info->probes_table.reset (nullptr);
 }
 
-/* Free the solib list.  */
+/* Free the solib lists for all namespaces.  */
 
 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 ()
 {
-  free_solib_list (this);
+  free_solib_lists (this);
 }
 
 /* Get the svr4 data for program space PSPACE.  If none is found yet, add it now.
@@ -428,11 +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.  */
-  if (target_auxv_search (current_top_target (), AT_PHDR, &at_phdr) <= 0)
+  if (target_auxv_search (AT_PHDR, &at_phdr) <= 0)
     return {};
-  if (target_auxv_search (current_top_target (), AT_PHENT, &at_phent) <= 0)
+  if (target_auxv_search (AT_PHENT, &at_phent) <= 0)
     return {};
-  if (target_auxv_search (current_top_target (), AT_PHNUM, &at_phnum) <= 0)
+  if (target_auxv_search (AT_PHNUM, &at_phnum) <= 0)
     return {};
   if (!at_phdr || !at_phnum)
     return {};
@@ -554,21 +589,25 @@ read_program_header (int type, int *p_arch_size, CORE_ADDR *base_addr)
 static gdb::optional<gdb::byte_vector>
 find_program_interpreter (void)
 {
-  /* If we have an exec_bfd, use its section table.  */
-  if (exec_bfd
-      && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+  /* If we have a current exec_bfd, use its section table.  */
+  if (current_program_space->exec_bfd ()
+      && (bfd_get_flavour (current_program_space->exec_bfd ())
+         == bfd_target_elf_flavour))
    {
      struct bfd_section *interp_sect;
 
-     interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
+     interp_sect = bfd_get_section_by_name (current_program_space->exec_bfd (),
+                                           ".interp");
      if (interp_sect != NULL)
       {
        int sect_size = bfd_section_size (interp_sect);
 
        gdb::byte_vector buf (sect_size);
-       bfd_get_section_contents (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;
       }
    }
 
@@ -577,108 +616,6 @@ find_program_interpreter (void)
 }
 
 
-/* Scan for DESIRED_DYNTAG in .dynamic section of ABFD.  If DESIRED_DYNTAG is
-   found, 1 is returned and the corresponding PTR is set.  */
-
-static int
-scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
-            CORE_ADDR *ptr_addr)
-{
-  int arch_size, step, sect_size;
-  long current_dyntag;
-  CORE_ADDR dyn_ptr, dyn_addr;
-  gdb_byte *bufend, *bufstart, *buf;
-  Elf32_External_Dyn *x_dynp_32;
-  Elf64_External_Dyn *x_dynp_64;
-  struct bfd_section *sect;
-  struct target_section *target_section;
-
-  if (abfd == NULL)
-    return 0;
-
-  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
-    return 0;
-
-  arch_size = bfd_get_arch_size (abfd);
-  if (arch_size == -1)
-    return 0;
-
-  /* Find the start address of the .dynamic section.  */
-  sect = bfd_get_section_by_name (abfd, ".dynamic");
-  if (sect == NULL)
-    return 0;
-
-  for (target_section = current_target_sections->sections;
-       target_section < current_target_sections->sections_end;
-       target_section++)
-    if (sect == target_section->the_bfd_section)
-      break;
-  if (target_section < current_target_sections->sections_end)
-    dyn_addr = target_section->addr;
-  else
-    {
-      /* ABFD may come from OBJFILE acting only as a symbol file without being
-        loaded into the target (see add_symbol_file_command).  This case is
-        such fallback to the file VMA address without the possibility of
-        having the section relocated to its actual in-memory address.  */
-
-      dyn_addr = bfd_section_vma (sect);
-    }
-
-  /* Read in .dynamic from the BFD.  We will get the actual value
-     from memory later.  */
-  sect_size = bfd_section_size (sect);
-  buf = bufstart = (gdb_byte *) alloca (sect_size);
-  if (!bfd_get_section_contents (abfd, sect,
-                                buf, 0, sect_size))
-    return 0;
-
-  /* Iterate over BUF and scan for DYNTAG.  If found, set PTR and return.  */
-  step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
-                          : sizeof (Elf64_External_Dyn);
-  for (bufend = buf + sect_size;
-       buf < bufend;
-       buf += step)
-  {
-    if (arch_size == 32)
-      {
-       x_dynp_32 = (Elf32_External_Dyn *) buf;
-       current_dyntag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
-       dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
-      }
-    else
-      {
-       x_dynp_64 = (Elf64_External_Dyn *) buf;
-       current_dyntag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
-       dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
-      }
-     if (current_dyntag == DT_NULL)
-       return 0;
-     if (current_dyntag == desired_dyntag)
-       {
-        /* If requested, try to read the runtime value of this .dynamic
-           entry.  */
-        if (ptr)
-          {
-            struct type *ptr_type;
-            gdb_byte ptr_buf[8];
-            CORE_ADDR ptr_addr_1;
-
-            ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
-            ptr_addr_1 = dyn_addr + (buf - bufstart) + arch_size / 8;
-            if (target_read_memory (ptr_addr_1, ptr_buf, arch_size / 8) == 0)
-              dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
-            *ptr = dyn_ptr;
-            if (ptr_addr)
-              *ptr_addr = dyn_addr + (buf - bufstart);
-          }
-        return 1;
-       }
-  }
-
-  return 0;
-}
-
 /* Scan for DESIRED_DYNTAG in .dynamic section of the target's main executable,
    found by consulting the OS auxillary vector.  If DESIRED_DYNTAG is found, 1
    is returned and the corresponding PTR is set.  */
@@ -759,15 +696,20 @@ elf_locate_base (void)
   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.  */
-  if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr, NULL)
+  if (gdb_bfd_scan_elf_dyntag (DT_MIPS_RLD_MAP,
+                              current_program_space->exec_bfd (),
+                              &dyn_ptr, NULL)
       || scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr, NULL))
     {
       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
@@ -780,12 +722,14 @@ elf_locate_base (void)
   /* Then check DT_MIPS_RLD_MAP_REL.  MIPS executables now use this form
      because of needing to support PIE.  DT_MIPS_RLD_MAP will also exist
      in non-PIE.  */
-  if (scan_dyntag (DT_MIPS_RLD_MAP_REL, exec_bfd, &dyn_ptr, &dyn_ptr_addr)
+  if (gdb_bfd_scan_elf_dyntag (DT_MIPS_RLD_MAP_REL,
+                              current_program_space->exec_bfd (),
+                              &dyn_ptr, &dyn_ptr_addr)
       || scan_dyntag_auxv (DT_MIPS_RLD_MAP_REL, &dyn_ptr, &dyn_ptr_addr))
     {
       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
@@ -796,59 +740,22 @@ elf_locate_base (void)
     }
 
   /* Find DT_DEBUG.  */
-  if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr, NULL)
+  if (gdb_bfd_scan_elf_dyntag (DT_DEBUG, current_program_space->exec_bfd (),
+                              &dyn_ptr, NULL)
       || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr, NULL))
     return dyn_ptr;
 
   /* This may be a static executable.  Look for the symbol
      conventionally named _r_debug, as a last resort.  */
-  msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
+  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;
 }
 
-/* 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.
@@ -858,7 +765,7 @@ locate_base (struct svr4_info *info)
    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;
@@ -866,8 +773,8 @@ solib_svr4_r_map (struct svr4_info *info)
 
   try
     {
-      addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
-                                        ptr_type);
+      addr = read_memory_typed_address (debug_base + lmo->r_map_offset,
+                                       ptr_type);
     }
   catch (const gdb_exception_error &ex)
     {
@@ -920,6 +827,35 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
                                    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
@@ -936,9 +872,8 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
 
   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);
@@ -957,11 +892,9 @@ static int
 open_symbol_file_object (int from_tty)
 {
   CORE_ADDR lm, l_name;
-  gdb::unique_xmalloc_ptr<char> filename;
-  int errcode;
   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;
@@ -969,17 +902,17 @@ open_symbol_file_object (int from_tty)
   if (from_tty)
     add_flags |= SYMFILE_VERBOSE;
 
-  if (symfile_objfile)
+  if (current_program_space->symfile_object_file)
     if (!query (_("Attempt to reload symbols from process? ")))
       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.  */
-  lm = solib_svr4_r_map (info);
+  lm = solib_svr4_r_map (info->debug_base);
   if (lm == 0)
     return 0;  /* failed somehow...  */
 
@@ -993,12 +926,12 @@ open_symbol_file_object (int from_tty)
     return 0;          /* No filename.  */
 
   /* Now fetch the filename from target memory.  */
-  target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+  gdb::unique_xmalloc_ptr<char> filename
+    = target_read_string (l_name, SO_NAME_MAX_PATH_SIZE - 1);
 
-  if (errcode)
+  if (filename == nullptr)
     {
-      warning (_("failed to read exec filename from attached file: %s"),
-              safe_strerror (errcode));
+      warning (_("failed to read exec filename from attached file"));
       return 0;
     }
 
@@ -1013,11 +946,19 @@ open_symbol_file_object (int from_tty)
 
 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;
+
+  /* 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.  */
@@ -1049,13 +990,11 @@ svr4_clear_so (struct so_list *so)
     li->l_addr_p = 0;
 }
 
-/* Free so_list built so far (called via cleanup).  */
+/* Free so_list built so far.  */
 
 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;
@@ -1128,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);
 
-  *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.  */
@@ -1152,6 +1120,12 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser,
 
   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.
@@ -1163,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 },
+  { "lmid", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
@@ -1199,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)
 {
-  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)
     {
@@ -1235,7 +1213,8 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
 
   /* Fetch the list of shared libraries.  */
   gdb::optional<gdb::char_vector> svr4_library_document
-    = target_read_stralloc (current_top_target (), TARGET_OBJECT_LIBRARIES_SVR4,
+    = target_read_stralloc (current_inferior ()->top_target (),
+                           TARGET_OBJECT_LIBRARIES_SVR4,
                            annex);
   if (!svr4_library_document)
     return 0;
@@ -1270,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.  */
-  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);
@@ -1297,9 +1276,6 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
 
   for (; lm != 0; prev_lm = lm, lm = next_lm)
     {
-      int errcode;
-      gdb::unique_xmalloc_ptr<char> buffer;
-
       so_list_up newobj (XCNEW (struct so_list));
 
       lm_info_svr4 *li = lm_info_read (lm).release ();
@@ -1318,10 +1294,10 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
        }
 
       /* For SVR4 versions, the first entry in the link map is for the
-         inferior executable, so we must ignore it.  For some versions of
-         SVR4, it has no name.  For others (Solaris 2.3 for example), it
-         does have a name, so we can no longer use a missing name to
-         decide when to ignore it.  */
+        inferior executable, so we must ignore it.  For some versions of
+        SVR4, it has no name.  For others (Solaris 2.3 for example), it
+        does have a name, so we can no longer use a missing name to
+        decide when to ignore it.  */
       if (ignore_first && li->l_prev == 0)
        {
          first_l_name = li->l_name;
@@ -1330,17 +1306,16 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
        }
 
       /* Extract this shared object's name.  */
-      target_read_string (li->l_name, &buffer, SO_NAME_MAX_PATH_SIZE - 1,
-                         &errcode);
-      if (errcode != 0)
+      gdb::unique_xmalloc_ptr<char> buffer
+       = target_read_string (li->l_name, SO_NAME_MAX_PATH_SIZE - 1);
+      if (buffer == nullptr)
        {
          /* If this entry's l_name address matches that of the
             inferior executable, then this is not a normal shared
             object, but (most likely) a vDSO.  In this case, silently
             skip it; otherwise emit a warning. */
          if (first_l_name == 0 || li->l_name != first_l_name)
-           warning (_("Can't read pathname for load map: %s."),
-                    safe_strerror (errcode));
+           warning (_("Can't read pathname for load map."));
          continue;
        }
 
@@ -1365,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
-   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;
-  struct so_list *head = NULL;
-  struct so_list **link_ptr = &head;
-  int ignore_first;
+  bool ignore_first;
   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
@@ -1391,50 +1367,114 @@ svr4_current_sos_direct (struct svr4_info *info)
       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 (! 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 (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
-    ignore_first = 0;
+  if (current_program_space->exec_bfd ()
+      && bfd_get_section_by_name (current_program_space->exec_bfd (),
+                                 ".dynamic") == NULL)
+    ignore_first = false;
   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
-     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 ();
+}
+
+/* Collect sos read and stored by the probes interface.  */
+
+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;
 
-  if (head == NULL)
-    return svr4_default_sos (info);
+      *pnext = svr4_copy_library_list (solist);
 
-  return head;
+      /* 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 sos;
 }
 
 /* Implement the main part of the "current_sos" target_so_ops
@@ -1443,13 +1483,26 @@ svr4_current_sos_direct (struct 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.  */
@@ -1537,7 +1590,6 @@ svr4_current_sos (void)
 CORE_ADDR
 svr4_fetch_objfile_link_map (struct objfile *objfile)
 {
-  struct so_list *so;
   struct svr4_info *info = get_svr4_info (objfile->pspace);
 
   /* Cause svr4_current_sos() to be run if it hasn't been already.  */
@@ -1545,17 +1597,12 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
     solib_add (NULL, 0, auto_solib_add);
 
   /* svr4_current_sos() will set main_lm_addr for the main executable.  */
-  if (objfile == symfile_objfile)
+  if (objfile == current_program_space->symfile_object_file)
     return info->main_lm_addr;
 
-  /* If OBJFILE is a separate debug object file, look for the
-     original object file.  */
-  if (objfile->separate_debug_objfile_backlink != NULL)
-    objfile = objfile->separate_debug_objfile_backlink;
-
   /* The other link map addresses may be found by examining the list
      of shared libraries.  */
-  for (so = master_so_list (); so; so = so->next)
+  for (struct so_list *so : current_program_space->solibs ())
     if (so->objfile == objfile)
       {
        lm_info_svr4 *li = (lm_info_svr4 *) so->lm_info;
@@ -1745,7 +1792,7 @@ solib_event_probe_action (struct probe_and_action *pa)
 {
   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)
@@ -1789,8 +1836,7 @@ solib_event_probe_action (struct probe_and_action *pa)
 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;
 }
@@ -1801,29 +1847,51 @@ solist_update_full (struct svr4_info *info)
    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;
 
-  /* 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;
+
+  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;
 
-  lm_info_svr4 *li = (lm_info_svr4 *) tail->lm_info;
-  prev_lm = li->lm_addr;
+      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)
@@ -1831,23 +1899,46 @@ solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
       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;
 
-      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
     {
-      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.  */
-      if (!svr4_read_so_list (info, lm, prev_lm, &link, 0))
+      if (!svr4_read_so_list (info, lm, prev_lm, &pnext, 0))
        return 0;
     }
 
@@ -1865,7 +1956,7 @@ disable_probes_interface (svr4_info *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
@@ -1880,12 +1971,22 @@ svr4_handle_solib_event (void)
   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;
 
+  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] ()
@@ -1893,11 +1994,6 @@ svr4_handle_solib_event (void)
       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;
@@ -1939,9 +2035,17 @@ svr4_handle_solib_event (void)
     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
@@ -1964,13 +2068,6 @@ svr4_handle_solib_event (void)
          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
@@ -1996,7 +2093,7 @@ svr4_handle_solib_event (void)
 
   if (action == UPDATE_OR_RELOAD)
     {
-      if (!solist_update_incremental (info, lm))
+      if (!solist_update_incremental (info, debug_base, lm))
        action = FULL_RELOAD;
     }
 
@@ -2014,24 +2111,22 @@ svr4_handle_solib_event (void)
 static bool
 svr4_update_solib_event_breakpoint (struct breakpoint *b)
 {
-  struct bp_location *loc;
-
   if (b->type != bp_shlib_event)
     {
       /* Continue iterating.  */
       return false;
     }
 
-  for (loc = b->loc; loc != NULL; loc = loc->next)
+  for (bp_location &loc : b->locations ())
     {
       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;
 
-      pa = solib_event_probe_at (info, loc->address);
+      pa = solib_event_probe_at (info, loc.address);
       if (pa == NULL)
        continue;
 
@@ -2056,7 +2151,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
 static void
 svr4_update_solib_event_breakpoints (void)
 {
-  iterate_over_breakpoints (svr4_update_solib_event_breakpoint);
+  for (breakpoint &bp : all_breakpoints_safe ())
+    svr4_update_solib_event_breakpoint (&bp);
 }
 
 /* Create and register solib event breakpoints.  PROBES is an array
@@ -2077,6 +2173,9 @@ svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
        {
          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);
        }
@@ -2094,6 +2193,9 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
                                        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++)
@@ -2113,16 +2215,36 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
        }
 
       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 ())
-       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])
@@ -2146,6 +2268,7 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
     }
 
   /* All probes found.  Now create them.  */
+  solib_debug_printf ("using probes interface");
   svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
   return true;
 }
@@ -2171,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)))
-    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
@@ -2193,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,
-   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),
@@ -2232,7 +2351,7 @@ enable_break (struct svr4_info *info, int from_tty)
 
   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)
@@ -2241,9 +2360,8 @@ enable_break (struct svr4_info *info, int from_tty)
 
       sym_addr = gdbarch_addr_bits_remove
        (target_gdbarch (),
-        gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
-                                            sym_addr,
-                                            current_top_target ()));
+        gdbarch_convert_from_func_ptr_addr
+          (target_gdbarch (), sym_addr, current_inferior ()->top_target ()));
 
       /* On at least some versions of Solaris there's a dynamic relocation
         on _r_debug.r_brk and SYM_ADDR may not be relocated yet, e.g., if
@@ -2272,8 +2390,8 @@ enable_break (struct svr4_info *info, int from_tty)
          bfd *tmp_bfd;
          CORE_ADDR load_addr;
 
-         tmp_bfd = os->objfile->obfd;
-         load_addr = os->objfile->section_offsets[SECT_OFF_TEXT (os->objfile)];
+         tmp_bfd = os->objfile->obfd.get ();
+         load_addr = os->objfile->text_section_offset ();
 
          interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
          if (interp_sect)
@@ -2307,23 +2425,22 @@ 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;
-      struct so_list *so;
-      struct target_ops *tmp_bfd_target;
+      target_ops_up tmp_bfd_target;
 
       sym_addr = 0;
 
       /* Now we need to figure out where the dynamic linker was
-         loaded so that we can load its symbols and place a breakpoint
-         in the dynamic linker itself.
+        loaded so that we can load its symbols and place a breakpoint
+        in the dynamic linker itself.
 
-         This address is stored on the stack.  However, I've been unable
-         to find any magic formula to find it for Solaris (appears to
-         be trivial on GNU/Linux).  Therefore, we have to try an alternate
-         mechanism to find the dynamic linker's base address.  */
+        This address is stored on the stack.  However, I've been unable
+        to find any magic formula to find it for Solaris (appears to
+        be trivial on GNU/Linux).  Therefore, we have to try an alternate
+        mechanism to find the dynamic linker's base address.  */
 
       gdb_bfd_ref_ptr tmp_bfd;
       try
-        {
+       {
          tmp_bfd = solib_bfd_open (interp_name);
        }
       catch (const gdb_exception &ex)
@@ -2334,14 +2451,12 @@ enable_break (struct svr4_info *info, int from_tty)
        goto bkpt_at_symbol;
 
       /* Now convert the TMP_BFD into a target.  That way target, as
-         well as BFD operations can be used.  target_bfd_reopen
-         acquires its own reference.  */
-      tmp_bfd_target = target_bfd_reopen (tmp_bfd.get ());
+        well as BFD operations can be used.  */
+      tmp_bfd_target = target_bfd_reopen (tmp_bfd);
 
       /* On a running target, we can get the dynamic linker's base
-         address from the shared library table.  */
-      so = master_so_list ();
-      while (so)
+        address from the shared library table.  */
+      for (struct so_list *so : current_program_space->solibs ())
        {
          if (svr4_same_1 (interp_name, so->so_original_name))
            {
@@ -2350,13 +2465,12 @@ enable_break (struct svr4_info *info, int from_tty)
              load_addr = lm_addr_check (so, tmp_bfd.get ());
              break;
            }
-         so = so->next;
        }
 
       /* 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.  */
+        from our so_list, then try using the AT_BASE auxilliary entry.  */
       if (!load_addr_found)
-       if (target_auxv_search (current_top_target (), AT_BASE, &load_addr) > 0)
+       if (target_auxv_search (AT_BASE, &load_addr) > 0)
          {
            int addr_bit = gdbarch_addr_bit (target_gdbarch ());
 
@@ -2368,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;
-               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);
 
@@ -2388,9 +2502,9 @@ enable_break (struct svr4_info *info, int from_tty)
         the current pc (which should point at the entry point for the
         dynamic linker) and subtracting the offset of the entry point.
 
-         This is more fragile than the previous approaches, but is a good
-         fallback method because it has actually been working well in
-         most cases.  */
+        This is more fragile than the previous approaches, but is a good
+        fallback method because it has actually been working well in
+        most cases.  */
       if (!load_addr_found)
        {
          struct regcache *regcache
@@ -2398,7 +2512,8 @@ enable_break (struct svr4_info *info, int from_tty)
                                        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)
@@ -2410,7 +2525,7 @@ enable_break (struct svr4_info *info, int from_tty)
        }
 
       /* Record the relocated start and end address of the dynamic linker
-         text and plt section for svr4_in_dynsym_resolve_code.  */
+        text and plt section for svr4_in_dynsym_resolve_code.  */
       interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
        {
@@ -2431,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++)
        {
-         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;
        }
@@ -2444,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,
-                                                      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)
        {
@@ -2459,26 +2575,26 @@ enable_break (struct svr4_info *info, int from_tty)
        }
 
       /* For whatever reason we couldn't set a breakpoint in the dynamic
-         linker.  Warn and drop into the old code.  */
+        linker.  Warn and drop into the old code.  */
     bkpt_at_symbol:
       warning (_("Unable to find dynamic linker breakpoint function.\n"
-               "GDB will be unable to debug shared library initializers\n"
-               "and track explicitly loaded dynamic code."));
+              "GDB will be unable to debug shared library initializers\n"
+              "and track explicitly loaded dynamic code."));
     }
 
   /* Scan through the lists of symbols, trying to look up the symbol and
      set a breakpoint there.  Terminate loop when we/if we succeed.  */
 
+  objfile *objf = current_program_space->symfile_object_file;
   for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
     {
-      msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
+      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 = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
-                                                        sym_addr,
-                                                        current_top_target ());
+         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);
          return 1;
@@ -2489,14 +2605,14 @@ enable_break (struct svr4_info *info, int from_tty)
     {
       for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
        {
-         msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
+         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 = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
-                                                            sym_addr,
-                                                            current_top_target ());
+             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);
              return 1;
@@ -2518,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
-      || bfd_bread (buf.data (), phdrs_size, abfd) != phdrs_size)
+      || bfd_read (buf.data (), phdrs_size, abfd) != phdrs_size)
     return {};
 
   return buf;
@@ -2564,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
-     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
@@ -2574,27 +2690,30 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
      a call to gdbarch_convert_from_func_ptr_addr.  */
   CORE_ADDR entry_point, exec_displacement;
 
-  if (exec_bfd == NULL)
+  if (current_program_space->exec_bfd () == NULL)
     return 0;
 
   /* Therefore for ELF it is ET_EXEC and not ET_DYN.  Both shared libraries
      being executed themselves and PIE (Position Independent Executable)
      executables are ET_DYN.  */
 
-  if ((bfd_get_file_flags (exec_bfd) & DYNAMIC) == 0)
+  if ((bfd_get_file_flags (current_program_space->exec_bfd ()) & DYNAMIC) == 0)
     return 0;
 
-  if (target_auxv_search (current_top_target (), AT_ENTRY, &entry_point) <= 0)
+  if (target_auxv_search (AT_ENTRY, &entry_point) <= 0)
     return 0;
 
-  exec_displacement = entry_point - bfd_get_start_address (exec_bfd);
+  exec_displacement
+    = entry_point - bfd_get_start_address (current_program_space->exec_bfd ());
 
   /* Verify the EXEC_DISPLACEMENT candidate complies with the required page
      alignment.  It is cheaper than the program headers comparison below.  */
 
-  if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+  if (bfd_get_flavour (current_program_space->exec_bfd ())
+      == bfd_target_elf_flavour)
     {
-      const struct elf_backend_data *elf = get_elf_backend_data (exec_bfd);
+      const struct elf_backend_data *elf
+       = get_elf_backend_data (current_program_space->exec_bfd ());
 
       /* p_align of PT_LOAD segments does not specify any alignment but
         only congruency of addresses:
@@ -2611,7 +2730,8 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
      looking at a different file than the one used by the kernel - for
      instance, "gdb program" connected to "gdbserver :PORT ld.so program".  */
 
-  if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+  if (bfd_get_flavour (current_program_space->exec_bfd ())
+      == bfd_target_elf_flavour)
     {
       /* Be optimistic and return 0 only if GDB was able to verify the headers
         really do not match.  */
@@ -2620,7 +2740,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
       gdb::optional<gdb::byte_vector> phdrs_target
        = read_program_header (-1, &arch_size, NULL);
       gdb::optional<gdb::byte_vector> phdrs_binary
-       = read_program_headers_from_bfd (exec_bfd);
+       = read_program_headers_from_bfd (current_program_space->exec_bfd ());
       if (phdrs_target && phdrs_binary)
        {
          enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
@@ -2639,14 +2759,16 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
             content offset for the verification purpose.  */
 
          if (phdrs_target->size () != phdrs_binary->size ()
-             || bfd_get_arch_size (exec_bfd) != arch_size)
+             || bfd_get_arch_size (current_program_space->exec_bfd ()) != arch_size)
            return 0;
          else if (arch_size == 32
                   && phdrs_target->size () >= sizeof (Elf32_External_Phdr)
-                  && phdrs_target->size () % sizeof (Elf32_External_Phdr) == 0)
+                  && phdrs_target->size () % sizeof (Elf32_External_Phdr) == 0)
            {
-             Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
-             Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
+             Elf_Internal_Ehdr *ehdr2
+               = elf_tdata (current_program_space->exec_bfd ())->elf_header;
+             Elf_Internal_Phdr *phdr2
+               = elf_tdata (current_program_space->exec_bfd ())->phdr;
              CORE_ADDR displacement = 0;
              int i;
 
@@ -2683,7 +2805,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                  }
 
              /* Now compare program headers from the target and the binary
-                with optional DISPLACEMENT.  */
+                with optional DISPLACEMENT.  */
 
              for (i = 0;
                   i < phdrs_target->size () / sizeof (Elf32_External_Phdr);
@@ -2746,6 +2868,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                    }
 
                  /* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS.  */
+                 bfd *exec_bfd = current_program_space->exec_bfd ();
                  plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt");
                  if (plt2_asect)
                    {
@@ -2778,10 +2901,12 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
            }
          else if (arch_size == 64
                   && phdrs_target->size () >= sizeof (Elf64_External_Phdr)
-                  && phdrs_target->size () % sizeof (Elf64_External_Phdr) == 0)
+                  && phdrs_target->size () % sizeof (Elf64_External_Phdr) == 0)
            {
-             Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
-             Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
+             Elf_Internal_Ehdr *ehdr2
+               = elf_tdata (current_program_space->exec_bfd ())->elf_header;
+             Elf_Internal_Phdr *phdr2
+               = elf_tdata (current_program_space->exec_bfd ())->phdr;
              CORE_ADDR displacement = 0;
              int i;
 
@@ -2880,7 +3005,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                    }
 
                  /* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS.  */
-                 plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt");
+                 plt2_asect
+                   = bfd_get_section_by_name (current_program_space->exec_bfd (),
+                                              ".plt");
                  if (plt2_asect)
                    {
                      int content2;
@@ -2893,8 +3020,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      filesz = extract_unsigned_integer (buf_filesz_p, 8,
                                                         byte_order);
 
-                     /* PLT2_ASECT is from on-disk file (exec_bfd) while
-                        FILESZ is from the in-memory image.  */
+                     /* PLT2_ASECT is from on-disk file (current
+                        exec_bfd) while FILESZ is from the in-memory
+                        image.  */
                      if (content2)
                        filesz += bfd_section_size (plt2_asect);
                      else
@@ -2921,10 +3049,10 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
         the executable symbols/file has been already relocated to
         displacement.  */
 
-      printf_unfiltered (_("Using PIE (Position Independent Executable) "
-                          "displacement %s for \"%s\".\n"),
-                        paddress (target_gdbarch (), exec_displacement),
-                        bfd_get_filename (exec_bfd));
+      gdb_printf (_("Using PIE (Position Independent Executable) "
+                   "displacement %s for \"%s\".\n"),
+                 paddress (target_gdbarch (), exec_displacement),
+                 bfd_get_filename (current_program_space->exec_bfd ()));
     }
 
   *displacementp = exec_displacement;
@@ -2973,16 +3101,18 @@ svr4_relocate_main_executable (void)
   /* Even DISPLACEMENT 0 is a valid new difference of in-memory vs. in-file
      addresses.  */
 
-  if (symfile_objfile)
+  objfile *objf = current_program_space->symfile_object_file;
+  if (objf)
     {
-      section_offsets new_offsets (symfile_objfile->section_offsets.size (),
+      section_offsets new_offsets (objf->section_offsets.size (),
                                   displacement);
-      objfile_relocate (symfile_objfile, new_offsets);
+      objfile_relocate (objf, new_offsets);
     }
-  else if (exec_bfd)
+  else if (current_program_space->exec_bfd ())
     {
       asection *asect;
 
+      bfd *exec_bfd = current_program_space->exec_bfd ();
       for (asect = exec_bfd->sections; asect != NULL; asect = asect->next)
        exec_set_section_address (bfd_get_filename (exec_bfd), asect->index,
                                  bfd_section_vma (asect) + displacement);
@@ -3017,14 +3147,14 @@ svr4_solib_create_inferior_hook (int from_tty)
 
   /* 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 ();
 
   /* No point setting a breakpoint in the dynamic linker if we can't
      hit it (e.g., a core file, or a trace file).  */
-  if (!target_has_execution)
+  if (!target_has_execution ())
     return;
 
   if (!svr4_have_link_map_offsets ())
@@ -3074,7 +3204,7 @@ svr4_truncate_ptr (CORE_ADDR addr)
 
 static void
 svr4_relocate_section_addresses (struct so_list *so,
-                                 struct target_section *sec)
+                                struct target_section *sec)
 {
   bfd *abfd = sec->the_bfd_section->owner;
 
@@ -3085,24 +3215,23 @@ svr4_relocate_section_addresses (struct so_list *so,
 
 /* 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 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.  */
 
-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;
 }
 
@@ -3111,14 +3240,13 @@ solib_svr4_init (struct obstack *obstack)
 
 void
 set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
-                                       struct link_map_offsets *(*flmo) (void))
+                                      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;
 
-  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);
 }
@@ -3129,9 +3257,7 @@ set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
 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 ();
@@ -3142,9 +3268,7 @@ svr4_fetch_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);
 }
@@ -3172,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_next_offset = -1;
 
       /* Everything we need is in the first 20 bytes.  */
       lmo.link_map_size = 20;
@@ -3203,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_next_offset = -1;
 
       /* Everything we need is in the first 40 bytes.  */
       lmo.link_map_size = 40;
@@ -3217,17 +3343,65 @@ svr4_lp64_fetch_link_map_offsets (void)
 }
 \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
-   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
-  (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)
@@ -3235,49 +3409,76 @@ svr4_iterate_over_objfiles_in_search_order
       bfd *abfd;
 
       if (current_objfile->separate_debug_objfile_backlink != nullptr)
-        current_objfile = current_objfile->separate_debug_objfile_backlink;
+       current_objfile = current_objfile->separate_debug_objfile_backlink;
 
-      if (current_objfile == symfile_objfile)
-       abfd = exec_bfd;
+      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
-         && scan_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
+         && 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;
        }
     }
 
+  /* 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;
-      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;
     }
 }
 
+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)
-{
-  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);
+_initialize_svr4_solib ()
+{
+  gdb::observers::free_objfile.attach (svr4_free_objfile_observer,
+                                      "solib-svr4");
 }