/* Darwin support for GDB, the GNU debugger.
- Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Copyright (C) 2008-2018 Free Software Foundation, Inc.
Contributed by AdaCore.
#include "symfile.h"
#include "symtab.h"
#include "objfiles.h"
-#include "gdb.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "gdbthread.h"
#include <sys/ptrace.h>
#include <sys/signal.h>
-#include <machine/setjmp.h>
+#include <setjmp.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include "darwin-nat.h"
#include "common/filestuff.h"
+#include "nat/fork-inferior.h"
/* Quick overview.
Darwin kernel is Mach + BSD derived kernel. Note that they share the
#define PTRACE(CMD, PID, ADDR, SIG) \
darwin_ptrace(#CMD, CMD, (PID), (ADDR), (SIG))
-static void darwin_stop (struct target_ops *self, ptid_t);
-
-static void darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
- enum gdb_signal signal);
-static void darwin_resume (ptid_t ptid, int step,
- enum gdb_signal signal);
-
-static ptid_t darwin_wait_to (struct target_ops *ops, ptid_t ptid,
- struct target_waitstatus *status, int options);
static ptid_t darwin_wait (ptid_t ptid, struct target_waitstatus *status);
-static void darwin_mourn_inferior (struct target_ops *ops);
-
-static void darwin_kill_inferior (struct target_ops *ops);
-
static void darwin_ptrace_me (void);
static void darwin_ptrace_him (int pid);
-static void darwin_create_inferior (struct target_ops *ops, char *exec_file,
- char *allargs, char **env, int from_tty);
-
-static void darwin_files_info (struct target_ops *ops);
-
-static char *darwin_pid_to_str (struct target_ops *ops, ptid_t tpid);
-
-static int darwin_thread_alive (struct target_ops *ops, ptid_t tpid);
-
static void darwin_encode_reply (mig_reply_error_t *reply,
mach_msg_header_t *hdr, integer_t code);
+static void darwin_setup_request_notification (struct inferior *inf);
+static void darwin_deallocate_exception_ports (darwin_inferior *inf);
+static void darwin_setup_exceptions (struct inferior *inf);
+static void darwin_deallocate_threads (struct inferior *inf);
+
/* Target operations for Darwin. */
static struct target_ops *darwin_ops;
"</dict>\n"
"</plist>\n";
+static void inferior_debug (int level, const char *fmt, ...)
+ ATTRIBUTE_PRINTF (2, 3);
+
static void
inferior_debug (int level, const char *fmt, ...)
{
static int
darwin_ptrace (const char *name,
- int request, int pid, PTRACE_TYPE_ARG3 arg3, int arg4)
+ int request, int pid, caddr_t arg3, int arg4)
{
int ret;
errno = 0;
- ret = ptrace (request, pid, (caddr_t) arg3, arg4);
+ ret = ptrace (request, pid, arg3, arg4);
if (ret == -1 && errno == 0)
ret = 0;
- inferior_debug (4, _("ptrace (%s, %d, 0x%x, %d): %d (%s)\n"),
- name, pid, arg3, arg4, ret,
+ inferior_debug (4, _("ptrace (%s, %d, 0x%lx, %d): %d (%s)\n"),
+ name, pid, (unsigned long) arg3, arg4, ret,
(ret != 0) ? safe_strerror (errno) : _("no error"));
return ret;
}
darwin_check_new_threads (struct inferior *inf)
{
kern_return_t kret;
- unsigned int i;
thread_array_t thread_list;
unsigned int new_nbr;
unsigned int old_nbr;
unsigned int new_ix, old_ix;
- darwin_inferior *darwin_inf = inf->private;
- VEC (darwin_thread_t) *thread_vec;
+ darwin_inferior *darwin_inf = get_darwin_inferior (inf);
+ std::vector<darwin_thread_t *> new_thread_vec;
/* Get list of threads. */
kret = task_threads (darwin_inf->task, &thread_list, &new_nbr);
if (new_nbr > 1)
qsort (thread_list, new_nbr, sizeof (thread_t), cmp_thread_t);
- if (darwin_inf->threads)
- old_nbr = VEC_length (darwin_thread_t, darwin_inf->threads);
- else
- old_nbr = 0;
+ old_nbr = darwin_inf->threads.size ();
/* Quick check for no changes. */
if (old_nbr == new_nbr)
{
+ size_t i;
+
for (i = 0; i < new_nbr; i++)
- if (thread_list[i]
- != VEC_index (darwin_thread_t, darwin_inf->threads, i)->gdb_port)
+ if (thread_list[i] != darwin_inf->threads[i]->gdb_port)
break;
if (i == new_nbr)
{
}
}
- thread_vec = VEC_alloc (darwin_thread_t, new_nbr);
+ /* Full handling: detect new threads, remove dead threads. */
+
+ new_thread_vec.reserve (new_nbr);
for (new_ix = 0, old_ix = 0; new_ix < new_nbr || old_ix < old_nbr;)
{
- thread_t new_id = (new_ix < new_nbr) ?
- thread_list[new_ix] : THREAD_NULL;
- darwin_thread_t *old = (old_ix < old_nbr) ?
- VEC_index (darwin_thread_t, darwin_inf->threads, old_ix) : NULL;
- thread_t old_id = old ? old->gdb_port : THREAD_NULL;
+ thread_t new_id = (new_ix < new_nbr) ? thread_list[new_ix] : THREAD_NULL;
+ darwin_thread_t *old
+ = (old_ix < old_nbr) ? darwin_inf->threads[old_ix] : NULL;
+ thread_t old_id = old != NULL ? old->gdb_port : THREAD_NULL;
inferior_debug
(12, _(" new_ix:%d/%d, old_ix:%d/%d, new_id:0x%x old_id:0x%x\n"),
if (old_id == new_id)
{
/* Thread still exist. */
- VEC_safe_push (darwin_thread_t, thread_vec, old);
+ new_thread_vec.push_back (old);
new_ix++;
old_ix++;
if (new_ix < new_nbr && (old_ix == old_nbr || new_id < old_id))
{
/* A thread was created. */
- struct thread_info *tp;
- struct private_thread_info *pti;
+ darwin_thread_info *pti = new darwin_thread_info;
- pti = XCNEW (struct private_thread_info);
pti->gdb_port = new_id;
pti->msg_state = DARWIN_RUNNING;
- /* Add a new thread unless this is the first one ever met. */
- if (!(old_nbr == 0 && new_ix == 0))
- tp = add_thread_with_info (ptid_build (inf->pid, 0, new_id), pti);
- else
- {
- tp = find_thread_ptid (ptid_build (inf->pid, 0, 0));
- gdb_assert (tp);
- tp->private = pti;
- }
- VEC_safe_push (darwin_thread_t, thread_vec, pti);
+ /* Add the new thread. */
+ add_thread_with_info (ptid_build (inf->pid, 0, new_id), pti);
+ new_thread_vec.push_back (pti);
new_ix++;
continue;
}
gdb_assert_not_reached ("unexpected thread case");
}
- if (darwin_inf->threads)
- VEC_free (darwin_thread_t, darwin_inf->threads);
- darwin_inf->threads = thread_vec;
+ darwin_inf->threads = std::move (new_thread_vec);
/* Deallocate the buffer. */
kret = vm_deallocate (gdb_task, (vm_address_t) thread_list,
static int
find_inferior_task_it (struct inferior *inf, void *port_ptr)
{
- return inf->private->task == *(task_t*)port_ptr;
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ return priv->task == *(task_t *)port_ptr;
}
static int
-find_inferior_notify_it (struct inferior *inf, void *port_ptr)
+find_inferior_pid_it (struct inferior *inf, void *pid_ptr)
{
- return inf->private->notify_port == *(task_t*)port_ptr;
+ return inf->pid == *(int *)pid_ptr;
}
/* Return an inferior by task port. */
return iterate_over_inferiors (&find_inferior_task_it, &port);
}
-/* Return an inferior by notification port. */
+/* Return an inferior by pid port. */
static struct inferior *
-darwin_find_inferior_by_notify (mach_port_t port)
+darwin_find_inferior_by_pid (int pid)
{
- return iterate_over_inferiors (&find_inferior_notify_it, &port);
+ return iterate_over_inferiors (&find_inferior_pid_it, &pid);
}
/* Return a thread by port. */
static darwin_thread_t *
darwin_find_thread (struct inferior *inf, thread_t thread)
{
- darwin_thread_t *t;
- int k;
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ for (darwin_thread_t *t : priv->threads)
+ {
+ if (t->gdb_port == thread)
+ return t;
+ }
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
- k++)
- if (t->gdb_port == thread)
- return t;
return NULL;
}
static void
darwin_suspend_inferior (struct inferior *inf)
{
- if (!inf->private->suspended)
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ if (!priv->suspended)
{
kern_return_t kret;
- kret = task_suspend (inf->private->task);
+ kret = task_suspend (priv->task);
MACH_CHECK_ERROR (kret);
- inf->private->suspended = 1;
+ priv->suspended = 1;
}
}
static void
darwin_resume_inferior (struct inferior *inf)
{
- if (inf->private->suspended)
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ if (priv->suspended)
{
kern_return_t kret;
- kret = task_resume (inf->private->task);
+ kret = task_resume (priv->task);
MACH_CHECK_ERROR (kret);
- inf->private->suspended = 0;
+ priv->suspended = 0;
}
}
}
}
+/* Adjust inferior data when a new task was created. */
+
+static struct inferior *
+darwin_find_new_inferior (task_t task_port, thread_t thread_port)
+{
+ int task_pid;
+ struct inferior *inf;
+ kern_return_t kret;
+ mach_port_t prev;
+
+ /* Find the corresponding pid. */
+ kret = pid_for_task (task_port, &task_pid);
+ if (kret != KERN_SUCCESS)
+ {
+ MACH_CHECK_ERROR (kret);
+ return NULL;
+ }
+
+ /* Find the inferior for this pid. */
+ inf = darwin_find_inferior_by_pid (task_pid);
+ if (inf == NULL)
+ return NULL;
+
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ /* Deallocate saved exception ports. */
+ darwin_deallocate_exception_ports (priv);
+
+ /* No need to remove dead_name notification, but still... */
+ kret = mach_port_request_notification (gdb_task, priv->task,
+ MACH_NOTIFY_DEAD_NAME, 0,
+ MACH_PORT_NULL,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &prev);
+ if (kret != KERN_INVALID_ARGUMENT)
+ MACH_CHECK_ERROR (kret);
+
+ /* Replace old task port. */
+ kret = mach_port_deallocate (gdb_task, priv->task);
+ MACH_CHECK_ERROR (kret);
+ priv->task = task_port;
+
+ darwin_setup_request_notification (inf);
+ darwin_setup_exceptions (inf);
+
+ return inf;
+}
+
+/* Check data representation. */
+
+static int
+darwin_check_message_ndr (NDR_record_t *ndr)
+{
+ if (ndr->mig_vers != NDR_PROTOCOL_2_0
+ || ndr->if_vers != NDR_PROTOCOL_2_0
+ || ndr->mig_encoding != NDR_record.mig_encoding
+ || ndr->int_rep != NDR_record.int_rep
+ || ndr->char_rep != NDR_record.char_rep
+ || ndr->float_rep != NDR_record.float_rep)
+ return -1;
+ return 0;
+}
+
+/* Decode an exception message. */
+
static int
darwin_decode_exception_message (mach_msg_header_t *hdr,
struct inferior **pinf,
/* Check data representation. */
ndr = (NDR_record_t *)(desc + 2);
- if (ndr->mig_vers != NDR_PROTOCOL_2_0
- || ndr->if_vers != NDR_PROTOCOL_2_0
- || ndr->mig_encoding != NDR_record.mig_encoding
- || ndr->int_rep != NDR_record.int_rep
- || ndr->char_rep != NDR_record.char_rep
- || ndr->float_rep != NDR_record.float_rep)
+ if (darwin_check_message_ndr (ndr) != 0)
return -1;
/* Ok, the hard work. */
task_port = desc[1].name;
thread_port = desc[0].name;
- /* We got new rights to the task, get rid of it. Do not get rid of thread
- right, as we will need it to find the thread. */
- kret = mach_port_deallocate (mach_task_self (), task_port);
- MACH_CHECK_ERROR (kret);
-
/* Find process by port. */
inf = darwin_find_inferior_by_task (task_port);
*pinf = inf;
+
+ if (inf == NULL && data[0] == EXC_SOFTWARE && data[1] == 2
+ && data[2] == EXC_SOFT_SIGNAL && data[3] == SIGTRAP)
+ {
+ /* Not a known inferior, but a sigtrap. This happens on darwin 16.1.0,
+ as a new Mach task is created when a process exec. */
+ inf = darwin_find_new_inferior (task_port, thread_port);
+ *pinf = inf;
+
+ if (inf == NULL)
+ {
+ /* Deallocate task_port, unless it was saved. */
+ kret = mach_port_deallocate (mach_task_self (), task_port);
+ MACH_CHECK_ERROR (kret);
+ }
+ }
+ else
+ {
+ /* We got new rights to the task, get rid of it. Do not get rid of
+ thread right, as we will need it to find the thread. */
+ kret = mach_port_deallocate (mach_task_self (), task_port);
+ MACH_CHECK_ERROR (kret);
+ }
+
if (inf == NULL)
{
/* Not a known inferior. This could happen if the child fork, as
kern_return_t kret;
mig_reply_error_t reply;
+ inferior_debug
+ (4, _("darwin_decode_exception_message: unknown task 0x%x\n"),
+ task_port);
+
/* Free thread port (we don't know it). */
kret = mach_port_deallocate (mach_task_self (), thread_port);
MACH_CHECK_ERROR (kret);
return 0;
}
+/* Decode dead_name notify message. */
+
+static int
+darwin_decode_notify_message (mach_msg_header_t *hdr, struct inferior **pinf)
+{
+ NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
+ integer_t *data = (integer_t *)(ndr + 1);
+ struct inferior *inf;
+ darwin_thread_t *thread;
+ task_t task_port;
+ thread_t thread_port;
+ kern_return_t kret;
+ int i;
+
+ /* Check message header. */
+ if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+ return -1;
+
+ /* Check descriptors. */
+ if (hdr->msgh_size < (sizeof (*hdr) + sizeof (*ndr) + sizeof (integer_t)))
+ return -2;
+
+ /* Check data representation. */
+ if (darwin_check_message_ndr (ndr) != 0)
+ return -3;
+
+ task_port = data[0];
+
+ /* Find process by port. */
+ inf = darwin_find_inferior_by_task (task_port);
+ *pinf = inf;
+
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ /* Check message destination. */
+ if (inf != NULL && hdr->msgh_local_port != priv->notify_port)
+ return -4;
+
+ return 0;
+}
+
static void
darwin_encode_reply (mig_reply_error_t *reply, mach_msg_header_t *hdr,
integer_t code)
{
kern_return_t kret;
mig_reply_error_t reply;
+ darwin_inferior *priv = get_darwin_inferior (inf);
darwin_encode_reply (&reply, &thread->event.header, KERN_SUCCESS);
MACH_PORT_NULL);
MACH_CHECK_ERROR (kret);
- inf->private->pending_messages--;
+ priv->pending_messages--;
}
static void
{
/* Either deliver a new signal or cancel the signal received. */
res = PTRACE (PT_THUPDATE, inf->pid,
- (void *)(uintptr_t)thread->gdb_port, nsignal);
+ (caddr_t) (uintptr_t) thread->gdb_port, nsignal);
if (res < 0)
inferior_debug (1, _("ptrace THUP: res=%d\n"), res);
}
}
/* Set or reset single step. */
- if (step != thread->single_step)
- {
- inferior_debug (4, _("darwin_set_sstep (thread=0x%x, enable=%d)\n"),
- thread->gdb_port, step);
- darwin_set_sstep (thread->gdb_port, step);
- thread->single_step = step;
- }
+ inferior_debug (4, _("darwin_set_sstep (thread=0x%x, enable=%d)\n"),
+ thread->gdb_port, step);
+ darwin_set_sstep (thread->gdb_port, step);
+ thread->single_step = step;
darwin_send_reply (inf, thread);
thread->msg_state = DARWIN_RUNNING;
static void
darwin_resume_inferior_threads (struct inferior *inf, int step, int nsignal)
{
- darwin_thread_t *thread;
- int k;
+ darwin_inferior *priv = get_darwin_inferior (inf);
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, thread);
- k++)
+ for (darwin_thread_t *thread : priv->threads)
darwin_resume_thread (inf, thread, step, nsignal);
}
static void
darwin_suspend_inferior_threads (struct inferior *inf)
{
- darwin_thread_t *thread;
- kern_return_t kret;
- int k;
+ darwin_inferior *priv = get_darwin_inferior (inf);
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, thread);
- k++)
- switch (thread->msg_state)
- {
- case DARWIN_STOPPED:
- case DARWIN_MESSAGE:
- break;
- case DARWIN_RUNNING:
- kret = thread_suspend (thread->gdb_port);
- MACH_CHECK_ERROR (kret);
- thread->msg_state = DARWIN_STOPPED;
- break;
- }
+ for (darwin_thread_t *thread : priv->threads)
+ {
+ switch (thread->msg_state)
+ {
+ case DARWIN_STOPPED:
+ case DARWIN_MESSAGE:
+ break;
+ case DARWIN_RUNNING:
+ {
+ kern_return_t kret = thread_suspend (thread->gdb_port);
+ MACH_CHECK_ERROR (kret);
+ thread->msg_state = DARWIN_STOPPED;
+ break;
+ }
+ }
+ }
}
-static void
-darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
+void
+darwin_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
{
struct target_waitstatus status;
int pid;
struct inferior *inf;
inferior_debug
- (2, _("darwin_resume: pid=%d, tid=0x%x, step=%d, signal=%d\n"),
+ (2, _("darwin_resume: pid=%d, tid=0x%lx, step=%d, signal=%d\n"),
ptid_get_pid (ptid), ptid_get_tid (ptid), step, signal);
if (signal == GDB_SIGNAL_0)
}
else
{
- struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid));
+ struct inferior *inf = find_inferior_ptid (ptid);
long tid = ptid_get_tid (ptid);
/* Stop the inferior (should be useless). */
}
}
-static void
-darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
- enum gdb_signal signal)
-{
- return darwin_resume (ptid, step, signal);
-}
-
static ptid_t
darwin_decode_message (mach_msg_header_t *hdr,
darwin_thread_t **pthread,
}
*pinf = inf;
*pthread = thread;
- inf->private->pending_messages++;
+
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ priv->pending_messages++;
status->kind = TARGET_WAITKIND_STOPPED;
thread->msg_state = DARWIN_MESSAGE;
else if (hdr->msgh_id == 0x48)
{
/* MACH_NOTIFY_DEAD_NAME: notification for exit. */
+ int res;
+
+ res = darwin_decode_notify_message (hdr, &inf);
+
+ if (res < 0)
+ {
+ /* Should not happen... */
+ printf_unfiltered
+ (_("darwin_wait: ill-formatted message (id=0x%x, res=%d)\n"),
+ hdr->msgh_id, res);
+ }
+
*pinf = NULL;
*pthread = NULL;
- inf = darwin_find_inferior_by_notify (hdr->msgh_local_port);
+ if (res < 0 || inf == NULL)
+ {
+ status->kind = TARGET_WAITKIND_IGNORE;
+ return minus_one_ptid;
+ }
+
if (inf != NULL)
{
- if (!inf->private->no_ptrace)
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ if (!priv->no_ptrace)
{
pid_t res;
int wstatus;
else
{
status->kind = TARGET_WAITKIND_SIGNALLED;
- status->value.sig = WTERMSIG (wstatus);
+ status->value.sig = gdb_signal_from_host (WTERMSIG (wstatus));
}
inferior_debug (4, _("darwin_wait: pid=%d exit, status=0x%x\n"),
/* Looks necessary on Leopard and harmless... */
wait4 (inf->pid, &wstatus, 0, NULL);
- return ptid_build (inf->pid, 0, 0);
+ inferior_ptid = ptid_build (inf->pid, 0, 0);
+ return inferior_ptid;
}
else
{
tripped on it. */
struct regcache *regcache = get_thread_regcache (ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR pc;
- pc = regcache_read_pc (regcache) - target_decr_pc_after_break (gdbarch);
- if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+ pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch);
+ if (breakpoint_inserted_here_p (regcache->aspace (), pc))
{
- inferior_debug (4, "cancel_breakpoint for thread 0x%x\n",
- ptid_get_tid (ptid));
+ inferior_debug (4, "cancel_breakpoint for thread 0x%lx\n",
+ (unsigned long) ptid_get_tid (ptid));
/* Back up the PC if necessary. */
- if (target_decr_pc_after_break (gdbarch))
+ if (gdbarch_decr_pc_after_break (gdbarch))
regcache_write_pc (regcache, pc);
return 1;
inf = darwin_inf_fake_stop;
darwin_inf_fake_stop = NULL;
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = GDB_SIGNAL_TRAP;
- thread = VEC_index (darwin_thread_t, inf->private->threads, 0);
+ thread = priv->threads[0];
thread->msg_state = DARWIN_STOPPED;
return ptid_build (inf->pid, 0, thread->gdb_port);
}
return res;
}
-static ptid_t
-darwin_wait_to (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+darwin_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
+ int options)
{
return darwin_wait (ptid, status);
}
-static void
-darwin_stop (struct target_ops *self, ptid_t t)
+void
+darwin_nat_target::interrupt ()
{
struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
/* FIXME: handle in no_ptrace mode. */
- gdb_assert (!inf->private->no_ptrace);
- kill (inf->pid, SIGINT);
+ gdb_assert (!priv->no_ptrace);
+ ::kill (inf->pid, SIGINT);
}
+/* Deallocate threads port and vector. */
+
static void
-darwin_mourn_inferior (struct target_ops *ops)
+darwin_deallocate_threads (struct inferior *inf)
+{
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ for (darwin_thread_t *t : priv->threads)
+ {
+ kern_return_t kret = mach_port_deallocate (gdb_task, t->gdb_port);
+ MACH_CHECK_ERROR (kret);
+ }
+
+ priv->threads.clear ();
+}
+
+void
+darwin_nat_target::mourn_inferior ()
{
struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
kern_return_t kret;
mach_port_t prev;
int i;
/* Deallocate threads. */
- if (inf->private->threads)
- {
- int k;
- darwin_thread_t *t;
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
- k++)
- {
- kret = mach_port_deallocate (gdb_task, t->gdb_port);
- MACH_CHECK_ERROR (kret);
- }
- VEC_free (darwin_thread_t, inf->private->threads);
- inf->private->threads = NULL;
- }
+ darwin_deallocate_threads (inf);
+ /* Remove notify_port from darwin_port_set. */
kret = mach_port_move_member (gdb_task,
- inf->private->notify_port, MACH_PORT_NULL);
+ priv->notify_port, MACH_PORT_NULL);
MACH_CHECK_ERROR (kret);
- kret = mach_port_request_notification (gdb_task, inf->private->task,
+ /* Remove task port dead_name notification. */
+ kret = mach_port_request_notification (gdb_task, priv->task,
MACH_NOTIFY_DEAD_NAME, 0,
MACH_PORT_NULL,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&prev);
/* This can fail if the task is dead. */
inferior_debug (4, "task=0x%x, prev=0x%x, notify_port=0x%x\n",
- inf->private->task, prev, inf->private->notify_port);
+ priv->task, prev, priv->notify_port);
if (kret == KERN_SUCCESS)
{
MACH_CHECK_ERROR (kret);
}
- kret = mach_port_destroy (gdb_task, inf->private->notify_port);
+ /* Destroy notify_port. */
+ kret = mach_port_destroy (gdb_task, priv->notify_port);
MACH_CHECK_ERROR (kret);
-
/* Deallocate saved exception ports. */
- for (i = 0; i < inf->private->exception_info.count; i++)
- {
- kret = mach_port_deallocate
- (gdb_task, inf->private->exception_info.ports[i]);
- MACH_CHECK_ERROR (kret);
- }
- inf->private->exception_info.count = 0;
+ darwin_deallocate_exception_ports (priv);
- kret = mach_port_deallocate (gdb_task, inf->private->task);
+ /* Deallocate task port. */
+ kret = mach_port_deallocate (gdb_task, priv->task);
MACH_CHECK_ERROR (kret);
- xfree (inf->private);
- inf->private = NULL;
+ inf->priv = NULL;
- inf_child_mourn_inferior (ops);
+ inf_child_target::mourn_inferior ();
}
static void
darwin_reply_to_all_pending_messages (struct inferior *inf)
{
- int k;
- darwin_thread_t *t;
+ darwin_inferior *priv = get_darwin_inferior (inf);
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
- k++)
+ for (darwin_thread_t *t : priv->threads)
{
if (t->msg_state == DARWIN_MESSAGE)
darwin_resume_thread (inf, t, 0, 0);
kern_return_t kret;
int status;
int res;
+ darwin_inferior *priv = get_darwin_inferior (inf);
gdb_assert (inf != NULL);
darwin_reply_to_all_pending_messages (inf);
- if (inf->private->no_ptrace)
+ if (priv->no_ptrace)
return;
res = kill (inf->pid, SIGSTOP);
return KERN_SUCCESS;
}
+/* Deallocate saved exception ports. */
+
+static void
+darwin_deallocate_exception_ports (darwin_inferior *inf)
+{
+ int i;
+ kern_return_t kret;
+
+ for (i = 0; i < inf->exception_info.count; i++)
+ {
+ kret = mach_port_deallocate (gdb_task, inf->exception_info.ports[i]);
+ MACH_CHECK_ERROR (kret);
+ }
+ inf->exception_info.count = 0;
+}
+
static void
-darwin_kill_inferior (struct target_ops *ops)
+darwin_setup_exceptions (struct inferior *inf)
+{
+ darwin_inferior *priv = get_darwin_inferior (inf);
+ kern_return_t kret;
+ int traps_expected;
+ exception_mask_t mask;
+
+ kret = darwin_save_exception_ports (priv);
+ if (kret != KERN_SUCCESS)
+ error (_("Unable to save exception ports, task_get_exception_ports"
+ "returned: %d"),
+ kret);
+
+ /* Set exception port. */
+ if (enable_mach_exceptions)
+ mask = EXC_MASK_ALL;
+ else
+ mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
+ kret = task_set_exception_ports (priv->task, mask, darwin_ex_port,
+ EXCEPTION_DEFAULT, THREAD_STATE_NONE);
+ if (kret != KERN_SUCCESS)
+ error (_("Unable to set exception ports, task_set_exception_ports"
+ "returned: %d"),
+ kret);
+}
+
+void
+darwin_nat_target::kill ()
{
struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
struct target_waitstatus wstatus;
ptid_t ptid;
kern_return_t kret;
gdb_assert (inf != NULL);
- kret = darwin_restore_exception_ports (inf->private);
+ kret = darwin_restore_exception_ports (priv);
MACH_CHECK_ERROR (kret);
darwin_reply_to_all_pending_messages (inf);
- res = kill (inf->pid, 9);
+ res = ::kill (inf->pid, 9);
if (res == 0)
{
warning (_("Failed to kill inferior: kill (%d, 9) returned [%s]"),
inf->pid, safe_strerror (errno));
- target_mourn_inferior ();
+ target_mourn_inferior (inferior_ptid);
+}
+
+static void
+darwin_setup_request_notification (struct inferior *inf)
+{
+ darwin_inferior *priv = get_darwin_inferior (inf);
+ kern_return_t kret;
+ mach_port_t prev_not;
+
+ kret = mach_port_request_notification (gdb_task, priv->task,
+ MACH_NOTIFY_DEAD_NAME, 0,
+ priv->notify_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &prev_not);
+ if (kret != KERN_SUCCESS)
+ error (_("Termination notification request failed, "
+ "mach_port_request_notification\n"
+ "returned: %d"),
+ kret);
+ if (prev_not != MACH_PORT_NULL)
+ {
+ /* This is unexpected, as there should not be any previously
+ registered notification request. But this is not a fatal
+ issue, so just emit a warning. */
+ warning (_("\
+A task termination request was registered before the debugger registered\n\
+its own. This is unexpected, but should otherwise not have any actual\n\
+impact on the debugging session."));
+ }
}
static void
mach_port_t prev_not;
exception_mask_t mask;
- inf->private = XCNEW (darwin_inferior);
+ darwin_inferior *priv = new darwin_inferior;
+ inf->priv.reset (priv);
- kret = task_for_pid (gdb_task, inf->pid, &inf->private->task);
+ kret = task_for_pid (gdb_task, inf->pid, &priv->task);
if (kret != KERN_SUCCESS)
{
int status;
}
inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"),
- inf->private->task, inf->pid);
+ priv->task, inf->pid);
if (darwin_ex_port == MACH_PORT_NULL)
{
/* 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);
+ &priv->notify_port);
if (kret != KERN_SUCCESS)
error (_("Unable to create notification port, mach_port_allocate "
"returned: %d"),
kret);
kret = mach_port_move_member (gdb_task,
- inf->private->notify_port, darwin_port_set);
+ priv->notify_port, darwin_port_set);
if (kret != KERN_SUCCESS)
error (_("Unable to move notification port into new port set, "
"mach_port_move_member\n"
"returned: %d"),
kret);
- kret = mach_port_request_notification (gdb_task, inf->private->task,
- MACH_NOTIFY_DEAD_NAME, 0,
- inf->private->notify_port,
- MACH_MSG_TYPE_MAKE_SEND_ONCE,
- &prev_not);
- if (kret != KERN_SUCCESS)
- error (_("Termination notification request failed, "
- "mach_port_request_notification\n"
- "returned: %d"),
- kret);
- if (prev_not != MACH_PORT_NULL)
- {
- /* This is unexpected, as there should not be any previously
- registered notification request. But this is not a fatal
- issue, so just emit a warning. */
- warning (_("\
-A task termination request was registered before the debugger registered\n\
-its own. This is unexpected, but should otherwise not have any actual\n\
-impact on the debugging session."));
- }
-
- kret = darwin_save_exception_ports (inf->private);
- if (kret != KERN_SUCCESS)
- error (_("Unable to save exception ports, task_get_exception_ports"
- "returned: %d"),
- kret);
+ darwin_setup_request_notification (inf);
- /* Set exception port. */
- if (enable_mach_exceptions)
- mask = EXC_MASK_ALL;
- else
- mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
- kret = task_set_exception_ports (inf->private->task, mask, darwin_ex_port,
- EXCEPTION_DEFAULT, THREAD_STATE_NONE);
- if (kret != KERN_SUCCESS)
- error (_("Unable to set exception ports, task_set_exception_ports"
- "returned: %d"),
- kret);
+ darwin_setup_exceptions (inf);
if (!target_is_pushed (darwin_ops))
push_target (darwin_ops);
}
+/* Get the thread_info object corresponding to this darwin_thread_info. */
+
+static struct thread_info *
+thread_info_from_private_thread_info (darwin_thread_info *pti)
+{
+ struct thread_info *it;
+
+ ALL_THREADS (it)
+ {
+ darwin_thread_info *iter_pti = get_darwin_thread_info (it);
+
+ if (iter_pti->gdb_port == pti->gdb_port)
+ break;
+ }
+
+ gdb_assert (it != NULL);
+
+ return it;
+}
+
static void
darwin_init_thread_list (struct inferior *inf)
{
- darwin_thread_t *thread;
- ptid_t new_ptid;
-
darwin_check_new_threads (inf);
- gdb_assert (inf->private->threads
- && VEC_length (darwin_thread_t, inf->private->threads) > 0);
- thread = VEC_index (darwin_thread_t, inf->private->threads, 0);
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ gdb_assert (!priv->threads.empty ());
- /* 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;
+ darwin_thread_info *first_pti = priv->threads.front ();
+ struct thread_info *first_thread
+ = thread_info_from_private_thread_info (first_pti);
+
+ inferior_ptid = first_thread->ptid;
}
/* The child must synchronize with gdb: gdb must set the exception port
char c;
/* Close write end point. */
- close (ptrace_fds[1]);
+ if (close (ptrace_fds[1]) < 0)
+ trace_start_error_with_name ("close");
/* Wait until gdb is ready. */
res = read (ptrace_fds[0], &c, 1);
if (res != 0)
- error (_("unable to read from pipe, read returned: %d"), res);
- close (ptrace_fds[0]);
+ trace_start_error (_("unable to read from pipe, read returned: %d"), res);
+
+ if (close (ptrace_fds[0]) < 0)
+ trace_start_error_with_name ("close");
/* Get rid of privileges. */
- setegid (getgid ());
+ if (setegid (getgid ()) < 0)
+ trace_start_error_with_name ("setegid");
/* Set TRACEME. */
- PTRACE (PT_TRACE_ME, 0, 0, 0);
+ if (PTRACE (PT_TRACE_ME, 0, 0, 0) < 0)
+ trace_start_error_with_name ("PTRACE");
/* Redirect signals to exception port. */
- PTRACE (PT_SIGEXC, 0, 0, 0);
+ if (PTRACE (PT_SIGEXC, 0, 0, 0) < 0)
+ trace_start_error_with_name ("PTRACE");
}
/* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2). */
darwin_init_thread_list (inf);
- startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+ gdb_startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED);
}
static void
posix_spawnp (NULL, argv[0], NULL, &attr, argv, env);
}
-static void
-darwin_create_inferior (struct target_ops *ops, char *exec_file,
- char *allargs, char **env, int from_tty)
+void
+darwin_nat_target::create_inferior (const char *exec_file,
+ const std::string &allargs,
+ char **env, int from_tty)
{
/* Do the hard work. */
- fork_inferior (exec_file, allargs, env, darwin_ptrace_me, darwin_ptrace_him,
- darwin_pre_ptrace, NULL, darwin_execvp);
-
- /* Return now in case of error. */
- if (ptid_equal (inferior_ptid, null_ptid))
- return;
+ fork_inferior (exec_file, allargs, env, darwin_ptrace_me,
+ darwin_ptrace_him, darwin_pre_ptrace, NULL,
+ darwin_execvp);
}
\f
static void
darwin_setup_fake_stop_event (struct inferior *inf)
{
+ darwin_inferior *priv = get_darwin_inferior (inf);
darwin_thread_t *thread;
kern_return_t kret;
as well. Otherwise, we'll try resuming it when resuming the
inferior, and get a warning because the thread's suspend count
is already zero, making the resume request useless. */
- thread = VEC_index (darwin_thread_t, inf->private->threads, 0);
+ thread = priv->threads[0];
kret = thread_suspend (thread->gdb_port);
MACH_CHECK_ERROR (kret);
}
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
-static void
-darwin_attach (struct target_ops *ops, const char *args, int from_tty)
+void
+darwin_nat_target::attach (const char *args, int from_tty)
{
pid_t pid;
pid_t pid2;
gdb_flush (gdb_stdout);
}
- if (pid == 0 || kill (pid, 0) < 0)
+ if (pid == 0 || ::kill (pid, 0) < 0)
error (_("Can't attach to process %d: %s (%d)"),
pid, safe_strerror (errno), errno);
inferior_appeared (inf, pid);
inf->attach_flag = 1;
- /* Always add a main thread. */
- add_thread_silent (inferior_ptid);
-
darwin_attach_pid (inf);
darwin_suspend_inferior (inf);
darwin_init_thread_list (inf);
- darwin_check_osabi (inf->private, ptid_get_tid (inferior_ptid));
+ darwin_inferior *priv = get_darwin_inferior (inf);
+
+ darwin_check_osabi (priv, ptid_get_tid (inferior_ptid));
darwin_setup_fake_stop_event (inf);
- inf->private->no_ptrace = 1;
+ priv->no_ptrace = 1;
}
/* Take a program previously attached to and detaches it.
to work, it may be necessary for the process to have been
previously attached. It *might* work if the program was
started via fork. */
-static void
-darwin_detach (struct target_ops *ops, const char *args, int from_tty)
+
+void
+darwin_nat_target::detach (inferior *inf, int from_tty)
{
pid_t pid = ptid_get_pid (inferior_ptid);
- struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
kern_return_t kret;
int res;
/* Display message. */
- if (from_tty)
- {
- char *exec_file = get_exec_file (0);
- if (exec_file == 0)
- exec_file = "";
- printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (pid_to_ptid (pid)));
- gdb_flush (gdb_stdout);
- }
+ target_announce_detach (from_tty);
/* If ptrace() is in use, stop the process. */
- if (!inf->private->no_ptrace)
+ if (!priv->no_ptrace)
darwin_stop_inferior (inf);
- kret = darwin_restore_exception_ports (inf->private);
+ kret = darwin_restore_exception_ports (priv);
MACH_CHECK_ERROR (kret);
- if (!inf->private->no_ptrace)
+ if (!priv->no_ptrace)
{
res = PTRACE (PT_DETACH, inf->pid, 0, 0);
if (res != 0)
/* When using ptrace, we have just performed a PT_DETACH, which
resumes the inferior. On the other hand, when we are not using
ptrace, we need to resume its execution ourselves. */
- if (inf->private->no_ptrace)
+ if (priv->no_ptrace)
darwin_resume_inferior (inf);
- darwin_mourn_inferior (ops);
+ mourn_inferior ();
}
-static void
-darwin_files_info (struct target_ops *ops)
-{
-}
-
-static char *
-darwin_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+darwin_nat_target::pid_to_str (ptid_t ptid)
{
static char buf[80];
long tid = ptid_get_tid (ptid);
return normal_pid_to_str (ptid);
}
-static int
-darwin_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+darwin_nat_target::thread_alive (ptid_t ptid)
{
- return 1;
+ return true;
}
/* If RDADDR is not NULL, read inferior task's LEN bytes from ADDR and
If WRADDR is not NULL, write gdb's LEN bytes from WRADDR and copy it
to ADDR in inferior task's address space.
Return 0 on failure; number of bytes read / writen otherwise. */
+
static int
darwin_read_write_inferior (task_t task, CORE_ADDR addr,
gdb_byte *rdaddr, const gdb_byte *wraddr,
ULONGEST length)
{
kern_return_t kret;
- mach_vm_address_t offset = addr & (mach_page_size - 1);
- mach_vm_address_t low_address = (mach_vm_address_t) (addr - offset);
- mach_vm_size_t aligned_length = (mach_vm_size_t) PAGE_ROUND (offset + length);
+ mach_vm_size_t res_length = 0;
pointer_t copied;
mach_msg_type_number_t copy_count;
mach_vm_size_t remaining_length;
inferior_debug (8, _("darwin_read_write_inferior(task=0x%x, %s, len=%s)\n"),
task, core_addr_to_string (addr), pulongest (length));
- /* Get memory from inferior with page aligned addresses. */
- kret = mach_vm_read (task, low_address, aligned_length,
- &copied, ©_count);
- if (kret != KERN_SUCCESS)
+ /* First read. */
+ if (rdaddr != NULL)
{
- inferior_debug
- (1, _("darwin_read_write_inferior: mach_vm_read failed at %s: %s"),
- core_addr_to_string (addr), mach_error_string (kret));
- return 0;
- }
+ mach_vm_size_t count;
- if (rdaddr != NULL)
- memcpy (rdaddr, (char *)copied + offset, length);
+ /* According to target.h(to_xfer_partial), one and only one may be
+ non-null. */
+ gdb_assert (wraddr == NULL);
- if (wraddr == NULL)
- goto out;
+ kret = mach_vm_read_overwrite (task, addr, length,
+ (mach_vm_address_t) rdaddr, &count);
+ if (kret != KERN_SUCCESS)
+ {
+ inferior_debug
+ (1, _("darwin_read_write_inferior: mach_vm_read failed at %s: %s"),
+ core_addr_to_string (addr), mach_error_string (kret));
+ return 0;
+ }
+ return count;
+ }
- memcpy ((char *)copied + offset, wraddr, length);
+ /* See above. */
+ gdb_assert (wraddr != NULL);
- /* Do writes atomically.
- First check for holes and unwritable memory. */
- for (region_address = low_address, remaining_length = aligned_length;
- region_address < low_address + aligned_length;
- region_address += region_length, remaining_length -= region_length)
+ while (length != 0)
{
+ mach_vm_address_t offset = addr & (mach_page_size - 1);
+ mach_vm_address_t region_address = (mach_vm_address_t) (addr - offset);
+ mach_vm_size_t aligned_length =
+ (mach_vm_size_t) PAGE_ROUND (offset + length);
vm_region_submap_short_info_data_64_t info;
+ mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
+ natural_t region_depth = 1000;
mach_vm_address_t region_start = region_address;
- mach_msg_type_number_t count;
- natural_t region_depth;
+ mach_vm_size_t region_length;
+ mach_vm_size_t write_length;
- region_depth = 100000;
- count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
+ /* Read page protection. */
kret = mach_vm_region_recurse
(task, ®ion_start, ®ion_length, ®ion_depth,
(vm_region_recurse_info_t) &info, &count);
"mach_vm_region_recurse failed at %s: %s\n"),
core_addr_to_string (region_address),
mach_error_string (kret));
- goto out;
+ return res_length;
}
inferior_debug
core_addr_to_string (region_address),
core_addr_to_string (region_start),
(unsigned)region_length);
- length = 0;
- goto out;
+ return res_length;
}
/* Adjust the length. */
region_length -= (region_address - region_start);
+ if (region_length > aligned_length)
+ region_length = aligned_length;
- if (!(info.max_protection & VM_PROT_WRITE))
+ /* Make the pages RW. */
+ if (!(info.protection & VM_PROT_WRITE))
{
- kret = mach_vm_protect
- (task, region_address, region_length,
- TRUE, info.max_protection | VM_PROT_WRITE | VM_PROT_COPY);
+ vm_prot_t prot = VM_PROT_READ | VM_PROT_WRITE;
+
+ kret = mach_vm_protect (task, region_address, region_length,
+ FALSE, prot);
if (kret != KERN_SUCCESS)
{
- warning (_("darwin_read_write_inf: "
- "mach_vm_protect max failed at %s: %s"),
+ prot |= VM_PROT_COPY;
+ kret = mach_vm_protect (task, region_address, region_length,
+ FALSE, prot);
+ }
+ if (kret != KERN_SUCCESS)
+ {
+ warning (_("darwin_read_write_inferior: "
+ "mach_vm_protect failed at %s "
+ "(len=0x%lx, prot=0x%x): %s"),
core_addr_to_string (region_address),
+ (unsigned long) region_length, (unsigned) prot,
mach_error_string (kret));
- length = 0;
- goto out;
+ return res_length;
}
}
+ if (offset + length > region_length)
+ write_length = region_length - offset;
+ else
+ write_length = length;
+
+ /* Write. */
+ kret = mach_vm_write (task, addr, (vm_offset_t) wraddr, write_length);
+ if (kret != KERN_SUCCESS)
+ {
+ warning (_("darwin_read_write_inferior: mach_vm_write failed: %s"),
+ mach_error_string (kret));
+ return res_length;
+ }
+
+ /* Restore page rights. */
if (!(info.protection & VM_PROT_WRITE))
{
kret = mach_vm_protect (task, region_address, region_length,
- FALSE, info.protection | VM_PROT_WRITE);
+ FALSE, info.protection);
if (kret != KERN_SUCCESS)
{
- warning (_("darwin_read_write_inf: "
- "mach_vm_protect failed at %s (len=0x%lx): %s"),
+ warning (_("darwin_read_write_inferior: "
+ "mach_vm_protect restore failed at %s "
+ "(len=0x%lx): %s"),
core_addr_to_string (region_address),
- (unsigned long)region_length, mach_error_string (kret));
- length = 0;
- goto out;
+ (unsigned long) region_length,
+ mach_error_string (kret));
}
}
- }
-
- kret = mach_vm_write (task, low_address, copied, aligned_length);
- if (kret != KERN_SUCCESS)
- {
- warning (_("darwin_read_write_inferior: mach_vm_write failed: %s"),
- mach_error_string (kret));
- length = 0;
+ addr += write_length;
+ wraddr += write_length;
+ res_length += write_length;
+ length -= write_length;
}
-out:
- mach_vm_deallocate (mach_task_self (), copied, copy_count);
- return length;
+
+ return res_length;
}
/* Read LENGTH bytes at offset ADDR of task_dyld_info for TASK, and copy them
- to RDADDR.
+ to RDADDR (in big endian).
Return 0 on failure; number of bytes read / written otherwise. */
#ifdef TASK_DYLD_INFO_COUNT
int sz = TASK_DYLD_INFO_COUNT * sizeof (natural_t);
kern_return_t kret;
- if (addr >= sz)
+ if (addr != 0 || length > sizeof (mach_vm_address_t))
return TARGET_XFER_EOF;
- kret = task_info (task, TASK_DYLD_INFO, (task_info_t) &task_dyld_info, &count);
+ kret = task_info (task, TASK_DYLD_INFO,
+ (task_info_t) &task_dyld_info, &count);
MACH_CHECK_ERROR (kret);
if (kret != KERN_SUCCESS)
return TARGET_XFER_E_IO;
- /* Truncate. */
- if (addr + length > sz)
- length = sz - addr;
- memcpy (rdaddr, (char *)&task_dyld_info + addr, length);
+
+ store_unsigned_integer (rdaddr, length, BFD_ENDIAN_BIG,
+ task_dyld_info.all_image_info_addr);
*xfered_len = (ULONGEST) length;
return TARGET_XFER_OK;
}
\f
-static enum target_xfer_status
-darwin_xfer_partial (struct target_ops *ops,
- enum target_object object, const char *annex,
- gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
+enum target_xfer_status
+darwin_nat_target::xfer_partial (enum target_object object, const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
inferior_debug
(8, _("darwin_xfer_partial(%s, %s, rbuf=%s, wbuf=%s) pid=%u\n"),
{
case TARGET_OBJECT_MEMORY:
{
- int l = darwin_read_write_inferior (inf->private->task, offset,
+ int l = darwin_read_write_inferior (priv->task, offset,
readbuf, writebuf, len);
if (l == 0)
/* Support only read. */
return TARGET_XFER_E_IO;
}
- return darwin_read_dyld_info (inf->private->task, offset, readbuf, len,
+ return darwin_read_dyld_info (priv->task, offset, readbuf, len,
xfered_len);
#endif
default:
}
static void
-set_enable_mach_exceptions (char *args, int from_tty,
+set_enable_mach_exceptions (const char *args, int from_tty,
struct cmd_list_element *c)
{
if (!ptid_equal (inferior_ptid, null_ptid))
{
struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
exception_mask_t mask;
kern_return_t kret;
mask = EXC_MASK_ALL;
else
{
- darwin_restore_exception_ports (inf->private);
+ darwin_restore_exception_ports (priv);
mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
}
- kret = task_set_exception_ports (inf->private->task, mask, darwin_ex_port,
+ kret = task_set_exception_ports (priv->task, mask, darwin_ex_port,
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
MACH_CHECK_ERROR (kret);
}
}
-static char *
-darwin_pid_to_exec_file (struct target_ops *self, int pid)
+char *
+darwin_nat_target::pid_to_exec_file (int pid)
{
static char path[PATH_MAX];
int res;
return NULL;
}
-static ptid_t
-darwin_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
+ptid_t
+darwin_nat_target::get_ada_task_ptid (long lwp, long thread)
{
- int i;
- darwin_thread_t *t;
- int k;
struct inferior *inf = current_inferior ();
+ darwin_inferior *priv = get_darwin_inferior (inf);
kern_return_t kret;
mach_port_name_array_t names;
mach_msg_type_number_t names_count;
long res = 0;
/* First linear search. */
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
- k++)
- if (t->inf_port == lwp)
- return ptid_build (ptid_get_pid (inferior_ptid), 0, t->gdb_port);
+ for (darwin_thread_t *t : priv->threads)
+ {
+ if (t->inf_port == lwp)
+ return ptid_build (ptid_get_pid (inferior_ptid), 0, t->gdb_port);
+ }
/* Maybe the port was never extract. Do it now. */
/* First get inferior port names. */
- kret = mach_port_names (inf->private->task, &names, &names_count, &types,
+ kret = mach_port_names (priv->task, &names, &names_count, &types,
&types_count);
MACH_CHECK_ERROR (kret);
if (kret != KERN_SUCCESS)
/* For each name, copy the right in the gdb space and then compare with
our view of the inferior threads. We don't forget to deallocate the
right. */
- for (i = 0; i < names_count; i++)
+ for (int i = 0; i < names_count; i++)
{
mach_port_t local_name;
mach_msg_type_name_t local_type;
/* We just need to know the corresponding name in gdb name space.
So extract and deallocate the right. */
- kret = mach_port_extract_right (inf->private->task, names[i],
+ kret = mach_port_extract_right (priv->task, names[i],
MACH_MSG_TYPE_COPY_SEND,
&local_name, &local_type);
if (kret != KERN_SUCCESS)
continue;
mach_port_deallocate (gdb_task, local_name);
- for (k = 0;
- VEC_iterate (darwin_thread_t, inf->private->threads, k, t);
- k++)
- if (t->gdb_port == local_name)
- {
- t->inf_port = names[i];
- if (names[i] == lwp)
- res = t->gdb_port;
- }
+ for (darwin_thread_t *t : priv->threads)
+ {
+ if (t->gdb_port == local_name)
+ {
+ t->inf_port = names[i];
+ if (names[i] == lwp)
+ res = t->gdb_port;
+ }
+ }
}
vm_deallocate (gdb_task, (vm_address_t) names,
return null_ptid;
}
-static int
-darwin_supports_multi_process (struct target_ops *self)
+bool
+darwin_nat_target::supports_multi_process ()
{
- return 1;
+ return true;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_darwin_inferior;
-
void
-_initialize_darwin_inferior (void)
+_initialize_darwin_nat ()
{
kern_return_t kret;
MACH_CHECK_ERROR (kret);
}
- darwin_ops = inf_child_target ();
-
- darwin_ops->to_create_inferior = darwin_create_inferior;
- darwin_ops->to_attach = darwin_attach;
- darwin_ops->to_attach_no_wait = 0;
- darwin_ops->to_detach = darwin_detach;
- darwin_ops->to_files_info = darwin_files_info;
- darwin_ops->to_wait = darwin_wait_to;
- darwin_ops->to_mourn_inferior = darwin_mourn_inferior;
- darwin_ops->to_kill = darwin_kill_inferior;
- darwin_ops->to_stop = darwin_stop;
- darwin_ops->to_resume = darwin_resume_to;
- darwin_ops->to_thread_alive = darwin_thread_alive;
- darwin_ops->to_pid_to_str = darwin_pid_to_str;
- darwin_ops->to_pid_to_exec_file = darwin_pid_to_exec_file;
- darwin_ops->to_load = NULL;
- darwin_ops->to_xfer_partial = darwin_xfer_partial;
- darwin_ops->to_supports_multi_process = darwin_supports_multi_process;
- darwin_ops->to_get_ada_task_ptid = darwin_get_ada_task_ptid;
-
- darwin_complete_target (darwin_ops);
-
- add_target (darwin_ops);
-
- inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"), mach_task_self (),
- getpid ());
+ inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"),
+ (unsigned long) mach_task_self (), getpid ());
add_setshow_zuinteger_cmd ("darwin", class_obscure,
&darwin_debug_flag, _("\