/* Darwin support for GDB, the GNU debugger.
- Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2008-2012 Free Software Foundation, Inc.
Contributed by AdaCore.
#include <sys/proc.h>
#include <libproc.h>
#include <sys/syscall.h>
+#include <spawn.h>
#include <mach/mach_error.h>
#include <mach/mach_vm.h>
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))
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)
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 / writen otherwise. */
+
+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;
+}
+
\f
/* Return 0 on failure, number of bytes handled otherwise. TARGET
is ignored. */
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);
+ 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);
+ default:
+ return -1;
+ }
- return darwin_read_write_inferior (inf->private->task, offset,
- readbuf, writebuf, len);
}
static void