Date: Sun, 27 Jun 2004 02:25:44 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 55876 for review Message-ID: <200406270225.i5R2Pic4084862@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=55876 Change 55876 by davidxu@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200406270225.i5R2Pic4084862>