* gas/nios2/nios2.exp: Add copyright.
[deliverable/binutils-gdb.git] / gdb / darwin-nat.c
index 27c6e2c7dc302836a7105510f35f51d2450a4e66..1344101c7cb70ec3dda18031aa0bf9ee99bd6765 100644 (file)
@@ -1,5 +1,5 @@
 /* Darwin support for GDB, the GNU debugger.
-   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2008-2013 Free Software Foundation, Inc.
 
    Contributed by AdaCore.
 
@@ -39,6 +39,7 @@
 #include "value.h"
 #include "arch-utils.h"
 #include "bfd.h"
+#include "bfd/mach-o.h"
 
 #include <sys/ptrace.h>
 #include <sys/signal.h>
@@ -53,6 +54,7 @@
 #include <sys/proc.h>
 #include <libproc.h>
 #include <sys/syscall.h>
+#include <spawn.h>
 
 #include <mach/mach_error.h>
 #include <mach/mach_vm.h>
@@ -89,9 +91,9 @@ 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);
+                              enum gdb_signal signal);
 static void darwin_resume (ptid_t ptid, int step,
-                          enum target_signal signal);
+                          enum gdb_signal signal);
 
 static ptid_t darwin_wait_to (struct target_ops *ops, ptid_t ptid,
                               struct target_waitstatus *status, int options);
@@ -143,7 +145,7 @@ static struct inferior *darwin_inf_fake_stop;
 #define PAGE_ROUND(x) PAGE_TRUNC((x) + mach_page_size - 1)
 
 /* This controls output of inferior debugging.  */
-static int darwin_debug_flag = 0;
+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.
@@ -615,8 +617,11 @@ 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.  */
+  gdb_assert (thread->msg_state != DARWIN_MESSAGE);
+
   /* 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;
@@ -700,11 +705,14 @@ darwin_resume_thread (struct inferior *inf, darwin_thread_t *thread,
          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;
+      /* Set or reset single step.  */
+      if (step != thread->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;
@@ -779,7 +787,7 @@ darwin_suspend_inferior_threads (struct inferior *inf)
 }
 
 static void
-darwin_resume (ptid_t ptid, int step, enum target_signal signal)
+darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
   struct target_waitstatus status;
   int pid;
@@ -793,10 +801,10 @@ darwin_resume (ptid_t ptid, int step, enum target_signal signal)
     (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)
+  if (signal == GDB_SIGNAL_0)
     nsignal = 0;
   else
-    nsignal = target_signal_to_host (signal);
+    nsignal = gdb_signal_to_host (signal);
 
   /* Don't try to single step all threads.  */
   if (step)
@@ -845,7 +853,7 @@ darwin_resume (ptid_t ptid, int step, enum target_signal signal)
 
 static void
 darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
-                  enum target_signal signal)
+                  enum gdb_signal signal)
 {
   return darwin_resume (ptid, step, signal);
 }
@@ -905,10 +913,10 @@ darwin_decode_message (mach_msg_header_t *hdr,
          if (thread->event.ex_data[0] == EXC_SOFT_SIGNAL)
            {
              status->value.sig =
-               target_signal_from_host (thread->event.ex_data[1]);
+               gdb_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));
+                             gdb_signal_to_name (status->value.sig));
 
              /* If the thread is stopped because it has received a signal
                 that gdb has just sent, continue.  */
@@ -925,12 +933,12 @@ darwin_decode_message (mach_msg_header_t *hdr,
          break;
        case EXC_BREAKPOINT:
          /* Many internal GDB routines expect breakpoints to be reported
-            as TARGET_SIGNAL_TRAP, and will report TARGET_EXC_BREAKPOINT
+            as GDB_SIGNAL_TRAP, and will report TARGET_EXC_BREAKPOINT
             as a spurious signal.  */
-         status->value.sig = TARGET_SIGNAL_TRAP;
+         status->value.sig = GDB_SIGNAL_TRAP;
          break;
        default:
-         status->value.sig = TARGET_SIGNAL_UNKNOWN;
+         status->value.sig = GDB_SIGNAL_UNKNOWN;
          break;
        }
 
@@ -1044,7 +1052,7 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
       darwin_inf_fake_stop = NULL;
 
       status->kind = TARGET_WAITKIND_STOPPED;
-      status->value.sig = TARGET_SIGNAL_TRAP;
+      status->value.sig = GDB_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);
@@ -1255,7 +1263,7 @@ darwin_stop_inferior (struct inferior *inf)
     {
       ptid = darwin_wait (inferior_ptid, &wstatus);
       if (wstatus.kind == TARGET_WAITKIND_STOPPED
-         && wstatus.value.sig == TARGET_SIGNAL_STOP)
+         && wstatus.value.sig == GDB_SIGNAL_STOP)
        break;
     }
 }
@@ -1308,35 +1316,22 @@ darwin_kill_inferior (struct target_ops *ops)
 
   gdb_assert (inf != NULL);
 
-  if (!inf->private->no_ptrace)
-    {
-      darwin_stop_inferior (inf);
-
-      res = PTRACE (PT_KILL, inf->pid, 0, 0);
-      if (res != 0)
-        warning (_("Failed to kill inferior: ptrace returned %d "
-                  "[%s] (pid=%d)"),
-                res, safe_strerror (errno), inf->pid);
+  kret = darwin_restore_exception_ports (inf->private);
+  MACH_CHECK_ERROR (kret);
 
-      darwin_reply_to_all_pending_messages (inf);
+  darwin_reply_to_all_pending_messages (inf);
 
-      darwin_resume_inferior (inf);
+  res = kill (inf->pid, 9);
 
-      ptid = darwin_wait (inferior_ptid, &wstatus);
-    }
-  else
+  if (res == 0)
     {
-      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);
     }
+  else if (errno != ESRCH)
+    warning (_("Failed to kill inferior: kill (%d, 9) returned [%s]"),
+            inf->pid, safe_strerror (errno));
 
   target_mourn_inferior ();
 }
@@ -1503,13 +1498,47 @@ darwin_ptrace_him (int pid)
   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
 }
 
+static void
+darwin_execvp (const char *file, char * const argv[], char * const env[])
+{
+  posix_spawnattr_t attr;
+  short ps_flags = 0;
+  int res;
+
+  res = posix_spawnattr_init (&attr);
+  if (res != 0)
+    {
+      fprintf_unfiltered
+        (gdb_stderr, "Cannot initialize attribute for posix_spawn\n");
+      return;
+    }
+
+  /* Do like execve: replace the image.  */
+  ps_flags = POSIX_SPAWN_SETEXEC;
+
+  /* Disable ASLR.  The constant doesn't look to be available outside the
+     kernel include files.  */
+#ifndef _POSIX_SPAWN_DISABLE_ASLR
+#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
+#endif
+  ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
+  res = posix_spawnattr_setflags (&attr, ps_flags);
+  if (res != 0)
+    {
+      fprintf_unfiltered (gdb_stderr, "Cannot set posix_spawn flags\n");
+      return;
+    }
+
+  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)
 {
   /* Do the hard work.  */
   fork_inferior (exec_file, allargs, env, darwin_ptrace_me, darwin_ptrace_him,
-                darwin_pre_ptrace, NULL);
+                darwin_pre_ptrace, NULL, darwin_execvp);
 
   /* Return now in case of error.  */
   if (ptid_equal (inferior_ptid, null_ptid))
@@ -1656,7 +1685,7 @@ darwin_thread_alive (struct target_ops *ops, ptid_t ptid)
    copy it to RDADDR in gdb's address space.
    If WRADDR is not NULL, write gdb's LEN bytes from WRADDR and copy it
    to ADDR in inferior task's address space.
-   Return 0 on failure; number of bytes read / writen  otherwise.  */
+   Return 0 on failure; number of bytes read / writen otherwise.  */
 static int
 darwin_read_write_inferior (task_t task, CORE_ADDR addr,
                            char *rdaddr, const char *wraddr, int length)
@@ -1785,6 +1814,35 @@ out:
   return length;
 }
 
+/* Read LENGTH bytes at offset ADDR of task_dyld_info for TASK, and copy them
+   to RDADDR.
+   Return 0 on failure; number of bytes read / written otherwise.  */
+
+#ifdef TASK_DYLD_INFO_COUNT
+/* This is not available in Darwin 9.  */
+static int
+darwin_read_dyld_info (task_t task, CORE_ADDR addr, char *rdaddr, int length)
+{
+  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;
+
+  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;
+}
+#endif
+
 \f
 /* Return 0 on failure, number of bytes handled otherwise.  TARGET
    is ignored.  */
@@ -1821,11 +1879,24 @@ darwin_xfer_partial (struct target_ops *ops,
      host_address_to_string (readbuf), host_address_to_string (writebuf),
      inf->pid);
 
-  if (object != TARGET_OBJECT_MEMORY)
-    return -1;
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      return darwin_read_write_inferior (inf->private->task, offset,
+                                         readbuf, writebuf, len);
+#ifdef TASK_DYLD_INFO_COUNT
+    case TARGET_OBJECT_DARWIN_DYLD_INFO:
+      if (writebuf != NULL || readbuf == NULL)
+        {
+          /* Support only read.  */
+          return -1;
+        }
+      return darwin_read_dyld_info (inf->private->task, offset, readbuf, len);
+#endif
+    default:
+      return -1;
+    }
 
-  return darwin_read_write_inferior (inf->private->task, offset,
-                                    readbuf, writebuf, len);
 }
 
 static void
@@ -1940,6 +2011,9 @@ darwin_supports_multi_process (void)
   return 1;
 }
 
+/* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_darwin_inferior;
+
 void
 _initialize_darwin_inferior (void)
 {
@@ -1988,12 +2062,12 @@ _initialize_darwin_inferior (void)
   inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"), mach_task_self (),
                   getpid ());
 
-  add_setshow_zinteger_cmd ("darwin", class_obscure,
-                           &darwin_debug_flag, _("\
+  add_setshow_zuinteger_cmd ("darwin", class_obscure,
+                            &darwin_debug_flag, _("\
 Set if printing inferior communication debugging statements."), _("\
 Show if printing inferior communication debugging statements."), NULL,
-                           NULL, NULL,
-                           &setdebuglist, &showdebuglist);
+                            NULL, NULL,
+                            &setdebuglist, &showdebuglist);
 
   add_setshow_boolean_cmd ("mach-exceptions", class_support,
                           &enable_mach_exceptions, _("\
This page took 0.028182 seconds and 4 git commands to generate.