Remove exit_inferior_num_silent
[deliverable/binutils-gdb.git] / gdb / darwin-nat.c
index f0f938d260ae0cf44187d9d0d0aa562fb67ea836..6fb108846d0b921fb09ff585832843c9faf66946 100644 (file)
@@ -1,5 +1,5 @@
 /* Darwin support for GDB, the GNU debugger.
-   Copyright (C) 2008-2013 Free Software Foundation, Inc.
+   Copyright (C) 2008-2018 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"
@@ -33,7 +32,6 @@
 #include "event-top.h"
 #include "inf-loop.h"
 #include <sys/stat.h>
-#include "exceptions.h"
 #include "inf-child.h"
 #include "value.h"
 #include "arch-utils.h"
 
 #include <sys/ptrace.h>
 #include <sys/signal.h>
-#include <machine/setjmp.h>
+#include <setjmp.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <signal.h>
-#include <string.h>
 #include <ctype.h>
 #include <sys/sysctl.h>
 #include <sys/proc.h>
@@ -65,6 +62,7 @@
 
 #include "darwin-nat.h"
 #include "common/filestuff.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))
 
-extern boolean_t exc_server (mach_msg_header_t *in, mach_msg_header_t *out);
-
-static void darwin_stop (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);
 
-/* Target operations for Darwin.  */
-static struct target_ops *darwin_ops;
+static void darwin_setup_request_notification (struct inferior *inf);
+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);
 
 /* Task identifier of gdb.  */
 static task_t gdb_task;
@@ -127,7 +106,7 @@ mach_port_t darwin_host_self;
 /* Exception port.  */
 mach_port_t darwin_ex_port;
 
-/* Port set.  */
+/* Port set, to wait for answer on all ports.  */
 mach_port_t darwin_port_set;
 
 /* Page size.  */
@@ -149,10 +128,8 @@ static unsigned int darwin_debug_flag = 0;
 /* Create a __TEXT __info_plist section in the executable so that gdb could
    be signed.  This is required to get an authorization for task_for_pid.
 
-   Once gdb is built, you can either:
-   * make it setgid procmod
-   * or codesign it with any system-trusted signing authority.
-   See taskgated(8) for details.  */
+   Once gdb is built, you must codesign it with any system-trusted signing
+   authority.  See taskgated(8) for details.  */
 static const unsigned char info_plist[]
 __attribute__ ((section ("__TEXT,__info_plist"),used)) =
   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -174,6 +151,9 @@ __attribute__ ((section ("__TEXT,__info_plist"),used)) =
   "</dict>\n"
   "</plist>\n";
 
+static void inferior_debug (int level, const char *fmt, ...)
+  ATTRIBUTE_PRINTF (2, 3);
+
 static void
 inferior_debug (int level, const char *fmt, ...)
 {
@@ -245,17 +225,17 @@ unparse_exception_type (unsigned int i)
 
 static int
 darwin_ptrace (const char *name,
-              int request, int pid, PTRACE_TYPE_ARG3 arg3, int arg4)
+              int request, int pid, caddr_t arg3, int arg4)
 {
   int ret;
 
   errno = 0;
-  ret = ptrace (request, pid, (caddr_t) arg3, arg4);
+  ret = ptrace (request, pid, arg3, arg4);
   if (ret == -1 && errno == 0)
     ret = 0;
 
-  inferior_debug (4, _("ptrace (%s, %d, 0x%x, %d): %d (%s)\n"),
-                  name, pid, arg3, arg4, ret,
+  inferior_debug (4, _("ptrace (%s, %d, 0x%lx, %d): %d (%s)\n"),
+                  name, pid, (unsigned long) arg3, arg4, ret,
                   (ret != 0) ? safe_strerror (errno) : _("no error"));
   return ret;
 }
@@ -272,13 +252,12 @@ static void
 darwin_check_new_threads (struct 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->private;
-  VEC (darwin_thread_t) *thread_vec;
+  darwin_inferior *darwin_inf = get_darwin_inferior (inf);
+  std::vector<darwin_thread_t *> new_thread_vec;
 
   /* Get list of threads.  */
   kret = task_threads (darwin_inf->task, &thread_list, &new_nbr);
@@ -290,36 +269,44 @@ 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)
        {
+         /* Deallocate ports.  */
+         for (i = 0; i < new_nbr; i++)
+           {
+             kret = mach_port_deallocate (mach_task_self (), thread_list[i]);
+             MACH_CHECK_ERROR (kret);
+           }
+
+         /* Deallocate the buffer.  */
          kret = vm_deallocate (gdb_task, (vm_address_t) thread_list,
                                new_nbr * sizeof (int));
          MACH_CHECK_ERROR (kret);
+
          return;
        }
     }
 
-  thread_vec = VEC_alloc (darwin_thread_t, new_nbr);
+  /* Full handling: detect new threads, remove dead threads.  */
+
+  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"),
@@ -328,12 +315,14 @@ 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++;
 
-         kret = mach_port_deallocate (gdb_task, old_id);
+         /* Deallocate the port.  */
+         kret = mach_port_deallocate (gdb_task, new_id);
          MACH_CHECK_ERROR (kret);
+
          continue;
        }
       if (new_ix < new_nbr && new_id == MACH_PORT_DEAD)
@@ -347,30 +336,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 = XZALLOC (struct private_thread_info);
          pti->gdb_port = new_id;
          pti->msg_state = DARWIN_RUNNING;
 
-         /* Add a new thread unless this is the first one ever met.  */
-         if (!(old_nbr == 0 && new_ix == 0))
-           tp = add_thread_with_info (ptid_build (inf->pid, 0, new_id), pti);
-         else
-           {
-             tp = find_thread_ptid (ptid_build (inf->pid, 0, 0));
-             gdb_assert (tp);
-             tp->private = pti;
-           }
-         VEC_safe_push (darwin_thread_t, thread_vec, pti);
+         /* Add the new thread.  */
+         add_thread_with_info (ptid_build (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 (ptid_build (inf->pid, 0, old_id));
+         delete_thread (thr);
          kret = mach_port_deallocate (gdb_task, old_id);
          MACH_CHECK_ERROR (kret);
          old_ix++;
@@ -379,10 +361,9 @@ 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,
                        new_nbr * sizeof (int));
   MACH_CHECK_ERROR (kret);
@@ -391,13 +372,15 @@ darwin_check_new_threads (struct inferior *inf)
 static int
 find_inferior_task_it (struct inferior *inf, void *port_ptr)
 {
-  return inf->private->task == *(task_t*)port_ptr;
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  return priv->task == *(task_t *)port_ptr;
 }
 
 static int
-find_inferior_notify_it (struct inferior *inf, void *port_ptr)
+find_inferior_pid_it (struct inferior *inf, void *pid_ptr)
 {
-  return inf->private->notify_port == *(task_t*)port_ptr;
+  return inf->pid == *(int *)pid_ptr;
 }
 
 /* Return an inferior by task port.  */
@@ -407,25 +390,25 @@ darwin_find_inferior_by_task (task_t port)
   return iterate_over_inferiors (&find_inferior_task_it, &port);
 }
 
-/* Return an inferior by notification port.  */
+/* Return an inferior by pid port.  */
 static struct inferior *
-darwin_find_inferior_by_notify (mach_port_t port)
+darwin_find_inferior_by_pid (int pid)
 {
-  return iterate_over_inferiors (&find_inferior_notify_it, &port);
+  return iterate_over_inferiors (&find_inferior_pid_it, &pid);
 }
 
 /* Return a thread by port.  */
 static darwin_thread_t *
 darwin_find_thread (struct inferior *inf, thread_t thread)
 {
-  darwin_thread_t *t;
-  int k;
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  for (darwin_thread_t *t : priv->threads)
+    {
+      if (t->gdb_port == thread)
+       return t;
+    }
 
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
-       k++)
-    if (t->gdb_port == thread)
-      return t;
   return NULL;
 }
 
@@ -434,14 +417,16 @@ darwin_find_thread (struct inferior *inf, thread_t thread)
 static void
 darwin_suspend_inferior (struct inferior *inf)
 {
-  if (!inf->private->suspended)
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  if (!priv->suspended)
     {
       kern_return_t kret;
 
-      kret = task_suspend (inf->private->task);
+      kret = task_suspend (priv->task);
       MACH_CHECK_ERROR (kret);
 
-      inf->private->suspended = 1;
+      priv->suspended = 1;
     }
 }
 
@@ -450,14 +435,16 @@ darwin_suspend_inferior (struct inferior *inf)
 static void
 darwin_resume_inferior (struct inferior *inf)
 {
-  if (inf->private->suspended)
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  if (priv->suspended)
     {
       kern_return_t kret;
 
-      kret = task_resume (inf->private->task);
+      kret = task_resume (priv->task);
       MACH_CHECK_ERROR (kret);
 
-      inf->private->suspended = 0;
+      priv->suspended = 0;
     }
 }
 
@@ -492,7 +479,7 @@ darwin_dump_message (mach_msg_header_t *hdr, int disp_body)
   if (disp_body)
     {
       const unsigned char *data;
-      const unsigned long *ldata;
+      const unsigned int *ldata;
       int size;
       int i;
 
@@ -538,13 +525,78 @@ darwin_dump_message (mach_msg_header_t *hdr, int disp_body)
        }
 
       printf_unfiltered (_("  data:"));
-      ldata = (const unsigned long *)data;
-      for (i = 0; i < size / sizeof (unsigned long); i++)
-       printf_unfiltered (" %08lx", ldata[i]);
+      ldata = (const unsigned int *)data;
+      for (i = 0; i < size / sizeof (unsigned int); i++)
+       printf_unfiltered (" %08x", ldata[i]);
       printf_unfiltered (_("\n"));
     }
 }
 
+/* Adjust inferior data when a new task was created.  */
+
+static struct inferior *
+darwin_find_new_inferior (task_t task_port, thread_t thread_port)
+{
+  int task_pid;
+  struct inferior *inf;
+  kern_return_t kret;
+  mach_port_t prev;
+
+  /* Find the corresponding pid.  */
+  kret = pid_for_task (task_port, &task_pid);
+  if (kret != KERN_SUCCESS)
+    {
+      MACH_CHECK_ERROR (kret);
+      return NULL;
+    }
+
+  /* Find the inferior for this pid.  */
+  inf = darwin_find_inferior_by_pid (task_pid);
+  if (inf == NULL)
+    return NULL;
+
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  /* Deallocate saved exception ports.  */
+  darwin_deallocate_exception_ports (priv);
+
+  /* No need to remove dead_name notification, but still...  */
+  kret = mach_port_request_notification (gdb_task, priv->task,
+                                        MACH_NOTIFY_DEAD_NAME, 0,
+                                        MACH_PORT_NULL,
+                                        MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                        &prev);
+  if (kret != KERN_INVALID_ARGUMENT)
+    MACH_CHECK_ERROR (kret);
+
+  /* Replace old task port.  */
+  kret = mach_port_deallocate (gdb_task, priv->task);
+  MACH_CHECK_ERROR (kret);
+  priv->task = task_port;
+
+  darwin_setup_request_notification (inf);
+  darwin_setup_exceptions (inf);
+
+  return inf;
+}
+
+/* Check data representation.  */
+
+static int
+darwin_check_message_ndr (NDR_record_t *ndr)
+{
+  if (ndr->mig_vers != NDR_PROTOCOL_2_0
+      || ndr->if_vers != NDR_PROTOCOL_2_0
+      || ndr->mig_encoding != NDR_record.mig_encoding
+      || ndr->int_rep != NDR_record.int_rep
+      || ndr->char_rep != NDR_record.char_rep
+      || ndr->float_rep != NDR_record.float_rep)
+    return -1;
+  return 0;
+}
+
+/* Decode an exception message.  */
+
 static int
 darwin_decode_exception_message (mach_msg_header_t *hdr,
                                 struct inferior **pinf,
@@ -561,8 +613,8 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
   kern_return_t kret;
   int i;
 
-  /* Check message identifier.  2401 is exc.  */
-  if (hdr->msgh_id != 2401)
+  /* Check message destination.  */
+  if (hdr->msgh_local_port != darwin_ex_port)
     return -1;
 
   /* Check message header.  */
@@ -581,33 +633,76 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
 
   /* Check data representation.  */
   ndr = (NDR_record_t *)(desc + 2);
-  if (ndr->mig_vers != NDR_PROTOCOL_2_0
-      || ndr->if_vers != NDR_PROTOCOL_2_0
-      || ndr->mig_encoding != NDR_record.mig_encoding
-      || ndr->int_rep != NDR_record.int_rep
-      || ndr->char_rep != NDR_record.char_rep
-      || ndr->float_rep != NDR_record.float_rep)
+  if (darwin_check_message_ndr (ndr) != 0)
     return -1;
 
   /* Ok, the hard work.  */
   data = (integer_t *)(ndr + 1);
 
-  /* Find process by port.  */
   task_port = desc[1].name;
   thread_port = desc[0].name;
+
+  /* Find process by port.  */
   inf = darwin_find_inferior_by_task (task_port);
-  if (inf == NULL)
-    return -1;
   *pinf = inf;
 
+  if (inf == NULL && data[0] == EXC_SOFTWARE && data[1] == 2
+      && data[2] == EXC_SOFT_SIGNAL && data[3] == SIGTRAP)
+    {
+      /* Not a known inferior, but a sigtrap.  This happens on darwin 16.1.0,
+        as a new Mach task is created when a process exec.  */
+      inf = darwin_find_new_inferior (task_port, thread_port);
+      *pinf = inf;
+
+      if (inf == NULL)
+       {
+         /* Deallocate task_port, unless it was saved.  */
+         kret = mach_port_deallocate (mach_task_self (), task_port);
+         MACH_CHECK_ERROR (kret);
+       }
+    }
+  else
+    {
+      /* We got new rights to the task, get rid of it.  Do not get rid of
+        thread right, as we will need it to find the thread.  */
+      kret = mach_port_deallocate (mach_task_self (), task_port);
+      MACH_CHECK_ERROR (kret);
+    }
+
+  if (inf == NULL)
+    {
+      /* 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
+       (4, _("darwin_decode_exception_message: unknown task 0x%x\n"),
+        task_port);
+
+      /* Free thread port (we don't know it).  */
+      kret = mach_port_deallocate (mach_task_self (), thread_port);
+      MACH_CHECK_ERROR (kret);
+
+      darwin_encode_reply (&reply, hdr, KERN_SUCCESS);
+
+      kret = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
+                      reply.Head.msgh_size, 0,
+                      MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
+                      MACH_PORT_NULL);
+      MACH_CHECK_ERROR (kret);
+
+      return 0;
+    }
+
   /* 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);
 
-  /* We got new rights to the task and the thread.  Get rid of them.  */
-  kret = mach_port_deallocate (mach_task_self (), task_port);
-  MACH_CHECK_ERROR (kret);
+  /* Free the thread port (as gdb knows the thread, it has already has a right
+     for it, so this just decrement a reference counter).  */
   kret = mach_port_deallocate (mach_task_self (), thread_port);
   MACH_CHECK_ERROR (kret);
 
@@ -616,8 +711,8 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
     return -1;
   *pthread = thread;
 
-  /* The thread should be running.  However we have observed cases where a thread
-     got a SIGTTIN message after being stopped.  */
+  /* The thread should be running.  However we have observed cases where a
+     thread got a SIGTTIN message after being stopped.  */
   gdb_assert (thread->msg_state != DARWIN_MESSAGE);
 
   /* Finish decoding.  */
@@ -639,14 +734,56 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
   return 0;
 }
 
+/* Decode dead_name notify message.  */
+
+static int
+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)
+    return -1;
+
+  /* Check descriptors.  */
+  if (hdr->msgh_size < (sizeof (*hdr) + sizeof (*ndr) + sizeof (integer_t)))
+    return -2;
+
+  /* Check data representation.  */
+  if (darwin_check_message_ndr (ndr) != 0)
+    return -3;
+
+  task_port = data[0];
+
+  /* Find process by port.  */
+  inf = darwin_find_inferior_by_task (task_port);
+  *pinf = inf;
+
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  /* Check message destination.  */
+  if (inf != NULL && hdr->msgh_local_port != priv->notify_port)
+    return -4;
+
+  return 0;
+}
+
 static void
 darwin_encode_reply (mig_reply_error_t *reply, mach_msg_header_t *hdr,
                     integer_t code)
 {
   mach_msg_header_t *rh = &reply->Head;
-  rh->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(hdr->msgh_bits), 0);
+
+  rh->msgh_bits = MACH_MSGH_BITS (MACH_MSGH_BITS_REMOTE (hdr->msgh_bits), 0);
   rh->msgh_remote_port = hdr->msgh_remote_port;
-  rh->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
+  rh->msgh_size = (mach_msg_size_t) sizeof (mig_reply_error_t);
   rh->msgh_local_port = MACH_PORT_NULL;
   rh->msgh_id = hdr->msgh_id + 100;
 
@@ -659,6 +796,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);
 
@@ -668,7 +806,7 @@ darwin_send_reply (struct inferior *inf, darwin_thread_t *thread)
                   MACH_PORT_NULL);
   MACH_CHECK_ERROR (kret);
 
-  inf->private->pending_messages--;
+  priv->pending_messages--;
 }
 
 static void
@@ -690,7 +828,7 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
        {
          /* Either deliver a new signal or cancel the signal received.  */
          res = PTRACE (PT_THUPDATE, inf->pid,
-                       (void *)(uintptr_t)thread->gdb_port, nsignal);
+                       (caddr_t) (uintptr_t) thread->gdb_port, nsignal);
          if (res < 0)
            inferior_debug (1, _("ptrace THUP: res=%d\n"), res);
        }
@@ -705,13 +843,10 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
        }
 
       /* Set or reset single step.  */
-      if (step != thread->single_step)
-       {
-         inferior_debug (4, _("darwin_set_sstep (thread=0x%x, enable=%d)\n"),
-                         thread->gdb_port, step);
-         darwin_set_sstep (thread->gdb_port, step);
-         thread->single_step = step;
-       }
+      inferior_debug (4, _("darwin_set_sstep (thread=0x%x, enable=%d)\n"),
+                     thread->gdb_port, step);
+      darwin_set_sstep (thread->gdb_port, step);
+      thread->single_step = step;
 
       darwin_send_reply (inf, thread);
       thread->msg_state = DARWIN_RUNNING;
@@ -734,12 +869,9 @@ 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->private->threads, k, thread);
-       k++)
+  for (darwin_thread_t *thread : priv->threads)
     darwin_resume_thread (inf, thread, step, nsignal);
 }
 
@@ -765,28 +897,28 @@ 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->private->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;
@@ -797,7 +929,7 @@ darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
   struct inferior *inf;
 
   inferior_debug
-    (2, _("darwin_resume: pid=%d, tid=0x%x, step=%d, signal=%d\n"),
+    (2, _("darwin_resume: pid=%d, tid=0x%lx, step=%d, signal=%d\n"),
      ptid_get_pid (ptid), ptid_get_tid (ptid), step, signal);
 
   if (signal == GDB_SIGNAL_0)
@@ -824,7 +956,7 @@ darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
     }
   else
     {
-      struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid));
+      struct inferior *inf = find_inferior_ptid (ptid);
       long tid = ptid_get_tid (ptid);
 
       /* Stop the inferior (should be useless).  */
@@ -850,13 +982,6 @@ 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,
@@ -866,8 +991,8 @@ darwin_decode_message (mach_msg_header_t *hdr,
   darwin_thread_t *thread;
   struct inferior *inf;
 
-  /* Exception message.  */
-  if (hdr->msgh_local_port == darwin_ex_port)
+  /* Exception message.  2401 == 0x961 is exc.  */
+  if (hdr->msgh_id == 2401)
     {
       int res;
 
@@ -880,12 +1005,20 @@ darwin_decode_message (mach_msg_header_t *hdr,
          printf_unfiltered
            (_("darwin_wait: ill-formatted message (id=0x%x)\n"), hdr->msgh_id);
          /* FIXME: send a failure reply?  */
-         status->kind = TARGET_WAITKIND_SPURIOUS;
+         status->kind = TARGET_WAITKIND_IGNORE;
+         return minus_one_ptid;
+       }
+      if (inf == NULL)
+       {
+         status->kind = TARGET_WAITKIND_IGNORE;
          return minus_one_ptid;
        }
       *pinf = inf;
       *pthread = thread;
-      inf->private->pending_messages++;
+
+      darwin_inferior *priv = get_darwin_inferior (inf);
+
+      priv->pending_messages++;
 
       status->kind = TARGET_WAITKIND_STOPPED;
       thread->msg_state = DARWIN_MESSAGE;
@@ -943,56 +1076,80 @@ darwin_decode_message (mach_msg_header_t *hdr,
 
       return ptid_build (inf->pid, 0, thread->gdb_port);
     }
+  else if (hdr->msgh_id == 0x48)
+    {
+      /* MACH_NOTIFY_DEAD_NAME: notification for exit.  */
+      int res;
 
-  *pinf = NULL;
-  *pthread = NULL;
+      res = darwin_decode_notify_message (hdr, &inf);
 
-  inf = darwin_find_inferior_by_notify (hdr->msgh_local_port);
-  if (inf != NULL)
-    {
-      if (!inf->private->no_ptrace)
+      if (res < 0)
        {
-         pid_t res;
-         int wstatus;
+         /* Should not happen...  */
+         printf_unfiltered
+           (_("darwin_wait: ill-formatted message (id=0x%x, res=%d)\n"),
+            hdr->msgh_id, res);
+       }
 
-         res = wait4 (inf->pid, &wstatus, 0, NULL);
-         if (res < 0 || res != inf->pid)
-           {
-             printf_unfiltered (_("wait4: res=%d: %s\n"),
-                                res, safe_strerror (errno));
-             status->kind = TARGET_WAITKIND_SPURIOUS;
-             return minus_one_ptid;
-           }
-         if (WIFEXITED (wstatus))
+      *pinf = NULL;
+      *pthread = NULL;
+
+      if (res < 0 || inf == NULL)
+       {
+         status->kind = TARGET_WAITKIND_IGNORE;
+         return minus_one_ptid;
+       }
+
+      if (inf != NULL)
+       {
+         darwin_inferior *priv = get_darwin_inferior (inf);
+
+         if (!priv->no_ptrace)
            {
-             status->kind = TARGET_WAITKIND_EXITED;
-             status->value.integer = WEXITSTATUS (wstatus);
+             pid_t res;
+             int wstatus;
+
+             res = wait4 (inf->pid, &wstatus, 0, NULL);
+             if (res < 0 || res != inf->pid)
+               {
+                 printf_unfiltered (_("wait4: res=%d: %s\n"),
+                                    res, safe_strerror (errno));
+                 status->kind = TARGET_WAITKIND_IGNORE;
+                 return minus_one_ptid;
+               }
+             if (WIFEXITED (wstatus))
+               {
+                 status->kind = TARGET_WAITKIND_EXITED;
+                 status->value.integer = WEXITSTATUS (wstatus);
+               }
+             else
+               {
+                 status->kind = TARGET_WAITKIND_SIGNALLED;
+                 status->value.sig = gdb_signal_from_host (WTERMSIG (wstatus));
+               }
+
+             inferior_debug (4, _("darwin_wait: pid=%d exit, status=0x%x\n"),
+                             res, wstatus);
+
+             /* Looks necessary on Leopard and harmless...  */
+             wait4 (inf->pid, &wstatus, 0, NULL);
+
+             inferior_ptid = ptid_build (inf->pid, 0, 0);
+             return inferior_ptid;
            }
          else
            {
-             status->kind = TARGET_WAITKIND_SIGNALLED;
-             status->value.sig = WTERMSIG (wstatus);
+             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);
            }
-
-         inferior_debug (4, _("darwin_wait: pid=%d exit, status=0x%x\n"),
-                         res, wstatus);
-
-         /* Looks necessary on Leopard and harmless...  */
-         wait4 (inf->pid, &wstatus, 0, NULL);
-
-         return ptid_build (inf->pid, 0, 0);
-       }
-      else
-       {
-         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);
        }
     }
 
-  printf_unfiltered (_("Bad local-port: 0x%x\n"), hdr->msgh_local_port);
-  status->kind = TARGET_WAITKIND_SPURIOUS;
+  /* Unknown message.  */
+  warning (_("darwin: got unknown message, id: 0x%x"), hdr->msgh_id);
+  status->kind = TARGET_WAITKIND_IGNORE;
   return minus_one_ptid;
 }
 
@@ -1008,14 +1165,14 @@ cancel_breakpoint (ptid_t ptid)
      tripped on it.  */
 
   struct regcache *regcache = get_thread_regcache (ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  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%x\n",
-                     ptid_get_tid (ptid));
+      inferior_debug (4, "cancel_breakpoint for thread 0x%lx\n",
+                     (unsigned long) ptid_get_tid (ptid));
 
       /* Back up the PC if necessary.  */
       if (gdbarch_decr_pc_after_break (gdbarch))
@@ -1050,9 +1207,11 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
       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->private->threads, 0);
+      thread = priv->threads[0];
       thread->msg_state = DARWIN_STOPPED;
       return ptid_build (inf->pid, 0, thread->gdb_port);
     }
@@ -1085,7 +1244,10 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
        darwin_dump_message (hdr, darwin_debug_flag > 11);
 
       res = darwin_decode_message (hdr, &thread, &inf, status);
+      if (ptid_equal (res, minus_one_ptid))
+       continue;
 
+      /* Early return in case an inferior has exited.  */
       if (inf == NULL)
        return res;
     }
@@ -1113,6 +1275,10 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
          break;
        }
 
+      /* Debug: display message.  */
+      if (darwin_debug_flag > 10)
+       darwin_dump_message (hdr, darwin_debug_flag > 11);
+
       ptid2 = darwin_decode_message (hdr, &thread, &inf, &status2);
 
       if (inf != NULL && thread != NULL
@@ -1136,61 +1302,66 @@ 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);
 }
 
-static void
-darwin_stop (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->private->no_ptrace);
-  kill (inf->pid, SIGINT);
+  gdb_assert (!priv->no_ptrace);
+  ::kill (inf->pid, SIGINT);
 }
 
+/* Deallocate threads port and vector.  */
+
 static void
-darwin_mourn_inferior (struct target_ops *ops)
+darwin_deallocate_threads (struct inferior *inf)
+{
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  for (darwin_thread_t *t : priv->threads)
+    {
+      kern_return_t kret = mach_port_deallocate (gdb_task, t->gdb_port);
+      MACH_CHECK_ERROR (kret);
+    }
+
+  priv->threads.clear ();
+}
+
+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;
 
-  unpush_target (darwin_ops);
-
   /* Deallocate threads.  */
-  if (inf->private->threads)
-    {
-      int k;
-      darwin_thread_t *t;
-      for (k = 0;
-          VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
-          k++)
-       {
-         kret = mach_port_deallocate (gdb_task, t->gdb_port);
-         MACH_CHECK_ERROR (kret);
-       }
-      VEC_free (darwin_thread_t, inf->private->threads);
-      inf->private->threads = NULL;
-    }
+  darwin_deallocate_threads (inf);
 
+  /* Remove notify_port from darwin_port_set.  */
   kret = mach_port_move_member (gdb_task,
-                               inf->private->notify_port, MACH_PORT_NULL);
+                               priv->notify_port, MACH_PORT_NULL);
   MACH_CHECK_ERROR (kret);
 
-  kret = mach_port_request_notification (gdb_task, inf->private->task,
+  /* Remove task port dead_name notification.  */
+  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->private->task, prev, inf->private->notify_port);
+                 priv->task, prev, priv->notify_port);
 
   if (kret == KERN_SUCCESS)
     {
@@ -1198,37 +1369,28 @@ darwin_mourn_inferior (struct target_ops *ops)
       MACH_CHECK_ERROR (kret);
     }
 
-  kret = mach_port_destroy (gdb_task, inf->private->notify_port);
+  /* Destroy notify_port.  */
+  kret = mach_port_destroy (gdb_task, priv->notify_port);
   MACH_CHECK_ERROR (kret);
 
-
   /* Deallocate saved exception ports.  */
-  for (i = 0; i < inf->private->exception_info.count; i++)
-    {
-      kret = mach_port_deallocate
-       (gdb_task, inf->private->exception_info.ports[i]);
-      MACH_CHECK_ERROR (kret);
-    }
-  inf->private->exception_info.count = 0;
+  darwin_deallocate_exception_ports (priv);
 
-  kret = mach_port_deallocate (gdb_task, inf->private->task);
+  /* Deallocate task port.  */
+  kret = mach_port_deallocate (gdb_task, priv->task);
   MACH_CHECK_ERROR (kret);
 
-  xfree (inf->private);
-  inf->private = NULL;
+  inf->priv = NULL;
 
-  generic_mourn_inferior ();
+  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->private->threads, k, t);
-       k++)
+  for (darwin_thread_t *t : priv->threads)
     {
       if (t->msg_state == DARWIN_MESSAGE)
        darwin_resume_thread (inf, t, 0, 0);
@@ -1243,6 +1405,7 @@ darwin_stop_inferior (struct inferior *inf)
   kern_return_t kret;
   int status;
   int res;
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
   gdb_assert (inf != NULL);
 
@@ -1250,7 +1413,7 @@ darwin_stop_inferior (struct inferior *inf)
 
   darwin_reply_to_all_pending_messages (inf);
 
-  if (inf->private->no_ptrace)
+  if (priv->no_ptrace)
     return;
 
   res = kill (inf->pid, SIGSTOP);
@@ -1300,10 +1463,54 @@ darwin_restore_exception_ports (darwin_inferior *inf)
   return KERN_SUCCESS;
 }
 
+/* Deallocate saved exception ports.  */
+
+static void
+darwin_deallocate_exception_ports (darwin_inferior *inf)
+{
+  int i;
+  kern_return_t kret;
+
+  for (i = 0; i < inf->exception_info.count; i++)
+    {
+      kret = mach_port_deallocate (gdb_task, inf->exception_info.ports[i]);
+      MACH_CHECK_ERROR (kret);
+    }
+  inf->exception_info.count = 0;
+}
+
 static void
-darwin_kill_inferior (struct target_ops *ops)
+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 (priv);
+  if (kret != KERN_SUCCESS)
+    error (_("Unable to save exception ports, task_get_exception_ports"
+            "returned: %d"),
+          kret);
+
+  /* Set exception port.  */
+  if (enable_mach_exceptions)
+    mask = EXC_MASK_ALL;
+  else
+    mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
+  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"
+            "returned: %d"),
+          kret);
+}
+
+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;
@@ -1315,24 +1522,53 @@ darwin_kill_inferior (struct target_ops *ops)
 
   gdb_assert (inf != NULL);
 
-  kret = darwin_restore_exception_ports (inf->private);
+  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)
     {
       darwin_resume_inferior (inf);
-         
+
       ptid = darwin_wait (inferior_ptid, &wstatus);
     }
   else if (errno != ESRCH)
     warning (_("Failed to kill inferior: kill (%d, 9) returned [%s]"),
             inf->pid, safe_strerror (errno));
 
-  target_mourn_inferior ();
+  target_mourn_inferior (inferior_ptid);
+}
+
+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, priv->task,
+                                        MACH_NOTIFY_DEAD_NAME, 0,
+                                        priv->notify_port,
+                                        MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                        &prev_not);
+  if (kret != KERN_SUCCESS)
+    error (_("Termination notification request failed, "
+            "mach_port_request_notification\n"
+            "returned: %d"),
+          kret);
+  if (prev_not != MACH_PORT_NULL)
+    {
+      /* This is unexpected, as there should not be any previously
+        registered notification request.  But this is not a fatal
+        issue, so just emit a warning.  */
+      warning (_("\
+A task termination request was registered before the debugger registered\n\
+its own.  This is unexpected, but should otherwise not have any actual\n\
+impact on the debugging session."));
+    }
 }
 
 static void
@@ -1344,135 +1580,135 @@ darwin_attach_pid (struct inferior *inf)
   mach_port_t prev_not;
   exception_mask_t mask;
 
-  inf->private = XZALLOC (darwin_inferior);
+  darwin_inferior *priv = new darwin_inferior;
+  inf->priv.reset (priv);
 
-  kret = task_for_pid (gdb_task, inf->pid, &inf->private->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;
 
-      error (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n"
+         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"
               " (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->private->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);
+
+      darwin_setup_request_notification (inf);
+
+      darwin_setup_exceptions (inf);
     }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      inf->pid = 0;
+      inf->priv.reset ();
+      inferior_ptid = null_ptid;
 
-  /* Create a port to be notified when the child task terminates.  */
-  kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
-                            &inf->private->notify_port);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to create notification port, mach_port_allocate "
-            "returned: %d"),
-          kret);
+      throw_exception (ex);
+    }
+  END_CATCH
 
-  kret = mach_port_move_member (gdb_task,
-                               inf->private->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);
+  target_ops *darwin_ops = get_native_target ();
+  if (!target_is_pushed (darwin_ops))
+    push_target (darwin_ops);
+}
 
-  kret = mach_port_request_notification (gdb_task, inf->private->task,
-                                        MACH_NOTIFY_DEAD_NAME, 0,
-                                        inf->private->notify_port,
-                                        MACH_MSG_TYPE_MAKE_SEND_ONCE,
-                                        &prev_not);
-  if (kret != KERN_SUCCESS)
-    error (_("Termination notification request failed, "
-            "mach_port_request_notification\n"
-            "returned: %d"),
-          kret);
-  if (prev_not != MACH_PORT_NULL)
+/* 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)
+{
+  struct thread_info *it;
+
+  ALL_THREADS (it)
     {
-      /* This is unexpected, as there should not be any previously
-        registered notification request.  But this is not a fatal
-        issue, so just emit a warning.  */
-      warning (_("\
-A task termination request was registered before the debugger registered\n\
-its own.  This is unexpected, but should otherwise not have any actual\n\
-impact on the debugging session."));
-    }
+      darwin_thread_info *iter_pti = get_darwin_thread_info (it);
 
-  kret = darwin_save_exception_ports (inf->private);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to save exception ports, task_get_exception_ports"
-            "returned: %d"),
-          kret);
+      if (iter_pti->gdb_port == pti->gdb_port)
+       break;
+    }
 
-  /* Set exception port.  */
-  if (enable_mach_exceptions)
-    mask = EXC_MASK_ALL;
-  else
-    mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
-  kret = task_set_exception_ports (inf->private->task, mask, darwin_ex_port,
-                                  EXCEPTION_DEFAULT, THREAD_STATE_NONE);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to set exception ports, task_set_exception_ports"
-            "returned: %d"),
-          kret);
+  gdb_assert (it != NULL);
 
-  push_target (darwin_ops);
+  return it;
 }
 
 static void
 darwin_init_thread_list (struct inferior *inf)
 {
-  darwin_thread_t *thread;
-  ptid_t new_ptid;
-
   darwin_check_new_threads (inf);
 
-  gdb_assert (inf->private->threads
-             && VEC_length (darwin_thread_t, inf->private->threads) > 0);
-  thread = VEC_index (darwin_thread_t, inf->private->threads, 0);
+  darwin_inferior *priv = get_darwin_inferior (inf);
 
-  /* 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;
+  gdb_assert (!priv->threads.empty ());
+
+  darwin_thread_info *first_pti = priv->threads.front ();
+  struct thread_info *first_thread
+    = thread_info_from_private_thread_info (first_pti);
+
+  inferior_ptid = first_thread->ptid;
 }
 
 /* The child must synchronize with gdb: gdb must set the exception port
@@ -1487,22 +1723,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).  */
@@ -1540,7 +1782,7 @@ darwin_ptrace_him (int pid)
 
   darwin_init_thread_list (inf);
 
-  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+  gdb_startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED);
 }
 
 static void
@@ -1577,17 +1819,15 @@ darwin_execvp (const char *file, char * const argv[], char * const env[])
   posix_spawnp (NULL, argv[0], NULL, &attr, argv, env);
 }
 
-static void
-darwin_create_inferior (struct target_ops *ops, char *exec_file,
-                       char *allargs, char **env, int from_tty)
+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);
-
-  /* Return now in case of error.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return;
+  fork_inferior (exec_file, allargs, env, darwin_ptrace_me,
+                darwin_ptrace_him, darwin_pre_ptrace, NULL,
+                darwin_execvp);
 }
 \f
 
@@ -1600,6 +1840,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;
 
@@ -1612,15 +1853,15 @@ 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->private->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, char *args, int from_tty)
+void
+darwin_nat_target::attach (const char *args, int from_tty)
 {
   pid_t pid;
   pid_t pid2;
@@ -1648,7 +1889,7 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty)
       gdb_flush (gdb_stdout);
     }
 
-  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);
 
@@ -1657,20 +1898,19 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty)
   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);
 
-  darwin_check_osabi (inf->private, ptid_get_tid (inferior_ptid));
+  darwin_inferior *priv = get_darwin_inferior (inf);
+
+  darwin_check_osabi (priv, ptid_get_tid (inferior_ptid));
 
   darwin_setup_fake_stop_event (inf);
 
-  inf->private->no_ptrace = 1;
+  priv->no_ptrace = 1;
 }
 
 /* Take a program previously attached to and detaches it.
@@ -1680,33 +1920,26 @@ darwin_attach (struct target_ops *ops, 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;
 
   /* Display message.  */
-  if (from_tty)
-    {
-      char *exec_file = get_exec_file (0);
-      if (exec_file == 0)
-       exec_file = "";
-      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
-                        target_pid_to_str (pid_to_ptid (pid)));
-      gdb_flush (gdb_stdout);
-    }
+  target_announce_detach (from_tty);
 
   /* If ptrace() is in use, stop the process.  */
-  if (!inf->private->no_ptrace)
+  if (!priv->no_ptrace)
     darwin_stop_inferior (inf);
 
-  kret = darwin_restore_exception_ports (inf->private);
+  kret = darwin_restore_exception_ports (priv);
   MACH_CHECK_ERROR (kret);
 
-  if (!inf->private->no_ptrace)
+  if (!priv->no_ptrace)
     {
       res = PTRACE (PT_DETACH, inf->pid, 0, 0);
       if (res != 0)
@@ -1719,19 +1952,14 @@ 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->private->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)
+const char *
+darwin_nat_target::pid_to_str (ptid_t ptid)
 {
   static char buf[80];
   long tid = ptid_get_tid (ptid);
@@ -1746,10 +1974,10 @@ darwin_pid_to_str (struct target_ops *ops, ptid_t ptid)
   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
@@ -1757,56 +1985,61 @@ darwin_thread_alive (struct target_ops *ops, ptid_t ptid)
    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.  */
+
 static int
 darwin_read_write_inferior (task_t task, CORE_ADDR addr,
                            gdb_byte *rdaddr, const gdb_byte *wraddr,
-                           int length)
+                           ULONGEST length)
 {
   kern_return_t kret;
-  mach_vm_address_t offset = addr & (mach_page_size - 1);
-  mach_vm_address_t low_address = (mach_vm_address_t) (addr - offset);
-  mach_vm_size_t aligned_length = (mach_vm_size_t) PAGE_ROUND (offset + length);
+  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=%d)\n"),
-                 task, core_addr_to_string (addr), length);
+  inferior_debug (8, _("darwin_read_write_inferior(task=0x%x, %s, len=%s)\n"),
+                 task, core_addr_to_string (addr), pulongest (length));
 
-  /* Get memory from inferior with page aligned addresses.  */
-  kret = mach_vm_read (task, low_address, aligned_length,
-                     &copied, &copy_count);
-  if (kret != KERN_SUCCESS)
+  /* First read.  */
+  if (rdaddr != NULL)
     {
-      inferior_debug
-       (1, _("darwin_read_write_inferior: mach_vm_read failed at %s: %s"),
-        core_addr_to_string (addr), mach_error_string (kret));
-      return 0;
-    }
+      mach_vm_size_t count;
 
-  if (rdaddr != NULL)
-    memcpy (rdaddr, (char *)copied + offset, length);
+      /* According to target.h(to_xfer_partial), one and only one may be
+        non-null.  */
+      gdb_assert (wraddr == NULL);
 
-  if (wraddr == NULL)
-    goto out;
+      kret = mach_vm_read_overwrite (task, addr, length,
+                                    (mach_vm_address_t) rdaddr, &count);
+      if (kret != KERN_SUCCESS)
+       {
+         inferior_debug
+           (1, _("darwin_read_write_inferior: mach_vm_read failed at %s: %s"),
+            core_addr_to_string (addr), mach_error_string (kret));
+         return 0;
+       }
+      return count;
+    }
 
-  memcpy ((char *)copied + offset, wraddr, length);
+  /* See above.  */
+  gdb_assert (wraddr != NULL);
 
-  /* Do writes atomically.
-     First check for holes and unwritable memory.  */
-  for (region_address = low_address, remaining_length = aligned_length;
-       region_address < low_address + aligned_length;
-       region_address += region_length, remaining_length -= region_length)
+  while (length != 0)
     {
+      mach_vm_address_t offset = addr & (mach_page_size - 1);
+      mach_vm_address_t region_address = (mach_vm_address_t) (addr - offset);
+      mach_vm_size_t aligned_length =
+       (mach_vm_size_t) PAGE_ROUND (offset + length);
       vm_region_submap_short_info_data_64_t info;
+      mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
+      natural_t region_depth = 1000;
       mach_vm_address_t region_start = region_address;
-      mach_msg_type_number_t count;
-      natural_t region_depth;
+      mach_vm_size_t region_length;
+      mach_vm_size_t write_length;
 
-      region_depth = 100000;
-      count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
+      /* Read page protection.  */
       kret = mach_vm_region_recurse
        (task, &region_start, &region_length, &region_depth,
         (vm_region_recurse_info_t) &info, &count);
@@ -1817,7 +2050,7 @@ darwin_read_write_inferior (task_t task, CORE_ADDR addr,
                               "mach_vm_region_recurse failed at %s: %s\n"),
                          core_addr_to_string (region_address),
                          mach_error_string (kret));
-         goto out;
+         return res_length;
        }
 
       inferior_debug
@@ -1834,131 +2067,166 @@ darwin_read_write_inferior (task_t task, CORE_ADDR addr,
                   core_addr_to_string (region_address),
                   core_addr_to_string (region_start),
                   (unsigned)region_length);
-         length = 0;
-         goto out;
+         return res_length;
        }
 
       /* Adjust the length.  */
       region_length -= (region_address - region_start);
+      if (region_length > aligned_length)
+       region_length = aligned_length;
 
-      if (!(info.max_protection & VM_PROT_WRITE))
+      /* Make the pages RW.  */
+      if (!(info.protection & VM_PROT_WRITE))
        {
-         kret = mach_vm_protect
-           (task, region_address, region_length,
-            TRUE, info.max_protection | VM_PROT_WRITE | VM_PROT_COPY);
+         vm_prot_t prot = VM_PROT_READ | VM_PROT_WRITE;
+
+         kret = mach_vm_protect (task, region_address, region_length,
+                                 FALSE, prot);
+         if (kret != KERN_SUCCESS)
+           {
+             prot |= VM_PROT_COPY;
+             kret = mach_vm_protect (task, region_address, region_length,
+                                     FALSE, prot);
+           }
          if (kret != KERN_SUCCESS)
            {
-             warning (_("darwin_read_write_inf: "
-                        "mach_vm_protect max failed at %s: %s"),
+             warning (_("darwin_read_write_inferior: "
+                        "mach_vm_protect failed at %s "
+                        "(len=0x%lx, prot=0x%x): %s"),
                       core_addr_to_string (region_address),
+                      (unsigned long) region_length, (unsigned) prot,
                       mach_error_string (kret));
-             length = 0;
-             goto out;
+             return res_length;
            }
        }
 
+      if (offset + length > region_length)
+       write_length = region_length - offset;
+      else
+       write_length = length;
+
+      /* Write.  */
+      kret = mach_vm_write (task, addr, (vm_offset_t) wraddr, write_length);
+      if (kret != KERN_SUCCESS)
+       {
+         warning (_("darwin_read_write_inferior: mach_vm_write failed: %s"),
+                  mach_error_string (kret));
+         return res_length;
+       }
+
+      /* Restore page rights.  */
       if (!(info.protection & VM_PROT_WRITE))
        {
          kret = mach_vm_protect (task, region_address, region_length,
-                                FALSE, info.protection | VM_PROT_WRITE);
+                                 FALSE, info.protection);
          if (kret != KERN_SUCCESS)
            {
-             warning (_("darwin_read_write_inf: "
-                        "mach_vm_protect failed at %s (len=0x%lx): %s"),
+             warning (_("darwin_read_write_inferior: "
+                        "mach_vm_protect restore failed at %s "
+                        "(len=0x%lx): %s"),
                       core_addr_to_string (region_address),
-                      (unsigned long)region_length, mach_error_string (kret));
-             length = 0;
-             goto out;
+                      (unsigned long) region_length,
+                      mach_error_string (kret));
            }
        }
-    }
 
-  kret = mach_vm_write (task, low_address, copied, aligned_length);
-
-  if (kret != KERN_SUCCESS)
-    {
-      warning (_("darwin_read_write_inferior: mach_vm_write failed: %s"),
-              mach_error_string (kret));
-      length = 0;
+      addr += write_length;
+      wraddr += write_length;
+      res_length += write_length;
+      length -= write_length;
     }
-out:
-  mach_vm_deallocate (mach_task_self (), copied, copy_count);
-  return length;
+
+  return res_length;
 }
 
 /* Read LENGTH bytes at offset ADDR of task_dyld_info for TASK, and copy them
-   to RDADDR.
+   to RDADDR (in big endian).
    Return 0 on failure; number of bytes read / written otherwise.  */
 
 #ifdef TASK_DYLD_INFO_COUNT
 /* This is not available in Darwin 9.  */
-static int
+static enum target_xfer_status
 darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr,
-                      int length)
+                      ULONGEST length, ULONGEST *xfered_len)
 {
   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 >= sz)
-    return 0;
+  if (addr != 0 || length > sizeof (mach_vm_address_t))
+    return TARGET_XFER_EOF;
 
-  kret = task_info (task, TASK_DYLD_INFO, (task_info_t) &task_dyld_info, &count);
+  kret = task_info (task, TASK_DYLD_INFO,
+                   (task_info_t) &task_dyld_info, &count);
   MACH_CHECK_ERROR (kret);
   if (kret != KERN_SUCCESS)
-    return -1;
-  /* Truncate.  */
-  if (addr + length > sz)
-    length = sz - addr;
-  memcpy (rdaddr, (char *)&task_dyld_info + addr, length);
-  return length;
+    return TARGET_XFER_E_IO;
+
+  store_unsigned_integer (rdaddr, length, BFD_ENDIAN_BIG,
+                         task_dyld_info.all_image_info_addr);
+  *xfered_len = (ULONGEST) length;
+  return TARGET_XFER_OK;
 }
 #endif
 
 \f
 
-static LONGEST
-darwin_xfer_partial (struct target_ops *ops,
-                    enum target_object object, const char *annex,
-                    gdb_byte *readbuf, const gdb_byte *writebuf,
-                    ULONGEST offset, LONGEST 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, %d, rbuf=%s, wbuf=%s) pid=%u\n"),
-     core_addr_to_string (offset), (int)len,
+    (8, _("darwin_xfer_partial(%s, %s, rbuf=%s, wbuf=%s) pid=%u\n"),
+     core_addr_to_string (offset), pulongest (len),
      host_address_to_string (readbuf), host_address_to_string (writebuf),
      inf->pid);
 
   switch (object)
     {
     case TARGET_OBJECT_MEMORY:
-      return darwin_read_write_inferior (inf->private->task, offset,
-                                         readbuf, writebuf, len);
+      {
+       int l = darwin_read_write_inferior (priv->task, offset,
+                                           readbuf, writebuf, len);
+
+       if (l == 0)
+         return TARGET_XFER_EOF;
+       else
+         {
+           gdb_assert (l > 0);
+           *xfered_len = (ULONGEST) l;
+           return TARGET_XFER_OK;
+         }
+      }
 #ifdef TASK_DYLD_INFO_COUNT
     case TARGET_OBJECT_DARWIN_DYLD_INFO:
       if (writebuf != NULL || readbuf == NULL)
         {
           /* Support only read.  */
-          return -1;
+          return TARGET_XFER_E_IO;
         }
-      return darwin_read_dyld_info (inf->private->task, offset, readbuf, len);
+      return darwin_read_dyld_info (priv->task, offset, readbuf, len,
+                                   xfered_len);
 #endif
     default:
-      return -1;
+      return TARGET_XFER_E_IO;
     }
 
 }
 
 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))
     {
       struct inferior *inf = current_inferior ();
+      darwin_inferior *priv = get_darwin_inferior (inf);
       exception_mask_t mask;
       kern_return_t kret;
 
@@ -1966,24 +2234,21 @@ set_enable_mach_exceptions (char *args, int from_tty,
        mask = EXC_MASK_ALL;
       else
        {
-         darwin_restore_exception_ports (inf->private);
+         darwin_restore_exception_ports (priv);
          mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
        }
-      kret = task_set_exception_ports (inf->private->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 (int pid)
+char *
+darwin_nat_target::pid_to_exec_file (int pid)
 {
-  char *path;
+  static char path[PATH_MAX];
   int res;
 
-  path = xmalloc (PATH_MAX);
-  make_cleanup (xfree, path);
-
   res = proc_pidinfo (pid, PROC_PIDPATHINFO, 0, path, PATH_MAX);
   if (res >= 0)
     return path;
@@ -1991,13 +2256,11 @@ darwin_pid_to_exec_file (int pid)
     return NULL;
 }
 
-static ptid_t
-darwin_get_ada_task_ptid (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;
@@ -2006,16 +2269,16 @@ darwin_get_ada_task_ptid (long lwp, long thread)
   long res = 0;
 
   /* First linear search.  */
-  for (k = 0;
-       VEC_iterate (darwin_thread_t, inf->private->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_build (ptid_get_pid (inferior_ptid), 0, t->gdb_port);
+    }
 
   /* Maybe the port was never extract.  Do it now.  */
 
   /* First get inferior port names.  */
-  kret = mach_port_names (inf->private->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)
@@ -2024,29 +2287,29 @@ darwin_get_ada_task_ptid (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->private->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->private->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,
@@ -2058,17 +2321,14 @@ darwin_get_ada_task_ptid (long lwp, long thread)
     return null_ptid;
 }
 
-static int
-darwin_supports_multi_process (void)
+bool
+darwin_nat_target::supports_multi_process ()
 {
-  return 1;
+  return true;
 }
 
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_darwin_inferior;
-
 void
-_initialize_darwin_inferior (void)
+_initialize_darwin_nat ()
 {
   kern_return_t kret;
 
@@ -2083,36 +2343,8 @@ _initialize_darwin_inferior (void)
       MACH_CHECK_ERROR (kret);
     }
 
-  darwin_ops = inf_child_target ();
-
-  darwin_ops->to_shortname = "darwin-child";
-  darwin_ops->to_longname = _("Darwin child process");
-  darwin_ops->to_doc =
-    _("Darwin child process (started by the \"run\" command).");
-  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_stop = darwin_stop;
-  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"), mach_task_self (),
-                  getpid ());
+  inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"),
+                 (unsigned long) mach_task_self (), getpid ());
 
   add_setshow_zuinteger_cmd ("darwin", class_obscure,
                             &darwin_debug_flag, _("\
This page took 0.048806 seconds and 4 git commands to generate.