[PATCH] x86_64 stack trace cleanup
From: Andres Salomon
Date: Fri Feb 24 2006 - 05:39:02 EST
Hi,
This patch cleans up the clutter of x86_64 stack traces, making the
output closer to what i386 and sparc64 stack traces look like. It uses
print_symbol instead of resolving the symbols manually, and prints one
frame per line instead of displaying multiple frames per line. I left
the other stuff in the stack dump alone; this affects only the frame
list.
I know this has been brought up before
(http://www.uwsg.iu.edu/hypermail/linux/kernel/0602.0/2238.html,
although I noticed a slight problem w/ that patch, as __print_symbol
returns void); however, for people that don't spend all their time
looking at x86_64 backtraces, I think this consistency shouldn't be
scoffed at. When you switch back and forth between different archs,
x86_64's backtrace is cluttered and confusing in comparison.
With this patch, traces end up looking as follows:
getty S ffff81001e7d1db8 0 3812 1 3814 3811
(NOTLB)
ffff81001e7d1db8 0000000000000008 ffffffff80240323 0000000000001d93
ffff81001f82a2d8 ffff81001f82a0c0 ffff81001f68b0c0
0000000000000000
ffff81001fa841fc ffff81001e7d0000
Call Trace:
[<ffffffff80240323>] do_con_write+0x1853/0x1890
[<ffffffff80164daa>] __pagevec_free+0x2a/0x40
[<ffffffff802e0e55>] schedule_timeout+0x25/0xd0
[<ffffffff80134868>] release_console_sem+0x1a8/0x220
[<ffffffff8014b93c>] add_wait_queue+0x1c/0x60
[<ffffffff8023441f>] read_chan+0x48f/0x6e2
[<ffffffff8012e7e0>] default_wake_function+0x0/0x10
[<ffffffff8022f292>] tty_read+0xa2/0x110
[<ffffffff80185eff>] vfs_read+0xdf/0x1a0
[<ffffffff80186b63>] sys_read+0x53/0x90
[<ffffffff8010afee>] system_call+0x7e/0x83
The old-style trace:
pdflush D ffff810037a417a0 0 4293 11 4294 4292
(L-TLB)
ffff810031fb3d68 0000000000000046 ffff8100107b1d78 0000000000000f60
0000000000000160 ffff810037a419b8 ffff810037a417a0 f
fff810037a40300
ffff810001707d80 ffffffff80146b79
Call Trace:<ffffffff80146b79>{lock_timer_base+41}
<ffffffff8014785d>{__mod_timer+189}
<ffffffff80154690>{keventd_create_kthread+0}
<ffffffff8030f96a>{schedule_timeout+154}
<ffffffff80147110>{process_timeout+0}
<ffffffff8030e621>{__sched_text_start+49}
<ffffffff801fd279>{blk_congestion_wait+153}
<ffffffff80154bc0>{autoremove_wake_function+0}
<ffffffff801b4051>{writeback_inodes+177}
<ffffffff8016d2d5>{background_writeout+165}
<ffffffff8016df40>{pdflush+0} <ffffffff8016e095>{pdflush+341}
Signed-off-by: Andres Salomon <dilinger@xxxxxxxxxx>
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 28d50dc..7598107 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -17,6 +17,7 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <linux/kallsyms.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
@@ -106,30 +107,11 @@ static inline void preempt_conditional_c
static int kstack_depth_to_print = 10;
-#ifdef CONFIG_KALLSYMS
-#include <linux/kallsyms.h>
-int printk_address(unsigned long address)
+void printk_address(unsigned long address)
{
- unsigned long offset = 0, symsize;
- const char *symname;
- char *modname;
- char *delim = ":";
- char namebuf[128];
-
- symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
- if (!symname)
- return printk("[<%016lx>]", address);
- if (!modname)
- modname = delim = "";
- return printk("<%016lx>{%s%s%s%s%+ld}",
- address,delim,modname,delim,symname,offset);
+ printk(" [<%016lx>] ", address);
+ print_symbol("%s\n", address);
}
-#else
-int printk_address(unsigned long address)
-{
- return printk("[<%016lx>]", address);
-}
-#endif
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
unsigned *usedp, const char **idp)
@@ -205,24 +187,23 @@ void show_trace(unsigned long *stack)
printk("\nCall Trace:");
#define HANDLE_STACK(cond) \
- do while (cond) { \
- unsigned long addr = *stack++; \
- if (kernel_text_address(addr)) { \
- if (i > 50) { \
- printk("\n "); \
- i = 0; \
+ do { \
+ i = 0; \
+ printk("\n"); \
+ while (cond) { \
+ unsigned long addr = *stack++; \
+ if (kernel_text_address(addr)) { \
+ /* \
+ * If the address is either in the text segment \
+ * of the kernel, or in the region which \
+ * contains vmalloc'ed memory, it *may* be the \
+ * address of a calling routine; if so, print it \
+ * so that someone tracing down the cause of the \
+ * crash will be able to figure out the call \
+ * path that was taken. \
+ */ \
+ printk_address(addr); \
} \
- else \
- i += printk(" "); \
- /* \
- * If the address is either in the text segment of the \
- * kernel, or in the region which contains vmalloc'ed \
- * memory, it *may* be the address of a calling \
- * routine; if so, print it so that someone tracing \
- * down the cause of the crash will be able to figure \
- * out the call path that was taken. \
- */ \
- i += printk_address(addr); \
} \
} while (0)
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index b9ed4c0..72f5261 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -48,7 +48,7 @@ static inline int notify_die(enum die_va
return notifier_call_chain(&die_chain, val, &args);
}
-extern int printk_address(unsigned long address);
+extern void printk_address(unsigned long address);
extern void die(const char *,struct pt_regs *,long);
extern void __die(const char *,struct pt_regs *,long);
extern void show_registers(struct pt_regs *regs);
Attachment:
signature.asc
Description: This is a digitally signed message part