From: Corey Minyard Add a debugging interface for PowerPC that allows signal handlers (or any jump to a context, really) to perform debug functions. It allows the a user program to turn on single-stepping, for instance, and the thread will get a trap after executing the next instruction. It can also (on supported PPC processors) turn on branch tracing and get a trap after the next branch instruction is executed. This is useful for in-application debugging. Note that you can enable single-stepping on x86 processors directly from signal handlers. Newer x86 processors have the equivalent of a branch-trace bit in the IA32_DEBUGCTL MSR and could have similar function to this syscall. Most other processors could benefit from a similar interface, except for ARM which is extraordinarily broken for debugging. Future uses of this could be adding the ability to set the hardware breakpoint registers from a signal handler. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc/kernel/entry.S | 30 +++++++------ 25-akpm/arch/ppc/kernel/misc.S | 2 25-akpm/arch/ppc/kernel/signal.c | 90 +++++++++++++++++++++++++++++++++++++++ 25-akpm/arch/ppc/kernel/traps.c | 2 25-akpm/include/asm-ppc/signal.h | 19 ++++++++ 25-akpm/include/asm-ppc/unistd.h | 2 6 files changed, 129 insertions(+), 16 deletions(-) diff -puN arch/ppc/kernel/entry.S~ppc32-debug-setcontext-syscall-implementation arch/ppc/kernel/entry.S --- 25/arch/ppc/kernel/entry.S~ppc32-debug-setcontext-syscall-implementation Thu Dec 9 13:45:32 2004 +++ 25-akpm/arch/ppc/kernel/entry.S Thu Dec 9 13:45:32 2004 @@ -111,8 +111,10 @@ transfer_to_handler: addi r11,r1,STACK_FRAME_OVERHEAD stw r11,PT_REGS(r12) #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) - lwz r12,PTRACE-THREAD(r12) - andi. r12,r12,PT_PTRACED + /* Check to see if the dbcr0 register is set up to debug. Use the + single-step bit to do this. */ + lwz r12,THREAD_DBCR0(r12) + andis. r12,r12,DBCR0_IC@h beq+ 3f /* From user and task is ptraced - load up global dbcr0 */ li r12,-1 /* clear all pending debug events */ @@ -242,9 +244,10 @@ ret_from_syscall: bne- syscall_exit_work syscall_exit_cont: #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) - /* If the process has its own DBCR0 value, load it up */ - lwz r0,PTRACE(r2) - andi. r0,r0,PT_PTRACED + /* If the process has its own DBCR0 value, load it up. The single + step bit tells us that dbcr0 should be loaded. */ + lwz r0,THREAD+THREAD_DBCR0(r2) + andis. r10,r0,DBCR0_IC@h bnel- load_dbcr0 #endif stwcx. r0,0,r1 /* to clear the reservation */ @@ -599,9 +602,10 @@ user_exc_return: /* r10 contains MSR_KE restore_user: #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) - /* Check whether this process has its own DBCR0 value */ - lwz r0,PTRACE(r2) - andi. r0,r0,PT_PTRACED + /* Check whether this process has its own DBCR0 value. The single + step bit tells us that dbcr0 should be loaded. */ + lwz r0,THREAD+THREAD_DBCR0(r2) + andis. r10,r0,DBCR0_IC@h bnel- load_dbcr0 #endif @@ -876,17 +880,17 @@ ret_from_mcheck_exc: /* * Load the DBCR0 value for a task that is being ptraced, - * having first saved away the global DBCR0. + * having first saved away the global DBCR0. Note that r0 + * has the dbcr0 value to set upon entry to this. */ load_dbcr0: - mfmsr r0 /* first disable debug exceptions */ - rlwinm r0,r0,0,~MSR_DE - mtmsr r0 + mfmsr r10 /* first disable debug exceptions */ + rlwinm r10,r10,0,~MSR_DE + mtmsr r10 isync mfspr r10,SPRN_DBCR0 lis r11,global_dbcr0@ha addi r11,r11,global_dbcr0@l - lwz r0,THREAD+THREAD_DBCR0(r2) stw r10,0(r11) mtspr SPRN_DBCR0,r0 lwz r10,4(r11) diff -puN arch/ppc/kernel/misc.S~ppc32-debug-setcontext-syscall-implementation arch/ppc/kernel/misc.S --- 25/arch/ppc/kernel/misc.S~ppc32-debug-setcontext-syscall-implementation Thu Dec 9 13:45:32 2004 +++ 25-akpm/arch/ppc/kernel/misc.S Thu Dec 9 13:45:32 2004 @@ -1434,7 +1434,7 @@ _GLOBAL(sys_call_table) .long sys_fstatfs64 .long ppc_fadvise64_64 .long sys_ni_syscall /* 255 - rtas (used on ppc64) */ - .long sys_ni_syscall /* 256 reserved for sys_debug_setcontext */ + .long sys_debug_setcontext .long sys_ni_syscall /* 257 reserved for vserver */ .long sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */ .long sys_ni_syscall /* 259 reserved for new sys_mbind */ diff -puN arch/ppc/kernel/signal.c~ppc32-debug-setcontext-syscall-implementation arch/ppc/kernel/signal.c --- 25/arch/ppc/kernel/signal.c~ppc32-debug-setcontext-syscall-implementation Thu Dec 9 13:45:32 2004 +++ 25-akpm/arch/ppc/kernel/signal.c Thu Dec 9 13:45:32 2004 @@ -509,6 +509,96 @@ int sys_rt_sigreturn(int r3, int r4, int return 0; } +int sys_debug_setcontext(struct ucontext __user *ctx, + int ndbg, struct sig_dbg_op *dbg, + int r6, int r7, int r8, + struct pt_regs *regs) +{ + struct sig_dbg_op op; + int i; + unsigned long new_msr = regs->msr; +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) + unsigned long new_dbcr0 = current->thread.dbcr0; +#endif + + for (i=0; imsr = new_msr; +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) + current->thread.dbcr0 = new_dbcr0; +#endif + + /* + * If we get a fault copying the context into the kernel's + * image of the user's registers, we can't just return -EFAULT + * because the user's registers will be corrupted. For instance + * the NIP value may have been updated but not some of the + * other registers. Given that we have done the verify_area + * and successfully read the first and last bytes of the region + * above, this should only happen in an out-of-memory situation + * or if another thread unmaps the region containing the context. + * We kill the task with a SIGSEGV in this situation. + */ + if (do_setcontext(ctx, regs, 1)) { + force_sig(SIGSEGV, current); + goto out; + } + + /* + * It's not clear whether or why it is desirable to save the + * sigaltstack setting on signal delivery and restore it on + * signal return. But other architectures do this and we have + * always done it up until now so it is probably better not to + * change it. -- paulus + */ + do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]); + + sigreturn_exit(regs); + /* doesn't actually return back to here */ + + out: + return 0; +} + /* * OK, we're invoking a handler */ diff -puN arch/ppc/kernel/traps.c~ppc32-debug-setcontext-syscall-implementation arch/ppc/kernel/traps.c --- 25/arch/ppc/kernel/traps.c~ppc32-debug-setcontext-syscall-implementation Thu Dec 9 13:45:32 2004 +++ 25-akpm/arch/ppc/kernel/traps.c Thu Dec 9 13:45:32 2004 @@ -566,7 +566,7 @@ void ProgramCheckException(struct pt_reg void SingleStepException(struct pt_regs *regs) { - regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ + regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ if (debugger_sstep(regs)) return; _exception(SIGTRAP, regs, TRAP_TRACE, 0); diff -puN include/asm-ppc/signal.h~ppc32-debug-setcontext-syscall-implementation include/asm-ppc/signal.h --- 25/include/asm-ppc/signal.h~ppc32-debug-setcontext-syscall-implementation Thu Dec 9 13:45:32 2004 +++ 25-akpm/include/asm-ppc/signal.h Thu Dec 9 13:45:32 2004 @@ -157,4 +157,23 @@ typedef struct sigaltstack { #define ptrace_signal_deliver(regs, cookie) do { } while (0) #endif /* __KERNEL__ */ +/* + * These are parameters to dbg_sigreturn syscall. They enable or + * disable certain debugging things that can be done from signal + * handlers. The dbg_sigreturn syscall *must* be called from a + * SA_SIGINFO signal so the ucontext can be passed to it. It takes an + * array of struct sig_dbg_op, which has the debug operations to + * perform before returning from the signal. + */ +struct sig_dbg_op { + int dbg_type; + unsigned long dbg_value; +}; + +/* Enable or disable single-stepping. The value sets the state. */ +#define SIG_DBG_SINGLE_STEPPING 1 + +/* Enable or disable branch tracing. The value sets the state. */ +#define SIG_DBG_BRANCH_TRACING 2 + #endif diff -puN include/asm-ppc/unistd.h~ppc32-debug-setcontext-syscall-implementation include/asm-ppc/unistd.h --- 25/include/asm-ppc/unistd.h~ppc32-debug-setcontext-syscall-implementation Thu Dec 9 13:45:32 2004 +++ 25-akpm/include/asm-ppc/unistd.h Thu Dec 9 13:45:32 2004 @@ -260,7 +260,7 @@ #define __NR_fstatfs64 253 #define __NR_fadvise64_64 254 #define __NR_rtas 255 -/* Number 256 is reserved for sys_debug_setcontext */ +#define __NR_sys_debug_setcontext 256 /* Number 257 is reserved for vserver */ /* Number 258 is reserved for new sys_remap_file_pages */ /* Number 259 is reserved for new sys_mbind */ _