[RFC] Smarter stack traces using the frame pointer

Adam Litke
2003-11-04T22:15:40Z

I was working on this for the mjb tree but I thought I'd throw it out
here in case anyone else finds it interesting. This simple change to
the stack trace code uses the frame pointer to do the trace instead of
assuming any kernel address on the stack is a return address. It makes
for much more readable stack traces.

diff -purN linux-2.6.0-test9-virgin/arch/i386/kernel/traps.c linux-2.6.0-test9-stack/arch/i386/kernel/traps.c
--- linux-2.6.0-test9-virgin/arch/i386/kernel/traps.c 2003-11-03 10:34:18.000000000 -0800
+++ linux-2.6.0-test9-stack/arch/i386/kernel/traps.c 2003-11-04 13:51:20.000000000 -0800
@@ -93,17 +93,36 @@ asmlinkage void machine_check(void);

static int kstack_depth_to_print = 24;

-void show_trace(struct task_struct *task, unsigned long * stack)
+#ifdef CONFIG_FRAME_POINTER
+void show_trace_fp(struct task_struct *task)
+{
+ unsigned long addr, ebp;
+
+ 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 (ebp) {
+ addr = *(unsigned long *) (ebp + 4);
+ if (!kernel_text_address(addr))
+ return;
+ printk(" [<%08lx>] ", addr);
+ print_symbol("%s\n", addr);
+ ebp = *(unsigned long *) ebp;
+ }
+}
+#else
+void show_trace_guess(unsigned long * stack)
{
unsigned long addr;

if (!stack)
stack = (unsigned long*)&stack;

- printk("Call Trace:");
-#ifdef CONFIG_KALLSYMS
- printk("\n");
-#endif
while (!kstack_end(stack)) {
addr = *stack++;
if (kernel_text_address(addr)) {
@@ -111,6 +130,20 @@ void show_trace(struct task_struct *task
print_symbol("%s\n", addr);
}
}
+}
+#endif
+
+void show_trace(struct task_struct *task, unsigned long * stack)
+{
+ printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+#ifdef CONFIG_FRAME_POINTER
+ show_trace_fp(task);
+#else
+ show_trace_guess(stack);
+#endif
printk("\n");
}
--
Adam Litke (agl at us.ibm.com)
IBM Linux Technology Center
(503) 578 - 3283 t/l 775 - 3283