Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d7d8c82 authored by Chuck Ebbert's avatar Chuck Ebbert Committed by Linus Torvalds
Browse files

[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: default avatarChuck Ebbert <76306.1226@compuserve.com>
Signed-off-by: default avatarDave Jones <davej@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b824eb60
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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

+27 −5
Original line number Diff line number Diff line
@@ -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)
{
	if (!printed)
		printk(log_lvl);

#if CONFIG_STACK_BACKTRACE_COLS == 1
	printk(" [<%08lx>] ", addr);
#else
	printk(" <%08lx> ", addr);
#endif
	print_symbol("%s", addr);

	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;
}