forked from Minki/linux
[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>
This commit is contained in:
parent
b824eb605c
commit
4d7d8c82c1
@ -31,6 +31,15 @@ config DEBUG_STACK_USAGE
|
||||
|
||||
This option will slow down process creation somewhat.
|
||||
|
||||
config STACK_BACKTRACE_COLS
|
||||
int "Stack backtraces per line" if DEBUG_KERNEL
|
||||
range 1 3
|
||||
default 2
|
||||
help
|
||||
Selects how many stack backtrace entries per line to display.
|
||||
|
||||
This can save screen space when displaying traces.
|
||||
|
||||
comment "Page alloc debug is incompatible with Software Suspend on i386"
|
||||
depends on DEBUG_KERNEL && SOFTWARE_SUSPEND
|
||||
|
||||
|
@ -112,12 +112,30 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
|
||||
p < (void *)tinfo + THREAD_SIZE - 3;
|
||||
}
|
||||
|
||||
static void print_addr_and_symbol(unsigned long addr, char *log_lvl)
|
||||
/*
|
||||
* Print CONFIG_STACK_BACKTRACE_COLS address/symbol entries per line.
|
||||
*/
|
||||
static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl,
|
||||
int printed)
|
||||
{
|
||||
printk(log_lvl);
|
||||
if (!printed)
|
||||
printk(log_lvl);
|
||||
|
||||
#if CONFIG_STACK_BACKTRACE_COLS == 1
|
||||
printk(" [<%08lx>] ", addr);
|
||||
#else
|
||||
printk(" <%08lx> ", addr);
|
||||
#endif
|
||||
print_symbol("%s", addr);
|
||||
printk("\n");
|
||||
|
||||
printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS;
|
||||
|
||||
if (printed)
|
||||
printk(" ");
|
||||
else
|
||||
printk("\n");
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
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,
|
||||
char *log_lvl)
|
||||
{
|
||||
unsigned long addr;
|
||||
int printed = 0; /* nr of entries already printed on current line */
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
while (valid_stack_ptr(tinfo, (void *)ebp)) {
|
||||
addr = *(unsigned long *)(ebp + 4);
|
||||
print_addr_and_symbol(addr, log_lvl);
|
||||
printed = print_addr_and_symbol(addr, log_lvl, printed);
|
||||
ebp = *(unsigned long *)ebp;
|
||||
}
|
||||
#else
|
||||
while (valid_stack_ptr(tinfo, stack)) {
|
||||
addr = *stack++;
|
||||
if (__kernel_text_address(addr))
|
||||
print_addr_and_symbol(addr, log_lvl);
|
||||
printed = print_addr_and_symbol(addr, log_lvl, printed);
|
||||
}
|
||||
#endif
|
||||
if (printed)
|
||||
printk("\n");
|
||||
|
||||
return ebp;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user