Commit a32cf397 authored by Andi Kleen's avatar Andi Kleen Committed by Andi Kleen

[PATCH] i386: Get ebp from unwinder state when continuing fallback backtrace

Cc: jbeulich@novell.com
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 950fee84
...@@ -171,7 +171,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, ...@@ -171,7 +171,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long *stack,
struct stacktrace_ops *ops, void *data) struct stacktrace_ops *ops, void *data)
{ {
unsigned long ebp; unsigned long ebp = 0;
if (!task) if (!task)
task = current; task = current;
...@@ -199,6 +199,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, ...@@ -199,6 +199,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
stack = (void *)UNW_SP(&info); stack = (void *)UNW_SP(&info);
if (!stack) if (!stack)
return; return;
ebp = UNW_FP(&info);
} else } else
ops->warning(data, "Full inexact backtrace again:\n"); ops->warning(data, "Full inexact backtrace again:\n");
} else if (call_trace >= 1) } else if (call_trace >= 1)
...@@ -207,20 +208,25 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, ...@@ -207,20 +208,25 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
ops->warning(data, "Full inexact backtrace again:\n"); ops->warning(data, "Full inexact backtrace again:\n");
} else } else
ops->warning(data, "Inexact backtrace:\n"); ops->warning(data, "Inexact backtrace:\n");
} else if (!stack) { }
if (!stack) {
unsigned long dummy; unsigned long dummy;
stack = &dummy; stack = &dummy;
if (task && task != current) if (task && task != current)
stack = (unsigned long *)task->thread.esp; stack = (unsigned long *)task->thread.esp;
} }
if (task == current) { #ifdef CONFIG_FRAME_POINTER
/* Grab ebp right from our regs */ if (!ebp) {
asm ("movl %%ebp, %0" : "=r" (ebp) : ); if (task == current) {
} else { /* Grab ebp right from our regs */
/* ebp is the last reg pushed by switch_to */ asm ("movl %%ebp, %0" : "=r" (ebp) : );
ebp = *(unsigned long *) task->thread.esp; } else {
/* ebp is the last reg pushed by switch_to */
ebp = *(unsigned long *) task->thread.esp;
}
} }
#endif
while (1) { while (1) {
struct thread_info *context; struct thread_info *context;
......
...@@ -28,6 +28,8 @@ struct unwind_frame_info ...@@ -28,6 +28,8 @@ struct unwind_frame_info
#define FRAME_LINK_OFFSET 0 #define FRAME_LINK_OFFSET 0
#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0) #define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0)
#define STACK_TOP(tsk) ((tsk)->thread.esp0) #define STACK_TOP(tsk) ((tsk)->thread.esp0)
#else
#define UNW_FP(frame) ((void)(frame), 0)
#endif #endif
#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) #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) ...@@ -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_PC(frame) ((void)(frame), 0)
#define UNW_SP(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) static inline int arch_unw_user_mode(const void *info)
{ {
......
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