diff options
Diffstat (limited to 'arch/m32r/kernel/ptrace.c')
| -rw-r--r-- | arch/m32r/kernel/ptrace.c | 169 |
1 files changed, 40 insertions, 129 deletions
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 62a51429306..51f5e9aa490 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -19,7 +19,6 @@ #include <linux/mm.h> #include <linux/err.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/ptrace.h> #include <linux/user.h> @@ -30,7 +29,6 @@ #include <asm/io.h> #include <asm/uaccess.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/processor.h> #include <asm/mmu_context.h> @@ -78,7 +76,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, struct user * dummy = NULL; #endif - if ((off & 3) || (off < 0) || (off > sizeof(struct user) - 3)) + if ((off & 3) || off > sizeof(struct user) - 3) return -EIO; off >>= 2; @@ -140,8 +138,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, struct user * dummy = NULL; #endif - if ((off & 3) || off < 0 || - off > sizeof(struct user) - 3) + if ((off & 3) || off > sizeof(struct user) - 3) return -EIO; off >>= 2; @@ -476,7 +473,7 @@ unregister_debug_trap(struct task_struct *child, unsigned long addr, return 0; } - /* Recover orignal instruction code. */ + /* Recover original instruction code. */ *code = p->insn[i]; /* Shift debug trap entries. */ @@ -570,7 +567,7 @@ withdraw_debug_trap(struct pt_regs *regs) } } -static void +void init_debug_traps(struct task_struct *child) { struct debug_trap *p = &child->thread.debug_trap; @@ -582,6 +579,35 @@ init_debug_traps(struct task_struct *child) } } +void user_enable_single_step(struct task_struct *child) +{ + unsigned long next_pc; + unsigned long pc, insn; + + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + + /* Compute next pc. */ + pc = get_stack_long(child, PT_BPC); + + if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) + != sizeof(insn)) + return; + + compute_next_pc(insn, pc, &next_pc, child); + if (next_pc & 0x80000000) + return; + + if (embed_debug_trap(child, next_pc)) + return; + + invalidate_cache(); +} + +void user_disable_single_step(struct task_struct *child) +{ + unregister_all_debug_traps(child); + invalidate_cache(); +} /* * Called by kernel/ptrace.c when detaching.. @@ -593,10 +619,12 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -static int -do_ptrace(long request, struct task_struct *child, long addr, long data) +long +arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) { int ret; + unsigned long __user *datap = (unsigned long __user *) data; switch (request) { /* @@ -611,8 +639,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) * read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: - ret = ptrace_read_user(child, addr, - (unsigned long __user *)data); + ret = ptrace_read_user(child, addr, datap); break; /* @@ -632,92 +659,12 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) ret = ptrace_write_user(child, addr, data); break; - /* - * continue/restart and stop at next (return from) syscall - */ - case PTRACE_SYSCALL: - case PTRACE_CONT: - ret = -EIO; - if (!valid_signal(data)) - break; - 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); - ret = 0; - 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: { - ret = 0; - unregister_all_debug_traps(child); - invalidate_cache(); - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - } - - /* - * execute single instruction. - */ - case PTRACE_SINGLESTEP: { - unsigned long next_pc; - unsigned long pc, insn; - - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - - /* Compute next pc. */ - pc = get_stack_long(child, PT_BPC); - - if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) - != sizeof(insn)) - break; - - compute_next_pc(insn, pc, &next_pc, child); - if (next_pc & 0x80000000) - break; - - if (embed_debug_trap(child, next_pc)) - break; - - invalidate_cache(); - child->exit_code = data; - - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - break; - } - - /* - * detach a process that was attached. - */ - case PTRACE_DETACH: - ret = 0; - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: - ret = ptrace_getregs(child, (void __user *)data); + ret = ptrace_getregs(child, datap); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (void __user *)data); + ret = ptrace_setregs(child, datap); break; default: @@ -728,42 +675,6 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - if (ret == 0) - init_debug_traps(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - - return ret; -} - /* notification of system call entry/exit * - triggered by current->work.syscall_trace */ |
