diff options
author | iedowse <iedowse@FreeBSD.org> | 2002-09-05 01:02:50 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2002-09-05 01:02:50 +0000 |
commit | 0fc3eadf20ecae2b394e1856ed0c95e9d9fb83bd (patch) | |
tree | 88144ad581a587656c0375f96143cb040d046da5 /sys/i386/linux/linux_ptrace.c | |
parent | d049443a42264304294047ef289f370128540ce0 (diff) | |
download | FreeBSD-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.c | 147 |
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; |