PERFORCE change 103403 for review
Marcel Moolenaar
marcel at FreeBSD.org
Mon Aug 7 22:01:56 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103403
Change 103403 by marcel at 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) <<<
More information about the p4-projects
mailing list