diff options
author | Andi Kleen <ak@suse.de> | 2006-09-26 04:52:34 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:34 -0400 |
commit | a32cf3975bed3b84491f8ffeb24abe8c45d86ab0 (patch) | |
tree | f327b09bc2b17e66645f1b7b97c3b7ac11133e1b /arch/i386/kernel/traps.c | |
parent | 950fee84557416a3427dd404a13addc4be7b3e6c (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.c | 22 |
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; |