[PATCH] x86_64: Dump leftover backtrace entries when dwarf2 unwinder got stuck

The dwarf2 unwinder currently often gets stuck because a lot
of assembly code doesn't have proper dwarf2 annotiation yet.

This currently often happens with __down. Should fix this by
adding proper dwarf2 annotation to all inline assembly. However
until that's done we need a quick fix for 2.6.18 to avoid
incomplete backtraces.

So when this happens dump the rest of the stack with the old unwinder
instead of silently not dumping it. There was already a optional
"both" mode that dumped both, but that was too ugly.

I also clarified the headers for the different backtraces a bit.

Also add a clear error message for missing dwarf2
annotation that people can work on.

And I removed a dead variable left over from Ingo's changes.

Cc: mingo@elte.hu
Cc: jbeulich@novell.com
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Andi Kleen and committed by Linus Torvalds b13761ec a4045dff

+16 -6
+16 -6
arch/x86_64/kernel/traps.c
··· 254 254 { 255 255 const unsigned cpu = safe_smp_processor_id(); 256 256 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; 257 - int i = 11; 258 257 unsigned used = 0; 259 258 260 259 printk("\nCall Trace:\n"); ··· 274 275 if (unwind_init_blocked(&info, tsk) == 0) 275 276 unw_ret = show_trace_unwind(&info, NULL); 276 277 } 277 - if (unw_ret > 0) { 278 - if (call_trace > 0) 278 + if (unw_ret > 0 && !arch_unw_user_mode(&info)) { 279 + #ifdef CONFIG_STACK_UNWIND 280 + unsigned long rip = info.regs.rip; 281 + print_symbol("DWARF2 unwinder stuck at %s\n", rip); 282 + if (call_trace == 1) { 283 + printk("Leftover inexact backtrace:\n"); 284 + stack = (unsigned long *)info.regs.rsp; 285 + } else if (call_trace > 1) 279 286 return; 280 - printk("Legacy call trace:"); 281 - i = 18; 287 + else 288 + printk("Full inexact backtrace again:\n"); 289 + #else 290 + printk("Inexact backtrace:\n"); 291 + #endif 282 292 } 283 293 } 284 294 ··· 1126 1118 call_trace = -1; 1127 1119 else if (strcmp(s, "both") == 0) 1128 1120 call_trace = 0; 1129 - else if (strcmp(s, "new") == 0) 1121 + else if (strcmp(s, "newfallback") == 0) 1130 1122 call_trace = 1; 1123 + else if (strcmp(s, "new") == 0) 1124 + call_trace = 2; 1131 1125 return 1; 1132 1126 } 1133 1127 __setup("call_trace=", call_trace_setup);