diff options
Diffstat (limited to 'arch/m68knommu/kernel/traps.c')
-rw-r--r-- | arch/m68knommu/kernel/traps.c | 88 |
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 | |||
106 | int kstack_depth_to_print = 48; | 106 | int kstack_depth_to_print = 48; |
107 | 107 | ||
108 | void show_stack(struct task_struct *task, unsigned long *stack) | 108 | static 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 | ||
157 | void bad_super_trap(struct frame *fp) | 149 | void 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 | */ |
305 | void dump_stack(void) | 296 | void 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 | } | ||
312 | EXPORT_SYMBOL(dump_stack); | 324 | EXPORT_SYMBOL(dump_stack); |
313 | 325 | ||
326 | void 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 |
315 | asmlinkage void fpemu_signal(int signal, int code, void *addr) | 335 | asmlinkage void fpemu_signal(int signal, int code, void *addr) |
316 | { | 336 | { |