gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / darwin-nat.c
index 8c5e8a0b1fd3859951c7464febb811d51df5f815..2d74bc010c35e29a3048b880355b3be5d55d9706 100644 (file)
@@ -1,5 +1,5 @@
 /* Darwin support for GDB, the GNU debugger.
-   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    Contributed by AdaCore.
 
@@ -25,7 +25,6 @@
 #include "symfile.h"
 #include "symtab.h"
 #include "objfiles.h"
-#include "gdb.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "gdbthread.h"
@@ -38,7 +37,9 @@
 #include "arch-utils.h"
 #include "bfd.h"
 #include "bfd/mach-o.h"
+#include "gdbarch.h"
 
+#include <copyfile.h>
 #include <sys/ptrace.h>
 #include <sys/signal.h>
 #include <setjmp.h>
 #include <mach/port.h>
 
 #include "darwin-nat.h"
-#include "common/filestuff.h"
+#include "filenames.h"
+#include "gdbsupport/filestuff.h"
+#include "gdbsupport/gdb_unlinker.h"
+#include "gdbsupport/pathstuff.h"
+#include "gdbsupport/scoped_fd.h"
+#include "nat/fork-inferior.h"
 
 /* Quick overview.
    Darwin kernel is Mach + BSD derived kernel.  Note that they share the
 #define PTRACE(CMD, PID, ADDR, SIG) \
  darwin_ptrace(#CMD, CMD, (PID), (ADDR), (SIG))
 
-static void darwin_interrupt (struct target_ops *self, ptid_t);
-
-static void darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
-                              enum gdb_signal signal);
-static void darwin_resume (ptid_t ptid, int step,
-                          enum gdb_signal signal);
-
-static ptid_t darwin_wait_to (struct target_ops *ops, ptid_t ptid,
-                              struct target_waitstatus *status, int options);
-static ptid_t darwin_wait (ptid_t ptid, struct target_waitstatus *status);
-
-static void darwin_mourn_inferior (struct target_ops *ops);
-
-static void darwin_kill_inferior (struct target_ops *ops);
-
 static void darwin_ptrace_me (void);
 
-static void darwin_ptrace_him (int pid);
-
-static void darwin_create_inferior (struct target_ops *ops, char *exec_file,
-                                   char *allargs, char **env, int from_tty);
-
-static void darwin_files_info (struct target_ops *ops);
-
-static char *darwin_pid_to_str (struct target_ops *ops, ptid_t tpid);
-
-static int darwin_thread_alive (struct target_ops *ops, ptid_t tpid);
-
 static void darwin_encode_reply (mig_reply_error_t *reply,
                                 mach_msg_header_t *hdr, integer_t code);
 
@@ -119,9 +99,6 @@ static void darwin_deallocate_exception_ports (darwin_inferior *inf);
 static void darwin_setup_exceptions (struct inferior *inf);
 static void darwin_deallocate_threads (struct inferior *inf);
 
-/* Target operations for Darwin.  */
-static struct target_ops *darwin_ops;
-
 /* Task identifier of gdb.  */
 static task_t gdb_task;
 
@@ -139,11 +116,15 @@ static vm_size_t mach_page_size;
 
 /* If Set, catch all mach exceptions (before they are converted to signals
    by the kernel).  */
-static int enable_mach_exceptions;
+static bool enable_mach_exceptions;
 
 /* Inferior that should report a fake stop event.  */
 static struct inferior *darwin_inf_fake_stop;
 
+/* If non-NULL, the shell we actually invoke.  See maybe_cache_shell
+   for details.  */
+static const char *copied_shell;
+
 #define PAGE_TRUNC(x) ((x) & ~(mach_page_size - 1))
 #define PAGE_ROUND(x) PAGE_TRUNC((x) + mach_page_size - 1)
 
@@ -273,17 +254,19 @@ cmp_thread_t (const void *l, const void *r)
   return (int)(tl - tr);
 }
 
-static void
-darwin_check_new_threads (struct inferior *inf)
+void
+darwin_nat_target::check_new_threads (inferior *inf)
 {
   kern_return_t kret;
-  unsigned int i;
   thread_array_t thread_list;
   unsigned int new_nbr;
   unsigned int old_nbr;
   unsigned int new_ix, old_ix;
-  darwin_inferior *darwin_inf = inf->priv;
-  VEC (darwin_thread_t) *thread_vec;
+  darwin_inferior *darwin_inf = get_darwin_inferior (inf);
+  std::vector<darwin_thread_t *> new_thread_vec;
+
+  if (darwin_inf == nullptr)
+    return;
 
   /* Get list of threads.  */
   kret = task_threads (darwin_inf->task, &thread_list, &new_nbr);
@@ -295,17 +278,15 @@ darwin_check_new_threads (struct inferior *inf)
   if (new_nbr > 1)
     qsort (thread_list, new_nbr, sizeof (thread_t), cmp_thread_t);
 
-  if (darwin_inf->threads)
-    old_nbr = VEC_length (darwin_thread_t, darwin_inf->threads);
-  else
-    old_nbr = 0;
+  old_nbr = darwin_inf->threads.size ();
 
   /* Quick check for no changes.  */
   if (old_nbr == new_nbr)
     {
+      size_t i;
+
       for (i = 0; i < new_nbr; i++)
-       if (thread_list[i]
-           != VEC_index (darwin_thread_t, darwin_inf->threads, i)->gdb_port)
+       if (thread_list[i] != darwin_inf->threads[i]->gdb_port)
          break;
       if (i == new_nbr)
        {
@@ -326,15 +307,15 @@ darwin_check_new_threads (struct inferior *inf)
     }
 
   /* Full handling: detect new threads, remove dead threads.  */
-  thread_vec = VEC_alloc (darwin_thread_t, new_nbr);
+
+  new_thread_vec.reserve (new_nbr);
 
   for (new_ix = 0, old_ix = 0; new_ix < new_nbr || old_ix < old_nbr;)
     {
-      thread_t new_id = (new_ix < new_nbr) ?
-       thread_list[new_ix] : THREAD_NULL;
-      darwin_thread_t *old = (old_ix < old_nbr) ?
-       VEC_index (darwin_thread_t, darwin_inf->threads, old_ix) : NULL;
-      thread_t old_id = old ? old->gdb_port : THREAD_NULL;
+      thread_t new_id = (new_ix < new_nbr) ? thread_list[new_ix] : THREAD_NULL;
+      darwin_thread_t *old
+       = (old_ix < old_nbr) ? darwin_inf->threads[old_ix] : NULL;
+      thread_t old_id = old != NULL ? old->gdb_port : THREAD_NULL;
 
       inferior_debug
        (12, _(" new_ix:%d/%d, old_ix:%d/%d, new_id:0x%x old_id:0x%x\n"),
@@ -343,7 +324,7 @@ darwin_check_new_threads (struct inferior *inf)
       if (old_id == new_id)
        {
          /* Thread still exist.  */
-         VEC_safe_push (darwin_thread_t, thread_vec, old);
+         new_thread_vec.push_back (old);
          new_ix++;
          old_ix++;
 
@@ -364,37 +345,23 @@ darwin_check_new_threads (struct inferior *inf)
       if (new_ix < new_nbr && (old_ix == old_nbr || new_id < old_id))
        {
          /* A thread was created.  */
-         struct thread_info *tp;
-         struct private_thread_info *pti;
+         darwin_thread_info *pti = new darwin_thread_info;
 
-         pti = XCNEW (struct private_thread_info);
          pti->gdb_port = new_id;
          pti->msg_state = DARWIN_RUNNING;
 
-         if (old_nbr == 0 && new_ix == 0)
-           {
-             /* A ptid is create when the inferior is started (see
-                fork-child.c) with lwp=tid=0.  This ptid will be renamed
-                later by darwin_init_thread_list ().  */
-             tp = find_thread_ptid (ptid_build (inf->pid, 0, 0));
-             gdb_assert (tp);
-             gdb_assert (tp->priv == NULL);
-             tp->priv = pti;
-           }
-         else
-           {
-             /* Add the new thread.  */
-             tp = add_thread_with_info
-               (ptid_build (inf->pid, 0, new_id), pti);
-           }
-         VEC_safe_push (darwin_thread_t, thread_vec, pti);
+         /* Add the new thread.  */
+         add_thread_with_info (this, ptid_t (inf->pid, 0, new_id), pti);
+         new_thread_vec.push_back (pti);
          new_ix++;
          continue;
        }
       if (old_ix < old_nbr && (new_ix == new_nbr || new_id > old_id))
        {
          /* A thread was removed.  */
-         delete_thread (ptid_build (inf->pid, 0, old_id));
+         struct thread_info *thr
+           = find_thread_ptid (this, ptid_t (inf->pid, 0, old_id));
+         delete_thread (thr);
          kret = mach_port_deallocate (gdb_task, old_id);
          MACH_CHECK_ERROR (kret);
          old_ix++;
@@ -403,9 +370,7 @@ darwin_check_new_threads (struct inferior *inf)
       gdb_assert_not_reached ("unexpected thread case");
     }
 
-  if (darwin_inf->threads)
-    VEC_free (darwin_thread_t, darwin_inf->threads);
-  darwin_inf->threads = thread_vec;
+  darwin_inf->threads = std::move (new_thread_vec);
 
   /* Deallocate the buffer.  */
   kret = vm_deallocate (gdb_task, (vm_address_t) thread_list,
@@ -413,44 +378,45 @@ darwin_check_new_threads (struct inferior *inf)
   MACH_CHECK_ERROR (kret);
 }
 
-static int
-find_inferior_task_it (struct inferior *inf, void *port_ptr)
-{
-  return inf->priv->task == *(task_t *)port_ptr;
-}
-
-static int
-find_inferior_pid_it (struct inferior *inf, void *pid_ptr)
-{
-  return inf->pid == *(int *)pid_ptr;
-}
-
 /* Return an inferior by task port.  */
 static struct inferior *
 darwin_find_inferior_by_task (task_t port)
 {
-  return iterate_over_inferiors (&find_inferior_task_it, &port);
+  for (inferior *inf : all_inferiors ())
+    {
+      darwin_inferior *priv = get_darwin_inferior (inf);
+
+      if (priv != nullptr && priv->task == port)
+       return inf;
+    }
+  return nullptr;
 }
 
 /* Return an inferior by pid port.  */
 static struct inferior *
 darwin_find_inferior_by_pid (int pid)
 {
-  return iterate_over_inferiors (&find_inferior_pid_it, &pid);
+  for (inferior *inf : all_inferiors ())
+    {
+      if (inf->pid == pid)
+       return inf;
+    }
+  return nullptr;
 }
 
 /* Return a thread by port.  */
 static darwin_thread_t *
 darwin_find_thread (struct inferior *inf, thread_t thread)
 {
-  darwin_thread_t *t;
-  int k;
-
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->priv->threads, k, t);
-       k++)
-    if (t->gdb_port == thread)
-      return t;
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  if (priv != nullptr)
+    for (darwin_thread_t *t : priv->threads)
+      {
+       if (t->gdb_port == thread)
+         return t;
+      }
+
   return NULL;
 }
 
@@ -459,14 +425,16 @@ darwin_find_thread (struct inferior *inf, thread_t thread)
 static void
 darwin_suspend_inferior (struct inferior *inf)
 {
-  if (!inf->priv->suspended)
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  if (priv != nullptr && !priv->suspended)
     {
       kern_return_t kret;
 
-      kret = task_suspend (inf->priv->task);
+      kret = task_suspend (priv->task);
       MACH_CHECK_ERROR (kret);
 
-      inf->priv->suspended = 1;
+      priv->suspended = 1;
     }
 }
 
@@ -475,34 +443,19 @@ darwin_suspend_inferior (struct inferior *inf)
 static void
 darwin_resume_inferior (struct inferior *inf)
 {
-  if (inf->priv->suspended)
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  if (priv != nullptr && priv->suspended)
     {
       kern_return_t kret;
 
-      kret = task_resume (inf->priv->task);
+      kret = task_resume (priv->task);
       MACH_CHECK_ERROR (kret);
 
-      inf->priv->suspended = 0;
+      priv->suspended = 0;
     }
 }
 
-/* Iterator functions.  */
-
-static int
-darwin_suspend_inferior_it (struct inferior *inf, void *arg)
-{
-  darwin_suspend_inferior (inf);
-  darwin_check_new_threads (inf);
-  return 0;
-}
-
-static int
-darwin_resume_inferior_it (struct inferior *inf, void *arg)
-{
-  darwin_resume_inferior (inf);
-  return 0;
-}
-
 static void
 darwin_dump_message (mach_msg_header_t *hdr, int disp_body)
 {
@@ -593,11 +546,13 @@ darwin_find_new_inferior (task_t task_port, thread_t thread_port)
   if (inf == NULL)
     return NULL;
 
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
   /* Deallocate saved exception ports.  */
-  darwin_deallocate_exception_ports (inf->priv);
+  darwin_deallocate_exception_ports (priv);
 
   /* No need to remove dead_name notification, but still...  */
-  kret = mach_port_request_notification (gdb_task, inf->priv->task,
+  kret = mach_port_request_notification (gdb_task, priv->task,
                                         MACH_NOTIFY_DEAD_NAME, 0,
                                         MACH_PORT_NULL,
                                         MACH_MSG_TYPE_MAKE_SEND_ONCE,
@@ -606,9 +561,9 @@ darwin_find_new_inferior (task_t task_port, thread_t thread_port)
     MACH_CHECK_ERROR (kret);
 
   /* Replace old task port.  */
-  kret = mach_port_deallocate (gdb_task, inf->priv->task);
+  kret = mach_port_deallocate (gdb_task, priv->task);
   MACH_CHECK_ERROR (kret);
-  inf->priv->task = task_port;
+  priv->task = task_port;
 
   darwin_setup_request_notification (inf);
   darwin_setup_exceptions (inf);
@@ -633,10 +588,10 @@ darwin_check_message_ndr (NDR_record_t *ndr)
 
 /* Decode an exception message.  */
 
-static int
-darwin_decode_exception_message (mach_msg_header_t *hdr,
-                                struct inferior **pinf,
-                                darwin_thread_t **pthread)
+int
+darwin_nat_target::decode_exception_message (mach_msg_header_t *hdr,
+                                            inferior **pinf,
+                                            darwin_thread_t **pthread)
 {
   mach_msg_body_t *bod = (mach_msg_body_t*)(hdr + 1);
   mach_msg_port_descriptor_t *desc = (mach_msg_port_descriptor_t *)(bod + 1);
@@ -710,7 +665,6 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
       /* Not a known inferior.  This could happen if the child fork, as
         the created process will inherit its exception port.
         FIXME: should the exception port be restored ?  */
-      kern_return_t kret;
       mig_reply_error_t reply;
 
       inferior_debug
@@ -735,7 +689,7 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
   /* Find thread by port.  */
   /* Check for new threads.  Do it early so that the port in the exception
      message can be deallocated.  */
-  darwin_check_new_threads (inf);
+  check_new_threads (inf);
 
   /* Free the thread port (as gdb knows the thread, it has already has a right
      for it, so this just decrement a reference counter).  */
@@ -778,11 +732,7 @@ darwin_decode_notify_message (mach_msg_header_t *hdr, struct inferior **pinf)
   NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
   integer_t *data = (integer_t *)(ndr + 1);
   struct inferior *inf;
-  darwin_thread_t *thread;
   task_t task_port;
-  thread_t thread_port;
-  kern_return_t kret;
-  int i;
 
   /* Check message header.  */
   if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
@@ -803,8 +753,12 @@ darwin_decode_notify_message (mach_msg_header_t *hdr, struct inferior **pinf)
   *pinf = inf;
 
   /* Check message destination.  */
-  if (inf != NULL && hdr->msgh_local_port != inf->priv->notify_port)
-    return -4;
+  if (inf != NULL)
+    {
+      darwin_inferior *priv = get_darwin_inferior (inf);
+      if (hdr->msgh_local_port != priv->notify_port)
+       return -4;
+    }
 
   return 0;
 }
@@ -830,6 +784,7 @@ darwin_send_reply (struct inferior *inf, darwin_thread_t *thread)
 {
   kern_return_t kret;
   mig_reply_error_t reply;
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
   darwin_encode_reply (&reply, &thread->event.header, KERN_SUCCESS);
 
@@ -839,16 +794,27 @@ darwin_send_reply (struct inferior *inf, darwin_thread_t *thread)
                   MACH_PORT_NULL);
   MACH_CHECK_ERROR (kret);
 
-  inf->priv->pending_messages--;
+  priv->pending_messages--;
+}
+
+/* Wrapper around the __pthread_kill syscall.  We use this instead of the
+   pthread_kill function to be able to send a signal to any kind of thread,
+   including GCD threads.  */
+
+static int
+darwin_pthread_kill (darwin_thread_t *thread, int nsignal)
+{
+  DIAGNOSTIC_PUSH;
+  DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS;
+  int res = syscall (SYS___pthread_kill, thread->gdb_port, nsignal);
+  DIAGNOSTIC_POP;
+  return res;
 }
 
 static void
 darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
                      int step, int nsignal)
 {
-  kern_return_t kret;
-  int res;
-
   inferior_debug
     (3, _("darwin_resume_thread: state=%d, thread=0x%x, step=%d nsignal=%d\n"),
      thread->msg_state, thread->gdb_port, step, nsignal);
@@ -860,8 +826,8 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
          && thread->event.ex_data[0] == EXC_SOFT_SIGNAL)
        {
          /* Either deliver a new signal or cancel the signal received.  */
-         res = PTRACE (PT_THUPDATE, inf->pid,
-                       (caddr_t) (uintptr_t) thread->gdb_port, nsignal);
+         int res = PTRACE (PT_THUPDATE, inf->pid,
+                           (caddr_t) (uintptr_t) thread->gdb_port, nsignal);
          if (res < 0)
            inferior_debug (1, _("ptrace THUP: res=%d\n"), res);
        }
@@ -869,7 +835,7 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
        {
          /* Note: ptrace is allowed only if the process is stopped.
             Directly send the signal to the thread.  */
-         res = syscall (SYS___pthread_kill, thread->gdb_port, nsignal);
+         int res = darwin_pthread_kill (thread, nsignal);
          inferior_debug (4, _("darwin_resume_thread: kill 0x%x %d: %d\n"),
                          thread->gdb_port, nsignal, res);
          thread->signaled = 1;
@@ -889,7 +855,7 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
       break;
 
     case DARWIN_STOPPED:
-      kret = thread_resume (thread->gdb_port);
+      kern_return_t kret = thread_resume (thread->gdb_port);
       MACH_CHECK_ERROR (kret);
 
       thread->msg_state = DARWIN_RUNNING;
@@ -902,30 +868,11 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
 static void
 darwin_resume_inferior_threads (struct inferior *inf, int step, int nsignal)
 {
-  darwin_thread_t *thread;
-  int k;
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->priv->threads, k, thread);
-       k++)
-    darwin_resume_thread (inf, thread, step, nsignal);
-}
-
-struct resume_inferior_threads_param
-{
-  int step;
-  int nsignal;
-};
-
-static int
-darwin_resume_inferior_threads_it (struct inferior *inf, void *param)
-{
-  int step = ((struct resume_inferior_threads_param *)param)->step;
-  int nsignal = ((struct resume_inferior_threads_param *)param)->nsignal;
-
-  darwin_resume_inferior_threads (inf, step, nsignal);
-
-  return 0;
+  if (priv != nullptr)
+    for (darwin_thread_t *thread : priv->threads)
+      darwin_resume_thread (inf, thread, step, nsignal);
 }
 
 /* Suspend all threads of INF.  */
@@ -933,40 +880,36 @@ darwin_resume_inferior_threads_it (struct inferior *inf, void *param)
 static void
 darwin_suspend_inferior_threads (struct inferior *inf)
 {
-  darwin_thread_t *thread;
-  kern_return_t kret;
-  int k;
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->priv->threads, k, thread);
-       k++)
-    switch (thread->msg_state)
-      {
-      case DARWIN_STOPPED:
-      case DARWIN_MESSAGE:
-       break;
-      case DARWIN_RUNNING:
-       kret = thread_suspend (thread->gdb_port);
-       MACH_CHECK_ERROR (kret);
-       thread->msg_state = DARWIN_STOPPED;
-       break;
-      }
+  for (darwin_thread_t *thread : priv->threads)
+    {
+      switch (thread->msg_state)
+       {
+       case DARWIN_STOPPED:
+       case DARWIN_MESSAGE:
+         break;
+       case DARWIN_RUNNING:
+         {
+           kern_return_t kret = thread_suspend (thread->gdb_port);
+           MACH_CHECK_ERROR (kret);
+           thread->msg_state = DARWIN_STOPPED;
+           break;
+         }
+       }
+    }
 }
 
-static void
-darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
+void
+darwin_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
   struct target_waitstatus status;
-  int pid;
 
-  kern_return_t kret;
-  int res;
   int nsignal;
-  struct inferior *inf;
 
   inferior_debug
     (2, _("darwin_resume: pid=%d, tid=0x%lx, step=%d, signal=%d\n"),
-     ptid_get_pid (ptid), ptid_get_tid (ptid), step, signal);
+     ptid.pid (), ptid.tid (), step, signal);
 
   if (signal == GDB_SIGNAL_0)
     nsignal = 0;
@@ -978,22 +921,20 @@ darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
     ptid = inferior_ptid;
 
   /* minus_one_ptid is RESUME_ALL.  */
-  if (ptid_equal (ptid, minus_one_ptid))
+  if (ptid == minus_one_ptid)
     {
-      struct resume_inferior_threads_param param;
-
-      param.nsignal = nsignal;
-      param.step = step;
-
       /* Resume threads.  */
-      iterate_over_inferiors (darwin_resume_inferior_threads_it, &param);
+      for (inferior *inf : all_inferiors ())
+       darwin_resume_inferior_threads (inf, step, nsignal);
+
       /* Resume tasks.  */
-      iterate_over_inferiors (darwin_resume_inferior_it, NULL);
+      for (inferior *inf : all_inferiors ())
+       darwin_resume_inferior (inf);
     }
   else
     {
-      struct inferior *inf = find_inferior_ptid (ptid);
-      long tid = ptid_get_tid (ptid);
+      inferior *inf = find_inferior_ptid (this, ptid);
+      long tid = ptid.tid ();
 
       /* Stop the inferior (should be useless).  */
       darwin_suspend_inferior (inf);
@@ -1018,18 +959,11 @@ darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
     }
 }
 
-static void
-darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
-                  enum gdb_signal signal)
-{
-  return darwin_resume (ptid, step, signal);
-}
-
-static ptid_t
-darwin_decode_message (mach_msg_header_t *hdr,
-                      darwin_thread_t **pthread,
-                      struct inferior **pinf,
-                      struct target_waitstatus *status)
+ptid_t
+darwin_nat_target::decode_message (mach_msg_header_t *hdr,
+                                  darwin_thread_t **pthread,
+                                  inferior **pinf,
+                                  target_waitstatus *status)
 {
   darwin_thread_t *thread;
   struct inferior *inf;
@@ -1040,7 +974,7 @@ darwin_decode_message (mach_msg_header_t *hdr,
       int res;
 
       /* Decode message.  */
-      res = darwin_decode_exception_message (hdr, &inf, &thread);
+      res = decode_exception_message (hdr, &inf, &thread);
 
       if (res < 0)
        {
@@ -1058,7 +992,10 @@ darwin_decode_message (mach_msg_header_t *hdr,
        }
       *pinf = inf;
       *pthread = thread;
-      inf->priv->pending_messages++;
+
+      darwin_inferior *priv = get_darwin_inferior (inf);
+
+      priv->pending_messages++;
 
       status->kind = TARGET_WAITKIND_STOPPED;
       thread->msg_state = DARWIN_MESSAGE;
@@ -1114,7 +1051,7 @@ darwin_decode_message (mach_msg_header_t *hdr,
          break;
        }
 
-      return ptid_build (inf->pid, 0, thread->gdb_port);
+      return ptid_t (inf->pid, 0, thread->gdb_port);
     }
   else if (hdr->msgh_id == 0x48)
     {
@@ -1142,16 +1079,18 @@ darwin_decode_message (mach_msg_header_t *hdr,
 
       if (inf != NULL)
        {
-         if (!inf->priv->no_ptrace)
+         darwin_inferior *priv = get_darwin_inferior (inf);
+
+         if (!priv->no_ptrace)
            {
-             pid_t res;
+             pid_t res_pid;
              int wstatus;
 
-             res = wait4 (inf->pid, &wstatus, 0, NULL);
-             if (res < 0 || res != inf->pid)
+             res_pid = wait4 (inf->pid, &wstatus, 0, NULL);
+             if (res_pid < 0 || res_pid != inf->pid)
                {
                  printf_unfiltered (_("wait4: res=%d: %s\n"),
-                                    res, safe_strerror (errno));
+                                    res_pid, safe_strerror (errno));
                  status->kind = TARGET_WAITKIND_IGNORE;
                  return minus_one_ptid;
                }
@@ -1167,12 +1106,12 @@ darwin_decode_message (mach_msg_header_t *hdr,
                }
 
              inferior_debug (4, _("darwin_wait: pid=%d exit, status=0x%x\n"),
-                             res, wstatus);
+                             res_pid, wstatus);
 
              /* Looks necessary on Leopard and harmless...  */
              wait4 (inf->pid, &wstatus, 0, NULL);
 
-             inferior_ptid = ptid_build (inf->pid, 0, 0);
+             inferior_ptid = ptid_t (inf->pid, 0, 0);
              return inferior_ptid;
            }
          else
@@ -1180,7 +1119,7 @@ darwin_decode_message (mach_msg_header_t *hdr,
              inferior_debug (4, _("darwin_wait: pid=%d\n"), inf->pid);
              status->kind = TARGET_WAITKIND_EXITED;
              status->value.integer = 0; /* Don't know.  */
-             return ptid_build (inf->pid, 0, 0);
+             return ptid_t (inf->pid, 0, 0);
            }
        }
     }
@@ -1191,8 +1130,8 @@ darwin_decode_message (mach_msg_header_t *hdr,
   return minus_one_ptid;
 }
 
-static int
-cancel_breakpoint (ptid_t ptid)
+int
+darwin_nat_target::cancel_breakpoint (ptid_t ptid)
 {
   /* Arrange for a breakpoint to be hit again later.  We will handle
      the current event, eventually we will resume this thread, and this
@@ -1202,15 +1141,15 @@ cancel_breakpoint (ptid_t ptid)
      delete or disable the breakpoint, but the thread will have already
      tripped on it.  */
 
-  struct regcache *regcache = get_thread_regcache (ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct regcache *regcache = get_thread_regcache (this, ptid);
+  struct gdbarch *gdbarch = regcache->arch ();
   CORE_ADDR pc;
 
   pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch);
-  if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+  if (breakpoint_inserted_here_p (regcache->aspace (), pc))
     {
       inferior_debug (4, "cancel_breakpoint for thread 0x%lx\n",
-                     (unsigned long) ptid_get_tid (ptid));
+                     (unsigned long) ptid.tid ());
 
       /* Back up the PC if necessary.  */
       if (gdbarch_decr_pc_after_break (gdbarch))
@@ -1221,8 +1160,8 @@ cancel_breakpoint (ptid_t ptid)
   return 0;
 }
 
-static ptid_t
-darwin_wait (ptid_t ptid, struct target_waitstatus *status)
+ptid_t
+darwin_nat_target::wait_1 (ptid_t ptid, struct target_waitstatus *status)
 {
   kern_return_t kret;
   union
@@ -1233,23 +1172,24 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
   mach_msg_header_t *hdr = &msgin.hdr;
   ptid_t res;
   darwin_thread_t *thread;
-  struct inferior *inf;
 
   inferior_debug
     (2, _("darwin_wait: waiting for a message pid=%d thread=%lx\n"),
-     ptid_get_pid (ptid), ptid_get_tid (ptid));
+     ptid.pid (), ptid.tid ());
 
   /* Handle fake stop events at first.  */
   if (darwin_inf_fake_stop != NULL)
     {
-      inf = darwin_inf_fake_stop;
+      inferior *inf = darwin_inf_fake_stop;
       darwin_inf_fake_stop = NULL;
 
+      darwin_inferior *priv = get_darwin_inferior (inf);
+
       status->kind = TARGET_WAITKIND_STOPPED;
       status->value.sig = GDB_SIGNAL_TRAP;
-      thread = VEC_index (darwin_thread_t, inf->priv->threads, 0);
+      thread = priv->threads[0];
       thread->msg_state = DARWIN_STOPPED;
-      return ptid_build (inf->pid, 0, thread->gdb_port);
+      return ptid_t (inf->pid, 0, thread->gdb_port);
     }
 
   do
@@ -1279,8 +1219,9 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
       if (darwin_debug_flag > 10)
        darwin_dump_message (hdr, darwin_debug_flag > 11);
 
-      res = darwin_decode_message (hdr, &thread, &inf, status);
-      if (ptid_equal (res, minus_one_ptid))
+      inferior *inf;
+      res = decode_message (hdr, &thread, &inf, status);
+      if (res == minus_one_ptid)
        continue;
 
       /* Early return in case an inferior has exited.  */
@@ -1290,7 +1231,11 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
   while (status->kind == TARGET_WAITKIND_IGNORE);
 
   /* Stop all tasks.  */
-  iterate_over_inferiors (darwin_suspend_inferior_it, NULL);
+  for (inferior *inf : all_inferiors (this))
+    {
+      darwin_suspend_inferior (inf);
+      check_new_threads (inf);
+    }
 
   /* Read pending messages.  */
   while (1)
@@ -1315,13 +1260,14 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
       if (darwin_debug_flag > 10)
        darwin_dump_message (hdr, darwin_debug_flag > 11);
 
-      ptid2 = darwin_decode_message (hdr, &thread, &inf, &status2);
+      inferior *inf;
+      ptid2 = decode_message (hdr, &thread, &inf, &status2);
 
       if (inf != NULL && thread != NULL
          && thread->event.ex_type == EXC_BREAKPOINT)
        {
          if (thread->single_step
-             || cancel_breakpoint (ptid_build (inf->pid, 0, thread->gdb_port)))
+             || cancel_breakpoint (ptid_t (inf->pid, 0, thread->gdb_port)))
            {
              gdb_assert (thread->msg_state == DARWIN_MESSAGE);
              darwin_send_reply (inf, thread);
@@ -1338,21 +1284,22 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
   return res;
 }
 
-static ptid_t
-darwin_wait_to (struct target_ops *ops,
-                ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+darwin_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
+                        int options)
 {
-  return darwin_wait (ptid, status);
+  return wait_1 (ptid, status);
 }
 
-static void
-darwin_interrupt (struct target_ops *self, ptid_t t)
+void
+darwin_nat_target::interrupt ()
 {
   struct inferior *inf = current_inferior ();
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
   /* FIXME: handle in no_ptrace mode.  */
-  gdb_assert (!inf->priv->no_ptrace);
-  kill (inf->pid, SIGINT);
+  gdb_assert (!priv->no_ptrace);
+  ::kill (inf->pid, SIGINT);
 }
 
 /* Deallocate threads port and vector.  */
@@ -1360,48 +1307,42 @@ darwin_interrupt (struct target_ops *self, ptid_t t)
 static void
 darwin_deallocate_threads (struct inferior *inf)
 {
-  if (inf->priv->threads)
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  for (darwin_thread_t *t : priv->threads)
     {
-      kern_return_t kret;
-      int k;
-      darwin_thread_t *t;
-      for (k = 0;
-          VEC_iterate (darwin_thread_t, inf->priv->threads, k, t);
-          k++)
-       {
-         kret = mach_port_deallocate (gdb_task, t->gdb_port);
-         MACH_CHECK_ERROR (kret);
-       }
-      VEC_free (darwin_thread_t, inf->priv->threads);
-      inf->priv->threads = NULL;
+      kern_return_t kret = mach_port_deallocate (gdb_task, t->gdb_port);
+      MACH_CHECK_ERROR (kret);
     }
+
+  priv->threads.clear ();
 }
 
-static void
-darwin_mourn_inferior (struct target_ops *ops)
+void
+darwin_nat_target::mourn_inferior ()
 {
   struct inferior *inf = current_inferior ();
+  darwin_inferior *priv = get_darwin_inferior (inf);
   kern_return_t kret;
   mach_port_t prev;
-  int i;
 
   /* Deallocate threads.  */
   darwin_deallocate_threads (inf);
 
   /* Remove notify_port from darwin_port_set.  */
   kret = mach_port_move_member (gdb_task,
-                               inf->priv->notify_port, MACH_PORT_NULL);
+                               priv->notify_port, MACH_PORT_NULL);
   MACH_CHECK_ERROR (kret);
 
   /* Remove task port dead_name notification.  */
-  kret = mach_port_request_notification (gdb_task, inf->priv->task,
+  kret = mach_port_request_notification (gdb_task, priv->task,
                                         MACH_NOTIFY_DEAD_NAME, 0,
                                         MACH_PORT_NULL,
                                         MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                         &prev);
   /* This can fail if the task is dead.  */
   inferior_debug (4, "task=0x%x, prev=0x%x, notify_port=0x%x\n",
-                 inf->priv->task, prev, inf->priv->notify_port);
+                 priv->task, prev, priv->notify_port);
 
   if (kret == KERN_SUCCESS)
     {
@@ -1410,45 +1351,40 @@ darwin_mourn_inferior (struct target_ops *ops)
     }
 
   /* Destroy notify_port.  */
-  kret = mach_port_destroy (gdb_task, inf->priv->notify_port);
+  kret = mach_port_destroy (gdb_task, priv->notify_port);
   MACH_CHECK_ERROR (kret);
 
   /* Deallocate saved exception ports.  */
-  darwin_deallocate_exception_ports (inf->priv);
+  darwin_deallocate_exception_ports (priv);
 
   /* Deallocate task port.  */
-  kret = mach_port_deallocate (gdb_task, inf->priv->task);
+  kret = mach_port_deallocate (gdb_task, priv->task);
   MACH_CHECK_ERROR (kret);
 
-  xfree (inf->priv);
   inf->priv = NULL;
 
-  inf_child_mourn_inferior (ops);
+  inf_child_target::mourn_inferior ();
 }
 
 static void
 darwin_reply_to_all_pending_messages (struct inferior *inf)
 {
-  int k;
-  darwin_thread_t *t;
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->priv->threads, k, t);
-       k++)
+  for (darwin_thread_t *t : priv->threads)
     {
       if (t->msg_state == DARWIN_MESSAGE)
        darwin_resume_thread (inf, t, 0, 0);
     }
 }
 
-static void
-darwin_stop_inferior (struct inferior *inf)
+void
+darwin_nat_target::stop_inferior (inferior *inf)
 {
   struct target_waitstatus wstatus;
   ptid_t ptid;
-  kern_return_t kret;
-  int status;
   int res;
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
   gdb_assert (inf != NULL);
 
@@ -1456,17 +1392,17 @@ darwin_stop_inferior (struct inferior *inf)
 
   darwin_reply_to_all_pending_messages (inf);
 
-  if (inf->priv->no_ptrace)
+  if (priv->no_ptrace)
     return;
 
-  res = kill (inf->pid, SIGSTOP);
+  res = ::kill (inf->pid, SIGSTOP);
   if (res != 0)
     warning (_("cannot kill: %s"), safe_strerror (errno));
 
   /* Wait until the process is really stopped.  */
   while (1)
     {
-      ptid = darwin_wait (inferior_ptid, &wstatus);
+      ptid = wait_1 (inferior_ptid, &wstatus);
       if (wstatus.kind == TARGET_WAITKIND_STOPPED
          && wstatus.value.sig == GDB_SIGNAL_STOP)
        break;
@@ -1525,11 +1461,11 @@ darwin_deallocate_exception_ports (darwin_inferior *inf)
 static void
 darwin_setup_exceptions (struct inferior *inf)
 {
+  darwin_inferior *priv = get_darwin_inferior (inf);
   kern_return_t kret;
-  int traps_expected;
   exception_mask_t mask;
 
-  kret = darwin_save_exception_ports (inf->priv);
+  kret = darwin_save_exception_ports (priv);
   if (kret != KERN_SUCCESS)
     error (_("Unable to save exception ports, task_get_exception_ports"
             "returned: %d"),
@@ -1540,7 +1476,7 @@ darwin_setup_exceptions (struct inferior *inf)
     mask = EXC_MASK_ALL;
   else
     mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
-  kret = task_set_exception_ports (inf->priv->task, mask, darwin_ex_port,
+  kret = task_set_exception_ports (priv->task, mask, darwin_ex_port,
                                   EXCEPTION_DEFAULT, THREAD_STATE_NONE);
   if (kret != KERN_SUCCESS)
     error (_("Unable to set exception ports, task_set_exception_ports"
@@ -1548,33 +1484,50 @@ darwin_setup_exceptions (struct inferior *inf)
           kret);
 }
 
-static void
-darwin_kill_inferior (struct target_ops *ops)
+void
+darwin_nat_target::kill ()
 {
   struct inferior *inf = current_inferior ();
+  darwin_inferior *priv = get_darwin_inferior (inf);
   struct target_waitstatus wstatus;
   ptid_t ptid;
   kern_return_t kret;
-  int status;
   int res;
 
-  if (ptid_equal (inferior_ptid, null_ptid))
+  if (inferior_ptid == null_ptid)
     return;
 
   gdb_assert (inf != NULL);
 
-  kret = darwin_restore_exception_ports (inf->priv);
+  kret = darwin_restore_exception_ports (priv);
   MACH_CHECK_ERROR (kret);
 
   darwin_reply_to_all_pending_messages (inf);
 
-  res = kill (inf->pid, 9);
+  res = ::kill (inf->pid, 9);
 
   if (res == 0)
     {
+      /* On MacOS version Sierra, the darwin_restore_exception_ports call
+         does not work as expected.
+         When the kill function is called, the SIGKILL signal is received
+         by gdb whereas it should have been received by the kernel since
+         the exception ports have been restored.
+         This behavior is not the expected one thus gdb does not reply to
+         the received SIGKILL message. This situation leads to a "busy"
+         resource from the kernel point of view and the inferior is never
+         released, causing it to remain as a zombie process, even after
+        GDB exits.
+         To work around this, we mark all the threads of the inferior as
+         signaled thus darwin_decode_message function knows that the kill
+         signal was sent by gdb and will take the appropriate action
+         (cancel signal and reply to the signal message).  */
+      for (darwin_thread_t *thread : priv->threads)
+        thread->signaled = 1;
+
       darwin_resume_inferior (inf);
 
-      ptid = darwin_wait (inferior_ptid, &wstatus);
+      ptid = wait_1 (inferior_ptid, &wstatus);
     }
   else if (errno != ESRCH)
     warning (_("Failed to kill inferior: kill (%d, 9) returned [%s]"),
@@ -1586,12 +1539,13 @@ darwin_kill_inferior (struct target_ops *ops)
 static void
 darwin_setup_request_notification (struct inferior *inf)
 {
+  darwin_inferior *priv = get_darwin_inferior (inf);
   kern_return_t kret;
   mach_port_t prev_not;
 
-  kret = mach_port_request_notification (gdb_task, inf->priv->task,
+  kret = mach_port_request_notification (gdb_task, priv->task,
                                         MACH_NOTIFY_DEAD_NAME, 0,
-                                        inf->priv->notify_port,
+                                        priv->notify_port,
                                         MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                         &prev_not);
   if (kret != KERN_SUCCESS)
@@ -1615,106 +1569,130 @@ static void
 darwin_attach_pid (struct inferior *inf)
 {
   kern_return_t kret;
-  mach_port_t prev_port;
-  int traps_expected;
-  mach_port_t prev_not;
-  exception_mask_t mask;
 
-  inf->priv = XCNEW (darwin_inferior);
+  darwin_inferior *priv = new darwin_inferior;
+  inf->priv.reset (priv);
 
-  kret = task_for_pid (gdb_task, inf->pid, &inf->priv->task);
-  if (kret != KERN_SUCCESS)
+  try
     {
-      int status;
-
-      if (!inf->attach_flag)
+      kret = task_for_pid (gdb_task, inf->pid, &priv->task);
+      if (kret != KERN_SUCCESS)
        {
-         kill (inf->pid, 9);
-         waitpid (inf->pid, &status, 0);
-       }
+         int status;
+
+         if (!inf->attach_flag)
+           {
+             kill (inf->pid, 9);
+             waitpid (inf->pid, &status, 0);
+           }
 
-      error (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n"
+         error
+           (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n"
               " (please check gdb is codesigned - see taskgated(8))"),
-             inf->pid, mach_error_string (kret), (unsigned long) kret);
-    }
+            inf->pid, mach_error_string (kret), (unsigned long) kret);
+       }
 
-  inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"),
-                 inf->priv->task, inf->pid);
+      inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"),
+                     priv->task, inf->pid);
 
-  if (darwin_ex_port == MACH_PORT_NULL)
-    {
-      /* Create a port to get exceptions.  */
-      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
-                                &darwin_ex_port);
-      if (kret != KERN_SUCCESS)
-       error (_("Unable to create exception port, mach_port_allocate "
-                "returned: %d"),
-              kret);
+      if (darwin_ex_port == MACH_PORT_NULL)
+       {
+         /* Create a port to get exceptions.  */
+         kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
+                                    &darwin_ex_port);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to create exception port, mach_port_allocate "
+                    "returned: %d"),
+                  kret);
 
-      kret = mach_port_insert_right (gdb_task, darwin_ex_port, darwin_ex_port,
-                                    MACH_MSG_TYPE_MAKE_SEND);
-      if (kret != KERN_SUCCESS)
-       error (_("Unable to create exception port, mach_port_insert_right "
-                "returned: %d"),
-              kret);
+         kret = mach_port_insert_right (gdb_task, darwin_ex_port,
+                                        darwin_ex_port,
+                                        MACH_MSG_TYPE_MAKE_SEND);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to create exception port, mach_port_insert_right "
+                    "returned: %d"),
+                  kret);
+
+         /* Create a port set and put ex_port in it.  */
+         kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_PORT_SET,
+                                    &darwin_port_set);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to create port set, mach_port_allocate "
+                    "returned: %d"),
+                  kret);
+
+         kret = mach_port_move_member (gdb_task, darwin_ex_port,
+                                       darwin_port_set);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to move exception port into new port set, "
+                    "mach_port_move_member\n"
+                    "returned: %d"),
+                  kret);
+       }
 
-      /* Create a port set and put ex_port in it.  */
-      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_PORT_SET,
-                                &darwin_port_set);
+      /* Create a port to be notified when the child task terminates.  */
+      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
+                                &priv->notify_port);
       if (kret != KERN_SUCCESS)
-       error (_("Unable to create port set, mach_port_allocate "
+       error (_("Unable to create notification port, mach_port_allocate "
                 "returned: %d"),
               kret);
 
-      kret = mach_port_move_member (gdb_task, darwin_ex_port, darwin_port_set);
+      kret = mach_port_move_member (gdb_task,
+                                   priv->notify_port, darwin_port_set);
       if (kret != KERN_SUCCESS)
-       error (_("Unable to move exception port into new port set, "
+       error (_("Unable to move notification port into new port set, "
                 "mach_port_move_member\n"
                 "returned: %d"),
               kret);
-    }
 
-  /* Create a port to be notified when the child task terminates.  */
-  kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
-                            &inf->priv->notify_port);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to create notification port, mach_port_allocate "
-            "returned: %d"),
-          kret);
+      darwin_setup_request_notification (inf);
 
-  kret = mach_port_move_member (gdb_task,
-                               inf->priv->notify_port, darwin_port_set);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to move notification port into new port set, "
-            "mach_port_move_member\n"
-            "returned: %d"),
-          kret);
-
-  darwin_setup_request_notification (inf);
+      darwin_setup_exceptions (inf);
+    }
+  catch (const gdb_exception &ex)
+    {
+      exit_inferior (inf);
+      inferior_ptid = null_ptid;
 
-  darwin_setup_exceptions (inf);
+      throw;
+    }
 
+  target_ops *darwin_ops = get_native_target ();
   if (!target_is_pushed (darwin_ops))
     push_target (darwin_ops);
 }
 
-static void
-darwin_init_thread_list (struct inferior *inf)
+/* Get the thread_info object corresponding to this darwin_thread_info.  */
+
+static struct thread_info *
+thread_info_from_private_thread_info (darwin_thread_info *pti)
 {
-  darwin_thread_t *thread;
-  ptid_t new_ptid;
+  for (struct thread_info *it : all_threads ())
+    {
+      darwin_thread_info *iter_pti = get_darwin_thread_info (it);
 
-  darwin_check_new_threads (inf);
+      if (iter_pti->gdb_port == pti->gdb_port)
+       return it;
+    }
+
+  gdb_assert_not_reached ("did not find gdb thread for darwin thread");
+}
+
+void
+darwin_nat_target::init_thread_list (inferior *inf)
+{
+  check_new_threads (inf);
+
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  gdb_assert (!priv->threads.empty ());
 
-  gdb_assert (inf->priv->threads
-             && VEC_length (darwin_thread_t, inf->priv->threads) > 0);
-  thread = VEC_index (darwin_thread_t, inf->priv->threads, 0);
+  darwin_thread_info *first_pti = priv->threads.front ();
+  struct thread_info *first_thread
+    = thread_info_from_private_thread_info (first_pti);
 
-  /* Note: fork_inferior automatically add a thead but it uses a wrong ptid.
-     Fix up.  */
-  new_ptid = ptid_build (inf->pid, 0, thread->gdb_port);
-  thread_change_ptid (inferior_ptid, new_ptid);
-  inferior_ptid = new_ptid;
+  inferior_ptid = first_thread->ptid;
 }
 
 /* The child must synchronize with gdb: gdb must set the exception port
@@ -1729,22 +1707,28 @@ darwin_ptrace_me (void)
   char c;
 
   /* Close write end point.  */
-  close (ptrace_fds[1]);
+  if (close (ptrace_fds[1]) < 0)
+    trace_start_error_with_name ("close");
 
   /* Wait until gdb is ready.  */
   res = read (ptrace_fds[0], &c, 1);
   if (res != 0)
-    error (_("unable to read from pipe, read returned: %d"), res);
-  close (ptrace_fds[0]);
+    trace_start_error (_("unable to read from pipe, read returned: %d"), res);
+
+  if (close (ptrace_fds[0]) < 0)
+    trace_start_error_with_name ("close");
 
   /* Get rid of privileges.  */
-  setegid (getgid ());
+  if (setegid (getgid ()) < 0)
+    trace_start_error_with_name ("setegid");
 
   /* Set TRACEME.  */
-  PTRACE (PT_TRACE_ME, 0, 0, 0);
+  if (PTRACE (PT_TRACE_ME, 0, 0, 0) < 0)
+    trace_start_error_with_name ("PTRACE");
 
   /* Redirect signals to exception port.  */
-  PTRACE (PT_SIGEXC, 0, 0, 0);
+  if (PTRACE (PT_SIGEXC, 0, 0, 0) < 0)
+    trace_start_error_with_name ("PTRACE");
 }
 
 /* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2).  */
@@ -1762,27 +1746,23 @@ darwin_pre_ptrace (void)
   mark_fd_no_cloexec (ptrace_fds[1]);
 }
 
-static void
-darwin_ptrace_him (int pid)
+void
+darwin_nat_target::ptrace_him (int pid)
 {
-  task_t itask;
-  kern_return_t kret;
-  mach_port_t prev_port;
-  int traps_expected;
   struct inferior *inf = current_inferior ();
 
   darwin_attach_pid (inf);
 
   /* Let's the child run.  */
-  close (ptrace_fds[0]);
-  close (ptrace_fds[1]);
+  ::close (ptrace_fds[0]);
+  ::close (ptrace_fds[1]);
 
   unmark_fd_no_cloexec (ptrace_fds[0]);
   unmark_fd_no_cloexec (ptrace_fds[1]);
 
-  darwin_init_thread_list (inf);
+  init_thread_list (inf);
 
-  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+  gdb_startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED);
 }
 
 static void
@@ -1819,17 +1799,175 @@ darwin_execvp (const char *file, char * const argv[], char * const env[])
   posix_spawnp (NULL, argv[0], NULL, &attr, argv, env);
 }
 
+/* Read kernel version, and return TRUE if this host may have System
+   Integrity Protection (Sierra or later).  */
+
+static bool
+may_have_sip ()
+{
+  char str[16];
+  size_t sz = sizeof (str);
+  int ret;
+
+  ret = sysctlbyname ("kern.osrelease", str, &sz, NULL, 0);
+  if (ret == 0 && sz < sizeof (str))
+    {
+      unsigned long ver = strtoul (str, NULL, 10);
+      if (ver >= 16)
+        return true;
+    }
+  return false;
+}
+
+/* A helper for maybe_cache_shell.  This copies the shell to the
+   cache.  It will throw an exception on any failure.  */
+
 static void
-darwin_create_inferior (struct target_ops *ops, char *exec_file,
-                       char *allargs, char **env, int from_tty)
+copy_shell_to_cache (const char *shell, const std::string &new_name)
+{
+  scoped_fd from_fd (gdb_open_cloexec (shell, O_RDONLY, 0));
+  if (from_fd.get () < 0)
+    error (_("Could not open shell (%s) for reading: %s"),
+          shell, safe_strerror (errno));
+
+  std::string new_dir = ldirname (new_name.c_str ());
+  if (!mkdir_recursive (new_dir.c_str ()))
+    error (_("Could not make cache directory \"%s\": %s"),
+          new_dir.c_str (), safe_strerror (errno));
+
+  gdb::char_vector temp_name = make_temp_filename (new_name);
+  scoped_fd to_fd (gdb_mkostemp_cloexec (&temp_name[0]));
+  gdb::unlinker unlink_file_on_error (temp_name.data ());
+
+  if (to_fd.get () < 0)
+    error (_("Could not open temporary file \"%s\" for writing: %s"),
+          temp_name.data (), safe_strerror (errno));
+
+  if (fcopyfile (from_fd.get (), to_fd.get (), nullptr,
+                COPYFILE_STAT | COPYFILE_DATA) != 0)
+    error (_("Could not copy shell to cache as \"%s\": %s"),
+          temp_name.data (), safe_strerror (errno));
+
+  /* Be sure that the caching is atomic so that we don't get bad
+     results from multiple copies of gdb running at the same time.  */
+  if (rename (temp_name.data (), new_name.c_str ()) != 0)
+    error (_("Could not rename shell cache file to \"%s\": %s"),
+          new_name.c_str (), safe_strerror (errno));
+
+  unlink_file_on_error.keep ();
+}
+
+/* If $SHELL is restricted, try to cache a copy.  Starting with El
+   Capitan, macOS introduced System Integrity Protection.  Among other
+   things, this prevents certain executables from being ptrace'd.  In
+   particular, executables in /bin, like most shells, are affected.
+   To work around this, while preserving command-line glob expansion
+   and redirections, gdb will cache a copy of the shell.  Return true
+   if all is well -- either the shell is not subject to SIP or it has
+   been successfully cached.  Returns false if something failed.  */
+
+static bool
+maybe_cache_shell ()
+{
+  /* SF_RESTRICTED is defined in sys/stat.h and lets us determine if a
+     given file is subject to SIP.  */
+#ifdef SF_RESTRICTED
+
+  /* If a check fails we want to revert -- maybe the user deleted the
+     cache while gdb was running, or something like that.  */
+  copied_shell = nullptr;
+
+  const char *shell = get_shell ();
+  if (!IS_ABSOLUTE_PATH (shell))
+    {
+      warning (_("This version of macOS has System Integrity Protection.\n\
+Normally gdb would try to work around this by caching a copy of your shell,\n\
+but because your shell (%s) is not an absolute path, this is being skipped."),
+              shell);
+      return false;
+    }
+
+  struct stat sb;
+  if (stat (shell, &sb) < 0)
+    {
+      warning (_("This version of macOS has System Integrity Protection.\n\
+Normally gdb would try to work around this by caching a copy of your shell,\n\
+but because gdb could not stat your shell (%s), this is being skipped.\n\
+The error was: %s"),
+              shell, safe_strerror (errno));
+      return false;
+    }
+
+  if ((sb.st_flags & SF_RESTRICTED) == 0)
+    return true;
+
+  /* Put the copy somewhere like ~/Library/Caches/gdb/bin/sh.  */
+  std::string new_name = get_standard_cache_dir ();
+  /* There's no need to insert a directory separator here, because
+     SHELL is known to be absolute.  */
+  new_name.append (shell);
+
+  /* Maybe it was cached by some earlier gdb.  */
+  if (stat (new_name.c_str (), &sb) != 0 || !S_ISREG (sb.st_mode))
+    {
+      try
+       {
+         copy_shell_to_cache (shell, new_name);
+       }
+      catch (const gdb_exception_error &ex)
+       {
+         warning (_("This version of macOS has System Integrity Protection.\n\
+Because `startup-with-shell' is enabled, gdb tried to work around SIP by\n\
+caching a copy of your shell.  However, this failed:\n\
+%s\n\
+If you correct the problem, gdb will automatically try again the next time\n\
+you \"run\".  To prevent these attempts, you can use:\n\
+    set startup-with-shell off"),
+                  ex.what ());
+         return false;
+       }
+
+      printf_filtered (_("Note: this version of macOS has System Integrity Protection.\n\
+Because `startup-with-shell' is enabled, gdb has worked around this by\n\
+caching a copy of your shell.  The shell used by \"run\" is now:\n\
+    %s\n"),
+                      new_name.c_str ());
+    }
+
+  /* We need to make sure that the new name has the correct lifetime.  */
+  static std::string saved_shell = std::move (new_name);
+  copied_shell = saved_shell.c_str ();
+
+#endif /* SF_RESTRICTED */
+
+  return true;
+}
+
+void
+darwin_nat_target::create_inferior (const char *exec_file,
+                                   const std::string &allargs,
+                                   char **env, int from_tty)
 {
-  /* Do the hard work.  */
-  fork_inferior (exec_file, allargs, env, darwin_ptrace_me, darwin_ptrace_him,
-                darwin_pre_ptrace, NULL, darwin_execvp);
+  gdb::optional<scoped_restore_tmpl<bool>> restore_startup_with_shell;
+  darwin_nat_target *the_target = this;
 
-  /* Return now in case of error.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return;
+  if (startup_with_shell && may_have_sip ())
+    {
+      if (!maybe_cache_shell ())
+       {
+         warning (_("startup-with-shell is now temporarily disabled"));
+         restore_startup_with_shell.emplace (&startup_with_shell, 0);
+       }
+    }
+
+  /* Do the hard work.  */
+  fork_inferior (exec_file, allargs, env, darwin_ptrace_me,
+                [the_target] (int pid)
+                  {
+                    the_target->ptrace_him (pid);
+                  },
+                darwin_pre_ptrace, copied_shell,
+                darwin_execvp);
 }
 \f
 
@@ -1842,6 +1980,7 @@ darwin_create_inferior (struct target_ops *ops, char *exec_file,
 static void
 darwin_setup_fake_stop_event (struct inferior *inf)
 {
+  darwin_inferior *priv = get_darwin_inferior (inf);
   darwin_thread_t *thread;
   kern_return_t kret;
 
@@ -1854,22 +1993,18 @@ darwin_setup_fake_stop_event (struct inferior *inf)
      as well.  Otherwise, we'll try resuming it when resuming the
      inferior, and get a warning because the thread's suspend count
      is already zero, making the resume request useless.  */
-  thread = VEC_index (darwin_thread_t, inf->priv->threads, 0);
+  thread = priv->threads[0];
   kret = thread_suspend (thread->gdb_port);
   MACH_CHECK_ERROR (kret);
 }
 
 /* Attach to process PID, then initialize for debugging it
    and wait for the trace-trap that results from attaching.  */
-static void
-darwin_attach (struct target_ops *ops, const char *args, int from_tty)
+void
+darwin_nat_target::attach (const char *args, int from_tty)
 {
   pid_t pid;
-  pid_t pid2;
-  int wstatus;
-  int res;
   struct inferior *inf;
-  kern_return_t kret;
 
   pid = parse_pid_to_attach (args);
 
@@ -1878,41 +2013,38 @@ darwin_attach (struct target_ops *ops, const char *args, int from_tty)
 
   if (from_tty)
     {
-      char *exec_file = get_exec_file (0);
+      const char *exec_file = get_exec_file (0);
 
       if (exec_file)
        printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
-                          target_pid_to_str (pid_to_ptid (pid)));
+                          target_pid_to_str (ptid_t (pid)).c_str ());
       else
        printf_unfiltered (_("Attaching to %s\n"),
-                          target_pid_to_str (pid_to_ptid (pid)));
-
-      gdb_flush (gdb_stdout);
+                          target_pid_to_str (ptid_t (pid)).c_str ());
     }
 
-  if (pid == 0 || kill (pid, 0) < 0)
+  if (pid == 0 || ::kill (pid, 0) < 0)
     error (_("Can't attach to process %d: %s (%d)"),
            pid, safe_strerror (errno), errno);
 
-  inferior_ptid = pid_to_ptid (pid);
+  inferior_ptid = ptid_t (pid);
   inf = current_inferior ();
   inferior_appeared (inf, pid);
   inf->attach_flag = 1;
 
-  /* Always add a main thread.  */
-  add_thread_silent (inferior_ptid);
-
   darwin_attach_pid (inf);
 
   darwin_suspend_inferior (inf);
 
-  darwin_init_thread_list (inf);
+  init_thread_list (inf);
 
-  darwin_check_osabi (inf->priv, ptid_get_tid (inferior_ptid));
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  darwin_check_osabi (priv, inferior_ptid.tid ());
 
   darwin_setup_fake_stop_event (inf);
 
-  inf->priv->no_ptrace = 1;
+  priv->no_ptrace = 1;
 }
 
 /* Take a program previously attached to and detaches it.
@@ -1922,11 +2054,11 @@ darwin_attach (struct target_ops *ops, const char *args, int from_tty)
    to work, it may be necessary for the process to have been
    previously attached.  It *might* work if the program was
    started via fork.  */
-static void
-darwin_detach (struct target_ops *ops, const char *args, int from_tty)
+
+void
+darwin_nat_target::detach (inferior *inf, int from_tty)
 {
-  pid_t pid = ptid_get_pid (inferior_ptid);
-  struct inferior *inf = current_inferior ();
+  darwin_inferior *priv = get_darwin_inferior (inf);
   kern_return_t kret;
   int res;
 
@@ -1934,13 +2066,13 @@ darwin_detach (struct target_ops *ops, const char *args, int from_tty)
   target_announce_detach (from_tty);
 
   /* If ptrace() is in use, stop the process.  */
-  if (!inf->priv->no_ptrace)
-    darwin_stop_inferior (inf);
+  if (!priv->no_ptrace)
+    stop_inferior (inf);
 
-  kret = darwin_restore_exception_ports (inf->priv);
+  kret = darwin_restore_exception_ports (priv);
   MACH_CHECK_ERROR (kret);
 
-  if (!inf->priv->no_ptrace)
+  if (!priv->no_ptrace)
     {
       res = PTRACE (PT_DETACH, inf->pid, 0, 0);
       if (res != 0)
@@ -1953,44 +2085,35 @@ darwin_detach (struct target_ops *ops, const char *args, int from_tty)
   /* When using ptrace, we have just performed a PT_DETACH, which
      resumes the inferior.  On the other hand, when we are not using
      ptrace, we need to resume its execution ourselves.  */
-  if (inf->priv->no_ptrace)
+  if (priv->no_ptrace)
     darwin_resume_inferior (inf);
 
-  darwin_mourn_inferior (ops);
-}
-
-static void
-darwin_files_info (struct target_ops *ops)
-{
+  mourn_inferior ();
 }
 
-static char *
-darwin_pid_to_str (struct target_ops *ops, ptid_t ptid)
+std::string
+darwin_nat_target::pid_to_str (ptid_t ptid)
 {
-  static char buf[80];
-  long tid = ptid_get_tid (ptid);
+  long tid = ptid.tid ();
 
   if (tid != 0)
-    {
-      snprintf (buf, sizeof (buf), _("Thread 0x%lx of process %u"),
-               tid, ptid_get_pid (ptid));
-      return buf;
-    }
+    return string_printf (_("Thread 0x%lx of process %u"),
+                         tid, ptid.pid ());
 
   return normal_pid_to_str (ptid);
 }
 
-static int
-darwin_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+darwin_nat_target::thread_alive (ptid_t ptid)
 {
-  return 1;
+  return true;
 }
 
 /* If RDADDR is not NULL, read inferior task's LEN bytes from ADDR and
    copy it to RDADDR in gdb's address space.
    If WRADDR is not NULL, write gdb's LEN bytes from WRADDR and copy it
    to ADDR in inferior task's address space.
-   Return 0 on failure; number of bytes read / writen otherwise.  */
+   Return 0 on failure; number of bytes read / written otherwise.  */
 
 static int
 darwin_read_write_inferior (task_t task, CORE_ADDR addr,
@@ -1999,11 +2122,6 @@ darwin_read_write_inferior (task_t task, CORE_ADDR addr,
 {
   kern_return_t kret;
   mach_vm_size_t res_length = 0;
-  pointer_t copied;
-  mach_msg_type_number_t copy_count;
-  mach_vm_size_t remaining_length;
-  mach_vm_address_t region_address;
-  mach_vm_size_t region_length;
 
   inferior_debug (8, _("darwin_read_write_inferior(task=0x%x, %s, len=%s)\n"),
                  task, core_addr_to_string (addr), pulongest (length));
@@ -2157,7 +2275,6 @@ darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr,
 {
   struct task_dyld_info task_dyld_info;
   mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
-  int sz = TASK_DYLD_INFO_COUNT * sizeof (natural_t);
   kern_return_t kret;
 
   if (addr != 0 || length > sizeof (mach_vm_address_t))
@@ -2178,13 +2295,14 @@ darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr,
 
 \f
 
-static enum target_xfer_status
-darwin_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
+darwin_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 inferior *inf = current_inferior ();
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
   inferior_debug
     (8, _("darwin_xfer_partial(%s, %s, rbuf=%s, wbuf=%s) pid=%u\n"),
@@ -2196,7 +2314,7 @@ darwin_xfer_partial (struct target_ops *ops,
     {
     case TARGET_OBJECT_MEMORY:
       {
-       int l = darwin_read_write_inferior (inf->priv->task, offset,
+       int l = darwin_read_write_inferior (priv->task, offset,
                                            readbuf, writebuf, len);
 
        if (l == 0)
@@ -2215,7 +2333,7 @@ darwin_xfer_partial (struct target_ops *ops,
           /* Support only read.  */
           return TARGET_XFER_E_IO;
         }
-      return darwin_read_dyld_info (inf->priv->task, offset, readbuf, len,
+      return darwin_read_dyld_info (priv->task, offset, readbuf, len,
                                    xfered_len);
 #endif
     default:
@@ -2225,12 +2343,13 @@ darwin_xfer_partial (struct target_ops *ops,
 }
 
 static void
-set_enable_mach_exceptions (char *args, int from_tty,
+set_enable_mach_exceptions (const char *args, int from_tty,
                            struct cmd_list_element *c)
 {
-  if (!ptid_equal (inferior_ptid, null_ptid))
+  if (inferior_ptid != null_ptid)
     {
       struct inferior *inf = current_inferior ();
+      darwin_inferior *priv = get_darwin_inferior (inf);
       exception_mask_t mask;
       kern_return_t kret;
 
@@ -2238,17 +2357,17 @@ set_enable_mach_exceptions (char *args, int from_tty,
        mask = EXC_MASK_ALL;
       else
        {
-         darwin_restore_exception_ports (inf->priv);
+         darwin_restore_exception_ports (priv);
          mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
        }
-      kret = task_set_exception_ports (inf->priv->task, mask, darwin_ex_port,
+      kret = task_set_exception_ports (priv->task, mask, darwin_ex_port,
                                       EXCEPTION_DEFAULT, THREAD_STATE_NONE);
       MACH_CHECK_ERROR (kret);
     }
 }
 
-static char *
-darwin_pid_to_exec_file (struct target_ops *self, int pid)
+char *
+darwin_nat_target::pid_to_exec_file (int pid)
 {
   static char path[PATH_MAX];
   int res;
@@ -2260,13 +2379,11 @@ darwin_pid_to_exec_file (struct target_ops *self, int pid)
     return NULL;
 }
 
-static ptid_t
-darwin_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
+ptid_t
+darwin_nat_target::get_ada_task_ptid (long lwp, long thread)
 {
-  int i;
-  darwin_thread_t *t;
-  int k;
   struct inferior *inf = current_inferior ();
+  darwin_inferior *priv = get_darwin_inferior (inf);
   kern_return_t kret;
   mach_port_name_array_t names;
   mach_msg_type_number_t names_count;
@@ -2275,16 +2392,16 @@ darwin_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
   long res = 0;
 
   /* First linear search.  */
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->priv->threads, k, t);
-       k++)
-    if (t->inf_port == lwp)
-      return ptid_build (ptid_get_pid (inferior_ptid), 0, t->gdb_port);
+  for (darwin_thread_t *t : priv->threads)
+    {
+      if (t->inf_port == lwp)
+       return ptid_t (inferior_ptid.pid (), 0, t->gdb_port);
+    }
 
   /* Maybe the port was never extract.  Do it now.  */
 
   /* First get inferior port names.  */
-  kret = mach_port_names (inf->priv->task, &names, &names_count, &types,
+  kret = mach_port_names (priv->task, &names, &names_count, &types,
                          &types_count);
   MACH_CHECK_ERROR (kret);
   if (kret != KERN_SUCCESS)
@@ -2293,51 +2410,49 @@ darwin_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
   /* For each name, copy the right in the gdb space and then compare with
      our view of the inferior threads.  We don't forget to deallocate the
      right.  */
-  for (i = 0; i < names_count; i++)
+  for (int i = 0; i < names_count; i++)
     {
       mach_port_t local_name;
       mach_msg_type_name_t local_type;
 
       /* We just need to know the corresponding name in gdb name space.
         So extract and deallocate the right.  */
-      kret = mach_port_extract_right (inf->priv->task, names[i],
+      kret = mach_port_extract_right (priv->task, names[i],
                                      MACH_MSG_TYPE_COPY_SEND,
                                      &local_name, &local_type);
       if (kret != KERN_SUCCESS)
        continue;
       mach_port_deallocate (gdb_task, local_name);
 
-      for (k = 0;
-          VEC_iterate (darwin_thread_t, inf->priv->threads, k, t);
-          k++)
-       if (t->gdb_port == local_name)
-         {
-           t->inf_port = names[i];
-           if (names[i] == lwp)
-             res = t->gdb_port;
-         }
+      for (darwin_thread_t *t : priv->threads)
+       {
+         if (t->gdb_port == local_name)
+           {
+             t->inf_port = names[i];
+             if (names[i] == lwp)
+               res = t->gdb_port;
+           }
+       }
     }
 
   vm_deallocate (gdb_task, (vm_address_t) names,
                  names_count * sizeof (mach_port_t));
 
   if (res)
-    return ptid_build (ptid_get_pid (inferior_ptid), 0, res);
+    return ptid_t (inferior_ptid.pid (), 0, res);
   else
     return null_ptid;
 }
 
-static int
-darwin_supports_multi_process (struct target_ops *self)
+bool
+darwin_nat_target::supports_multi_process ()
 {
-  return 1;
+  return true;
 }
 
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_darwin_inferior;
-
+void _initialize_darwin_nat ();
 void
-_initialize_darwin_inferior (void)
+_initialize_darwin_nat ()
 {
   kern_return_t kret;
 
@@ -2352,30 +2467,6 @@ _initialize_darwin_inferior (void)
       MACH_CHECK_ERROR (kret);
     }
 
-  darwin_ops = inf_child_target ();
-
-  darwin_ops->to_create_inferior = darwin_create_inferior;
-  darwin_ops->to_attach = darwin_attach;
-  darwin_ops->to_attach_no_wait = 0;
-  darwin_ops->to_detach = darwin_detach;
-  darwin_ops->to_files_info = darwin_files_info;
-  darwin_ops->to_wait = darwin_wait_to;
-  darwin_ops->to_mourn_inferior = darwin_mourn_inferior;
-  darwin_ops->to_kill = darwin_kill_inferior;
-  darwin_ops->to_interrupt = darwin_interrupt;
-  darwin_ops->to_resume = darwin_resume_to;
-  darwin_ops->to_thread_alive = darwin_thread_alive;
-  darwin_ops->to_pid_to_str = darwin_pid_to_str;
-  darwin_ops->to_pid_to_exec_file = darwin_pid_to_exec_file;
-  darwin_ops->to_load = NULL;
-  darwin_ops->to_xfer_partial = darwin_xfer_partial;
-  darwin_ops->to_supports_multi_process = darwin_supports_multi_process;
-  darwin_ops->to_get_ada_task_ptid = darwin_get_ada_task_ptid;
-
-  darwin_complete_target (darwin_ops);
-
-  add_target (darwin_ops);
-
   inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"),
                  (unsigned long) mach_task_self (), getpid ());
 
This page took 0.084426 seconds and 4 git commands to generate.