PERFORCE change 55876 for review
David Xu
davidxu at FreeBSD.org
Sun Jun 27 02:26:43 GMT 2004
http://perforce.freebsd.org/chv.cgi?CH=55876
Change 55876 by davidxu at davidxu_alona on 2004/06/27 02:24:55
Implement MI ttrace.
Affected files ...
.. //depot/projects/davidxu_ksedbg/src/sys/kern/sys_process.c#2 edit
.. //depot/projects/davidxu_ksedbg/src/sys/sys/proc.h#2 edit
.. //depot/projects/davidxu_ksedbg/src/sys/sys/ptrace.h#2 edit
Differences ...
==== //depot/projects/davidxu_ksedbg/src/sys/kern/sys_process.c#2 (text+ko) ====
@@ -43,6 +43,7 @@
#include <sys/ptrace.h>
#include <sys/sx.h>
#include <sys/user.h>
+#include <sys/malloc.h>
#include <machine/reg.h>
@@ -54,6 +55,9 @@
#include <vm/vm_object.h>
#include <vm/vm_page.h>
+static int kern_ttrace(struct thread *td, int req, pid_t pid, lwpid_t tid,
+ void *addr, int data);
+
/*
* Functions implemented using PROC_ACTION():
*
@@ -359,16 +363,97 @@
return (error);
}
+#ifndef _SYS_SYSPROTO_H_
+struct ttrace_args {
+ int req;
+ pid_t pid;
+ lwpid_t tid;
+ caddr_t addr;
+ int data;
+};
+#endif
+
int
+ttrace(struct thread *td, struct ttrace_args * uap)
+{
+ /*
+ * XXX this obfuscation is to reduce stack usage, but the register
+ * structs may be too large to put on the stack anyway.
+ */
+ union {
+ struct ptrace_io_desc piod;
+ struct dbreg dbreg;
+ struct fpreg fpreg;
+ struct reg reg;
+ } r;
+ void *addr;
+ int error = 0;
+
+ addr = &r;
+ switch (uap->req) {
+ case PT_GETREGS:
+ case PT_GETFPREGS:
+ case PT_GETDBREGS:
+ break;
+ case PT_SETREGS:
+ error = copyin(uap->addr, &r.reg, sizeof r.reg);
+ break;
+ case PT_SETFPREGS:
+ error = copyin(uap->addr, &r.fpreg, sizeof r.fpreg);
+ break;
+ case PT_SETDBREGS:
+ error = copyin(uap->addr, &r.dbreg, sizeof r.dbreg);
+ break;
+ case PT_IO:
+ error = copyin(uap->addr, &r.piod, sizeof r.piod);
+ break;
+ default:
+ addr = uap->addr;
+ break;
+ }
+ if (error)
+ return (error);
+
+ error = kern_ttrace(td, uap->req, uap->pid, uap->tid, addr, uap->data);
+ if (error)
+ return (error);
+
+ switch (uap->req) {
+ case PT_IO:
+ (void)copyout(&r.piod, uap->addr, sizeof r.piod);
+ break;
+ case PT_GETREGS:
+ error = copyout(&r.reg, uap->addr, sizeof r.reg);
+ break;
+ case PT_GETFPREGS:
+ error = copyout(&r.fpreg, uap->addr, sizeof r.fpreg);
+ break;
+ case PT_GETDBREGS:
+ error = copyout(&r.dbreg, uap->addr, sizeof r.dbreg);
+ break;
+ }
+
+ return (error);
+}
+
+int
kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
{
+ return kern_ttrace(td, req, pid, 0, addr, data);
+}
+
+int
+kern_ttrace(struct thread *td, int req, pid_t pid, lwpid_t tid, void *addr,
+ int data)
+{
struct iovec iov;
struct uio uio;
struct proc *curp, *p, *pp;
struct thread *td2;
struct ptrace_io_desc *piod;
- int error, write, tmp;
+ int error, write, tmp, num;
int proctree_locked = 0;
+ lwpid_t *buf, tid2;
curp = td->td_proc;
@@ -448,6 +533,12 @@
/* OK */
break;
+ case PT_CLEARSTEP:
+ /* Allow thread to clear single step for itself */
+ if (td->td_tid == tid)
+ break;
+
+ /* FALLTHROUGH */
default:
/* not being traced... */
if ((p->p_flag & P_TRACED) == 0) {
@@ -462,7 +553,8 @@
}
/* not currently stopped */
- if (!P_SHOULDSTOP(p) || (p->p_flag & P_WAITED) == 0) {
+ if (!P_SHOULDSTOP(p) || p->p_suspcount != p->p_numthreads ||
+ (p->p_flag & P_WAITED) == 0) {
error = EBUSY;
goto fail;
}
@@ -471,7 +563,19 @@
break;
}
- td2 = FIRST_THREAD_IN_PROC(p);
+ if (tid == 0)
+ td2 = FIRST_THREAD_IN_PROC(p);
+ else {
+ FOREACH_THREAD_IN_PROC(p, td2) {
+ if (td2->td_tid == tid)
+ break;
+ }
+ if (td2 == NULL) {
+ error = ESRCH;
+ goto fail;
+ }
+ }
+
#ifdef FIX_SSTEP
/*
* Single step fixup ala procfs
@@ -503,6 +607,23 @@
data = SIGSTOP;
goto sendsig; /* in PT_CONTINUE below */
+ case PT_CLEARSTEP:
+ _PHOLD(p);
+ error = ptrace_clear_single_step(td2);
+ _PRELE(p);
+ if (error)
+ goto fail;
+ PROC_UNLOCK(p);
+ return (0);
+
+ case PT_SETSTEP:
+ _PHOLD(p);
+ error = ptrace_single_step(td2);
+ _PRELE(p);
+ if (error)
+ goto fail;
+ PROC_UNLOCK(p);
+ return (0);
case PT_STEP:
case PT_CONTINUE:
case PT_TO_SCE:
@@ -578,12 +699,13 @@
p->p_xstat = data;
p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG);
mtx_lock_spin(&sched_lock);
- thread_unsuspend(p);
- setrunnable(td2); /* XXXKSE */
- /* Need foreach kse in proc, ... make_kse_queued(). */
+ thread_unsuspend_one(p->p_xthread);
mtx_unlock_spin(&sched_lock);
- } else if (data)
+ p->p_xthread = NULL;
+ } else if (data) {
+ p->p_xthread = NULL;
psignal(p, data);
+ }
PROC_UNLOCK(p);
return (0);
@@ -697,6 +819,44 @@
PROC_UNLOCK(p);
return (error);
+ case PT_GETNUMTHRS:
+ td->td_retval[0] = p->p_numthreads;
+ PROC_UNLOCK(p);
+ return (0);
+
+ case PT_GETXTHREAD: /* Get trigger thread */
+ if (p->p_xthread)
+ tid2 = p->p_xthread->td_tid;
+ else
+ tid2 = td2->td_tid;
+ PROC_UNLOCK(p);
+ error = copyout(&tid2, addr, sizeof(lwpid_t));
+ return (error);
+
+ case PT_GETTHRLIST:
+ if (data <= 0) {
+ PROC_UNLOCK(p);
+ return (EINVAL);
+ }
+ num = imin(p->p_numthreads, data);
+ PROC_UNLOCK(p);
+ buf = malloc(num * sizeof(lwpid_t), M_TEMP, M_WAITOK);
+ tmp = 0;
+ PROC_LOCK(p);
+ mtx_lock_spin(&sched_lock);
+ FOREACH_THREAD_IN_PROC(p, td2) {
+ if (tmp >= num)
+ break;
+ buf[tmp++] = td2->td_tid;
+ }
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(p);
+ error = copyout(buf, addr, tmp * sizeof(lwpid_t));
+ free(buf, M_TEMP);
+ if (!error)
+ td->td_retval[0] = num;
+ return (error);
+
default:
#ifdef __HAVE_PTRACE_MACHDEP
if (req >= PT_FIRSTMACH) {
==== //depot/projects/davidxu_ksedbg/src/sys/sys/proc.h#2 (text+ko) ====
@@ -585,6 +585,7 @@
void *p_aioinfo; /* (?) ASYNC I/O info. */
struct thread *p_singlethread;/* (c + j) If single threading this is it */
int p_suspcount; /* (c) # threads in suspended mode */
+ struct thread *p_xthread; /* (c) Trap thread */
/* End area that is zeroed on creation. */
#define p_endzero p_magic
==== //depot/projects/davidxu_ksedbg/src/sys/sys/ptrace.h#2 (text+ko) ====
@@ -46,7 +46,7 @@
#define PT_ATTACH 10 /* trace some running process */
#define PT_DETACH 11 /* stop tracing a process */
-#define PT_IO 12 /* do I/O to/from stopped process. */
+#define PT_IO 12 /* do I/O to/from stopped process. */
#define PT_TO_SCE 20
#define PT_TO_SCX 21
@@ -58,8 +58,12 @@
#define PT_SETFPREGS 36 /* set floating-point registers */
#define PT_GETDBREGS 37 /* get debugging registers */
#define PT_SETDBREGS 38 /* set debugging registers */
-
-#define PT_FIRSTMACH 64 /* for machine-specific requests */
+#define PT_GETNUMTHRS 39 /* get total number of threads */
+#define PT_GETXTHREAD 40 /* get signal trigger thread */
+#define PT_GETTHRLIST 41 /* get thread list */
+#define PT_CLEARSTEP 42 /* turn off single step */
+#define PT_SETSTEP 43 /* turn on single step */
+#define PT_FIRSTMACH 64 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */
struct ptrace_io_desc {
@@ -93,6 +97,7 @@
int ptrace_set_pc(struct thread *_td, unsigned long _addr);
int ptrace_single_step(struct thread *_td);
+int ptrace_clear_single_step(struct thread *_td);
#ifdef __HAVE_PTRACE_MACHDEP
int cpu_ptrace(struct thread *_td, int _req, void *_addr, int _data);
@@ -122,6 +127,8 @@
__BEGIN_DECLS
int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
+int ttrace(int _request, pid_t _pid, lwpid_t _tid, caddr_t _addr,
+ int _data);
__END_DECLS
#endif /* !_KERNEL */
More information about the p4-projects
mailing list