2009-06-19 Tristan Gingold <gingold@adacore.com>
authorTristan Gingold <gingold@adacore.com>
Fri, 19 Jun 2009 14:30:30 +0000 (14:30 +0000)
committerTristan Gingold <gingold@adacore.com>
Fri, 19 Jun 2009 14:30:30 +0000 (14:30 +0000)
* machoread.c (macho_symtab_read): Adjust for bfd changes.
* darwin-nat.h (struct darwin_exception_msg): New type to describe
a mach exception.
(struct private_thread_info): New type to describe the state of the
thread.
(DEF_VEC_I thread_t): Removed, replaced by ...
(DEF_VEC_O darwin_thread_t): ... this new type.
(struct darwin_inferior): Renamed to ...
(struct private_inferior): ... this type.  Fields added.
(darwin_not_port): Moved into the private inferior structure.
* darwin-nat.c: Add includes, improve comments.
Rewrite to handle multiple threads and processes.
(darwin_resume_to): New function and protype.
(darwin_resume, darwin_wait_to, darwin_wait): Ditto.
(darwin_kill_inferior): Add ops argument.
(darwin_pid_to_str): New function.
(darwin_thread_alive): Ditto.
(darwin_inf, darwin_not_port): Removed.
(darwin_inf_fake_stop): New variable.
(msgin, msgout, msg_state, exc_msg): Removed.
(mach_check_error): Use warning instead of error.
(darwin_ptrace): Adjust debug level.
(cmp_thread_t): Fix names (typo).
(darwin_check_new_threads): Argument is now an inferior,
adjust for new structures, add no change check, ignore dead ports,
handle first thread case.
(find_inferior_task_it): New function.
(find_inferior_notify_it): Ditto.
(darwin_find_inferior_by_task): Ditto.
(darwin_find_inferior_by_notify): Ditto.
(darwin_find_thread): Ditto.
(darwin_suspend_inferior): Ditto.
(darwin_resume_inferior): Ditto.
(catch_exception_raise_state): Removed.
(catch_exception_raise_state_identity): Removed.
(darwin_suspend_inferior_it): New function.
(darwin_resume_inferior_it): Ditto.
(darwin_dump_message): New function, extracted from darwin_wait.
(darwin_decode_exception_message): New function.
(darwin_encode_reply): New function.
(catch_exception_raise): Removed.
(darwin_send_reply): New function, extracted from darwin_resume.
(darwin_resume_thread): New function, extracted from darwin_resume.
(struct resume_inferior_threads_param): New type.
(darwin_resume_inferior_threads_it): New function.
(darwin_resume_inferior_threads): New function.
(darwin_suspend_inferior_threads): New function.
(darwin_resume): Mostly rewritten to handle multiple threads and
some corner cases.
(darwin_decode_message): New function extracted from darwin_wait.
(cancel_breakpoint): New function.
(darwin_wait): Mostly rewritten.  Handle multiple threads.
(darwin_mourn_inferior): Adjust for per process structures.
(darwin_reply_to_all_pending_messages): New function.
(darwin_stop_inferior): Adjust for per inferior structures.
(darwin_attach_pid): Ditto.
(darwin_init_thread_list): Ditto.
(darwin_attach): Ditto.
(darwin_detach): Ditto.
(darwin_files_info): Now empty.
(darwin_pid_to_str): Adjust returns string to match one expected by
the testsuite.
(darwin_read_write_inferior): Rename err variable to match other uses.
Adjust debug message.  Handle submaps.
(darwin_xfer_memory): Adjust for per inferior structures.
(set_enable_mach_exceptions): Ditto.
(darwin_pid_to_exec_file): New function.
(darwin_get_ada_task_ptid): Ditto.
(darwin_supports_multi_process): Ditto.
(_initialize_darwin_inferior): Remove useless assertion, adjust for
per inferior structures.  Add new target operations.

gdb/ChangeLog
gdb/darwin-nat-info.c
gdb/darwin-nat.c
gdb/darwin-nat.h
gdb/machoread.c

index 3c4748c..2dd7915 100644 (file)
@@ -1,3 +1,77 @@
+2009-06-19  Tristan Gingold  <gingold@adacore.com>
+
+       * machoread.c (macho_symtab_read): Adjust for bfd changes.
+       * darwin-nat.h (struct darwin_exception_msg): New type to describe
+       a mach exception.
+       (struct private_thread_info): New type to describe the state of the
+       thread.
+       (DEF_VEC_I thread_t): Removed, replaced by ...
+       (DEF_VEC_O darwin_thread_t): ... this new type.
+       (struct darwin_inferior): Renamed to ...
+       (struct private_inferior): ... this type.  Fields added.
+       (darwin_not_port): Moved into the private inferior structure.
+       * darwin-nat.c: Add includes, improve comments.
+       Rewrite to handle multiple threads and processes.
+       (darwin_resume_to): New function and protype.
+       (darwin_resume, darwin_wait_to, darwin_wait): Ditto.
+       (darwin_kill_inferior): Add ops argument.
+       (darwin_pid_to_str): New function.
+       (darwin_thread_alive): Ditto.
+       (darwin_inf, darwin_not_port): Removed.
+       (darwin_inf_fake_stop): New variable.
+       (msgin, msgout, msg_state, exc_msg): Removed.
+       (mach_check_error): Use warning instead of error.
+       (darwin_ptrace): Adjust debug level.
+       (cmp_thread_t): Fix names (typo).
+       (darwin_check_new_threads): Argument is now an inferior,
+       adjust for new structures, add no change check, ignore dead ports,
+       handle first thread case.
+       (find_inferior_task_it): New function.
+       (find_inferior_notify_it): Ditto.
+       (darwin_find_inferior_by_task): Ditto.
+       (darwin_find_inferior_by_notify): Ditto.
+       (darwin_find_thread): Ditto.
+       (darwin_suspend_inferior): Ditto.
+       (darwin_resume_inferior): Ditto.
+       (catch_exception_raise_state): Removed.
+       (catch_exception_raise_state_identity): Removed.
+       (darwin_suspend_inferior_it): New function.
+       (darwin_resume_inferior_it): Ditto.
+       (darwin_dump_message): New function, extracted from darwin_wait.
+       (darwin_decode_exception_message): New function.
+       (darwin_encode_reply): New function.
+       (catch_exception_raise): Removed.
+       (darwin_send_reply): New function, extracted from darwin_resume.
+       (darwin_resume_thread): New function, extracted from darwin_resume.
+       (struct resume_inferior_threads_param): New type.
+       (darwin_resume_inferior_threads_it): New function.
+       (darwin_resume_inferior_threads): New function.
+       (darwin_suspend_inferior_threads): New function.
+       (darwin_resume): Mostly rewritten to handle multiple threads and
+       some corner cases.
+       (darwin_decode_message): New function extracted from darwin_wait.
+       (cancel_breakpoint): New function.
+       (darwin_wait): Mostly rewritten.  Handle multiple threads.
+       (darwin_mourn_inferior): Adjust for per process structures.
+       (darwin_reply_to_all_pending_messages): New function.
+       (darwin_stop_inferior): Adjust for per inferior structures.
+       (darwin_attach_pid): Ditto.
+       (darwin_init_thread_list): Ditto.
+       (darwin_attach): Ditto.
+       (darwin_detach): Ditto.
+       (darwin_files_info): Now empty.
+       (darwin_pid_to_str): Adjust returns string to match one expected by
+       the testsuite.
+       (darwin_read_write_inferior): Rename err variable to match other uses.
+       Adjust debug message.  Handle submaps.
+       (darwin_xfer_memory): Adjust for per inferior structures.
+       (set_enable_mach_exceptions): Ditto.
+       (darwin_pid_to_exec_file): New function.
+       (darwin_get_ada_task_ptid): Ditto.
+       (darwin_supports_multi_process): Ditto.
+       (_initialize_darwin_inferior): Remove useless assertion, adjust for
+       per inferior structures.  Add new target operations.
+
 2009-06-18  Hui Zhu  <teawater@gmail.com>
            Michael Snyder  <msnyder@vmware.com>
 
index c48d2fe..3b14006 100644 (file)
@@ -1,5 +1,5 @@
 /* Darwin support for GDB, the GNU debugger.
-   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2008, 2009
+   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2008
    Free Software Foundation, Inc.
 
    Contributed by Apple Computer, Inc.
@@ -8,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
+   the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,7 +17,9 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 /* The name of the ppc_thread_state structure, and the names of its
    members, have been changed for Unix conformance reasons.  The easiest
@@ -118,9 +120,9 @@ get_task_from_args (char *args)
 
   if (args == NULL || *args == 0)
     {
-      if (darwin_inf->task == TASK_NULL)
+      if (ptid_equal (inferior_ptid, null_ptid))
        printf_unfiltered (_("No inferior running\n"));
-      return darwin_inf->task;
+      return current_inferior ()->private->task;
     }
   if (strcmp (args, "gdb") == 0)
     return mach_task_self ();
@@ -252,25 +254,44 @@ info_mach_ports_command (char *args, int from_tty)
            printf_unfiltered (_(" gdb-task"));
          else if (port == darwin_host_self)
            printf_unfiltered (_(" host-self"));
-         else if (port == darwin_not_port)
-           printf_unfiltered (_(" gdb-notifier"));
          else if (port == darwin_ex_port)
            printf_unfiltered (_(" gdb-exception"));
          else if (port == darwin_port_set)
            printf_unfiltered (_(" gdb-port_set"));
-         else if (darwin_inf && port == darwin_inf->task)
-           printf_unfiltered (_(" inferior-task"));
-         else if (darwin_inf && darwin_inf->threads)
+         else if (!ptid_equal (inferior_ptid, null_ptid))
            {
-             int k;
-             thread_t t;
-             for (k = 0; VEC_iterate(thread_t, darwin_inf->threads, k, t); k++)
-               if (port == t)
-                 {
-                   printf_unfiltered (_(" inferior-thread for 0x%x"),
-                                      darwin_inf->task);
-                   break;
-                 }
+             struct inferior *inf = current_inferior ();
+
+             if (port == inf->private->task)
+               printf_unfiltered (_(" inferior-task"));
+             else if (port == inf->private->notify_port)
+               printf_unfiltered (_(" inferior-notify"));
+             else
+               {
+                 int k;
+                 darwin_thread_t *t;
+
+                 for (k = 0; k < inf->private->exception_info.count; k++)
+                   if (port == inf->private->exception_info.ports[k])
+                     {
+                       printf_unfiltered (_(" inferior-excp-port"));
+                       break;
+                     }
+
+                 if (inf->private->threads)
+                   {
+                     for (k = 0;
+                          VEC_iterate(darwin_thread_t,
+                                      inf->private->threads, k, t);
+                          k++)
+                       if (port == t->gdb_port)
+                         {
+                           printf_unfiltered (_(" inferior-thread for 0x%x"),
+                                              inf->private->task);
+                           break;
+                         }
+                   }
+               }
            }
        }
       printf_unfiltered (_("\n"));
@@ -600,12 +621,36 @@ darwin_debug_regions_recurse (task_t task)
   vm_region_submap_short_info_data_64_t r_info;
   kern_return_t kret;
   int ret;
+  struct cleanup *table_chain;
+
+  table_chain = make_cleanup_ui_out_table_begin_end (uiout, 9, -1, "regions");
+
+  if (gdbarch_addr_bit (current_gdbarch) <= 32)
+    {
+      ui_out_table_header (uiout, 10, ui_left, "start", "Start");
+      ui_out_table_header (uiout, 10, ui_left, "end", "End");
+    }
+  else
+    {
+      ui_out_table_header (uiout, 18, ui_left, "start", "Start");
+      ui_out_table_header (uiout, 18, ui_left, "end", "End");
+    }
+  ui_out_table_header (uiout, 3, ui_left, "min-prot", "Min");
+  ui_out_table_header (uiout, 3, ui_left, "max-prot", "Max");
+  ui_out_table_header (uiout, 5, ui_left, "inheritence", "Inh");
+  ui_out_table_header (uiout, 9, ui_left, "share-mode", "Shr");
+  ui_out_table_header (uiout, 1, ui_left, "depth", "D");
+  ui_out_table_header (uiout, 3, ui_left, "submap", "Sm");
+  ui_out_table_header (uiout, 0, ui_noalign, "tag", "Tag");
+
+  ui_out_table_body (uiout);
 
   r_start = 0;
   r_depth = 0;
   while (1)
     {
       const char *tag;
+      struct cleanup *row_chain;
 
       r_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
       r_size = -1;
@@ -614,25 +659,39 @@ darwin_debug_regions_recurse (task_t task)
                                     &r_info_size);
       if (kret != KERN_SUCCESS)
        break;
-      printf_filtered (_("%s-%s %s/%s  %-5s %-10s %2d %s"),
-                      paddr(r_start),
-                      paddr(r_start + r_size),
-                      unparse_protection (r_info.protection),
-                      unparse_protection (r_info.max_protection),
-                      unparse_inheritance (r_info.inheritance),
-                      unparse_share_mode (r_info.share_mode),
-                      r_depth,
-                      r_info.is_submap ? _("sm ") : _("obj"));
+      row_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "regions-row");
+
+      ui_out_field_core_addr (uiout, "start", r_start);
+      ui_out_field_core_addr (uiout, "end", r_start + r_size);
+      ui_out_field_string (uiout, "min-prot", 
+                          unparse_protection (r_info.protection));
+      ui_out_field_string (uiout, "max-prot", 
+                          unparse_protection (r_info.max_protection));
+      ui_out_field_string (uiout, "inheritence",
+                          unparse_inheritance (r_info.inheritance));
+      ui_out_field_string (uiout, "share-mode",
+                          unparse_share_mode (r_info.share_mode));
+      ui_out_field_int (uiout, "depth", r_depth);
+      ui_out_field_string (uiout, "submap",
+                          r_info.is_submap ? _("sm ") : _("obj"));
       tag = unparse_user_tag (r_info.user_tag);
       if (tag)
-       printf_unfiltered (_(" %s\n"), tag);
+       ui_out_field_string (uiout, "tag", tag);
       else
-       printf_unfiltered (_(" %u\n"), r_info.user_tag);
+       ui_out_field_int (uiout, "tag", r_info.user_tag);
+
+      do_cleanups (row_chain);
+
+      if (!ui_out_is_mi_like_p (uiout))
+       ui_out_text (uiout, "\n");
+
       if (r_info.is_submap)
        r_depth++;
       else
        r_start += r_size;
     }
+  do_cleanups (table_chain);
+
 }
 
 
@@ -672,6 +731,7 @@ info_mach_region_command (char *exp, int from_tty)
   struct expression *expr;
   struct value *val;
   mach_vm_address_t address;
+  struct inferior *inf;
 
   expr = parse_expression (exp);
   val = evaluate_expression (expr);
@@ -679,22 +739,13 @@ info_mach_region_command (char *exp, int from_tty)
     {
       val = value_ind (val);
     }
-  /* In rvalue contexts, such as this, functions are coerced into
-     pointers to functions. */
-  if (TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC
-      && VALUE_LVAL (val) == lval_memory)
-    {
-      address = value_address (val);
-    }
-  else
-    {
-      address = value_as_address (val);
-    }
+  address = value_as_address (val);
 
-  if ((!darwin_inf) || (darwin_inf->task == TASK_NULL))
+  if (ptid_equal (inferior_ptid, null_ptid))
     error (_("Inferior not available"));
 
-  darwin_debug_region (darwin_inf->task, address);
+  inf = current_inferior ();
+  darwin_debug_region (inf->private->task, address);
 }
 
 static void
@@ -761,9 +812,9 @@ info_mach_exceptions_command (char *args, int from_tty)
     {
       if (strcmp (args, "saved") == 0)
        {
-         if (darwin_inf->task == TASK_NULL)
-           error (_("No inferior running\n"));
-         disp_exception (&darwin_inf->exception_info);
+         if (ptid_equal (inferior_ptid, null_ptid))
+           printf_unfiltered (_("No inferior running\n"));
+         disp_exception (&current_inferior ()->private->exception_info);
          return;
        }
       else if (strcmp (args, "host") == 0)
@@ -780,11 +831,14 @@ info_mach_exceptions_command (char *args, int from_tty)
     }
   else
     {
-      if (darwin_inf->task == TASK_NULL)
-       error (_("No inferior running\n"));
+      struct inferior *inf;
+
+      if (ptid_equal (inferior_ptid, null_ptid))
+       printf_unfiltered (_("No inferior running\n"));
+      inf = current_inferior ();
       
       kret = task_get_exception_ports
-       (darwin_inf->task, EXC_MASK_ALL, info.masks,
+       (inf->private->task, EXC_MASK_ALL, info.masks,
         &info.count, info.ports, info.behaviors, info.flavors);
       MACH_CHECK_ERROR (kret);
       disp_exception (&info);
index 3246881..2b45689 100644 (file)
@@ -51,6 +51,8 @@
 #include <sys/param.h>
 #include <sys/sysctl.h>
 #include <sys/proc.h>
+#include <libproc.h>
+#include <sys/syscall.h>
 
 #include <mach/mach_error.h>
 #include <mach/mach_vm.h>
@@ -86,6 +88,15 @@ 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 target_signal signal);
+static void darwin_resume (ptid_t ptid, int step,
+                          enum target_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 int darwin_lookup_task (char *args, task_t * ptask, int *ppid);
@@ -101,8 +112,9 @@ static void darwin_create_inferior (struct target_ops *ops, char *exec_file,
 
 static void darwin_files_info (struct target_ops *ops);
 
-/* Current inferior.  */
-darwin_inferior *darwin_inf = NULL;
+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);
 
 /* Target operations for Darwin.  */
 static struct target_ops *darwin_ops;
@@ -116,9 +128,6 @@ mach_port_t darwin_host_self;
 /* Exception port.  */
 mach_port_t darwin_ex_port;
 
-/* Notification port.  */
-mach_port_t darwin_not_port;
-
 /* Port set.  */
 mach_port_t darwin_port_set;
 
@@ -129,47 +138,13 @@ static vm_size_t mach_page_size;
    by the kernel).  */
 static int enable_mach_exceptions;
 
+/* Inferior that should report a fake stop event.  */
+static struct inferior *darwin_inf_fake_stop;
+
 #define PAGE_TRUNC(x) ((x) & ~(mach_page_size - 1))
 #define PAGE_ROUND(x) PAGE_TRUNC((x) + mach_page_size - 1)
 
-/* Buffer containing received message and to be sent message.  */
-static union
-{
-  mach_msg_header_t hdr;
-  char data[1024];
-} msgin, msgout;
-
-/* Current message state.
-   If the kernel has sent a message it expects a reply and the inferior
-   can't be killed before.  */
-static enum msg_state { NO_MESSAGE, GOT_MESSAGE, REPLY_SENT } msg_state;
-
-/* Unmarshalled received message.  */
-static struct exc_msg
-{
-  /* Receive port.  */
-  mach_port_t port;
-
-  /* Thread and task taking the exception.  */
-  mach_port_t thread_port;
-  mach_port_t task_port;
-
-  /* Type of the exception.  */
-  exception_type_t ex_type;
-
-  /* Machine dependent details.  */
-  mach_msg_type_number_t data_count;
-  integer_t ex_data[4];
-} exc_msg;
-
-
-/* This controls output of inferior debugging.
-   1 = basic exception handling
-   2 = task management
-   3 = thread management
-   4 = pending_event_handler
-   6 = most chatty level.  */
-
+/* This controls output of inferior debugging.  */
 static int darwin_debug_flag = 0;
 
 static void
@@ -194,9 +169,9 @@ mach_check_error (kern_return_t ret, const char *file,
     return;
   if (func == NULL)
     func = _("[UNKNOWN]");
-  
-  error (_("error on line %u of \"%s\" in function \"%s\": %s (0x%lx)\n"),
-         line, file, func, mach_error_string (ret), (unsigned long) ret);
+
+  warning (_("Mach error at \"%s:%u\" in function \"%s\": %s (0x%lx)\n"),
+          file, line, func, mach_error_string (ret), (unsigned long) ret);
 }
 
 static const char *
@@ -240,7 +215,7 @@ darwin_ptrace (const char *name,
 
   ret = ptrace (request, pid, (caddr_t) arg3, arg4);
 
-  inferior_debug (2, _("ptrace (%s, %d, 0x%x, %d): %d (%s)\n"),
+  inferior_debug (4, _("ptrace (%s, %d, 0x%x, %d): %d (%s)\n"),
                   name, pid, arg3, arg4, ret,
                   (ret != 0) ? safe_strerror (errno) : _("no error"));
   return ret;
@@ -249,13 +224,13 @@ darwin_ptrace (const char *name,
 static int
 cmp_thread_t (const void *l, const void *r)
 {
-  thread_t lt = *(const thread_t *)l;
-  thread_t lr = *(const thread_t *)r;
-  return (int)(lr - lt);
+  thread_t tl = *(const thread_t *)l;
+  thread_t tr = *(const thread_t *)r;
+  return (int)(tl - tr);
 }
 
 static void
-darwin_check_new_threads (darwin_inferior *inf)
+darwin_check_new_threads (struct inferior *inf)
 {
   kern_return_t kret;
   unsigned int i;
@@ -263,35 +238,58 @@ darwin_check_new_threads (darwin_inferior *inf)
   unsigned int new_nbr;
   unsigned int old_nbr;
   unsigned int new_ix, old_ix;
-  VEC (thread_t) *thread_vec;
+  darwin_inferior *darwin_inf = inf->private;
+  VEC (darwin_thread_t) *thread_vec;
 
   /* Get list of threads.  */
-  kret = task_threads (inf->task, &thread_list, &new_nbr);
+  kret = task_threads (darwin_inf->task, &thread_list, &new_nbr);
   MACH_CHECK_ERROR (kret);
   if (kret != KERN_SUCCESS)
     return;
 
+  /* Sort the list.  */
   if (new_nbr > 1)
     qsort (thread_list, new_nbr, sizeof (thread_t), cmp_thread_t);
 
-  thread_vec = VEC_alloc (thread_t, new_nbr);
-
-  if (inf->threads)
-    old_nbr = VEC_length (thread_t, inf->threads);
+  if (darwin_inf->threads)
+    old_nbr = VEC_length (darwin_thread_t, darwin_inf->threads);
   else
     old_nbr = 0;
 
+  /* Quick check for no changes.  */
+  if (old_nbr == new_nbr)
+    {
+      for (i = 0; i < new_nbr; i++)
+       if (thread_list[i]
+           != VEC_index (darwin_thread_t, darwin_inf->threads, i)->gdb_port)
+         break;
+      if (i == new_nbr)
+       {
+         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);
+
   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;
-      thread_t old_id = (old_ix < old_nbr) ?
-       VEC_index (thread_t, inf->threads, old_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;
+
+      inferior_debug
+       (12, _(" new_ix:%d/%d, old_ix:%d/%d, new_id:%x old_id:%x\n"),
+        new_ix, new_nbr, old_ix, old_nbr, new_id, old_id);
 
       if (old_id == new_id)
        {
          /* Thread still exist.  */
-         VEC_safe_push (thread_t, thread_vec, old_id);
+         VEC_safe_push (darwin_thread_t, thread_vec, old);
          new_ix++;
          old_ix++;
 
@@ -299,251 +297,559 @@ darwin_check_new_threads (darwin_inferior *inf)
          MACH_CHECK_ERROR (kret);
          continue;
        }
-      if (new_id < old_id || old_ix == old_nbr)
+      if (new_ix < new_nbr && new_id == MACH_PORT_DEAD)
+       {
+         /* Ignore dead ports.
+            In some weird cases, we might get dead ports.  They should
+            correspond to dead thread so they could safely be ignored.  */
+         new_ix++;
+         continue;
+       }
+      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;
 
-         tp = add_thread (ptid_build (inf->pid, 0, new_id));
-         VEC_safe_push (thread_t, thread_vec, new_id);
+         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);
          new_ix++;
          continue;
        }
-      if (new_id > old_id || new_ix == new_nbr)
+      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));
          kret = mach_port_deallocate (gdb_task, old_id);
          MACH_CHECK_ERROR (kret);
          old_ix++;
+         continue;
        }
+      gdb_assert (0);
     }
 
-  if (inf->threads)
-    VEC_free (thread_t, inf->threads);
-  inf->threads = thread_vec;
+  if (darwin_inf->threads)
+    VEC_free (darwin_thread_t, darwin_inf->threads);
+  darwin_inf->threads = thread_vec;
 
   kret = vm_deallocate (gdb_task, (vm_address_t) thread_list,
                        new_nbr * sizeof (int));
   MACH_CHECK_ERROR (kret);
 }
 
-static void
-darwin_stop (ptid_t t)
+static int
+find_inferior_task_it (struct inferior *inf, void *port_ptr)
 {
-  int ret;
+  return inf->private->task == *(task_t*)port_ptr;
+}
 
-  ret = kill (ptid_get_pid (inferior_ptid), SIGINT);
+static int
+find_inferior_notify_it (struct inferior *inf, void *port_ptr)
+{
+  return inf->private->notify_port == *(task_t*)port_ptr;
 }
 
-static void
-darwin_resume (struct target_ops *ops,
-              ptid_t ptid, int step, enum target_signal signal)
+/* Return an inferior by task port.  */
+static struct inferior *
+darwin_find_inferior_by_task (task_t port)
 {
-  struct target_waitstatus status;
-  int pid;
-  thread_t thread;
-  kern_return_t kret;
-  int res;
+  return iterate_over_inferiors (&find_inferior_task_it, &port);
+}
 
-  /* minus_one_ptid is RESUME_ALL.  */
-  if (ptid_equal (ptid, minus_one_ptid))
-    ptid = inferior_ptid;
+/* Return an inferior by notification port.  */
+static struct inferior *
+darwin_find_inferior_by_notify (mach_port_t port)
+{
+  return iterate_over_inferiors (&find_inferior_notify_it, &port);
+}
 
-  pid = ptid_get_pid (ptid);
-  thread = ptid_get_tid (ptid);
+/* 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->private->threads, k, t);
+       k++)
+    if (t->gdb_port == thread)
+      return t;
+  return NULL;
+}
 
-  inferior_debug
-    (2, _("darwin_resume: state=%d, thread=0x%x, step=%d signal=%d\n"),
-     msg_state, thread, step, signal);
+/* Suspend (ie stop) an inferior at Mach level.  */
 
-  switch (msg_state)
+static void
+darwin_suspend_inferior (struct inferior *inf)
+{
+  if (!inf->private->suspended)
     {
-    case GOT_MESSAGE:
-      switch (exc_msg.ex_type)
-       {
-       case EXC_SOFTWARE:
-         if (exc_msg.ex_data[0] == EXC_SOFT_SIGNAL)
-           {
-             int nsignal = target_signal_to_host (signal);
-             res = PTRACE (PT_THUPDATE, pid,
-                           (void *)(uintptr_t)exc_msg.thread_port, nsignal);
-             if (res < 0)
-               printf_unfiltered (_("ptrace THUP: res=%d\n"), res);
-           }
-         break;
+      kern_return_t kret;
 
-       default:
-         break;
-       }
-         
-      if (thread != 0)
-       {
-         inferior_debug (2, _("darwin_set_sstep (thread=%x, enable=%d)\n"),
-                         thread, step);
-         darwin_set_sstep (thread, step);
-       }
+      kret = task_suspend (inf->private->task);
+      MACH_CHECK_ERROR (kret);
 
-      kret = mach_msg (&msgout.hdr, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
-                      msgout.hdr.msgh_size, 0,
-                      MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
-                      MACH_PORT_NULL);
-      if (kret != 0)
-       printf_unfiltered (_("mach_msg (reply) ret=%d\n"), kret);
+      inf->private->suspended = 1;
+    }
+}
 
-      msg_state = REPLY_SENT;
-      break;
+/* Resume an inferior at Mach level.  */
 
-    case NO_MESSAGE:
-      if (step)
-       res = PTRACE (PT_STEP, pid, (caddr_t)1, 0);
-      else
-       res = PTRACE (PT_CONTINUE, pid, (caddr_t)1, 0);
-      break;
+static void
+darwin_resume_inferior (struct inferior *inf)
+{
+  if (inf->private->suspended)
+    {
+      kern_return_t kret;
 
-    default:
-      gdb_assert (0);
+      kret = task_resume (inf->private->task);
+      MACH_CHECK_ERROR (kret);
+
+      inf->private->suspended = 0;
     }
 }
 
-kern_return_t
-catch_exception_raise_state
-  (mach_port_t port,
-   exception_type_t exception_type, mach_exception_data_t exception_data,
-   mach_msg_type_number_t data_count, thread_state_flavor_t * state_flavor,
-   thread_state_t in_state, mach_msg_type_number_t in_state_count,
-   thread_state_t out_state, mach_msg_type_number_t out_state_count)
+/* Iterator functions.  */
+
+static int
+darwin_suspend_inferior_it (struct inferior *inf, void *arg)
 {
-  return KERN_FAILURE;
+  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;
 }
 
-kern_return_t
-catch_exception_raise_state_identity
-  (mach_port_t port, mach_port_t thread_port, mach_port_t task_port,
-   exception_type_t exception_type, mach_exception_data_t exception_data,
-   mach_msg_type_number_t data_count, thread_state_flavor_t * state_flavor,
-   thread_state_t in_state, mach_msg_type_number_t in_state_count,
-   thread_state_t out_state, mach_msg_type_number_t out_state_count)
+static void
+darwin_dump_message (mach_msg_header_t *hdr, int disp_body)
+{
+  printf_unfiltered (_("message header:\n"));
+  printf_unfiltered (_(" bits: 0x%x\n"), hdr->msgh_bits);
+  printf_unfiltered (_(" size: 0x%x\n"), hdr->msgh_size);
+  printf_unfiltered (_(" remote-port: 0x%x\n"), hdr->msgh_remote_port);
+  printf_unfiltered (_(" local-port: 0x%x\n"), hdr->msgh_local_port);
+  printf_unfiltered (_(" reserved: 0x%x\n"), hdr->msgh_reserved);
+  printf_unfiltered (_(" id: 0x%x\n"), hdr->msgh_id);
+
+  if (disp_body)
+    {
+      const unsigned char *data;
+      const unsigned long *ldata;
+      int size;
+      int i;
+
+      data = (unsigned char *)(hdr + 1);
+      size = hdr->msgh_size - sizeof (mach_msg_header_t);
+
+      if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+       {
+         mach_msg_body_t *bod = (mach_msg_body_t*)data;
+         mach_msg_port_descriptor_t *desc =
+           (mach_msg_port_descriptor_t *)(bod + 1);
+         int k;
+         NDR_record_t *ndr;
+         printf_unfiltered (_("body: descriptor_count=%u\n"),
+                            bod->msgh_descriptor_count);
+         data += sizeof (mach_msg_body_t);
+         size -= sizeof (mach_msg_body_t);
+         for (k = 0; k < bod->msgh_descriptor_count; k++)
+           switch (desc[k].type)
+             {
+             case MACH_MSG_PORT_DESCRIPTOR:
+               printf_unfiltered
+                 (_(" descr %d: type=%u (port) name=0x%x, dispo=%d\n"),
+                  k, desc[k].type, desc[k].name, desc[k].disposition);
+               break;
+             default:
+               printf_unfiltered (_(" descr %d: type=%u\n"),
+                                  k, desc[k].type);
+               break;
+             }
+         data += bod->msgh_descriptor_count
+           * sizeof (mach_msg_port_descriptor_t);
+         size -= bod->msgh_descriptor_count
+           * sizeof (mach_msg_port_descriptor_t);
+         ndr = (NDR_record_t *)(desc + bod->msgh_descriptor_count);
+         printf_unfiltered
+           (_("NDR: mig=%02x if=%02x encod=%02x "
+              "int=%02x char=%02x float=%02x\n"),
+            ndr->mig_vers, ndr->if_vers, ndr->mig_encoding,
+            ndr->int_rep, ndr->char_rep, ndr->float_rep);
+         data += sizeof (NDR_record_t);
+         size -= sizeof (NDR_record_t);
+       }
+
+      printf_unfiltered (_("  data:"));
+      ldata = (const unsigned long *)data;
+      for (i = 0; i < size / sizeof (unsigned long); i++)
+       printf_unfiltered (" %08lx", ldata[i]);
+      printf_unfiltered (_("\n"));
+    }
+}
+
+static int
+darwin_decode_exception_message (mach_msg_header_t *hdr,
+                                struct 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);
+  NDR_record_t *ndr;
+  integer_t *data;
+  struct inferior *inf;
+  darwin_thread_t *thread;
+  task_t task_port;
+  thread_t thread_port;
   kern_return_t kret;
+  int i;
 
+  /* Check message identifier.  2401 is exc.  */
+  if (hdr->msgh_id != 2401)
+    return -1;
+
+  /* Check message header.  */
+  if (!(hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX))
+    return -1;
+
+  /* Check descriptors.  */
+  if (hdr->msgh_size < (sizeof (*hdr) + sizeof (*bod) + 2 * sizeof (*desc)
+                       + sizeof (*ndr) + 2 * sizeof (integer_t))
+      || bod->msgh_descriptor_count != 2
+      || desc[0].type != MACH_MSG_PORT_DESCRIPTOR
+      || desc[0].disposition != MACH_MSG_TYPE_MOVE_SEND
+      || desc[1].type != MACH_MSG_PORT_DESCRIPTOR
+      || desc[1].disposition != MACH_MSG_TYPE_MOVE_SEND)
+    return -1;
+
+  /* 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)
+    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;
+  inf = darwin_find_inferior_by_task (task_port);
+  if (inf == NULL)
+    return -1;
+  *pinf = inf;
+
+  /* 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);
   kret = mach_port_deallocate (mach_task_self (), thread_port);
   MACH_CHECK_ERROR (kret);
 
-  return KERN_FAILURE;
+  thread = darwin_find_thread (inf, thread_port);
+  if (thread == NULL)
+    return -1;
+  *pthread = thread;
+
+  /* Finish decoding.  */
+  gdb_assert (thread->msg_state == DARWIN_RUNNING);
+  thread->event.header = *hdr;
+  thread->event.thread_port = thread_port;
+  thread->event.task_port = task_port;
+  thread->event.ex_type = data[0];
+  thread->event.data_count = data[1];
+
+  if (hdr->msgh_size < (sizeof (*hdr) + sizeof (*bod) + 2 * sizeof (*desc)
+                       + sizeof (*ndr) + 2 * sizeof (integer_t)
+                       + data[1] * sizeof (integer_t)))
+      return -1;
+  for (i = 0; i < data[1]; i++)
+    thread->event.ex_data[i] = data[2 + i];
+
+  thread->msg_state = DARWIN_MESSAGE;
+
+  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_remote_port = hdr->msgh_remote_port;
+  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;
+
+  reply->NDR = NDR_record;
+  reply->RetCode = code;
 }
 
-kern_return_t
-catch_exception_raise (mach_port_t port,
-                      mach_port_t thread_port,
-                      mach_port_t task_port,
-                      exception_type_t exception_type,
-                      exception_data_t exception_data,
-                      mach_msg_type_number_t data_count)
+static void
+darwin_send_reply (struct inferior *inf, darwin_thread_t *thread)
 {
   kern_return_t kret;
-  int i;
-  int res;
+  mig_reply_error_t reply;
 
-  /* We got new rights to the task.  Get rid of it.  */
-  kret = mach_port_deallocate (mach_task_self (), task_port);
+  darwin_encode_reply (&reply, &thread->event.header, 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);
 
+  inf->private->pending_messages--;
+}
+
+static void
+darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
+                     int step, int nsignal)
+{
+  kern_return_t kret;
+  int res;
+
   inferior_debug
-    (7, _("catch_exception_raise: exception_type=%d, data_count=%d\n"),
-     exception_type, data_count);
-  if (darwin_debug_flag > 7)
+    (3, _("darwin_resume_thread: state=%d, thread=0x%x, step=%d nsignal=%d\n"),
+     thread->msg_state, thread->gdb_port, step, nsignal);
+
+  switch (thread->msg_state)
     {
-      for (i = 0; i < data_count; i++)
-       printf_unfiltered (" %08x", exception_data[i]);
-      printf_unfiltered ("\n");
+    case DARWIN_MESSAGE:
+      if (thread->event.ex_type == EXC_SOFTWARE
+         && thread->event.ex_data[0] == EXC_SOFT_SIGNAL)
+       {
+         /* Either deliver a new signal or cancel the signal received.  */
+         res = PTRACE (PT_THUPDATE, inf->pid,
+                       (void *)(uintptr_t)thread->gdb_port, nsignal);
+         if (res < 0)
+           inferior_debug (1, _("ptrace THUP: res=%d\n"), res);
+       }
+      else if (nsignal)
+       {
+         /* 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);
+         inferior_debug (4, _("darwin_resume_thread: kill 0x%x %d: %d\n"),
+                         thread->gdb_port, nsignal, res);
+         thread->signaled = 1;
+       }
+
+      /* Set single step.  */
+      inferior_debug (4, _("darwin_set_sstep (thread=%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;
+      break;
+
+    case DARWIN_RUNNING:
+      break;
+
+    case DARWIN_STOPPED:
+      kret = thread_resume (thread->gdb_port);
+      MACH_CHECK_ERROR (kret);
+
+      thread->msg_state = DARWIN_RUNNING;
+      break;
     }
+}
 
-  /* Save the message.
-     FIXME: this should be in a per-thread variable.  */
-  exc_msg.port = port;
-  exc_msg.thread_port = thread_port;
-  exc_msg.task_port = task_port;
-  exc_msg.ex_type = exception_type;
-  exc_msg.data_count = data_count;
-  for (i = 0; i < data_count && i < 4; i++)
-    exc_msg.ex_data[i] = exception_data[i];
+/* Resume all threads of the inferior.  */
 
-  return KERN_SUCCESS;
+static void
+darwin_resume_inferior_threads (struct inferior *inf, int step, int nsignal)
+{
+  darwin_thread_t *thread;
+  int k;
+
+  for (k = 0;
+       VEC_iterate (darwin_thread_t, inf->private->threads, k, thread);
+       k++)
+    darwin_resume_thread (inf, thread, step, nsignal);
 }
 
-static ptid_t
-darwin_wait (struct target_ops *ops,
-            ptid_t ptid, struct target_waitstatus *status, int options)
+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;
+}
+
+/* Suspend all threads of INF.  */
+
+static void
+darwin_suspend_inferior_threads (struct inferior *inf)
+{
+  darwin_thread_t *thread;
   kern_return_t kret;
-  mach_msg_header_t *hdr = &msgin.hdr;
-  pid_t pid = ptid_get_pid (inferior_ptid); /* FIXME.  */
+  int k;
+
+  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;
+      }
+}
 
-  gdb_assert (msg_state != GOT_MESSAGE);
+static void
+darwin_resume (ptid_t ptid, int step, enum target_signal signal)
+{
+  struct target_waitstatus status;
+  int pid;
 
-  inferior_debug (6, _("darwin_wait: waiting for a message\n"));
+  kern_return_t kret;
+  int res;
+  int nsignal;
+  struct inferior *inf;
 
-  /* Wait for a message.  */
-  kret = mach_msg (&msgin.hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0,
-                  sizeof (msgin.data), darwin_port_set, 0, MACH_PORT_NULL);
+  inferior_debug
+    (2, _("darwin_resume: pid=%d, tid=0x%x, step=%d, signal=%d\n"),
+     ptid_get_pid (ptid), ptid_get_tid (ptid), step, signal);
+
+  if (signal == TARGET_SIGNAL_0)
+    nsignal = 0;
+  else
+    nsignal = target_signal_to_host (signal);
 
-  if (kret == MACH_RCV_INTERRUPTED)
+  /* Don't try to single step all threads.  */
+  if (step)
+    ptid = inferior_ptid;
+
+  /* minus_one_ptid is RESUME_ALL.  */
+  if (ptid_equal (ptid, minus_one_ptid))
     {
-      status->kind = TARGET_WAITKIND_IGNORE;
-      return minus_one_ptid;
-    }
+      struct resume_inferior_threads_param param;
+
+      param.nsignal = nsignal;
+      param.step = step;
 
-  if (kret != MACH_MSG_SUCCESS)
+      /* Resume threads.  */
+      iterate_over_inferiors (darwin_resume_inferior_threads_it, &param);
+      /* Resume tasks.  */
+      iterate_over_inferiors (darwin_resume_inferior_it, NULL);
+    }
+  else
     {
-      inferior_debug (1, _("mach_msg: ret=%x\n"), kret);
-      status->kind = TARGET_WAITKIND_SPURIOUS;
-      return minus_one_ptid;
+      struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid));
+      long tid = ptid_get_tid (ptid);
+
+      /* Stop the inferior (should be useless).  */
+      darwin_suspend_inferior (inf);
+
+      if (tid == 0)
+        darwin_resume_inferior_threads (inf, step, nsignal);
+      else
+        {
+          darwin_thread_t *thread;
+
+          /* Suspend threads of the task.  */
+          darwin_suspend_inferior_threads (inf);
+
+          /* Resume the selected thread.  */
+          thread = darwin_find_thread (inf, tid);
+          gdb_assert (thread);
+          darwin_resume_thread (inf, thread, step, nsignal);
+        }
+
+      /* Resume the task.  */
+      darwin_resume_inferior (inf);
     }
+}
 
-  /* Debug: display message.  */
-  if (darwin_debug_flag > 10)
-   {
-     const unsigned long *buf = (unsigned long *) hdr;
-     unsigned int i;
-     
-     printf_unfiltered (_(" bits: 0x%x"), hdr->msgh_bits);
-     printf_unfiltered (_(", size: 0x%x"), hdr->msgh_size);
-     printf_unfiltered (_(", remote-port: 0x%x"), hdr->msgh_remote_port);
-     printf_unfiltered (_(", local-port: 0x%x"), hdr->msgh_local_port);
-     printf_unfiltered (_(", reserved: 0x%x"), hdr->msgh_reserved);
-     printf_unfiltered (_(", id: 0x%x\n"), hdr->msgh_id);
-
-     if (darwin_debug_flag > 11)
-       {
-         printf_unfiltered (_("  data:"));
-         for (i = 0; i < hdr->msgh_size; i++)
-           printf_unfiltered (" %08lx", buf[i]);
-         printf_unfiltered (_("\n"));
-       }
-   }
+static void
+darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
+                  enum target_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)
+{
+  darwin_thread_t *thread;
+  struct inferior *inf;
 
   /* Exception message.  */
   if (hdr->msgh_local_port == darwin_ex_port)
     {
-      /* Handle it via the exception server.  */
-      if (!exc_server (&msgin.hdr, &msgout.hdr))
+      int res;
+
+      /* Decode message.  */
+      res = darwin_decode_exception_message (hdr, &inf, &thread);
+
+      if (res < 0)
        {
-         printf_unfiltered (_("exc_server: unknown message (id=%x)\n"),
+         /* Should not happen...  */
+         printf_unfiltered (_("darwin_wait: ill-formatted message (id=%x)\n"),
                             hdr->msgh_id);
+         /* FIXME: send a failure reply?  */
          status->kind = TARGET_WAITKIND_SPURIOUS;
          return minus_one_ptid;
        }
+      *pinf = inf;
+      *pthread = thread;
+      inf->private->pending_messages++;
 
       status->kind = TARGET_WAITKIND_STOPPED;
+      thread->msg_state = DARWIN_MESSAGE;
+
+      inferior_debug (4, _("darwin_wait: thread=%x, got %s\n"),
+                     thread->gdb_port,
+                     unparse_exception_type (thread->event.ex_type));
 
-      inferior_debug (2, _("darwin_wait: thread=%x, got %s\n"),
-                     exc_msg.thread_port, 
-                     unparse_exception_type (exc_msg.ex_type));
-  
-      switch (exc_msg.ex_type)
+      switch (thread->event.ex_type)
        {
        case EXC_BAD_ACCESS:
          status->value.sig = TARGET_EXC_BAD_ACCESS;
@@ -558,15 +864,26 @@ darwin_wait (struct target_ops *ops,
          status->value.sig = TARGET_EXC_EMULATION;
          break;
        case EXC_SOFTWARE:
-         if (exc_msg.ex_data[0] == EXC_SOFT_SIGNAL)
+         if (thread->event.ex_data[0] == EXC_SOFT_SIGNAL)
            {
-             status->value.sig = target_signal_from_host (exc_msg.ex_data[1]);
-             inferior_debug (2, _("  (signal %d: %s)\n"),
-                             exc_msg.ex_data[1],
+             status->value.sig =
+               target_signal_from_host (thread->event.ex_data[1]);
+             inferior_debug (5, _("  (signal %d: %s)\n"),
+                             thread->event.ex_data[1],
                              target_signal_to_name (status->value.sig));
+
+             /* If the thread is stopped because it has received a signal
+                that gdb has just sent, continue.  */
+             if (thread->signaled)
+               {
+                 thread->signaled = 0;
+                 darwin_send_reply (inf, thread);
+                 thread->msg_state = DARWIN_RUNNING;
+                 status->kind = TARGET_WAITKIND_IGNORE;
+               }
            }
          else
-            status->value.sig = TARGET_EXC_SOFTWARE;
+           status->value.sig = TARGET_EXC_SOFTWARE;
          break;
        case EXC_BREAKPOINT:
          /* Many internal GDB routines expect breakpoints to be reported
@@ -579,38 +896,216 @@ darwin_wait (struct target_ops *ops,
          break;
        }
 
-      msg_state = GOT_MESSAGE;
+      return ptid_build (inf->pid, 0, thread->gdb_port);
+    }
+
+  *pinf = NULL;
+  *pthread = NULL;
+
+  inf = darwin_find_inferior_by_notify (hdr->msgh_local_port);
+  if (inf != NULL)
+    {
+      if (!inf->private->no_ptrace)
+       {
+         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_SPURIOUS;
+             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 = WTERMSIG (wstatus);
+           }
+
+         inferior_debug (4, _("darwin_wait: pid=%d exit, status=%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: %x\n"), hdr->msgh_local_port);
+  status->kind = TARGET_WAITKIND_SPURIOUS;
+  return minus_one_ptid;
+}
+
+static int
+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
+     breakpoint will trap again.
+
+     If we do not do this, then we run the risk that the user will
+     delete or disable the breakpoint, but the thread will have already
+     tripped on it.  */
+
+  struct regcache *regcache = get_thread_regcache (ptid);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  CORE_ADDR pc;
 
-      return ptid_build (pid, 0, exc_msg.thread_port);
+  pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch);
+  if (breakpoint_inserted_here_p (pc))
+    {
+      inferior_debug (4, "cancel_breakpoint for thread %x\n",
+                     ptid_get_tid (ptid));
+
+      /* Back up the PC if necessary.  */
+      if (gdbarch_decr_pc_after_break (gdbarch))
+       regcache_write_pc (regcache, pc);
+
+      return 1;
     }
-  else if (hdr->msgh_local_port == darwin_not_port)
+  return 0;
+}
+
+static ptid_t
+darwin_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+  kern_return_t kret;
+  union
+  {
+    mach_msg_header_t hdr;
+    char data[0x100];
+  } msgin;
+  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));
+
+  /* Handle fake stop events at first.  */
+  if (darwin_inf_fake_stop != NULL)
+    {
+      inf = darwin_inf_fake_stop;
+      darwin_inf_fake_stop = NULL;
+
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      thread = VEC_index (darwin_thread_t, inf->private->threads, 0);
+      thread->msg_state = DARWIN_STOPPED;
+      return ptid_build (inf->pid, 0, thread->gdb_port);
+    }
+
+  do
+    {
+      /* set_sigint_trap (); */
+
+      /* Wait for a message.  */
+      kret = mach_msg (&msgin.hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0,
+                      sizeof (msgin.data), darwin_port_set, 0, MACH_PORT_NULL);
+
+      /* clear_sigint_trap (); */
+
+      if (kret == MACH_RCV_INTERRUPTED)
+       {
+         status->kind = TARGET_WAITKIND_IGNORE;
+         return minus_one_ptid;
+       }
+
+      if (kret != MACH_MSG_SUCCESS)
+       {
+         inferior_debug (5, _("mach_msg: ret=%x\n"), kret);
+         status->kind = TARGET_WAITKIND_SPURIOUS;
+         return minus_one_ptid;
+       }
+
+      /* Debug: display message.  */
+      if (darwin_debug_flag > 10)
+       darwin_dump_message (hdr, darwin_debug_flag > 11);
+
+      res = darwin_decode_message (hdr, &thread, &inf, status);
+
+      if (inf == NULL)
+       return res;
+    }
+  while (status->kind == TARGET_WAITKIND_IGNORE);
+
+  /* Stop all tasks.  */
+  iterate_over_inferiors (darwin_suspend_inferior_it, NULL);
+
+  /* Read pending messages.  */
+  while (1)
     {
-      pid_t res;
-      int wstatus;
+      struct target_waitstatus status2;
+      ptid_t ptid2;
+
+      kret = mach_msg (&msgin.hdr,
+                      MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
+                      sizeof (msgin.data), darwin_port_set, 1, MACH_PORT_NULL);
+
+      if (kret == MACH_RCV_TIMED_OUT)
+       break;
+      if (kret != MACH_MSG_SUCCESS)
+       {
+         inferior_debug
+           (5, _("darwin_wait: mach_msg(pending) ret=%x\n"), kret);
+         break;
+       }
+
+      ptid2 = darwin_decode_message (hdr, &thread, &inf, &status2);
 
-      /* FIXME: translate task port to pid.  */
-      res = wait4 (pid, &wstatus, 0, NULL);
-      if (res != pid)
+      if (inf != NULL && thread != NULL
+         && thread->event.ex_type == EXC_BREAKPOINT)
        {
-         printf_unfiltered (_("wait4: res=%x\n"), res);
-         wstatus = 0;
+         if (thread->single_step
+             || cancel_breakpoint (ptid_build (inf->pid, 0, thread->gdb_port)))
+           {
+             gdb_assert (thread->msg_state == DARWIN_MESSAGE);
+             darwin_send_reply (inf, thread);
+             thread->msg_state = DARWIN_RUNNING;
+           }
+         else
+           inferior_debug
+             (3, _("darwin_wait: thread %x hit a non-gdb breakpoint\n"),
+              thread->gdb_port);
        }
-      status->kind = TARGET_WAITKIND_EXITED;
-      status->value.integer = WEXITSTATUS (wstatus);
+      else
+       inferior_debug (3, _("darwin_wait: unhandled pending message\n"));
+    }
+  return res;
+}
 
-      inferior_debug (2, _("darwin_wait: pid=%d exit, status=%x\n"),
-                     pid, wstatus);
+static ptid_t
+darwin_wait_to (struct target_ops *ops, 
+                ptid_t ptid, struct target_waitstatus *status, int options)
+{
+  return darwin_wait (ptid, status);
+}
 
-      msg_state = NO_MESSAGE;
+static void
+darwin_stop (ptid_t t)
+{
+  struct inferior *inf = current_inferior ();
 
-      return ptid;
-    }
-  else
-    {
-      printf_unfiltered (_("Bad local-port: %x\n"), hdr->msgh_local_port);
-      status->kind = TARGET_WAITKIND_SPURIOUS;
-      return minus_one_ptid;
-    }
+  /* FIXME: handle in no_ptrace mode.  */
+  gdb_assert (!inf->private->no_ptrace);
+  kill (inf->pid, SIGINT);
 }
 
 static void
@@ -624,76 +1119,79 @@ darwin_mourn_inferior (struct target_ops *ops)
   unpush_target (darwin_ops);
 
   /* Deallocate threads.  */
-  if (darwin_inf->threads)
+  if (inf->private->threads)
     {
       int k;
-      thread_t t;
-      for (k = 0; VEC_iterate (thread_t, darwin_inf->threads, k, t); 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);
+         kret = mach_port_deallocate (gdb_task, t->gdb_port);
          MACH_CHECK_ERROR (kret);
        }
-      VEC_free (thread_t, darwin_inf->threads);
-      darwin_inf->threads = NULL;
+      VEC_free (darwin_thread_t, inf->private->threads);
+      inf->private->threads = NULL;
     }
 
-  kret = mach_port_request_notification (gdb_task, darwin_inf->task,
+  kret = mach_port_move_member (gdb_task,
+                               inf->private->notify_port, MACH_PORT_NULL);
+  gdb_assert (kret == KERN_SUCCESS);
+
+  kret = mach_port_request_notification (gdb_task, inf->private->task,
                                         MACH_NOTIFY_DEAD_NAME, 0,
-                                        darwin_inf->prev_not_port,
+                                        MACH_PORT_NULL,
                                         MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                         &prev);
   /* This can fail if the task is dead.  */
+  inferior_debug (4, "task=%x, prev=%x, notify_port=%x\n",
+                 inf->private->task, prev, inf->private->notify_port);
+
   if (kret == KERN_SUCCESS)
     {
       kret = mach_port_deallocate (gdb_task, prev);
       MACH_CHECK_ERROR (kret);
     }
 
+  kret = mach_port_destroy (gdb_task, inf->private->notify_port);
+  MACH_CHECK_ERROR (kret);
+
+
   /* Deallocate saved exception ports.  */
-  for (i = 0; i < darwin_inf->exception_info.count; i++)
+  for (i = 0; i < inf->private->exception_info.count; i++)
     {
       kret = mach_port_deallocate
-       (gdb_task, darwin_inf->exception_info.ports[i]);
+       (gdb_task, inf->private->exception_info.ports[i]);
       MACH_CHECK_ERROR (kret);
     }
-  darwin_inf->exception_info.count = 0;
+  inf->private->exception_info.count = 0;
 
-  kret = mach_port_deallocate (gdb_task, darwin_inf->task);
+  kret = mach_port_deallocate (gdb_task, inf->private->task);
   MACH_CHECK_ERROR (kret);
 
-  darwin_inf->task = 0;
-  darwin_inf->pid = 0;
+  xfree (inf->private);
+  inf->private = NULL;
 
   generic_mourn_inferior ();
 }
 
 static void
-darwin_stop_inferior (struct target_ops *ops, darwin_inferior *inf)
+darwin_reply_to_all_pending_messages (struct inferior *inf)
 {
-  struct target_waitstatus wstatus;
-  ptid_t ptid;
-  kern_return_t kret;
-  int status;
-  int res;
-
-  gdb_assert (inf != NULL);
-
-  kret = task_suspend (inf->task);
-  MACH_CHECK_ERROR (kret);
-
-  if (msg_state == GOT_MESSAGE)
-    darwin_resume (darwin_ops, inferior_ptid, 0, 0);
-
-  res = kill (inf->pid, SIGSTOP);
-  if (res != 0)
-    warning (_("cannot kill: %s\n"), safe_strerror (errno));
+  int k;
+  darwin_thread_t *t;
 
-  ptid = darwin_wait (ops, inferior_ptid, &wstatus, 0);
-  gdb_assert (wstatus.kind = TARGET_WAITKIND_STOPPED);
+  for (k = 0;
+       VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
+       k++)
+    {
+      if (t->msg_state == DARWIN_MESSAGE)
+       darwin_resume_thread (inf, t, 0, 0);
+    }
 }
 
 static void
-darwin_kill_inferior (struct target_ops *ops)
+darwin_stop_inferior (struct inferior *inf)
 {
   struct target_waitstatus wstatus;
   ptid_t ptid;
@@ -701,74 +1199,26 @@ darwin_kill_inferior (struct target_ops *ops)
   int status;
   int res;
 
-  gdb_assert (darwin_inf != NULL);
-
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return;
-
-  darwin_stop_inferior (ops, darwin_inf);
-
-  res = PTRACE (PT_KILL, darwin_inf->pid, 0, 0);
-  gdb_assert (res == 0);
-
-  if (msg_state == GOT_MESSAGE)
-    {
-      exc_msg.ex_type = 0;
-      darwin_resume (ops, inferior_ptid, 0, 0);
-    }
-
-  kret = task_resume (darwin_inf->task);
-  MACH_CHECK_ERROR (kret);
-
-  ptid = darwin_wait (ops, inferior_ptid, &wstatus, 0);
-
-  /* This double wait seems required...  */
-  res = waitpid (darwin_inf->pid, &status, 0);
-  gdb_assert (res == darwin_inf->pid);
-
-  msg_state = NO_MESSAGE;
-
-  target_mourn_inferior ();
-}
-
-/* The child must synchronize with gdb: gdb must set the exception port
-   before the child call PTRACE_SIGEXC.  We use a pipe to achieve this.
-   FIXME: is there a lighter way ?  */
-static int ptrace_fds[2];
-
-static void
-darwin_ptrace_me (void)
-{
-  int res;
-  char c;
-
-  /* Close write end point.  */
-  close (ptrace_fds[1]);
+  gdb_assert (inf != NULL);
 
-  /* Wait until gdb is ready.  */
-  res = read (ptrace_fds[0], &c, 1);
-  gdb_assert (res == 0);
-  close (ptrace_fds[0]);
+  darwin_suspend_inferior (inf);
 
-  /* Get rid of privileges.  */
-  setegid (getgid ());
+  darwin_reply_to_all_pending_messages (inf);
 
-  /* Set TRACEME.  */
-  PTRACE (PT_TRACE_ME, 0, 0, 0);
+  if (inf->private->no_ptrace)
+    return;
 
-  /* Redirect signals to exception port.  */
-  PTRACE (PT_SIGEXC, 0, 0, 0);
-}
+  res = kill (inf->pid, SIGSTOP);
+  if (res != 0)
+    warning (_("cannot kill: %s\n"), safe_strerror (errno));
 
-/* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2).  */
-static void
-darwin_pre_ptrace (void)
-{
-  if (pipe (ptrace_fds) != 0)
+  /* Wait until the process is really stopped.  */
+  while (1)
     {
-      ptrace_fds[0] = -1;
-      ptrace_fds[1] = -1;
-      error (_("unable to create a pipe: %s"), safe_strerror (errno));
+      ptid = darwin_wait (inferior_ptid, &wstatus);
+      if (wstatus.kind == TARGET_WAITKIND_STOPPED
+         && wstatus.value.sig == TARGET_SIGNAL_STOP)
+       break;
     }
 }
 
@@ -806,32 +1256,79 @@ darwin_restore_exception_ports (darwin_inferior *inf)
 }
 
 static void
-darwin_attach_pid (int pid)
+darwin_kill_inferior (struct target_ops *ops)
+{
+  struct inferior *inf = current_inferior ();
+  struct target_waitstatus wstatus;
+  ptid_t ptid;
+  kern_return_t kret;
+  int status;
+  int res;
+
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return;
+
+  gdb_assert (inf != NULL);
+
+  if (!inf->private->no_ptrace)
+    {
+      darwin_stop_inferior (inf);
+
+      res = PTRACE (PT_KILL, inf->pid, 0, 0);
+      gdb_assert (res == 0);
+
+      darwin_reply_to_all_pending_messages (inf);
+
+      darwin_resume_inferior (inf);
+
+      ptid = darwin_wait (inferior_ptid, &wstatus);
+    }
+  else
+    {
+      kret = darwin_restore_exception_ports (inf->private);
+      MACH_CHECK_ERROR (kret);
+
+      darwin_reply_to_all_pending_messages (inf);
+
+      darwin_resume_inferior (inf);
+
+      res = kill (inf->pid, 9);
+
+      ptid = darwin_wait (inferior_ptid, &wstatus);
+    }
+
+  target_mourn_inferior ();
+}
+
+static void
+darwin_attach_pid (struct inferior *inf)
 {
-  task_t itask;
   kern_return_t kret;
   mach_port_t prev_port;
   int traps_expected;
+  mach_port_t prev_not;
   exception_mask_t mask;
 
-  kret = task_for_pid (gdb_task, pid, &itask);
+  inf->private = XZALLOC (darwin_inferior);
+
+  kret = task_for_pid (gdb_task, inf->pid, &inf->private->task);
   if (kret != KERN_SUCCESS)
     {
       int status;
-      struct inferior *inf = current_inferior ();
 
       if (!inf->attach_flag)
        {
-         kill (pid, 9);
-         waitpid (pid, &status, 0);
+         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 setgid procmod)"),
-             pid, mach_error_string (kret), (unsigned long) kret);
+             inf->pid, mach_error_string (kret), (unsigned long) kret);
     }
 
-  inferior_debug (2, _("inferior task: 0x%08x, pid: %d\n"), itask, pid);
+  inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"),
+                 inf->private->task, inf->pid);
 
   if (darwin_ex_port == MACH_PORT_NULL)
     {
@@ -851,55 +1348,98 @@ darwin_attach_pid (int pid)
 
       kret = mach_port_move_member (gdb_task, darwin_ex_port, darwin_port_set);
       gdb_assert (kret == KERN_SUCCESS);
+    }
 
-      /* Create a port to be notified when the child task terminates.  */
-      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
-                                &darwin_not_port);
-      gdb_assert (kret == KERN_SUCCESS);
-
-      kret = mach_port_insert_right (gdb_task, darwin_not_port, darwin_not_port,
-                                    MACH_MSG_TYPE_MAKE_SEND);
-      gdb_assert (kret == KERN_SUCCESS);
+  /* 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);
+  gdb_assert (kret == KERN_SUCCESS);
 
-      kret = mach_port_move_member (gdb_task, darwin_not_port, darwin_port_set);
-      gdb_assert (kret == KERN_SUCCESS);
-    }
+  kret = mach_port_move_member (gdb_task,
+                               inf->private->notify_port, darwin_port_set);
+  gdb_assert (kret == KERN_SUCCESS);
 
-  kret = mach_port_request_notification (gdb_task, itask,
+  kret = mach_port_request_notification (gdb_task, inf->private->task,
                                         MACH_NOTIFY_DEAD_NAME, 0,
-                                        darwin_not_port,
+                                        inf->private->notify_port,
                                         MACH_MSG_TYPE_MAKE_SEND_ONCE,
-                                        &darwin_inf->prev_not_port);
+                                        &prev_not);
   gdb_assert (kret == KERN_SUCCESS);
+  gdb_assert (prev_not == MACH_PORT_NULL);
 
-  darwin_inf->task = itask;
-  darwin_inf->pid = pid;
-
-  kret = darwin_save_exception_ports (darwin_inf);
+  kret = darwin_save_exception_ports (inf->private);
   gdb_assert (kret == KERN_SUCCESS);
 
   /* Set exception port.  */
   if (enable_mach_exceptions)
     mask = EXC_MASK_ALL;
   else
-    mask = EXC_MASK_SOFTWARE;
-  kret = task_set_exception_ports
-    (itask, mask, darwin_ex_port, EXCEPTION_DEFAULT, THREAD_STATE_NONE);
+    mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
+  kret = task_set_exception_ports (inf->private->task, mask, darwin_ex_port,
+                                  EXCEPTION_DEFAULT, THREAD_STATE_NONE);
   gdb_assert (kret == KERN_SUCCESS);
 
   push_target (darwin_ops);
 }
 
 static void
-darwin_init_thread_list (darwin_inferior *inf)
+darwin_init_thread_list (struct inferior *inf)
 {
-  thread_t thread;
+  darwin_thread_t *thread;
+  ptid_t new_ptid;
 
   darwin_check_new_threads (inf);
 
-  gdb_assert (inf->threads && VEC_length (thread_t, inf->threads) > 0);
-  thread = VEC_index (thread_t, inf->threads, 0);
-  inferior_ptid = ptid_build (inf->pid, 0, thread);
+  gdb_assert (inf->private->threads
+             && VEC_length (darwin_thread_t, inf->private->threads) > 0);
+  thread = VEC_index (darwin_thread_t, inf->private->threads, 0);
+
+  /* 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;
+}
+
+/* The child must synchronize with gdb: gdb must set the exception port
+   before the child call PTRACE_SIGEXC.  We use a pipe to achieve this.
+   FIXME: is there a lighter way ?  */
+static int ptrace_fds[2];
+
+static void
+darwin_ptrace_me (void)
+{
+  int res;
+  char c;
+
+  /* Close write end point.  */
+  close (ptrace_fds[1]);
+
+  /* Wait until gdb is ready.  */
+  res = read (ptrace_fds[0], &c, 1);
+  gdb_assert (res == 0);
+  close (ptrace_fds[0]);
+
+  /* Get rid of privileges.  */
+  setegid (getgid ());
+
+  /* Set TRACEME.  */
+  PTRACE (PT_TRACE_ME, 0, 0, 0);
+
+  /* Redirect signals to exception port.  */
+  PTRACE (PT_SIGEXC, 0, 0, 0);
+}
+
+/* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2).  */
+static void
+darwin_pre_ptrace (void)
+{
+  if (pipe (ptrace_fds) != 0)
+    {
+      ptrace_fds[0] = -1;
+      ptrace_fds[1] = -1;
+      error (_("unable to create a pipe: %s"), safe_strerror (errno));
+    }
 }
 
 static void
@@ -909,17 +1449,16 @@ darwin_ptrace_him (int pid)
   kern_return_t kret;
   mach_port_t prev_port;
   int traps_expected;
+  struct inferior *inf = current_inferior ();
 
-  darwin_attach_pid (pid);
+  darwin_attach_pid (inf);
 
   /* Let's the child run.  */
   close (ptrace_fds[0]);
   close (ptrace_fds[1]);
 
-  /* fork_inferior automatically add a thread - but it uses a wrong tid.  */
-  delete_thread_silent (inferior_ptid);
-  darwin_init_thread_list (darwin_inf);
-  
+  darwin_init_thread_list (inf);
+
   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
 }
 
@@ -930,7 +1469,7 @@ darwin_create_inferior (struct target_ops *ops, char *exec_file,
   /* Do the hard work.  */
   fork_inferior (exec_file, allargs, env, darwin_ptrace_me, darwin_ptrace_him,
                 darwin_pre_ptrace, NULL);
-  
+
   /* Return now in case of error.  */
   if (ptid_equal (inferior_ptid, null_ptid))
     return;
@@ -947,8 +1486,7 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty)
   int wstatus;
   int res;
   struct inferior *inf;
-
-  gdb_assert (msg_state == NO_MESSAGE);
+  kern_return_t kret;
 
   if (!args)
     error_no_arg (_("process-id to attach"));
@@ -959,33 +1497,40 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty)
     error (_("I refuse to debug myself!"));
 
   if (from_tty)
-    printf_unfiltered (_("Attaching to pid %d\n"), pid);
+    {
+      char *exec_file = get_exec_file (0);
 
-  res = PTRACE (PT_ATTACHEXC, pid, 0, 0);
-  if (res != 0)
-    error (_("Unable to attach to process-id %d: %s (%d)"),
-          pid, safe_strerror (errno), errno);
+      if (exec_file)
+       printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
+                          target_pid_to_str (pid_to_ptid (pid)));
+      else
+       printf_unfiltered (_("Attaching to %s\n"),
+                          target_pid_to_str (pid_to_ptid (pid)));
+
+      gdb_flush (gdb_stdout);
+    }
+
+  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);
   inf = add_inferior (pid);
   inf->attach_flag = 1;
+  /* Always add a main thread.  */
+  add_thread_silent (inferior_ptid);
 
-  darwin_attach_pid (pid);
+  darwin_attach_pid (inf);
 
-  pid2 = wait4 (pid, &wstatus, WUNTRACED, NULL);
-  gdb_assert (pid2 == pid);
-  inferior_debug (1, _("darwin_attach: wait4 pid=%d, status=0x%x\n"),
-                 pid2, wstatus);
+  darwin_suspend_inferior (inf);
 
-  
-  darwin_init_thread_list (darwin_inf);
+  darwin_init_thread_list (inf);
 
-  darwin_check_osabi (darwin_inf, ptid_get_tid (inferior_ptid));
+  darwin_check_osabi (inf->private, ptid_get_tid (inferior_ptid));
 
-  /* Looks strange, but the kernel doesn't stop the process...
-     (Bug in Leopard ?)
-     Do it manually.  */
-  /* FIXME: doesn't look to work with multi-threads!!  */
-  kill (pid, SIGSTOP);
+  gdb_assert (darwin_inf_fake_stop == NULL);
+  darwin_inf_fake_stop = inf;
+  inf->private->no_ptrace = 1;
 }
 
 /* Take a program previously attached to and detaches it.
@@ -998,39 +1543,40 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty)
 static void
 darwin_detach (struct target_ops *ops, char *args, int from_tty)
 {
+  pid_t pid = ptid_get_pid (inferior_ptid);
+  struct inferior *inf = current_inferior ();
   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, %d\n"), exec_file,
-                        ptid_get_pid (inferior_ptid));
+      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
+                        target_pid_to_str (pid_to_ptid (pid)));
       gdb_flush (gdb_stdout);
     }
 
-  darwin_stop_inferior (ops, darwin_inf);
+  /* If ptrace() is in use, stop the process.  */
+  if (!inf->private->no_ptrace)
+    darwin_stop_inferior (inf);
 
-  kret = darwin_restore_exception_ports (darwin_inf);
+  kret = darwin_restore_exception_ports (inf->private);
   MACH_CHECK_ERROR (kret);
 
-  if (msg_state == GOT_MESSAGE)
+  if (!inf->private->no_ptrace)
     {
-      exc_msg.ex_type = 0;
-      darwin_resume (ops, inferior_ptid, 0, 0);
+      res = PTRACE (PT_DETACH, inf->pid, 0, 0);
+      if (res != 0)
+       printf_unfiltered (_("Unable to detach from process-id %d: %s (%d)"),
+                          inf->pid, safe_strerror (errno), errno);
     }
 
-  kret = task_resume (darwin_inf->task);
-  gdb_assert (kret == KERN_SUCCESS);
-
-  res = PTRACE (PT_DETACH, darwin_inf->pid, 0, 0);
-  if (res != 0)
-    printf_unfiltered (_("Unable to detach from process-id %d: %s (%d)"),
-                      darwin_inf->pid, safe_strerror (errno), errno);
+  darwin_reply_to_all_pending_messages (inf);
 
-  msg_state = NO_MESSAGE;
+  darwin_resume_inferior (inf);
 
   darwin_mourn_inferior (ops);
 }
@@ -1038,19 +1584,22 @@ darwin_detach (struct target_ops *ops, char *args, int from_tty)
 static void
 darwin_files_info (struct target_ops *ops)
 {
-  gdb_assert (darwin_inf != NULL);
 }
 
 static char *
 darwin_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
-  static char buf[128];
+  static char buf[80];
+  long tid = ptid_get_tid (ptid);
+
+  if (tid != 0)
+    {
+      snprintf (buf, sizeof (buf), _("Thread 0x%lx of process %u"),
+               tid, ptid_get_pid (ptid));
+      return buf;
+    }
 
-  snprintf (buf, sizeof (buf),
-           _("process %d gdb-thread 0x%lx"),
-           (unsigned) ptid_get_pid (ptid),
-           (unsigned long) ptid_get_tid (ptid));
-  return buf;
+  return normal_pid_to_str (ptid);
 }
 
 static int
@@ -1068,7 +1617,7 @@ static int
 darwin_read_write_inferior (task_t task, CORE_ADDR addr,
                            char *rdaddr, const char *wraddr, int length)
 {
-  kern_return_t err;
+  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);
@@ -1078,16 +1627,17 @@ darwin_read_write_inferior (task_t task, CORE_ADDR addr,
   mach_vm_address_t region_address;
   mach_vm_size_t region_length;
 
-  inferior_debug (8, _("darwin_read_write_inferior(%s, len=%d)\n"),
-                 core_addr_to_string (addr), length);
-  
+  inferior_debug (8, _("darwin_read_write_inferior(task=%x, %s, len=%d)\n"),
+                 task, core_addr_to_string (addr), length);
+
   /* Get memory from inferior with page aligned addresses */
-  err = mach_vm_read (task, low_address, aligned_length,
+  kret = mach_vm_read (task, low_address, aligned_length,
                      &copied, &copy_count);
-  if (err != KERN_SUCCESS)
+  if (kret != KERN_SUCCESS)
     {
-      warning (_("darwin_read_write_inferior: vm_read failed: %s"), 
-              mach_error_string (err));
+      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;
     }
 
@@ -1105,64 +1655,85 @@ darwin_read_write_inferior (task_t task, CORE_ADDR addr,
        region_address < low_address + aligned_length;
        region_address += region_length, remaining_length -= region_length)
     {
-      vm_region_basic_info_data_64_t info;
-      mach_port_t object_name;
-      mach_vm_address_t old_address = region_address;
+      vm_region_submap_short_info_data_64_t info;
+      mach_vm_address_t region_start = region_address;
       mach_msg_type_number_t count;
-      
-      region_length = remaining_length;
-      count = VM_REGION_BASIC_INFO_COUNT_64;
-      err = mach_vm_region (task, &region_address, &region_length,
-                           VM_REGION_BASIC_INFO_64,
-                           (vm_region_info_t) &info, &count, &object_name);
-      
-      if (err != KERN_SUCCESS)
+      natural_t region_depth;
+
+      region_depth = 100000;
+      count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
+      kret = mach_vm_region_recurse
+       (task, &region_start, &region_length, &region_depth,
+        (vm_region_recurse_info_t) &info, &count);
+
+      if (kret != KERN_SUCCESS)
        {
-         warning (_("darwin_write_inferior: mach_vm_region failed: %s"), 
-                  mach_error_string (err));
+         inferior_debug (1, _("darwin_read_write_inferior: "
+                              "mach_vm_region_recurse failed at %s: %s\n"),
+                         core_addr_to_string (region_address),
+                         mach_error_string (kret));
          goto out;
        }
 
+      inferior_debug
+       (9, _("darwin_read_write_inferior: "
+             "mach_vm_region_recurse addr=%s, start=%s, len=%s\n"),
+        core_addr_to_string (region_address),
+        core_addr_to_string (region_start),
+        core_addr_to_string (region_length));
+
       /* Check for holes in memory */
-      if (region_address > old_address)
+      if (region_start > region_address)
        {
          warning (_("No memory at %s (vs %s+0x%x). Nothing written"),
-                  core_addr_to_string (old_address),
                   core_addr_to_string (region_address),
+                  core_addr_to_string (region_start),
                   (unsigned)region_length);
          length = 0;
          goto out;
        }
 
+      /* Adjust the length.  */
+      region_length -= (region_address - region_start);
+
       if (!(info.max_protection & VM_PROT_WRITE))
        {
-         warning (_("Memory at address %s is unwritable. Nothing written"),
-                  core_addr_to_string (old_address));
-         length = 0;
-         goto out;
+         kret = mach_vm_protect
+           (task, region_address, region_length,
+            TRUE, info.max_protection | VM_PROT_WRITE | VM_PROT_COPY);
+         if (kret != KERN_SUCCESS)
+           {
+             warning (_("darwin_read_write_inf: "
+                        "mach_vm_protect max failed at %s: %s"),
+                      core_addr_to_string (region_address),
+                      mach_error_string (kret));
+             length = 0;
+             goto out;
+           }
        }
 
       if (!(info.protection & VM_PROT_WRITE))
        {
-         err = mach_vm_protect (task, old_address, region_length,
+         kret = mach_vm_protect (task, region_address, region_length,
                                 FALSE, info.protection | VM_PROT_WRITE);
-         if (err != KERN_SUCCESS)
+         if (kret != KERN_SUCCESS)
            {
-             warning
-               (_("darwin_read_write_inferior: mach_vm_protect failed: %s"), 
-                mach_error_string (err));
+             warning (_("darwin_read_write_inf: "
+                        "mach_vm_protect 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;
            }
        }
     }
 
-  err = mach_vm_write (task, low_address, copied, aligned_length);
+  kret = mach_vm_write (task, low_address, copied, aligned_length);
 
-  if (err != KERN_SUCCESS)
+  if (kret != KERN_SUCCESS)
     {
       warning (_("darwin_read_write_inferior: mach_vm_write failed: %s"),
-              mach_error_string (err));
+              mach_error_string (kret));
       length = 0;
     }
 out:
@@ -1177,7 +1748,8 @@ static int
 darwin_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
                    struct mem_attrib *attrib, struct target_ops *target)
 {
-  task_t task = darwin_inf->task;
+  struct inferior *inf = current_inferior ();
+  task_t task = inf->private->task;
 
   if (task == MACH_PORT_NULL)
     return 0;
@@ -1197,15 +1769,16 @@ darwin_xfer_partial (struct target_ops *ops,
                     gdb_byte *readbuf, const gdb_byte *writebuf,
                     ULONGEST offset, LONGEST len)
 {
-  inferior_debug (8, _("darwin_xfer_partial(%s, %d, rbuf=%s, wbuf=%s)\n"),
-                 core_addr_to_string (offset), (int)len, 
-                 host_address_to_string (readbuf),
-                 host_address_to_string (writebuf));
+  struct inferior *inf = current_inferior ();
+
+  inferior_debug
+    (8, _("darwin_xfer_partial(%s, %d, rbuf=%p, wbuf=%p) pid=%u\n"),
+     core_addr_to_string (offset), (int)len, readbuf, writebuf, inf->pid);
 
   if (object != TARGET_OBJECT_MEMORY)
     return -1;
 
-  return darwin_read_write_inferior (darwin_inf->task, offset,
+  return darwin_read_write_inferior (inf->private->task, offset,
                                     readbuf, writebuf, len);
 }
 
@@ -1213,8 +1786,9 @@ static void
 set_enable_mach_exceptions (char *args, int from_tty,
                            struct cmd_list_element *c)
 {
-  if (darwin_inf && darwin_inf->task != TASK_NULL)
+  if (!ptid_equal (inferior_ptid, null_ptid))
     {
+      struct inferior *inf = current_inferior ();
       exception_mask_t mask;
       kern_return_t kret;
 
@@ -1222,22 +1796,109 @@ set_enable_mach_exceptions (char *args, int from_tty,
        mask = EXC_MASK_ALL;
       else
        {
-         darwin_restore_exception_ports (darwin_inf);
-         mask = EXC_MASK_SOFTWARE;
+         darwin_restore_exception_ports (inf->private);
+         mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
        }
-      kret = task_set_exception_ports (darwin_inf->task, mask, darwin_ex_port,
+      kret = task_set_exception_ports (inf->private->task, mask, darwin_ex_port,
                                       EXCEPTION_DEFAULT, THREAD_STATE_NONE);
       MACH_CHECK_ERROR (kret);
     }
 }
 
+static char *
+darwin_pid_to_exec_file (int pid)
+{
+  char *path;
+  int res;
+
+  path = xmalloc (MAXPATHLEN);
+  make_cleanup (xfree, path);
+
+  res = proc_pidinfo (pid, PROC_PIDPATHINFO, 0, path, MAXPATHLEN);
+  if (res >= 0)
+    return path;
+  else
+    return NULL;
+}
+
+static ptid_t
+darwin_get_ada_task_ptid (long lwp, long thread)
+{
+  int i;
+  darwin_thread_t *t;
+  int k;
+  struct inferior *inf = current_inferior ();
+  kern_return_t kret;
+  mach_port_name_array_t names;
+  mach_msg_type_number_t names_count;
+  mach_port_type_array_t types;
+  mach_msg_type_number_t types_count;
+  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);
+
+  /* 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,
+                         &types_count);
+  MACH_CHECK_ERROR (kret);
+  if (kret != KERN_SUCCESS)
+    return null_ptid;
+
+  /* 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++)
+    {
+      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],
+                                     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;
+         }
+    }
+
+  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);
+  else
+    return null_ptid;
+}
+
+static int
+darwin_supports_multi_process (void)
+{
+  return 1;
+}
+
 void
-_initialize_darwin_inferior ()
+_initialize_darwin_inferior (void)
 {
   kern_return_t kret;
 
-  gdb_assert (darwin_inf == NULL);
-  
   gdb_task = mach_task_self ();
   darwin_host_self = mach_host_self ();
 
@@ -1249,11 +1910,6 @@ _initialize_darwin_inferior ()
       MACH_CHECK_ERROR (kret);
     }
 
-  darwin_inf = (struct darwin_inferior *)
-    xmalloc (sizeof (struct darwin_inferior));
-
-  memset (darwin_inf, 0, sizeof (*darwin_inf));
-
   darwin_ops = inf_child_target ();
 
   darwin_ops->to_shortname = "darwin-child";
@@ -1265,17 +1921,20 @@ _initialize_darwin_inferior ()
   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;
+  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;
+  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->deprecated_xfer_memory = darwin_xfer_memory;
   darwin_ops->to_xfer_partial = darwin_xfer_partial;
-  darwin_ops->to_has_thread_control = tc_schedlock /*| tc_switch */;
+  darwin_ops->to_supports_multi_process = darwin_supports_multi_process;
+  darwin_ops->to_get_ada_task_ptid = darwin_get_ada_task_ptid;
+  /* darwin_ops->to_has_thread_control = tc_schedlock | tc_switch */;
 
   darwin_complete_target (darwin_ops);
 
index 43a1522..3d216cc 100644 (file)
@@ -22,9 +22,6 @@
 #include <mach/mach.h>
 #include "gdb_assert.h"
 
-/* Define the threads vector type.  */
-DEF_VEC_I (thread_t);
-
 /* Describe the mach exception handling state for a task.  This state is saved
    before being changed and restored when a process is detached.
    For more information on these fields see task_get_exception_ports manual
@@ -48,35 +45,83 @@ struct darwin_exception_info
 };
 typedef struct darwin_exception_info darwin_exception_info;
 
-/* Describe an inferior.  */
-struct darwin_inferior
+struct darwin_exception_msg
 {
-  /* Inferior PID.  */
-  int pid;
+  mach_msg_header_t header;
+
+  /* Thread and task taking the exception.  */
+  mach_port_t thread_port;
+  mach_port_t task_port;
+
+  /* Type of the exception.  */
+  exception_type_t ex_type;
+
+  /* Machine dependent details.  */
+  mach_msg_type_number_t data_count;
+  integer_t ex_data[2];
+};
+
+enum darwin_msg_state { DARWIN_RUNNING, DARWIN_STOPPED, DARWIN_MESSAGE };
+
+struct private_thread_info
+{
+  /* The thread port from a GDB point of view.  */
+  thread_t gdb_port;
+
+  /* The thread port from the inferior point of view.  Not to be used inside
+     gdb except for get_ada_task_ptid.  */
+  thread_t inf_port;
+
+  /* Current message state.
+     If the kernel has sent a message it expects a reply and the inferior
+     can't be killed before.  */
+  enum darwin_msg_state msg_state;
+
+  /* True if this thread is single-stepped.  */
+  unsigned char single_step;
 
+  /* True if a signal was manually sent to the thread.  */
+  unsigned char signaled;
+
+  /* The last exception received.  */
+  struct darwin_exception_msg event;
+};
+typedef struct private_thread_info darwin_thread_t;
+
+/* Define the threads vector type.  */
+DEF_VEC_O (darwin_thread_t);
+
+
+/* Describe an inferior.  */
+struct private_inferior
+{
   /* Corresponding task port.  */
   task_t task;
 
-  /* Previous port for request notification on task.  */
-  mach_port_t prev_not_port;
+  /* Port which will receive the dead-name notification for the task port.
+     This is used to detect the death of the task.  */
+  mach_port_t notify_port;
 
   /* Initial exception handling.  */
   darwin_exception_info exception_info;
 
+  /* Number of messages that have been received but not yet replied.  */
+  unsigned int pending_messages;
+
+  /* Set if inferior is not controlled by ptrace(2) but through Mach.  */
+  unsigned char no_ptrace;
+
+  /* True if this task is suspended.  */
+  unsigned char suspended;
+
   /* Sorted vector of known threads.  */
-  VEC(thread_t) *threads;
+  VEC(darwin_thread_t) *threads;
 };
-typedef struct darwin_inferior darwin_inferior;
-
-/* Current inferior.  */
-extern darwin_inferior *darwin_inf;
+typedef struct private_inferior darwin_inferior;
 
 /* Exception port.  */
 extern mach_port_t darwin_ex_port;
 
-/* Notification port.  */
-extern mach_port_t darwin_not_port;
-
 /* Port set.  */
 extern mach_port_t darwin_port_set;
 
index 78daa75..5f9a0fe 100644 (file)
@@ -103,7 +103,6 @@ macho_symtab_read (struct objfile *objfile,
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   long storage_needed;
-  asymbol *sym;
   long i, j;
   CORE_ADDR offset;
   enum minimal_symbol_type ms_type;
@@ -114,15 +113,16 @@ macho_symtab_read (struct objfile *objfile,
 
   for (i = 0; i < number_of_symbols; i++)
     {
-      sym = symbol_table[i];
+      asymbol *sym = symbol_table[i];
+      bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym;
+
       offset = ANOFFSET (objfile->section_offsets, sym->section->index);
 
       if (sym->flags & BSF_DEBUGGING)
        {
-         unsigned char type = BFD_MACH_O_SYM_NTYPE(sym);
          bfd_vma addr;
 
-         switch (type)
+         switch (mach_o_sym->n_type)
            {
            case N_SO:
              if ((sym->name == NULL || sym->name[0] == 0)