aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/sysrq.c
diff options
context:
space:
mode:
authorDaniel Walter <dwalter@google.com>2014-08-20 05:56:00 -0400
committerRichard Weinberger <richard@nod.at>2014-10-13 15:46:25 -0400
commit970e51feaddbc33ed0e7d187af7f69d1a12c7b6a (patch)
treedbe47fda5a1271dc5404c9c96d7965a870320fc2 /arch/um/kernel/sysrq.c
parent2a2361228c5e6d8c1733f00653481de918598e50 (diff)
um: Add support for CONFIG_STACKTRACE
Add stacktrace support for User Mode Linux Signed-off-by: Daniel Walter <dwalter@google.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/kernel/sysrq.c')
-rw-r--r--arch/um/kernel/sysrq.c69
1 files changed, 17 insertions, 52 deletions
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 799d7e413bf5..894c8d303cda 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -12,57 +12,20 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/sched.h> 13#include <linux/sched.h>
14#include <asm/sysrq.h> 14#include <asm/sysrq.h>
15#include <asm/stacktrace.h>
15#include <os.h> 16#include <os.h>
16 17
17struct stack_frame { 18static void _print_addr(void *data, unsigned long address, int reliable)
18 struct stack_frame *next_frame;
19 unsigned long return_address;
20};
21
22static void do_stack_trace(unsigned long *sp, unsigned long bp)
23{ 19{
24 int reliable; 20 pr_info(" [<%08lx>]", address);
25 unsigned long addr; 21 pr_cont(" %s", reliable ? "" : "? ");
26 struct stack_frame *frame = (struct stack_frame *)bp; 22 print_symbol("%s", address);
27 23 pr_cont("\n");
28 printk(KERN_INFO "Call Trace:\n");
29 while (((long) sp & (THREAD_SIZE-1)) != 0) {
30 addr = *sp;
31 if (__kernel_text_address(addr)) {
32 reliable = 0;
33 if ((unsigned long) sp == bp + sizeof(long)) {
34 frame = frame ? frame->next_frame : NULL;
35 bp = (unsigned long)frame;
36 reliable = 1;
37 }
38
39 printk(KERN_INFO " [<%08lx>]", addr);
40 printk(KERN_CONT " %s", reliable ? "" : "? ");
41 print_symbol(KERN_CONT "%s", addr);
42 printk(KERN_CONT "\n");
43 }
44 sp++;
45 }
46 printk(KERN_INFO "\n");
47} 24}
48 25
49static unsigned long get_frame_pointer(struct task_struct *task, 26static const struct stacktrace_ops stackops = {
50 struct pt_regs *segv_regs) 27 .address = _print_addr
51{ 28};
52 if (!task || task == current)
53 return segv_regs ? PT_REGS_BP(segv_regs) : current_bp();
54 else
55 return KSTK_EBP(task);
56}
57
58static unsigned long *get_stack_pointer(struct task_struct *task,
59 struct pt_regs *segv_regs)
60{
61 if (!task || task == current)
62 return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp();
63 else
64 return (unsigned long *)KSTK_ESP(task);
65}
66 29
67void show_stack(struct task_struct *task, unsigned long *stack) 30void show_stack(struct task_struct *task, unsigned long *stack)
68{ 31{
@@ -71,7 +34,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
71 int i; 34 int i;
72 35
73 if (!segv_regs && os_is_signal_stack()) { 36 if (!segv_regs && os_is_signal_stack()) {
74 printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler," 37 pr_err("Received SIGSEGV in SIGSEGV handler,"
75 " aborting stack trace!\n"); 38 " aborting stack trace!\n");
76 return; 39 return;
77 } 40 }
@@ -83,16 +46,18 @@ void show_stack(struct task_struct *task, unsigned long *stack)
83 if (!stack) 46 if (!stack)
84 sp = get_stack_pointer(task, segv_regs); 47 sp = get_stack_pointer(task, segv_regs);
85 48
86 printk(KERN_INFO "Stack:\n"); 49 pr_info("Stack:\n");
87 stack = sp; 50 stack = sp;
88 for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) { 51 for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) {
89 if (kstack_end(stack)) 52 if (kstack_end(stack))
90 break; 53 break;
91 if (i && ((i % STACKSLOTS_PER_LINE) == 0)) 54 if (i && ((i % STACKSLOTS_PER_LINE) == 0))
92 printk(KERN_CONT "\n"); 55 pr_cont("\n");
93 printk(KERN_CONT " %08lx", *stack++); 56 pr_cont(" %08lx", *stack++);
94 } 57 }
95 printk(KERN_CONT "\n"); 58 pr_cont("\n");
96 59
97 do_stack_trace(sp, bp); 60 pr_info("Call Trace:\n");
61 dump_trace(current, &stackops, NULL);
62 pr_info("\n");
98} 63}