diff options
Diffstat (limited to 'arch/um/kernel/sysrq.c')
-rw-r--r-- | arch/um/kernel/sysrq.c | 102 |
1 files changed, 35 insertions, 67 deletions
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 799d7e4..0dc4d1c 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -1,10 +1,6 @@ /* * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Copyright (C) 2013 Richard Weinberger <richrd@nod.at> - * - * 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. + * Licensed under the GPL */ #include <linux/kallsyms.h> @@ -12,87 +8,59 @@ #include <linux/module.h> #include <linux/sched.h> #include <asm/sysrq.h> -#include <os.h> -struct stack_frame { - struct stack_frame *next_frame; - unsigned long return_address; -}; - -static void do_stack_trace(unsigned long *sp, unsigned long bp) +/* Catch non-i386 SUBARCH's. */ +#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) +void show_trace(struct task_struct *task, unsigned long * stack) { - int reliable; unsigned long addr; - struct stack_frame *frame = (struct stack_frame *)bp; - printk(KERN_INFO "Call Trace:\n"); - while (((long) sp & (THREAD_SIZE-1)) != 0) { - addr = *sp; - if (__kernel_text_address(addr)) { - reliable = 0; - if ((unsigned long) sp == bp + sizeof(long)) { - frame = frame ? frame->next_frame : NULL; - bp = (unsigned long)frame; - reliable = 1; - } + if (!stack) { + stack = (unsigned long*) &stack; + WARN_ON(1); + } - printk(KERN_INFO " [<%08lx>]", addr); - printk(KERN_CONT " %s", reliable ? "" : "? "); - print_symbol(KERN_CONT "%s", addr); + printk(KERN_INFO "Call Trace: \n"); + while (((long) stack & (THREAD_SIZE-1)) != 0) { + addr = *stack; + if (__kernel_text_address(addr)) { + printk(KERN_INFO "%08lx: [<%08lx>]", + (unsigned long) stack, addr); + print_symbol(KERN_CONT " %s", addr); printk(KERN_CONT "\n"); } - sp++; + stack++; } printk(KERN_INFO "\n"); } +#endif -static unsigned long get_frame_pointer(struct task_struct *task, - struct pt_regs *segv_regs) -{ - if (!task || task == current) - return segv_regs ? PT_REGS_BP(segv_regs) : current_bp(); - else - return KSTK_EBP(task); -} +/*Stolen from arch/i386/kernel/traps.c */ +static const int kstack_depth_to_print = 24; -static unsigned long *get_stack_pointer(struct task_struct *task, - struct pt_regs *segv_regs) +/* This recently started being used in arch-independent code too, as in + * kernel/sched/core.c.*/ +void show_stack(struct task_struct *task, unsigned long *esp) { - 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; + unsigned long *stack; int i; - if (!segv_regs && os_is_signal_stack()) { - printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler," - " aborting stack trace!\n"); - return; + if (esp == NULL) { + if (task != current && task != NULL) { + esp = (unsigned long *) KSTK_ESP(task); + } else { + esp = (unsigned long *) &esp; + } } -#ifdef CONFIG_FRAME_POINTER - bp = get_frame_pointer(task, segv_regs); -#endif - - if (!stack) - sp = get_stack_pointer(task, segv_regs); - - printk(KERN_INFO "Stack:\n"); - stack = sp; - for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) { + stack = esp; + for (i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; - if (i && ((i % STACKSLOTS_PER_LINE) == 0)) - printk(KERN_CONT "\n"); - printk(KERN_CONT " %08lx", *stack++); + if (i && ((i % 8) == 0)) + printk(KERN_INFO " "); + printk(KERN_CONT "%08lx ", *stack++); } - printk(KERN_CONT "\n"); - do_stack_trace(sp, bp); + show_trace(task, esp); } |