aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
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 /arch/i386/kernel/traps.c
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>
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c22
1 files changed, 14 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;