version 1.14, 2008/12/17 20:51:33 |
version 1.14.6.1, 2010/07/03 01:19:31 |
Line 90 struct linux_reg { |
|
Line 90 struct linux_reg { |
|
int linux_ptrace_disabled = 1; /* bitrotted */ |
int linux_ptrace_disabled = 1; /* bitrotted */ |
|
|
int |
int |
linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval) |
linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, |
|
register_t *retval) |
{ |
{ |
/* { |
/* { |
syscallarg(int) request; |
syscallarg(int) request; |
Line 98 linux_sys_ptrace_arch(struct lwp *l, con |
|
Line 99 linux_sys_ptrace_arch(struct lwp *l, con |
|
syscallarg(int) addr; |
syscallarg(int) addr; |
syscallarg(int) data; |
syscallarg(int) data; |
} */ |
} */ |
struct proc *p = l->l_proc; |
struct proc *p = l->l_proc, *t; |
int request, error; |
|
struct proc *t; /* target process */ |
|
struct lwp *lt; |
struct lwp *lt; |
struct reg *regs = NULL; |
struct reg *regs = NULL; |
struct fpreg *fpregs = NULL; |
|
struct linux_reg *linux_regs = NULL; |
struct linux_reg *linux_regs = NULL; |
struct linux_fpreg *linux_fpregs = NULL; |
int request, error; |
|
|
if (linux_ptrace_disabled) |
if (linux_ptrace_disabled) |
return ENOSYS; |
return ENOSYS; |
|
|
|
error = 0; |
request = SCARG(uap, request); |
request = SCARG(uap, request); |
|
regs = kmem_alloc(sizeof(struct reg), KM_SLEEP); |
|
linux_regs = kmem_alloc(sizeof(struct linux_reg), KM_SLEEP); |
|
|
if ((request != LINUX_PTRACE_GETREGS) && |
switch (request) { |
(request != LINUX_PTRACE_SETREGS)) |
case LINUX_PTRACE_GETREGS: |
return EIO; |
break; |
|
case LINUX_PTRACE_SETREGS: |
/* Find the process we're supposed to be operating on. */ |
error = copyin((void *)SCARG(uap, data), linux_regs, |
if ((t = pfind(SCARG(uap, pid))) == NULL) |
sizeof(struct linux_reg)); |
return ESRCH; |
if (error) { |
|
goto out; |
/* |
} |
* You can't do what you want to the process if: |
break; |
* (1) It's not being traced at all, |
default: |
*/ |
error = EIO; |
if (!ISSET(t->p_slflag, PSL_TRACED)) |
goto out; |
return EPERM; |
} |
|
|
/* |
/* Find the process we are supposed to be operating on. */ |
* (2) it's being traced by procfs (which has |
mutex_enter(proc_lock); |
* different signal delivery semantics), |
if ((t = proc_find(SCARG(uap, pid))) == NULL) { |
*/ |
mutex_exit(proc_lock); |
if (ISSET(t->p_slflag, PSL_FSTRACE)) |
error = ESRCH; |
return EBUSY; |
goto out; |
|
} |
|
mutex_enter(t->p_lock); |
|
mutex_exit(proc_lock); |
|
|
/* |
/* |
* (3) it's not being traced by _you_, or |
* You cannot do what you want to the process if: |
|
* 1. It is not being traced at all, |
*/ |
*/ |
if (t->p_pptr != p) |
if (!ISSET(t->p_slflag, PSL_TRACED)) { |
return EBUSY; |
mutex_exit(t->p_lock); |
|
error = EPERM; |
|
goto out; |
|
} |
/* |
/* |
* (4) it's not currently stopped. |
* 2. It is being traced by procfs (which has different signal |
*/ |
* delivery semantics), |
if (t->p_stat != SSTOP || !t->p_waited) |
* 3. It is not being traced by _you_, or |
return EBUSY; |
* 4. It is not currently stopped. |
|
|
/* XXX NJWLWP |
|
* The entire ptrace interface needs work to be useful to |
|
* a process with multiple LWPs. For the moment, we'll |
|
* just kluge this and fail on others. |
|
*/ |
*/ |
|
if (ISSET(t->p_slflag, PSL_FSTRACE) || t->p_pptr != p || |
if (p->p_nlwps > 1) |
t->p_stat != SSTOP || !t->p_waited) { |
return (ENOSYS); |
mutex_exit(t->p_lock); |
|
error = EBUSY; |
|
goto out; |
|
} |
|
/* XXX: ptrace needs revamp for multi-threading support. */ |
|
if (t->p_nlwps > 1) { |
|
mutex_exit(t->p_lock); |
|
error = ENOSYS; |
|
goto out; |
|
} |
lt = LIST_FIRST(&t->p_lwps); |
lt = LIST_FIRST(&t->p_lwps); |
|
|
*retval = 0; |
*retval = 0; |
|
|
switch (request) { |
switch (request) { |
case LINUX_PTRACE_GETREGS: |
case LINUX_PTRACE_GETREGS: |
regs = malloc(sizeof(struct reg), M_TEMP, M_WAITOK); |
|
linux_regs = malloc(sizeof(struct linux_reg), |
|
M_TEMP, M_WAITOK); |
|
|
|
error = process_read_regs(lt, regs); |
error = process_read_regs(lt, regs); |
if (error != 0) |
mutex_exit(t->p_lock); |
goto out; |
if (error) { |
|
break; |
|
} |
memcpy(linux_regs->uregs, regs->r, 13 * sizeof(register_t)); |
memcpy(linux_regs->uregs, regs->r, 13 * sizeof(register_t)); |
linux_regs->uregs[LINUX_REG_SP] = regs->r_sp; |
linux_regs->uregs[LINUX_REG_SP] = regs->r_sp; |
linux_regs->uregs[LINUX_REG_LR] = regs->r_lr; |
linux_regs->uregs[LINUX_REG_LR] = regs->r_lr; |
Line 178 linux_sys_ptrace_arch(struct lwp *l, con |
|
Line 184 linux_sys_ptrace_arch(struct lwp *l, con |
|
|
|
error = copyout(linux_regs, (void *)SCARG(uap, data), |
error = copyout(linux_regs, (void *)SCARG(uap, data), |
sizeof(struct linux_reg)); |
sizeof(struct linux_reg)); |
goto out; |
break; |
|
|
case LINUX_PTRACE_SETREGS: |
|
regs = malloc(sizeof(struct reg), M_TEMP, M_WAITOK); |
|
linux_regs = malloc(sizeof(struct linux_reg), |
|
M_TEMP, M_WAITOK); |
|
|
|
error = copyin((void *)SCARG(uap, data), linux_regs, |
|
sizeof(struct linux_reg)); |
|
if (error != 0) |
|
goto out; |
|
|
|
|
case LINUX_PTRACE_SETREGS: |
memcpy(regs->r, linux_regs->uregs, 13 * sizeof(register_t)); |
memcpy(regs->r, linux_regs->uregs, 13 * sizeof(register_t)); |
regs->r_sp = linux_regs->uregs[LINUX_REG_SP]; |
regs->r_sp = linux_regs->uregs[LINUX_REG_SP]; |
regs->r_lr = linux_regs->uregs[LINUX_REG_LR]; |
regs->r_lr = linux_regs->uregs[LINUX_REG_LR]; |
regs->r_pc = linux_regs->uregs[LINUX_REG_PC]; |
regs->r_pc = linux_regs->uregs[LINUX_REG_PC]; |
regs->r_cpsr = linux_regs->uregs[LINUX_REG_CPSR]; |
regs->r_cpsr = linux_regs->uregs[LINUX_REG_CPSR]; |
|
|
error = process_write_regs(lt, regs); |
error = process_write_regs(lt, regs); |
goto out; |
/* FALLTHROUGH */ |
|
|
default: |
default: |
/* never reached */ |
mutex_exit(t->p_lock); |
break; |
|
} |
} |
|
out: |
return EIO; |
|
|
|
out: |
|
if (regs) |
if (regs) |
free(regs, M_TEMP); |
kmem_free(regs, sizeof(*regs)); |
if (fpregs) |
|
free(fpregs, M_TEMP); |
|
if (linux_regs) |
if (linux_regs) |
free(linux_regs, M_TEMP); |
kmem_free(linux_regs, sizeof(*linux_regs)); |
if (linux_fpregs) |
return error; |
free(linux_fpregs, M_TEMP); |
|
return (error); |
|
|
|
} |
} |