Loading arch/blackfin/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ config RWSEM_XCHGADD_ALGORITHM config BLACKFIN def_bool y select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST Loading arch/blackfin/include/asm/ptrace.h +23 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #ifndef __ASSEMBLY__ struct task_struct; /* this struct defines the way the registers are stored on the stack during a system call. */ Loading Loading @@ -101,9 +103,30 @@ struct pt_regs { master interrupt enable. */ #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1))) #define instruction_pointer(regs) ((regs)->pc) #define user_stack_pointer(regs) ((regs)->usp) #define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs *); #define arch_has_single_step() (1) extern void user_enable_single_step(struct task_struct *child); extern void user_disable_single_step(struct task_struct *child); /* common code demands this function */ #define ptrace_disable(child) user_disable_single_step(child) /* * Get the address of the live pt_regs for the specified task. * These are saved onto the top kernel stack when the process * is not running. * * Note: if a user thread is execve'd from kernel space, the * kernel stack will not be empty on entry to the kernel, so * ptracing these tasks will fail. */ #define task_pt_regs(task) \ (struct pt_regs *) \ ((unsigned long)task_stack_page(task) + \ (THREAD_SIZE - sizeof(struct pt_regs))) #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ Loading arch/blackfin/include/asm/syscall.h 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Magic syscall break down functions * * Copyright 2010 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ #ifndef __ASM_BLACKFIN_SYSCALL_H__ #define __ASM_BLACKFIN_SYSCALL_H__ /* * Blackfin syscalls are simple: * enter: * p0: syscall number * r{0,1,2,3,4,5}: syscall args 0,1,2,3,4,5 * exit: * r0: return/error value */ #include <linux/err.h> #include <linux/sched.h> #include <asm/ptrace.h> static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { return regs->p0; } static inline void syscall_rollback(struct task_struct *task, struct pt_regs *regs) { regs->p0 = regs->orig_p0; } static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { return IS_ERR_VALUE(regs->r0) ? regs->r0 : 0; } static inline long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { return regs->r0; } static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { regs->r0 = error ? -error : val; } /** * syscall_get_arguments() * @task: unused * @regs: the register layout to extract syscall arguments from * @i: first syscall argument to extract * @n: number of syscall arguments to extract * @args: array to return the syscall arguments in * * args[0] gets i'th argument, args[n - 1] gets the i+n-1'th argument */ static inline void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, unsigned int i, unsigned int n, unsigned long *args) { /* * Assume the ptrace layout doesn't change -- r5 is first in memory, * then r4, ..., then r0. So we simply reverse the ptrace register * array in memory to store into the args array. */ long *aregs = ®s->r0 - i; BUG_ON(i > 5 || i + n > 6); while (n--) *args++ = *aregs--; } /* See syscall_get_arguments() comments */ static inline void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, unsigned int i, unsigned int n, const unsigned long *args) { long *aregs = ®s->r0 - i; BUG_ON(i > 5 || i + n > 6); while (n--) *aregs-- = *args++; } #endif arch/blackfin/kernel/ptrace.c +17 −49 Original line number Diff line number Diff line /* * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds * these modifications are Copyright 2004-2009 Analog Devices Inc. * these modifications are Copyright 2004-2010 Analog Devices Inc. * * Licensed under the GPL-2 */ Loading @@ -15,6 +15,7 @@ #include <linux/user.h> #include <linux/regset.h> #include <linux/signal.h> #include <linux/tracehook.h> #include <linux/uaccess.h> #include <asm/page.h> Loading @@ -32,25 +33,6 @@ * in exit.c or in signal.c. */ /* Find the stack offset for a register, relative to thread.esp0. */ #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) /* * Get the address of the live pt_regs for the specified task. * These are saved onto the top kernel stack when the process * is not running. * * Note: if a user thread is execve'd from kernel space, the * kernel stack will not be empty on entry to the kernel, so * ptracing these tasks will fail. */ static inline struct pt_regs *task_pt_regs(struct task_struct *task) { return (struct pt_regs *) ((unsigned long)task_stack_page(task) + (THREAD_SIZE - sizeof(struct pt_regs))); } /* * Get contents of register REGNO in task TASK. */ Loading Loading @@ -234,18 +216,13 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_bfin_native_view; } void ptrace_enable(struct task_struct *child) void user_enable_single_step(struct task_struct *child) { struct pt_regs *regs = task_pt_regs(child); regs->syscfg |= SYSCFG_SSSTEP; } /* * Called by kernel/ptrace.c when detaching.. * * Make sure the single step bit is not set. */ void ptrace_disable(struct task_struct *child) void user_disable_single_step(struct task_struct *child) { struct pt_regs *regs = task_pt_regs(child); regs->syscfg &= ~SYSCFG_SSSTEP; Loading Loading @@ -412,27 +389,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } asmlinkage void syscall_trace(void) asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; if (!(current->ptrace & PT_PTRACED)) return; int ret = 0; /* 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)); if (test_thread_flag(TIF_SYSCALL_TRACE)) ret = tracehook_report_syscall_entry(regs); /* * 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) { send_sig(current->exit_code, current, 1); current->exit_code = 0; return ret; } asmlinkage void syscall_trace_leave(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); } arch/blackfin/kernel/signal.c +3 −11 Original line number Diff line number Diff line /* * Copyright 2004-2009 Analog Devices Inc. * Copyright 2004-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later */ Loading Loading @@ -206,16 +206,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, regs->r1 = (unsigned long)(&frame->info); regs->r2 = (unsigned long)(&frame->uc); /* * Clear the trace flag when entering the signal handler, but * notify any tracer that was single-stepping it. The tracer * may want to single-step inside the handler too. */ if (regs->syscfg & TRACE_BITS) { regs->syscfg &= ~TRACE_BITS; ptrace_notify(SIGTRAP); } return 0; give_sigsegv: Loading Loading @@ -315,6 +305,8 @@ asmlinkage void do_signal(struct pt_regs *regs) * clear the TIF_RESTORE_SIGMASK flag */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); tracehook_signal_handler(signr, &info, &ka, regs, 1); } return; Loading Loading
arch/blackfin/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ config RWSEM_XCHGADD_ALGORITHM config BLACKFIN def_bool y select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST Loading
arch/blackfin/include/asm/ptrace.h +23 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #ifndef __ASSEMBLY__ struct task_struct; /* this struct defines the way the registers are stored on the stack during a system call. */ Loading Loading @@ -101,9 +103,30 @@ struct pt_regs { master interrupt enable. */ #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1))) #define instruction_pointer(regs) ((regs)->pc) #define user_stack_pointer(regs) ((regs)->usp) #define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs *); #define arch_has_single_step() (1) extern void user_enable_single_step(struct task_struct *child); extern void user_disable_single_step(struct task_struct *child); /* common code demands this function */ #define ptrace_disable(child) user_disable_single_step(child) /* * Get the address of the live pt_regs for the specified task. * These are saved onto the top kernel stack when the process * is not running. * * Note: if a user thread is execve'd from kernel space, the * kernel stack will not be empty on entry to the kernel, so * ptracing these tasks will fail. */ #define task_pt_regs(task) \ (struct pt_regs *) \ ((unsigned long)task_stack_page(task) + \ (THREAD_SIZE - sizeof(struct pt_regs))) #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ Loading
arch/blackfin/include/asm/syscall.h 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Magic syscall break down functions * * Copyright 2010 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ #ifndef __ASM_BLACKFIN_SYSCALL_H__ #define __ASM_BLACKFIN_SYSCALL_H__ /* * Blackfin syscalls are simple: * enter: * p0: syscall number * r{0,1,2,3,4,5}: syscall args 0,1,2,3,4,5 * exit: * r0: return/error value */ #include <linux/err.h> #include <linux/sched.h> #include <asm/ptrace.h> static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { return regs->p0; } static inline void syscall_rollback(struct task_struct *task, struct pt_regs *regs) { regs->p0 = regs->orig_p0; } static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { return IS_ERR_VALUE(regs->r0) ? regs->r0 : 0; } static inline long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { return regs->r0; } static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { regs->r0 = error ? -error : val; } /** * syscall_get_arguments() * @task: unused * @regs: the register layout to extract syscall arguments from * @i: first syscall argument to extract * @n: number of syscall arguments to extract * @args: array to return the syscall arguments in * * args[0] gets i'th argument, args[n - 1] gets the i+n-1'th argument */ static inline void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, unsigned int i, unsigned int n, unsigned long *args) { /* * Assume the ptrace layout doesn't change -- r5 is first in memory, * then r4, ..., then r0. So we simply reverse the ptrace register * array in memory to store into the args array. */ long *aregs = ®s->r0 - i; BUG_ON(i > 5 || i + n > 6); while (n--) *args++ = *aregs--; } /* See syscall_get_arguments() comments */ static inline void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, unsigned int i, unsigned int n, const unsigned long *args) { long *aregs = ®s->r0 - i; BUG_ON(i > 5 || i + n > 6); while (n--) *aregs-- = *args++; } #endif
arch/blackfin/kernel/ptrace.c +17 −49 Original line number Diff line number Diff line /* * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds * these modifications are Copyright 2004-2009 Analog Devices Inc. * these modifications are Copyright 2004-2010 Analog Devices Inc. * * Licensed under the GPL-2 */ Loading @@ -15,6 +15,7 @@ #include <linux/user.h> #include <linux/regset.h> #include <linux/signal.h> #include <linux/tracehook.h> #include <linux/uaccess.h> #include <asm/page.h> Loading @@ -32,25 +33,6 @@ * in exit.c or in signal.c. */ /* Find the stack offset for a register, relative to thread.esp0. */ #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) /* * Get the address of the live pt_regs for the specified task. * These are saved onto the top kernel stack when the process * is not running. * * Note: if a user thread is execve'd from kernel space, the * kernel stack will not be empty on entry to the kernel, so * ptracing these tasks will fail. */ static inline struct pt_regs *task_pt_regs(struct task_struct *task) { return (struct pt_regs *) ((unsigned long)task_stack_page(task) + (THREAD_SIZE - sizeof(struct pt_regs))); } /* * Get contents of register REGNO in task TASK. */ Loading Loading @@ -234,18 +216,13 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_bfin_native_view; } void ptrace_enable(struct task_struct *child) void user_enable_single_step(struct task_struct *child) { struct pt_regs *regs = task_pt_regs(child); regs->syscfg |= SYSCFG_SSSTEP; } /* * Called by kernel/ptrace.c when detaching.. * * Make sure the single step bit is not set. */ void ptrace_disable(struct task_struct *child) void user_disable_single_step(struct task_struct *child) { struct pt_regs *regs = task_pt_regs(child); regs->syscfg &= ~SYSCFG_SSSTEP; Loading Loading @@ -412,27 +389,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } asmlinkage void syscall_trace(void) asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; if (!(current->ptrace & PT_PTRACED)) return; int ret = 0; /* 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)); if (test_thread_flag(TIF_SYSCALL_TRACE)) ret = tracehook_report_syscall_entry(regs); /* * 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) { send_sig(current->exit_code, current, 1); current->exit_code = 0; return ret; } asmlinkage void syscall_trace_leave(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); }
arch/blackfin/kernel/signal.c +3 −11 Original line number Diff line number Diff line /* * Copyright 2004-2009 Analog Devices Inc. * Copyright 2004-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later */ Loading Loading @@ -206,16 +206,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, regs->r1 = (unsigned long)(&frame->info); regs->r2 = (unsigned long)(&frame->uc); /* * Clear the trace flag when entering the signal handler, but * notify any tracer that was single-stepping it. The tracer * may want to single-step inside the handler too. */ if (regs->syscfg & TRACE_BITS) { regs->syscfg &= ~TRACE_BITS; ptrace_notify(SIGTRAP); } return 0; give_sigsegv: Loading Loading @@ -315,6 +305,8 @@ asmlinkage void do_signal(struct pt_regs *regs) * clear the TIF_RESTORE_SIGMASK flag */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); tracehook_signal_handler(signr, &info, &ka, regs, 1); } return; Loading