X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fdarwin-nat.c;h=47483bf5e9e10aed562738595020898d9ab6147b;hb=9f1b45b0da430a7a7abf9e54acbe6f2ef9d3a763;hp=6dedc4054466e0a0e24c637176dbe04d5c198ee5;hpb=c8c9911faa52bbd1edcae3a12181bb76fa867f31;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c index 6dedc40544..47483bf5e9 100644 --- a/gdb/darwin-nat.c +++ b/gdb/darwin-nat.c @@ -1,5 +1,5 @@ /* Darwin support for GDB, the GNU debugger. - Copyright (C) 2008-2013 Free Software Foundation, Inc. + Copyright (C) 2008-2014 Free Software Foundation, Inc. Contributed by AdaCore. @@ -16,8 +16,7 @@ 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 . -*/ + along with this program. If not, see . */ #include "defs.h" #include "top.h" @@ -33,7 +32,7 @@ #include "regcache.h" #include "event-top.h" #include "inf-loop.h" -#include "gdb_stat.h" +#include #include "exceptions.h" #include "inf-child.h" #include "value.h" @@ -49,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -66,6 +64,7 @@ #include #include "darwin-nat.h" +#include "common/filestuff.h" /* Quick overview. Darwin kernel is Mach + BSD derived kernel. Note that they share the @@ -351,7 +350,7 @@ darwin_check_new_threads (struct inferior *inf) struct thread_info *tp; struct private_thread_info *pti; - pti = XZALLOC (struct private_thread_info); + pti = XCNEW (struct private_thread_info); pti->gdb_port = new_id; pti->msg_state = DARWIN_RUNNING; @@ -898,16 +897,16 @@ darwin_decode_message (mach_msg_header_t *hdr, switch (thread->event.ex_type) { case EXC_BAD_ACCESS: - status->value.sig = TARGET_EXC_BAD_ACCESS; + status->value.sig = GDB_EXC_BAD_ACCESS; break; case EXC_BAD_INSTRUCTION: - status->value.sig = TARGET_EXC_BAD_INSTRUCTION; + status->value.sig = GDB_EXC_BAD_INSTRUCTION; break; case EXC_ARITHMETIC: - status->value.sig = TARGET_EXC_ARITHMETIC; + status->value.sig = GDB_EXC_ARITHMETIC; break; case EXC_EMULATION: - status->value.sig = TARGET_EXC_EMULATION; + status->value.sig = GDB_EXC_EMULATION; break; case EXC_SOFTWARE: if (thread->event.ex_data[0] == EXC_SOFT_SIGNAL) @@ -929,11 +928,11 @@ darwin_decode_message (mach_msg_header_t *hdr, } } else - status->value.sig = TARGET_EXC_SOFTWARE; + status->value.sig = GDB_EXC_SOFTWARE; break; case EXC_BREAKPOINT: /* Many internal GDB routines expect breakpoints to be reported - as GDB_SIGNAL_TRAP, and will report TARGET_EXC_BREAKPOINT + as GDB_SIGNAL_TRAP, and will report GDB_EXC_BREAKPOINT as a spurious signal. */ status->value.sig = GDB_SIGNAL_TRAP; break; @@ -1012,14 +1011,14 @@ cancel_breakpoint (ptid_t ptid) struct gdbarch *gdbarch = get_regcache_arch (regcache); CORE_ADDR pc; - pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch); + pc = regcache_read_pc (regcache) - target_decr_pc_after_break (gdbarch); if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) { inferior_debug (4, "cancel_breakpoint for thread 0x%x\n", ptid_get_tid (ptid)); /* Back up the PC if necessary. */ - if (gdbarch_decr_pc_after_break (gdbarch)) + if (target_decr_pc_after_break (gdbarch)) regcache_write_pc (regcache, pc); return 1; @@ -1345,7 +1344,7 @@ darwin_attach_pid (struct inferior *inf) mach_port_t prev_not; exception_mask_t mask; - inf->private = XZALLOC (darwin_inferior); + inf->private = XCNEW (darwin_inferior); kret = task_for_pid (gdb_task, inf->pid, &inf->private->task); if (kret != KERN_SUCCESS) @@ -1516,6 +1515,9 @@ darwin_pre_ptrace (void) ptrace_fds[1] = -1; error (_("unable to create a pipe: %s"), safe_strerror (errno)); } + + mark_fd_no_cloexec (ptrace_fds[0]); + mark_fd_no_cloexec (ptrace_fds[1]); } static void @@ -1533,6 +1535,9 @@ darwin_ptrace_him (int pid) close (ptrace_fds[0]); close (ptrace_fds[1]); + unmark_fd_no_cloexec (ptrace_fds[0]); + unmark_fd_no_cloexec (ptrace_fds[1]); + darwin_init_thread_list (inf); startup_inferior (START_INFERIOR_TRAPS_EXPECTED); @@ -1586,6 +1591,32 @@ darwin_create_inferior (struct target_ops *ops, char *exec_file, } +/* Set things up such that the next call to darwin_wait will immediately + return a fake stop event for inferior INF. + + This assumes that the inferior's thread list has been initialized, + as it will suspend the inferior's first thread. */ + +static void +darwin_setup_fake_stop_event (struct inferior *inf) +{ + darwin_thread_t *thread; + kern_return_t kret; + + gdb_assert (darwin_inf_fake_stop == NULL); + darwin_inf_fake_stop = inf; + + /* When detecting a fake pending stop event, darwin_wait returns + an event saying that the first thread is in a DARWIN_STOPPED + state. To make that accurate, we need to suspend that thread + as well. Otherwise, we'll try resuming it when resuming the + inferior, and get a warning because the thread's suspend count + is already zero, making the resume request useless. */ + thread = VEC_index (darwin_thread_t, inf->private->threads, 0); + kret = thread_suspend (thread->gdb_port); + MACH_CHECK_ERROR (kret); +} + /* Attach to process PID, then initialize for debugging it and wait for the trace-trap that results from attaching. */ static void @@ -1637,8 +1668,8 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty) darwin_check_osabi (inf->private, ptid_get_tid (inferior_ptid)); - gdb_assert (darwin_inf_fake_stop == NULL); - darwin_inf_fake_stop = inf; + darwin_setup_fake_stop_event (inf); + inf->private->no_ptrace = 1; } @@ -1650,7 +1681,7 @@ darwin_attach (struct target_ops *ops, char *args, int from_tty) previously attached. It *might* work if the program was started via fork. */ static void -darwin_detach (struct target_ops *ops, char *args, int from_tty) +darwin_detach (struct target_ops *ops, const char *args, int from_tty) { pid_t pid = ptid_get_pid (inferior_ptid); struct inferior *inf = current_inferior (); @@ -1729,7 +1760,7 @@ darwin_thread_alive (struct target_ops *ops, ptid_t ptid) static int darwin_read_write_inferior (task_t task, CORE_ADDR addr, gdb_byte *rdaddr, const gdb_byte *wraddr, - int length) + ULONGEST length) { kern_return_t kret; mach_vm_address_t offset = addr & (mach_page_size - 1); @@ -1741,8 +1772,8 @@ 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(task=0x%x, %s, len=%d)\n"), - task, core_addr_to_string (addr), length); + inferior_debug (8, _("darwin_read_write_inferior(task=0x%x, %s, len=%s)\n"), + task, core_addr_to_string (addr), pulongest (length)); /* Get memory from inferior with page aligned addresses. */ kret = mach_vm_read (task, low_address, aligned_length, @@ -1861,9 +1892,9 @@ out: #ifdef TASK_DYLD_INFO_COUNT /* This is not available in Darwin 9. */ -static int +static enum target_xfer_status darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr, - int length) + ULONGEST length, ULONGEST *xfered_len) { struct task_dyld_info task_dyld_info; mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; @@ -1871,72 +1902,65 @@ darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr, kern_return_t kret; if (addr >= sz) - return 0; + return TARGET_XFER_EOF; kret = task_info (task, TASK_DYLD_INFO, (task_info_t) &task_dyld_info, &count); MACH_CHECK_ERROR (kret); if (kret != KERN_SUCCESS) - return -1; + return TARGET_XFER_E_IO; /* Truncate. */ if (addr + length > sz) length = sz - addr; memcpy (rdaddr, (char *)&task_dyld_info + addr, length); - return length; + *xfered_len = (ULONGEST) length; + return TARGET_XFER_OK; } #endif -/* Return 0 on failure, number of bytes handled otherwise. TARGET - is ignored. */ -static int -darwin_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write, - struct mem_attrib *attrib, struct target_ops *target) -{ - struct inferior *inf = current_inferior (); - task_t task = inf->private->task; - - if (task == MACH_PORT_NULL) - return 0; - - inferior_debug (8, _("darwin_xfer_memory(%s, %d, %c)\n"), - core_addr_to_string (memaddr), len, write ? 'w' : 'r'); - - if (write) - return darwin_read_write_inferior (task, memaddr, NULL, myaddr, len); - else - return darwin_read_write_inferior (task, memaddr, myaddr, NULL, len); -} static LONGEST darwin_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { struct inferior *inf = current_inferior (); inferior_debug - (8, _("darwin_xfer_partial(%s, %d, rbuf=%s, wbuf=%s) pid=%u\n"), - core_addr_to_string (offset), (int)len, + (8, _("darwin_xfer_partial(%s, %s, rbuf=%s, wbuf=%s) pid=%u\n"), + core_addr_to_string (offset), pulongest (len), host_address_to_string (readbuf), host_address_to_string (writebuf), inf->pid); switch (object) { case TARGET_OBJECT_MEMORY: - return darwin_read_write_inferior (inf->private->task, offset, - readbuf, writebuf, len); + { + int l = darwin_read_write_inferior (inf->private->task, offset, + readbuf, writebuf, len); + + if (l == 0) + return TARGET_XFER_EOF; + else + { + gdb_assert (l > 0); + *xfered_len = (ULONGEST) l; + return TARGET_XFER_OK; + } + } #ifdef TASK_DYLD_INFO_COUNT case TARGET_OBJECT_DARWIN_DYLD_INFO: if (writebuf != NULL || readbuf == NULL) { /* Support only read. */ - return -1; + return TARGET_XFER_E_IO; } - return darwin_read_dyld_info (inf->private->task, offset, readbuf, len); + return darwin_read_dyld_info (inf->private->task, offset, readbuf, len, + xfered_len); #endif default: - return -1; + return TARGET_XFER_E_IO; } } @@ -1970,10 +1994,10 @@ darwin_pid_to_exec_file (int pid) char *path; int res; - path = xmalloc (MAXPATHLEN); + path = xmalloc (PATH_MAX); make_cleanup (xfree, path); - res = proc_pidinfo (pid, PROC_PIDPATHINFO, 0, path, MAXPATHLEN); + res = proc_pidinfo (pid, PROC_PIDPATHINFO, 0, path, PATH_MAX); if (res >= 0) return path; else @@ -2092,7 +2116,6 @@ _initialize_darwin_inferior (void) 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_supports_multi_process = darwin_supports_multi_process; darwin_ops->to_get_ada_task_ptid = darwin_get_ada_task_ptid;