diff options
author | Chuck Ebbert <76306.1226@compuserve.com> | 2006-03-23 05:59:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-23 10:38:03 -0500 |
commit | 4d7d8c82c181711d28c8336108330a9121f5ef07 (patch) | |
tree | 2e1537702c1e8447dfbe5b5917333f58f4416c1a /arch/i386/kernel/traps.c | |
parent | b824eb605ccba995fd32c6590aed365f93d48002 (diff) |
[PATCH] i386: multi-column stack backtraces
Print stack backtraces in multiple columns, saving screen space. Number of
columns is configurable and defaults to one so behavior is
backwards-compatible.
Also removes the brackets around addresses when printing more
that one entry per line so they print as:
<address>
instead of:
[<address>]
This helps multiple entries fit better on one line.
Original idea by Dave Jones, taken from x86_64.
Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com>
Signed-off-by: Dave Jones <davej@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index b814dbdcc91e..ee61988f61b5 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -112,12 +112,30 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | |||
112 | p < (void *)tinfo + THREAD_SIZE - 3; | 112 | p < (void *)tinfo + THREAD_SIZE - 3; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void print_addr_and_symbol(unsigned long addr, char *log_lvl) | 115 | /* |
116 | * Print CONFIG_STACK_BACKTRACE_COLS address/symbol entries per line. | ||
117 | */ | ||
118 | static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl, | ||
119 | int printed) | ||
116 | { | 120 | { |
117 | printk(log_lvl); | 121 | if (!printed) |
122 | printk(log_lvl); | ||
123 | |||
124 | #if CONFIG_STACK_BACKTRACE_COLS == 1 | ||
118 | printk(" [<%08lx>] ", addr); | 125 | printk(" [<%08lx>] ", addr); |
126 | #else | ||
127 | printk(" <%08lx> ", addr); | ||
128 | #endif | ||
119 | print_symbol("%s", addr); | 129 | print_symbol("%s", addr); |
120 | printk("\n"); | 130 | |
131 | printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS; | ||
132 | |||
133 | if (printed) | ||
134 | printk(" "); | ||
135 | else | ||
136 | printk("\n"); | ||
137 | |||
138 | return printed; | ||
121 | } | 139 | } |
122 | 140 | ||
123 | static inline unsigned long print_context_stack(struct thread_info *tinfo, | 141 | static inline unsigned long print_context_stack(struct thread_info *tinfo, |
@@ -125,20 +143,24 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, | |||
125 | char *log_lvl) | 143 | char *log_lvl) |
126 | { | 144 | { |
127 | unsigned long addr; | 145 | unsigned long addr; |
146 | int printed = 0; /* nr of entries already printed on current line */ | ||
128 | 147 | ||
129 | #ifdef CONFIG_FRAME_POINTER | 148 | #ifdef CONFIG_FRAME_POINTER |
130 | while (valid_stack_ptr(tinfo, (void *)ebp)) { | 149 | while (valid_stack_ptr(tinfo, (void *)ebp)) { |
131 | addr = *(unsigned long *)(ebp + 4); | 150 | addr = *(unsigned long *)(ebp + 4); |
132 | print_addr_and_symbol(addr, log_lvl); | 151 | printed = print_addr_and_symbol(addr, log_lvl, printed); |
133 | ebp = *(unsigned long *)ebp; | 152 | ebp = *(unsigned long *)ebp; |
134 | } | 153 | } |
135 | #else | 154 | #else |
136 | while (valid_stack_ptr(tinfo, stack)) { | 155 | while (valid_stack_ptr(tinfo, stack)) { |
137 | addr = *stack++; | 156 | addr = *stack++; |
138 | if (__kernel_text_address(addr)) | 157 | if (__kernel_text_address(addr)) |
139 | print_addr_and_symbol(addr, log_lvl); | 158 | printed = print_addr_and_symbol(addr, log_lvl, printed); |
140 | } | 159 | } |
141 | #endif | 160 | #endif |
161 | if (printed) | ||
162 | printk("\n"); | ||
163 | |||
142 | return ebp; | 164 | return ebp; |
143 | } | 165 | } |
144 | 166 | ||