Rework Mach exception and Darwin's ptrace. gdb is now able to attach a

remote process. This new implementation also passes all the test programs
I've written so far.

- When exceptions come from traps, no UNIX signal should evet be sent.
- Add a lock to ensure a debugger handles only one exception at a time
- Use a structure to hold flavor and behavior in exception ports, instead
  of stuffing the two argument into an int.
- Implement new Mach services: thread_suspend, thread_resume and thread_abort
- Implement Darwin's ptrace PT_ATTACHEXC and PT_THUPDATE commands
- Handle NULL second argument correctly in sigprocmask.
- One mistake in the last commit (darwin_tracesig prototype)
This commit is contained in:
manu 2003-12-24 23:22:22 +00:00
parent 3bc6a59873
commit 834aafd284
15 changed files with 403 additions and 194 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: darwin_ptrace.c,v 1.2 2003/12/04 23:59:50 manu Exp $ */
/* $NetBSD: darwin_ptrace.c,v 1.3 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: darwin_ptrace.c,v 1.2 2003/12/04 23:59:50 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: darwin_ptrace.c,v 1.3 2003/12/24 23:22:22 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -56,47 +56,8 @@ __KERNEL_RCSID(0, "$NetBSD: darwin_ptrace.c,v 1.2 2003/12/04 23:59:50 manu Exp $
#include <compat/darwin/darwin_ptrace.h>
#include <compat/darwin/darwin_syscallargs.h>
#if 0
#define ISSET(t, f) ((t) & (f))
static inline int ptrace_sanity_check(struct proc *, struct proc *);
/* Sanity checks copied from native sys_ptrace() */
static inline int
ptrace_sanity_check(p, t)
struct proc *p;
struct proc *t;
{
/*
* You can't do what you want to the process if:
* (1) It's not being traced at all,
*/
if (!ISSET(t->p_flag, P_TRACED))
return (EPERM);
/*
* (2) it's being traced by procfs (which has
* different signal delivery semantics),
*/
if (ISSET(t->p_flag, P_FSTRACE))
return (EBUSY);
/*
* (3) it's not being traced by _you_, or
*/
if (t->p_pptr != p)
return (EBUSY);
/*
* (4) it's not currently stopped.
*/
if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
return (EBUSY);
return 0;
}
#endif
int
darwin_sys_ptrace(l, v, retval)
struct lwp *l;
@ -115,32 +76,100 @@ darwin_sys_ptrace(l, v, retval)
struct proc *t; /* target process */
int error;
ded = (struct darwin_emuldata *)p->p_emuldata;
switch (req) {
case DARWIN_PT_ATTACHEXC:
if ((t = pfind(SCARG(uap, pid))) == NULL)
return ESRCH;
if (t->p_emul != &emul_darwin)
return ESRCH;
ded = t->p_emuldata;
if (ded->ded_flags & DARWIN_DED_SIGEXC)
return EBUSY;
ded->ded_flags |= DARWIN_DED_SIGEXC;
SCARG(uap, req) = PT_ATTACH;
if ((error = sys_ptrace(l, v, retval)) != 0)
ded->ded_flags &= ~DARWIN_DED_SIGEXC;
return error;
break;
case DARWIN_PT_SIGEXC:
ded = (struct darwin_emuldata *)p->p_emuldata;
if ((p->p_flag & P_TRACED) == 0)
return EBUSY;
ded->ded_flags |= DARWIN_DED_SIGEXC;
break;
case DARWIN_PT_DETACH:
case DARWIN_PT_DETACH: {
int had_sigexc = 0;
if ((t = pfind(SCARG(uap, pid))) == NULL)
return (ESRCH);
/*
* Clear signal-as-exceptions flag if detaching is
* successful and if it is a Darwin process.
*/
if (((error = sys_ptrace(l, v, retval)) == 0) &&
(t->p_emul != &emul_darwin)) {
ded = (struct darwin_emuldata *)t->p_emuldata;
ded->ded_flags &= ~DARWIN_DED_SIGEXC;
if ((t->p_emul == &emul_darwin) &&
(t->p_flag & P_TRACED) &&
(t->p_pptr == p)) {
ded = t->p_emuldata;
if (ded->ded_flags & DARWIN_DED_SIGEXC) {
had_sigexc = 1;
ded->ded_flags &= ~DARWIN_DED_SIGEXC;
}
}
/*
* If the process is not marked as stopped,
* sys_ptrace sanity checks will return EBUSY.
*/
proc_stop(t, 0);
if ((error = sys_ptrace(l, v, retval)) != 0) {
proc_unstop(t);
if (had_sigexc)
ded->ded_flags |= DARWIN_DED_SIGEXC;
}
break;
}
case DARWIN_PT_THUPDATE: {
int signo = SCARG(uap, data);
if ((t = pfind(SCARG(uap, pid))) == NULL)
return ESRCH;
/* Checks from native ptrace */
if (!ISSET(t->p_flag, P_TRACED))
return EPERM;
if (ISSET(t->p_flag, P_FSTRACE))
return EBUSY;
if (t->p_pptr != p)
return EBUSY;
#if 0
if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
return EBUSY;
#endif
if ((signo < 0) || (signo > NSIG))
return EINVAL;
t->p_xstat = signo;
if (signo != 0)
sigaddset(&p->p_sigctx.ps_siglist, signo);
break;
}
case DARWIN_PT_READ_U:
case DARWIN_PT_WRITE_U:
case DARWIN_PT_STEP:
case DARWIN_PT_THUPDATE:
case DARWIN_PT_ATTACHEXC:
case DARWIN_PT_FORCEQUOTA:
case DARWIN_PT_DENY_ATTACH:
printf("darwin_sys_ptrace: unimplemented command %d\n", req);

View File

@ -1,4 +1,4 @@
/* $NetBSD: darwin_signal.c,v 1.16 2003/12/24 22:57:22 manu Exp $ */
/* $NetBSD: darwin_signal.c,v 1.17 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: darwin_signal.c,v 1.16 2003/12/24 22:57:22 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: darwin_signal.c,v 1.17 2003/12/24 23:22:22 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -138,48 +138,29 @@ darwin_trapsignal(l, ksi)
int
darwin_tracesig(p, signo)
struct proc *l;
struct proc *p;
int signo;
{
struct proc *p = l->l_proc;
struct darwin_emuldata *ded;
struct lwp *l;
int code[2];
int error;
int signo;
/*
* Don't generate Mach exeption for non
* maskable, stop and continue signals
*/
if (sigprop[signo] & (SA_CANTMASK | SA_STOP | SA_CONT | SA_TTYSTOP))
return EINVAL;
/* Don't send an exception if the signal is masked or ignored */
if ((p->p_flag & P_TRACED) == 0) {
if ((sigismember(&p->p_sigctx.ps_sigignore, signo)) ||
(sigismember(&p->p_sigctx.ps_sigmask, signo)))
return EINVAL;
}
/*
* Send signals as software exception if the process requested that.
* If the process does not have softsignals,
* we are done, normal signal delivery should
* occur.
*/
ded = (struct darwin_emuldata *)p->p_emuldata;
if (ded->ded_flags & DARWIN_DED_SIGEXC) {
code[0] = MACH_SOFT_SIGNAL;
code[1] = signo;
error = mach_exception(l, MACH_EXC_SOFTWARE, code);
if ((ded->ded_flags & DARWIN_DED_SIGEXC) == 0)
return 0;
/* Like if the signal was sent, wakeup any waiting process */
if ((error == 0) &&
p->p_sigctx.ps_sigwaited &&
sigismember(p->p_sigctx.ps_sigwait, signo) &&
(p->p_stat != SSTOP))
wakeup_one(&p->p_sigctx.ps_sigwait);
return error;
}
code[0] = MACH_SOFT_SIGNAL;
code[1] = signo;
l = proc_representative_lwp(p);
error = mach_exception(l, MACH_EXC_SOFTWARE, code);
/* Inhibit normal signal delivery */
return EINVAL;
}
@ -199,7 +180,7 @@ darwin_sys_sigprocmask(l, v, retval)
int error;
sigset13_t kdset, kdoset;
sigset_t kbset, kboset;
sigset_t *ubset;
sigset_t *ubset = NULL;
sigset_t *uboset = NULL;
caddr_t sg = stackgap_init(p, 0);
@ -207,13 +188,16 @@ darwin_sys_sigprocmask(l, v, retval)
if (SCARG(uap, oset) != NULL)
uboset = stackgap_alloc(p, &sg, sizeof(*uboset));
if ((error = copyin(SCARG(uap, set), &kdset, sizeof(kdset))) != 0)
return error;
if (SCARG(uap, set) != NULL) {
error = copyin(SCARG(uap, set), &kdset, sizeof(kdset));
if (error != 0)
return error;
native_sigset13_to_sigset(&kdset, &kbset);
native_sigset13_to_sigset(&kdset, &kbset);
if ((error = copyout(&kbset, ubset, sizeof(kbset))) != 0)
return error;
if ((error = copyout(&kbset, ubset, sizeof(kbset))) != 0)
return error;
}
SCARG(&cup, how) = SCARG(uap, how);
SCARG(&cup, set) = ubset;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exception.c,v 1.1 2003/12/09 12:13:44 manu Exp $ */
/* $NetBSD: mach_exception.c,v 1.2 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -37,9 +37,10 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.1 2003/12/09 12:13:44 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.2 2003/12/24 23:22:22 manu Exp $");
#include "opt_ktrace.h"
#include "opt_compat_darwin.h"
#include <sys/types.h>
#include <sys/param.h>
@ -47,8 +48,13 @@ __KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.1 2003/12/09 12:13:44 manu Exp
#include <sys/proc.h>
#include <sys/malloc.h>
#ifdef COMPAT_DARWIN
#include <compat/darwin/darwin_exec.h>
#endif
#include <compat/mach/mach_types.h>
#include <compat/mach/mach_exec.h>
#include <compat/mach/mach_errno.h>
#include <compat/mach/mach_thread.h>
#include <compat/mach/mach_exception.h>
#include <compat/mach/mach_message.h>
@ -119,8 +125,8 @@ mach_trapsignal1(l, ksi)
}
int
mach_exception(l, exc, code)
struct lwp *l;
mach_exception(exc_l, exc, code)
struct lwp *exc_l; /* currently running lwp */
int exc;
int *code;
{
@ -128,32 +134,47 @@ mach_exception(l, exc, code)
mach_msg_header_t *msgh;
size_t msglen;
struct mach_right *exc_mr;
struct mach_emuldata *med;
struct mach_emuldata *exc_med;
struct mach_lwp_emuldata *exc_mle;
struct mach_emuldata *catcher_med;
struct mach_right *kernel_mr;
struct lwp *catcher_lwp;
struct mach_right *task;
struct mach_right *thread;
struct lwp *catcher_l; /* The lwp catching the exception */
struct mach_right *exc_task;
struct mach_right *exc_thread;
struct mach_port *exc_port;
int error;
struct mach_exc_info *mei;
int error = 0;
#ifdef DIAGNOSTIC
if (exc_l == NULL) {
printf("mach_exception: exc_l = %p\n", exc_l);
return ESRCH;
}
#endif
#ifdef DEBUG_MACH
printf("mach_exception: pid %d, exc %d, code (%d, %d)\n",
l->l_proc->p_pid, exc, code[0], code[1]);
printf("mach_exception: %d.%d, exc %d, code (%d, %d)\n",
exc_l->l_proc->p_pid, exc_l->l_lid, exc, code[0], code[1]);
#endif
/*
* No exception if there is no exception port or if it has no receiver
*/
med = l->l_proc->p_emuldata;
if (((exc_port = med->med_exc[exc]) == NULL) ||
exc_mle = exc_l->l_emuldata;
exc_med = exc_l->l_proc->p_emuldata;
if (((exc_port = exc_med->med_exc[exc]) == NULL) ||
(exc_port->mp_recv == NULL))
return EINVAL;
#ifdef DEBUG_MACH
printf("catcher is %d.%d, state %d\n",
exc_port->mp_recv->mr_lwp->l_proc->p_pid,
exc_port->mp_recv->mr_lwp->l_lid,
exc_port->mp_recv->mr_lwp->l_proc->p_stat);
#endif
/*
* Don't send exceptions to dying processes
*/
if (P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc))
return EINVAL;
return ESRCH;
/*
* XXX Avoid a nasty deadlock because process in TX state
@ -175,33 +196,38 @@ mach_exception(l, exc, code)
* a dying parent, a signal is sent instead of the
* notification, this fixes the problem.
*/
if ((l->l_proc->p_flag & P_TRACED) &&
(l->l_proc->p_pptr->p_flag & P_WEXIT)) {
if ((exc_l->l_proc->p_flag & P_TRACED) &&
(exc_l->l_proc->p_pptr->p_flag & P_WEXIT)) {
#ifdef DEBUG_MACH
printf("mach_exception: deadlock avoided\n");
#endif
return EINVAL;
}
if (exc_port->mp_datatype != MACH_MP_EXC_INFO) {
#ifdef DIAGNOSTIC
if (exc_port->mp_datatype != MACH_MP_EXC_FLAGS)
printf("mach_exception: unexpected datatype");
#endif
behavior = (int)exc_port->mp_data >> 16;
flavor = (int)exc_port->mp_data & 0xffff;
return EINVAL;
}
mei = exc_port->mp_data;
behavior = mei->mei_behavior;
flavor = mei->mei_flavor;
/*
* We want the port names in the target process, that is,
* the process with receive right for exc_port.
*/
catcher_lwp = exc_port->mp_recv->mr_lwp;
catcher_med = catcher_lwp->l_proc->p_emuldata;
exc_mr = mach_right_get(exc_port, catcher_lwp, MACH_PORT_TYPE_SEND, 0);
catcher_l = exc_port->mp_recv->mr_lwp;
catcher_med = catcher_l->l_proc->p_emuldata;
exc_mr = mach_right_get(exc_port, catcher_l, MACH_PORT_TYPE_SEND, 0);
kernel_mr = mach_right_get(catcher_med->med_kernel,
catcher_lwp, MACH_PORT_TYPE_SEND, 0);
catcher_l, MACH_PORT_TYPE_SEND, 0);
/* XXX Thread and task should have different ports */
task = mach_right_get(med->med_kernel,
catcher_lwp, MACH_PORT_TYPE_SEND, 0);
thread = mach_right_get(med->med_kernel,
catcher_lwp, MACH_PORT_TYPE_SEND, 0);
exc_task = mach_right_get(exc_med->med_kernel,
catcher_l, MACH_PORT_TYPE_SEND, 0);
exc_thread = mach_right_get(exc_mle->mle_kernel,
catcher_l, MACH_PORT_TYPE_SEND, 0);
switch (behavior) {
case MACH_EXCEPTION_DEFAULT: {
@ -220,13 +246,15 @@ mach_exception(l, exc, code)
req->req_msgh.msgh_local_port = exc_mr->mr_name;
req->req_msgh.msgh_id = MACH_EXC_RAISE_MSGID;
mach_add_port_desc(req, thread->mr_name);
mach_add_port_desc(req, task->mr_name);
mach_add_port_desc(req, exc_thread->mr_name);
mach_add_port_desc(req, exc_task->mr_name);
req->req_exc = exc;
req->req_codecount = 2;
memcpy(&req->req_code[0], code, sizeof(req->req_code));
mach_set_trailer(req, msglen);
break;
}
@ -250,11 +278,13 @@ mach_exception(l, exc, code)
req->req_codecount = 2;
memcpy(&req->req_code[0], code, sizeof(req->req_code));
req->req_flavor = flavor;
mach_thread_get_state_machdep(l, flavor, req->req_state, &dc);
mach_thread_get_state_machdep(exc_l,
flavor, req->req_state, &dc);
msglen = msglen -
sizeof(req->req_state) +
(dc * sizeof(req->req_state[0]));
mach_set_trailer(req, msglen);
break;
}
@ -277,20 +307,22 @@ mach_exception(l, exc, code)
req->req_msgh.msgh_id = MACH_EXC_RAISE_STATE_IDENTITY_MSGID;
req->req_body.msgh_descriptor_count = 2;
mach_add_port_desc(req, thread->mr_name);
mach_add_port_desc(req, task->mr_name);
mach_add_port_desc(req, exc_thread->mr_name);
mach_add_port_desc(req, exc_task->mr_name);
req->req_exc = exc;
req->req_codecount = 2;
memcpy(&req->req_code[0], code, sizeof(req->req_code));
req->req_flavor = flavor;
mach_thread_get_state_machdep(l, flavor, req->req_state, &dc);
/* Trailer */
req->req_state[(dc / sizeof(req->req_state[0])) + 1] = 8;
mach_thread_get_state_machdep(exc_l,
flavor, req->req_state, &dc);
msglen = msglen -
sizeof(req->req_state) +
(dc * sizeof(req->req_state[0]));
mach_set_trailer(req, msglen);
break;
}
@ -302,20 +334,44 @@ mach_exception(l, exc, code)
mach_set_trailer(msgh, msglen);
/*
* Once an exception is sent on the exception port,
* no new exception will be taken until the catcher
* acknowledge the first one.
*/
lockmgr(&catcher_med->med_exclock, LK_EXCLUSIVE, NULL);
/*
* If the catcher died, we are done.
*/
if (((exc_port = exc_med->med_exc[exc]) == NULL) ||
(exc_port->mp_recv == NULL) ||
(P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc)))
return ESRCH;
(void)mach_message_get(msgh, msglen, exc_port, NULL);
wakeup(exc_port->mp_recv->mr_sethead);
/*
* The thread that caused the exception is now
* supposed to wait for a reply to its message.
* This is to avoid an endless loop on the same
* exception.
*/
error = tsleep(kernel_mr->mr_port, PZERO|PCATCH, "mach_exc", 0);
if ((error == ERESTART) || (error == EINTR))
return error;
#ifdef DEBUG_MACH
printf("mach_exception: %d.%d sleep on catcher_med->med_exclock = %p\n",
exc_l->l_proc->p_pid, exc_l->l_lid, &catcher_med->med_exclock);
#endif
error = tsleep(&catcher_med->med_exclock, PZERO, "mach_exc", 0);
#ifdef DEBUG_MACH
printf("mach_exception: %d.%d resumed, error = %d\n",
exc_l->l_proc->p_pid, exc_l->l_lid, error);
#endif
return 0;
/*
* Unlock the catcher's exception handler
*/
lockmgr(&catcher_med->med_exclock, LK_RELEASE, NULL);
return error;
}
static void
@ -396,10 +452,8 @@ int
mach_exception_raise(args)
struct mach_trap_args *args;
{
mach_exception_raise_reply_t *rep;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
mach_exception_raise_reply_t *rep;
struct mach_emuldata *med;
/*
@ -409,30 +463,38 @@ mach_exception_raise(args)
*/
rep = args->smsg;
/*
* Sanity check the remote port: it should be a
* right to the process' kernel port
*/
mn = rep->rep_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0)
return MACH_SEND_INVALID_RIGHT;
med = (struct mach_emuldata *)l->l_proc->p_emuldata;
if (med->med_kernel != mr->mr_port) {
#ifdef DEBUG_MACH
printf("mach_exception_raise: remote port not kernel port\n");
#endif
return 0;
}
/*
* This message is sent by the process catching the
* exception to release the process that raised the exception.
* We wake it up if the return value is 0 (no error), else
* we should ignore this message.
*/
if (rep->rep_retval == 0)
wakeup(mr->mr_port);
#ifdef DEBUG_MACH
printf("mach_excpetion_raise: retval = %ld\n", (long)rep->rep_retval);
#endif
if (rep->rep_retval != 0)
return 0;
med = l->l_proc->p_emuldata;
/*
* Check for unexpected exception acknowledge, whereas
* the kernel sent no exception message.
*/
if (lockstatus(&med->med_exclock) == 0) {
#ifdef DEBUG_MACH
printf("spurious mach_exception_raise\n");
#endif
return mach_msg_error(args, EINVAL);
}
/*
* Wakeup the thread that raised the exception.
*/
#ifdef DEBUG_MACH
printf("mach_exception_raise: wakeup at %p\n", &med->med_exclock);
#endif
wakeup(&med->med_exclock);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exception.h,v 1.2 2003/12/18 01:10:20 grant Exp $ */
/* $NetBSD: mach_exception.h,v 1.3 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -142,6 +142,10 @@ typedef struct {
mach_kern_return_t rep_retval;
} mach_exception_raise_state_identity_reply_t;
struct mach_exc_info {
int mei_flavor;
int mei_behavior;
};
void mach_trapsignal(struct lwp *, const struct ksiginfo *);
int mach_trapsignal1(struct lwp *, const struct ksiginfo *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exec.c,v 1.48 2003/12/20 19:43:17 manu Exp $ */
/* $NetBSD: mach_exec.c,v 1.49 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.48 2003/12/20 19:43:17 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.49 2003/12/24 23:22:22 manu Exp $");
#include "opt_syscall_debug.h"
@ -242,6 +242,10 @@ mach_e_proc_fork1(p, parent, allocate)
* but we need to double their reference counts,
* since the ports are referenced by rights in the
* parent and in the child.
*
* XXX we need to convert all the parent's rights
* to the child namespace. This will make the
* following fixup obsolete.
*/
for (i = 0; i <= MACH_EXC_MAX; i++) {
med1->med_exc[i] = med2->med_exc[i];
@ -306,6 +310,7 @@ mach_e_proc_init(p, vmspace)
*/
LIST_INIT(&med->med_right);
lockinit(&med->med_rightlock, PZERO|PCATCH, "mach_right", 0, 0);
lockinit(&med->med_exclock, PZERO, "exclock", 0, 0);
/*
* For debugging purpose, it's convenient to have each process
@ -376,6 +381,14 @@ mach_e_proc_exit(p)
if (--med->med_bootstrap->mp_refcount <= 0)
mach_port_put(med->med_bootstrap);
/*
* If the lock on this task exception handler is held,
* release it now as it will never be released by the
* exception handler.
*/
if (lockstatus(&med->med_exclock) != 0)
lockmgr(&med->med_exclock, LK_RELEASE, NULL);
/*
* If the kernel and host port are still referenced, remove
* the pointer to this process' struct proc, as it will

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exec.h,v 1.25 2003/12/20 19:43:17 manu Exp $ */
/* $NetBSD: mach_exec.h,v 1.26 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -61,12 +61,11 @@ struct mach_emuldata {
int med_dirty_thid; /* Thread id not yet initialized */
int med_suspend; /* Suspend semaphore */
struct lock med_exclock; /* Process exception handler lock */
};
struct mach_lwp_emuldata {
struct mach_port *mle_kernel; /* Thread's kernel port */
struct mach_port *mle_exc; /* Exception we stop on */
};
int exec_mach_copyargs(struct proc *, struct exec_package *,

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_message.c,v 1.40 2003/12/21 07:53:59 simonb Exp $ */
/* $NetBSD: mach_message.c,v 1.41 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.40 2003/12/21 07:53:59 simonb Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.41 2003/12/24 23:22:22 manu Exp $");
#include "opt_ktrace.h"
#include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
@ -603,6 +603,8 @@ mach_msg_recv(l, urm, option, recv_size, timeout, mn)
/*
* Get rights carried by the message if it is not a
* reply from the kernel.
* XXX mm->mm_l could contain stall data. Reference
* the thread's kernel port instead?
*/
if (mm->mm_l != NULL) {
mach_port_t *mnp;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_port.h,v 1.32 2003/12/20 19:43:17 manu Exp $ */
/* $NetBSD: mach_port.h,v 1.33 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -316,7 +316,7 @@ struct mach_port {
#define MACH_MP_PROC 0x4 /* (struct proc *) */
#define MACH_MP_NOTIFY_SYNC 0x5 /* int */
#define MACH_MP_MEMORY_ENTRY 0x6 /* (struct mach_memory_entry *) */
#define MACH_MP_EXC_FLAGS 0x7 /* Two shorts: behavior, flavor */
#define MACH_MP_EXC_INFO 0x7 /* (struct mach_exc_info *) */
#define MACH_MP_SEMAPHORE 0x8 /* (struct mach_semaphore *) */
void mach_port_init(void);

View File

@ -1,14 +1,14 @@
/* $NetBSD: mach_services.c,v 1.11 2003/12/09 12:13:44 manu Exp $ */
/* $NetBSD: mach_services.c,v 1.12 2003/12/24 23:22:22 manu Exp $ */
/*
* Mach services table.
*
* DO NOT EDIT -- this file is automatically generated.
* created from NetBSD: mach_services.master,v 1.7 2003/11/30 20:42:03 manu Exp
* created from NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_services.c,v 1.11 2003/12/09 12:13:44 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_services.c,v 1.12 2003/12/24 23:22:22 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -255,9 +255,9 @@ struct mach_service mach_services_table[] = {
{3602, NULL, "unimpl. act_set_state", 0, 0},
{3603, mach_thread_get_state, "thread_get_state", sizeof(mach_thread_get_state_request_t), sizeof(mach_thread_get_state_reply_t)},
{3604, mach_thread_set_state, "thread_set_state", sizeof(mach_thread_set_state_request_t), sizeof(mach_thread_set_state_reply_t)},
{3605, NULL, "unimpl. thread_suspend", 0, 0},
{3606, NULL, "unimpl. thread_resume", 0, 0},
{3607, NULL, "unimpl. thread_abort", 0, 0},
{3605, mach_thread_suspend, "thread_suspend", sizeof(mach_thread_suspend_request_t), sizeof(mach_thread_suspend_reply_t)},
{3606, mach_thread_resume, "thread_resume", sizeof(mach_thread_resume_request_t), sizeof(mach_thread_resume_reply_t)},
{3607, mach_thread_abort, "thread_abort", sizeof(mach_thread_abort_request_t), sizeof(mach_thread_abort_reply_t)},
{3608, NULL, "unimpl. thread_abort_safely", 0, 0},
{3609, NULL, "unimpl. thread_depress_abort", 0, 0},
{3610, NULL, "unimpl. thread_get_special_port", 0, 0},

View File

@ -1,14 +1,14 @@
/* $NetBSD: mach_services.h,v 1.11 2003/12/09 12:13:44 manu Exp $ */
/* $NetBSD: mach_services.h,v 1.12 2003/12/24 23:22:22 manu Exp $ */
/*
* Mach services prototypes.
*
* DO NOT EDIT -- this file is automatically generated.
* created from NetBSD: mach_services.master,v 1.7 2003/11/30 20:42:03 manu Exp
* created from NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_services.h,v 1.11 2003/12/09 12:13:44 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_services.h,v 1.12 2003/12/24 23:22:22 manu Exp $");
#include <compat/mach/mach_types.h>
#include <compat/mach/mach_message.h>
@ -74,6 +74,9 @@ int mach_semaphore_create(struct mach_trap_args *);
int mach_semaphore_destroy(struct mach_trap_args *);
int mach_thread_get_state(struct mach_trap_args *);
int mach_thread_set_state(struct mach_trap_args *);
int mach_thread_suspend(struct mach_trap_args *);
int mach_thread_resume(struct mach_trap_args *);
int mach_thread_abort(struct mach_trap_args *);
int mach_thread_info(struct mach_trap_args *);
int mach_thread_policy(struct mach_trap_args *);
int mach_vm_region(struct mach_trap_args *);

View File

@ -1,4 +1,4 @@
$NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp $
$NetBSD: mach_services.master,v 1.9 2003/12/24 23:22:22 manu Exp $
;
; Mach services list.
;
@ -333,9 +333,9 @@
3602 UNIMPL act_set_state
3603 STD thread_get_state
3604 STD thread_set_state
3605 UNIMPL thread_suspend
3606 UNIMPL thread_resume
3607 UNIMPL thread_abort
3605 STD thread_suspend
3606 STD thread_resume
3607 STD thread_abort
3608 UNIMPL thread_abort_safely
3609 UNIMPL thread_depress_abort
3610 UNIMPL thread_get_special_port

View File

@ -1,15 +1,15 @@
/* $NetBSD: mach_services_names.c,v 1.8 2003/12/09 12:13:44 manu Exp $ */
/* $NetBSD: mach_services_names.c,v 1.9 2003/12/24 23:22:22 manu Exp $ */
/*
* Mach services names. This file is not built
* by the kernel, it is included by kdump sources.
*
* DO NOT EDIT -- this file is automatically generated.
* created from NetBSD: mach_services.master,v 1.7 2003/11/30 20:42:03 manu Exp
* created from NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_services_names.c,v 1.8 2003/12/09 12:13:44 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_services_names.c,v 1.9 2003/12/24 23:22:22 manu Exp $");
struct mach_service_name {
int srv_id;
@ -244,9 +244,9 @@ struct mach_service_name mach_services_names[] = {
{3602, "unimpl. act_set_state"},
{3603, "thread_get_state"},
{3604, "thread_set_state"},
{3605, "unimpl. thread_suspend"},
{3606, "unimpl. thread_resume"},
{3607, "unimpl. thread_abort"},
{3605, "thread_suspend"},
{3606, "thread_resume"},
{3607, "thread_abort"},
{3608, "unimpl. thread_abort_safely"},
{3609, "unimpl. thread_depress_abort"},
{3610, "unimpl. thread_get_special_port"},

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_task.c,v 1.51 2003/12/20 19:43:17 manu Exp $ */
/* $NetBSD: mach_task.c,v 1.52 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -40,7 +40,7 @@
#include "opt_compat_darwin.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.51 2003/12/20 19:43:17 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.52 2003/12/24 23:22:22 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -326,6 +326,7 @@ mach_task_get_exception_ports(args)
size_t *msglen = args->rsize;
struct mach_emuldata *med;
struct mach_right *mr;
struct mach_exc_info *mei;
int i, j, count;
med = tl->l_proc->p_emuldata;
@ -342,13 +343,21 @@ mach_task_get_exception_ports(args)
if (med->med_exc[i] == NULL)
continue;
if (med->med_exc[i]->mp_datatype != MACH_MP_EXC_INFO) {
#ifdef DIAGNOSTIC
printf("Exception port without mach_exc_info\n");
#endif
continue;
}
mei = med->med_exc[i]->mp_data;
mr = mach_right_get(med->med_exc[i], l, MACH_PORT_TYPE_SEND, 0);
mach_add_port_desc(rep, mr->mr_name);
rep->rep_masks[j] = 1 << i;
rep->rep_old_behaviors[j] = (int)mr->mr_port->mp_data >> 16;
rep->rep_old_flavors[j] = (int)mr->mr_port->mp_data & 0xffff;
rep->rep_old_behaviors[j] = mei->mei_behavior;
rep->rep_old_flavors[j] = mei->mei_flavor;
j++;
}
@ -389,6 +398,7 @@ mach_task_set_exception_ports(args)
mach_port_name_t mn;
struct mach_right *mr;
struct mach_port *mp;
struct mach_exc_info *mei;
mn = req->req_new_port.name;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_SEND)) == 0)
@ -396,12 +406,17 @@ mach_task_set_exception_ports(args)
mp = mr->mr_port;
#ifdef DIAGNOSTIC
if ((mp->mp_datatype != MACH_MP_EXC_FLAGS) &&
if ((mp->mp_datatype != MACH_MP_EXC_INFO) &&
(mp->mp_datatype != MACH_MP_NONE))
printf("mach_task_set_exception_ports: data exists\n");
#endif
mp->mp_datatype = MACH_MP_EXC_FLAGS;
mp->mp_data = (void *)((req->req_behavior << 16) | req->req_flavor);
mei = malloc(sizeof(*mei), M_EMULDATA, M_WAITOK);
mei->mei_flavor = req->req_flavor;
mei->mei_behavior = req->req_behavior;
mp->mp_data = mei;
mp->mp_flags |= MACH_MP_DATA_ALLOCATED;
mp->mp_datatype = MACH_MP_EXC_INFO;
med = tl->l_proc->p_emuldata;
if (req->req_mask & MACH_EXC_MASK_BAD_ACCESS)

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_thread.c,v 1.31 2003/12/20 19:43:17 manu Exp $ */
/* $NetBSD: mach_thread.c,v 1.32 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_thread.c,v 1.31 2003/12/20 19:43:17 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_thread.c,v 1.32 2003/12/24 23:22:22 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -411,3 +411,62 @@ mach_thread_set_state(args)
return 0;
}
int
mach_thread_suspend(args)
struct mach_trap_args *args;
{
mach_thread_suspend_request_t *req = args->smsg;
mach_thread_suspend_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct lwp *tl = args->tl;
int error;
error = lwp_suspend(l, tl);
*msglen = sizeof(*rep);
mach_set_header(rep, req, *msglen);
rep->rep_retval = native_to_mach_errno[error];
mach_set_trailer(rep, *msglen);
return 0;
}
int
mach_thread_resume(args)
struct mach_trap_args *args;
{
mach_thread_resume_request_t *req = args->smsg;
mach_thread_resume_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *tl = args->tl;
lwp_continue(tl);
*msglen = sizeof(*rep);
mach_set_header(rep, req, *msglen);
rep->rep_retval = 0;
mach_set_trailer(rep, *msglen);
return 0;
}
int
mach_thread_abort(args)
struct mach_trap_args *args;
{
mach_thread_abort_request_t *req = args->smsg;
mach_thread_abort_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *tl = args->tl;
lwp_exit(tl);
*msglen = sizeof(*rep);
mach_set_header(rep, req, *msglen);
rep->rep_retval = 0;
mach_set_trailer(rep, *msglen);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_thread.h,v 1.14 2003/12/18 01:10:20 grant Exp $ */
/* $NetBSD: mach_thread.h,v 1.15 2003/12/24 23:22:22 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -188,6 +188,45 @@ typedef struct {
mach_msg_trailer_t rep_trailer;
} mach_thread_set_state_reply_t;
/* thread_suspend */
typedef struct {
mach_msg_header_t req_msgh;
} mach_thread_suspend_request_t;
typedef struct {
mach_msg_header_t rep_msgh;
mach_ndr_record_t rep_ndr;
mach_kern_return_t rep_retval;
mach_msg_trailer_t rep_trailer;
} mach_thread_suspend_reply_t;
/* thread_resume */
typedef struct {
mach_msg_header_t req_msgh;
} mach_thread_resume_request_t;
typedef struct {
mach_msg_header_t rep_msgh;
mach_ndr_record_t rep_ndr;
mach_kern_return_t rep_retval;
mach_msg_trailer_t rep_trailer;
} mach_thread_resume_reply_t;
/* thread_abort */
typedef struct {
mach_msg_header_t req_msgh;
} mach_thread_abort_request_t;
typedef struct {
mach_msg_header_t rep_msgh;
mach_ndr_record_t rep_ndr;
mach_kern_return_t rep_retval;
mach_msg_trailer_t rep_trailer;
} mach_thread_abort_reply_t;
/* These are machine dependent functions */
int mach_thread_get_state_machdep(struct lwp *, int, void *, int *);
int mach_thread_set_state_machdep(struct lwp *, int, void *);