aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/sysrq.c
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2013-09-23 11:38:01 -0400
committerRichard Weinberger <richard@nod.at>2013-11-17 05:27:25 -0500
commit9d1ee8ce92e16c6aa0a3fd91ee8ed9e403b3a2eb (patch)
treefa38685d0c62cbc97d9016750bb18c7feac54799 /arch/um/kernel/sysrq.c
parent5e01dc7b26d9f24f39abace5da98ccbd6a5ceb52 (diff)
um: Rewrite show_stack()
Currently on UML stack traces are not very reliable and both x86 and x86_64 have their on implementations. This patch unifies both and adds support to outline unreliable functions calls. Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/kernel/sysrq.c')
-rw-r--r--arch/um/kernel/sysrq.c85
1 files changed, 53 insertions, 32 deletions
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 0dc4d1c6f98a..33cc72e26c6e 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -1,6 +1,10 @@
1/* 1/*
2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Copyright (C) 2013 Richard Weinberger <richrd@nod.at>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
4 */ 8 */
5 9
6#include <linux/kallsyms.h> 10#include <linux/kallsyms.h>
@@ -9,58 +13,75 @@
9#include <linux/sched.h> 13#include <linux/sched.h>
10#include <asm/sysrq.h> 14#include <asm/sysrq.h>
11 15
12/* Catch non-i386 SUBARCH's. */ 16struct stack_frame {
13#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) 17 struct stack_frame *next_frame;
14void show_trace(struct task_struct *task, unsigned long * stack) 18 unsigned long return_address;
19};
20
21static void print_stack_trace(unsigned long *sp, unsigned long bp)
15{ 22{
23 int reliable;
16 unsigned long addr; 24 unsigned long addr;
25 struct stack_frame *frame = (struct stack_frame *)bp;
17 26
18 if (!stack) { 27 printk(KERN_INFO "Call Trace:\n");
19 stack = (unsigned long*) &stack; 28 while (((long) sp & (THREAD_SIZE-1)) != 0) {
20 WARN_ON(1); 29 addr = *sp;
21 }
22
23 printk(KERN_INFO "Call Trace: \n");
24 while (((long) stack & (THREAD_SIZE-1)) != 0) {
25 addr = *stack;
26 if (__kernel_text_address(addr)) { 30 if (__kernel_text_address(addr)) {
27 printk(KERN_INFO "%08lx: [<%08lx>]", 31 reliable = 0;
28 (unsigned long) stack, addr); 32 if ((unsigned long) sp == bp + sizeof(long)) {
29 print_symbol(KERN_CONT " %s", addr); 33 frame = frame ? frame->next_frame : NULL;
34 bp = (unsigned long)frame;
35 reliable = 1;
36 }
37
38 printk(KERN_INFO " [<%08lx>]", addr);
39 printk(KERN_CONT " %s", reliable ? "" : "? ");
40 print_symbol(KERN_CONT "%s", addr);
30 printk(KERN_CONT "\n"); 41 printk(KERN_CONT "\n");
31 } 42 }
32 stack++; 43 sp++;
33 } 44 }
34 printk(KERN_INFO "\n"); 45 printk(KERN_INFO "\n");
35} 46}
36#endif
37 47
38/*Stolen from arch/i386/kernel/traps.c */ 48/*Stolen from arch/i386/kernel/traps.c */
39static const int kstack_depth_to_print = 24; 49static const int kstack_depth_to_print = 24;
40 50
41/* This recently started being used in arch-independent code too, as in 51static unsigned long get_frame_pointer(struct task_struct *task)
42 * kernel/sched/core.c.*/ 52{
43void show_stack(struct task_struct *task, unsigned long *esp) 53 if (!task || task == current)
54 return current_bp();
55 else
56 return KSTK_EBP(task);
57}
58
59void show_stack(struct task_struct *task, unsigned long *stack)
44{ 60{
45 unsigned long *stack; 61 unsigned long *sp = stack, bp = 0;
46 int i; 62 int i;
47 63
48 if (esp == NULL) { 64#ifdef CONFIG_FRAME_POINTER
49 if (task != current && task != NULL) { 65 bp = get_frame_pointer(task);
50 esp = (unsigned long *) KSTK_ESP(task); 66#endif
51 } else { 67
52 esp = (unsigned long *) &esp; 68 if (!stack) {
53 } 69 if (!task || task == current)
70 sp = current_sp();
71 else
72 sp = (unsigned long *)KSTK_ESP(task);
54 } 73 }
55 74
56 stack = esp; 75 printk(KERN_INFO "Stack:\n");
76 stack = sp;
57 for (i = 0; i < kstack_depth_to_print; i++) { 77 for (i = 0; i < kstack_depth_to_print; i++) {
58 if (kstack_end(stack)) 78 if (kstack_end(stack))
59 break; 79 break;
60 if (i && ((i % 8) == 0)) 80 if (i && ((i % STACKSLOTS_PER_LINE) == 0))
61 printk(KERN_INFO " "); 81 printk(KERN_CONT "\n");
62 printk(KERN_CONT "%08lx ", *stack++); 82 printk(KERN_CONT " %08lx", *stack++);
63 } 83 }
84 printk(KERN_CONT "\n");
64 85
65 show_trace(task, esp); 86 print_stack_trace(sp, bp);
66} 87}