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 | |
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>
-rw-r--r-- | arch/i386/kernel/traps.c | 22 | ||||
-rw-r--r-- | include/asm-i386/unwind.h | 3 |
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 | ||
92 | static inline int arch_unw_user_mode(const void *info) | 95 | static inline int arch_unw_user_mode(const void *info) |
93 | { | 96 | { |