aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-09-26 04:52:34 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:34 -0400
commita32cf3975bed3b84491f8ffeb24abe8c45d86ab0 (patch)
treef327b09bc2b17e66645f1b7b97c3b7ac11133e1b
parent950fee84557416a3427dd404a13addc4be7b3e6c (diff)
[PATCH] i386: Get ebp from unwinder state when continuing fallback backtrace
Cc: jbeulich@novell.com Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r--arch/i386/kernel/traps.c22
-rw-r--r--include/asm-i386/unwind.h3
2 files changed, 17 insertions, 8 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 86fa7e47f301..bdf949c30c7c 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -171,7 +171,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
171 unsigned long *stack, 171 unsigned long *stack,
172 struct stacktrace_ops *ops, void *data) 172 struct stacktrace_ops *ops, void *data)
173{ 173{
174 unsigned long ebp; 174 unsigned long ebp = 0;
175 175
176 if (!task) 176 if (!task)
177 task = current; 177 task = current;
@@ -199,6 +199,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
199 stack = (void *)UNW_SP(&info); 199 stack = (void *)UNW_SP(&info);
200 if (!stack) 200 if (!stack)
201 return; 201 return;
202 ebp = UNW_FP(&info);
202 } else 203 } else
203 ops->warning(data, "Full inexact backtrace again:\n"); 204 ops->warning(data, "Full inexact backtrace again:\n");
204 } else if (call_trace >= 1) 205 } else if (call_trace >= 1)
@@ -207,20 +208,25 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
207 ops->warning(data, "Full inexact backtrace again:\n"); 208 ops->warning(data, "Full inexact backtrace again:\n");
208 } else 209 } else
209 ops->warning(data, "Inexact backtrace:\n"); 210 ops->warning(data, "Inexact backtrace:\n");
210 } else if (!stack) { 211 }
212 if (!stack) {
211 unsigned long dummy; 213 unsigned long dummy;
212 stack = &dummy; 214 stack = &dummy;
213 if (task && task != current) 215 if (task && task != current)
214 stack = (unsigned long *)task->thread.esp; 216 stack = (unsigned long *)task->thread.esp;
215 } 217 }
216 218
217 if (task == current) { 219#ifdef CONFIG_FRAME_POINTER
218 /* Grab ebp right from our regs */ 220 if (!ebp) {
219 asm ("movl %%ebp, %0" : "=r" (ebp) : ); 221 if (task == current) {
220 } else { 222 /* Grab ebp right from our regs */
221 /* ebp is the last reg pushed by switch_to */ 223 asm ("movl %%ebp, %0" : "=r" (ebp) : );
222 ebp = *(unsigned long *) task->thread.esp; 224 } else {
225 /* ebp is the last reg pushed by switch_to */
226 ebp = *(unsigned long *) task->thread.esp;
227 }
223 } 228 }
229#endif
224 230
225 while (1) { 231 while (1) {
226 struct thread_info *context; 232 struct thread_info *context;
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
index 4c1a0b968569..f0ac399bae3c 100644
--- a/include/asm-i386/unwind.h
+++ b/include/asm-i386/unwind.h
@@ -28,6 +28,8 @@ struct unwind_frame_info
28#define FRAME_LINK_OFFSET 0 28#define FRAME_LINK_OFFSET 0
29#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0) 29#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0)
30#define STACK_TOP(tsk) ((tsk)->thread.esp0) 30#define STACK_TOP(tsk) ((tsk)->thread.esp0)
31#else
32#define UNW_FP(frame) ((void)(frame), 0)
31#endif 33#endif
32#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) 34#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1))
33 35
@@ -88,6 +90,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
88 90
89#define UNW_PC(frame) ((void)(frame), 0) 91#define UNW_PC(frame) ((void)(frame), 0)
90#define UNW_SP(frame) ((void)(frame), 0) 92#define UNW_SP(frame) ((void)(frame), 0)
93#define UNW_FP(frame) ((void)(frame), 0)
91 94
92static inline int arch_unw_user_mode(const void *info) 95static inline int arch_unw_user_mode(const void *info)
93{ 96{