[PATCH] i386: Get ebp from unwinder state when continuing fallback backtrace
authorAndi Kleen <ak@suse.de>
Tue, 26 Sep 2006 08:52:34 +0000 (10:52 +0200)
committerAndi Kleen <andi@basil.nowhere.org>
Tue, 26 Sep 2006 08:52:34 +0000 (10:52 +0200)
Cc: jbeulich@novell.com
Signed-off-by: Andi Kleen <ak@suse.de>
arch/i386/kernel/traps.c
include/asm-i386/unwind.h

index 86fa7e47f301a15184a8318b0e313711f1e8b4b4..bdf949c30c7c73ef957e19e224b652b3e5aff540 100644 (file)
@@ -171,7 +171,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                unsigned long *stack,
                struct stacktrace_ops *ops, void *data)
 {
-       unsigned long ebp;
+       unsigned long ebp = 0;
 
        if (!task)
                task = current;
@@ -199,6 +199,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                                        stack = (void *)UNW_SP(&info);
                                        if (!stack)
                                                return;
+                                       ebp = UNW_FP(&info);
                                } else
                                        ops->warning(data, "Full inexact backtrace again:\n");
                        } else if (call_trace >= 1)
@@ -207,20 +208,25 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                                ops->warning(data, "Full inexact backtrace again:\n");
                } else
                        ops->warning(data, "Inexact backtrace:\n");
-       } else  if (!stack) {
+       }
+       if (!stack) {
                unsigned long dummy;
                stack = &dummy;
                if (task && task != current)
                        stack = (unsigned long *)task->thread.esp;
        }
 
-       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;
+#ifdef CONFIG_FRAME_POINTER
+       if (!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;
+               }
        }
+#endif
 
        while (1) {
                struct thread_info *context;
index 4c1a0b968569ef64844d1ad5d159ce7b44141249..f0ac399bae3c9e88204ec4e39c65089fe88835ed 100644 (file)
@@ -28,6 +28,8 @@ struct unwind_frame_info
 #define FRAME_LINK_OFFSET    0
 #define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
 #define STACK_TOP(tsk)       ((tsk)->thread.esp0)
+#else
+#define UNW_FP(frame) ((void)(frame), 0)
 #endif
 #define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
 
@@ -88,6 +90,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
 
 #define UNW_PC(frame) ((void)(frame), 0)
 #define UNW_SP(frame) ((void)(frame), 0)
+#define UNW_FP(frame) ((void)(frame), 0)
 
 static inline int arch_unw_user_mode(const void *info)
 {