aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/traps_64.c
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-01-30 07:33:07 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:07 -0500
commitbc850d6b374fffd08336996f4b4d3bbd6bf427f6 (patch)
tree1106f4a1718f5ed09625f75c95a8bc06635231de /arch/x86/kernel/traps_64.c
parent3d1f7cae883ce4aac99c661562111a25d52effe0 (diff)
x86: add the capability to print fuzzy backtraces
For enhancing the 32 bit EBP based backtracer, I need the capability for the backtracer to tell it's customer that an entry is either reliable or unreliable, and the backtrace printing code then needs to print the unreliable ones slightly different. This patch adds the basic capability, the next patch will add a user of this capability. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/traps_64.c')
-rw-r--r--arch/x86/kernel/traps_64.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index 37b07d08704..62c4d8f46ee 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)
99int kstack_depth_to_print = 12; 99int kstack_depth_to_print = 12;
100 100
101#ifdef CONFIG_KALLSYMS 101#ifdef CONFIG_KALLSYMS
102void printk_address(unsigned long address) 102void 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
122void printk_address(unsigned long address) 126void 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
217void dump_trace(struct task_struct *tsk, struct pt_regs *regs, 221void 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
334static void print_trace_address(void *data, unsigned long addr) 338static 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
340static const struct stacktrace_ops print_trace_ops = { 344static const struct stacktrace_ops print_trace_ops = {
@@ -345,15 +349,17 @@ static const struct stacktrace_ops print_trace_ops = {
345}; 349};
346 350
347void 351void
348show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack) 352show_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
355static void 360static 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
393void show_stack(struct task_struct *tsk, unsigned long * sp) 399void 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)
401void dump_stack(void) 407void 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
413EXPORT_SYMBOL(dump_stack); 420EXPORT_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);