[PATCH 1e] utrace: tracehook for AVR32 From: Haavard Skinnemoen This patch does the initial tracehook conversion for AVR32. Signed-off-by: Haavard Skinnemoen Signed-off-by: Roland McGrath --- arch/avr32/kernel/ptrace.c | 50 +++++++++++++++---------------- arch/avr32/kernel/process.c | 2 - arch/avr32/kernel/entry-avr32b.S | 10 +++++- include/asm-avr32/tracehook.h | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 30 deletions(-) create include/asm-avr32/tracehook.h --- linux-2.6/arch/avr32/kernel/ptrace.c +++ linux-2.6/arch/avr32/kernel/ptrace.c @@ -5,20 +5,16 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#undef DEBUG +#include +#include +#include #include #include #include #include #include #include -#include -#include -#include - -#include -#include -#include + #include #include @@ -28,6 +24,7 @@ static struct pt_regs *get_user_regs(str THREAD_SIZE - sizeof(struct pt_regs)); } +#if 0 static void ptrace_single_step(struct task_struct *tsk) { pr_debug("ptrace_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", @@ -229,30 +226,31 @@ long arch_ptrace(struct task_struct *chi return ret; } +#endif -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(struct pt_regs *regs, int is_exit) { if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; - if (!(current->ptrace & PT_PTRACED)) - return; - /* The 0x80 provides a way for the tracing parent to - * distinguish between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); + tracehook_report_syscall(regs, is_exit); +} - /* - * this isn't the same as continuing with a signal, but it - * will do for normal use. strace only continues with a - * signal if the stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - pr_debug("syscall_trace: sending signal %d to PID %u\n", - current->exit_code, current->pid); - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } +/* + * Handle hitting a breakpoint + */ +static void do_breakpoint(struct task_struct *tsk, struct pt_regs *regs) +{ + siginfo_t info; + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; + info.si_addr = (void __user *)instruction_pointer(regs); + + pr_debug("ptrace_break: Sending SIGTRAP to PID %u (pc = 0x%p)\n", + tsk->pid, info.si_addr); + force_sig_info(SIGTRAP, &info, tsk); } /* --- linux-2.6/arch/avr32/kernel/process.c +++ linux-2.6/arch/avr32/kernel/process.c @@ -383,8 +383,6 @@ asmlinkage int sys_execve(char __user *u goto out; error = do_execve(filename, uargv, uenvp, regs); - if (error == 0) - current->ptrace &= ~PT_DTRACE; putname(filename); out: --- linux-2.6/arch/avr32/kernel/entry-avr32b.S +++ linux-2.6/arch/avr32/kernel/entry-avr32b.S @@ -230,15 +230,21 @@ ret_from_fork: rjmp syscall_exit_cont syscall_trace_enter: - pushm r8-r12 + mov r12, sp /* regs */ + mov r11, 0 /* is_exit */ rcall syscall_trace - popm r8-r12 + + /* syscall_trace may update r8, so reload r8-r12 from regs. */ + sub lr, sp, -REG_R12 + ldm lr, r8-r12 rjmp syscall_trace_cont syscall_exit_work: bld r1, TIF_SYSCALL_TRACE brcc 1f unmask_interrupts + mov r12, sp + mov r11, 1 rcall syscall_trace mask_interrupts ld.w r1, r0[TI_flags] --- linux-2.6/include/asm-avr32/tracehook.h +++ linux-2.6/include/asm-avr32/tracehook.h @@ -0,0 +1,62 @@ +/* + * Tracing hooks for AVR32 + * + * Copyright (C) 2007 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _ASM_AVR32_TRACEHOOK_H +#define _ASM_AVR32_TRACEHOOK_H + +#include + +#define ARCH_HAS_SINGLE_STEP 1 + +static inline void tracehook_enable_single_step(struct task_struct *tsk) +{ + /* + * If the process is stopped in debug mode, simply set + * TIF_SINGLE_STEP to tell the monitor code to set the single + * step bit in DC before returning. + * + * Otherwise, we need to set a breakpoint at the return + * address before returning to userspace. TIF_BREAKPOINT will + * tell the syscall/exception exit code to do this. + */ + if (!(tsk->thread.cpu_context.sr & SR_D)) + set_tsk_thread_flag(tsk, TIF_BREAKPOINT); + + set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); +} + +static inline void tracehook_disable_single_step(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_BREAKPOINT); + clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP); +} + +static inline int tracehook_single_step_enabled(struct task_struct *tsk) +{ + return test_tsk_thread_flag(tsk, TIF_SINGLE_STEP); +} + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + /* Invalid system call number => return -ENOSYS */ + regs->r8 = -1; +} + + +#endif /* _ASM_AVR32_TRACEHOOK_H */