Use new to allocate mapped_index
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index 1f9bb4720da679d8d367c4d23940a31cf95fd743..445b59fa4adadbb2890a9e2debffb5330f1e09e4 100644 (file)
@@ -1,6 +1,6 @@
 /* GNU/Linux native-dependent code common to multiple platforms.
 
-   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+   Copyright (C) 2001-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -186,38 +186,11 @@ leader.  */
 #define O_LARGEFILE 0
 #endif
 
+struct linux_nat_target *linux_target;
+
 /* Does the current host support PTRACE_GETREGSET?  */
 enum tribool have_ptrace_getregset = TRIBOOL_UNKNOWN;
 
-/* The single-threaded native GNU/Linux target_ops.  We save a pointer for
-   the use of the multi-threaded target.  */
-static struct target_ops *linux_ops;
-static struct target_ops linux_ops_saved;
-
-/* The method to call, if any, when a new thread is attached.  */
-static void (*linux_nat_new_thread) (struct lwp_info *);
-
-/* The method to call, if any, when a new fork is attached.  */
-static linux_nat_new_fork_ftype *linux_nat_new_fork;
-
-/* The method to call, if any, when a process is no longer
-   attached.  */
-static linux_nat_forget_process_ftype *linux_nat_forget_process_hook;
-
-/* Hook to call prior to resuming a thread.  */
-static void (*linux_nat_prepare_to_resume) (struct lwp_info *);
-
-/* The method to call, if any, when the siginfo object needs to be
-   converted between the layout returned by ptrace, and the layout in
-   the architecture of the inferior.  */
-static int (*linux_nat_siginfo_fixup) (siginfo_t *,
-                                      gdb_byte *,
-                                      int);
-
-/* The saved to_xfer_partial method, inherited from inf-ptrace.c.
-   Called by our to_xfer_partial.  */
-static target_xfer_partial_ftype *super_xfer_partial;
-
 /* The saved to_close method, inherited from inf-ptrace.c.
    Called by our to_close.  */
 static void (*super_close) (struct target_ops *);
@@ -239,6 +212,9 @@ struct simple_pid_list
 };
 struct simple_pid_list *stopped_pids;
 
+/* Whether target_thread_events is in effect.  */
+static int report_thread_events;
+
 /* Async mode support.  */
 
 /* The read/write ends of the pipe registered as waitable file in the
@@ -303,9 +279,7 @@ static struct lwp_info *find_lwp_pid (ptid_t ptid);
 
 static int lwp_status_pending_p (struct lwp_info *lp);
 
-static int check_stopped_by_breakpoint (struct lwp_info *lp);
-static int sigtrap_is_event (int status);
-static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
+static void save_stop_reason (struct lwp_info *lp);
 
 \f
 /* LWP accessors.  */
@@ -351,6 +325,14 @@ lwp_stop_reason (struct lwp_info *lwp)
   return lwp->stop_reason;
 }
 
+/* See nat/linux-nat.h.  */
+
+int
+lwp_is_stepping (struct lwp_info *lwp)
+{
+  return lwp->step;
+}
+
 \f
 /* Trivial list manipulation functions to keep track of a list of
    new stopped processes.  */
@@ -416,14 +398,17 @@ linux_init_ptrace (pid_t pid, int attached)
   linux_ptrace_init_warnings ();
 }
 
-static void
-linux_child_post_attach (struct target_ops *self, int pid)
+linux_nat_target::~linux_nat_target ()
+{}
+
+void
+linux_nat_target::post_attach (int pid)
 {
   linux_init_ptrace (pid, 1);
 }
 
-static void
-linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
+void
+linux_nat_target::post_startup_inferior (ptid_t ptid)
 {
   linux_init_ptrace (ptid_get_pid (ptid), 0);
 }
@@ -457,15 +442,13 @@ delete_lwp_cleanup (void *lp_voidp)
    ptid of the followed inferior.  At return, inferior_ptid will be
    unchanged.  */
 
-static int
-linux_child_follow_fork (struct target_ops *ops, int follow_child,
-                        int detach_fork)
+int
+linux_nat_target::follow_fork (int follow_child, int detach_fork)
 {
   if (!follow_child)
     {
       struct lwp_info *child_lp = NULL;
       int status = W_STOPCODE (0);
-      struct cleanup *old_chain;
       int has_vforked;
       ptid_t parent_ptid, child_ptid;
       int parent_pid, child_pid;
@@ -478,19 +461,17 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
       child_pid = ptid_get_lwp (child_ptid);
 
       /* We're already attached to the parent, by default.  */
-      old_chain = save_inferior_ptid ();
-      inferior_ptid = child_ptid;
-      child_lp = add_lwp (inferior_ptid);
+      child_lp = add_lwp (child_ptid);
       child_lp->stopped = 1;
       child_lp->last_resume_kind = resume_stop;
 
       /* Detach new forked process?  */
       if (detach_fork)
        {
-         make_cleanup (delete_lwp_cleanup, child_lp);
+         struct cleanup *old_chain = make_cleanup (delete_lwp_cleanup,
+                                                   child_lp);
 
-         if (linux_nat_prepare_to_resume != NULL)
-           linux_nat_prepare_to_resume (child_lp);
+         linux_target->low_prepare_to_resume (child_lp);
 
          /* When debugging an inferior in an architecture that supports
             hardware single stepping on a kernel without commit
@@ -500,8 +481,11 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
             To work around this, single step the child process
             once before detaching to clear the flags.  */
 
+         /* Note that we consult the parent's architecture instead of
+            the child's because there's no inferior for the child at
+            this point.  */
          if (!gdbarch_software_single_step_p (target_thread_architecture
-                                                  (child_lp->ptid)))
+                                              (parent_ptid)))
            {
              linux_disable_event_reporting (child_pid);
              if (ptrace (PTRACE_SINGLESTEP, child_pid, 0, 0) < 0)
@@ -521,17 +505,18 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
              ptrace (PTRACE_DETACH, child_pid, 0, signo);
            }
 
-         /* Resets value of inferior_ptid to parent ptid.  */
          do_cleanups (old_chain);
        }
       else
        {
+         scoped_restore save_inferior_ptid
+           = make_scoped_restore (&inferior_ptid);
+         inferior_ptid = child_ptid;
+
          /* Let the thread_db layer learn about this new process.  */
          check_for_thread_db ();
        }
 
-      do_cleanups (old_chain);
-
       if (has_vforked)
        {
          struct lwp_info *parent_lp;
@@ -621,46 +606,45 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
 }
 
 \f
-static int
-linux_child_insert_fork_catchpoint (struct target_ops *self, int pid)
+int
+linux_nat_target::insert_fork_catchpoint (int pid)
 {
   return !linux_supports_tracefork ();
 }
 
-static int
-linux_child_remove_fork_catchpoint (struct target_ops *self, int pid)
+int
+linux_nat_target::remove_fork_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-linux_child_insert_vfork_catchpoint (struct target_ops *self, int pid)
+int
+linux_nat_target::insert_vfork_catchpoint (int pid)
 {
   return !linux_supports_tracefork ();
 }
 
-static int
-linux_child_remove_vfork_catchpoint (struct target_ops *self, int pid)
+int
+linux_nat_target::remove_vfork_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-linux_child_insert_exec_catchpoint (struct target_ops *self, int pid)
+int
+linux_nat_target::insert_exec_catchpoint (int pid)
 {
   return !linux_supports_tracefork ();
 }
 
-static int
-linux_child_remove_exec_catchpoint (struct target_ops *self, int pid)
+int
+linux_nat_target::remove_exec_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-linux_child_set_syscall_catchpoint (struct target_ops *self,
-                                   int pid, int needed, int any_count,
-                                   int table_size, int *table)
+int
+linux_nat_target::set_syscall_catchpoint (int pid, bool needed, int any_count,
+                                         gdb::array_view<const int> syscall_counts)
 {
   if (!linux_supports_tracesysgood ())
     return 1;
@@ -668,13 +652,91 @@ linux_child_set_syscall_catchpoint (struct target_ops *self,
   /* On GNU/Linux, we ignore the arguments.  It means that we only
      enable the syscall catchpoints, but do not disable them.
 
-     Also, we do not use the `table' information because we do not
+     Also, we do not use the `syscall_counts' information because we do not
      filter system calls here.  We let GDB do the logic for us.  */
   return 0;
 }
 
-/* List of known LWPs.  */
+/* List of known LWPs, keyed by LWP PID.  This speeds up the common
+   case of mapping a PID returned from the kernel to our corresponding
+   lwp_info data structure.  */
+static htab_t lwp_lwpid_htab;
+
+/* Calculate a hash from a lwp_info's LWP PID.  */
+
+static hashval_t
+lwp_info_hash (const void *ap)
+{
+  const struct lwp_info *lp = (struct lwp_info *) ap;
+  pid_t pid = ptid_get_lwp (lp->ptid);
+
+  return iterative_hash_object (pid, 0);
+}
+
+/* Equality function for the lwp_info hash table.  Compares the LWP's
+   PID.  */
+
+static int
+lwp_lwpid_htab_eq (const void *a, const void *b)
+{
+  const struct lwp_info *entry = (const struct lwp_info *) a;
+  const struct lwp_info *element = (const struct lwp_info *) b;
+
+  return ptid_get_lwp (entry->ptid) == ptid_get_lwp (element->ptid);
+}
+
+/* Create the lwp_lwpid_htab hash table.  */
+
+static void
+lwp_lwpid_htab_create (void)
+{
+  lwp_lwpid_htab = htab_create (100, lwp_info_hash, lwp_lwpid_htab_eq, NULL);
+}
+
+/* Add LP to the hash table.  */
+
+static void
+lwp_lwpid_htab_add_lwp (struct lwp_info *lp)
+{
+  void **slot;
+
+  slot = htab_find_slot (lwp_lwpid_htab, lp, INSERT);
+  gdb_assert (slot != NULL && *slot == NULL);
+  *slot = lp;
+}
+
+/* Head of doubly-linked list of known LWPs.  Sorted by reverse
+   creation order.  This order is assumed in some cases.  E.g.,
+   reaping status after killing alls lwps of a process: the leader LWP
+   must be reaped last.  */
 struct lwp_info *lwp_list;
+
+/* Add LP to sorted-by-reverse-creation-order doubly-linked list.  */
+
+static void
+lwp_list_add (struct lwp_info *lp)
+{
+  lp->next = lwp_list;
+  if (lwp_list != NULL)
+    lwp_list->prev = lp;
+  lwp_list = lp;
+}
+
+/* Remove LP from sorted-by-reverse-creation-order doubly-linked
+   list.  */
+
+static void
+lwp_list_remove (struct lwp_info *lp)
+{
+  /* Remove from sorted-by-creation-order list.  */
+  if (lp->next != NULL)
+    lp->next->prev = lp->prev;
+  if (lp->prev != NULL)
+    lp->prev->next = lp->next;
+  if (lp == lwp_list)
+    lwp_list = lp->next;
+}
+
 \f
 
 /* Original signal mask.  */
@@ -716,9 +778,8 @@ restore_child_signals_mask (sigset_t *prev_mask)
 static sigset_t pass_mask;
 
 /* Update signals to pass to the inferior.  */
-static void
-linux_nat_pass_signals (struct target_ops *self,
-                       int numsigs, unsigned char *pass_signals)
+void
+linux_nat_target::pass_signals (int numsigs, unsigned char *pass_signals)
 {
   int signo;
 
@@ -736,8 +797,8 @@ linux_nat_pass_signals (struct target_ops *self,
 
 /* Prototypes for local functions.  */
 static int stop_wait_callback (struct lwp_info *lp, void *data);
-static char *linux_child_pid_to_exec_file (struct target_ops *self, int pid);
 static int resume_stopped_resumed_lwps (struct lwp_info *lp, void *data);
+static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp);
 
 \f
 
@@ -746,35 +807,36 @@ static int resume_stopped_resumed_lwps (struct lwp_info *lp, void *data);
 static void
 lwp_free (struct lwp_info *lp)
 {
-  xfree (lp->arch_private);
+  /* Let the arch specific bits release arch_lwp_info.  */
+  linux_target->low_delete_thread (lp->arch_private);
+
   xfree (lp);
 }
 
-/* Remove all LWPs belong to PID from the lwp list.  */
+/* Traversal function for purge_lwp_list.  */
 
-static void
-purge_lwp_list (int pid)
+static int
+lwp_lwpid_htab_remove_pid (void **slot, void *info)
 {
-  struct lwp_info *lp, *lpprev, *lpnext;
+  struct lwp_info *lp = (struct lwp_info *) *slot;
+  int pid = *(int *) info;
 
-  lpprev = NULL;
-
-  for (lp = lwp_list; lp; lp = lpnext)
+  if (ptid_get_pid (lp->ptid) == pid)
     {
-      lpnext = lp->next;
+      htab_clear_slot (lwp_lwpid_htab, slot);
+      lwp_list_remove (lp);
+      lwp_free (lp);
+    }
 
-      if (ptid_get_pid (lp->ptid) == pid)
-       {
-         if (lp == lwp_list)
-           lwp_list = lp->next;
-         else
-           lpprev->next = lp->next;
+  return 1;
+}
 
-         lwp_free (lp);
-       }
-      else
-       lpprev = lp;
-    }
+/* Remove all LWPs belong to PID from the lwp list.  */
+
+static void
+purge_lwp_list (int pid)
+{
+  htab_traverse_noresize (lwp_lwpid_htab, lwp_lwpid_htab_remove_pid, &pid);
 }
 
 /* Add the LWP specified by PTID to the list.  PTID is the first LWP
@@ -808,8 +870,11 @@ add_initial_lwp (ptid_t ptid)
   lp->ptid = ptid;
   lp->core = -1;
 
-  lp->next = lwp_list;
-  lwp_list = lp;
+  /* Add to sorted-by-reverse-creation-order list.  */
+  lwp_list_add (lp);
+
+  /* Add to keyed-by-pid htab.  */
+  lwp_lwpid_htab_add_lwp (lp);
 
   return lp;
 }
@@ -829,8 +894,7 @@ add_lwp (ptid_t ptid)
      clients of this callback take the opportunity to install
      watchpoints in the new thread.  We don't do this for the first
      thread though.  See add_initial_lwp.  */
-  if (linux_nat_new_thread != NULL)
-    linux_nat_new_thread (lp);
+  linux_target->low_new_thread (lp);
 
   return lp;
 }
@@ -840,22 +904,24 @@ add_lwp (ptid_t ptid)
 static void
 delete_lwp (ptid_t ptid)
 {
-  struct lwp_info *lp, *lpprev;
+  struct lwp_info *lp;
+  void **slot;
+  struct lwp_info dummy;
 
-  lpprev = NULL;
+  dummy.ptid = ptid;
+  slot = htab_find_slot (lwp_lwpid_htab, &dummy, NO_INSERT);
+  if (slot == NULL)
+    return;
 
-  for (lp = lwp_list; lp; lpprev = lp, lp = lp->next)
-    if (ptid_equal (lp->ptid, ptid))
-      break;
+  lp = *(struct lwp_info **) slot;
+  gdb_assert (lp != NULL);
 
-  if (!lp)
-    return;
+  htab_clear_slot (lwp_lwpid_htab, slot);
 
-  if (lpprev)
-    lpprev->next = lp->next;
-  else
-    lwp_list = lp->next;
+  /* Remove from sorted-by-creation-order list.  */
+  lwp_list_remove (lp);
 
+  /* Release.  */
   lwp_free (lp);
 }
 
@@ -867,17 +933,16 @@ find_lwp_pid (ptid_t ptid)
 {
   struct lwp_info *lp;
   int lwp;
+  struct lwp_info dummy;
 
   if (ptid_lwp_p (ptid))
     lwp = ptid_get_lwp (ptid);
   else
     lwp = ptid_get_pid (ptid);
 
-  for (lp = lwp_list; lp; lp = lp->next)
-    if (lwp == ptid_get_lwp (lp->ptid))
-      return lp;
-
-  return NULL;
+  dummy.ptid = ptid_build (0, lwp, 0);
+  lp = (struct lwp_info *) htab_find (lwp_lwpid_htab, &dummy);
+  return lp;
 }
 
 /* See nat/linux-nat.h.  */
@@ -951,7 +1016,7 @@ exit_lwp (struct lwp_info *lp)
    Returns a wait status for that LWP, to cache.  */
 
 static int
-linux_nat_post_attach_wait (ptid_t ptid, int first, int *signalled)
+linux_nat_post_attach_wait (ptid_t ptid, int *signalled)
 {
   pid_t new_pid, pid = ptid_get_lwp (ptid);
   int status;
@@ -1009,23 +1074,21 @@ linux_nat_post_attach_wait (ptid_t ptid, int first, int *signalled)
   return status;
 }
 
-static void
-linux_nat_create_inferior (struct target_ops *ops, 
-                          char *exec_file, char *allargs, char **env,
-                          int from_tty)
+void
+linux_nat_target::create_inferior (const char *exec_file,
+                                  const std::string &allargs,
+                                  char **env, int from_tty)
 {
-  struct cleanup *restore_personality
-    = maybe_disable_address_space_randomization (disable_randomization);
+  maybe_disable_address_space_randomization restore_personality
+    (disable_randomization);
 
   /* The fork_child mechanism is synchronous and calls target_wait, so
      we have to mask the async mode.  */
 
   /* Make sure we report all signals during startup.  */
-  linux_nat_pass_signals (ops, 0, NULL);
+  pass_signals (0, NULL);
 
-  linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty);
-
-  do_cleanups (restore_personality);
+  inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty);
 }
 
 /* Callback for linux_proc_attach_tgid_threads.  Attach to PTID if not
@@ -1065,10 +1128,11 @@ attach_proc_task_lwp_callback (ptid_t ptid)
            }
          else
            {
+             std::string reason
+               = linux_ptrace_attach_fail_reason_string (ptid, err);
+
              warning (_("Cannot attach to lwp %d: %s"),
-                      lwpid,
-                      linux_ptrace_attach_fail_reason_string (ptid,
-                                                              err));
+                      lwpid, reason.c_str ());
            }
        }
       else
@@ -1087,6 +1151,16 @@ attach_proc_task_lwp_callback (ptid_t ptid)
          /* We need to wait for a stop before being able to make the
             next ptrace call on this LWP.  */
          lp->must_set_ptrace_flags = 1;
+
+         /* So that wait collects the SIGSTOP.  */
+         lp->resumed = 1;
+
+         /* Also add the LWP to gdb's thread list, in case a
+            matching libthread_db is not found (or the process uses
+            raw clone).  */
+         add_thread (lp->ptid);
+         set_running (lp->ptid, 1);
+         set_executing (lp->ptid, 1);
        }
 
       return 1;
@@ -1094,40 +1168,29 @@ attach_proc_task_lwp_callback (ptid_t ptid)
   return 0;
 }
 
-static void
-linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
+void
+linux_nat_target::attach (const char *args, int from_tty)
 {
   struct lwp_info *lp;
   int status;
   ptid_t ptid;
 
   /* Make sure we report all signals during attach.  */
-  linux_nat_pass_signals (ops, 0, NULL);
+  pass_signals (0, NULL);
 
   TRY
     {
-      linux_ops->to_attach (ops, args, from_tty);
+      inf_ptrace_target::attach (args, from_tty);
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
       pid_t pid = parse_pid_to_attach (args);
-      struct buffer buffer;
-      char *message, *buffer_s;
+      std::string reason = linux_ptrace_attach_fail_reason (pid);
 
-      message = xstrdup (ex.message);
-      make_cleanup (xfree, message);
-
-      buffer_init (&buffer);
-      linux_ptrace_attach_fail_reason (pid, &buffer);
-
-      buffer_grow_str0 (&buffer, "");
-      buffer_s = buffer_finish (&buffer);
-      make_cleanup (xfree, buffer_s);
-
-      if (*buffer_s != '\0')
-       throw_error (ex.error, "warning: %s\n%s", buffer_s, message);
+      if (!reason.empty ())
+       throw_error (ex.error, "warning: %s\n%s", reason.c_str (), ex.message);
       else
-       throw_error (ex.error, "%s", message);
+       throw_error (ex.error, "%s", ex.message);
     }
   END_CATCH
 
@@ -1141,15 +1204,15 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
   /* Add the initial process as the first LWP to the list.  */
   lp = add_initial_lwp (ptid);
 
-  status = linux_nat_post_attach_wait (lp->ptid, 1, &lp->signalled);
+  status = linux_nat_post_attach_wait (lp->ptid, &lp->signalled);
   if (!WIFSTOPPED (status))
     {
       if (WIFEXITED (status))
        {
          int exit_code = WEXITSTATUS (status);
 
-         target_terminal_ours ();
-         target_mourn_inferior ();
+         target_terminal::ours ();
+         target_mourn_inferior (inferior_ptid);
          if (exit_code == 0)
            error (_("Unable to attach: program exited normally."));
          else
@@ -1160,8 +1223,8 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
        {
          enum gdb_signal signo;
 
-         target_terminal_ours ();
-         target_mourn_inferior ();
+         target_terminal::ours ();
+         target_mourn_inferior (inferior_ptid);
 
          signo = gdb_signal_from_host (WTERMSIG (status));
          error (_("Unable to attach: program terminated with signal "
@@ -1200,9 +1263,13 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
     target_async (1);
 }
 
-/* Get pending status of LP.  */
+/* Get pending signal of THREAD as a host signal number, for detaching
+   purposes.  This is the signal the thread last stopped for, which we
+   need to deliver to the thread when detaching, otherwise, it'd be
+   suppressed/lost.  */
+
 static int
-get_pending_status (struct lwp_info *lp, int *status)
+get_detach_signal (struct lwp_info *lp)
 {
   enum gdb_signal signo = GDB_SIGNAL_0;
 
@@ -1235,7 +1302,10 @@ get_pending_status (struct lwp_info *lp, int *status)
     {
       struct thread_info *tp = find_thread_ptid (lp->ptid);
 
-      signo = tp->suspend.stop_signal;
+      if (tp->suspend.waitstatus_pending_p)
+       signo = tp->suspend.waitstatus.value.sig;
+      else
+       signo = tp->suspend.stop_signal;
     }
   else if (!target_is_non_stop_p ())
     {
@@ -1252,8 +1322,6 @@ get_pending_status (struct lwp_info *lp, int *status)
        }
     }
 
-  *status = 0;
-
   if (signo == GDB_SIGNAL_0)
     {
       if (debug_linux_nat)
@@ -1272,21 +1340,28 @@ get_pending_status (struct lwp_info *lp, int *status)
     }
   else
     {
-      *status = W_STOPCODE (gdb_signal_to_host (signo));
-
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
                            "GPT: lwp %s has pending signal %s\n",
                            target_pid_to_str (lp->ptid),
                            gdb_signal_to_string (signo));
+
+      return gdb_signal_to_host (signo);
     }
 
   return 0;
 }
 
-static int
-detach_callback (struct lwp_info *lp, void *data)
+/* Detach from LP.  If SIGNO_P is non-NULL, then it points to the
+   signal number that should be passed to the LWP when detaching.
+   Otherwise pass any pending signal the LWP may have, if any.  */
+
+static void
+detach_one_lwp (struct lwp_info *lp, int *signo_p)
 {
+  int lwpid = ptid_get_lwp (lp->ptid);
+  int signo;
+
   gdb_assert (lp->status == 0 || WIFSTOPPED (lp->status));
 
   if (debug_linux_nat && lp->status)
@@ -1302,47 +1377,90 @@ detach_callback (struct lwp_info *lp, void *data)
                            "DC: Sending SIGCONT to %s\n",
                            target_pid_to_str (lp->ptid));
 
-      kill_lwp (ptid_get_lwp (lp->ptid), SIGCONT);
+      kill_lwp (lwpid, SIGCONT);
       lp->signalled = 0;
     }
 
-  /* We don't actually detach from the LWP that has an id equal to the
-     overall process id just yet.  */
-  if (ptid_get_lwp (lp->ptid) != ptid_get_pid (lp->ptid))
+  if (signo_p == NULL)
     {
-      int status = 0;
-
       /* Pass on any pending signal for this LWP.  */
-      get_pending_status (lp, &status);
+      signo = get_detach_signal (lp);
+    }
+  else
+    signo = *signo_p;
 
-      if (linux_nat_prepare_to_resume != NULL)
-       linux_nat_prepare_to_resume (lp);
-      errno = 0;
-      if (ptrace (PTRACE_DETACH, ptid_get_lwp (lp->ptid), 0,
-                 WSTOPSIG (status)) < 0)
-       error (_("Can't detach %s: %s"), target_pid_to_str (lp->ptid),
-              safe_strerror (errno));
+  /* Preparing to resume may try to write registers, and fail if the
+     lwp is zombie.  If that happens, ignore the error.  We'll handle
+     it below, when detach fails with ESRCH.  */
+  TRY
+    {
+      linux_target->low_prepare_to_resume (lp);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (!check_ptrace_stopped_lwp_gone (lp))
+       throw_exception (ex);
+    }
+  END_CATCH
 
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "PTRACE_DETACH (%s, %s, 0) (OK)\n",
-                           target_pid_to_str (lp->ptid),
-                           strsignal (WSTOPSIG (status)));
+  if (ptrace (PTRACE_DETACH, lwpid, 0, signo) < 0)
+    {
+      int save_errno = errno;
+
+      /* We know the thread exists, so ESRCH must mean the lwp is
+        zombie.  This can happen if one of the already-detached
+        threads exits the whole thread group.  In that case we're
+        still attached, and must reap the lwp.  */
+      if (save_errno == ESRCH)
+       {
+         int ret, status;
 
-      delete_lwp (lp->ptid);
+         ret = my_waitpid (lwpid, &status, __WALL);
+         if (ret == -1)
+           {
+             warning (_("Couldn't reap LWP %d while detaching: %s"),
+                      lwpid, strerror (errno));
+           }
+         else if (!WIFEXITED (status) && !WIFSIGNALED (status))
+           {
+             warning (_("Reaping LWP %d while detaching "
+                        "returned unexpected status 0x%x"),
+                      lwpid, status);
+           }
+       }
+      else
+       {
+         error (_("Can't detach %s: %s"), target_pid_to_str (lp->ptid),
+                safe_strerror (save_errno));
+       }
+    }
+  else if (debug_linux_nat)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+                         "PTRACE_DETACH (%s, %s, 0) (OK)\n",
+                         target_pid_to_str (lp->ptid),
+                         strsignal (signo));
     }
 
+  delete_lwp (lp->ptid);
+}
+
+static int
+detach_callback (struct lwp_info *lp, void *data)
+{
+  /* We don't actually detach from the thread group leader just yet.
+     If the thread group exits, we must reap the zombie clone lwps
+     before we're able to reap the leader.  */
+  if (ptid_get_lwp (lp->ptid) != ptid_get_pid (lp->ptid))
+    detach_one_lwp (lp, NULL);
   return 0;
 }
 
-static void
-linux_nat_detach (struct target_ops *ops, const char *args, int from_tty)
+void
+linux_nat_target::detach (inferior *inf, int from_tty)
 {
-  int pid;
-  int status;
   struct lwp_info *main_lwp;
-
-  pid = ptid_get_pid (inferior_ptid);
+  int pid = inf->pid;
 
   /* Don't unregister from the event loop, as there may be other
      inferiors running. */
@@ -1357,43 +1475,29 @@ linux_nat_detach (struct target_ops *ops, const char *args, int from_tty)
   iterate_over_lwps (pid_to_ptid (pid), detach_callback, NULL);
 
   /* Only the initial process should be left right now.  */
-  gdb_assert (num_lwps (ptid_get_pid (inferior_ptid)) == 1);
+  gdb_assert (num_lwps (pid) == 1);
 
   main_lwp = find_lwp_pid (pid_to_ptid (pid));
 
-  /* Pass on any pending signal for the last LWP.  */
-  if ((args == NULL || *args == '\0')
-      && get_pending_status (main_lwp, &status) != -1
-      && WIFSTOPPED (status))
-    {
-      char *tem;
-
-      /* Put the signal number in ARGS so that inf_ptrace_detach will
-        pass it along with PTRACE_DETACH.  */
-      tem = (char *) alloca (8);
-      xsnprintf (tem, 8, "%d", (int) WSTOPSIG (status));
-      args = tem;
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "LND: Sending signal %s to %s\n",
-                           args,
-                           target_pid_to_str (main_lwp->ptid));
-    }
-
-  if (linux_nat_prepare_to_resume != NULL)
-    linux_nat_prepare_to_resume (main_lwp);
-  delete_lwp (main_lwp->ptid);
-
   if (forks_exist_p ())
     {
       /* Multi-fork case.  The current inferior_ptid is being detached
         from, but there are other viable forks to debug.  Detach from
         the current fork, and context-switch to the first
         available.  */
-      linux_fork_detach (args, from_tty);
+      linux_fork_detach (from_tty);
     }
   else
-    linux_ops->to_detach (ops, args, from_tty);
+    {
+      target_announce_detach (from_tty);
+
+      /* Pass on any pending signal for the last LWP.  */
+      int signo = get_detach_signal (main_lwp);
+
+      detach_one_lwp (main_lwp, &signo);
+
+      detach_success (inf);
+    }
 }
 
 /* Resume execution of the inferior process.  If STEP is nonzero,
@@ -1417,9 +1521,8 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
   else
     lp->stop_pc = 0;
 
-  if (linux_nat_prepare_to_resume != NULL)
-    linux_nat_prepare_to_resume (lp);
-  linux_ops->to_resume (linux_ops, lp->ptid, step, signo);
+  linux_target->low_prepare_to_resume (lp);
+  linux_target->low_resume (lp->ptid, step, signo);
 
   /* Successfully resumed.  Clear state that no longer makes sense,
      and mark the LWP as running.  Must not do this before resuming
@@ -1428,6 +1531,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
      status.  Note that we must not throw after this is cleared,
      otherwise handle_zombie_lwp_error would get confused.  */
   lp->stopped = 0;
+  lp->core = -1;
   lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
   registers_changed_ptid (lp->ptid);
 }
@@ -1571,9 +1675,8 @@ resume_set_callback (struct lwp_info *lp, void *data)
   return 0;
 }
 
-static void
-linux_nat_resume (struct target_ops *ops,
-                 ptid_t ptid, int step, enum gdb_signal signo)
+void
+linux_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
 {
   struct lwp_info *lp;
   int resume_many;
@@ -1862,8 +1965,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
          /* The arch-specific native code may need to know about new
             forks even if those end up never mapped to an
             inferior.  */
-         if (linux_nat_new_fork != NULL)
-           linux_nat_new_fork (lp, new_pid);
+         linux_target->low_new_fork (lp, new_pid);
        }
 
       if (event == PTRACE_EVENT_FORK
@@ -1951,6 +2053,11 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
                                    status_to_str (status));
              new_lp->status = status;
            }
+         else if (report_thread_events)
+           {
+             new_lp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
+             new_lp->status = status;
+           }
 
          return 1;
        }
@@ -1967,7 +2074,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
 
       ourstatus->kind = TARGET_WAITKIND_EXECD;
       ourstatus->value.execd_pathname
-       = xstrdup (linux_child_pid_to_exec_file (NULL, pid));
+       = xstrdup (linux_proc_pid_to_exec_file (pid));
 
       /* The thread that execed must have been resumed, but, when a
         thread execs, it changes its tid to the tgid, and the old
@@ -2002,6 +2109,30 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
                  _("unknown ptrace event %d"), event);
 }
 
+/* Suspend waiting for a signal.  We're mostly interested in
+   SIGCHLD/SIGINT.  */
+
+static void
+wait_for_signal ()
+{
+  if (debug_linux_nat)
+    fprintf_unfiltered (gdb_stdlog, "linux-nat: about to sigsuspend\n");
+  sigsuspend (&suspend_mask);
+
+  /* If the quit flag is set, it means that the user pressed Ctrl-C
+     and we're debugging a process that is running on a separate
+     terminal, so we must forward the Ctrl-C to the inferior.  (If the
+     inferior is sharing GDB's terminal, then the Ctrl-C reaches the
+     inferior directly.)  We must do this here because functions that
+     need to block waiting for a signal loop forever until there's an
+     event to report before returning back to the event loop.  */
+  if (!target_terminal::is_ours ())
+    {
+      if (check_quit_flag ())
+       target_pass_ctrlc ();
+    }
+}
+
 /* Wait for LP to stop.  Returns the wait status, or 0 if the LWP has
    exited.  */
 
@@ -2067,10 +2198,7 @@ wait_lwp (struct lwp_info *lp)
         linux_nat_wait_1 and there if we get called my_waitpid gets called
         again before it gets to sigsuspend so we can safely let the handlers
         get executed here.  */
-
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog, "WL: about to sigsuspend\n");
-      sigsuspend (&suspend_mask);
+      wait_for_signal ();
     }
 
   restore_child_signals_mask (&prev_mask);
@@ -2090,13 +2218,14 @@ wait_lwp (struct lwp_info *lp)
       /* Check if the thread has exited.  */
       if (WIFEXITED (status) || WIFSIGNALED (status))
        {
-         if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+         if (report_thread_events
+             || ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
            {
              if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog, "WL: Process %d exited.\n",
+               fprintf_unfiltered (gdb_stdlog, "WL: LWP %d exited.\n",
                                    ptid_get_pid (lp->ptid));
 
-             /* This is the leader exiting, it means the whole
+             /* If this is the leader exiting, it means the whole
                 process is gone.  Store the status to report to the
                 core.  Store it in lp->waitstatus, because lp->status
                 would be ambiguous (W_EXITCODE(0,0) == 0).  */
@@ -2296,59 +2425,23 @@ maybe_clear_ignore_sigint (struct lwp_info *lp)
 static int
 check_stopped_by_watchpoint (struct lwp_info *lp)
 {
-  struct cleanup *old_chain;
-
-  if (linux_ops->to_stopped_by_watchpoint == NULL)
-    return 0;
-
-  old_chain = save_inferior_ptid ();
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
   inferior_ptid = lp->ptid;
 
-  if (linux_ops->to_stopped_by_watchpoint (linux_ops))
+  if (linux_target->low_stopped_by_watchpoint ())
     {
       lp->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
-
-      if (linux_ops->to_stopped_data_address != NULL)
-       lp->stopped_data_address_p =
-         linux_ops->to_stopped_data_address (&current_target,
-                                             &lp->stopped_data_address);
-      else
-       lp->stopped_data_address_p = 0;
+      lp->stopped_data_address_p
+       = linux_target->low_stopped_data_address (&lp->stopped_data_address);
     }
 
-  do_cleanups (old_chain);
-
   return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
-/* Called when the LWP stopped for a trap that could be explained by a
-   watchpoint or a breakpoint.  */
-
-static void
-save_sigtrap (struct lwp_info *lp)
-{
-  gdb_assert (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON);
-  gdb_assert (lp->status != 0);
-
-  /* Check first if this was a SW/HW breakpoint before checking
-     watchpoints, because at least s390 can't tell the data address of
-     hardware watchpoint hits, and the kernel returns
-     stopped-by-watchpoint as long as there's a watchpoint set.  */
-  if (linux_nat_status_is_event (lp->status))
-    check_stopped_by_breakpoint (lp);
-
-  /* Note that TRAP_HWBKPT can indicate either a hardware breakpoint
-     or hardware watchpoint.  Check which is which if we got
-     TARGET_STOPPED_BY_HW_BREAKPOINT.  */
-  if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON
-      || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)
-    check_stopped_by_watchpoint (lp);
-}
-
 /* Returns true if the LWP had stopped for a watchpoint.  */
 
-static int
-linux_nat_stopped_by_watchpoint (struct target_ops *ops)
+bool
+linux_nat_target::stopped_by_watchpoint ()
 {
   struct lwp_info *lp = find_lwp_pid (inferior_ptid);
 
@@ -2357,8 +2450,8 @@ linux_nat_stopped_by_watchpoint (struct target_ops *ops)
   return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
-static int
-linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
+bool
+linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
 {
   struct lwp_info *lp = find_lwp_pid (inferior_ptid);
 
@@ -2371,23 +2464,12 @@ linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 
 /* Commonly any breakpoint / watchpoint generate only SIGTRAP.  */
 
-static int
-sigtrap_is_event (int status)
+bool
+linux_nat_target::low_status_is_event (int status)
 {
   return WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP;
 }
 
-/* Set alternative SIGTRAP-like events recognizer.  If
-   breakpoint_inserted_here_p there then gdbarch_decr_pc_after_break will be
-   applied.  */
-
-void
-linux_nat_set_status_is_event (struct target_ops *t,
-                              int (*status_is_event) (int status))
-{
-  linux_nat_status_is_event = status_is_event;
-}
-
 /* Wait until LP is stopped.  */
 
 static int
@@ -2441,7 +2523,7 @@ stop_wait_callback (struct lwp_info *lp, void *data)
          /* Save the sigtrap event.  */
          lp->status = status;
          gdb_assert (lp->signalled);
-         save_sigtrap (lp);
+         save_stop_reason (lp);
        }
       else
        {
@@ -2481,7 +2563,6 @@ status_callback (struct lwp_info *lp, void *data)
       || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)
     {
       struct regcache *regcache = get_thread_regcache (lp->ptid);
-      struct gdbarch *gdbarch = get_regcache_arch (regcache);
       CORE_ADDR pc;
       int discard = 0;
 
@@ -2499,7 +2580,7 @@ status_callback (struct lwp_info *lp, void *data)
        }
 
 #if !USE_SIGTRAP_SIGINFO
-      else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+      else if (!breakpoint_inserted_here_p (regcache->aspace (), pc))
        {
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
@@ -2583,29 +2664,32 @@ select_event_lwp_callback (struct lwp_info *lp, void *data)
   return 0;
 }
 
-/* Called when the LWP got a signal/trap that could be explained by a
-   software or hardware breakpoint.  */
+/* Called when the LWP stopped for a signal/trap.  If it stopped for a
+   trap check what caused it (breakpoint, watchpoint, trace, etc.),
+   and save the result in the LWP's stop_reason field.  If it stopped
+   for a breakpoint, decrement the PC if necessary on the lwp's
+   architecture.  */
 
-static int
-check_stopped_by_breakpoint (struct lwp_info *lp)
+static void
+save_stop_reason (struct lwp_info *lp)
 {
-  /* Arrange for a breakpoint to be hit again later.  We don't keep
-     the SIGTRAP status and don't forward the SIGTRAP signal to the
-     LWP.  We will handle the current event, eventually we will resume
-     this LWP, and this breakpoint will trap again.
-
-     If we do not do this, then we run the risk that the user will
-     delete or disable the breakpoint, but the LWP will have already
-     tripped on it.  */
-
-  struct regcache *regcache = get_thread_regcache (lp->ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct regcache *regcache;
+  struct gdbarch *gdbarch;
   CORE_ADDR pc;
   CORE_ADDR sw_bp_pc;
 #if USE_SIGTRAP_SIGINFO
   siginfo_t siginfo;
 #endif
 
+  gdb_assert (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON);
+  gdb_assert (lp->status != 0);
+
+  if (!linux_target->low_status_is_event (lp->status))
+    return;
+
+  regcache = get_thread_regcache (lp->ptid);
+  gdbarch = regcache->arch ();
+
   pc = regcache_read_pc (regcache);
   sw_bp_pc = pc - gdbarch_decr_pc_after_break (gdbarch);
 
@@ -2614,33 +2698,29 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
     {
       if (siginfo.si_signo == SIGTRAP)
        {
-         if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code))
+         if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)
+             && GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code))
            {
-             if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "CSBB: %s stopped by software "
-                                   "breakpoint\n",
-                                   target_pid_to_str (lp->ptid));
-
-             /* Back up the PC if necessary.  */
-             if (pc != sw_bp_pc)
-               regcache_write_pc (regcache, sw_bp_pc);
-
-             lp->stop_pc = sw_bp_pc;
+             /* The si_code is ambiguous on this arch -- check debug
+                registers.  */
+             if (!check_stopped_by_watchpoint (lp))
+               lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
+           }
+         else if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code))
+           {
+             /* If we determine the LWP stopped for a SW breakpoint,
+                trust it.  Particularly don't check watchpoint
+                registers, because at least on s390, we'd find
+                stopped-by-watchpoint as long as there's a watchpoint
+                set.  */
              lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
-             return 1;
            }
-         else if (siginfo.si_code == TRAP_HWBKPT)
+         else if (GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code))
            {
-             if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "CSBB: %s stopped by hardware "
-                                   "breakpoint/watchpoint\n",
-                                   target_pid_to_str (lp->ptid));
-
-             lp->stop_pc = pc;
-             lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
-             return 1;
+             /* This can indicate either a hardware breakpoint or
+                hardware watchpoint.  Check debug registers.  */
+             if (!check_stopped_by_watchpoint (lp))
+               lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
            }
          else if (siginfo.si_code == TRAP_TRACE)
            {
@@ -2648,16 +2728,35 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
                fprintf_unfiltered (gdb_stdlog,
                                    "CSBB: %s stopped by trace\n",
                                    target_pid_to_str (lp->ptid));
+
+             /* We may have single stepped an instruction that
+                triggered a watchpoint.  In that case, on some
+                architectures (such as x86), instead of TRAP_HWBKPT,
+                si_code indicates TRAP_TRACE, and we need to check
+                the debug registers separately.  */
+             check_stopped_by_watchpoint (lp);
            }
        }
     }
 #else
   if ((!lp->step || lp->stop_pc == sw_bp_pc)
-      && software_breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+      && software_breakpoint_inserted_here_p (regcache->aspace (),
                                              sw_bp_pc))
     {
       /* The LWP was either continued, or stepped a software
         breakpoint instruction.  */
+      lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
+    }
+
+  if (hardware_breakpoint_inserted_here_p (regcache->aspace (), pc))
+    lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
+
+  if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON)
+    check_stopped_by_watchpoint (lp);
+#endif
+
+  if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT)
+    {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
                            "CSBB: %s stopped by software breakpoint\n",
@@ -2667,32 +2766,32 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
       if (pc != sw_bp_pc)
        regcache_write_pc (regcache, sw_bp_pc);
 
-      lp->stop_pc = sw_bp_pc;
-      lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
-      return 1;
+      /* Update this so we record the correct stop PC below.  */
+      pc = sw_bp_pc;
     }
-
-  if (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+  else if (lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "CSBB: stopped by hardware breakpoint %s\n",
+                           "CSBB: %s stopped by hardware breakpoint\n",
+                           target_pid_to_str (lp->ptid));
+    }
+  else if (lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
+    {
+      if (debug_linux_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "CSBB: %s stopped by hardware watchpoint\n",
                            target_pid_to_str (lp->ptid));
-
-      lp->stop_pc = pc;
-      lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
-      return 1;
     }
-#endif
 
-  return 0;
+  lp->stop_pc = pc;
 }
 
 
 /* Returns true if the LWP had stopped for a software breakpoint.  */
 
-static int
-linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops)
+bool
+linux_nat_target::stopped_by_sw_breakpoint ()
 {
   struct lwp_info *lp = find_lwp_pid (inferior_ptid);
 
@@ -2703,8 +2802,8 @@ linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops)
 
 /* Implement the supports_stopped_by_sw_breakpoint method.  */
 
-static int
-linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
+bool
+linux_nat_target::supports_stopped_by_sw_breakpoint ()
 {
   return USE_SIGTRAP_SIGINFO;
 }
@@ -2712,8 +2811,8 @@ linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
 /* Returns true if the LWP had stopped for a hardware
    breakpoint/watchpoint.  */
 
-static int
-linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops)
+bool
+linux_nat_target::stopped_by_hw_breakpoint ()
 {
   struct lwp_info *lp = find_lwp_pid (inferior_ptid);
 
@@ -2724,8 +2823,8 @@ linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops)
 
 /* Implement the supports_stopped_by_hw_breakpoint method.  */
 
-static int
-linux_nat_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
+bool
+linux_nat_target::supports_stopped_by_hw_breakpoint ()
 {
   return USE_SIGTRAP_SIGINFO;
 }
@@ -2908,7 +3007,8 @@ linux_nat_filter_event (int lwpid, int status)
   /* Check if the thread has exited.  */
   if (WIFEXITED (status) || WIFSIGNALED (status))
     {
-      if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
+      if (!report_thread_events
+         && num_lwps (ptid_get_pid (lp->ptid)) > 1)
        {
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
@@ -2928,15 +3028,9 @@ linux_nat_filter_event (int lwpid, int status)
         resumed.  */
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "Process %ld exited (resumed=%d)\n",
+                           "LWP %ld exited (resumed=%d)\n",
                            ptid_get_lwp (lp->ptid), lp->resumed);
 
-      /* This was the last lwp in the process.  Since events are
-        serialized to GDB core, we may not be able report this one
-        right now, but GDB core and the other target layers will want
-        to be notified about the exit code/signal, leave the status
-        pending for the next time we're able to report it.  */
-
       /* Dead LWP's aren't expected to reported a pending sigstop.  */
       lp->signalled = 0;
 
@@ -3057,7 +3151,7 @@ linux_nat_filter_event (int lwpid, int status)
   /* An interesting event.  */
   gdb_assert (lp);
   lp->status = status;
-  save_sigtrap (lp);
+  save_stop_reason (lp);
   return lp;
 }
 
@@ -3116,9 +3210,32 @@ check_zombie_leaders (void)
     }
 }
 
+/* Convenience function that is called when the kernel reports an exit
+   event.  This decides whether to report the event to GDB as a
+   process exit event, a thread exit event, or to suppress the
+   event.  */
+
 static ptid_t
-linux_nat_wait_1 (struct target_ops *ops,
-                 ptid_t ptid, struct target_waitstatus *ourstatus,
+filter_exit_event (struct lwp_info *event_child,
+                  struct target_waitstatus *ourstatus)
+{
+  ptid_t ptid = event_child->ptid;
+
+  if (num_lwps (ptid_get_pid (ptid)) > 1)
+    {
+      if (report_thread_events)
+       ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
+      else
+       ourstatus->kind = TARGET_WAITKIND_IGNORE;
+
+      exit_lwp (event_child);
+    }
+
+  return ptid;
+}
+
+static ptid_t
+linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
                  int target_options)
 {
   sigset_t prev_mask;
@@ -3245,9 +3362,7 @@ linux_nat_wait_1 (struct target_ops *ops,
       gdb_assert (lp == NULL);
 
       /* Block until we get an event reported with SIGCHLD.  */
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog, "LNW: about to sigsuspend\n");
-      sigsuspend (&suspend_mask);
+      wait_for_signal ();
     }
 
   gdb_assert (lp);
@@ -3280,7 +3395,7 @@ linux_nat_wait_1 (struct target_ops *ops,
       && !USE_SIGTRAP_SIGINFO)
     {
       struct regcache *regcache = get_thread_regcache (lp->ptid);
-      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      struct gdbarch *gdbarch = regcache->arch ();
       int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
 
       if (decr_pc != 0)
@@ -3308,7 +3423,7 @@ linux_nat_wait_1 (struct target_ops *ops,
       resume_clear_callback (lp, NULL);
     }
 
-  if (linux_nat_status_is_event (status))
+  if (linux_target->low_status_is_event (status))
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
@@ -3345,6 +3460,9 @@ linux_nat_wait_1 (struct target_ops *ops,
   else
     lp->core = linux_common_core_of_thread (lp->ptid);
 
+  if (ourstatus->kind == TARGET_WAITKIND_EXITED)
+    return filter_exit_event (lp, ourstatus);
+
   return lp->ptid;
 }
 
@@ -3380,7 +3498,7 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data)
   else
     {
       struct regcache *regcache = get_thread_regcache (lp->ptid);
-      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      struct gdbarch *gdbarch = regcache->arch ();
 
       TRY
        {
@@ -3391,7 +3509,7 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data)
             immediately, and we're not waiting for this LWP.  */
          if (!ptid_match (lp->ptid, *wait_ptid_p))
            {
-             if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+             if (breakpoint_inserted_here_p (regcache->aspace (), pc))
                leave_stopped = 1;
            }
 
@@ -3419,10 +3537,9 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data)
   return 0;
 }
 
-static ptid_t
-linux_nat_wait (struct target_ops *ops,
-               ptid_t ptid, struct target_waitstatus *ourstatus,
-               int target_options)
+ptid_t
+linux_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+                       int target_options)
 {
   ptid_t event_ptid;
 
@@ -3452,7 +3569,7 @@ linux_nat_wait (struct target_ops *ops,
   if (target_is_non_stop_p ())
     iterate_over_lwps (minus_one_ptid, resume_stopped_resumed_lwps, &ptid);
 
-  event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus, target_options);
+  event_ptid = linux_nat_wait_1 (ptid, ourstatus, target_options);
 
   /* If we requested any event, and something came out, assume there
      may be more.  If we requested a specific lwp or process, also
@@ -3466,44 +3583,44 @@ linux_nat_wait (struct target_ops *ops,
   return event_ptid;
 }
 
-static int
-kill_callback (struct lwp_info *lp, void *data)
+/* Kill one LWP.  */
+
+static void
+kill_one_lwp (pid_t pid)
 {
   /* PTRACE_KILL may resume the inferior.  Send SIGKILL first.  */
 
   errno = 0;
-  kill_lwp (ptid_get_lwp (lp->ptid), SIGKILL);
+  kill_lwp (pid, SIGKILL);
   if (debug_linux_nat)
     {
       int save_errno = errno;
 
       fprintf_unfiltered (gdb_stdlog,
-                         "KC:  kill (SIGKILL) %s, 0, 0 (%s)\n",
-                         target_pid_to_str (lp->ptid),
+                         "KC:  kill (SIGKILL) %ld, 0, 0 (%s)\n", (long) pid,
                          save_errno ? safe_strerror (save_errno) : "OK");
     }
 
   /* Some kernels ignore even SIGKILL for processes under ptrace.  */
 
   errno = 0;
-  ptrace (PTRACE_KILL, ptid_get_lwp (lp->ptid), 0, 0);
+  ptrace (PTRACE_KILL, pid, 0, 0);
   if (debug_linux_nat)
     {
       int save_errno = errno;
 
       fprintf_unfiltered (gdb_stdlog,
-                         "KC:  PTRACE_KILL %s, 0, 0 (%s)\n",
-                         target_pid_to_str (lp->ptid),
+                         "KC:  PTRACE_KILL %ld, 0, 0 (%s)\n", (long) pid,
                          save_errno ? safe_strerror (save_errno) : "OK");
     }
-
-  return 0;
 }
 
-static int
-kill_wait_callback (struct lwp_info *lp, void *data)
+/* Wait for an LWP to die.  */
+
+static void
+kill_wait_one_lwp (pid_t pid)
 {
-  pid_t pid;
+  pid_t res;
 
   /* We must make sure that there are no pending events (delayed
      SIGSTOPs, pending SIGTRAPs, etc.) to make sure the current
@@ -3511,49 +3628,80 @@ kill_wait_callback (struct lwp_info *lp, void *data)
 
   do
     {
-      pid = my_waitpid (ptid_get_lwp (lp->ptid), NULL, __WALL);
-      if (pid != (pid_t) -1)
+      res = my_waitpid (pid, NULL, __WALL);
+      if (res != (pid_t) -1)
        {
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
-                               "KWC: wait %s received unknown.\n",
-                               target_pid_to_str (lp->ptid));
+                               "KWC: wait %ld received unknown.\n",
+                               (long) pid);
          /* The Linux kernel sometimes fails to kill a thread
             completely after PTRACE_KILL; that goes from the stop
             point in do_fork out to the one in get_signal_to_deliver
             and waits again.  So kill it again.  */
-         kill_callback (lp, NULL);
+         kill_one_lwp (pid);
        }
     }
-  while (pid == ptid_get_lwp (lp->ptid));
+  while (res == pid);
+
+  gdb_assert (res == -1 && errno == ECHILD);
+}
+
+/* Callback for iterate_over_lwps.  */
+
+static int
+kill_callback (struct lwp_info *lp, void *data)
+{
+  kill_one_lwp (ptid_get_lwp (lp->ptid));
+  return 0;
+}
 
-  gdb_assert (pid == -1 && errno == ECHILD);
+/* Callback for iterate_over_lwps.  */
+
+static int
+kill_wait_callback (struct lwp_info *lp, void *data)
+{
+  kill_wait_one_lwp (ptid_get_lwp (lp->ptid));
   return 0;
 }
 
+/* Kill the fork children of any threads of inferior INF that are
+   stopped at a fork event.  */
+
 static void
-linux_nat_kill (struct target_ops *ops)
+kill_unfollowed_fork_children (struct inferior *inf)
 {
-  struct target_waitstatus last;
-  ptid_t last_ptid;
-  int status;
+  struct thread_info *thread;
 
+  ALL_NON_EXITED_THREADS (thread)
+    if (thread->inf == inf)
+      {
+       struct target_waitstatus *ws = &thread->pending_follow;
+
+       if (ws->kind == TARGET_WAITKIND_FORKED
+           || ws->kind == TARGET_WAITKIND_VFORKED)
+         {
+           ptid_t child_ptid = ws->value.related_pid;
+           int child_pid = ptid_get_pid (child_ptid);
+           int child_lwp = ptid_get_lwp (child_ptid);
+
+           kill_one_lwp (child_lwp);
+           kill_wait_one_lwp (child_lwp);
+
+           /* Let the arch-specific native code know this process is
+              gone.  */
+           linux_target->low_forget_process (child_pid);
+         }
+      }
+}
+
+void
+linux_nat_target::kill ()
+{
   /* If we're stopped while forking and we haven't followed yet,
      kill the other task.  We need to do this first because the
      parent will be sleeping if this is a vfork.  */
-
-  get_last_target_status (&last_ptid, &last);
-
-  if (last.kind == TARGET_WAITKIND_FORKED
-      || last.kind == TARGET_WAITKIND_VFORKED)
-    {
-      ptrace (PT_KILL, ptid_get_pid (last.value.related_pid), 0, 0);
-      wait (&status);
-
-      /* Let the arch-specific native code know this process is
-        gone.  */
-      linux_nat_forget_process (ptid_get_pid (last.value.related_pid));
-    }
+  kill_unfollowed_fork_children (current_inferior ());
 
   if (forks_exist_p ())
     linux_fork_killall ();
@@ -3575,11 +3723,11 @@ linux_nat_kill (struct target_ops *ops)
       iterate_over_lwps (ptid, kill_wait_callback, NULL);
     }
 
-  target_mourn_inferior ();
+  target_mourn_inferior (inferior_ptid);
 }
 
-static void
-linux_nat_mourn_inferior (struct target_ops *ops)
+void
+linux_nat_target::mourn_inferior ()
 {
   int pid = ptid_get_pid (inferior_ptid);
 
@@ -3587,7 +3735,7 @@ linux_nat_mourn_inferior (struct target_ops *ops)
 
   if (! forks_exist_p ())
     /* Normal case, no other forks available.  */
-    linux_ops->to_mourn_inferior (ops);
+    inf_ptrace_target::mourn_inferior ();
   else
     /* Multi-fork case.  The current inferior_ptid has exited, but
        there are other viable forks to debug.  Delete the exiting
@@ -3595,7 +3743,7 @@ linux_nat_mourn_inferior (struct target_ops *ops)
     linux_fork_mourn_inferior ();
 
   /* Let the arch-specific native code know this process is gone.  */
-  linux_nat_forget_process (pid);
+  linux_target->low_forget_process (pid);
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
@@ -3604,14 +3752,9 @@ linux_nat_mourn_inferior (struct target_ops *ops)
 static void
 siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction)
 {
-  int done = 0;
-
-  if (linux_nat_siginfo_fixup != NULL)
-    done = linux_nat_siginfo_fixup (siginfo, inf_siginfo, direction);
-
-  /* If there was no callback, or the callback didn't do anything,
-     then just do a straight memcpy.  */
-  if (!done)
+  /* If the low target didn't do anything, then just do a straight
+     memcpy.  */
+  if (!linux_target->low_siginfo_fixup (siginfo, inf_siginfo, direction))
     {
       if (direction == 1)
        memcpy (siginfo, inf_siginfo, sizeof (siginfo_t));
@@ -3621,7 +3764,7 @@ siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction)
 }
 
 static enum target_xfer_status
-linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
+linux_xfer_siginfo (enum target_object object,
                     const char *annex, gdb_byte *readbuf,
                    const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
                    ULONGEST *xfered_len)
@@ -3676,16 +3819,33 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
 }
 
 static enum target_xfer_status
-linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
-                       const char *annex, gdb_byte *readbuf,
-                       const gdb_byte *writebuf,
-                       ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
+linux_nat_xfer_osdata (enum target_object object,
+                      const char *annex, gdb_byte *readbuf,
+                      const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+                      ULONGEST *xfered_len);
+
+static enum target_xfer_status
+linux_proc_xfer_spu (enum target_object object,
+                    const char *annex, gdb_byte *readbuf,
+                    const gdb_byte *writebuf,
+                    ULONGEST offset, ULONGEST len, ULONGEST *xfered_len);
+
+static enum target_xfer_status
+linux_proc_xfer_partial (enum target_object object,
+                        const char *annex, gdb_byte *readbuf,
+                        const gdb_byte *writebuf,
+                        ULONGEST offset, LONGEST len, ULONGEST *xfered_len);
+
+enum target_xfer_status
+linux_nat_target::xfer_partial (enum target_object object,
+                               const char *annex, gdb_byte *readbuf,
+                               const gdb_byte *writebuf,
+                               ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
 {
-  struct cleanup *old_chain;
   enum target_xfer_status xfer;
 
   if (object == TARGET_OBJECT_SIGNAL_INFO)
-    return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf,
+    return linux_xfer_siginfo (object, annex, readbuf, writebuf,
                               offset, len, xfered_len);
 
   /* The target is connected but no live inferior is selected.  Pass
@@ -3694,20 +3854,44 @@ linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
   if (object == TARGET_OBJECT_MEMORY && ptid_equal (inferior_ptid, null_ptid))
     return TARGET_XFER_EOF;
 
-  old_chain = save_inferior_ptid ();
+  if (object == TARGET_OBJECT_AUXV)
+    return memory_xfer_auxv (this, object, annex, readbuf, writebuf,
+                            offset, len, xfered_len);
+
+  if (object == TARGET_OBJECT_OSDATA)
+    return linux_nat_xfer_osdata (object, annex, readbuf, writebuf,
+                                 offset, len, xfered_len);
+
+  if (object == TARGET_OBJECT_SPU)
+    return linux_proc_xfer_spu (object, annex, readbuf, writebuf,
+                               offset, len, xfered_len);
 
-  if (ptid_lwp_p (inferior_ptid))
-    inferior_ptid = pid_to_ptid (ptid_get_lwp (inferior_ptid));
+  /* GDB calculates all addresses in the largest possible address
+     width.
+     The address width must be masked before its final use - either by
+     linux_proc_xfer_partial or inf_ptrace_target::xfer_partial.
 
-  xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
-                                    offset, len, xfered_len);
+     Compare ADDR_BIT first to avoid a compiler warning on shift overflow.  */
 
-  do_cleanups (old_chain);
-  return xfer;
+  if (object == TARGET_OBJECT_MEMORY)
+    {
+      int addr_bit = gdbarch_addr_bit (target_gdbarch ());
+
+      if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
+       offset &= ((ULONGEST) 1 << addr_bit) - 1;
+    }
+
+  xfer = linux_proc_xfer_partial (object, annex, readbuf, writebuf,
+                                 offset, len, xfered_len);
+  if (xfer != TARGET_XFER_EOF)
+    return xfer;
+
+  return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf,
+                                         offset, len, xfered_len);
 }
 
-static int
-linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+linux_nat_target::thread_alive (ptid_t ptid)
 {
   /* As long as a PTID is in lwp list, consider it alive.  */
   return find_lwp_pid (ptid) != NULL;
@@ -3716,8 +3900,8 @@ linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid)
 /* Implement the to_update_thread_list target method for this
    target.  */
 
-static void
-linux_nat_update_thread_list (struct target_ops *ops)
+void
+linux_nat_target::update_thread_list ()
 {
   struct lwp_info *lwp;
 
@@ -3729,11 +3913,17 @@ linux_nat_update_thread_list (struct target_ops *ops)
   /* Update the processor core that each lwp/thread was last seen
      running on.  */
   ALL_LWPS (lwp)
-    lwp->core = linux_common_core_of_thread (lwp->ptid);
+    {
+      /* Avoid accessing /proc if the thread hasn't run since we last
+        time we fetched the thread's core.  Accessing /proc becomes
+        noticeably expensive when we have thousands of LWPs.  */
+      if (lwp->core == -1)
+       lwp->core = linux_common_core_of_thread (lwp->ptid);
+    }
 }
 
-static char *
-linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+linux_nat_target::pid_to_str (ptid_t ptid)
 {
   static char buf[64];
 
@@ -3748,8 +3938,8 @@ linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
   return normal_pid_to_str (ptid);
 }
 
-static const char *
-linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
+const char *
+linux_nat_target::thread_name (struct thread_info *thr)
 {
   return linux_proc_tid_get_name (thr->ptid);
 }
@@ -3757,19 +3947,18 @@ linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
 /* Accepts an integer PID; Returns a string representing a file that
    can be opened to get the symbols for the child process.  */
 
-static char *
-linux_child_pid_to_exec_file (struct target_ops *self, int pid)
+char *
+linux_nat_target::pid_to_exec_file (int pid)
 {
   return linux_proc_pid_to_exec_file (pid);
 }
 
-/* Implement the to_xfer_partial interface for memory reads using the /proc
-   filesystem.  Because we can use a single read() call for /proc, this
-   can be much more efficient than banging away at PTRACE_PEEKTEXT,
-   but it doesn't support writes.  */
+/* Implement the to_xfer_partial target method 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.  */
 
 static enum target_xfer_status
-linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
+linux_proc_xfer_partial (enum target_object object,
                         const char *annex, gdb_byte *readbuf,
                         const gdb_byte *writebuf,
                         ULONGEST offset, LONGEST len, ULONGEST *xfered_len)
@@ -3778,7 +3967,7 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
   int fd;
   char filename[64];
 
-  if (object != TARGET_OBJECT_MEMORY || !readbuf)
+  if (object != TARGET_OBJECT_MEMORY)
     return TARGET_XFER_EOF;
 
   /* Don't bother for one word.  */
@@ -3787,28 +3976,29 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
 
   /* We could keep this file open and cache it - possibly one per
      thread.  That requires some juggling, but is even faster.  */
-  xsnprintf (filename, sizeof filename, "/proc/%d/mem",
-            ptid_get_pid (inferior_ptid));
-  fd = gdb_open_cloexec (filename, O_RDONLY | O_LARGEFILE, 0);
+  xsnprintf (filename, sizeof filename, "/proc/%ld/mem",
+            ptid_get_lwp (inferior_ptid));
+  fd = gdb_open_cloexec (filename, ((readbuf ? O_RDONLY : O_WRONLY)
+                                   | O_LARGEFILE), 0);
   if (fd == -1)
     return TARGET_XFER_EOF;
 
-  /* 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).  */
 #ifdef HAVE_PREAD64
-  if (pread64 (fd, readbuf, len, offset) != len)
+  ret = (readbuf ? pread64 (fd, readbuf, len, offset)
+        : pwrite64 (fd, writebuf, len, offset));
 #else
-  if (lseek (fd, offset, SEEK_SET) == -1 || read (fd, readbuf, len) != len)
+  ret = lseek (fd, offset, SEEK_SET);
+  if (ret != -1)
+    ret = (readbuf ? read (fd, readbuf, len)
+          : write (fd, writebuf, len));
 #endif
-    ret = 0;
-  else
-    ret = len;
 
   close (fd);
 
-  if (ret == 0)
+  if (ret == -1 || ret == 0)
     return TARGET_XFER_EOF;
   else
     {
@@ -3872,7 +4062,7 @@ spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, ULONGEST len)
    object type, using the /proc file system.  */
 
 static enum target_xfer_status
-linux_proc_xfer_spu (struct target_ops *ops, enum target_object object,
+linux_proc_xfer_spu (enum target_object object,
                     const char *annex, gdb_byte *readbuf,
                     const gdb_byte *writebuf,
                     ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
@@ -3880,7 +4070,7 @@ linux_proc_xfer_spu (struct target_ops *ops, enum target_object object,
   char buf[128];
   int fd = 0;
   int ret = -1;
-  int pid = ptid_get_pid (inferior_ptid);
+  int pid = ptid_get_lwp (inferior_ptid);
 
   if (!annex)
     {
@@ -3980,20 +4170,17 @@ void
 linux_proc_pending_signals (int pid, sigset_t *pending,
                            sigset_t *blocked, sigset_t *ignored)
 {
-  FILE *procfile;
   char buffer[PATH_MAX], fname[PATH_MAX];
-  struct cleanup *cleanup;
 
   sigemptyset (pending);
   sigemptyset (blocked);
   sigemptyset (ignored);
   xsnprintf (fname, sizeof fname, "/proc/%d/status", pid);
-  procfile = gdb_fopen_cloexec (fname, "r");
+  gdb_file_up procfile = gdb_fopen_cloexec (fname, "r");
   if (procfile == NULL)
     error (_("Could not open %s"), fname);
-  cleanup = make_cleanup_fclose (procfile);
 
-  while (fgets (buffer, PATH_MAX, procfile) != NULL)
+  while (fgets (buffer, PATH_MAX, procfile.get ()) != NULL)
     {
       /* Normal queued signals are on the SigPnd line in the status
         file.  However, 2.6 kernels also have a "shared" pending
@@ -4012,12 +4199,10 @@ linux_proc_pending_signals (int pid, sigset_t *pending,
       else if (startswith (buffer, "SigIgn:\t"))
        add_line_to_sigset (buffer + 8, ignored);
     }
-
-  do_cleanups (cleanup);
 }
 
 static enum target_xfer_status
-linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
+linux_nat_xfer_osdata (enum target_object object,
                       const char *annex, gdb_byte *readbuf,
                       const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
                       ULONGEST *xfered_len)
@@ -4031,49 +4216,6 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
     return TARGET_XFER_OK;
 }
 
-static enum target_xfer_status
-linux_xfer_partial (struct target_ops *ops, enum target_object object,
-                    const char *annex, gdb_byte *readbuf,
-                   const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
-                   ULONGEST *xfered_len)
-{
-  enum target_xfer_status xfer;
-
-  if (object == TARGET_OBJECT_AUXV)
-    return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
-                            offset, len, xfered_len);
-
-  if (object == TARGET_OBJECT_OSDATA)
-    return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
-                                 offset, len, xfered_len);
-
-  if (object == TARGET_OBJECT_SPU)
-    return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf,
-                               offset, len, xfered_len);
-
-  /* GDB calculates all the addresses in possibly larget width of the address.
-     Address width needs to be masked before its final use - either by
-     linux_proc_xfer_partial or inf_ptrace_xfer_partial.
-
-     Compare ADDR_BIT first to avoid a compiler warning on shift overflow.  */
-
-  if (object == TARGET_OBJECT_MEMORY)
-    {
-      int addr_bit = gdbarch_addr_bit (target_gdbarch ());
-
-      if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
-       offset &= ((ULONGEST) 1 << addr_bit) - 1;
-    }
-
-  xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
-                                 offset, len, xfered_len);
-  if (xfer != TARGET_XFER_EOF)
-    return xfer;
-
-  return super_xfer_partial (ops, object, annex, readbuf, writebuf,
-                            offset, len, xfered_len);
-}
-
 static void
 cleanup_target_stop (void *arg)
 {
@@ -4082,20 +4224,19 @@ cleanup_target_stop (void *arg)
   gdb_assert (arg != NULL);
 
   /* Unpause all */
-  target_resume (*ptid, 0, GDB_SIGNAL_0);
+  target_continue_no_signal (*ptid);
 }
 
-static VEC(static_tracepoint_marker_p) *
-linux_child_static_tracepoint_markers_by_strid (struct target_ops *self,
-                                               const char *strid)
+std::vector<static_tracepoint_marker>
+linux_nat_target::static_tracepoint_markers_by_strid (const char *strid)
 {
   char s[IPA_CMD_BUF_SIZE];
   struct cleanup *old_chain;
   int pid = ptid_get_pid (inferior_ptid);
-  VEC(static_tracepoint_marker_p) *markers = NULL;
-  struct static_tracepoint_marker *marker = NULL;
-  char *p = s;
+  std::vector<static_tracepoint_marker> markers;
+  const char *p = s;
   ptid_t ptid = ptid_build (pid, 0, 0);
+  static_tracepoint_marker marker;
 
   /* Pause all */
   target_stop (ptid);
@@ -4105,29 +4246,16 @@ linux_child_static_tracepoint_markers_by_strid (struct target_ops *self,
 
   agent_run_command (pid, s, strlen (s) + 1);
 
-  old_chain = make_cleanup (free_current_marker, &marker);
-  make_cleanup (cleanup_target_stop, &ptid);
+  old_chain = make_cleanup (cleanup_target_stop, &ptid);
 
   while (*p++ == 'm')
     {
-      if (marker == NULL)
-       marker = XCNEW (struct static_tracepoint_marker);
-
       do
        {
-         parse_static_tracepoint_marker_definition (p, &p, marker);
+         parse_static_tracepoint_marker_definition (p, &p, &marker);
 
-         if (strid == NULL || strcmp (strid, marker->str_id) == 0)
-           {
-             VEC_safe_push (static_tracepoint_marker_p,
-                            markers, marker);
-             marker = NULL;
-           }
-         else
-           {
-             release_static_tracepoint_marker (marker);
-             memset (marker, 0, sizeof (*marker));
-           }
+         if (strid == NULL || marker.str_id == strid)
+           markers.push_back (std::move (marker));
        }
       while (*p++ == ',');     /* comma-separated list */
 
@@ -4142,82 +4270,34 @@ linux_child_static_tracepoint_markers_by_strid (struct target_ops *self,
   return markers;
 }
 
-/* Create a prototype generic GNU/Linux target.  The client can override
-   it with local methods.  */
-
-static void
-linux_target_install_ops (struct target_ops *t)
-{
-  t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
-  t->to_remove_fork_catchpoint = linux_child_remove_fork_catchpoint;
-  t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
-  t->to_remove_vfork_catchpoint = linux_child_remove_vfork_catchpoint;
-  t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
-  t->to_remove_exec_catchpoint = linux_child_remove_exec_catchpoint;
-  t->to_set_syscall_catchpoint = linux_child_set_syscall_catchpoint;
-  t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
-  t->to_post_startup_inferior = linux_child_post_startup_inferior;
-  t->to_post_attach = linux_child_post_attach;
-  t->to_follow_fork = linux_child_follow_fork;
-
-  super_xfer_partial = t->to_xfer_partial;
-  t->to_xfer_partial = linux_xfer_partial;
-
-  t->to_static_tracepoint_markers_by_strid
-    = linux_child_static_tracepoint_markers_by_strid;
-}
-
-struct target_ops *
-linux_target (void)
-{
-  struct target_ops *t;
-
-  t = inf_ptrace_target ();
-  linux_target_install_ops (t);
-
-  return t;
-}
-
-struct target_ops *
-linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
-{
-  struct target_ops *t;
-
-  t = inf_ptrace_trad_target (register_u_offset);
-  linux_target_install_ops (t);
-
-  return t;
-}
-
 /* target_is_async_p implementation.  */
 
-static int
-linux_nat_is_async_p (struct target_ops *ops)
+bool
+linux_nat_target::is_async_p ()
 {
   return linux_is_async_p ();
 }
 
 /* target_can_async_p implementation.  */
 
-static int
-linux_nat_can_async_p (struct target_ops *ops)
+bool
+linux_nat_target::can_async_p ()
 {
-  /* NOTE: palves 2008-03-21: We're only async when the user requests
-     it explicitly with the "set target-async" command.
-     Someday, linux will always be async.  */
+  /* We're always async, unless the user explicitly prevented it with the
+     "maint set target-async" command.  */
   return target_async_permitted;
 }
 
-static int
-linux_nat_supports_non_stop (struct target_ops *self)
+bool
+linux_nat_target::supports_non_stop ()
 {
   return 1;
 }
 
 /* to_always_non_stop_p implementation.  */
 
-static int
-linux_nat_always_non_stop_p (struct target_ops *self)
+bool
+linux_nat_target::always_non_stop_p ()
 {
   return 1;
 }
@@ -4227,14 +4307,14 @@ linux_nat_always_non_stop_p (struct target_ops *self)
 
 int linux_multi_process = 1;
 
-static int
-linux_nat_supports_multi_process (struct target_ops *self)
+bool
+linux_nat_target::supports_multi_process ()
 {
   return linux_multi_process;
 }
 
-static int
-linux_nat_supports_disable_randomization (struct target_ops *self)
+bool
+linux_nat_target::supports_disable_randomization ()
 {
 #ifdef HAVE_PERSONALITY
   return 1;
@@ -4243,51 +4323,6 @@ linux_nat_supports_disable_randomization (struct target_ops *self)
 #endif
 }
 
-static int async_terminal_is_ours = 1;
-
-/* target_terminal_inferior implementation.
-
-   This is a wrapper around child_terminal_inferior to add async support.  */
-
-static void
-linux_nat_terminal_inferior (struct target_ops *self)
-{
-  child_terminal_inferior (self);
-
-  /* Calls to target_terminal_*() are meant to be idempotent.  */
-  if (!async_terminal_is_ours)
-    return;
-
-  delete_file_handler (input_fd);
-  async_terminal_is_ours = 0;
-  set_sigint_trap ();
-}
-
-/* target_terminal_ours implementation.
-
-   This is a wrapper around child_terminal_ours to add async support (and
-   implement the target_terminal_ours vs target_terminal_ours_for_output
-   distinction).  child_terminal_ours is currently no different than
-   child_terminal_ours_for_output.
-   We leave target_terminal_ours_for_output alone, leaving it to
-   child_terminal_ours_for_output.  */
-
-static void
-linux_nat_terminal_ours (struct target_ops *self)
-{
-  /* GDB should never give the terminal to the inferior if the
-     inferior is running in the background (run&, continue&, etc.),
-     but claiming it sure should.  */
-  child_terminal_ours (self);
-
-  if (async_terminal_is_ours)
-    return;
-
-  clear_sigint_trap ();
-  add_file_handler (input_fd, stdin_event_handler, 0);
-  async_terminal_is_ours = 1;
-}
-
 /* SIGCHLD handler that serves two purposes: In non-stop/async mode,
    so we notice when any child changes state, and notify the
    event-loop; it allows us to use sigsuspend in linux_nat_wait_1
@@ -4358,8 +4393,8 @@ linux_async_pipe (int enable)
 
 /* target_async implementation.  */
 
-static void
-linux_nat_async (struct target_ops *ops, int enable)
+void
+linux_nat_target::async (int enable)
 {
   if (enable)
     {
@@ -4427,32 +4462,20 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
   return 0;
 }
 
-static void
-linux_nat_stop (struct target_ops *self, ptid_t ptid)
+void
+linux_nat_target::stop (ptid_t ptid)
 {
   iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
 }
 
-static void
-linux_nat_interrupt (struct target_ops *self, ptid_t ptid)
-{
-  if (non_stop)
-    iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
-  else
-    linux_ops->to_interrupt (linux_ops, ptid);
-}
-
-static void
-linux_nat_close (struct target_ops *self)
+void
+linux_nat_target::close ()
 {
   /* Unregister from the event loop.  */
-  if (linux_nat_is_async_p (self))
-    linux_nat_async (self, 0);
-
-  if (linux_ops->to_close)
-    linux_ops->to_close (linux_ops);
+  if (is_async_p ())
+    async (0);
 
-  super_close (self);
+  inf_ptrace_target::close ();
 }
 
 /* When requests are passed down from the linux-nat layer to the
@@ -4462,8 +4485,8 @@ linux_nat_close (struct target_ops *self)
    lwpid is a "main" process id or not (it assumes so).  We reverse
    look up the "main" process id from the lwp here.  */
 
-static struct address_space *
-linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid)
+struct address_space *
+linux_nat_target::thread_address_space (ptid_t ptid)
 {
   struct lwp_info *lwp;
   struct inferior *inf;
@@ -4489,8 +4512,8 @@ linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid)
 
 /* Return the cached value of the processor core for thread PTID.  */
 
-static int
-linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
+int
+linux_nat_target::core_of_thread (ptid_t ptid)
 {
   struct lwp_info *info = find_lwp_pid (ptid);
 
@@ -4501,13 +4524,13 @@ linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
 
 /* Implementation of to_filesystem_is_local.  */
 
-static int
-linux_nat_filesystem_is_local (struct target_ops *ops)
+bool
+linux_nat_target::filesystem_is_local ()
 {
   struct inferior *inf = current_inferior ();
 
   if (inf->fake_pid_p || inf->pid == 0)
-    return 1;
+    return true;
 
   return linux_ns_same (inf->pid, LINUX_NS_MNT);
 }
@@ -4531,11 +4554,10 @@ linux_nat_fileio_pid_of (struct inferior *inf)
 
 /* Implementation of to_fileio_open.  */
 
-static int
-linux_nat_fileio_open (struct target_ops *self,
-                      struct inferior *inf, const char *filename,
-                      int flags, int mode, int warn_if_slow,
-                      int *target_errno)
+int
+linux_nat_target::fileio_open (struct inferior *inf, const char *filename,
+                              int flags, int mode, int warn_if_slow,
+                              int *target_errno)
 {
   int nat_flags;
   mode_t nat_mode;
@@ -4558,35 +4580,29 @@ linux_nat_fileio_open (struct target_ops *self,
 
 /* Implementation of to_fileio_readlink.  */
 
-static char *
-linux_nat_fileio_readlink (struct target_ops *self,
-                          struct inferior *inf, const char *filename,
-                          int *target_errno)
+gdb::optional<std::string>
+linux_nat_target::fileio_readlink (struct inferior *inf, const char *filename,
+                                  int *target_errno)
 {
   char buf[PATH_MAX];
   int len;
-  char *ret;
 
   len = linux_mntns_readlink (linux_nat_fileio_pid_of (inf),
                              filename, buf, sizeof (buf));
   if (len < 0)
     {
       *target_errno = host_to_fileio_error (errno);
-      return NULL;
+      return {};
     }
 
-  ret = (char *) xmalloc (len + 1);
-  memcpy (ret, buf, len);
-  ret[len] = '\0';
-  return ret;
+  return std::string (buf, len);
 }
 
 /* Implementation of to_fileio_unlink.  */
 
-static int
-linux_nat_fileio_unlink (struct target_ops *self,
-                        struct inferior *inf, const char *filename,
-                        int *target_errno)
+int
+linux_nat_target::fileio_unlink (struct inferior *inf, const char *filename,
+                                int *target_errno)
 {
   int ret;
 
@@ -4598,135 +4614,21 @@ linux_nat_fileio_unlink (struct target_ops *self,
   return ret;
 }
 
+/* Implementation of the to_thread_events method.  */
+
 void
-linux_nat_add_target (struct target_ops *t)
-{
-  /* Save the provided single-threaded target.  We save this in a separate
-     variable because another target we've inherited from (e.g. inf-ptrace)
-     may have saved a pointer to T; we want to use it for the final
-     process stratum target.  */
-  linux_ops_saved = *t;
-  linux_ops = &linux_ops_saved;
-
-  /* Override some methods for multithreading.  */
-  t->to_create_inferior = linux_nat_create_inferior;
-  t->to_attach = linux_nat_attach;
-  t->to_detach = linux_nat_detach;
-  t->to_resume = linux_nat_resume;
-  t->to_wait = linux_nat_wait;
-  t->to_pass_signals = linux_nat_pass_signals;
-  t->to_xfer_partial = linux_nat_xfer_partial;
-  t->to_kill = linux_nat_kill;
-  t->to_mourn_inferior = linux_nat_mourn_inferior;
-  t->to_thread_alive = linux_nat_thread_alive;
-  t->to_update_thread_list = linux_nat_update_thread_list;
-  t->to_pid_to_str = linux_nat_pid_to_str;
-  t->to_thread_name = linux_nat_thread_name;
-  t->to_has_thread_control = tc_schedlock;
-  t->to_thread_address_space = linux_nat_thread_address_space;
-  t->to_stopped_by_watchpoint = linux_nat_stopped_by_watchpoint;
-  t->to_stopped_data_address = linux_nat_stopped_data_address;
-  t->to_stopped_by_sw_breakpoint = linux_nat_stopped_by_sw_breakpoint;
-  t->to_supports_stopped_by_sw_breakpoint = linux_nat_supports_stopped_by_sw_breakpoint;
-  t->to_stopped_by_hw_breakpoint = linux_nat_stopped_by_hw_breakpoint;
-  t->to_supports_stopped_by_hw_breakpoint = linux_nat_supports_stopped_by_hw_breakpoint;
-
-  t->to_can_async_p = linux_nat_can_async_p;
-  t->to_is_async_p = linux_nat_is_async_p;
-  t->to_supports_non_stop = linux_nat_supports_non_stop;
-  t->to_always_non_stop_p = linux_nat_always_non_stop_p;
-  t->to_async = linux_nat_async;
-  t->to_terminal_inferior = linux_nat_terminal_inferior;
-  t->to_terminal_ours = linux_nat_terminal_ours;
-
-  super_close = t->to_close;
-  t->to_close = linux_nat_close;
-
-  t->to_stop = linux_nat_stop;
-  t->to_interrupt = linux_nat_interrupt;
-
-  t->to_supports_multi_process = linux_nat_supports_multi_process;
-
-  t->to_supports_disable_randomization
-    = linux_nat_supports_disable_randomization;
-
-  t->to_core_of_thread = linux_nat_core_of_thread;
-
-  t->to_filesystem_is_local = linux_nat_filesystem_is_local;
-  t->to_fileio_open = linux_nat_fileio_open;
-  t->to_fileio_readlink = linux_nat_fileio_readlink;
-  t->to_fileio_unlink = linux_nat_fileio_unlink;
+linux_nat_target::thread_events (int enable)
+{
+  report_thread_events = enable;
+}
 
+linux_nat_target::linux_nat_target ()
+{
   /* We don't change the stratum; this target will sit at
      process_stratum and thread_db will set at thread_stratum.  This
      is a little strange, since this is a multi-threaded-capable
      target, but we want to be on the stack below thread_db, and we
      also want to be used for single-threaded processes.  */
-
-  add_target (t);
-}
-
-/* Register a method to call whenever a new thread is attached.  */
-void
-linux_nat_set_new_thread (struct target_ops *t,
-                         void (*new_thread) (struct lwp_info *))
-{
-  /* Save the pointer.  We only support a single registered instance
-     of the GNU/Linux native target, so we do not need to map this to
-     T.  */
-  linux_nat_new_thread = new_thread;
-}
-
-/* See declaration in linux-nat.h.  */
-
-void
-linux_nat_set_new_fork (struct target_ops *t,
-                       linux_nat_new_fork_ftype *new_fork)
-{
-  /* Save the pointer.  */
-  linux_nat_new_fork = new_fork;
-}
-
-/* See declaration in linux-nat.h.  */
-
-void
-linux_nat_set_forget_process (struct target_ops *t,
-                             linux_nat_forget_process_ftype *fn)
-{
-  /* Save the pointer.  */
-  linux_nat_forget_process_hook = fn;
-}
-
-/* See declaration in linux-nat.h.  */
-
-void
-linux_nat_forget_process (pid_t pid)
-{
-  if (linux_nat_forget_process_hook != NULL)
-    linux_nat_forget_process_hook (pid);
-}
-
-/* Register a method that converts a siginfo object between the layout
-   that ptrace returns, and the layout in the architecture of the
-   inferior.  */
-void
-linux_nat_set_siginfo_fixup (struct target_ops *t,
-                            int (*siginfo_fixup) (siginfo_t *,
-                                                  gdb_byte *,
-                                                  int))
-{
-  /* Save the pointer.  */
-  linux_nat_siginfo_fixup = siginfo_fixup;
-}
-
-/* Register a method to call prior to resuming a thread.  */
-
-void
-linux_nat_set_prepare_to_resume (struct target_ops *t,
-                                void (*prepare_to_resume) (struct lwp_info *))
-{
-  /* Save the pointer.  */
-  linux_nat_prepare_to_resume = prepare_to_resume;
 }
 
 /* See linux-nat.h.  */
@@ -4759,9 +4661,6 @@ current_lwp_ptid (void)
   return inferior_ptid;
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_linux_nat;
-
 void
 _initialize_linux_nat (void)
 {
@@ -4799,6 +4698,8 @@ Enables printf debugging output."),
   sigdelset (&suspend_mask, SIGCHLD);
 
   sigemptyset (&blocked_mask);
+
+  lwp_lwpid_htab_create ();
 }
 \f
 
This page took 0.052837 seconds and 4 git commands to generate.