summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux/linux_ptrace.c
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-09-05 01:02:50 +0000
committeriedowse <iedowse@FreeBSD.org>2002-09-05 01:02:50 +0000
commit0fc3eadf20ecae2b394e1856ed0c95e9d9fb83bd (patch)
tree88144ad581a587656c0375f96143cb040d046da5 /sys/i386/linux/linux_ptrace.c
parentd049443a42264304294047ef289f370128540ce0 (diff)
downloadFreeBSD-src-0fc3eadf20ecae2b394e1856ed0c95e9d9fb83bd.zip
FreeBSD-src-0fc3eadf20ecae2b394e1856ed0c95e9d9fb83bd.tar.gz
Split up ptrace() into a wrapper that does the copying to and from
user space and a kern_ptrace() implementation. Use the kern_*() version in the Linux emulation code to remove more stack gap uses. Approved by: des
Diffstat (limited to 'sys/i386/linux/linux_ptrace.c')
-rw-r--r--sys/i386/linux/linux_ptrace.c147
1 files changed, 52 insertions, 95 deletions
diff --git a/sys/i386/linux/linux_ptrace.c b/sys/i386/linux/linux_ptrace.c
index a19dcc7..f5e47f9 100644
--- a/sys/i386/linux/linux_ptrace.c
+++ b/sys/i386/linux/linux_ptrace.c
@@ -34,6 +34,7 @@
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
+#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/user.h>
@@ -246,119 +247,92 @@ linux_proc_write_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs)
int
linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
{
- struct ptrace_args bsd_args;
- int error;
- caddr_t sg;
union {
struct linux_pt_reg reg;
struct linux_pt_fpreg fpreg;
struct linux_pt_fpxreg fpxreg;
} r;
-
- sg = stackgap_init();
+ union {
+ struct reg bsd_reg;
+ struct fpreg bsd_fpreg;
+ struct dbreg bsd_dbreg;
+ } u;
+ void *addr;
+ pid_t pid;
+ int error, req;
error = 0;
/* by default, just copy data intact */
- bsd_args.req = uap->req;
- bsd_args.pid = (pid_t)uap->pid;
- bsd_args.addr = (caddr_t)uap->addr;
- bsd_args.data = uap->data;
+ req = uap->req;
+ pid = (pid_t)uap->pid;
+ addr = (void *)uap->addr;
- switch (uap->req) {
+ switch (req) {
case PTRACE_TRACEME:
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
case PTRACE_KILL:
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, req, pid, addr, uap->data);
break;
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA: {
/* need to preserve return value */
int rval = td->td_retval[0];
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, req, pid, addr, 0);
if (error == 0)
- error = copyout(td->td_retval,
- (caddr_t)uap->data, sizeof(l_int));
+ error = copyout(td->td_retval, (caddr_t)uap->data,
+ sizeof(l_int));
td->td_retval[0] = rval;
break;
}
case PTRACE_DETACH:
- bsd_args.req = PT_DETACH;
- /* fall through */
+ error = kern_ptrace(td, PT_DETACH, pid, (void *)1,
+ map_signum(uap->data));
+ break;
case PTRACE_SINGLESTEP:
case PTRACE_CONT:
- bsd_args.data = map_signum(uap->data);
- bsd_args.addr = (caddr_t)1;
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, req, pid, (void *)1,
+ map_signum(uap->data));
break;
case PTRACE_ATTACH:
- bsd_args.req = PT_ATTACH;
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
break;
- case PTRACE_GETREGS: {
- struct reg *bsd_r;
-
- bsd_r = (struct reg*)stackgap_alloc(&sg, sizeof(*bsd_r));
+ case PTRACE_GETREGS:
/* Linux is using data where FreeBSD is using addr */
- bsd_args.req = PT_GETREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
if (error == 0) {
- map_regs_to_linux(bsd_r, &r.reg);
+ map_regs_to_linux(&u.bsd_reg, &r.reg);
error = copyout(&r.reg, (caddr_t)uap->data,
sizeof(r.reg));
}
break;
- }
- case PTRACE_SETREGS: {
- struct reg *bsd_r;
-
- bsd_r = (struct reg*)stackgap_alloc(&sg, sizeof(*bsd_r));
+ case PTRACE_SETREGS:
/* Linux is using data where FreeBSD is using addr */
- bsd_args.req = PT_SETREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
error = copyin((caddr_t)uap->data, &r.reg, sizeof(r.reg));
if (error == 0) {
- map_regs_from_linux(bsd_r, &r.reg);
- error = ptrace(td, &bsd_args);
+ map_regs_from_linux(&u.bsd_reg, &r.reg);
+ error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
}
break;
- }
- case PTRACE_GETFPREGS: {
- struct fpreg *bsd_r;
-
- bsd_r = (struct fpreg*)stackgap_alloc(&sg, sizeof(*bsd_r));
+ case PTRACE_GETFPREGS:
/* Linux is using data where FreeBSD is using addr */
- bsd_args.req = PT_GETFPREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0);
if (error == 0) {
- map_fpregs_to_linux(bsd_r, &r.fpreg);
+ map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg);
error = copyout(&r.fpreg, (caddr_t)uap->data,
sizeof(r.fpreg));
}
break;
- }
- case PTRACE_SETFPREGS: {
- struct fpreg *bsd_r;
-
- bsd_r = (struct fpreg*)stackgap_alloc(&sg, sizeof(*bsd_r));
+ case PTRACE_SETFPREGS:
/* Linux is using data where FreeBSD is using addr */
- bsd_args.req = PT_SETFPREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
error = copyin((caddr_t)uap->data, &r.fpreg, sizeof(r.fpreg));
if (error == 0) {
- map_fpregs_from_linux(bsd_r, &r.fpreg);
- error = ptrace(td, &bsd_args);
+ map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg);
+ error = kern_ptrace(td, PT_SETFPREGS, pid,
+ &u.bsd_fpreg, 0);
}
break;
- }
case PTRACE_SETFPXREGS:
#ifdef CPU_ENABLE_SSA
error = copyin((caddr_t)uap->data, &r.fpxreg,
@@ -415,7 +389,7 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
}
td2 = FIRST_THREAD_IN_PROC(p);
- if (uap->req == PTRACE_GETFPXREGS) {
+ if (req == PTRACE_GETFPXREGS) {
_PHOLD(p);
error = linux_proc_read_fpxregs(td2, &r.fpxreg);
_PRELE(p);
@@ -453,20 +427,12 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
* as necessary.
*/
if (uap->addr < sizeof(struct linux_pt_reg)) {
- struct reg *bsd_r;
-
- bsd_r = (struct reg*)stackgap_alloc(&sg,
- sizeof(*bsd_r));
- bsd_args.req = PT_GETREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
-
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
if (error != 0)
break;
- map_regs_to_linux(bsd_r, &r.reg);
- if (uap->req == PTRACE_PEEKUSR) {
+ map_regs_to_linux(&u.bsd_reg, &r.reg);
+ if (req == PTRACE_PEEKUSR) {
error = copyout((char *)&r.reg + uap->addr,
(caddr_t)uap->data, sizeof(l_int));
break;
@@ -475,11 +441,8 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
*(l_int *)((char *)&r.reg + uap->addr) =
(l_int)uap->data;
- map_regs_from_linux(bsd_r, &r.reg);
- bsd_args.req = PT_SETREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
+ map_regs_from_linux(&u.bsd_reg, &r.reg);
+ error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
}
/*
@@ -487,29 +450,23 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
*/
if (uap->addr >= LINUX_DBREG_OFFSET &&
uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) {
- struct dbreg *bsd_r;
-
- bsd_r = (struct dbreg*)stackgap_alloc(&sg,
- sizeof(*bsd_r));
- bsd_args.req = PT_GETDBREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
+ error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg,
+ 0);
if (error != 0)
break;
uap->addr -= LINUX_DBREG_OFFSET;
- if (uap->req == PTRACE_PEEKUSR) {
- error = copyout((char *)bsd_r + uap->addr,
- (caddr_t)uap->data, sizeof(l_int));
+ if (req == PTRACE_PEEKUSR) {
+ error = copyout((char *)&u.bsd_dbreg +
+ uap->addr, (caddr_t)uap->data,
+ sizeof(l_int));
break;
}
- *(l_int *)((char *)bsd_r + uap->addr) = uap->data;
- bsd_args.req = PT_SETDBREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
+ *(l_int *)((char *)&u.bsd_dbreg + uap->addr) =
+ uap->data;
+ error = kern_ptrace(td, PT_SETDBREGS, pid,
+ &u.bsd_dbreg, 0);
}
break;
OpenPOWER on IntegriCloud