From 190aa9f60f9575d1b7382cd1ee33e2589208c514 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 6 Feb 2008 22:08:18 -0800 Subject: [SPARC]: Remove PTRACE_SUN* handling. Supporting SunOS ptrace() is pretty pointless and these kinds of quirks keep us from being able to share more code with other platforms. Signed-off-by: David S. Miller --- include/asm-sparc/ptrace.h | 2 -- include/asm-sparc64/ptrace.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'include') diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index 714497099a42..a84345ba8bee 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h @@ -151,8 +151,6 @@ extern void show_regs(struct pt_regs *); #define SF_XXARG 0x5c /* Stuff for the ptrace system call */ -#define PTRACE_SUNATTACH 10 -#define PTRACE_SUNDETACH 11 #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 7eba90c6c753..2ba989b3056e 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -261,8 +261,6 @@ extern void show_regs(struct pt_regs *); #define SF_XXARG 0x5c /* Stuff for the ptrace system call */ -#define PTRACE_SUNATTACH 10 -#define PTRACE_SUNDETACH 11 #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 -- cgit v1.2.3 From 9775369ec06bad8edb2fbd8c77316f49b439c225 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 7 Feb 2008 03:00:17 -0800 Subject: [SPARC]: Move over to arch_ptrace(). Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.S | 17 -- arch/sparc/kernel/ptrace.c | 462 ++++++------------------------------------- arch/sparc64/kernel/entry.S | 4 - arch/sparc64/kernel/ptrace.c | 389 ++++++++++-------------------------- include/asm-sparc/ptrace.h | 5 - include/asm-sparc64/ptrace.h | 16 -- 6 files changed, 172 insertions(+), 721 deletions(-) (limited to 'include') diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 88d2cefd01be..c2eed8f71516 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1224,23 +1224,6 @@ sys_nis_syscall: call c_sys_nis_syscall mov %l5, %o7 - .align 4 - .globl sys_ptrace -sys_ptrace: - call do_ptrace - add %sp, STACKFRAME_SZ, %o0 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - RESTORE_ALL - .align 4 .globl sys_execve sys_execve: diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 29fa6e5cb450..1c0d5363f720 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -26,215 +26,6 @@ #include #include -#define MAGIC_CONSTANT 0x80000000 - - -/* Returning from ptrace is a bit tricky because the syscall return - * low level code assumes any value returned which is negative and - * is a valid errno will mean setting the condition codes to indicate - * an error return. This doesn't work, so we have this hook. - */ -static inline void pt_error_return(struct pt_regs *regs, unsigned long error) -{ - regs->u_regs[UREG_I0] = error; - regs->psr |= PSR_C; - regs->pc = regs->npc; - regs->npc += 4; -} - -static inline void pt_succ_return(struct pt_regs *regs, unsigned long value) -{ - regs->u_regs[UREG_I0] = value; - regs->psr &= ~PSR_C; - regs->pc = regs->npc; - regs->npc += 4; -} - -static void -pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr) -{ - if (put_user(value, addr)) { - pt_error_return(regs, EFAULT); - return; - } - regs->u_regs[UREG_I0] = 0; - regs->psr &= ~PSR_C; - regs->pc = regs->npc; - regs->npc += 4; -} - -static void -pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr) -{ - if (current->personality == PER_SUNOS) - pt_succ_return (regs, val); - else - pt_succ_return_linux (regs, val, addr); -} - -/* Fuck me gently with a chainsaw... */ -static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset, - struct task_struct *tsk, long __user *addr) -{ - struct pt_regs *cregs = tsk->thread.kregs; - struct thread_info *t = task_thread_info(tsk); - int v; - - if(offset >= 1024) - offset -= 1024; /* whee... */ - if(offset & ((sizeof(unsigned long) - 1))) { - pt_error_return(regs, EIO); - return; - } - if(offset >= 16 && offset < 784) { - offset -= 16; offset >>= 2; - pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr); - return; - } - if(offset >= 784 && offset < 832) { - offset -= 784; offset >>= 2; - pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr); - return; - } - switch(offset) { - case 0: - v = t->ksp; - break; - case 4: - v = t->kpc; - break; - case 8: - v = t->kpsr; - break; - case 12: - v = t->uwinmask; - break; - case 832: - v = t->w_saved; - break; - case 896: - v = cregs->u_regs[UREG_I0]; - break; - case 900: - v = cregs->u_regs[UREG_I1]; - break; - case 904: - v = cregs->u_regs[UREG_I2]; - break; - case 908: - v = cregs->u_regs[UREG_I3]; - break; - case 912: - v = cregs->u_regs[UREG_I4]; - break; - case 916: - v = cregs->u_regs[UREG_I5]; - break; - case 920: - v = cregs->u_regs[UREG_I6]; - break; - case 924: - if(tsk->thread.flags & MAGIC_CONSTANT) - v = cregs->u_regs[UREG_G1]; - else - v = 0; - break; - case 940: - v = cregs->u_regs[UREG_I0]; - break; - case 944: - v = cregs->u_regs[UREG_I1]; - break; - - case 948: - /* Isn't binary compatibility _fun_??? */ - if(cregs->psr & PSR_C) - v = cregs->u_regs[UREG_I0] << 24; - else - v = 0; - break; - - /* Rest of them are completely unsupported. */ - default: - printk("%s [%d]: Wants to read user offset %ld\n", - current->comm, task_pid_nr(current), offset); - pt_error_return(regs, EIO); - return; - } - if (current->personality == PER_SUNOS) - pt_succ_return (regs, v); - else - pt_succ_return_linux (regs, v, addr); - return; -} - -static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset, - struct task_struct *tsk) -{ - struct pt_regs *cregs = tsk->thread.kregs; - struct thread_info *t = task_thread_info(tsk); - unsigned long value = regs->u_regs[UREG_I3]; - - if(offset >= 1024) - offset -= 1024; /* whee... */ - if(offset & ((sizeof(unsigned long) - 1))) - goto failure; - if(offset >= 16 && offset < 784) { - offset -= 16; offset >>= 2; - *(((unsigned long *)(&t->reg_window[0]))+offset) = value; - goto success; - } - if(offset >= 784 && offset < 832) { - offset -= 784; offset >>= 2; - *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value; - goto success; - } - switch(offset) { - case 896: - cregs->u_regs[UREG_I0] = value; - break; - case 900: - cregs->u_regs[UREG_I1] = value; - break; - case 904: - cregs->u_regs[UREG_I2] = value; - break; - case 908: - cregs->u_regs[UREG_I3] = value; - break; - case 912: - cregs->u_regs[UREG_I4] = value; - break; - case 916: - cregs->u_regs[UREG_I5] = value; - break; - case 920: - cregs->u_regs[UREG_I6] = value; - break; - case 924: - cregs->u_regs[UREG_I7] = value; - break; - case 940: - cregs->u_regs[UREG_I0] = value; - break; - case 944: - cregs->u_regs[UREG_I1] = value; - break; - - /* Rest of them are completely unsupported or "no-touch". */ - default: - printk("%s [%d]: Wants to write user offset %ld\n", - current->comm, task_pid_nr(current), offset); - goto failure; - } -success: - pt_succ_return(regs, 0); - return; -failure: - pt_error_return(regs, EIO); - return; -} - /* #define ALLOW_INIT_TRACING */ /* @@ -528,113 +319,42 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_sparc32_view; } -asmlinkage void do_ptrace(struct pt_regs *regs) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - unsigned long request = regs->u_regs[UREG_I0]; - unsigned long pid = regs->u_regs[UREG_I1]; - unsigned long addr = regs->u_regs[UREG_I2]; - unsigned long data = regs->u_regs[UREG_I3]; - unsigned long addr2 = regs->u_regs[UREG_I4]; - struct task_struct *child; - int ret; - - lock_kernel(); - - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (ret < 0) - pt_error_return(regs, -ret); - else - pt_succ_return(regs, 0); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - pt_error_return(regs, -ret); - goto out; - } - - if (request == PTRACE_ATTACH) { - if (ptrace_attach(child)) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) { - pt_error_return(regs, -ret); - goto out_tsk; - } + unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; + int i, ret; switch(request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp; - - if (access_process_vm(child, addr, - &tmp, sizeof(tmp), 0) == sizeof(tmp)) - pt_os_succ_return(regs, tmp, (long __user *)data); - else - pt_error_return(regs, EIO); - goto out_tsk; - } - - case PTRACE_PEEKUSR: - read_sunos_user(regs, addr, child, (long __user *) data); - goto out_tsk; - - case PTRACE_POKEUSR: - write_sunos_user(regs, addr, child); - goto out_tsk; - - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: { - if (access_process_vm(child, addr, - &data, sizeof(data), 1) == sizeof(data)) - pt_succ_return(regs, 0); - else - pt_error_return(regs, EIO); - goto out_tsk; - } - case PTRACE_GETREGS: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; struct pt_regs *cregs = child->thread.kregs; - int rval; - if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) { - rval = -EFAULT; - pt_error_return(regs, -rval); - goto out_tsk; - } + ret = -EFAULT; + if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) + break; + __put_user(cregs->psr, (&pregs->psr)); __put_user(cregs->pc, (&pregs->pc)); __put_user(cregs->npc, (&pregs->npc)); __put_user(cregs->y, (&pregs->y)); - for(rval = 1; rval < 16; rval++) - __put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1])); - pt_succ_return(regs, 0); - goto out_tsk; + for (i = 1; i < 16; i++) + __put_user(cregs->u_regs[i], &pregs->u_regs[i - 1]); + ret = 0; + break; } case PTRACE_SETREGS: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; struct pt_regs *cregs = child->thread.kregs; unsigned long psr, pc, npc, y; - int i; /* Must be careful, tracing process can only set certain * bits in the psr. */ - if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + ret = -EFAULT; + if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) + break; + __get_user(psr, (&pregs->psr)); __get_user(pc, (&pregs->pc)); __get_user(npc, (&pregs->npc)); @@ -647,10 +367,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs) cregs->npc =npc; } cregs->y = y; - for(i = 1; i < 16; i++) - __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])); - pt_succ_return(regs, 0); - goto out_tsk; + for (i = 1; i < 16; i++) + __get_user(cregs->u_regs[i], &pregs->u_regs[i-1]); + ret = 0; + break; } case PTRACE_GETFPREGS: { @@ -666,26 +386,25 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } fpq[16]; }; struct fps __user *fps = (struct fps __user *) addr; - int i; - if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) { - i = -EFAULT; - pt_error_return(regs, -i); - goto out_tsk; - } - for(i = 0; i < 32; i++) - __put_user(child->thread.float_regs[i], (&fps->regs[i])); + ret = -EFAULT; + if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) + break; + + for (i = 0; i < 32; i++) + __put_user(child->thread.float_regs[i], &fps->regs[i]); __put_user(child->thread.fsr, (&fps->fsr)); __put_user(child->thread.fpqdepth, (&fps->fpqd)); __put_user(0, (&fps->flags)); __put_user(0, (&fps->extra)); - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { __put_user(child->thread.fpqueue[i].insn_addr, (&fps->fpq[i].insnaddr)); - __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); + __put_user(child->thread.fpqueue[i].insn, + &fps->fpq[i].insn); } - pt_succ_return(regs, 0); - goto out_tsk; + ret = 0; + break; } case PTRACE_SETFPREGS: { @@ -701,107 +420,53 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } fpq[16]; }; struct fps __user *fps = (struct fps __user *) addr; - int i; - if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) { - i = -EFAULT; - pt_error_return(regs, -i); - goto out_tsk; - } - copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long))); + ret = -EFAULT; + if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) + break; + + copy_from_user(&child->thread.float_regs[0], &fps->regs[0], + (32 * sizeof(unsigned long))); __get_user(child->thread.fsr, (&fps->fsr)); __get_user(child->thread.fpqdepth, (&fps->fpqd)); - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { __get_user(child->thread.fpqueue[i].insn_addr, (&fps->fpq[i].insnaddr)); - __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); + __get_user(child->thread.fpqueue[i].insn, + &fps->fpq[i].insn); } - pt_succ_return(regs, 0); - goto out_tsk; + ret = 0; + break; } case PTRACE_READTEXT: - case PTRACE_READDATA: { - int res = ptrace_readdata(child, addr, - (void __user *) addr2, data); - - if (res == data) { - pt_succ_return(regs, 0); - goto out_tsk; - } - /* Partial read is an IO failure */ - if (res >= 0) - res = -EIO; - pt_error_return(regs, -res); - goto out_tsk; - } + case PTRACE_READDATA: + ret = ptrace_readdata(child, addr, + (void __user *) addr2, data); + + if (ret == data) + ret = 0; + else if (ret >= 0) + ret = -EIO; + break; case PTRACE_WRITETEXT: - case PTRACE_WRITEDATA: { - int res = ptrace_writedata(child, (void __user *) addr2, - addr, data); - - if (res == data) { - pt_succ_return(regs, 0); - goto out_tsk; - } - /* Partial write is an IO failure */ - if (res >= 0) - res = -EIO; - pt_error_return(regs, -res); - goto out_tsk; - } - - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ - addr = 1; - - case PTRACE_CONT: { /* restart after signal. */ - if (!valid_signal(data)) { - pt_error_return(regs, EIO); - goto out_tsk; - } - - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - child->exit_code = data; - wake_up_process(child); - pt_succ_return(regs, 0); - goto out_tsk; - } + case PTRACE_WRITEDATA: + ret = ptrace_writedata(child, (void __user *) addr2, + addr, data); + + if (ret == data) + ret = 0; + else if (ret >= 0) + ret = -EIO; + break; -/* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: { - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ - pt_succ_return(regs, 0); - goto out_tsk; - } - wake_up_process(child); - child->exit_code = SIGKILL; - pt_succ_return(regs, 0); - goto out_tsk; + default: + ret = ptrace_request(child, request, addr, data); + break; } - default: { - int err = ptrace_request(child, request, addr, data); - if (err) - pt_error_return(regs, -err); - else - pt_succ_return(regs, 0); - goto out_tsk; - } - } -out_tsk: - if (child) - put_task_struct(child); -out: - unlock_kernel(); + return ret; } asmlinkage void syscall_trace(void) @@ -810,7 +475,6 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->thread.flags ^= MAGIC_CONSTANT; ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); /* diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index ea257e828364..6be4d2d2904e 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1477,10 +1477,6 @@ sys32_rt_sigreturn: add %o7, 1f-.-4, %o7 nop #endif -sys_ptrace: add %sp, PTREGS_OFF, %o0 - call do_ptrace - add %o7, 1f-.-4, %o7 - nop .align 32 1: ldx [%curptr + TI_FLAGS], %l5 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index e881dbbd2c49..c831d426c4ac 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -36,56 +36,6 @@ #include #include -/* Returning from ptrace is a bit tricky because the syscall return - * low level code assumes any value returned which is negative and - * is a valid errno will mean setting the condition codes to indicate - * an error return. This doesn't work, so we have this hook. - */ -static inline void pt_error_return(struct pt_regs *regs, unsigned long error) -{ - regs->u_regs[UREG_I0] = error; - regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY); - regs->tpc = regs->tnpc; - regs->tnpc += 4; -} - -static inline void pt_succ_return(struct pt_regs *regs, unsigned long value) -{ - regs->u_regs[UREG_I0] = value; - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY); - regs->tpc = regs->tnpc; - regs->tnpc += 4; -} - -static inline void -pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr) -{ - if (test_thread_flag(TIF_32BIT)) { - if (put_user(value, (unsigned int __user *) addr)) { - pt_error_return(regs, EFAULT); - return; - } - } else { - if (put_user(value, (long __user *) addr)) { - pt_error_return(regs, EFAULT); - return; - } - } - regs->u_regs[UREG_I0] = 0; - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY); - regs->tpc = regs->tnpc; - regs->tnpc += 4; -} - -static void -pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr) -{ - if (current->personality == PER_SUNOS) - pt_succ_return (regs, val); - else - pt_succ_return_linux (regs, val, addr); -} - /* #define ALLOW_INIT_TRACING */ /* @@ -734,171 +684,113 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_sparc64_view; } -asmlinkage void do_ptrace(struct pt_regs *regs) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - int request = regs->u_regs[UREG_I0]; - pid_t pid = regs->u_regs[UREG_I1]; - unsigned long addr = regs->u_regs[UREG_I2]; - unsigned long data = regs->u_regs[UREG_I3]; - unsigned long addr2 = regs->u_regs[UREG_I4]; - struct task_struct *child; - int ret; + long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; + int i, ret; - if (test_thread_flag(TIF_32BIT)) { - addr &= 0xffffffffUL; - data &= 0xffffffffUL; +#if 1 + printk(KERN_INFO + "arch_ptrace: request[%ld] addr[%lx] data[%lx] addr2[%lx]\n", + request, addr, data, addr2); +#endif + if (test_thread_flag(TIF_32BIT)) addr2 &= 0xffffffffUL; - } - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (ret < 0) - pt_error_return(regs, -ret); - else - pt_succ_return(regs, 0); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - pt_error_return(regs, -ret); - goto out; - } - - if (request == PTRACE_ATTACH) { - if (ptrace_attach(child)) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) { - pt_error_return(regs, -ret); - goto out_tsk; - } - - if (!(test_thread_flag(TIF_32BIT)) && - ((request == PTRACE_READDATA64) || - (request == PTRACE_WRITEDATA64) || - (request == PTRACE_READTEXT64) || - (request == PTRACE_WRITETEXT64) || - (request == PTRACE_PEEKTEXT64) || - (request == PTRACE_POKETEXT64) || - (request == PTRACE_PEEKDATA64) || - (request == PTRACE_POKEDATA64))) { - addr = regs->u_regs[UREG_G2]; - addr2 = regs->u_regs[UREG_G3]; - request -= 30; /* wheee... */ - } switch(request) { case PTRACE_PEEKUSR: - if (addr != 0) - pt_error_return(regs, EIO); - else - pt_succ_return(regs, 0); - goto out_tsk; + ret = (addr != 0) ? -EIO : 0; + break; case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp64; unsigned int tmp32; - int res, copied; + int copied; - res = -EIO; + ret = -EIO; if (test_thread_flag(TIF_32BIT)) { copied = access_process_vm(child, addr, &tmp32, sizeof(tmp32), 0); - tmp64 = (unsigned long) tmp32; if (copied == sizeof(tmp32)) - res = 0; + ret = put_user(tmp32, + (unsigned int __user *) data); } else { copied = access_process_vm(child, addr, &tmp64, sizeof(tmp64), 0); if (copied == sizeof(tmp64)) - res = 0; + ret = put_user(tmp64, + (unsigned long __user *) data); } - if (res < 0) - pt_error_return(regs, -res); - else - pt_os_succ_return(regs, tmp64, (void __user *) data); - goto out_tsk; + break; } case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: { unsigned long tmp64; unsigned int tmp32; - int copied, res = -EIO; + int copied; + ret = -EIO; if (test_thread_flag(TIF_32BIT)) { tmp32 = data; copied = access_process_vm(child, addr, &tmp32, sizeof(tmp32), 1); if (copied == sizeof(tmp32)) - res = 0; + ret = 0; } else { tmp64 = data; copied = access_process_vm(child, addr, &tmp64, sizeof(tmp64), 1); if (copied == sizeof(tmp64)) - res = 0; + ret = 0; } - if (res < 0) - pt_error_return(regs, -res); - else - pt_succ_return(regs, res); - goto out_tsk; + break; } case PTRACE_GETREGS: { struct pt_regs32 __user *pregs = (struct pt_regs32 __user *) addr; struct pt_regs *cregs = task_pt_regs(child); - int rval; + ret = -EFAULT; if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || __put_user(cregs->tpc, (&pregs->pc)) || __put_user(cregs->tnpc, (&pregs->npc)) || - __put_user(cregs->y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; + __put_user(cregs->y, (&pregs->y))) + break; + for (i = 1; i < 16; i++) { + if (__put_user(cregs->u_regs[i], + (&pregs->u_regs[i - 1]))) + break; } - for (rval = 1; rval < 16; rval++) - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; + if (i == 16) + ret = 0; + break; } case PTRACE_GETREGS64: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; struct pt_regs *cregs = task_pt_regs(child); unsigned long tpc = cregs->tpc; - int rval; if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) tpc &= 0xffffffff; + + ret = -EFAULT; if (__put_user(cregs->tstate, (&pregs->tstate)) || __put_user(tpc, (&pregs->tpc)) || __put_user(cregs->tnpc, (&pregs->tnpc)) || - __put_user(cregs->y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; + __put_user(cregs->y, (&pregs->y))) + break; + for (i = 1; i < 16; i++) { + if (__put_user(cregs->u_regs[i], + (&pregs->u_regs[i - 1]))) + break; } - for (rval = 1; rval < 16; rval++) - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; + if (i == 16) + ret = 0; + break; } case PTRACE_SETREGS: { @@ -906,18 +798,16 @@ asmlinkage void do_ptrace(struct pt_regs *regs) (struct pt_regs32 __user *) addr; struct pt_regs *cregs = task_pt_regs(child); unsigned int psr, pc, npc, y; - int i; /* Must be careful, tracing process can only set certain * bits in the psr. */ + ret = -EFAULT; if (__get_user(psr, (&pregs->psr)) || __get_user(pc, (&pregs->pc)) || __get_user(npc, (&pregs->npc)) || - __get_user(y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + __get_user(y, (&pregs->y))) + break; cregs->tstate &= ~(TSTATE_ICC); cregs->tstate |= psr_to_tstate_icc(psr); if (!((pc | npc) & 3)) { @@ -926,31 +816,28 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } cregs->y = y; for (i = 1; i < 16; i++) { - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) + break; } - pt_succ_return(regs, 0); - goto out_tsk; + if (i == 16) + ret = 0; + break; } case PTRACE_SETREGS64: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; struct pt_regs *cregs = task_pt_regs(child); unsigned long tstate, tpc, tnpc, y; - int i; /* Must be careful, tracing process can only set certain * bits in the psr. */ + ret = -EFAULT; if (__get_user(tstate, (&pregs->tstate)) || __get_user(tpc, (&pregs->tpc)) || __get_user(tnpc, (&pregs->tnpc)) || - __get_user(y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + __get_user(y, (&pregs->y))) + break; if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { tpc &= 0xffffffff; tnpc &= 0xffffffff; @@ -964,13 +851,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } cregs->y = y; for (i = 1; i < 16; i++) { - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) + break; } - pt_succ_return(regs, 0); - goto out_tsk; + if (i == 16) + ret = 0; + break; } case PTRACE_GETFPREGS: { @@ -988,18 +874,18 @@ asmlinkage void do_ptrace(struct pt_regs *regs) struct fps __user *fps = (struct fps __user *) addr; unsigned long *fpregs = task_thread_info(child)->fpregs; + ret = -EFAULT; if (copy_to_user(&fps->regs[0], fpregs, (32 * sizeof(unsigned int))) || __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || __put_user(0, (&fps->fpqd)) || __put_user(0, (&fps->flags)) || __put_user(0, (&fps->extra)) || - clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; + clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) + break; + + ret = 0; + break; } case PTRACE_GETFPREGS64: { @@ -1010,14 +896,14 @@ asmlinkage void do_ptrace(struct pt_regs *regs) struct fps __user *fps = (struct fps __user *) addr; unsigned long *fpregs = task_thread_info(child)->fpregs; + ret = -EFAULT; if (copy_to_user(&fps->regs[0], fpregs, (64 * sizeof(unsigned int))) || - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; + __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) + break; + + ret = 0; + break; } case PTRACE_SETFPREGS: { @@ -1036,19 +922,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs) unsigned long *fpregs = task_thread_info(child)->fpregs; unsigned fsr; + ret = -EFAULT; if (copy_from_user(fpregs, &fps->regs[0], (32 * sizeof(unsigned int))) || - __get_user(fsr, (&fps->fsr))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + __get_user(fsr, (&fps->fsr))) + break; + task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; task_thread_info(child)->xfsr[0] |= fsr; if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) task_thread_info(child)->gsr[0] = 0; task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); - pt_succ_return(regs, 0); - goto out_tsk; + ret = 0; + break; } case PTRACE_SETFPREGS64: { @@ -1059,113 +945,56 @@ asmlinkage void do_ptrace(struct pt_regs *regs) struct fps __user *fps = (struct fps __user *) addr; unsigned long *fpregs = task_thread_info(child)->fpregs; + ret = -EFAULT; if (copy_from_user(fpregs, &fps->regs[0], (64 * sizeof(unsigned int))) || - __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } + __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) + break; + if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) task_thread_info(child)->gsr[0] = 0; - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); - pt_succ_return(regs, 0); - goto out_tsk; + task_thread_info(child)->fpsaved[0] |= + (FPRS_FEF | FPRS_DL | FPRS_DU); + ret = 0; + break; } case PTRACE_READTEXT: - case PTRACE_READDATA: { - int res = ptrace_readdata(child, addr, - (char __user *)addr2, data); - if (res == data) { - pt_succ_return(regs, 0); - goto out_tsk; - } - if (res >= 0) - res = -EIO; - pt_error_return(regs, -res); - goto out_tsk; - } + case PTRACE_READDATA: + ret = ptrace_readdata(child, addr, + (char __user *)addr2, data); + if (ret == data) + ret = 0; + else if (ret >= 0) + ret = -EIO; + break; case PTRACE_WRITETEXT: - case PTRACE_WRITEDATA: { - int res = ptrace_writedata(child, (char __user *) addr2, - addr, data); - if (res == data) { - pt_succ_return(regs, 0); - goto out_tsk; - } - if (res >= 0) - res = -EIO; - pt_error_return(regs, -res); - goto out_tsk; - } - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ - addr = 1; - - case PTRACE_CONT: { /* restart after signal. */ - if (!valid_signal(data)) { - pt_error_return(regs, EIO); - goto out_tsk; - } - - if (request == PTRACE_SYSCALL) { - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } else { - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } - - child->exit_code = data; - wake_up_process(child); - pt_succ_return(regs, 0); - goto out_tsk; - } - -/* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: { - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ - pt_succ_return(regs, 0); - goto out_tsk; - } - child->exit_code = SIGKILL; - wake_up_process(child); - pt_succ_return(regs, 0); - goto out_tsk; - } + case PTRACE_WRITEDATA: + ret = ptrace_writedata(child, (char __user *) addr2, + addr, data); + if (ret == data) + ret = 0; + else if (ret >= 0) + ret = -EIO; + break; case PTRACE_GETEVENTMSG: { - int err; - if (test_thread_flag(TIF_32BIT)) - err = put_user(child->ptrace_message, + ret = put_user(child->ptrace_message, (unsigned int __user *) data); else - err = put_user(child->ptrace_message, + ret = put_user(child->ptrace_message, (unsigned long __user *) data); - if (err) - pt_error_return(regs, -err); - else - pt_succ_return(regs, 0); break; } - default: { - int err = ptrace_request(child, request, addr, data); - if (err) - pt_error_return(regs, -err); - else - pt_succ_return(regs, 0); - goto out_tsk; - } + default: + ret = ptrace_request(child, request, addr, data); + break; } -out_tsk: - if (child) - put_task_struct(child); -out: - unlock_kernel(); + + return ret; } asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p) diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index a84345ba8bee..8201a7b29d49 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h @@ -61,8 +61,6 @@ struct sparc_stackf { #ifdef __KERNEL__ -#define __ARCH_SYS_PTRACE 1 - #define user_mode(regs) (!((regs)->psr & PSR_PS)) #define instruction_pointer(regs) ((regs)->pc) unsigned long profile_pc(struct pt_regs *); @@ -162,7 +160,4 @@ extern void show_regs(struct pt_regs *); #define PTRACE_GETFPAREGS 20 #define PTRACE_SETFPAREGS 21 -#define PTRACE_GETUCODE 29 /* stupid bsd-ism */ - - #endif /* !(_SPARC_PTRACE_H) */ diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 2ba989b3056e..734a767f0a4e 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -95,8 +95,6 @@ struct sparc_trapf { #ifdef __KERNEL__ -#define __ARCH_SYS_PTRACE 1 - #define force_successful_syscall_return() \ do { current_thread_info()->syscall_noerror = 1; \ } while (0) @@ -282,18 +280,4 @@ extern void show_regs(struct pt_regs *); #define PTRACE_GETFPREGS64 25 #define PTRACE_SETFPREGS64 26 -#define PTRACE_GETUCODE 29 /* stupid bsd-ism */ - -/* These are for 32-bit processes debugging 64-bit ones. - * Here addr and addr2 are passed in %g2 and %g3 respectively. - */ -#define PTRACE_PEEKTEXT64 (30 + PTRACE_PEEKTEXT) -#define PTRACE_POKETEXT64 (30 + PTRACE_POKETEXT) -#define PTRACE_PEEKDATA64 (30 + PTRACE_PEEKDATA) -#define PTRACE_POKEDATA64 (30 + PTRACE_POKEDATA) -#define PTRACE_READDATA64 (30 + PTRACE_READDATA) -#define PTRACE_WRITEDATA64 (30 + PTRACE_WRITEDATA) -#define PTRACE_READTEXT64 (30 + PTRACE_READTEXT) -#define PTRACE_WRITETEXT64 (30 + PTRACE_WRITETEXT) - #endif /* !(_SPARC64_PTRACE_H) */ -- cgit v1.2.3 From 3389742f3c346d9ef5fb46e7baa04972bdd6d151 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 7 Feb 2008 04:19:34 -0800 Subject: [SPARC64]: Use regsets for ELF core dumping. Signed-off-by: David S. Miller --- arch/sparc64/kernel/binfmt_elf32.c | 31 ++++--------------------------- include/asm-sparc64/elf.h | 30 +++++------------------------- 2 files changed, 9 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c index 1587a29a4b0e..d141300e76b7 100644 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ b/arch/sparc64/kernel/binfmt_elf32.c @@ -1,7 +1,7 @@ /* * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra. * - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@davemloft.net) + * Copyright (C) 1995, 1996, 1997, 1998, 2008 David S. Miller (davem@davemloft.net) * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) */ @@ -9,13 +9,6 @@ #define ELF_CLASS ELFCLASS32 #define ELF_DATA ELFDATA2MSB; -/* For the most part we present code dumps in the format - * Solaris does. - */ -typedef unsigned int elf_greg_t; -#define ELF_NGREG 38 -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - /* Format is: * G0 --> G7 * O0 --> O7 @@ -23,25 +16,9 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; * I0 --> I7 * PSR, PC, nPC, Y, WIM, TBR */ -#include -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ -do { unsigned int *dest = &(__elf_regs[0]); \ - struct pt_regs *src = (__pt_regs); \ - unsigned int __user *sp; \ - int i; \ - for(i = 0; i < 16; i++) \ - dest[i] = (unsigned int) src->u_regs[i];\ - /* Don't try this at home kids... */ \ - sp = (unsigned int __user *) (src->u_regs[14] & \ - 0x00000000fffffffc); \ - for(i = 0; i < 16; i++) \ - __get_user(dest[i+16], &sp[i]); \ - dest[32] = tstate_to_psr(src->tstate); \ - dest[33] = (unsigned int) src->tpc; \ - dest[34] = (unsigned int) src->tnpc; \ - dest[35] = src->y; \ - dest[36] = dest[37] = 0; /* XXX */ \ -} while(0); +typedef unsigned int elf_greg_t; +#define ELF_NGREG 38 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct { union { diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h index 8653e8665009..217d768cf7dd 100644 --- a/include/asm-sparc64/elf.h +++ b/include/asm-sparc64/elf.h @@ -72,6 +72,8 @@ #define HWCAP_SPARC_BLKINIT 64 #define HWCAP_SPARC_N2 128 +#define CORE_DUMP_USE_REGSET + /* * These are used to set parameters in the core dumps. */ @@ -80,10 +82,6 @@ #define ELF_CLASS ELFCLASS64 #define ELF_DATA ELFDATA2MSB -typedef unsigned long elf_greg_t; - -#define ELF_NGREG 36 -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; /* Format of 64-bit elf_gregset_t is: * G0 --> G7 * O0 --> O7 @@ -94,24 +92,9 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; * TNPC * Y */ -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ -do { unsigned long *dest = &(__elf_regs[0]); \ - struct pt_regs *src = (__pt_regs); \ - unsigned long __user *sp; \ - int i; \ - for(i = 0; i < 16; i++) \ - dest[i] = src->u_regs[i]; \ - /* Don't try this at home kids... */ \ - sp = (unsigned long __user *) \ - ((src->u_regs[14] + STACK_BIAS) \ - & 0xfffffffffffffff8UL); \ - for(i = 0; i < 16; i++) \ - __get_user(dest[i+16], &sp[i]); \ - dest[32] = src->tstate; \ - dest[33] = src->tpc; \ - dest[34] = src->tnpc; \ - dest[35] = src->y; \ -} while (0); +typedef unsigned long elf_greg_t; +#define ELF_NGREG 36 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct { unsigned long pr_regs[32]; @@ -121,9 +104,6 @@ typedef struct { } elf_fpregset_t; #endif -#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), task_pt_regs(__tsk)); 1; }) - /* * This is used to ensure we don't load something for the wrong architecture. */ -- cgit v1.2.3 From 5a4924d7be5df430132e109d3d2f26be610b4707 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 7 Feb 2008 04:36:02 -0800 Subject: [SPARC32]: Use regsets for ELF core dumping. Signed-off-by: David S. Miller --- include/asm-sparc/elf.h | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h index aaf6ef40ee2f..2f8ff3fa0957 100644 --- a/include/asm-sparc/elf.h +++ b/include/asm-sparc/elf.h @@ -65,8 +65,14 @@ #define HWCAP_SPARC_V9 16 #define HWCAP_SPARC_ULTRA3 32 -/* For the most part we present code dumps in the format - * Solaris does. +#define CORE_DUMP_USE_REGSET + +/* Format is: + * G0 --> G7 + * O0 --> O7 + * L0 --> L7 + * I0 --> I7 + * PSR, PC, nPC, Y, WIM, TBR */ typedef unsigned long elf_greg_t; #define ELF_NGREG 38 @@ -87,34 +93,6 @@ typedef struct { #ifdef __KERNEL__ #include -#include - -/* Format is: - * G0 --> G7 - * O0 --> O7 - * L0 --> L7 - * I0 --> I7 - * PSR, PC, nPC, Y, WIM, TBR - */ -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ -do { unsigned long *dest = &(__elf_regs[0]); \ - struct pt_regs *src = (__pt_regs); \ - unsigned long __user *sp; \ - memcpy(&dest[0], &src->u_regs[0], \ - sizeof(unsigned long) * 16); \ - /* Don't try this at home kids... */ \ - sp = (unsigned long __user *) src->u_regs[14]; \ - copy_from_user(&dest[16], sp, \ - sizeof(unsigned long) * 16); \ - dest[32] = src->psr; \ - dest[33] = src->pc; \ - dest[34] = src->npc; \ - dest[35] = src->y; \ - dest[36] = dest[37] = 0; /* XXX */ \ -} while(0); /* Janitors: Don't touch this semicolon. */ - -#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; }) /* * This is used to ensure we don't load something for the wrong architecture. -- cgit v1.2.3