Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Aug 2006 22:01:53 GMT
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 103403 for review
Message-ID:  <200608072201.k77M1rGJ074123@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103403

Change 103403 by marcel@marcel_nfs on 2006/08/07 22:01:07

	The PT_GET{,DB,FP}REGS and PT_SET{,DB,FP}REGS requests are now
	based on a new data structure, called struct ptgetset. The
	struct ptregset is a meta-structure that describes the size of
	the register set and has two function pointers: one to build
	the register set from the thread's context and one to update
	the thread's context from the register set. These functions
	do the same as fill_*regs() and set_*regs() without having to
	hard code that.
	The 3 struct ptregset data structures are linked to from the
	process' sysentvec. As such, kern_ptrace() can now handle these
	requests without having to go through translation steps (see
	sys/i386/linux/linux_ptrace.c) or without having to hardcode 
	special cases (see COMPAT_IA32).
	
	Add PT_GETXREGSIZE, PT_GETXREGS and PT_SETXREGS requests that
	too are based on struct ptregset. The data argument is used as
	an index, allowing for multiple extra (machine-specific) sets.
	The struct ptregset abtracts the MD differences between the
	extra registers. These requests are needed on ia64 and i386
	and are to be used by GDB, in relation to proc_services.h and
	thread_db.h.
	
	Update procfs(4), thereby eliminating the hardcoding fo handling
	COMPAT_IA32.
	
	This commit does not have the changes to the various sysentvecs
	and is therefore incomplete...

Affected files ...

.. //depot/projects/gdb/sys/arm/arm/machdep.c#6 edit
.. //depot/projects/gdb/sys/fs/procfs/procfs_ctl.c#4 edit
.. //depot/projects/gdb/sys/fs/procfs/procfs_dbregs.c#4 edit
.. //depot/projects/gdb/sys/fs/procfs/procfs_fpregs.c#4 edit
.. //depot/projects/gdb/sys/fs/procfs/procfs_mem.c#4 edit
.. //depot/projects/gdb/sys/fs/procfs/procfs_regs.c#4 edit
.. //depot/projects/gdb/sys/i386/linux/linux_ptrace.c#4 edit
.. //depot/projects/gdb/sys/ia64/ia64/machdep.c#15 edit
.. //depot/projects/gdb/sys/kern/sys_process.c#11 edit
.. //depot/projects/gdb/sys/sys/ptrace.h#7 edit
.. //depot/projects/gdb/sys/sys/syscallsubr.h#4 edit
.. //depot/projects/gdb/sys/sys/sysent.h#5 edit

Differences ...

==== //depot/projects/gdb/sys/arm/arm/machdep.c#6 (text+ko) ====

@@ -364,7 +364,7 @@
 	uio.uio_segflg = UIO_SYSSPACE;
 	uio.uio_rw = UIO_READ;
 	uio.uio_td = td;
-	return proc_rwmem(td->td_proc, &uio);
+	return ptrace_rwmem(td->td_proc, &uio);
 }
 
 static int
@@ -383,7 +383,7 @@
 	uio.uio_segflg = UIO_SYSSPACE;
 	uio.uio_rw = UIO_WRITE;
 	uio.uio_td = td;
-	return proc_rwmem(td->td_proc, &uio);
+	return ptrace_rwmem(td->td_proc, &uio);
 }
 
 int

==== //depot/projects/gdb/sys/fs/procfs/procfs_ctl.c#4 (text+ko) ====

@@ -245,7 +245,7 @@
 	 * What does it mean to single step a threaded program?
 	 */
 	case PROCFS_CTL_STEP:
-		error = proc_sstep(FIRST_THREAD_IN_PROC(p)); /* XXXKSE */
+		error = ptrace_sstep(FIRST_THREAD_IN_PROC(p)); /* XXXKSE */
 		PROC_UNLOCK(p);
 		if (error)
 			return (error);

==== //depot/projects/gdb/sys/fs/procfs/procfs_dbregs.c#4 (text+ko) ====

@@ -48,52 +48,27 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/lock.h>
+#include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
+#include <sys/sysent.h>
 #include <sys/uio.h>
 
-#include <machine/reg.h>
-
 #include <fs/pseudofs/pseudofs.h>
 #include <fs/procfs/procfs.h>
 
 #ifdef COMPAT_IA32
-#include <sys/procfs.h>
-#include <machine/fpu.h>
-#include <compat/ia32/ia32_reg.h>
-
 extern struct sysentvec ia32_freebsd_sysvec;
-/*
- * PROC(write, dbregs, td2, &r) becomes
- * proc_write_dbregs(td2, &r)   or
- * proc_write_dbregs32(td2, &r32)
- *
- * UIOMOVE_FROMBUF(r, uio) becomes
- * uiomove_frombuf(&r, sizeof(r), uio)  or
- * uiomove_frombuf(&r32, sizeof(r32), uio)
- */
-#define	PROC(d, w, t, r)	wrap32 ? \
-	proc_ ## d ## _ ## w ## 32(t, r ## 32) : \
-	proc_ ## d ## _ ## w(t, r)
-#define	UIOMOVE_FROMBUF(k, u)	wrap32 ? \
-	uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \
-	uiomove_frombuf(& k, sizeof(k), u)
-#else
-#define	PROC(d, w, t, r)	proc_ ## d ## _ ## w(t, r)
-#define	UIOMOVE_FROMBUF(k, u)	uiomove_frombuf(& k, sizeof(k), u)
 #endif
 
 int
 procfs_doprocdbregs(PFS_FILL_ARGS)
 {
+	struct sysentvec *sv;
+	struct thread *td2;
+	void *buf;
 	int error;
-	struct dbreg r;
-	struct thread *td2;
-#ifdef COMPAT_IA32
-	struct dbreg32 r32;
-	int wrap32 = 0;
-#endif
 
 	PROC_LOCK(p);
 	KASSERT(p->p_lock > 0, ("proc not held"));
@@ -104,19 +79,30 @@
 
 	/* XXXKSE: */
 	td2 = FIRST_THREAD_IN_PROC(p);
+	sv = td2->td_proc->p_sysent;
+
+	if (sv->sv_dbreg == NULL) {
+		PROC_UNLOCK(p);
+		return (ENXIO);
+	}
 #ifdef COMPAT_IA32
-	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
-		if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) {
-			PROC_UNLOCK(p);
-			return (EINVAL);
-		}
-		wrap32 = 1;
+	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec &&
+	    sv != &ia32_freebsd_sysvec) {
+		PROC_UNLOCK(p);
+		return (EINVAL);
 	}
 #endif
-	error = PROC(read, dbregs, td2, &r);
+
+	PROC_UNLOCK(p);
+	buf = malloc(sv->sv_dbreg->rs_size, M_TEMP, M_WAITOK);
+	if (buf == NULL)
+		return (ENOMEM);
+
+	PROC_LOCK(p);
+	error = ptrace_read_regf(td2, buf, sv->sv_dbreg->rs_read);
 	if (error == 0) {
 		PROC_UNLOCK(p);
-		error = UIOMOVE_FROMBUF(r, uio);
+		error = uiomove_frombuf(buf, sv->sv_dbreg->rs_size, uio);
 		PROC_LOCK(p);
 	}
 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
@@ -124,10 +110,12 @@
 			error = EBUSY;
 		else
 			/* XXXKSE: */
-			error = PROC(write, dbregs, td2, &r);
+			error = ptrace_write_regf(td2, buf,
+			    sv->sv_dbreg->rs_write);
 	}
 	PROC_UNLOCK(p);
 
+	free(buf, M_TEMP);
 	uio->uio_offset = 0;
 	return (error);
 }

==== //depot/projects/gdb/sys/fs/procfs/procfs_fpregs.c#4 (text+ko) ====

@@ -42,52 +42,27 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/lock.h>
+#include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
+#include <sys/sysent.h>
 #include <sys/uio.h>
 
-#include <machine/reg.h>
-
 #include <fs/pseudofs/pseudofs.h>
 #include <fs/procfs/procfs.h>
 
 #ifdef COMPAT_IA32
-#include <sys/procfs.h>
-#include <machine/fpu.h>
-#include <compat/ia32/ia32_reg.h>
-
 extern struct sysentvec ia32_freebsd_sysvec;
-/*
- * PROC(write, fpregs, td2, &r) becomes
- * proc_write_fpregs(td2, &r)   or
- * proc_write_fpregs32(td2, &r32)
- *
- * UIOMOVE_FROMBUF(r, uio) becomes
- * uiomove_frombuf(&r, sizeof(r), uio)  or
- * uiomove_frombuf(&r32, sizeof(r32), uio)
- */
-#define	PROC(d, w, t, r)	wrap32 ? \
-	proc_ ## d ## _ ## w ## 32(t, r ## 32) : \
-	proc_ ## d ## _ ## w(t, r)
-#define	UIOMOVE_FROMBUF(k, u)	wrap32 ? \
-	uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \
-	uiomove_frombuf(& k, sizeof(k), u)
-#else
-#define	PROC(d, w, t, r)	proc_ ## d ## _ ## w(t, r)
-#define	UIOMOVE_FROMBUF(k, u)	uiomove_frombuf(& k, sizeof(k), u)
 #endif
 
 int
 procfs_doprocfpregs(PFS_FILL_ARGS)
 {
+	struct sysentvec *sv;
+	struct thread *td2;
+	void *buf;
 	int error;
-	struct fpreg r;
-	struct thread *td2;
-#ifdef COMPAT_IA32
-	struct fpreg32 r32;
-	int wrap32 = 0;
-#endif
 
 	PROC_LOCK(p);
 	KASSERT(p->p_lock > 0, ("proc not held"));
@@ -98,19 +73,31 @@
 
 	/* XXXKSE: */
 	td2 = FIRST_THREAD_IN_PROC(p);
+	sv = td2->td_proc->p_sysent;
+
+	if (sv->sv_fpreg == NULL) {
+		PROC_UNLOCK(p);
+		return (ENXIO);
+	}
+
 #ifdef COMPAT_IA32
-	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
-		if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) {
-			PROC_UNLOCK(p);
-			return (EINVAL);
-		}
-		wrap32 = 1;
+	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec &&
+	    sv != &ia32_freebsd_sysvec) {
+		PROC_UNLOCK(p);
+		return (EINVAL);
 	}
 #endif
-	error = PROC(read, fpregs, td2, &r);
+
+	PROC_UNLOCK(p);
+	buf = malloc(sv->sv_fpreg->rs_size, M_TEMP, M_WAITOK);
+	if (buf == NULL)
+		return (ENOMEM);
+
+	PROC_LOCK(p);
+	error = ptrace_read_regf(td2, buf, sv->sv_fpreg->rs_read);
 	if (error == 0) {
 		PROC_UNLOCK(p);
-		error = UIOMOVE_FROMBUF(r, uio);
+		error = uiomove_frombuf(buf, sv->sv_fpreg->rs_size, uio);
 		PROC_LOCK(p);
 	}
 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
@@ -118,10 +105,12 @@
 			error = EBUSY;
 		else
 			/* XXXKSE: */
-			error = PROC(write, fpregs, td2, &r);
+			error = ptrace_write_regf(td2, buf,
+			    sv->sv_fpreg->rs_write);
 	}
 	PROC_UNLOCK(p);
 
+	free(buf, M_TEMP);
 	uio->uio_offset = 0;
 	return (error);
 }

==== //depot/projects/gdb/sys/fs/procfs/procfs_mem.c#4 (text+ko) ====

@@ -65,7 +65,7 @@
 	error = p_candebug(td, p);
 	PROC_UNLOCK(p);
 	if (error == 0)
-		error = proc_rwmem(p, uio);
+		error = ptrace_rwmem(p, uio);
 
 	return (error);
 }

==== //depot/projects/gdb/sys/fs/procfs/procfs_regs.c#4 (text+ko) ====

@@ -42,52 +42,27 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/lock.h>
+#include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
+#include <sys/sysent.h>
 #include <sys/uio.h>
 
-#include <machine/reg.h>
-
 #include <fs/pseudofs/pseudofs.h>
 #include <fs/procfs/procfs.h>
 
 #ifdef COMPAT_IA32
-#include <sys/procfs.h>
-#include <machine/fpu.h>
-#include <compat/ia32/ia32_reg.h>
-
 extern struct sysentvec ia32_freebsd_sysvec;
-/*
- * PROC(write, regs, td2, &r) becomes
- * proc_write_regs(td2, &r)   or
- * proc_write_regs32(td2, &r32)
- *
- * UIOMOVE_FROMBUF(r, uio) becomes
- * uiomove_frombuf(&r, sizeof(r), uio)  or
- * uiomove_frombuf(&r32, sizeof(r32), uio)
- */
-#define	PROC(d, w, t, r)	wrap32 ? \
-	proc_ ## d ## _ ## w ## 32(t, r ## 32) : \
-	proc_ ## d ## _ ## w(t, r)
-#define	UIOMOVE_FROMBUF(k, u)	wrap32 ? \
-	uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \
-	uiomove_frombuf(& k, sizeof(k), u)
-#else
-#define	PROC(d, w, t, r)	proc_ ## d ## _ ## w(t, r)
-#define	UIOMOVE_FROMBUF(k, u)	uiomove_frombuf(& k, sizeof(k), u)
 #endif
 
 int
 procfs_doprocregs(PFS_FILL_ARGS)
 {
+	struct sysentvec *sv;
+	struct thread *td2;
+	void *buf;
 	int error;
-	struct reg r;
-	struct thread *td2;
-#ifdef COMPAT_IA32
-	struct reg32 r32;
-	int wrap32 = 0;
-#endif
 
 	PROC_LOCK(p);
 	KASSERT(p->p_lock > 0, ("proc not held"));
@@ -98,19 +73,31 @@
 
 	/* XXXKSE: */
 	td2 = FIRST_THREAD_IN_PROC(p);
+	sv = td2->td_proc->p_sysent;
+
+	if (sv->sv_reg == NULL) {
+		PROC_UNLOCK(p);
+		return (ENXIO);
+	}
+
 #ifdef COMPAT_IA32
-	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
-		if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) {
-			PROC_UNLOCK(p);
-			return (EINVAL);
-		}
-		wrap32 = 1;
+	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec &&
+	    sv != &ia32_freebsd_sysvec) {
+		PROC_UNLOCK(p);
+		return (EINVAL);
 	}
 #endif
-	error = PROC(read, regs, td2, &r);
+
+	PROC_UNLOCK(p);
+	buf = malloc(sv->sv_reg->rs_size, M_TEMP, M_WAITOK);
+	if (buf == NULL)
+		return (ENOMEM);
+ 
+	PROC_LOCK(p);
+	error = ptrace_read_regf(td2, buf, sv->sv_reg->rs_read);
 	if (error == 0) {
 		PROC_UNLOCK(p);
-		error = UIOMOVE_FROMBUF(r, uio);
+		error = uiomove_frombuf(buf, sv->sv_reg->rs_size, uio);
 		PROC_LOCK(p);
 	}
 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
@@ -118,10 +105,12 @@
 			error = EBUSY;
 		else
 			/* XXXKSE: */
-			error = PROC(write, regs, td2, &r);
+			error = ptrace_write_regf(td2, buf,
+			    sv->sv_reg->rs_write);
 	}
 	PROC_UNLOCK(p);
 
+	free(buf, M_TEMP);
 	uio->uio_offset = 0;
 	return (error);
 }

==== //depot/projects/gdb/sys/i386/linux/linux_ptrace.c#4 (text+ko) ====

@@ -269,13 +269,13 @@
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
 	case PTRACE_KILL:
-		error = kern_ptrace(td, req, pid, addr, uap->data);
+		error = kern_ptrace(td, req, pid, 0, addr, uap->data);
 		break;
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA: {
 		/* need to preserve return value */
 		int rval = td->td_retval[0];
-		error = kern_ptrace(td, req, pid, addr, 0);
+		error = kern_ptrace(td, req, pid, 0, addr, 0);
 		if (error == 0)
 			error = copyout(td->td_retval, (void *)uap->data,
 			    sizeof(l_int));
@@ -283,20 +283,20 @@
 		break;
 	}
 	case PTRACE_DETACH:
-		error = kern_ptrace(td, PT_DETACH, pid, (void *)1,
+		error = kern_ptrace(td, PT_DETACH, pid, 0, (void *)1,
 		     map_signum(uap->data));
 		break;
 	case PTRACE_SINGLESTEP:
 	case PTRACE_CONT:
-		error = kern_ptrace(td, req, pid, (void *)1,
+		error = kern_ptrace(td, req, pid, 0, (void *)1,
 		     map_signum(uap->data));
 		break;
 	case PTRACE_ATTACH:
-		error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
+		error = kern_ptrace(td, PT_ATTACH, pid, 0, addr, uap->data);
 		break;
 	case PTRACE_GETREGS:
 		/* Linux is using data where FreeBSD is using addr */
-		error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
+		error = kern_ptrace(td, PT_GETREGS, pid, 0, &u.bsd_reg, 0);
 		if (error == 0) {
 			map_regs_to_linux(&u.bsd_reg, &r.reg);
 			error = copyout(&r.reg, (void *)uap->data,
@@ -308,12 +308,13 @@
 		error = copyin((void *)uap->data, &r.reg, sizeof(r.reg));
 		if (error == 0) {
 			map_regs_from_linux(&u.bsd_reg, &r.reg);
-			error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
+			error = kern_ptrace(td, PT_SETREGS, pid, 0, &u.bsd_reg,
+			    0);
 		}
 		break;
 	case PTRACE_GETFPREGS:
 		/* Linux is using data where FreeBSD is using addr */
-		error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0);
+		error = kern_ptrace(td, PT_GETFPREGS, pid, 0, &u.bsd_fpreg, 0);
 		if (error == 0) {
 			map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg);
 			error = copyout(&r.fpreg, (void *)uap->data,
@@ -325,7 +326,7 @@
 		error = copyin((void *)uap->data, &r.fpreg, sizeof(r.fpreg));
 		if (error == 0) {
 			map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg);
-			error = kern_ptrace(td, PT_SETFPREGS, pid,
+			error = kern_ptrace(td, PT_SETFPREGS, pid, 0,
 			    &u.bsd_fpreg, 0);
 		}
 		break;
@@ -429,7 +430,8 @@
 		 * as necessary.
 		 */
 		if (uap->addr < sizeof(struct linux_pt_reg)) {
-			error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
+			error = kern_ptrace(td, PT_GETREGS, pid, 0, &u.bsd_reg,
+			    0);
 			if (error != 0)
 				break;
 
@@ -444,7 +446,8 @@
 			    (l_int)uap->data;
 
 			map_regs_from_linux(&u.bsd_reg, &r.reg);
-			error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
+			error = kern_ptrace(td, PT_SETREGS, pid, 0, &u.bsd_reg,
+			    0);
 		}
 
 		/*
@@ -452,8 +455,8 @@
 		 */
 		if (uap->addr >= LINUX_DBREG_OFFSET &&
 		    uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) {
-			error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg,
-			    0);
+			error = kern_ptrace(td, PT_GETDBREGS, pid, 0,
+			   &u.bsd_dbreg, 0);
 			if (error != 0)
 				break;
 
@@ -467,7 +470,7 @@
 
 			*(l_int *)((char *)&u.bsd_dbreg + uap->addr) =
 			     uap->data;
-			error = kern_ptrace(td, PT_SETDBREGS, pid,
+			error = kern_ptrace(td, PT_SETDBREGS, pid, 0,
 			    &u.bsd_dbreg, 0);
 		}
 

==== //depot/projects/gdb/sys/ia64/ia64/machdep.c#15 (text+ko) ====

@@ -1115,9 +1115,9 @@
 		uio.uio_segflg = UIO_SYSSPACE;
 		uio.uio_rw = UIO_WRITE;
 		uio.uio_td = td;
-		error = proc_rwmem(td->td_proc, &uio);
+		error = ptrace_rwmem(td->td_proc, &uio);
 		/*
-		 * XXX proc_rwmem() doesn't currently return ENOSPC,
+		 * XXX ptrace_rwmem() doesn't currently return ENOSPC,
 		 * so I think it can bogusly return 0. Neither do
 		 * we allow short writes.
 		 */

==== //depot/projects/gdb/sys/kern/sys_process.c#11 (text+ko) ====

@@ -39,6 +39,7 @@
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/syscallsubr.h>
+#include <sys/sysent.h>
 #include <sys/sysproto.h>
 #include <sys/proc.h>
 #include <sys/vnode.h>
@@ -74,32 +75,6 @@
 };
 #endif
 
-/*
- * Functions implemented using PROC_ACTION():
- *
- * proc_read_regs(proc, regs)
- *	Get the current user-visible register set from the process
- *	and copy it into the regs structure (<machine/reg.h>).
- *	The process is stopped at the time read_regs is called.
- *
- * proc_write_regs(proc, regs)
- *	Update the current register set from the passed in regs
- *	structure.  Take care to avoid clobbering special CPU
- *	registers or privileged bits in the PSL.
- *	Depending on the architecture this may have fix-up work to do,
- *	especially if the IAR or PCW are modified.
- *	The process is stopped at the time write_regs is called.
- *
- * proc_read_fpregs, proc_write_fpregs
- *	deal with the floating point register set, otherwise as above.
- *
- * proc_read_dbregs, proc_write_dbregs
- *	deal with the processor debug register set, otherwise as above.
- *
- * proc_sstep(proc)
- *	Arrange for the process to trap after executing a single instruction.
- */
-
 #define	PROC_ACTION(action) do {					\
 	int error;							\
 									\
@@ -112,105 +87,28 @@
 } while(0)
 
 int
-proc_read_regs(struct thread *td, struct reg *regs)
+ptrace_read_regf(struct thread *td, void *reg, ptregset_readf f)
 {
 
-	PROC_ACTION(fill_regs(td, regs));
+	PROC_ACTION((*f)(td, reg));
 }
 
 int
-proc_write_regs(struct thread *td, struct reg *regs)
+ptrace_write_regf(struct thread *td, const void *reg, ptregset_writef f)
 {
 
-	PROC_ACTION(set_regs(td, regs));
+	PROC_ACTION((*f)(td, reg));
 }
 
 int
-proc_read_dbregs(struct thread *td, struct dbreg *dbregs)
-{
-
-	PROC_ACTION(fill_dbregs(td, dbregs));
-}
-
-int
-proc_write_dbregs(struct thread *td, struct dbreg *dbregs)
-{
-
-	PROC_ACTION(set_dbregs(td, dbregs));
-}
-
-/*
- * Ptrace doesn't support fpregs at all, and there are no security holes
- * or translations for fpregs, so we can just copy them.
- */
-int
-proc_read_fpregs(struct thread *td, struct fpreg *fpregs)
-{
-
-	PROC_ACTION(fill_fpregs(td, fpregs));
-}
-
-int
-proc_write_fpregs(struct thread *td, struct fpreg *fpregs)
-{
-
-	PROC_ACTION(set_fpregs(td, fpregs));
-}
-
-#ifdef COMPAT_IA32
-/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */
-int
-proc_read_regs32(struct thread *td, struct reg32 *regs32)
-{
-
-	PROC_ACTION(fill_regs32(td, regs32));
-}
-
-int
-proc_write_regs32(struct thread *td, struct reg32 *regs32)
-{
-
-	PROC_ACTION(set_regs32(td, regs32));
-}
-
-int
-proc_read_dbregs32(struct thread *td, struct dbreg32 *dbregs32)
-{
-
-	PROC_ACTION(fill_dbregs32(td, dbregs32));
-}
-
-int
-proc_write_dbregs32(struct thread *td, struct dbreg32 *dbregs32)
-{
-
-	PROC_ACTION(set_dbregs32(td, dbregs32));
-}
-
-int
-proc_read_fpregs32(struct thread *td, struct fpreg32 *fpregs32)
-{
-
-	PROC_ACTION(fill_fpregs32(td, fpregs32));
-}
-
-int
-proc_write_fpregs32(struct thread *td, struct fpreg32 *fpregs32)
-{
-
-	PROC_ACTION(set_fpregs32(td, fpregs32));
-}
-#endif
-
-int
-proc_sstep(struct thread *td)
+ptrace_sstep(struct thread *td)
 {
 
 	PROC_ACTION(ptrace_single_step(td));
 }
 
 int
-proc_rwmem(struct proc *p, struct uio *uio)
+ptrace_rwmem(struct proc *p, struct uio *uio)
 {
 	vm_map_t map;
 	vm_object_t backing_object, object = NULL;
@@ -347,156 +245,164 @@
 };
 #endif
 
-#ifdef COMPAT_IA32
-/*
- * This CPP subterfuge is to try and reduce the number of ifdefs in
- * the body of the code.
- *   COPYIN(uap->addr, &r.reg, sizeof r.reg);
- * becomes either:
- *   copyin(uap->addr, &r.reg, sizeof r.reg);
- * or
- *   copyin(uap->addr, &r.reg32, sizeof r.reg32);
- * .. except this is done at runtime.
- */
-#define	COPYIN(u, k, s)		wrap32 ? \
-	copyin(u, k ## 32, s ## 32) : \
-	copyin(u, k, s)
-#define	COPYOUT(k, u, s)	wrap32 ? \
-	copyout(k ## 32, u, s ## 32) : \
-	copyout(k, u, s)
-#else
-#define	COPYIN(u, k, s)		copyin(u, k, s)
-#define	COPYOUT(k, u, s)	copyout(k, u, s)
-#endif
 /*
  * MPSAFE
  */
 int
 ptrace(struct thread *td, struct ptrace_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 ptrace_lwpinfo pl;
-		struct dbreg dbreg;
-		struct fpreg fpreg;
-		struct reg reg;
-#ifdef COMPAT_IA32
-		struct dbreg32 dbreg32;
-		struct fpreg32 fpreg32;
-		struct reg32 reg32;
-		struct ptrace_io_desc32 piod32;
-#endif
-	} r;
 	void *addr;
-	int error = 0;
-#ifdef COMPAT_IA32
-	int wrap32 = 0;
+	struct sysentvec *sv;
+	struct proc *p;
+	struct thread *td2;
+	size_t bufsz;
+	int error;
+	lwpid_t tid;
 
-	if (td->td_proc->p_sysent == &ia32_freebsd_sysvec)
-		wrap32 = 1;
-#endif
 	AUDIT_ARG(pid, uap->pid);
 	AUDIT_ARG(cmd, uap->req);
 	AUDIT_ARG(addr, uap->addr);
 	AUDIT_ARG(value, uap->data);
-	addr = &r;
+
+	tid = 0;
+	if (uap->req == PT_TRACE_ME) {
+		p = td->td_proc;
+		PROC_LOCK(p);
+	} else {
+		if (uap->pid <= PID_MAX) {
+			p = pfind(uap->pid);
+			if (p == NULL)
+				return (ESRCH);
+		} else {
+			tid = uap->pid;
+			sx_slock(&allproc_lock);
+			FOREACH_PROC_IN_SYSTEM(p) {
+				PROC_LOCK(p);
+				mtx_lock_spin(&sched_lock);
+				FOREACH_THREAD_IN_PROC(p, td2) {
+					if (td2->td_tid == tid)
+						break;
+				}
+				mtx_unlock_spin(&sched_lock);
+				if (td2 != NULL)
+					break;	/* proc lock held */
+				PROC_UNLOCK(p);
+			}
+			sx_sunlock(&allproc_lock);
+			if (p == NULL)
+				return (ESRCH);
+			uap->pid = p->p_pid;
+		}
+	}
+
+	sv = p->p_sysent;
+
 	switch (uap->req) {
 	case PT_GETREGS:
+	case PT_SETREGS:
+		bufsz = sv->sv_reg->rs_size;
+		break;
 	case PT_GETFPREGS:
+	case PT_SETFPREGS:
+		bufsz = sv->sv_fpreg->rs_size;
+		break;
 	case PT_GETDBREGS:
+	case PT_SETDBREGS:
+		bufsz = sv->sv_dbreg->rs_size;
+		break;
+	case PT_GETXREGSIZE:
+		bufsz = sizeof(size_t);
+		break;
+	case PT_GETXREGS:
+	case PT_SETXREGS:
+		if (uap->data < 0 || uap->data >= sv->sv_nxregs) {
+			PROC_UNLOCK(p);
+			return (EINVAL);
+		}
+		bufsz = sv->sv_xregs[uap->data].rs_size;
+		break;
 	case PT_LWPINFO:
+		bufsz = sizeof(struct ptrace_lwpinfo);
 		break;
+	case PT_IO:
+		if (sv == &ia32_freebsd_sysvec)
+			bufsz = sizeof(struct ptrace_io_desc32);
+		else
+			bufsz = sizeof(struct ptrace_io_desc);
+		break;
+	default:
+		bufsz = 0;
+		break;
+	}
+	PROC_UNLOCK(p);
+
+	if (bufsz != 0) {
+		addr = malloc(bufsz, M_TEMP, M_WAITOK);
+		if (addr == NULL)
+			return (ENOMEM);
+	} else
+		addr = uap->addr;
+
+	switch (uap->req) {
 	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_SETXREGS:
 	case PT_IO:
-		error = COPYIN(uap->addr, &r.piod, sizeof r.piod);
+		error = copyin(uap->addr, addr, bufsz);
 		break;
 	default:
-		addr = uap->addr;
+		error = 0;
 		break;
 	}
 	if (error)
-		return (error);
+		goto out;
 
-	error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
+	error = kern_ptrace(td, uap->req, uap->pid, tid, addr, uap->data);
 	if (error)
-		return (error);
+		goto out;
 
 	switch (uap->req) {
-	case PT_IO:
-		error = COPYOUT(&r.piod, uap->addr, sizeof r.piod);
-		break;
+	case PT_LWPINFO:
+		if (uap->data < bufsz)
+			bufsz = uap->data;
+		/* FALLTHROUGH */
 	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);
+	case PT_GETXREGSIZE:
+	case PT_GETXREGS:
+	case PT_IO:
+		error = copyout(addr, uap->addr, bufsz);
 		break;
-	case PT_LWPINFO:
-		error = copyout(&r.pl, uap->addr, uap->data);
+	default:
+		error = 0;
 		break;
 	}
 
+out:
+	if (bufsz > 0)
+		free(addr, M_TEMP);
 	return (error);
 }
-#undef COPYIN
-#undef COPYOUT
-
-#ifdef COMPAT_IA32
-/*
- *   PROC_READ(regs, td2, addr);
- * becomes either:
- *   proc_read_regs(td2, addr);
- * or
- *   proc_read_regs32(td2, addr);
- * .. except this is done at runtime.  There is an additional
- * complication in that PROC_WRITE disallows 32 bit consumers
- * from writing to 64 bit address space targets.
- */
-#define	PROC_READ(w, t, a)	wrap32 ? \
-	proc_read_ ## w ## 32(t, a) : \
-	proc_read_ ## w (t, a)
-#define	PROC_WRITE(w, t, a)	wrap32 ? \
-	(safe ? proc_write_ ## w ## 32(t, a) : EINVAL ) : \
-	proc_write_ ## w (t, a)
-#else
-#define	PROC_READ(w, t, a)	proc_read_ ## w (t, a)
-#define	PROC_WRITE(w, t, a)	proc_write_ ## w (t, a)
-#endif
 
 int
-kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
+kern_ptrace(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 proc *p, *pp;
+	struct sysentvec *sv;
 	struct thread *td2 = NULL;
 	struct ptrace_io_desc *piod = NULL;
 	struct ptrace_lwpinfo *pl;
 	int error, write, tmp, num;
 	int proctree_locked = 0;
-	lwpid_t tid = 0, *buf;
+	lwpid_t *buf;
 #ifdef COMPAT_IA32
-	int wrap32 = 0, safe = 0;
 	struct ptrace_io_desc32 *piod32 = NULL;
 #endif
 
-	curp = td->td_proc;
-
 	/* Lock proctree before locking the process. */
 	switch (req) {
 	case PT_TRACE_ME:
@@ -519,35 +425,31 @@
 		p = td->td_proc;
 		PROC_LOCK(p);
 	} else {
-		if (pid <= PID_MAX) {
-			if ((p = pfind(pid)) == NULL) {
-				if (proctree_locked)
-					sx_xunlock(&proctree_lock);
-				return (ESRCH);
+		p = pfind(pid);
+		if (p == NULL) {
+			if (proctree_locked)
+				sx_xunlock(&proctree_lock);
+			return (ESRCH);
+		}
+		if (tid != 0) {
+			mtx_lock_spin(&sched_lock);
+			FOREACH_THREAD_IN_PROC(p, td2) {
+				if (td2->td_tid == tid)
+					break;
 			}
-		} else {
-			/* this is slow, should be optimized */
-			sx_slock(&allproc_lock);

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608072201.k77M1rGJ074123>