aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/kernel/traps.c
diff options
context:
space:
mode:
authorSebastian Siewior <bigeasy@linutronix.de>2008-04-30 22:16:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-05-01 11:08:35 -0400
commitf6054e2131d8f5d43f6686ecc7687994adecc5a2 (patch)
treecd08ec02d9ca6259efbf948d4ca829b7ceafa8fd /arch/m68knommu/kernel/traps.c
parent008150f53729d188a5c14b1a86725972e15fe5f4 (diff)
m68knommu: add pretty back strace
With this patch and CONFIG_FRAME_POINTER=y CONFIG_KALLSYMS=y The backtrace shows resolved function names and their numeric address. Signed-off-by: Sebastian Siewior <bigeasy@linutronix.de> Signed-off-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68knommu/kernel/traps.c')
-rw-r--r--arch/m68knommu/kernel/traps.c88
1 files changed, 54 insertions, 34 deletions
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index 437a061d8b94..ec9aea652e79 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -28,6 +28,7 @@
28#include <linux/linkage.h> 28#include <linux/linkage.h>
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/ptrace.h> 30#include <linux/ptrace.h>
31#include <linux/kallsyms.h>
31 32
32#include <asm/setup.h> 33#include <asm/setup.h>
33#include <asm/fpu.h> 34#include <asm/fpu.h>
@@ -102,56 +103,47 @@ asmlinkage void buserr_c(struct frame *fp)
102 force_sig(SIGSEGV, current); 103 force_sig(SIGSEGV, current);
103} 104}
104 105
105
106int kstack_depth_to_print = 48; 106int kstack_depth_to_print = 48;
107 107
108void show_stack(struct task_struct *task, unsigned long *stack) 108static void __show_stack(struct task_struct *task, unsigned long *stack)
109{ 109{
110 unsigned long *endstack, addr; 110 unsigned long *endstack, addr;
111 extern char _start, _etext; 111 unsigned long *last_stack;
112 int i; 112 int i;
113 113
114 if (!stack) { 114 if (!stack)
115 if (task) 115 stack = (unsigned long *)task->thread.ksp;
116 stack = (unsigned long *)task->thread.ksp;
117 else
118 stack = (unsigned long *)&stack;
119 }
120 116
121 addr = (unsigned long) stack; 117 addr = (unsigned long) stack;
122 endstack = (unsigned long *) PAGE_ALIGN(addr); 118 endstack = (unsigned long *) PAGE_ALIGN(addr);
123 119
124 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); 120 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
125 for (i = 0; i < kstack_depth_to_print; i++) { 121 for (i = 0; i < kstack_depth_to_print; i++) {
126 if (stack + 1 > endstack) 122 if (stack + 1 + i > endstack)
127 break; 123 break;
128 if (i % 8 == 0) 124 if (i % 8 == 0)
129 printk("\n" KERN_EMERG " "); 125 printk("\n" KERN_EMERG " ");
130 printk(" %08lx", *stack++); 126 printk(" %08lx", *(stack + i));
131 } 127 }
132 printk("\n"); 128 printk("\n");
133 129
134 printk(KERN_EMERG "Call Trace:"); 130#ifdef CONFIG_FRAME_POINTER
135 i = 0; 131 printk(KERN_EMERG "Call Trace:\n");
136 while (stack + 1 <= endstack) { 132
137 addr = *stack++; 133 last_stack = stack - 1;
138 /* 134 while (stack <= endstack && stack > last_stack) {
139 * If the address is either in the text segment of the 135
140 * kernel, or in the region which contains vmalloc'ed 136 addr = *(stack + 1);
141 * memory, it *may* be the address of a calling 137 printk(KERN_EMERG " [%08lx] ", addr);
142 * routine; if so, print it so that someone tracing 138 print_symbol(KERN_CONT "%s\n", addr);
143 * down the cause of the crash will be able to figure 139
144 * out the call path that was taken. 140 last_stack = stack;
145 */ 141 stack = (unsigned long *)*stack;
146 if (((addr >= (unsigned long) &_start) &&
147 (addr <= (unsigned long) &_etext))) {
148 if (i % 4 == 0)
149 printk("\n" KERN_EMERG " ");
150 printk(" [<%08lx>]", addr);
151 i++;
152 }
153 } 142 }
154 printk("\n"); 143 printk("\n");
144#else
145 printk(KERN_EMERG "CONFIG_FRAME_POINTER disabled, no symbolic call trace\n");
146#endif
155} 147}
156 148
157void bad_super_trap(struct frame *fp) 149void bad_super_trap(struct frame *fp)
@@ -298,19 +290,47 @@ asmlinkage void set_esp0(unsigned long ssp)
298 current->thread.esp0 = ssp; 290 current->thread.esp0 = ssp;
299} 291}
300 292
301
302/* 293/*
303 * The architecture-independent backtrace generator 294 * The architecture-independent backtrace generator
304 */ 295 */
305void dump_stack(void) 296void dump_stack(void)
306{ 297{
307 unsigned long stack; 298 /*
299 * We need frame pointers for this little trick, which works as follows:
300 *
301 * +------------+ 0x00
302 * | Next SP | -> 0x0c
303 * +------------+ 0x04
304 * | Caller |
305 * +------------+ 0x08
306 * | Local vars | -> our stack var
307 * +------------+ 0x0c
308 * | Next SP | -> 0x18, that is what we pass to show_stack()
309 * +------------+ 0x10
310 * | Caller |
311 * +------------+ 0x14
312 * | Local vars |
313 * +------------+ 0x18
314 * | ... |
315 * +------------+
316 */
308 317
309 show_stack(current, &stack); 318 unsigned long *stack;
310}
311 319
320 stack = (unsigned long *)&stack;
321 stack++;
322 __show_stack(current, stack);
323}
312EXPORT_SYMBOL(dump_stack); 324EXPORT_SYMBOL(dump_stack);
313 325
326void show_stack(struct task_struct *task, unsigned long *stack)
327{
328 if (!stack && !task)
329 dump_stack();
330 else
331 __show_stack(task, stack);
332}
333
314#ifdef CONFIG_M68KFPU_EMU 334#ifdef CONFIG_M68KFPU_EMU
315asmlinkage void fpemu_signal(int signal, int code, void *addr) 335asmlinkage void fpemu_signal(int signal, int code, void *addr)
316{ 336{