aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
diff options
context:
space:
mode:
authorChuck Ebbert <76306.1226@compuserve.com>2006-03-23 05:59:30 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 10:38:03 -0500
commit4d7d8c82c181711d28c8336108330a9121f5ef07 (patch)
tree2e1537702c1e8447dfbe5b5917333f58f4416c1a /arch/i386/kernel/traps.c
parentb824eb605ccba995fd32c6590aed365f93d48002 (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.c32
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
115static void print_addr_and_symbol(unsigned long addr, char *log_lvl) 115/*
116 * Print CONFIG_STACK_BACKTRACE_COLS address/symbol entries per line.
117 */
118static 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
123static inline unsigned long print_context_stack(struct thread_info *tinfo, 141static 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