diff options
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/stacktrace.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/traps_32.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/traps_64.c | 39 | ||||
-rw-r--r-- | arch/x86/mm/fault_64.c | 2 | ||||
-rw-r--r-- | arch/x86/oprofile/backtrace.c | 2 | ||||
-rw-r--r-- | include/asm-x86/kdebug.h | 5 | ||||
-rw-r--r-- | include/asm-x86/stacktrace.h | 5 |
9 files changed, 40 insertions, 29 deletions
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index d2b46b489412..04ca5c5221d7 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -167,7 +167,7 @@ static void dump_leak(void) | |||
167 | iommu_leak_pages); | 167 | iommu_leak_pages); |
168 | for (i = 0; i < iommu_leak_pages; i += 2) { | 168 | for (i = 0; i < iommu_leak_pages; i += 2) { |
169 | printk(KERN_DEBUG "%lu: ", iommu_pages-i); | 169 | printk(KERN_DEBUG "%lu: ", iommu_pages-i); |
170 | printk_address((unsigned long) iommu_leak_tab[iommu_pages-i]); | 170 | printk_address((unsigned long) iommu_leak_tab[iommu_pages-i], 0); |
171 | printk(KERN_CONT "%c", (i+1)%2 == 0 ? '\n' : ' '); | 171 | printk(KERN_CONT "%c", (i+1)%2 == 0 ? '\n' : ' '); |
172 | } | 172 | } |
173 | printk(KERN_DEBUG "\n"); | 173 | printk(KERN_DEBUG "\n"); |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index a0130eb2fa50..383760bfd283 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -329,7 +329,7 @@ void __show_regs(struct pt_regs * regs) | |||
329 | (int)strcspn(init_utsname()->version, " "), | 329 | (int)strcspn(init_utsname()->version, " "), |
330 | init_utsname()->version); | 330 | init_utsname()->version); |
331 | printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); | 331 | printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); |
332 | printk_address(regs->ip); | 332 | printk_address(regs->ip, regs->bp); |
333 | printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp, | 333 | printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp, |
334 | regs->flags); | 334 | regs->flags); |
335 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", | 335 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", |
@@ -377,7 +377,7 @@ void show_regs(struct pt_regs *regs) | |||
377 | { | 377 | { |
378 | printk("CPU %d:", smp_processor_id()); | 378 | printk("CPU %d:", smp_processor_id()); |
379 | __show_regs(regs); | 379 | __show_regs(regs); |
380 | show_trace(NULL, regs, (void *)(regs + 1)); | 380 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); |
381 | } | 381 | } |
382 | 382 | ||
383 | /* | 383 | /* |
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index c571edd11878..8c4e4f5bf040 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c | |||
@@ -22,7 +22,7 @@ static int save_stack_stack(void *data, char *name) | |||
22 | return -1; | 22 | return -1; |
23 | } | 23 | } |
24 | 24 | ||
25 | static void save_stack_address(void *data, unsigned long addr) | 25 | static void save_stack_address(void *data, unsigned long addr, int reliable) |
26 | { | 26 | { |
27 | struct stack_trace *trace = (struct stack_trace *)data; | 27 | struct stack_trace *trace = (struct stack_trace *)data; |
28 | if (trace->skip > 0) { | 28 | if (trace->skip > 0) { |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index acc9af260fac..8ef8a9ddfec6 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
@@ -126,7 +126,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, | |||
126 | 126 | ||
127 | addr = frame->return_address; | 127 | addr = frame->return_address; |
128 | if (__kernel_text_address(addr)) | 128 | if (__kernel_text_address(addr)) |
129 | ops->address(data, addr); | 129 | ops->address(data, addr, 1); |
130 | /* | 130 | /* |
131 | * break out of recursive entries (such as | 131 | * break out of recursive entries (such as |
132 | * end_of_stack_stop_unwind_function). Also, | 132 | * end_of_stack_stop_unwind_function). Also, |
@@ -145,7 +145,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, | |||
145 | 145 | ||
146 | addr = *stack++; | 146 | addr = *stack++; |
147 | if (__kernel_text_address(addr)) | 147 | if (__kernel_text_address(addr)) |
148 | ops->address(data, addr); | 148 | ops->address(data, addr, 1); |
149 | } | 149 | } |
150 | #endif | 150 | #endif |
151 | return bp; | 151 | return bp; |
@@ -220,9 +220,11 @@ static int print_trace_stack(void *data, char *name) | |||
220 | /* | 220 | /* |
221 | * Print one address/symbol entries per line. | 221 | * Print one address/symbol entries per line. |
222 | */ | 222 | */ |
223 | static void print_trace_address(void *data, unsigned long addr) | 223 | static void print_trace_address(void *data, unsigned long addr, int reliable) |
224 | { | 224 | { |
225 | printk("%s [<%08lx>] ", (char *)data, addr); | 225 | printk("%s [<%08lx>] ", (char *)data, addr); |
226 | if (!reliable) | ||
227 | printk("? "); | ||
226 | print_symbol("%s\n", addr); | 228 | print_symbol("%s\n", addr); |
227 | touch_nmi_watchdog(); | 229 | touch_nmi_watchdog(); |
228 | } | 230 | } |
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); |
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index e82832961d72..cf7e99895b91 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c | |||
@@ -578,7 +578,7 @@ no_context: | |||
578 | else | 578 | else |
579 | printk(KERN_ALERT "Unable to handle kernel paging request"); | 579 | printk(KERN_ALERT "Unable to handle kernel paging request"); |
580 | printk(" at %016lx RIP: \n" KERN_ALERT, address); | 580 | printk(" at %016lx RIP: \n" KERN_ALERT, address); |
581 | printk_address(regs->ip); | 581 | printk_address(regs->ip, regs->bp); |
582 | dump_pagetable(address); | 582 | dump_pagetable(address); |
583 | tsk->thread.cr2 = address; | 583 | tsk->thread.cr2 = address; |
584 | tsk->thread.trap_no = 14; | 584 | tsk->thread.trap_no = 14; |
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c index cc353a0b183e..671a7ecf11aa 100644 --- a/arch/x86/oprofile/backtrace.c +++ b/arch/x86/oprofile/backtrace.c | |||
@@ -32,7 +32,7 @@ static int backtrace_stack(void *data, char *name) | |||
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | static void backtrace_address(void *data, unsigned long addr) | 35 | static void backtrace_address(void *data, unsigned long addr, int reliable) |
36 | { | 36 | { |
37 | unsigned int *depth = data; | 37 | unsigned int *depth = data; |
38 | 38 | ||
diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h index e9f42d1ac38f..dd442a1632c0 100644 --- a/include/asm-x86/kdebug.h +++ b/include/asm-x86/kdebug.h | |||
@@ -22,12 +22,13 @@ enum die_val { | |||
22 | DIE_PAGE_FAULT, | 22 | DIE_PAGE_FAULT, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | extern void printk_address(unsigned long address); | 25 | extern void printk_address(unsigned long address, int reliable); |
26 | extern void die(const char *,struct pt_regs *,long); | 26 | extern void die(const char *,struct pt_regs *,long); |
27 | extern int __must_check __die(const char *, struct pt_regs *, long); | 27 | extern int __must_check __die(const char *, struct pt_regs *, long); |
28 | extern void show_registers(struct pt_regs *regs); | 28 | extern void show_registers(struct pt_regs *regs); |
29 | extern void __show_registers(struct pt_regs *, int all); | 29 | extern void __show_registers(struct pt_regs *, int all); |
30 | extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *); | 30 | extern void show_trace(struct task_struct *t, struct pt_regs *regs, |
31 | unsigned long *sp, unsigned long bp); | ||
31 | extern void __show_regs(struct pt_regs *regs); | 32 | extern void __show_regs(struct pt_regs *regs); |
32 | extern void show_regs(struct pt_regs *regs); | 33 | extern void show_regs(struct pt_regs *regs); |
33 | extern void dump_pagetable(unsigned long); | 34 | extern void dump_pagetable(unsigned long); |
diff --git a/include/asm-x86/stacktrace.h b/include/asm-x86/stacktrace.h index 70dd5bae3235..30f82526a8e2 100644 --- a/include/asm-x86/stacktrace.h +++ b/include/asm-x86/stacktrace.h | |||
@@ -9,12 +9,13 @@ struct stacktrace_ops { | |||
9 | void (*warning)(void *data, char *msg); | 9 | void (*warning)(void *data, char *msg); |
10 | /* msg must contain %s for the symbol */ | 10 | /* msg must contain %s for the symbol */ |
11 | void (*warning_symbol)(void *data, char *msg, unsigned long symbol); | 11 | void (*warning_symbol)(void *data, char *msg, unsigned long symbol); |
12 | void (*address)(void *data, unsigned long address); | 12 | void (*address)(void *data, unsigned long address, int reliable); |
13 | /* On negative return stop dumping */ | 13 | /* On negative return stop dumping */ |
14 | int (*stack)(void *data, char *name); | 14 | int (*stack)(void *data, char *name); |
15 | }; | 15 | }; |
16 | 16 | ||
17 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, | 17 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, |
18 | unsigned long *stack, unsigned long bp, | ||
18 | const struct stacktrace_ops *ops, void *data); | 19 | const struct stacktrace_ops *ops, void *data); |
19 | 20 | ||
20 | #endif | 21 | #endif |