[PATCH 4d] utrace: avr32 ptrace compatibility From: Haavard Skinnemoen Rip out most of the ptrace code for AVR32 and replace it with the much nicer utrace stuff. It builds in all possible combinations of CONFIG_UTRACE and CONFIG_PTRACE, and it seems to work as far as I've tested it with strace and some simple debugging with gdb. Signed-off-by: Haavard Skinnemoen Signed-off-by: Roland McGrath --- arch/avr32/kernel/ptrace.c | 107 +++++++------------------------------------- 1 files changed, 18 insertions(+), 89 deletions(-) --- linux-2.6/arch/avr32/kernel/ptrace.c +++ linux-2.6/arch/avr32/kernel/ptrace.c @@ -78,115 +78,44 @@ const struct utrace_regset_view *utrace_ } #endif /* CONFIG_UTRACE */ +#ifdef CONFIG_PTRACE -#if 0 -long arch_ptrace(struct task_struct *child, long request, long addr, long data) +static const struct ptrace_layout_segment avr32_uarea[] = { + { 0, ELF_NGREG * sizeof(long), 0, 0 }, + { 0, 0, -1, 0 }, +}; + +int arch_ptrace(long *request, struct task_struct *child, + struct utrace_attached_engine *engine, + unsigned long addr, unsigned long data, long *val) { - unsigned long tmp; - int ret; - pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n", - request, child->pid, addr, data); + *request, child->pid, addr, data); pr_debug("ptrace: Enabling monitor mode...\n"); __mtdr(DBGREG_DC, __mfdr(DBGREG_DC) | DC_MM | DC_DBE); - switch (request) { - /* Read the word at location addr in the child process */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - if (ret == sizeof(tmp)) - ret = put_user(tmp, (unsigned long __user *)data); - else - ret = -EIO; - break; - + switch (*request) { case PTRACE_PEEKUSR: - ret = ptrace_read_user(child, addr, - (unsigned long __user *)data); - break; - - /* Write the word in data at location addr */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = access_process_vm(child, addr, &data, sizeof(data), 1); - if (ret == sizeof(data)) - ret = 0; - else - ret = -EIO; - break; + return ptrace_peekusr(child, engine, avr32_uarea, addr, data); case PTRACE_POKEUSR: - ret = ptrace_write_user(child, addr, data); - break; - - /* continue and stop at next (return from) syscall */ - case PTRACE_SYSCALL: - /* restart after signal */ - 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; - /* XXX: Are we sure no breakpoints are active here? */ - 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; - if (child->exit_state == EXIT_ZOMBIE) - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - - /* - * execute single instruction. - */ - case PTRACE_SINGLESTEP: - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - ptrace_single_step(child); - child->exit_code = data; - wake_up_process(child); - ret = 0; - break; - - /* Detach a process that was attached */ - case PTRACE_DETACH: - ret = ptrace_detach(child, data); + return ptrace_pokeusr(child, engine, avr32_uarea, addr, data); break; case PTRACE_GETREGS: - ret = ptrace_getregs(child, (void __user *)data); + return ptrace_whole_regset(child, engine, data, 0, 0); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (const void __user *)data); - break; - - default: - ret = ptrace_request(child, request, addr, data); + return ptrace_whole_regset(child, engine, data, 0, 1); break; } - pr_debug("sys_ptrace returning %d (DC = 0x%08lx)\n", ret, __mfdr(DBGREG_DC)); - return ret; + return -ENOSYS; } -#endif +#endif /* CONFIG_PTRACE */ +#endif /* CONFIG_UTRACE */ asmlinkage void syscall_trace(struct pt_regs *regs, int is_exit) {