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); ...@@ -94,27 +94,70 @@ asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24; 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; unsigned long addr;
if (!stack) while (valid_stack_ptr(task, (void *)ebp)) {
stack = (unsigned long*)&stack; 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:"); while (!kstack_end(stack)) {
#ifdef CONFIG_KALLSYMS addr = *stack++;
printk("\n"); if (kernel_text_address(addr)) {
printk(" [<%08lx>] ", addr);
print_symbol("%s\n", addr);
}
}
}
#endif #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) { while (1) {
struct thread_info *context; struct thread_info *context;
context = (struct thread_info*) ((unsigned long)stack & (~(THREAD_SIZE - 1))); context = (struct thread_info *)
while (!kstack_end(stack)) { ((unsigned long)stack & (~(THREAD_SIZE - 1)));
addr = *stack++; print_context_stack(task, stack, ebp);
if (kernel_text_address(addr)) {
printk(" [<%08lx>] ", addr);
print_symbol("%s\n", addr);
}
}
stack = (unsigned long*)context->previous_esp; stack = (unsigned long*)context->previous_esp;
if (!stack) if (!stack)
break; break;
...@@ -143,7 +186,7 @@ void show_stack(struct task_struct *task, unsigned long *esp) ...@@ -143,7 +186,7 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("\n "); printk("\n ");
printk("%08lx ", *stack++); printk("%08lx ", *stack++);
} }
printk("\n"); printk("\nCall Trace:\n");
show_trace(task, esp); 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