Commit 066479e3 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] x86: stack dumps using frame pointers

From: Adam Litke <agl@us.ibm.com>

Teach the x86 stack tracing code to use frame pointers, if they are available.
It eliminates all the false-positives in the normal stack traces.

This is a big improvement, and -fomit-frame-pointer seems to make no
difference at all to generated code size.  Maybe we should kill off
-fomit-frame-pointer.
parent fc4c3ad2
......@@ -94,27 +94,70 @@ asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
void show_trace(struct task_struct *task, unsigned long * stack)
static int valid_stack_ptr(struct task_struct *task, void *p)
{
if (p <= (void *)task->thread_info)
return 0;
if (kstack_end(p))
return 0;
return 1;
}
#ifdef CONFIG_FRAME_POINTER
void print_context_stack(struct task_struct *task, unsigned long *stack,
unsigned long ebp)
{
unsigned long addr;
if (!stack)
stack = (unsigned long*)&stack;
while (valid_stack_ptr(task, (void *)ebp)) {
addr = *(unsigned long *)(ebp + 4);
printk(" [<%08lx>] ", addr);
print_symbol("%s", addr);
printk("\n");
ebp = *(unsigned long *)ebp;
}
}
#else
void print_context_stack(struct task_struct *task, unsigned long *stack,
unsigned long ebp)
{
unsigned long addr;
printk("Call Trace:");
#ifdef CONFIG_KALLSYMS
printk("\n");
while (!kstack_end(stack)) {
addr = *stack++;
if (kernel_text_address(addr)) {
printk(" [<%08lx>] ", addr);
print_symbol("%s\n", addr);
}
}
}
#endif
void show_trace(struct task_struct *task, unsigned long * stack)
{
unsigned long ebp;
if (!task)
task = current;
if (!valid_stack_ptr(task, stack)) {
printk("Stack pointer is garbage, not printing trace\n");
return;
}
if (task == current) {
/* Grab ebp right from our regs */
asm ("movl %%ebp, %0" : "=r" (ebp) : );
} else {
/* ebp is the last reg pushed by switch_to */
ebp = *(unsigned long *) task->thread.esp;
}
while (1) {
struct thread_info *context;
context = (struct thread_info*) ((unsigned long)stack & (~(THREAD_SIZE - 1)));
while (!kstack_end(stack)) {
addr = *stack++;
if (kernel_text_address(addr)) {
printk(" [<%08lx>] ", addr);
print_symbol("%s\n", addr);
}
}
context = (struct thread_info *)
((unsigned long)stack & (~(THREAD_SIZE - 1)));
print_context_stack(task, stack, ebp);
stack = (unsigned long*)context->previous_esp;
if (!stack)
break;
......@@ -143,7 +186,7 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("\n ");
printk("%08lx ", *stack++);
}
printk("\n");
printk("\nCall Trace:\n");
show_trace(task, esp);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment