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