gdb/mi: remove warning about mi1
[binutils-gdb.git] / gdb / solib-svr4.c
index 080fd795ed48e70e86c6a7f1676e720e10d1d623..f5fdbc742e7ee8e8f0261bf6bba99f19d05210ab 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 1990-2017 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -33,7 +33,7 @@
 #include "infrun.h"
 #include "regcache.h"
 #include "gdbthread.h"
-#include "observer.h"
+#include "observable.h"
 
 #include "solist.h"
 #include "solib.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 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
+  (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
    GDB can try to place a breakpoint to monitor shared library
@@ -153,8 +160,12 @@ svr4_same_1 (const char *gdb_so_name, const char *inferior_so_name)
       && strcmp (inferior_so_name, "/lib/ld.so.1") == 0)
     return 1;
 
-  /* Similarly, we observed the same issue with sparc64, but with
+  /* Similarly, we observed the same issue with amd64 and sparcv9, but with
      different locations.  */
+  if (strcmp (gdb_so_name, "/usr/lib/amd64/ld.so.1") == 0
+      && strcmp (inferior_so_name, "/lib/amd64/ld.so.1") == 0)
+    return 1;
+
   if (strcmp (gdb_so_name, "/usr/lib/sparcv9/ld.so.1") == 0
       && strcmp (inferior_so_name, "/lib/sparcv9/ld.so.1") == 0)
     return 1;
@@ -165,31 +176,34 @@ 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 lm_info_svr4 *
+static std::unique_ptr<lm_info_svr4>
 lm_info_read (CORE_ADDR lm_addr)
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
-  gdb_byte *lm;
-  lm_info_svr4 *lm_info;
-  struct cleanup *back_to;
+  std::unique_ptr<lm_info_svr4> lm_info;
 
-  lm = (gdb_byte *) xmalloc (lmo->link_map_size);
-  back_to = make_cleanup (xfree, lm);
+  gdb::byte_vector lm (lmo->link_map_size);
 
-  if (target_read_memory (lm_addr, lm, lmo->link_map_size) != 0)
-    {
-      warning (_("Error reading shared library list entry at %s"),
-              paddress (target_gdbarch (), lm_addr)),
-      lm_info = NULL;
-    }
+  if (target_read_memory (lm_addr, lm.data (), lmo->link_map_size) != 0)
+    warning (_("Error reading shared library list entry at %s"),
+            paddress (target_gdbarch (), lm_addr));
   else
     {
       struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
 
-      lm_info = new lm_info_svr4;
+      lm_info.reset (new lm_info_svr4);
       lm_info->lm_addr = lm_addr;
 
       lm_info->l_addr_inferior = extract_typed_address (&lm[lmo->l_addr_offset],
@@ -203,8 +217,6 @@ lm_info_read (CORE_ADDR lm_addr)
                                               ptr_type);
     }
 
-  do_cleanups (back_to);
-
   return lm_info;
 }
 
@@ -237,7 +249,7 @@ lm_addr_check (const struct so_list *so, bfd *abfd)
       if (dyninfo_sect == NULL)
        goto set_addr;
 
-      dynaddr = bfd_section_vma (abfd, dyninfo_sect);
+      dynaddr = bfd_section_vma (dyninfo_sect);
 
       if (dynaddr + l_addr != l_dynaddr)
        {
@@ -291,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
            {
@@ -325,90 +337,104 @@ lm_addr_check (const struct so_list *so, bfd *abfd)
 
 struct svr4_info
 {
-  CORE_ADDR debug_base;        /* Base of dynamic linker structures.  */
+  svr4_info () = default;
+  ~svr4_info ();
+
+  /* Base of dynamic linker structures in default namespace.  */
+  CORE_ADDR debug_base = 0;
 
   /* Validity flag for debug_loader_offset.  */
-  int debug_loader_offset_p;
+  int debug_loader_offset_p = 0;
 
   /* Load address for the dynamic linker, inferred.  */
-  CORE_ADDR debug_loader_offset;
+  CORE_ADDR debug_loader_offset = 0;
 
   /* Name of the dynamic linker, valid if debug_loader_offset_p.  */
-  char *debug_loader_name;
+  char *debug_loader_name = nullptr;
 
-  /* Load map address for the main executable.  */
-  CORE_ADDR main_lm_addr;
+  /* Load map address for the main executable in default namespace.  */
+  CORE_ADDR main_lm_addr = 0;
 
-  CORE_ADDR interp_text_sect_low;
-  CORE_ADDR interp_text_sect_high;
-  CORE_ADDR interp_plt_sect_low;
-  CORE_ADDR interp_plt_sect_high;
+  CORE_ADDR interp_text_sect_low = 0;
+  CORE_ADDR interp_text_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.  */
-  int using_xfer;
+  bool using_xfer = false;
 
   /* Table of struct probe_and_action instances, used by the
      probes-based interface to map breakpoint addresses to probes
      and their associated actions.  Lookup is performed using
-     probe_and_action->probe->address.  */
-  htab_t probes_table;
+     probe_and_action->prob->address.  */
+  htab_up probes_table;
+
+  /* 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.
 
-  /* List of objects loaded into the inferior, used by the probes-
-     based interface.  */
-  struct so_list *solib_list;
+     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_data *solib_svr4_pspace_data;
+static const registry<program_space>::key<svr4_info> solib_svr4_pspace_data;
 
-/* Free the probes table.  */
+/* Return whether DEBUG_BASE is the default namespace of INFO.  */
 
-static void
-free_probes_table (struct svr4_info *info)
+static bool
+svr4_is_default_namespace (const svr4_info *info, CORE_ADDR debug_base)
 {
-  if (info->probes_table == NULL)
-    return;
-
-  htab_delete (info->probes_table);
-  info->probes_table = NULL;
+  return (debug_base == info->debug_base);
 }
 
-/* Free the solib list.  */
+/* Free the probes table.  */
 
 static void
-free_solib_list (struct svr4_info *info)
+free_probes_table (struct svr4_info *info)
 {
-  svr4_free_library_list (&info->solib_list);
-  info->solib_list = NULL;
+  info->probes_table.reset (nullptr);
 }
 
+/* Free the solib lists for all namespaces.  */
+
 static void
-svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
+free_solib_lists (svr4_info *info)
 {
-  struct svr4_info *info = (struct svr4_info *) arg;
+  for (const std::pair<CORE_ADDR, so_list *> tuple
+        : info->solib_lists)
+    svr4_free_library_list (tuple.second);
 
-  free_probes_table (info);
-  free_solib_list (info);
+  info->solib_lists.clear ();
+}
 
-  xfree (info);
+svr4_info::~svr4_info ()
+{
+  free_solib_lists (this);
 }
 
-/* Get the current svr4 data.  If none is found yet, add it now.  This
-   function always returns a valid object.  */
+/* Get the svr4 data for program space PSPACE.  If none is found yet, add it now.
+   This function always returns a valid object.  */
 
 static struct svr4_info *
-get_svr4_info (void)
+get_svr4_info (program_space *pspace)
 {
-  struct svr4_info *info;
+  struct svr4_info *info = solib_svr4_pspace_data.get (pspace);
 
-  info = (struct svr4_info *) program_space_data (current_program_space,
-                                                 solib_svr4_pspace_data);
-  if (info != NULL)
-    return info;
+  if (info == NULL)
+    info = solib_svr4_pspace_data.emplace (pspace);
 
-  info = XCNEW (struct svr4_info);
-  set_program_space_data (current_program_space, solib_svr4_pspace_data, info);
   return info;
 }
 
@@ -417,37 +443,34 @@ get_svr4_info (void)
 static int match_main (const char *);
 
 /* Read program header TYPE from inferior memory.  The header is found
-   by scanning the OS auxillary vector.
+   by scanning the OS auxiliary vector.
 
    If TYPE == -1, return the program headers instead of the contents of
    one program header.
 
-   Return a pointer to allocated memory holding the program header contents,
-   or NULL on failure.  If sucessful, and unless P_SECT_SIZE is NULL, the
-   size of those contents is returned to P_SECT_SIZE.  Likewise, the target
-   architecture size (32-bit or 64-bit) is returned to P_ARCH_SIZE and
-   the base address of the section is returned in BASE_ADDR.  */
+   Return vector of bytes holding the program header contents, or an empty
+   optional on failure.  If successful and P_ARCH_SIZE is non-NULL, the target
+   architecture size (32-bit or 64-bit) is returned to *P_ARCH_SIZE.  Likewise,
+   the base address of the section is returned in *BASE_ADDR.  */
 
-static gdb_byte *
-read_program_header (int type, int *p_sect_size, int *p_arch_size,
-                    CORE_ADDR *base_addr)
+static gdb::optional<gdb::byte_vector>
+read_program_header (int type, int *p_arch_size, CORE_ADDR *base_addr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr = 0;
   int arch_size, sect_size;
   CORE_ADDR sect_addr;
-  gdb_byte *buf;
   int pt_phdr_p = 0;
 
   /* Get required auxv elements from target.  */
-  if (target_auxv_search (&current_target, AT_PHDR, &at_phdr) <= 0)
-    return 0;
-  if (target_auxv_search (&current_target, AT_PHENT, &at_phent) <= 0)
-    return 0;
-  if (target_auxv_search (&current_target, AT_PHNUM, &at_phnum) <= 0)
-    return 0;
+  if (target_auxv_search (AT_PHDR, &at_phdr) <= 0)
+    return {};
+  if (target_auxv_search (AT_PHENT, &at_phent) <= 0)
+    return {};
+  if (target_auxv_search (AT_PHNUM, &at_phnum) <= 0)
+    return {};
   if (!at_phdr || !at_phnum)
-    return 0;
+    return {};
 
   /* Determine ELF architecture type.  */
   if (at_phent == sizeof (Elf32_External_Phdr))
@@ -455,7 +478,7 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
   else if (at_phent == sizeof (Elf64_External_Phdr))
     arch_size = 64;
   else
-    return 0;
+    return {};
 
   /* Find the requested segment.  */
   if (type == -1)
@@ -475,7 +498,7 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
 
          if (target_read_memory (at_phdr + i * sizeof (phdr),
                                  (gdb_byte *)&phdr, sizeof (phdr)))
-           return 0;
+           return {};
 
          p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type,
                                             4, byte_order);
@@ -492,7 +515,7 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
        }
 
       if (i == at_phnum)
-       return 0;
+       return {};
 
       /* Retrieve address and size.  */
       sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr,
@@ -512,7 +535,7 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
 
          if (target_read_memory (at_phdr + i * sizeof (phdr),
                                  (gdb_byte *)&phdr, sizeof (phdr)))
-           return 0;
+           return {};
 
          p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type,
                                             4, byte_order);
@@ -529,7 +552,7 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
        }
 
       if (i == at_phnum)
-       return 0;
+       return {};
 
       /* Retrieve address and size.  */
       sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr,
@@ -549,17 +572,12 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
     }
 
   /* Read in requested program header.  */
-  buf = (gdb_byte *) xmalloc (sect_size);
-  if (target_read_memory (sect_addr, buf, sect_size))
-    {
-      xfree (buf);
-      return NULL;
-    }
+  gdb::byte_vector buf (sect_size);
+  if (target_read_memory (sect_addr, buf.data (), sect_size))
+    return {};
 
   if (p_arch_size)
     *p_arch_size = arch_size;
-  if (p_sect_size)
-    *p_sect_size = sect_size;
   if (base_addr)
     *base_addr = sect_addr;
 
@@ -568,137 +586,36 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
 
 
 /* Return program interpreter string.  */
-static char *
+static gdb::optional<gdb::byte_vector>
 find_program_interpreter (void)
 {
-  gdb_byte *buf = NULL;
-
-  /* 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 (exec_bfd, interp_sect);
-
-       buf = (gdb_byte *) xmalloc (sect_size);
-       bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, sect_size);
+       int sect_size = bfd_section_size (interp_sect);
+
+       gdb::byte_vector buf (sect_size);
+       bool res
+         = bfd_get_section_contents (current_program_space->exec_bfd (),
+                                     interp_sect, buf.data (), 0, sect_size);
+       if (res)
+         return buf;
       }
    }
 
-  /* If we didn't find it, use the target auxillary vector.  */
-  if (!buf)
-    buf = read_program_header (PT_INTERP, NULL, NULL, NULL);
-
-  return (char *) buf;
+  /* If we didn't find it, use the target auxiliary vector.  */
+  return read_program_header (PT_INTERP, NULL, NULL);
 }
 
 
-/* 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 (abfd, sect);
-    }
-
-  /* Read in .dynamic from the BFD.  We will get the actual value
-     from memory later.  */
-  sect_size = bfd_section_size (abfd, 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.  */
@@ -708,24 +625,22 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
                  CORE_ADDR *ptr_addr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
-  int sect_size, arch_size, step;
+  int arch_size, step;
   long current_dyntag;
   CORE_ADDR dyn_ptr;
   CORE_ADDR base_addr;
-  gdb_byte *bufend, *bufstart, *buf;
 
   /* Read in .dynamic section.  */
-  buf = bufstart = read_program_header (PT_DYNAMIC, &sect_size, &arch_size,
-                                       &base_addr);
-  if (!buf)
+  gdb::optional<gdb::byte_vector> ph_data
+    = read_program_header (PT_DYNAMIC, &arch_size, &base_addr);
+  if (!ph_data)
     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)
+  for (gdb_byte *buf = ph_data->data (), *bufend = buf + ph_data->size ();
+       buf < bufend; buf += step)
   {
     if (arch_size == 32)
       {
@@ -754,14 +669,12 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
          *ptr = dyn_ptr;
 
        if (ptr_addr)
-         *ptr_addr = base_addr + buf - bufstart;
+         *ptr_addr = base_addr + buf - ph_data->data ();
 
-       xfree (bufstart);
        return 1;
       }
   }
 
-  xfree (bufstart);
   return 0;
 }
 
@@ -783,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
@@ -804,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
@@ -820,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.
@@ -882,22 +765,21 @@ 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;
   CORE_ADDR addr = 0;
 
-  TRY
+  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 (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stderr, ex);
     }
-  END_CATCH
 
   return addr;
 }
@@ -922,10 +804,10 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
-  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+  enum bfd_endian byte_order = type_byte_order (ptr_type);
   ULONGEST version = 0;
 
-  TRY
+  try
     {
       /* Check version, and return zero if `struct r_debug' doesn't have
         the r_ldsomap member.  */
@@ -933,11 +815,10 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
        = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
                                        lmo->r_version_size, byte_order);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stderr, ex);
     }
-  END_CATCH
 
   if (version < 2 || lmo->r_ldsomap_offset == -1)
     return 0;
@@ -946,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
@@ -958,108 +868,76 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
 {
   struct svr4_info *info;
   CORE_ADDR ldsomap;
-  struct so_list *newobj;
-  struct cleanup *old_chain;
   CORE_ADDR name_lm;
 
-  info = get_svr4_info ();
+  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);
   if (!ldsomap)
     return 0;
 
-  newobj = XCNEW (struct so_list);
-  old_chain = make_cleanup (xfree, newobj);
-  lm_info_svr4 *li = lm_info_read (ldsomap);
-  newobj->lm_info = li;
-  make_cleanup (xfree, newobj->lm_info);
+  std::unique_ptr<lm_info_svr4> li = lm_info_read (ldsomap);
   name_lm = li != NULL ? li->l_name : 0;
-  do_cleanups (old_chain);
 
   return (name_lm >= vaddr && name_lm < vaddr + size);
 }
 
-/* Implement the "open_symbol_file_object" target_so_ops method.
-
-   If no open symbol file, attempt to locate and open the main symbol
-   file.  On SVR4 systems, this is the first link map entry.  If its
-   name is here, we can open it.  Useful when attaching to a process
-   without first loading its symbol file.  */
+/* See solist.h.  */
 
 static int
-open_symbol_file_object (void *from_ttyp)
+open_symbol_file_object (int from_tty)
 {
   CORE_ADDR lm, l_name;
-  char *filename;
-  int errcode;
-  int from_tty = *(int *)from_ttyp;
   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);
-  gdb_byte *l_name_buf = (gdb_byte *) xmalloc (l_name_size);
-  struct cleanup *cleanups = make_cleanup (xfree, l_name_buf);
-  struct svr4_info *info = get_svr4_info ();
+  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;
 
   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? ")))
-      {
-       do_cleanups (cleanups);
-       return 0;
-      }
+      return 0;
 
   /* Always locate the debug struct, in case it has moved.  */
-  info->debug_base = 0;
-  if (locate_base (info) == 0)
-    {
-      do_cleanups (cleanups);
-      return 0;        /* failed somehow...  */
-    }
+  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)
-    {
-      do_cleanups (cleanups);
-      return 0;        /* failed somehow...  */
-    }
+    return 0;  /* failed somehow...  */
 
   /* Read address of name from target memory to GDB.  */
-  read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size);
+  read_memory (lm + lmo->l_name_offset, l_name_buf.data (), l_name_size);
 
   /* Convert the address to host format.  */
-  l_name = extract_typed_address (l_name_buf, ptr_type);
+  l_name = extract_typed_address (l_name_buf.data (), ptr_type);
 
   if (l_name == 0)
-    {
-      do_cleanups (cleanups);
-      return 0;                /* No filename.  */
-    }
+    return 0;          /* No filename.  */
 
   /* Now fetch the filename from target memory.  */
-  target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
-  make_cleanup (xfree, filename);
+  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));
-      do_cleanups (cleanups);
+      warning (_("failed to read exec filename from attached file"));
       return 0;
     }
 
   /* Have a pathname: read the symbol file.  */
-  symbol_file_add_main (filename, add_flags);
+  symbol_file_add_main (filename.get (), add_flags);
 
-  do_cleanups (cleanups);
   return 1;
 }
 
@@ -1068,13 +946,29 @@ open_symbol_file_object (void *from_ttyp)
 
 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.  */
+
+static void
+svr4_free_objfile_observer (struct objfile *objfile)
+{
+  probes_table_remove_objfile_probes (objfile);
+}
+
 /* Implementation for target_so_ops.free_so.  */
 
 static void
@@ -1096,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;
@@ -1150,17 +1042,18 @@ svr4_copy_library_list (struct so_list *src)
 static void
 library_list_start_library (struct gdb_xml_parser *parser,
                            const struct gdb_xml_element *element,
-                           void *user_data, VEC(gdb_xml_value_s) *attributes)
+                           void *user_data,
+                           std::vector<gdb_xml_value> &attributes)
 {
   struct svr4_library_list *list = (struct svr4_library_list *) user_data;
   const char *name
-    = (const char *) xml_find_attribute (attributes, "name")->value;
+    = (const char *) xml_find_attribute (attributes, "name")->value.get ();
   ULONGEST *lmp
-    = (ULONGEST *) xml_find_attribute (attributes, "lm")->value;
+    = (ULONGEST *) xml_find_attribute (attributes, "lm")->value.get ();
   ULONGEST *l_addrp
-    = (ULONGEST *) xml_find_attribute (attributes, "l_addr")->value;
+    = (ULONGEST *) xml_find_attribute (attributes, "l_addr")->value.get ();
   ULONGEST *l_ldp
-    = (ULONGEST *) xml_find_attribute (attributes, "l_ld")->value;
+    = (ULONGEST *) xml_find_attribute (attributes, "l_ld")->value.get ();
   struct so_list *new_elem;
 
   new_elem = XCNEW (struct so_list);
@@ -1174,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.  */
@@ -1183,11 +1105,12 @@ library_list_start_library (struct gdb_xml_parser *parser,
 static void
 svr4_library_list_start_list (struct gdb_xml_parser *parser,
                              const struct gdb_xml_element *element,
-                             void *user_data, VEC(gdb_xml_value_s) *attributes)
+                             void *user_data,
+                             std::vector<gdb_xml_value> &attributes)
 {
   struct svr4_library_list *list = (struct svr4_library_list *) user_data;
   const char *version
-    = (const char *) xml_find_attribute (attributes, "version")->value;
+    = (const char *) xml_find_attribute (attributes, "version")->value.get ();
   struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm");
 
   if (strcmp (version, "1.0") != 0)
@@ -1196,7 +1119,13 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser,
                   version);
 
   if (main_lm)
-    list->main_lm = *(ULONGEST *) main_lm->value;
+    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.
@@ -1208,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 }
 };
 
@@ -1244,20 +1174,24 @@ static const struct gdb_xml_element svr4_library_list_elements[] =
 static int
 svr4_parse_libraries (const char *document, struct svr4_library_list *list)
 {
-  struct cleanup *back_to = make_cleanup (svr4_free_library_list,
-                                         &list->head);
-
-  memset (list, 0, sizeof (*list));
-  list->tailp = &list->head;
+  auto cleanup = make_scope_exit ([list] ()
+    {
+      for (const std::pair<CORE_ADDR, so_list *> tuple
+            : list->solib_lists)
+       svr4_free_library_list (tuple.second);
+    });
+
+  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)
     {
       /* Parsed successfully, keep the result.  */
-      discard_cleanups (back_to);
+      cleanup.release ();
       return 1;
     }
 
-  do_cleanups (back_to);
   return 0;
 }
 
@@ -1275,24 +1209,17 @@ static int
 svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
                                     const char *annex)
 {
-  char *svr4_library_document;
-  int result;
-  struct cleanup *back_to;
-
   gdb_assert (annex == NULL || target_augmented_libraries_svr4_read ());
 
   /* Fetch the list of shared libraries.  */
-  svr4_library_document = target_read_stralloc (&current_target,
-                                               TARGET_OBJECT_LIBRARIES_SVR4,
-                                               annex);
-  if (svr4_library_document == NULL)
+  gdb::optional<gdb::char_vector> svr4_library_document
+    = target_read_stralloc (current_inferior ()->top_target (),
+                           TARGET_OBJECT_LIBRARIES_SVR4,
+                           annex);
+  if (!svr4_library_document)
     return 0;
 
-  back_to = make_cleanup (xfree, svr4_library_document);
-  result = svr4_parse_libraries (svr4_library_document, list);
-  do_cleanups (back_to);
-
-  return result;
+  return svr4_parse_libraries (svr4_library_document->data (), list);
 }
 
 #else
@@ -1310,9 +1237,8 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
    linker, build a fallback list from other sources.  */
 
 static struct so_list *
-svr4_default_sos (void)
+svr4_default_sos (svr4_info *info)
 {
-  struct svr4_info *info = get_svr4_info ();
   struct so_list *newobj;
 
   if (!info->debug_loader_offset_p)
@@ -1323,7 +1249,7 @@ svr4_default_sos (void)
   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);
@@ -1342,7 +1268,7 @@ svr4_default_sos (void)
    represent only part of the inferior library list.  */
 
 static int
-svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
+svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
                   struct so_list ***link_ptr_ptr, int ignore_first)
 {
   CORE_ADDR first_l_name = 0;
@@ -1350,21 +1276,12 @@ svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
 
   for (; lm != 0; prev_lm = lm, lm = next_lm)
     {
-      struct so_list *newobj;
-      struct cleanup *old_chain;
-      int errcode;
-      char *buffer;
-
-      newobj = XCNEW (struct so_list);
-      old_chain = make_cleanup_free_so (newobj);
+      so_list_up newobj (XCNEW (struct so_list));
 
-      lm_info_svr4 *li = lm_info_read (lm);
+      lm_info_svr4 *li = lm_info_read (lm).release ();
       newobj->lm_info = li;
       if (li == NULL)
-       {
-         do_cleanups (old_chain);
-         return 0;
-       }
+       return 0;
 
       next_lm = li->l_next;
 
@@ -1373,58 +1290,48 @@ svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
          warning (_("Corrupted shared library list: %s != %s"),
                   paddress (target_gdbarch (), prev_lm),
                   paddress (target_gdbarch (), li->l_prev));
-         do_cleanups (old_chain);
          return 0;
        }
 
       /* 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)
        {
-         struct svr4_info *info = get_svr4_info ();
-
          first_l_name = li->l_name;
          info->main_lm_addr = li->lm_addr;
-         do_cleanups (old_chain);
          continue;
        }
 
       /* 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));
-         do_cleanups (old_chain);
+           warning (_("Can't read pathname for load map."));
          continue;
        }
 
-      strncpy (newobj->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
+      strncpy (newobj->so_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
       newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
       strcpy (newobj->so_original_name, newobj->so_name);
-      xfree (buffer);
 
       /* If this entry has no name, or its name matches the name
         for the main executable, don't include it in the list.  */
       if (! newobj->so_name[0] || match_main (newobj->so_name))
-       {
-         do_cleanups (old_chain);
-         continue;
-       }
+       continue;
 
-      discard_cleanups (old_chain);
       newobj->next = 0;
-      **link_ptr_ptr = newobj;
-      *link_ptr_ptr = &newobj->next;
+      /* Don't free it now.  */
+      **link_ptr_ptr = newobj.release ();
+      *link_ptr_ptr = &(**link_ptr_ptr)->next;
     }
 
   return 1;
@@ -1433,18 +1340,18 @@ svr4_read_so_list (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;
-  struct cleanup *back_to;
-  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
@@ -1460,64 +1367,142 @@ 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 ();
+      /* 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->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;
 
-  back_to = make_cleanup (svr4_free_library_list, &head);
+  auto cleanup = make_scope_exit ([info] ()
+    {
+      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 (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 (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);
+       }
+    }
 
-  discard_cleanups (back_to);
+  cleanup.release ();
+}
+
+/* Collect sos read and stored by the probes interface.  */
 
-  if (head == NULL)
-    return svr4_default_sos ();
+static so_list *
+svr4_collect_probes_sos (svr4_info *info)
+{
+  so_list *sos = nullptr;
+  so_list **pnext = &sos;
 
-  return head;
+  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 sos;
 }
 
 /* Implement the main part of the "current_sos" target_so_ops
    method.  */
 
 static struct so_list *
-svr4_current_sos_1 (void)
+svr4_current_sos_1 (svr4_info *info)
 {
-  struct svr4_info *info = get_svr4_info ();
+  so_list *sos = nullptr;
+
+  /* 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 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);
+  /* 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);
 
-  /* Otherwise obtain the solib list directly from the inferior.  */
-  return 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.  */
@@ -1525,7 +1510,8 @@ svr4_current_sos_1 (void)
 static struct so_list *
 svr4_current_sos (void)
 {
-  struct so_list *so_head = svr4_current_sos_1 ();
+  svr4_info *info = get_svr4_info (current_program_space);
+  struct so_list *so_head = svr4_current_sos_1 (info);
   struct mem_range vsyscall_range;
 
   /* Filter out the vDSO module, if present.  Its symbol file would
@@ -1604,20 +1590,19 @@ 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 ();
+  struct svr4_info *info = get_svr4_info (objfile->pspace);
 
   /* Cause svr4_current_sos() to be run if it hasn't been already.  */
   if (info->main_lm_addr == 0)
     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;
 
   /* 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;
@@ -1653,7 +1638,7 @@ match_main (const char *soname)
 int
 svr4_in_dynsym_resolve_code (CORE_ADDR pc)
 {
-  struct svr4_info *info = get_svr4_info ();
+  struct svr4_info *info = get_svr4_info (current_program_space);
 
   return ((pc >= info->interp_text_sect_low
           && pc < info->interp_text_sect_high)
@@ -1690,13 +1675,16 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ)
 struct probe_and_action
 {
   /* The probe.  */
-  struct probe *probe;
+  probe *prob;
 
   /* The relocated address of the probe.  */
   CORE_ADDR address;
 
   /* The action.  */
   enum probe_action action;
+
+  /* The objfile where this probe was found.  */
+  struct objfile *objfile;
 };
 
 /* Returns a hash code for the probe_and_action referenced by p.  */
@@ -1721,32 +1709,58 @@ equal_probe_and_action (const void *p1, const void *p2)
   return pa1->address == pa2->address;
 }
 
+/* Traversal function for probes_table_remove_objfile_probes.  */
+
+static int
+probes_table_htab_remove_objfile_probes (void **slot, void *info)
+{
+  probe_and_action *pa = (probe_and_action *) *slot;
+  struct objfile *objfile = (struct objfile *) info;
+
+  if (pa->objfile == objfile)
+    htab_clear_slot (get_svr4_info (objfile->pspace)->probes_table.get (),
+                    slot);
+
+  return 1;
+}
+
+/* Remove all probes that belong to OBJFILE from the probes table.  */
+
+static void
+probes_table_remove_objfile_probes (struct objfile *objfile)
+{
+  svr4_info *info = get_svr4_info (objfile->pspace);
+  if (info->probes_table != nullptr)
+    htab_traverse_noresize (info->probes_table.get (),
+                           probes_table_htab_remove_objfile_probes, objfile);
+}
+
 /* Register a solib event probe and its associated action in the
    probes table.  */
 
 static void
-register_solib_event_probe (struct probe *probe, CORE_ADDR address,
+register_solib_event_probe (svr4_info *info, struct objfile *objfile,
+                           probe *prob, CORE_ADDR address,
                            enum probe_action action)
 {
-  struct svr4_info *info = get_svr4_info ();
   struct probe_and_action lookup, *pa;
   void **slot;
 
   /* Create the probes table, if necessary.  */
   if (info->probes_table == NULL)
-    info->probes_table = htab_create_alloc (1, hash_probe_and_action,
-                                           equal_probe_and_action,
-                                           xfree, xcalloc, xfree);
+    info->probes_table.reset (htab_create_alloc (1, hash_probe_and_action,
+                                                equal_probe_and_action,
+                                                xfree, xcalloc, xfree));
 
-  lookup.probe = probe;
   lookup.address = address;
-  slot = htab_find_slot (info->probes_table, &lookup, INSERT);
+  slot = htab_find_slot (info->probes_table.get (), &lookup, INSERT);
   gdb_assert (*slot == HTAB_EMPTY_ENTRY);
 
   pa = XCNEW (struct probe_and_action);
-  pa->probe = probe;
+  pa->prob = prob;
   pa->address = address;
   pa->action = action;
+  pa->objfile = objfile;
 
   *slot = pa;
 }
@@ -1762,7 +1776,7 @@ solib_event_probe_at (struct svr4_info *info, CORE_ADDR address)
   void **slot;
 
   lookup.address = address;
-  slot = htab_find_slot (info->probes_table, &lookup, NO_INSERT);
+  slot = htab_find_slot (info->probes_table.get (), &lookup, NO_INSERT);
 
   if (slot == NULL)
     return NULL;
@@ -1778,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)
@@ -1791,22 +1805,21 @@ solib_event_probe_action (struct probe_and_action *pa)
        arg0: Lmid_t lmid (mandatory)
        arg1: struct r_debug *debug_base (mandatory)
        arg2: struct link_map *new (optional, for incremental updates)  */
-  TRY
+  try
     {
-      probe_argc = get_probe_argument_count (pa->probe, frame);
+      probe_argc = pa->prob->get_argument_count (get_frame_arch (frame));
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stderr, ex);
       probe_argc = 0;
     }
-  END_CATCH
 
-  /* If get_probe_argument_count throws an exception, probe_argc will
-     be set to zero.  However, if pa->probe does not have arguments,
-     then get_probe_argument_count will succeed but probe_argc will
-     also be zero.  Both cases happen because of different things, but
-     they are treated equally here: action will be set to
+  /* If get_argument_count throws an exception, probe_argc will be set
+     to zero.  However, if pa->prob does not have arguments, then
+     get_argument_count will succeed but probe_argc will also be zero.
+     Both cases happen because of different things, but they are
+     treated equally here: action will be set to
      PROBES_INTERFACE_FAILED.  */
   if (probe_argc == 2)
     action = FULL_RELOAD;
@@ -1823,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;
 }
@@ -1835,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)
@@ -1865,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 (lm, prev_lm, &link, 0))
+      if (!svr4_read_so_list (info, lm, prev_lm, &pnext, 0))
        return 0;
     }
 
@@ -1893,15 +1950,13 @@ solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
    ones set up for the probes-based interface are adequate.  */
 
 static void
-disable_probes_interface_cleanup (void *arg)
+disable_probes_interface (svr4_info *info)
 {
-  struct svr4_info *info = get_svr4_info ();
-
   warning (_("Probes-based dynamic linker interface failed.\n"
-            "Reverting to original interface.\n"));
+            "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
@@ -1911,44 +1966,45 @@ disable_probes_interface_cleanup (void *arg)
 static void
 svr4_handle_solib_event (void)
 {
-  struct svr4_info *info = get_svr4_info ();
+  struct svr4_info *info = get_svr4_info (current_program_space);
   struct probe_and_action *pa;
   enum probe_action action;
-  struct cleanup *old_chain, *usm_chain;
   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;
 
-  /* If anything goes wrong we revert to the original linker
-     interface.  */
-  old_chain = make_cleanup (disable_probes_interface_cleanup, NULL);
-
   pc = regcache_read_pc (get_current_regcache ());
   pa = solib_event_probe_at (info, pc);
-  if (pa == NULL)
+  if (pa == nullptr)
     {
-      do_cleanups (old_chain);
+      /* 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] ()
+    {
+      disable_probes_interface (info);
+    });
+
   action = solib_event_probe_action (pa);
   if (action == PROBES_INTERFACE_FAILED)
-    {
-      do_cleanups (old_chain);
-      return;
-    }
+    return;
 
   if (action == DO_NOTHING)
     {
-      discard_cleanups (old_chain);
+      cleanup.release ();
       return;
     }
 
-  /* evaluate_probe_argument looks up symbols in the dynamic linker
+  /* evaluate_argument looks up symbols in the dynamic linker
      using find_pc_section.  find_pc_section is accelerated by a cache
      called the section map.  The section map is invalidated every
      time a shared library is loaded or unloaded, and if the inferior
@@ -1957,116 +2013,120 @@ svr4_handle_solib_event (void)
      We called find_pc_section in svr4_create_solib_event_breakpoints,
      so we can guarantee that the dynamic linker's sections are in the
      section map.  We can therefore inhibit section map updates across
-     these calls to evaluate_probe_argument and save a lot of time.  */
-  inhibit_section_map_updates (current_program_space);
-  usm_chain = make_cleanup (resume_section_map_updates_cleanup,
-                           current_program_space);
-
-  TRY
-    {
-      val = evaluate_probe_argument (pa->probe, 1, frame);
-    }
-  CATCH (ex, RETURN_MASK_ERROR)
-    {
-      exception_print (gdb_stderr, ex);
-      val = NULL;
-    }
-  END_CATCH
+     these calls to evaluate_argument and save a lot of time.  */
+  {
+    scoped_restore inhibit_updates
+      = inhibit_section_map_updates (current_program_space);
 
-  if (val == NULL)
-    {
-      do_cleanups (old_chain);
-      return;
-    }
+    try
+      {
+       val = pa->prob->evaluate_argument (1, frame);
+      }
+    catch (const gdb_exception_error &ex)
+      {
+       exception_print (gdb_stderr, ex);
+       val = NULL;
+      }
 
-  debug_base = value_as_address (val);
-  if (debug_base == 0)
-    {
-      do_cleanups (old_chain);
+    if (val == NULL)
       return;
-    }
 
-  /* Always locate the debug struct, in case it moved.  */
-  info->debug_base = 0;
-  if (locate_base (info) == 0)
-    {
-      do_cleanups (old_chain);
+    debug_base = value_as_address (val);
+    if (debug_base == 0)
       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 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 (action == UPDATE_OR_RELOAD)
-    {
-      TRY
-       {
-         val = evaluate_probe_argument (pa->probe, 2, frame);
-       }
-      CATCH (ex, RETURN_MASK_ERROR)
-       {
-         exception_print (gdb_stderr, ex);
-         do_cleanups (old_chain);
+    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
+          linker has finished relocating an LD_AUDIT library or its
+          dependencies).  Since we can't yet handle libraries from other link
+          namespaces, we don't lose anything by ignoring them here.  */
+       struct value *link_map_id_val;
+       try
+         {
+           link_map_id_val = pa->prob->evaluate_argument (0, frame);
+         }
+       catch (const gdb_exception_error)
+         {
+           link_map_id_val = NULL;
+         }
+       /* glibc and illumos' libc both define LM_ID_BASE as zero.  */
+       if (link_map_id_val != NULL && value_as_long (link_map_id_val) != 0)
+         action = DO_NOTHING;
+       else
          return;
-       }
-      END_CATCH
+      }
 
-      if (val != NULL)
-       lm = value_as_address (val);
+    if (action == UPDATE_OR_RELOAD)
+      {
+       try
+         {
+           val = pa->prob->evaluate_argument (2, frame);
+         }
+       catch (const gdb_exception_error &ex)
+         {
+           exception_print (gdb_stderr, ex);
+           return;
+         }
 
-      if (lm == 0)
-       action = FULL_RELOAD;
-    }
+       if (val != NULL)
+         lm = value_as_address (val);
 
-  /* Resume section map updates.  */
-  do_cleanups (usm_chain);
+       if (lm == 0)
+         action = FULL_RELOAD;
+      }
+
+    /* Resume section map updates.  Closing the scope is
+       sufficient.  */
+  }
 
   if (action == UPDATE_OR_RELOAD)
     {
-      if (!solist_update_incremental (info, lm))
+      if (!solist_update_incremental (info, debug_base, lm))
        action = FULL_RELOAD;
     }
 
   if (action == FULL_RELOAD)
     {
       if (!solist_update_full (info))
-       {
-         do_cleanups (old_chain);
-         return;
-       }
+       return;
     }
 
-  discard_cleanups (old_chain);
+  cleanup.release ();
 }
 
 /* Helper function for svr4_update_solib_event_breakpoints.  */
 
-static int
-svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
+static bool
+svr4_update_solib_event_breakpoint (struct breakpoint *b)
 {
-  struct bp_location *loc;
-
   if (b->type != bp_shlib_event)
     {
       /* Continue iterating.  */
-      return 0;
+      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 = ((struct svr4_info *)
-             program_space_data (loc->pspace, solib_svr4_pspace_data));
+      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;
 
@@ -2082,7 +2142,7 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
     }
 
   /* Continue iterating.  */
-  return 0;
+  return false;
 }
 
 /* Enable or disable optional solib event breakpoints as appropriate.
@@ -2091,7 +2151,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
 static void
 svr4_update_solib_event_breakpoints (void)
 {
-  iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
+  for (breakpoint &bp : all_breakpoints_safe ())
+    svr4_update_solib_event_breakpoint (&bp);
 }
 
 /* Create and register solib event breakpoints.  PROBES is an array
@@ -2100,32 +2161,118 @@ svr4_update_solib_event_breakpoints (void)
    probe.  */
 
 static void
-svr4_create_probe_breakpoints (struct gdbarch *gdbarch,
-                              VEC (probe_p) **probes,
+svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
+                              const std::vector<probe *> *probes,
                               struct objfile *objfile)
 {
-  int i;
-
-  for (i = 0; i < NUM_PROBES; i++)
+  for (int i = 0; i < NUM_PROBES; i++)
     {
       enum probe_action action = probe_info[i].action;
-      struct probe *probe;
-      int ix;
 
-      for (ix = 0;
-          VEC_iterate (probe_p, probes[i], ix, probe);
-          ++ix)
+      for (probe *p : probes[i])
        {
-         CORE_ADDR address = get_probe_address (probe, 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 (probe, address, action);
+         register_solib_event_probe (info, objfile, p, address, action);
        }
     }
 
   svr4_update_solib_event_breakpoints ();
 }
 
+/* Find all the glibc named probes.  Only if all of the probes are found, then
+   create them and return true.  Otherwise return false.  If WITH_PREFIX is set
+   then add "rtld" to the front of the probe names.  */
+static bool
+svr4_find_and_create_probe_breakpoints (svr4_info *info,
+                                       struct gdbarch *gdbarch,
+                                       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++)
+    {
+      const char *name = probe_info[i].name;
+      char buf[32];
+
+      /* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4 shipped with an early
+        version of the probes code in which the probes' names were prefixed
+        with "rtld_" and the "map_failed" probe did not exist.  The locations
+        of the probes are otherwise the same, so we check for probes with
+        prefixed names if probes with unprefixed names are not present.  */
+      if (with_prefix)
+       {
+         xsnprintf (buf, sizeof (buf), "rtld_%s", name);
+         name = buf;
+       }
+
+      probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
+      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 ())
+       {
+         /* 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])
+       {
+         if (!p->can_evaluate_arguments ())
+           return false;
+         /* This will fail if the probe is invalid.  This has been seen on Arm
+            due to references to symbols that have been resolved away.  */
+         try
+           {
+             p->get_argument_count (gdbarch);
+           }
+         catch (const gdb_exception_error &ex)
+           {
+             exception_print (gdb_stderr, ex);
+             warning (_("Initializing probes-based dynamic linker interface "
+                        "failed.\nReverting to original interface."));
+             return false;
+           }
+       }
+    }
+
+  /* All probes found.  Now create them.  */
+  solib_debug_printf ("using probes interface");
+  svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
+  return true;
+}
+
 /* Both the SunOS and the SVR4 dynamic linkers call a marker function
    before and after mapping and unmapping shared libraries.  The sole
    purpose of this method is to allow debuggers to set a breakpoint so
@@ -2139,92 +2286,21 @@ svr4_create_probe_breakpoints (struct gdbarch *gdbarch,
    marker function.  */
 
 static void
-svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch,
+svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
                                     CORE_ADDR address)
 {
-  struct obj_section *os;
+  struct obj_section *os = find_pc_section (address);
 
-  os = find_pc_section (address);
-  if (os != NULL)
+  if (os == nullptr
+      || (!svr4_find_and_create_probe_breakpoints (info, gdbarch, os, false)
+         && !svr4_find_and_create_probe_breakpoints (info, gdbarch, os, true)))
     {
-      int with_prefix;
-
-      for (with_prefix = 0; with_prefix <= 1; with_prefix++)
-       {
-         VEC (probe_p) *probes[NUM_PROBES];
-         int all_probes_found = 1;
-         int checked_can_use_probe_arguments = 0;
-         int i;
-
-         memset (probes, 0, sizeof (probes));
-         for (i = 0; i < NUM_PROBES; i++)
-           {
-             const char *name = probe_info[i].name;
-             struct probe *p;
-             char buf[32];
-
-             /* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4
-                shipped with an early version of the probes code in
-                which the probes' names were prefixed with "rtld_"
-                and the "map_failed" probe did not exist.  The
-                locations of the probes are otherwise the same, so
-                we check for probes with prefixed names if probes
-                with unprefixed names are not present.  */
-             if (with_prefix)
-               {
-                 xsnprintf (buf, sizeof (buf), "rtld_%s", name);
-                 name = buf;
-               }
-
-             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 (strcmp (name, "rtld_map_failed") == 0)
-               continue;
-
-             if (VEC_empty (probe_p, probes[i]))
-               {
-                 all_probes_found = 0;
-                 break;
-               }
-
-             /* Ensure probe arguments can be evaluated.  */
-             if (!checked_can_use_probe_arguments)
-               {
-                 p = VEC_index (probe_p, probes[i], 0);
-                 if (!can_evaluate_probe_arguments (p))
-                   {
-                     all_probes_found = 0;
-                     break;
-                   }
-                 checked_can_use_probe_arguments = 1;
-               }
-           }
-
-         if (all_probes_found)
-           svr4_create_probe_breakpoints (gdbarch, probes, os->objfile);
-
-         for (i = 0; i < NUM_PROBES; i++)
-           VEC_free (probe_p, probes[i]);
-
-         if (all_probes_found)
-           return;
-       }
+      solib_debug_printf ("falling back to r_brk breakpoint: addr=%s",
+                         paddress (gdbarch, address));
+      create_solib_event_breakpoint (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
@@ -2236,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),
@@ -2263,7 +2339,6 @@ enable_break (struct svr4_info *info, int from_tty)
   struct bound_minimal_symbol msymbol;
   const char * const *bkpt_namep;
   asection *interp_sect;
-  char *interp_name;
   CORE_ADDR sym_addr;
 
   info->interp_text_sect_low = info->interp_text_sect_high = 0;
@@ -2276,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)
@@ -2284,9 +2359,9 @@ enable_break (struct svr4_info *info, int from_tty)
       struct obj_section *os;
 
       sym_addr = gdbarch_addr_bits_remove
-       (target_gdbarch (), gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
-                                                            sym_addr,
-                                                            &current_target));
+       (target_gdbarch (),
+        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
@@ -2315,78 +2390,73 @@ enable_break (struct svr4_info *info, int from_tty)
          bfd *tmp_bfd;
          CORE_ADDR load_addr;
 
-         tmp_bfd = os->objfile->obfd;
-         load_addr = ANOFFSET (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)
            {
-             info->interp_text_sect_low =
-               bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
-             info->interp_text_sect_high =
-               info->interp_text_sect_low
-               + bfd_section_size (tmp_bfd, interp_sect);
+             info->interp_text_sect_low
+               = bfd_section_vma (interp_sect) + load_addr;
+             info->interp_text_sect_high
+               = info->interp_text_sect_low + bfd_section_size (interp_sect);
            }
          interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
          if (interp_sect)
            {
-             info->interp_plt_sect_low =
-               bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
-             info->interp_plt_sect_high =
-               info->interp_plt_sect_low
-               + bfd_section_size (tmp_bfd, interp_sect);
+             info->interp_plt_sect_low
+               = bfd_section_vma (interp_sect) + load_addr;
+             info->interp_plt_sect_high
+               = info->interp_plt_sect_low + bfd_section_size (interp_sect);
            }
 
-         svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+         svr4_create_solib_event_breakpoints (info, target_gdbarch (), sym_addr);
          return 1;
        }
     }
 
   /* Find the program interpreter; if not found, warn the user and drop
      into the old breakpoint at symbol code.  */
-  interp_name = find_program_interpreter ();
-  if (interp_name)
+  gdb::optional<gdb::byte_vector> interp_name_holder
+    = find_program_interpreter ();
+  if (interp_name_holder)
     {
+      const char *interp_name = (const char *) interp_name_holder->data ();
       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
-        {
+      try
+       {
          tmp_bfd = solib_bfd_open (interp_name);
        }
-      CATCH (ex, RETURN_MASK_ALL)
+      catch (const gdb_exception &ex)
        {
        }
-      END_CATCH
 
       if (tmp_bfd == NULL)
        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))
            {
@@ -2395,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_target, AT_BASE, &load_addr) > 0)
+       if (target_auxv_search (AT_BASE, &load_addr) > 0)
          {
            int addr_bit = gdbarch_addr_bit (target_gdbarch ());
 
@@ -2413,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);
 
@@ -2433,16 +2502,18 @@ 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
-           = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
+           = get_thread_arch_regcache (current_inferior ()->process_target (),
+                                       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)
@@ -2454,32 +2525,36 @@ 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)
        {
-         info->interp_text_sect_low =
-           bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
-         info->interp_text_sect_high =
-           info->interp_text_sect_low
-           + bfd_section_size (tmp_bfd.get (), interp_sect);
+         info->interp_text_sect_low
+           = bfd_section_vma (interp_sect) + load_addr;
+         info->interp_text_sect_high
+           = info->interp_text_sect_low + bfd_section_size (interp_sect);
        }
       interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
        {
-         info->interp_plt_sect_low =
-           bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
-         info->interp_plt_sect_high =
-           info->interp_plt_sect_low
-           + bfd_section_size (tmp_bfd.get (), interp_sect);
+         info->interp_plt_sect_low
+           = bfd_section_vma (interp_sect) + load_addr;
+         info->interp_plt_sect_high
+           = info->interp_plt_sect_low + bfd_section_size (interp_sect);
        }
 
       /* 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;
        }
@@ -2490,61 +2565,56 @@ 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)
        {
-         svr4_create_solib_event_breakpoints (target_gdbarch (),
+         svr4_create_solib_event_breakpoints (info, target_gdbarch (),
                                               load_addr + sym_addr);
-         xfree (interp_name);
          return 1;
        }
 
       /* 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:
-      xfree (interp_name);
       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_target);
-         svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+         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;
        }
     }
 
-  if (interp_name != NULL && !current_inferior ()->attach_flag)
+  if (interp_name_holder && !current_inferior ()->attach_flag)
     {
       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_target);
-             svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+             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;
            }
        }
@@ -2552,28 +2622,20 @@ enable_break (struct svr4_info *info, int from_tty)
   return 0;
 }
 
-/* Read the ELF program headers from ABFD.  Return the contents and
-   set *PHDRS_SIZE to the size of the program headers.  */
+/* Read the ELF program headers from ABFD.  */
 
-static gdb_byte *
-read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
+static gdb::optional<gdb::byte_vector>
+read_program_headers_from_bfd (bfd *abfd)
 {
-  Elf_Internal_Ehdr *ehdr;
-  gdb_byte *buf;
-
-  ehdr = elf_elfheader (abfd);
-
-  *phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
-  if (*phdrs_size == 0)
-    return NULL;
+  Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
+  int phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
+  if (phdrs_size == 0)
+    return {};
 
-  buf = (gdb_byte *) xmalloc (*phdrs_size);
+  gdb::byte_vector buf (phdrs_size);
   if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
-      || bfd_bread (buf, *phdrs_size, abfd) != *phdrs_size)
-    {
-      xfree (buf);
-      return NULL;
-    }
+      || bfd_read (buf.data (), phdrs_size, abfd) != phdrs_size)
+    return {};
 
   return buf;
 }
@@ -2589,7 +2651,7 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
      ...  Though the system chooses virtual addresses for
      individual processes, it maintains the segments' relative
      positions.  Because position-independent code uses relative
-     addressesing between segments, the difference between
+     addressing between segments, the difference between
      virtual addresses in memory must match the difference
      between virtual addresses in the file.  The difference
      between the virtual address of any segment in memory and
@@ -2618,7 +2680,7 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
      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
@@ -2628,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_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:
@@ -2665,17 +2730,18 @@ 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 clear OK only if GDB was able to verify the headers
+      /* Be optimistic and return 0 only if GDB was able to verify the headers
         really do not match.  */
-      int phdrs_size, phdrs2_size, ok = 1;
-      gdb_byte *buf, *buf2;
       int arch_size;
 
-      buf = read_program_header (-1, &phdrs_size, &arch_size, NULL);
-      buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
-      if (buf != NULL && buf2 != NULL)
+      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 (current_program_space->exec_bfd ());
+      if (phdrs_target && phdrs_binary)
        {
          enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
 
@@ -2692,15 +2758,17 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
             relocate BUF and BUF2 just by the EXEC_BFD vs. target memory
             content offset for the verification purpose.  */
 
-         if (phdrs_size != phdrs2_size
-             || bfd_get_arch_size (exec_bfd) != arch_size)
-           ok = 0;
+         if (phdrs_target->size () != phdrs_binary->size ()
+             || bfd_get_arch_size (current_program_space->exec_bfd ()) != arch_size)
+           return 0;
          else if (arch_size == 32
-                  && phdrs_size >= sizeof (Elf32_External_Phdr)
-                  && phdrs_size % sizeof (Elf32_External_Phdr) == 0)
+                  && phdrs_target->size () >= sizeof (Elf32_External_Phdr)
+                  && 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;
 
@@ -2718,7 +2786,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                    CORE_ADDR displacement_vaddr = 0;
                    CORE_ADDR displacement_paddr = 0;
 
-                   phdrp = &((Elf32_External_Phdr *) buf)[i];
+                   phdrp = &((Elf32_External_Phdr *) phdrs_target->data ())[i];
                    buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
                    buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
 
@@ -2736,9 +2804,12 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                    break;
                  }
 
-             /* Now compare BUF and BUF2 with optional DISPLACEMENT.  */
+             /* Now compare program headers from the target and the binary
+                with optional DISPLACEMENT.  */
 
-             for (i = 0; i < phdrs_size / sizeof (Elf32_External_Phdr); i++)
+             for (i = 0;
+                  i < phdrs_target->size () / sizeof (Elf32_External_Phdr);
+                  i++)
                {
                  Elf32_External_Phdr *phdrp;
                  Elf32_External_Phdr *phdr2p;
@@ -2746,10 +2817,10 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                  CORE_ADDR vaddr, paddr;
                  asection *plt2_asect;
 
-                 phdrp = &((Elf32_External_Phdr *) buf)[i];
+                 phdrp = &((Elf32_External_Phdr *) phdrs_target->data ())[i];
                  buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
                  buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
-                 phdr2p = &((Elf32_External_Phdr *) buf2)[i];
+                 phdr2p = &((Elf32_External_Phdr *) phdrs_binary->data ())[i];
 
                  /* PT_GNU_STACK is an exception by being never relocated by
                     prelink as its addresses are always zero.  */
@@ -2774,8 +2845,10 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
 
                  /* Strip modifies the flags and alignment of PT_GNU_RELRO.
                     CentOS-5 has problems with filesz, memsz as well.
+                    Strip also modifies memsz of PT_TLS.
                     See PR 11786.  */
-                 if (phdr2[i].p_type == PT_GNU_RELRO)
+                 if (phdr2[i].p_type == PT_GNU_RELRO
+                     || phdr2[i].p_type == PT_TLS)
                    {
                      Elf32_External_Phdr tmp_phdr = *phdrp;
                      Elf32_External_Phdr tmp_phdr2 = *phdr2p;
@@ -2795,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)
                    {
@@ -2802,7 +2876,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz;
                      CORE_ADDR filesz;
 
-                     content2 = (bfd_get_section_flags (exec_bfd, plt2_asect)
+                     content2 = (bfd_section_flags (plt2_asect)
                                  & SEC_HAS_CONTENTS) != 0;
 
                      filesz = extract_unsigned_integer (buf_filesz_p, 4,
@@ -2811,9 +2885,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      /* PLT2_ASECT is from on-disk file (exec_bfd) while
                         FILESZ is from the in-memory image.  */
                      if (content2)
-                       filesz += bfd_get_section_size (plt2_asect);
+                       filesz += bfd_section_size (plt2_asect);
                      else
-                       filesz -= bfd_get_section_size (plt2_asect);
+                       filesz -= bfd_section_size (plt2_asect);
 
                      store_unsigned_integer (buf_filesz_p, 4, byte_order,
                                              filesz);
@@ -2822,16 +2896,17 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                        continue;
                    }
 
-                 ok = 0;
-                 break;
+                 return 0;
                }
            }
          else if (arch_size == 64
-                  && phdrs_size >= sizeof (Elf64_External_Phdr)
-                  && phdrs_size % sizeof (Elf64_External_Phdr) == 0)
+                  && phdrs_target->size () >= sizeof (Elf64_External_Phdr)
+                  && 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;
 
@@ -2849,7 +2924,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                    CORE_ADDR displacement_vaddr = 0;
                    CORE_ADDR displacement_paddr = 0;
 
-                   phdrp = &((Elf64_External_Phdr *) buf)[i];
+                   phdrp = &((Elf64_External_Phdr *) phdrs_target->data ())[i];
                    buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
                    buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
 
@@ -2869,7 +2944,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
 
              /* Now compare BUF and BUF2 with optional DISPLACEMENT.  */
 
-             for (i = 0; i < phdrs_size / sizeof (Elf64_External_Phdr); i++)
+             for (i = 0;
+                  i < phdrs_target->size () / sizeof (Elf64_External_Phdr);
+                  i++)
                {
                  Elf64_External_Phdr *phdrp;
                  Elf64_External_Phdr *phdr2p;
@@ -2877,10 +2954,10 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                  CORE_ADDR vaddr, paddr;
                  asection *plt2_asect;
 
-                 phdrp = &((Elf64_External_Phdr *) buf)[i];
+                 phdrp = &((Elf64_External_Phdr *) phdrs_target->data ())[i];
                  buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
                  buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
-                 phdr2p = &((Elf64_External_Phdr *) buf2)[i];
+                 phdr2p = &((Elf64_External_Phdr *) phdrs_binary->data ())[i];
 
                  /* PT_GNU_STACK is an exception by being never relocated by
                     prelink as its addresses are always zero.  */
@@ -2905,8 +2982,10 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
 
                  /* Strip modifies the flags and alignment of PT_GNU_RELRO.
                     CentOS-5 has problems with filesz, memsz as well.
+                    Strip also modifies memsz of PT_TLS.
                     See PR 11786.  */
-                 if (phdr2[i].p_type == PT_GNU_RELRO)
+                 if (phdr2[i].p_type == PT_GNU_RELRO
+                     || phdr2[i].p_type == PT_TLS)
                    {
                      Elf64_External_Phdr tmp_phdr = *phdrp;
                      Elf64_External_Phdr tmp_phdr2 = *phdr2p;
@@ -2926,25 +3005,28 @@ 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;
                      gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz;
                      CORE_ADDR filesz;
 
-                     content2 = (bfd_get_section_flags (exec_bfd, plt2_asect)
+                     content2 = (bfd_section_flags (plt2_asect)
                                  & SEC_HAS_CONTENTS) != 0;
 
                      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_get_section_size (plt2_asect);
+                       filesz += bfd_section_size (plt2_asect);
                      else
-                       filesz -= bfd_get_section_size (plt2_asect);
+                       filesz -= bfd_section_size (plt2_asect);
 
                      store_unsigned_integer (buf_filesz_p, 8, byte_order,
                                              filesz);
@@ -2953,19 +3035,12 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                        continue;
                    }
 
-                 ok = 0;
-                 break;
+                 return 0;
                }
            }
          else
-           ok = 0;
+           return 0;
        }
-
-      xfree (buf);
-      xfree (buf2);
-
-      if (!ok)
-       return 0;
     }
 
   if (info_verbose)
@@ -2974,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;
@@ -3026,27 +3101,21 @@ 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)
     {
-      struct section_offsets *new_offsets;
-      int i;
-
-      new_offsets = XALLOCAVEC (struct section_offsets,
-                               symfile_objfile->num_sections);
-
-      for (i = 0; i < symfile_objfile->num_sections; i++)
-       new_offsets->offsets[i] = displacement;
-
-      objfile_relocate (symfile_objfile, new_offsets);
+      section_offsets new_offsets (objf->section_offsets.size (),
+                                  displacement);
+      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 (exec_bfd, asect)
-                                  + displacement));
+                                 bfd_section_vma (asect) + displacement);
     }
 }
 
@@ -3074,18 +3143,18 @@ svr4_solib_create_inferior_hook (int from_tty)
 {
   struct svr4_info *info;
 
-  info = get_svr4_info ();
+  info = get_svr4_info (current_program_space);
 
   /* 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 ())
@@ -3100,7 +3169,7 @@ svr4_clear_solib (void)
 {
   struct svr4_info *info;
 
-  info = get_svr4_info ();
+  info = get_svr4_info (current_program_space);
   info->debug_base = 0;
   info->debug_loader_offset_p = 0;
   info->debug_loader_offset = 0;
@@ -3135,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;
 
@@ -3146,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;
 }
 
@@ -3172,14 +3240,15 @@ 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);
 }
 
 /* Fetch a link_map_offsets structure using the architecture-specific
@@ -3188,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 ();
@@ -3201,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);
 }
@@ -3211,7 +3276,7 @@ svr4_have_link_map_offsets (void)
 
 /* Most OS'es that have SVR4-style ELF dynamic libraries define a
    `struct r_debug' and a `struct link_map' that are binary compatible
-   with the origional SVR4 implementation.  */
+   with the original SVR4 implementation.  */
 
 /* Fetch (and possibly build) an appropriate `struct link_map_offsets'
    for an ILP32 SVR4 system.  */
@@ -3231,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;
@@ -3262,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;
@@ -3276,56 +3343,142 @@ 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;
 
-/* Lookup global symbol 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.  */
+  for (so_list *so : current_program_space->solibs ())
+    if (so->objfile == objfile)
+      return so;
+
+  return nullptr;
+}
 
-static struct block_symbol
-elf_lookup_lib_symbol (struct objfile *objfile,
-                      const char *name,
-                      const domain_enum domain)
+/* 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)
 {
-  bfd *abfd;
+  if (solib == nullptr)
+    return 0;
 
-  if (objfile == symfile_objfile)
-    abfd = exec_bfd;
-  else
+  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)
     {
-      /* OBJFILE should have been passed as the non-debug one.  */
-      gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+      CORE_ADDR debug_base = tuple.first;
+      so_list *solist = tuple.second;
 
-      abfd = objfile->obfd;
+      for (; solist != nullptr; solist = solist->next)
+       if (svr4_same (solib, solist))
+         return debug_base;
     }
 
-  if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL, NULL) != 1)
-    return (struct block_symbol) {NULL, NULL};
+  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.  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
+  (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
+   objfile *current_objfile)
+{
+  bool checked_current_objfile = false;
+  if (current_objfile != nullptr)
+    {
+      bfd *abfd;
+
+      if (current_objfile->separate_debug_objfile_backlink != nullptr)
+       current_objfile = current_objfile->separate_debug_objfile_backlink;
+
+      if (current_objfile == current_program_space->symfile_object_file)
+       abfd = current_program_space->exec_bfd ();
+      else
+       abfd = current_objfile->obfd.get ();
+
+      if (abfd != nullptr
+         && gdb_bfd_scan_elf_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
+       {
+         checked_current_objfile = true;
+         if (cb (current_objfile))
+           return;
+       }
+    }
 
-  return lookup_global_symbol_from_objfile (objfile, name, domain);
+  /* 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;
+
+      /* 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;
+    }
 }
 
-extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
+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);
-  solib_svr4_pspace_data
-    = register_program_space_data_with_cleanup (NULL, svr4_pspace_data_cleanup);
-
-  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.lookup_lib_global_symbol = elf_lookup_lib_symbol;
-  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;
+_initialize_svr4_solib ()
+{
+  gdb::observers::free_objfile.attach (svr4_free_objfile_observer,
+                                      "solib-svr4");
 }