diff options
Diffstat (limited to 'arch/um/kernel/sysrq.c')
-rw-r--r-- | arch/um/kernel/sysrq.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 33cc72e26c6e..7122bf9c753e 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/sched.h> #include <asm/sysrq.h> +#include <os.h> struct stack_frame { struct stack_frame *next_frame; @@ -48,29 +49,42 @@ static void print_stack_trace(unsigned long *sp, unsigned long bp) /*Stolen from arch/i386/kernel/traps.c */ static const int kstack_depth_to_print = 24; -static unsigned long get_frame_pointer(struct task_struct *task) +static unsigned long get_frame_pointer(struct task_struct *task, + struct pt_regs *segv_regs) { if (!task || task == current) - return current_bp(); + return segv_regs ? PT_REGS_BP(segv_regs) : current_bp(); else return KSTK_EBP(task); } +static unsigned long *get_stack_pointer(struct task_struct *task, + struct pt_regs *segv_regs) +{ + if (!task || task == current) + return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp(); + else + return (unsigned long *)KSTK_ESP(task); +} + void show_stack(struct task_struct *task, unsigned long *stack) { unsigned long *sp = stack, bp = 0; + struct pt_regs *segv_regs = current->thread.segv_regs; int i; + if (!segv_regs && os_is_signal_stack()) { + printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler," + " aborting stack trace!\n"); + return; + } + #ifdef CONFIG_FRAME_POINTER - bp = get_frame_pointer(task); + bp = get_frame_pointer(task, segv_regs); #endif - if (!stack) { - if (!task || task == current) - sp = current_sp(); - else - sp = (unsigned long *)KSTK_ESP(task); - } + if (!stack) + sp = get_stack_pointer(task, segv_regs); printk(KERN_INFO "Stack:\n"); stack = sp; |