Remove expecting_notif parameter from getpkt_or_notif_sane_1
[binutils-gdb.git] / gdbserver / linux-low.cc
index 0a5b60631044afbc56313f8057a0fdde5bd04f20..e1806ade82f076672d6a8d5e37b94b7ace315e71 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level interface to ptrace, for the remote server for GDB.
-   Copyright (C) 1995-2022 Free Software Foundation, Inc.
+   Copyright (C) 1995-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -135,6 +135,15 @@ typedef struct
 /* Does the current host support PTRACE_GETREGSET?  */
 int have_ptrace_getregset = -1;
 
+/* Return TRUE if THREAD is the leader thread of the process.  */
+
+static bool
+is_leader (thread_info *thread)
+{
+  ptid_t ptid = ptid_of (thread);
+  return ptid.pid () == ptid.lwp ();
+}
+
 /* LWP accessors.  */
 
 /* See nat/linux-nat.h.  */
@@ -394,8 +403,22 @@ linux_process_target::low_delete_thread (arch_lwp_info *info)
   gdb_assert (info == nullptr);
 }
 
+/* Open the /proc/PID/mem file for PROC.  */
+
+static void
+open_proc_mem_file (process_info *proc)
+{
+  gdb_assert (proc->priv->mem_fd == -1);
+
+  char filename[64];
+  xsnprintf (filename, sizeof filename, "/proc/%d/mem", proc->pid);
+
+  proc->priv->mem_fd
+    = gdb_open_cloexec (filename, O_RDWR | O_LARGEFILE, 0).release ();
+}
+
 process_info *
-linux_process_target::add_linux_process (int pid, int attached)
+linux_process_target::add_linux_process_no_mem_file (int pid, int attached)
 {
   struct process_info *proc;
 
@@ -403,10 +426,34 @@ linux_process_target::add_linux_process (int pid, int attached)
   proc->priv = XCNEW (struct process_info_private);
 
   proc->priv->arch_private = low_new_process ();
+  proc->priv->mem_fd = -1;
+
+  return proc;
+}
 
+
+process_info *
+linux_process_target::add_linux_process (int pid, int attached)
+{
+  process_info *proc = add_linux_process_no_mem_file (pid, attached);
+  open_proc_mem_file (proc);
   return proc;
 }
 
+void
+linux_process_target::remove_linux_process (process_info *proc)
+{
+  if (proc->priv->mem_fd >= 0)
+    close (proc->priv->mem_fd);
+
+  this->low_delete_process (proc->priv->arch_private);
+
+  xfree (proc->priv);
+  proc->priv = nullptr;
+
+  remove_process (proc);
+}
+
 arch_process_info *
 linux_process_target::low_new_process ()
 {
@@ -694,14 +741,14 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp,
       return 0;
     }
 
-  internal_error (__FILE__, __LINE__, _("unknown ptrace event %d"), event);
+  internal_error (_("unknown ptrace event %d"), event);
 }
 
 CORE_ADDR
 linux_process_target::get_pc (lwp_info *lwp)
 {
-  struct regcache *regcache;
-  CORE_ADDR pc;
+  process_info *proc = get_thread_process (get_lwp_thread (lwp));
+  gdb_assert (!proc->starting_up);
 
   if (!low_supports_breakpoints ())
     return 0;
@@ -709,8 +756,8 @@ linux_process_target::get_pc (lwp_info *lwp)
   scoped_restore_current_thread restore_thread;
   switch_to_thread (get_lwp_thread (lwp));
 
-  regcache = get_thread_regcache (current_thread, 1);
-  pc = low_get_pc (regcache);
+  struct regcache *regcache = get_thread_regcache (current_thread, 1);
+  CORE_ADDR pc = low_get_pc (regcache);
 
   threads_debug_printf ("pc is 0x%lx", (long) pc);
 
@@ -750,6 +797,14 @@ linux_process_target::save_stop_reason (lwp_info *lwp)
   if (!low_supports_breakpoints ())
     return false;
 
+  process_info *proc = get_thread_process (get_lwp_thread (lwp));
+  if (proc->starting_up)
+    {
+      /* Claim we have the stop PC so that the caller doesn't try to
+        fetch it itself.  */
+      return true;
+    }
+
   pc = get_pc (lwp);
   sw_breakpoint_pc = pc - low_decr_pc_after_break ();
 
@@ -923,7 +978,11 @@ linux_process_target::create_inferior (const char *program,
                         NULL, NULL, NULL, NULL);
   }
 
-  add_linux_process (pid, 0);
+  /* When spawning a new process, we can't open the mem file yet.  We
+     still have to nurse the process through the shell, and that execs
+     a couple times.  The address space a /proc/PID/mem file is
+     accessing is destroyed on exec.  */
+  process_info *proc = add_linux_process_no_mem_file (pid, 0);
 
   ptid = ptid_t (pid, pid);
   new_lwp = add_lwp (ptid);
@@ -931,6 +990,10 @@ linux_process_target::create_inferior (const char *program,
 
   post_fork_inferior (pid, program);
 
+  /* PROC is now past the shell running the program we want, so we can
+     open the /proc/PID/mem file.  */
+  open_proc_mem_file (proc);
+
   return pid;
 }
 
@@ -1086,19 +1149,23 @@ linux_process_target::attach (unsigned long pid)
   ptid_t ptid = ptid_t (pid, pid);
   int err;
 
-  proc = add_linux_process (pid, 1);
+  /* Delay opening the /proc/PID/mem file until we've successfully
+     attached.  */
+  proc = add_linux_process_no_mem_file (pid, 1);
 
   /* Attach to PID.  We will check for other threads
      soon.  */
   err = attach_lwp (ptid);
   if (err != 0)
     {
-      remove_process (proc);
+      this->remove_linux_process (proc);
 
       std::string reason = linux_ptrace_attach_fail_reason_string (ptid, err);
       error ("Cannot attach to process %ld: %s", pid, reason.c_str ());
     }
 
+  open_proc_mem_file (proc);
+
   /* Don't ignore the initial SIGSTOP if we just attached to this
      process.  It will be collected by wait shortly.  */
   initial_thread = find_thread_ptid (ptid_t (pid, pid));
@@ -1520,8 +1587,6 @@ linux_process_target::detach (process_info *process)
 void
 linux_process_target::mourn (process_info *process)
 {
-  struct process_info_private *priv;
-
 #ifdef USE_THREAD_DB
   thread_db_mourn (process);
 #endif
@@ -1531,13 +1596,7 @@ linux_process_target::mourn (process_info *process)
       delete_lwp (get_thread_lwp (thread));
     });
 
-  /* Freeing all private data.  */
-  priv = process->priv;
-  low_delete_process (priv->arch_private);
-  free (priv);
-  process->priv = NULL;
-
-  remove_process (process);
+  this->remove_linux_process (process);
 }
 
 void
@@ -1672,9 +1731,9 @@ linux_process_target::status_pending_p_callback (thread_info *thread,
 struct lwp_info *
 find_lwp_pid (ptid_t ptid)
 {
-  thread_info *thread = find_thread ([&] (thread_info *thr_arg)
+  long lwp = ptid.lwp () != 0 ? ptid.lwp () : ptid.pid ();
+  thread_info *thread = find_thread ([lwp] (thread_info *thr_arg)
     {
-      int lwp = ptid.lwp () != 0 ? ptid.lwp () : ptid.pid ();
       return thr_arg->id.lwp () == lwp;
     });
 
@@ -1721,57 +1780,77 @@ iterate_over_lwps (ptid_t filter,
 void
 linux_process_target::check_zombie_leaders ()
 {
-  for_each_process ([this] (process_info *proc) {
-    pid_t leader_pid = pid_of (proc);
-    struct lwp_info *leader_lp;
-
-    leader_lp = find_lwp_pid (ptid_t (leader_pid));
-
-    threads_debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
-                         "num_lwps=%d, zombie=%d",
-                         leader_pid, leader_lp!= NULL, num_lwps (leader_pid),
-                         linux_proc_pid_is_zombie (leader_pid));
-
-    if (leader_lp != NULL && !leader_lp->stopped
-       /* Check if there are other threads in the group, as we may
-          have raced with the inferior simply exiting.  */
-       && !last_thread_of_process_p (leader_pid)
-       && linux_proc_pid_is_zombie (leader_pid))
-      {
-       /* A leader zombie can mean one of two things:
-
-          - It exited, and there's an exit status pending
-          available, or only the leader exited (not the whole
-          program).  In the latter case, we can't waitpid the
-          leader's exit status until all other threads are gone.
-
-          - There are 3 or more threads in the group, and a thread
-          other than the leader exec'd.  On an exec, the Linux
-          kernel destroys all other threads (except the execing
-          one) in the thread group, and resets the execing thread's
-          tid to the tgid.  No exit notification is sent for the
-          execing thread -- from the ptracer's perspective, it
-          appears as though the execing thread just vanishes.
-          Until we reap all other threads except the leader and the
-          execing thread, the leader will be zombie, and the
-          execing thread will be in `D (disc sleep)'.  As soon as
-          all other threads are reaped, the execing thread changes
-          it's tid to the tgid, and the previous (zombie) leader
-          vanishes, giving place to the "new" leader.  We could try
-          distinguishing the exit and exec cases, by waiting once
-          more, and seeing if something comes out, but it doesn't
-          sound useful.  The previous leader _does_ go away, and
-          we'll re-add the new one once we see the exec event
-          (which is just the same as what would happen if the
-          previous leader did exit voluntarily before some other
-          thread execs).  */
-
-       threads_debug_printf ("Thread group leader %d zombie "
-                             "(it exited, or another thread execd).",
-                             leader_pid);
-
-       delete_lwp (leader_lp);
-      }
+  for_each_process ([this] (process_info *proc)
+    {
+      pid_t leader_pid = pid_of (proc);
+      lwp_info *leader_lp = find_lwp_pid (ptid_t (leader_pid));
+
+      threads_debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
+                           "num_lwps=%d, zombie=%d",
+                           leader_pid, leader_lp!= NULL, num_lwps (leader_pid),
+                           linux_proc_pid_is_zombie (leader_pid));
+
+      if (leader_lp != NULL && !leader_lp->stopped
+         /* Check if there are other threads in the group, as we may
+            have raced with the inferior simply exiting.  Note this
+            isn't a watertight check.  If the inferior is
+            multi-threaded and is exiting, it may be we see the
+            leader as zombie before we reap all the non-leader
+            threads.  See comments below.  */
+         && !last_thread_of_process_p (leader_pid)
+         && linux_proc_pid_is_zombie (leader_pid))
+       {
+         /* A zombie leader in a multi-threaded program can mean one
+            of three things:
+
+            #1 - Only the leader exited, not the whole program, e.g.,
+            with pthread_exit.  Since we can't reap the leader's exit
+            status until all other threads are gone and reaped too,
+            we want to delete the zombie leader right away, as it
+            can't be debugged, we can't read its registers, etc.
+            This is the main reason we check for zombie leaders
+            disappearing.
+
+            #2 - The whole thread-group/process exited (a group exit,
+            via e.g. exit(3), and there is (or will be shortly) an
+            exit reported for each thread in the process, and then
+            finally an exit for the leader once the non-leaders are
+            reaped.
+
+            #3 - There are 3 or more threads in the group, and a
+            thread other than the leader exec'd.  See comments on
+            exec events at the top of the file.
+
+            Ideally we would never delete the leader for case #2.
+            Instead, we want to collect the exit status of each
+            non-leader thread, and then finally collect the exit
+            status of the leader as normal and use its exit code as
+            whole-process exit code.  Unfortunately, there's no
+            race-free way to distinguish cases #1 and #2.  We can't
+            assume the exit events for the non-leaders threads are
+            already pending in the kernel, nor can we assume the
+            non-leader threads are in zombie state already.  Between
+            the leader becoming zombie and the non-leaders exiting
+            and becoming zombie themselves, there's a small time
+            window, so such a check would be racy.  Temporarily
+            pausing all threads and checking to see if all threads
+            exit or not before re-resuming them would work in the
+            case that all threads are running right now, but it
+            wouldn't work if some thread is currently already
+            ptrace-stopped, e.g., due to scheduler-locking.
+
+            So what we do is we delete the leader anyhow, and then
+            later on when we see its exit status, we re-add it back.
+            We also make sure that we only report a whole-process
+            exit when we see the leader exiting, as opposed to when
+            the last LWP in the LWP list exits, which can be a
+            non-leader if we deleted the leader here.  */
+         threads_debug_printf ("Thread group leader %d zombie "
+                               "(it exited, or another thread execd), "
+                               "deleting it.",
+                               leader_pid);
+         delete_lwp (leader_lp);
+       }
     });
 }
 
@@ -1813,8 +1892,7 @@ lwp_suspended_decr (struct lwp_info *lwp)
     {
       struct thread_info *thread = get_lwp_thread (lwp);
 
-      internal_error (__FILE__, __LINE__,
-                     "unsuspend LWP %ld, suspended=%d\n", lwpid_of (thread),
+      internal_error ("unsuspend LWP %ld, suspended=%d\n", lwpid_of (thread),
                      lwp->suspended);
     }
 }
@@ -2148,46 +2226,65 @@ linux_process_target::filter_event (int lwpid, int wstat)
 
   child = find_lwp_pid (ptid_t (lwpid));
 
-  /* Check for stop events reported by a process we didn't already
-     know about - anything not already in our LWP list.
-
-     If we're expecting to receive stopped processes after
-     fork, vfork, and clone events, then we'll just add the
-     new one to our list and go back to waiting for the event
-     to be reported - the stopped process might be returned
-     from waitpid before or after the event is.
-
-     But note the case of a non-leader thread exec'ing after the
-     leader having exited, and gone from our lists (because
-     check_zombie_leaders deleted it).  The non-leader thread
-     changes its tid to the tgid.  */
-
-  if (WIFSTOPPED (wstat) && child == NULL && WSTOPSIG (wstat) == SIGTRAP
-      && linux_ptrace_get_extended_event (wstat) == PTRACE_EVENT_EXEC)
+  /* Check for events reported by anything not in our LWP list.  */
+  if (child == nullptr)
     {
-      ptid_t child_ptid;
+      if (WIFSTOPPED (wstat))
+       {
+         if (WSTOPSIG (wstat) == SIGTRAP
+             && linux_ptrace_get_extended_event (wstat) == PTRACE_EVENT_EXEC)
+           {
+             /* A non-leader thread exec'ed after we've seen the
+                leader zombie, and removed it from our lists (in
+                check_zombie_leaders).  The non-leader thread changes
+                its tid to the tgid.  */
+             threads_debug_printf
+               ("Re-adding thread group leader LWP %d after exec.",
+                lwpid);
 
-      /* A multi-thread exec after we had seen the leader exiting.  */
-      threads_debug_printf ("Re-adding thread group leader LWP %d after exec.",
-                           lwpid);
+             child = add_lwp (ptid_t (lwpid, lwpid));
+             child->stopped = 1;
+             switch_to_thread (child->thread);
+           }
+         else
+           {
+             /* A process we are controlling has forked and the new
+                child's stop was reported to us by the kernel.  Save
+                its PID and go back to waiting for the fork event to
+                be reported - the stopped process might be returned
+                from waitpid before or after the fork event is.  */
+             threads_debug_printf
+               ("Saving LWP %d status %s in stopped_pids list",
+                lwpid, status_to_str (wstat).c_str ());
+             add_to_pid_list (&stopped_pids, lwpid, wstat);
+           }
+       }
+      else
+       {
+         /* Don't report an event for the exit of an LWP not in our
+            list, i.e. not part of any inferior we're debugging.
+            This can happen if we detach from a program we originally
+            forked and then it exits.  However, note that we may have
+            earlier deleted a leader of an inferior we're debugging,
+            in check_zombie_leaders.  Re-add it back here if so.  */
+         find_process ([&] (process_info *proc)
+           {
+             if (proc->pid == lwpid)
+               {
+                 threads_debug_printf
+                   ("Re-adding thread group leader LWP %d after exit.",
+                    lwpid);
 
-      child_ptid = ptid_t (lwpid, lwpid);
-      child = add_lwp (child_ptid);
-      child->stopped = 1;
-      switch_to_thread (child->thread);
-    }
+                 child = add_lwp (ptid_t (lwpid, lwpid));
+                 return true;
+               }
+             return false;
+           });
+       }
 
-  /* If we didn't find a process, one of two things presumably happened:
-     - A process we started and then detached from has exited.  Ignore it.
-     - A process we are controlling has forked and the new child's stop
-     was reported to us by the kernel.  Save its PID.  */
-  if (child == NULL && WIFSTOPPED (wstat))
-    {
-      add_to_pid_list (&stopped_pids, lwpid, wstat);
-      return;
+      if (child == nullptr)
+       return;
     }
-  else if (child == NULL)
-    return;
 
   thread = get_lwp_thread (child);
 
@@ -2206,11 +2303,10 @@ linux_process_target::filter_event (int lwpid, int wstat)
          unsuspend_all_lwps (child);
        }
 
-      /* If there is at least one more LWP, then the exit signal was
-        not the end of the debugged application and should be
-        ignored, unless GDB wants to hear about thread exits.  */
-      if (cs.report_thread_events
-         || last_thread_of_process_p (pid_of (thread)))
+      /* If this is not the leader LWP, then the exit signal was not
+        the end of the debugged application and should be ignored,
+        unless GDB wants to hear about thread exits.  */
+      if (cs.report_thread_events || is_leader (thread))
        {
          /* Since events are serialized to GDB core, and we can't
             report this one right now.  Leave the status pending for
@@ -2367,7 +2463,12 @@ linux_process_target::resume_stopped_resumed_lwps (thread_info *thread)
       int step = 0;
 
       if (thread->last_resume_kind == resume_step)
-       step = maybe_hw_step (thread);
+       {
+         if (supports_software_single_step ())
+           install_software_single_step_breakpoints (lp);
+
+         step = maybe_hw_step (thread);
+       }
 
       threads_debug_printf ("resuming stopped-resumed LWP %s at %s: step=%d",
                            target_pid_to_str (ptid_of (thread)).c_str (),
@@ -2427,8 +2528,7 @@ linux_process_target::wait_for_event_filtered (ptid_t wait_ptid,
       if (requested_child->suspended
          && requested_child->status_pending_p)
        {
-         internal_error (__FILE__, __LINE__,
-                         "requesting an event out of a"
+         internal_error ("requesting an event out of a"
                          " suspended child?");
        }
 
@@ -2777,7 +2877,7 @@ linux_process_target::filter_exit_event (lwp_info *event_child,
   struct thread_info *thread = get_lwp_thread (event_child);
   ptid_t ptid = ptid_of (thread);
 
-  if (!last_thread_of_process_p (pid_of (thread)))
+  if (!is_leader (thread))
     {
       if (cs.report_thread_events)
        ourstatus->set_thread_exited (0);
@@ -3422,6 +3522,9 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
        unstop_all_lwps (1, event_child);
     }
 
+  /* At this point, we haven't set OURSTATUS.  This is where we do it.  */
+  gdb_assert (ourstatus->kind () == TARGET_WAITKIND_IGNORE);
+
   if (event_child->waitstatus.kind () != TARGET_WAITKIND_IGNORE)
     {
       /* If the reported event is an exit, fork, vfork or exec, let
@@ -3441,8 +3544,31 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
     }
   else
     {
-      /* The actual stop signal is overwritten below.  */
-      ourstatus->set_stopped (GDB_SIGNAL_0);
+      /* The LWP stopped due to a plain signal or a syscall signal.  Either way,
+        event_child->waitstatus wasn't filled in with the details, so look at
+        the wait status W.  */
+      if (WSTOPSIG (w) == SYSCALL_SIGTRAP)
+       {
+         int syscall_number;
+
+         get_syscall_trapinfo (event_child, &syscall_number);
+         if (event_child->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY)
+           ourstatus->set_syscall_entry (syscall_number);
+         else if (event_child->syscall_state == TARGET_WAITKIND_SYSCALL_RETURN)
+           ourstatus->set_syscall_return (syscall_number);
+         else
+           gdb_assert_not_reached ("unexpected syscall state");
+       }
+      else if (current_thread->last_resume_kind == resume_stop
+              && WSTOPSIG (w) == SIGSTOP)
+       {
+         /* A thread that has been requested to stop by GDB with vCont;t,
+            and it stopped cleanly, so report as SIG0.  The use of
+            SIGSTOP is an implementation detail.  */
+         ourstatus->set_stopped (GDB_SIGNAL_0);
+       }
+      else
+       ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w)));
     }
 
   /* Now that we've selected our final event LWP, un-adjust its PC if
@@ -3461,41 +3587,11 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
        }
     }
 
-  if (WSTOPSIG (w) == SYSCALL_SIGTRAP)
-    {
-      int syscall_number;
-
-      get_syscall_trapinfo (event_child, &syscall_number);
-      if (event_child->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY)
-       ourstatus->set_syscall_entry (syscall_number);
-      else if (event_child->syscall_state == TARGET_WAITKIND_SYSCALL_RETURN)
-       ourstatus->set_syscall_return (syscall_number);
-      else
-       gdb_assert_not_reached ("unexpected syscall state");
-    }
-  else if (current_thread->last_resume_kind == resume_stop
-          && WSTOPSIG (w) == SIGSTOP)
-    {
-      /* A thread that has been requested to stop by GDB with vCont;t,
-        and it stopped cleanly, so report as SIG0.  The use of
-        SIGSTOP is an implementation detail.  */
-      ourstatus->set_stopped (GDB_SIGNAL_0);
-    }
-  else if (current_thread->last_resume_kind == resume_stop
-          && WSTOPSIG (w) != SIGSTOP)
-    {
-      /* A thread that has been requested to stop by GDB with vCont;t,
-        but, it stopped for other reasons.  */
-      ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w)));
-    }
-  else if (ourstatus->kind () == TARGET_WAITKIND_STOPPED)
-    ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w)));
-
   gdb_assert (step_over_bkpt == null_ptid);
 
-  threads_debug_printf ("ret = %s, %d, %d",
+  threads_debug_printf ("ret = %s, %s",
                        target_pid_to_str (ptid_of (current_thread)).c_str (),
-                       ourstatus->kind (), ourstatus->sig ());
+                       ourstatus->to_string ().c_str ());
 
   if (ourstatus->kind () == TARGET_WAITKIND_EXITED)
     return filter_exit_event (event_child, ourstatus);
@@ -3700,8 +3796,7 @@ linux_process_target::stuck_in_jump_pad (thread_info *thread)
 
   if (lwp->suspended != 0)
     {
-      internal_error (__FILE__, __LINE__,
-                     "LWP %ld is suspended, suspended=%d\n",
+      internal_error ("LWP %ld is suspended, suspended=%d\n",
                      lwpid_of (thread), lwp->suspended);
     }
   gdb_assert (lwp->stopped);
@@ -3724,8 +3819,7 @@ linux_process_target::move_out_of_jump_pad (thread_info *thread)
 
   if (lwp->suspended != 0)
     {
-      internal_error (__FILE__, __LINE__,
-                     "LWP %ld is suspended, suspended=%d\n",
+      internal_error ("LWP %ld is suspended, suspended=%d\n",
                      lwpid_of (thread), lwp->suspended);
     }
   gdb_assert (lwp->stopped);
@@ -3974,8 +4068,7 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step,
        step = 1;
       else
        {
-         internal_error (__FILE__, __LINE__,
-                         "moving out of jump pad single-stepping"
+         internal_error ("moving out of jump pad single-stepping"
                          " not implemented on this target");
        }
     }
@@ -4044,7 +4137,15 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step,
          (PTRACE_TYPE_ARG4) (uintptr_t) signal);
 
   if (errno)
-    perror_with_name ("resuming thread");
+    {
+      int saved_errno = errno;
+
+      threads_debug_printf ("ptrace errno = %d (%s)",
+                           saved_errno, strerror (saved_errno));
+
+      errno = saved_errno;
+      perror_with_name ("resuming thread");
+    }
 
   /* Successfully resumed.  Clear state that no longer makes sense,
      and mark the LWP as running.  Must not do this before resuming
@@ -4105,7 +4206,15 @@ linux_process_target::resume_one_lwp (lwp_info *lwp, int step, int signal,
     }
   catch (const gdb_exception_error &ex)
     {
-      if (!check_ptrace_stopped_lwp_gone (lwp))
+      if (check_ptrace_stopped_lwp_gone (lwp))
+       {
+         /* This could because we tried to resume an LWP after its leader
+            exited.  Mark it as resumed, so we can collect an exit event
+            from it.  */
+         lwp->stopped = 0;
+         lwp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+       }
+      else
        throw;
     }
 }
@@ -4360,8 +4469,7 @@ linux_process_target::start_step_over (lwp_info *lwp)
 
   if (lwp->suspended != 0)
     {
-      internal_error (__FILE__, __LINE__,
-                     "LWP %ld suspended=%d\n", lwpid_of (thread),
+      internal_error ("LWP %ld suspended=%d\n", lwpid_of (thread),
                      lwp->suspended);
     }
 
@@ -5250,93 +5358,76 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
   return the_target->read_memory (memaddr, myaddr, len);
 }
 
-/* Copy LEN bytes from inferior's memory starting at MEMADDR
-   to debugger memory starting at MYADDR.  */
 
-int
-linux_process_target::read_memory (CORE_ADDR memaddr,
-                                  unsigned char *myaddr, int len)
+/* Helper for read_memory/write_memory using /proc/PID/mem.  Because
+   we can use a single read/write call, this can be much more
+   efficient than banging away at PTRACE_PEEKTEXT.  Also, unlike
+   PTRACE_PEEKTEXT/PTRACE_POKETEXT, this works with running threads.
+   One an only one of READBUF and WRITEBUF is non-null.  If READBUF is
+   not null, then we're reading, otherwise we're writing.  */
+
+static int
+proc_xfer_memory (CORE_ADDR memaddr, unsigned char *readbuf,
+                 const gdb_byte *writebuf, int len)
 {
-  int pid = lwpid_of (current_thread);
-  PTRACE_XFER_TYPE *buffer;
-  CORE_ADDR addr;
-  int count;
-  char filename[64];
-  int i;
-  int ret;
-  int fd;
+  gdb_assert ((readbuf == nullptr) != (writebuf == nullptr));
+
+  process_info *proc = current_process ();
+
+  int fd = proc->priv->mem_fd;
+  if (fd == -1)
+    return EIO;
 
-  /* Try using /proc.  Don't bother for one word.  */
-  if (len >= 3 * sizeof (long))
+  while (len > 0)
     {
       int bytes;
 
-      /* We could keep this file open and cache it - possibly one per
-        thread.  That requires some juggling, but is even faster.  */
-      sprintf (filename, "/proc/%d/mem", pid);
-      fd = open (filename, O_RDONLY | O_LARGEFILE);
-      if (fd == -1)
-       goto no_proc;
-
-      /* If pread64 is available, use it.  It's faster if the kernel
-        supports it (only one syscall), and it's 64-bit safe even on
-        32-bit platforms (for instance, SPARC debugging a SPARC64
-        application).  */
+      /* Use pread64/pwrite64 if available, since they save a syscall
+        and can handle 64-bit offsets even on 32-bit platforms (for
+        instance, SPARC debugging a SPARC64 application).  But only
+        use them if the offset isn't so high that when cast to off_t
+        it'd be negative, as seen on SPARC64.  pread64/pwrite64
+        outright reject such offsets.  lseek does not.  */
 #ifdef HAVE_PREAD64
-      bytes = pread64 (fd, myaddr, len, memaddr);
-#else
-      bytes = -1;
-      if (lseek (fd, memaddr, SEEK_SET) != -1)
-       bytes = read (fd, myaddr, len);
+      if ((off_t) memaddr >= 0)
+       bytes = (readbuf != nullptr
+                ? pread64 (fd, readbuf, len, memaddr)
+                : pwrite64 (fd, writebuf, len, memaddr));
+      else
 #endif
-
-      close (fd);
-      if (bytes == len)
-       return 0;
-
-      /* Some data was read, we'll try to get the rest with ptrace.  */
-      if (bytes > 0)
        {
-         memaddr += bytes;
-         myaddr += bytes;
-         len -= bytes;
+         bytes = -1;
+         if (lseek (fd, memaddr, SEEK_SET) != -1)
+           bytes = (readbuf != nullptr
+                    ? read (fd, readbuf, len)
+                    : write (fd, writebuf, len));
        }
-    }
 
- no_proc:
-  /* Round starting address down to longword boundary.  */
-  addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
-  /* Round ending address up; get number of longwords that makes.  */
-  count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
-          / sizeof (PTRACE_XFER_TYPE));
-  /* Allocate buffer of that many longwords.  */
-  buffer = XALLOCAVEC (PTRACE_XFER_TYPE, count);
+      if (bytes < 0)
+       return errno;
+      else if (bytes == 0)
+       {
+         /* EOF means the address space is gone, the whole process
+            exited or execed.  */
+         return EIO;
+       }
 
-  /* Read all the longwords */
-  errno = 0;
-  for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
-    {
-      /* Coerce the 3rd arg to a uintptr_t first to avoid potential gcc warning
-        about coercing an 8 byte integer to a 4 byte pointer.  */
-      buffer[i] = ptrace (PTRACE_PEEKTEXT, pid,
-                         (PTRACE_TYPE_ARG3) (uintptr_t) addr,
-                         (PTRACE_TYPE_ARG4) 0);
-      if (errno)
-       break;
+      memaddr += bytes;
+      if (readbuf != nullptr)
+       readbuf += bytes;
+      else
+       writebuf += bytes;
+      len -= bytes;
     }
-  ret = errno;
 
-  /* Copy appropriate bytes out of the buffer.  */
-  if (i > 0)
-    {
-      i *= sizeof (PTRACE_XFER_TYPE);
-      i -= memaddr & (sizeof (PTRACE_XFER_TYPE) - 1);
-      memcpy (myaddr,
-             (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
-             i < len ? i : len);
-    }
+  return 0;
+}
 
-  return ret;
+int
+linux_process_target::read_memory (CORE_ADDR memaddr,
+                                  unsigned char *myaddr, int len)
+{
+  return proc_xfer_memory (memaddr, myaddr, nullptr, len);
 }
 
 /* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
@@ -5347,25 +5438,6 @@ int
 linux_process_target::write_memory (CORE_ADDR memaddr,
                                    const unsigned char *myaddr, int len)
 {
-  int i;
-  /* Round starting address down to longword boundary.  */
-  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
-  /* Round ending address up; get number of longwords that makes.  */
-  int count
-    = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
-    / sizeof (PTRACE_XFER_TYPE);
-
-  /* Allocate buffer of that many longwords.  */
-  PTRACE_XFER_TYPE *buffer = XALLOCAVEC (PTRACE_XFER_TYPE, count);
-
-  int pid = lwpid_of (current_thread);
-
-  if (len == 0)
-    {
-      /* Zero length write always succeeds.  */
-      return 0;
-    }
-
   if (debug_threads)
     {
       /* Dump up to four bytes.  */
@@ -5373,7 +5445,7 @@ linux_process_target::write_memory (CORE_ADDR memaddr,
       char *p = str;
       int dump = len < 4 ? len : 4;
 
-      for (i = 0; i < dump; i++)
+      for (int i = 0; i < dump; i++)
        {
          sprintf (p, "%02x", myaddr[i]);
          p += 2;
@@ -5381,54 +5453,10 @@ linux_process_target::write_memory (CORE_ADDR memaddr,
       *p = '\0';
 
       threads_debug_printf ("Writing %s to 0x%08lx in process %d",
-                           str, (long) memaddr, pid);
+                           str, (long) memaddr, current_process ()->pid);
     }
 
-  /* Fill start and end extra bytes of buffer with existing memory data.  */
-
-  errno = 0;
-  /* Coerce the 3rd arg to a uintptr_t first to avoid potential gcc warning
-     about coercing an 8 byte integer to a 4 byte pointer.  */
-  buffer[0] = ptrace (PTRACE_PEEKTEXT, pid,
-                     (PTRACE_TYPE_ARG3) (uintptr_t) addr,
-                     (PTRACE_TYPE_ARG4) 0);
-  if (errno)
-    return errno;
-
-  if (count > 1)
-    {
-      errno = 0;
-      buffer[count - 1]
-       = ptrace (PTRACE_PEEKTEXT, pid,
-                 /* Coerce to a uintptr_t first to avoid potential gcc warning
-                    about coercing an 8 byte integer to a 4 byte pointer.  */
-                 (PTRACE_TYPE_ARG3) (uintptr_t) (addr + (count - 1)
-                                                 * sizeof (PTRACE_XFER_TYPE)),
-                 (PTRACE_TYPE_ARG4) 0);
-      if (errno)
-       return errno;
-    }
-
-  /* Copy data to be written over corresponding part of buffer.  */
-
-  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
-         myaddr, len);
-
-  /* Write the entire buffer.  */
-
-  for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
-    {
-      errno = 0;
-      ptrace (PTRACE_POKETEXT, pid,
-             /* Coerce to a uintptr_t first to avoid potential gcc warning
-                about coercing an 8 byte integer to a 4 byte pointer.  */
-             (PTRACE_TYPE_ARG3) (uintptr_t) addr,
-             (PTRACE_TYPE_ARG4) buffer[i]);
-      if (errno)
-       return errno;
-    }
-
-  return 0;
+  return proc_xfer_memory (memaddr, nullptr, myaddr, len);
 }
 
 void
@@ -5449,7 +5477,10 @@ linux_process_target::request_interrupt ()
 {
   /* Send a SIGINT to the process group.  This acts just like the user
      typed a ^C on the controlling terminal.  */
-  ::kill (-signal_pid, SIGINT);
+  int res = ::kill (-signal_pid, SIGINT);
+  if (res == -1)
+    warning (_("Sending SIGINT to process group of pid %ld failed: %s"),
+            signal_pid, safe_strerror (errno));
 }
 
 bool
@@ -5462,12 +5493,11 @@ linux_process_target::supports_read_auxv ()
    to debugger memory starting at MYADDR.  */
 
 int
-linux_process_target::read_auxv (CORE_ADDR offset, unsigned char *myaddr,
-                                unsigned int len)
+linux_process_target::read_auxv (int pid, CORE_ADDR offset,
+                                unsigned char *myaddr, unsigned int len)
 {
   char filename[PATH_MAX];
   int fd, n;
-  int pid = lwpid_of (current_thread);
 
   xsnprintf (filename, sizeof filename, "/proc/%d/auxv", pid);
 
@@ -6132,25 +6162,6 @@ linux_process_target::unpause_all (bool unfreeze)
   unstop_all_lwps (unfreeze, NULL);
 }
 
-int
-linux_process_target::prepare_to_access_memory ()
-{
-  /* Neither ptrace nor /proc/PID/mem allow accessing memory through a
-     running LWP.  */
-  if (non_stop)
-    target_pause_all (true);
-  return 0;
-}
-
-void
-linux_process_target::done_accessing_memory ()
-{
-  /* Neither ptrace nor /proc/PID/mem allow accessing memory through a
-     running LWP.  */
-  if (non_stop)
-    target_unpause_all (true);
-}
-
 /* Extract &phdr and num_phdr in the inferior.  Return 0 on success.  */
 
 static int
@@ -6438,6 +6449,9 @@ struct link_map_offsets
     /* Offset and size of r_debug.r_map.  */
     int r_map_offset;
 
+    /* Offset of r_debug_extended.r_next.  */
+    int r_next_offset;
+
     /* Offset to l_addr field in struct link_map.  */
     int l_addr_offset;
 
@@ -6454,6 +6468,79 @@ struct link_map_offsets
     int l_prev_offset;
   };
 
+static const link_map_offsets lmo_32bit_offsets =
+  {
+    0,     /* r_version offset.  */
+    4,     /* r_debug.r_map offset.  */
+    20,    /* r_debug_extended.r_next.  */
+    0,     /* l_addr offset in link_map.  */
+    4,     /* l_name offset in link_map.  */
+    8,     /* l_ld offset in link_map.  */
+    12,    /* l_next offset in link_map.  */
+    16     /* l_prev offset in link_map.  */
+  };
+
+static const link_map_offsets lmo_64bit_offsets =
+  {
+    0,     /* r_version offset.  */
+    8,     /* r_debug.r_map offset.  */
+    40,    /* r_debug_extended.r_next.  */
+    0,     /* l_addr offset in link_map.  */
+    8,     /* l_name offset in link_map.  */
+    16,    /* l_ld offset in link_map.  */
+    24,    /* l_next offset in link_map.  */
+    32     /* l_prev offset in link_map.  */
+  };
+
+/* Get the loaded shared libraries from one namespace.  */
+
+static void
+read_link_map (std::string &document, CORE_ADDR lmid, CORE_ADDR lm_addr,
+              CORE_ADDR lm_prev, int ptr_size, const link_map_offsets *lmo)
+{
+  CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
+
+  while (lm_addr
+        && read_one_ptr (lm_addr + lmo->l_name_offset,
+                         &l_name, ptr_size) == 0
+        && read_one_ptr (lm_addr + lmo->l_addr_offset,
+                         &l_addr, ptr_size) == 0
+        && read_one_ptr (lm_addr + lmo->l_ld_offset,
+                         &l_ld, ptr_size) == 0
+        && read_one_ptr (lm_addr + lmo->l_prev_offset,
+                         &l_prev, ptr_size) == 0
+        && read_one_ptr (lm_addr + lmo->l_next_offset,
+                         &l_next, ptr_size) == 0)
+    {
+      unsigned char libname[PATH_MAX];
+
+      if (lm_prev != l_prev)
+       {
+         warning ("Corrupted shared library list: 0x%s != 0x%s",
+                  paddress (lm_prev), paddress (l_prev));
+         break;
+       }
+
+      /* Not checking for error because reading may stop before we've got
+        PATH_MAX worth of characters.  */
+      libname[0] = '\0';
+      linux_read_memory (l_name, libname, sizeof (libname) - 1);
+      libname[sizeof (libname) - 1] = '\0';
+      if (libname[0] != '\0')
+       {
+         string_appendf (document, "<library name=\"");
+         xml_escape_text_append (document, (char *) libname);
+         string_appendf (document, "\" lm=\"0x%s\" l_addr=\"0x%s\" "
+                         "l_ld=\"0x%s\" lmid=\"0x%s\"/>",
+                         paddress (lm_addr), paddress (l_addr),
+                         paddress (l_ld), paddress (lmid));
+       }
+
+      lm_prev = lm_addr;
+      lm_addr = l_next;
+    }
+}
+
 /* Construct qXfer:libraries-svr4:read reply.  */
 
 int
@@ -6465,34 +6552,8 @@ linux_process_target::qxfer_libraries_svr4 (const char *annex,
   struct process_info_private *const priv = current_process ()->priv;
   char filename[PATH_MAX];
   int pid, is_elf64;
-
-  static const struct link_map_offsets lmo_32bit_offsets =
-    {
-      0,     /* r_version offset. */
-      4,     /* r_debug.r_map offset.  */
-      0,     /* l_addr offset in link_map.  */
-      4,     /* l_name offset in link_map.  */
-      8,     /* l_ld offset in link_map.  */
-      12,    /* l_next offset in link_map.  */
-      16     /* l_prev offset in link_map.  */
-    };
-
-  static const struct link_map_offsets lmo_64bit_offsets =
-    {
-      0,     /* r_version offset. */
-      8,     /* r_debug.r_map offset.  */
-      0,     /* l_addr offset in link_map.  */
-      8,     /* l_name offset in link_map.  */
-      16,    /* l_ld offset in link_map.  */
-      24,    /* l_next offset in link_map.  */
-      32     /* l_prev offset in link_map.  */
-    };
-  const struct link_map_offsets *lmo;
   unsigned int machine;
-  int ptr_size;
-  CORE_ADDR lm_addr = 0, lm_prev = 0;
-  CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
-  int header_done = 0;
+  CORE_ADDR lmid = 0, lm_addr = 0, lm_prev = 0;
 
   if (writebuf != NULL)
     return -2;
@@ -6502,8 +6563,18 @@ linux_process_target::qxfer_libraries_svr4 (const char *annex,
   pid = lwpid_of (current_thread);
   xsnprintf (filename, sizeof filename, "/proc/%d/exe", pid);
   is_elf64 = elf_64_file_p (filename, &machine);
-  lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets;
-  ptr_size = is_elf64 ? 8 : 4;
+  const link_map_offsets *lmo;
+  int ptr_size;
+  if (is_elf64)
+    {
+      lmo = &lmo_64bit_offsets;
+      ptr_size = 8;
+    }
+  else
+    {
+      lmo = &lmo_32bit_offsets;
+      ptr_size = 4;
+    }
 
   while (annex[0] != '\0')
     {
@@ -6516,7 +6587,9 @@ linux_process_target::qxfer_libraries_svr4 (const char *annex,
        break;
 
       name_len = sep - annex;
-      if (name_len == 5 && startswith (annex, "start"))
+      if (name_len == 4 && startswith (annex, "lmid"))
+       addrp = &lmid;
+      else if (name_len == 5 && startswith (annex, "start"))
        addrp = &lm_addr;
       else if (name_len == 4 && startswith (annex, "prev"))
        addrp = &lm_prev;
@@ -6532,104 +6605,109 @@ linux_process_target::qxfer_libraries_svr4 (const char *annex,
       annex = decode_address_to_semicolon (addrp, sep + 1);
     }
 
-  if (lm_addr == 0)
+  std::string document = "<library-list-svr4 version=\"1.0\"";
+
+  /* When the starting LM_ADDR is passed in the annex, only traverse that
+     namespace, which is assumed to be identified by LMID.
+
+     Otherwise, start with R_DEBUG and traverse all namespaces we find.  */
+  if (lm_addr != 0)
+    {
+      document += ">";
+      read_link_map (document, lmid, lm_addr, lm_prev, ptr_size, lmo);
+    }
+  else
     {
-      int r_version = 0;
+      if (lm_prev != 0)
+       warning ("ignoring prev=0x%s without start", paddress (lm_prev));
+
+      /* We could interpret LMID as 'provide only the libraries for this
+        namespace' but GDB is currently only providing lmid, start, and
+        prev, or nothing.  */
+      if (lmid != 0)
+       warning ("ignoring lmid=0x%s without start", paddress (lmid));
 
-      if (priv->r_debug == 0)
-       priv->r_debug = get_r_debug (pid, is_elf64);
+      CORE_ADDR r_debug = priv->r_debug;
+      if (r_debug == 0)
+       r_debug = priv->r_debug = get_r_debug (pid, is_elf64);
 
       /* We failed to find DT_DEBUG.  Such situation will not change
         for this inferior - do not retry it.  Report it to GDB as
         E01, see for the reasons at the GDB solib-svr4.c side.  */
-      if (priv->r_debug == (CORE_ADDR) -1)
+      if (r_debug == (CORE_ADDR) -1)
        return -1;
 
-      if (priv->r_debug != 0)
+      /* Terminate the header if we end up with an empty list.  */
+      if (r_debug == 0)
+       document += ">";
+
+      while (r_debug != 0)
        {
-         if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
+         int r_version = 0;
+         if (linux_read_memory (r_debug + lmo->r_version_offset,
                                 (unsigned char *) &r_version,
-                                sizeof (r_version)) != 0
-             || r_version < 1)
+                                sizeof (r_version)) != 0)
            {
-             warning ("unexpected r_debug version %d", r_version);
+             warning ("unable to read r_version from 0x%s",
+                      paddress (r_debug + lmo->r_version_offset));
+             break;
            }
-         else if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
-                                &lm_addr, ptr_size) != 0)
+
+         if (r_version < 1)
            {
-             warning ("unable to read r_map from 0x%lx",
-                      (long) priv->r_debug + lmo->r_map_offset);
+             warning ("unexpected r_debug version %d", r_version);
+             break;
            }
-       }
-    }
-
-  std::string document = "<library-list-svr4 version=\"1.0\"";
 
-  while (lm_addr
-        && read_one_ptr (lm_addr + lmo->l_name_offset,
-                         &l_name, ptr_size) == 0
-        && read_one_ptr (lm_addr + lmo->l_addr_offset,
-                         &l_addr, ptr_size) == 0
-        && read_one_ptr (lm_addr + lmo->l_ld_offset,
-                         &l_ld, ptr_size) == 0
-        && read_one_ptr (lm_addr + lmo->l_prev_offset,
-                         &l_prev, ptr_size) == 0
-        && read_one_ptr (lm_addr + lmo->l_next_offset,
-                         &l_next, ptr_size) == 0)
-    {
-      unsigned char libname[PATH_MAX];
+         if (read_one_ptr (r_debug + lmo->r_map_offset, &lm_addr,
+                           ptr_size) != 0)
+           {
+             warning ("unable to read r_map from 0x%s",
+                      paddress (r_debug + lmo->r_map_offset));
+             break;
+           }
 
-      if (lm_prev != l_prev)
-       {
-         warning ("Corrupted shared library list: 0x%lx != 0x%lx",
-                  (long) lm_prev, (long) l_prev);
-         break;
-       }
+         /* We read the entire namespace.  */
+         lm_prev = 0;
 
-      /* Ignore the first entry even if it has valid name as the first entry
-        corresponds to the main executable.  The first entry should not be
-        skipped if the dynamic loader was loaded late by a static executable
-        (see solib-svr4.c parameter ignore_first).  But in such case the main
-        executable does not have PT_DYNAMIC present and this function already
-        exited above due to failed get_r_debug.  */
-      if (lm_prev == 0)
-       string_appendf (document, " main-lm=\"0x%lx\"", (unsigned long) lm_addr);
-      else
-       {
-         /* Not checking for error because reading may stop before
-            we've got PATH_MAX worth of characters.  */
-         libname[0] = '\0';
-         linux_read_memory (l_name, libname, sizeof (libname) - 1);
-         libname[sizeof (libname) - 1] = '\0';
-         if (libname[0] != '\0')
+         /* The first entry corresponds to the main executable unless the
+            dynamic loader was loaded late by a static executable.  But
+            in such case the main executable does not have PT_DYNAMIC
+            present and we would not have gotten here.  */
+         if (r_debug == priv->r_debug)
            {
-             if (!header_done)
+             if (lm_addr != 0)
+               string_appendf (document, " main-lm=\"0x%s\">",
+                               paddress (lm_addr));
+             else
+               document += ">";
+
+             lm_prev = lm_addr;
+             if (read_one_ptr (lm_addr + lmo->l_next_offset,
+                               &lm_addr, ptr_size) != 0)
                {
-                 /* Terminate `<library-list-svr4'.  */
-                 document += '>';
-                 header_done = 1;
+                 warning ("unable to read l_next from 0x%s",
+                          paddress (lm_addr + lmo->l_next_offset));
+                 break;
                }
+           }
+
+         read_link_map (document, r_debug, lm_addr, lm_prev, ptr_size, lmo);
 
-             string_appendf (document, "<library name=\"");
-             xml_escape_text_append (&document, (char *) libname);
-             string_appendf (document, "\" lm=\"0x%lx\" "
-                             "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
-                             (unsigned long) lm_addr, (unsigned long) l_addr,
-                             (unsigned long) l_ld);
+         if (r_version < 2)
+           break;
+
+         if (read_one_ptr (r_debug + lmo->r_next_offset, &r_debug,
+                           ptr_size) != 0)
+           {
+             warning ("unable to read r_next from 0x%s",
+                      paddress (r_debug + lmo->r_next_offset));
+             break;
            }
        }
-
-      lm_prev = lm_addr;
-      lm_addr = l_next;
     }
 
-  if (!header_done)
-    {
-      /* Empty list; terminate `<library-list-svr4'.  */
-      document += "/>";
-    }
-  else
-    document += "</library-list-svr4>";
+  document += "</library-list-svr4>";
 
   int document_len = document.length ();
   if (offset < document_len)
@@ -6646,6 +6724,12 @@ linux_process_target::qxfer_libraries_svr4 (const char *annex,
 
 #ifdef HAVE_LINUX_BTRACE
 
+bool
+linux_process_target::supports_btrace ()
+{
+  return true;
+}
+
 btrace_target_info *
 linux_process_target::enable_btrace (thread_info *tp,
                                     const btrace_config *conf)
@@ -6667,38 +6751,38 @@ linux_process_target::disable_btrace (btrace_target_info *tinfo)
 /* Encode an Intel Processor Trace configuration.  */
 
 static void
-linux_low_encode_pt_config (struct buffer *buffer,
+linux_low_encode_pt_config (std::string *buffer,
                            const struct btrace_data_pt_config *config)
 {
-  buffer_grow_str (buffer, "<pt-config>\n");
+  *buffer += "<pt-config>\n";
 
   switch (config->cpu.vendor)
     {
     case CV_INTEL:
-      buffer_xml_printf (buffer, "<cpu vendor=\"GenuineIntel\" family=\"%u\" "
-                        "model=\"%u\" stepping=\"%u\"/>\n",
-                        config->cpu.family, config->cpu.model,
-                        config->cpu.stepping);
+      string_xml_appendf (*buffer, "<cpu vendor=\"GenuineIntel\" family=\"%u\" "
+                         "model=\"%u\" stepping=\"%u\"/>\n",
+                         config->cpu.family, config->cpu.model,
+                         config->cpu.stepping);
       break;
 
     default:
       break;
     }
 
-  buffer_grow_str (buffer, "</pt-config>\n");
+  *buffer += "</pt-config>\n";
 }
 
 /* Encode a raw buffer.  */
 
 static void
-linux_low_encode_raw (struct buffer *buffer, const gdb_byte *data,
+linux_low_encode_raw (std::string *buffer, const gdb_byte *data,
                      unsigned int size)
 {
   if (size == 0)
     return;
 
   /* We use hex encoding - see gdbsupport/rsp-low.h.  */
-  buffer_grow_str (buffer, "<raw>\n");
+  *buffer += "<raw>\n";
 
   while (size-- > 0)
     {
@@ -6707,17 +6791,17 @@ linux_low_encode_raw (struct buffer *buffer, const gdb_byte *data,
       elem[0] = tohex ((*data >> 4) & 0xf);
       elem[1] = tohex (*data++ & 0xf);
 
-      buffer_grow (buffer, elem, 2);
+      buffer->append (elem, 2);
     }
 
-  buffer_grow_str (buffer, "</raw>\n");
+  *buffer += "</raw>\n";
 }
 
 /* See to_read_btrace target method.  */
 
 int
 linux_process_target::read_btrace (btrace_target_info *tinfo,
-                                  buffer *buffer,
+                                  std::string *buffer,
                                   enum btrace_read_type type)
 {
   struct btrace_data btrace;
@@ -6727,9 +6811,9 @@ linux_process_target::read_btrace (btrace_target_info *tinfo,
   if (err != BTRACE_ERR_NONE)
     {
       if (err == BTRACE_ERR_OVERFLOW)
-       buffer_grow_str0 (buffer, "E.Overflow.");
+       *buffer += "E.Overflow.";
       else
-       buffer_grow_str0 (buffer, "E.Generic Error.");
+       *buffer += "E.Generic Error.";
 
       return -1;
     }
@@ -6737,36 +6821,36 @@ linux_process_target::read_btrace (btrace_target_info *tinfo,
   switch (btrace.format)
     {
     case BTRACE_FORMAT_NONE:
-      buffer_grow_str0 (buffer, "E.No Trace.");
+      *buffer += "E.No Trace.";
       return -1;
 
     case BTRACE_FORMAT_BTS:
-      buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
-      buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+      *buffer += "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n";
+      *buffer += "<btrace version=\"1.0\">\n";
 
       for (const btrace_block &block : *btrace.variant.bts.blocks)
-       buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
-                          paddress (block.begin), paddress (block.end));
+       string_xml_appendf (*buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
+                           paddress (block.begin), paddress (block.end));
 
-      buffer_grow_str0 (buffer, "</btrace>\n");
+      *buffer += "</btrace>\n";
       break;
 
     case BTRACE_FORMAT_PT:
-      buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
-      buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
-      buffer_grow_str (buffer, "<pt>\n");
+      *buffer += "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n";
+      *buffer += "<btrace version=\"1.0\">\n";
+      *buffer += "<pt>\n";
 
       linux_low_encode_pt_config (buffer, &btrace.variant.pt.config);
 
       linux_low_encode_raw (buffer, btrace.variant.pt.data,
                            btrace.variant.pt.size);
 
-      buffer_grow_str (buffer, "</pt>\n");
-      buffer_grow_str0 (buffer, "</btrace>\n");
+      *buffer += "</pt>\n";
+      *buffer += "</btrace>\n";
       break;
 
     default:
-      buffer_grow_str0 (buffer, "E.Unsupported Trace Format.");
+      *buffer += "E.Unsupported Trace Format.";
       return -1;
     }
 
@@ -6777,12 +6861,12 @@ linux_process_target::read_btrace (btrace_target_info *tinfo,
 
 int
 linux_process_target::read_btrace_conf (const btrace_target_info *tinfo,
-                                       buffer *buffer)
+                                       std::string *buffer)
 {
   const struct btrace_config *conf;
 
-  buffer_grow_str (buffer, "<!DOCTYPE btrace-conf SYSTEM \"btrace-conf.dtd\">\n");
-  buffer_grow_str (buffer, "<btrace-conf version=\"1.0\">\n");
+  *buffer += "<!DOCTYPE btrace-conf SYSTEM \"btrace-conf.dtd\">\n";
+  *buffer += "<btrace-conf version=\"1.0\">\n";
 
   conf = linux_btrace_conf (tinfo);
   if (conf != NULL)
@@ -6793,20 +6877,20 @@ linux_process_target::read_btrace_conf (const btrace_target_info *tinfo,
          break;
 
        case BTRACE_FORMAT_BTS:
-         buffer_xml_printf (buffer, "<bts");
-         buffer_xml_printf (buffer, " size=\"0x%x\"", conf->bts.size);
-         buffer_xml_printf (buffer, " />\n");
+         string_xml_appendf (*buffer, "<bts");
+         string_xml_appendf (*buffer, " size=\"0x%x\"", conf->bts.size);
+         string_xml_appendf (*buffer, " />\n");
          break;
 
        case BTRACE_FORMAT_PT:
-         buffer_xml_printf (buffer, "<pt");
-         buffer_xml_printf (buffer, " size=\"0x%x\"", conf->pt.size);
-         buffer_xml_printf (buffer, "/>\n");
+         string_xml_appendf (*buffer, "<pt");
+         string_xml_appendf (*buffer, " size=\"0x%x\"", conf->pt.size);
+         string_xml_appendf (*buffer, "/>\n");
          break;
        }
     }
 
-  buffer_grow_str0 (buffer, "</btrace-conf>\n");
+  *buffer += "</btrace-conf>\n";
   return 0;
 }
 #endif /* HAVE_LINUX_BTRACE */
@@ -6907,14 +6991,15 @@ linux_get_pc_64bit (struct regcache *regcache)
 /* See linux-low.h.  */
 
 int
-linux_get_auxv (int wordsize, CORE_ADDR match, CORE_ADDR *valp)
+linux_get_auxv (int pid, int wordsize, CORE_ADDR match, CORE_ADDR *valp)
 {
   gdb_byte *data = (gdb_byte *) alloca (2 * wordsize);
   int offset = 0;
 
   gdb_assert (wordsize == 4 || wordsize == 8);
 
-  while (the_target->read_auxv (offset, data, 2 * wordsize) == 2 * wordsize)
+  while (the_target->read_auxv (pid, offset, data, 2 * wordsize)
+        == 2 * wordsize)
     {
       if (wordsize == 4)
        {
@@ -6944,20 +7029,20 @@ linux_get_auxv (int wordsize, CORE_ADDR match, CORE_ADDR *valp)
 /* See linux-low.h.  */
 
 CORE_ADDR
-linux_get_hwcap (int wordsize)
+linux_get_hwcap (int pid, int wordsize)
 {
   CORE_ADDR hwcap = 0;
-  linux_get_auxv (wordsize, AT_HWCAP, &hwcap);
+  linux_get_auxv (pid, wordsize, AT_HWCAP, &hwcap);
   return hwcap;
 }
 
 /* See linux-low.h.  */
 
 CORE_ADDR
-linux_get_hwcap2 (int wordsize)
+linux_get_hwcap2 (int pid, int wordsize)
 {
   CORE_ADDR hwcap2 = 0;
-  linux_get_auxv (wordsize, AT_HWCAP2, &hwcap2);
+  linux_get_auxv (pid, wordsize, AT_HWCAP2, &hwcap2);
   return hwcap2;
 }