diff options
author | marcel <marcel@FreeBSD.org> | 2004-07-12 05:07:50 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2004-07-12 05:07:50 +0000 |
commit | 57e7de678f860b94b4ec21acf2e49439019e3e7f (patch) | |
tree | 354f543bfcbe27c384ccc9ed5c1d36a3fc6a26d1 /sys/kern | |
parent | 221d6a099a5664d5ce6f054052073470d06ffa2b (diff) | |
download | FreeBSD-src-57e7de678f860b94b4ec21acf2e49439019e3e7f.zip FreeBSD-src-57e7de678f860b94b4ec21acf2e49439019e3e7f.tar.gz |
Implement the PT_LWPINFO request. This request can be used by the
tracing process to obtain information about the LWP that caused the
traced process to stop. Debuggers can use this information to select
the thread currently running on the LWP as the current thread.
The request has been made compatible with NetBSD for as much as
possible. This implementation differs from NetBSD in the following
ways:
1. The data argument is allowed to be smaller than the size of the
ptrace_lwpinfo structure known to the kernel, but not 0. This
is opposite to what NetBSD allows. The reason for this is that
we can extend the structure without affecting older binaries.
2. On NetBSD the tracing process is to set the pl_lwpid field to
the Id of the LWP it wants information of. We don't do that.
Our ptrace interface allows passing the LWP Id instead of the
PID. The tracing process is to set the PID to the LWP Id it
wants information of.
3. When the PID is actually the PID of the tracing process, this
request returns the information about the LWP that caused the
process to stop. This was the whole purpose of the request in
the first place.
When the traced process has exited, this request will return the
LWP Id 0, indicating that the process state is not the result of
an event specific to a LWP.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exit.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 3 | ||||
-rw-r--r-- | sys/kern/sys_process.c | 19 |
3 files changed, 23 insertions, 0 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 5d0f4c3..056116d 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -429,6 +429,7 @@ retry: mtx_lock(&Giant); PROC_LOCK(p); p->p_xstat = rv; + p->p_xlwpid = td->td_tid; *p->p_ru = p->p_stats->p_ru; mtx_lock_spin(&sched_lock); calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index d17cbe2..bbc9e28 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1882,6 +1882,7 @@ do_tdsignal(struct thread *td, int sig, sigtarget_t target) goto out; p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; + p->p_xlwpid = td->td_tid; mtx_lock_spin(&sched_lock); FOREACH_THREAD_IN_PROC(p, td0) { if (TD_IS_SLEEPING(td0) && @@ -2011,6 +2012,7 @@ ptracestop(struct thread *td, int sig) &p->p_mtx.mtx_object, "Stopping for traced signal"); p->p_xstat = sig; + p->p_xlwpid = td->td_tid; PROC_LOCK(p->p_pptr); psignal(p->p_pptr, SIGCHLD); PROC_UNLOCK(p->p_pptr); @@ -2154,6 +2156,7 @@ issignal(td) &p->p_mtx.mtx_object, "Catching SIGSTOP"); p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; + p->p_xlwpid = td->td_tid; mtx_lock_spin(&sched_lock); FOREACH_THREAD_IN_PROC(p, td0) { if (TD_IS_SLEEPING(td0) && diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index f65b67c..0cae07b 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -305,6 +305,7 @@ ptrace(struct thread *td, struct ptrace_args *uap) */ union { struct ptrace_io_desc piod; + struct ptrace_lwpinfo pl; struct dbreg dbreg; struct fpreg fpreg; struct reg reg; @@ -317,6 +318,7 @@ ptrace(struct thread *td, struct ptrace_args *uap) case PT_GETREGS: case PT_GETFPREGS: case PT_GETDBREGS: + case PT_LWPINFO: break; case PT_SETREGS: error = copyin(uap->addr, &r.reg, sizeof r.reg); @@ -354,6 +356,9 @@ ptrace(struct thread *td, struct ptrace_args *uap) case PT_GETDBREGS: error = copyout(&r.dbreg, uap->addr, sizeof r.dbreg); break; + case PT_LWPINFO: + error = copyout(&r.pl, uap->addr, uap->data); + break; } return (error); @@ -367,6 +372,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) struct proc *curp, *p, *pp; struct thread *td2 = NULL; struct ptrace_io_desc *piod; + struct ptrace_lwpinfo *pl; int error, write, tmp; int proctree_locked = 0; lwpid_t tid = 0; @@ -606,6 +612,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) /* deliver or queue signal */ if (P_SHOULDSTOP(p)) { p->p_xstat = data; + p->p_xlwpid = 0; p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG); mtx_lock_spin(&sched_lock); thread_unsuspend(p); @@ -727,6 +734,17 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) PROC_UNLOCK(p); return (error); + case PT_LWPINFO: + if (data == 0 || data > sizeof(*pl)) + return (EINVAL); + pl = addr; + _PHOLD(p); + pl->pl_lwpid = p->p_xlwpid; + _PRELE(p); + PROC_UNLOCK(p); + pl->pl_event = PL_EVENT_SIGNAL; + return (0); + default: #ifdef __HAVE_PTRACE_MACHDEP if (req >= PT_FIRSTMACH) { @@ -764,6 +782,7 @@ stopevent(struct proc *p, unsigned int event, unsigned int val) p->p_step = 1; do { p->p_xstat = val; + p->p_xlwpid = 0; p->p_stype = event; /* Which event caused the stop? */ wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */ msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0); |