diff options
Diffstat (limited to 'arch/x86/kernel/traps_64.c')
-rw-r--r-- | arch/x86/kernel/traps_64.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 37b07d08704b..62c4d8f46ee9 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c | |||
@@ -99,13 +99,14 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) | |||
99 | int kstack_depth_to_print = 12; | 99 | int kstack_depth_to_print = 12; |
100 | 100 | ||
101 | #ifdef CONFIG_KALLSYMS | 101 | #ifdef CONFIG_KALLSYMS |
102 | void printk_address(unsigned long address) | 102 | void printk_address(unsigned long address, int reliable) |
103 | { | 103 | { |
104 | unsigned long offset = 0, symsize; | 104 | unsigned long offset = 0, symsize; |
105 | const char *symname; | 105 | const char *symname; |
106 | char *modname; | 106 | char *modname; |
107 | char *delim = ":"; | 107 | char *delim = ":"; |
108 | char namebuf[128]; | 108 | char namebuf[128]; |
109 | char reliab[4] = "";; | ||
109 | 110 | ||
110 | symname = kallsyms_lookup(address, &symsize, &offset, | 111 | symname = kallsyms_lookup(address, &symsize, &offset, |
111 | &modname, namebuf); | 112 | &modname, namebuf); |
@@ -113,13 +114,16 @@ void printk_address(unsigned long address) | |||
113 | printk(" [<%016lx>]\n", address); | 114 | printk(" [<%016lx>]\n", address); |
114 | return; | 115 | return; |
115 | } | 116 | } |
117 | if (!reliable) | ||
118 | strcpy(reliab, "? "); | ||
119 | |||
116 | if (!modname) | 120 | if (!modname) |
117 | modname = delim = ""; | 121 | modname = delim = ""; |
118 | printk(" [<%016lx>] %s%s%s%s+0x%lx/0x%lx\n", | 122 | printk(" [<%016lx>] %s%s%s%s%s+0x%lx/0x%lx\n", |
119 | address, delim, modname, delim, symname, offset, symsize); | 123 | address, reliab, delim, modname, delim, symname, offset, symsize); |
120 | } | 124 | } |
121 | #else | 125 | #else |
122 | void printk_address(unsigned long address) | 126 | void printk_address(unsigned long address, int reliable) |
123 | { | 127 | { |
124 | printk(" [<%016lx>]\n", address); | 128 | printk(" [<%016lx>]\n", address); |
125 | } | 129 | } |
@@ -215,7 +219,7 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | |||
215 | } | 219 | } |
216 | 220 | ||
217 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, | 221 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, |
218 | unsigned long *stack, | 222 | unsigned long *stack, unsigned long bp, |
219 | const struct stacktrace_ops *ops, void *data) | 223 | const struct stacktrace_ops *ops, void *data) |
220 | { | 224 | { |
221 | const unsigned cpu = get_cpu(); | 225 | const unsigned cpu = get_cpu(); |
@@ -252,7 +256,7 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, | |||
252 | * down the cause of the crash will be able to figure \ | 256 | * down the cause of the crash will be able to figure \ |
253 | * out the call path that was taken. \ | 257 | * out the call path that was taken. \ |
254 | */ \ | 258 | */ \ |
255 | ops->address(data, addr); \ | 259 | ops->address(data, addr, 1); \ |
256 | } \ | 260 | } \ |
257 | } while (0) | 261 | } while (0) |
258 | 262 | ||
@@ -331,10 +335,10 @@ static int print_trace_stack(void *data, char *name) | |||
331 | return 0; | 335 | return 0; |
332 | } | 336 | } |
333 | 337 | ||
334 | static void print_trace_address(void *data, unsigned long addr) | 338 | static void print_trace_address(void *data, unsigned long addr, int reliable) |
335 | { | 339 | { |
336 | touch_nmi_watchdog(); | 340 | touch_nmi_watchdog(); |
337 | printk_address(addr); | 341 | printk_address(addr, reliable); |
338 | } | 342 | } |
339 | 343 | ||
340 | static const struct stacktrace_ops print_trace_ops = { | 344 | static const struct stacktrace_ops print_trace_ops = { |
@@ -345,15 +349,17 @@ static const struct stacktrace_ops print_trace_ops = { | |||
345 | }; | 349 | }; |
346 | 350 | ||
347 | void | 351 | void |
348 | show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack) | 352 | show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, |
353 | unsigned long bp) | ||
349 | { | 354 | { |
350 | printk("\nCall Trace:\n"); | 355 | printk("\nCall Trace:\n"); |
351 | dump_trace(tsk, regs, stack, &print_trace_ops, NULL); | 356 | dump_trace(tsk, regs, stack, bp, &print_trace_ops, NULL); |
352 | printk("\n"); | 357 | printk("\n"); |
353 | } | 358 | } |
354 | 359 | ||
355 | static void | 360 | static void |
356 | _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *sp) | 361 | _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *sp, |
362 | unsigned long bp) | ||
357 | { | 363 | { |
358 | unsigned long *stack; | 364 | unsigned long *stack; |
359 | int i; | 365 | int i; |
@@ -387,12 +393,12 @@ _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *sp) | |||
387 | printk(" %016lx", *stack++); | 393 | printk(" %016lx", *stack++); |
388 | touch_nmi_watchdog(); | 394 | touch_nmi_watchdog(); |
389 | } | 395 | } |
390 | show_trace(tsk, regs, sp); | 396 | show_trace(tsk, regs, sp, bp); |
391 | } | 397 | } |
392 | 398 | ||
393 | void show_stack(struct task_struct *tsk, unsigned long * sp) | 399 | void show_stack(struct task_struct *tsk, unsigned long * sp) |
394 | { | 400 | { |
395 | _show_stack(tsk, NULL, sp); | 401 | _show_stack(tsk, NULL, sp, 0); |
396 | } | 402 | } |
397 | 403 | ||
398 | /* | 404 | /* |
@@ -401,13 +407,14 @@ void show_stack(struct task_struct *tsk, unsigned long * sp) | |||
401 | void dump_stack(void) | 407 | void dump_stack(void) |
402 | { | 408 | { |
403 | unsigned long dummy; | 409 | unsigned long dummy; |
410 | unsigned long bp = 0; | ||
404 | 411 | ||
405 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | 412 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", |
406 | current->pid, current->comm, print_tainted(), | 413 | current->pid, current->comm, print_tainted(), |
407 | init_utsname()->release, | 414 | init_utsname()->release, |
408 | (int)strcspn(init_utsname()->version, " "), | 415 | (int)strcspn(init_utsname()->version, " "), |
409 | init_utsname()->version); | 416 | init_utsname()->version); |
410 | show_trace(NULL, NULL, &dummy); | 417 | show_trace(NULL, NULL, &dummy, bp); |
411 | } | 418 | } |
412 | 419 | ||
413 | EXPORT_SYMBOL(dump_stack); | 420 | EXPORT_SYMBOL(dump_stack); |
@@ -432,7 +439,7 @@ void show_registers(struct pt_regs *regs) | |||
432 | */ | 439 | */ |
433 | if (in_kernel) { | 440 | if (in_kernel) { |
434 | printk("Stack: "); | 441 | printk("Stack: "); |
435 | _show_stack(NULL, regs, (unsigned long*)sp); | 442 | _show_stack(NULL, regs, (unsigned long *)sp, regs->bp); |
436 | 443 | ||
437 | printk("\nCode: "); | 444 | printk("\nCode: "); |
438 | if (regs->ip < PAGE_OFFSET) | 445 | if (regs->ip < PAGE_OFFSET) |
@@ -527,7 +534,7 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err) | |||
527 | add_taint(TAINT_DIE); | 534 | add_taint(TAINT_DIE); |
528 | /* Executive summary in case the oops scrolled away */ | 535 | /* Executive summary in case the oops scrolled away */ |
529 | printk(KERN_ALERT "RIP "); | 536 | printk(KERN_ALERT "RIP "); |
530 | printk_address(regs->ip); | 537 | printk_address(regs->ip, regs->bp); |
531 | printk(" RSP <%016lx>\n", regs->sp); | 538 | printk(" RSP <%016lx>\n", regs->sp); |
532 | if (kexec_should_crash(current)) | 539 | if (kexec_should_crash(current)) |
533 | crash_kexec(regs); | 540 | crash_kexec(regs); |