diff options
Diffstat (limited to 'arch/x86/kernel/traps_32.c')
-rw-r--r-- | arch/x86/kernel/traps_32.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 959d40edecd..6f3bb287c70 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -120,15 +120,6 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, { struct stack_frame *frame = (struct stack_frame *)bp; - /* - * if EBP is "deeper" into the stack than the actual stack pointer, - * we need to rewind the stack pointer a little to start at the - * first stack frame, but only if EBP is in this stack frame. - */ - if (stack > (unsigned long *) bp - && valid_stack_ptr(tinfo, frame, sizeof(*frame))) - stack = (unsigned long *) bp; - while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { unsigned long addr; @@ -139,7 +130,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, frame = frame->next_frame; bp = (unsigned long) frame; } else { - ops->address(data, addr, 0); + ops->address(data, addr, bp == 0); } } stack++; @@ -150,11 +141,9 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, #define MSG(msg) ops->warning(data, msg) void dump_trace(struct task_struct *task, struct pt_regs *regs, - unsigned long *stack, + unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data) { - unsigned long bp = 0; - if (!task) task = current; @@ -234,20 +223,20 @@ static const struct stacktrace_ops print_trace_ops = { static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, - unsigned long * stack, char *log_lvl) + unsigned long *stack, unsigned long bp, char *log_lvl) { - dump_trace(task, regs, stack, &print_trace_ops, log_lvl); + dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); printk("%s =======================\n", log_lvl); } void show_trace(struct task_struct *task, struct pt_regs *regs, - unsigned long * stack) + unsigned long *stack, unsigned long bp) { - show_trace_log_lvl(task, regs, stack, ""); + show_trace_log_lvl(task, regs, stack, bp, ""); } static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, - unsigned long *sp, char *log_lvl) + unsigned long *sp, unsigned long bp, char *log_lvl) { unsigned long *stack; int i; @@ -268,13 +257,13 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, printk("%08lx ", *stack++); } printk("\n%sCall Trace:\n", log_lvl); - show_trace_log_lvl(task, regs, sp, log_lvl); + show_trace_log_lvl(task, regs, sp, bp, log_lvl); } void show_stack(struct task_struct *task, unsigned long *sp) { printk(" "); - show_stack_log_lvl(task, NULL, sp, ""); + show_stack_log_lvl(task, NULL, sp, 0, ""); } /* @@ -283,13 +272,19 @@ void show_stack(struct task_struct *task, unsigned long *sp) void dump_stack(void) { unsigned long stack; + unsigned long bp = 0; + +#ifdef CONFIG_FRAME_POINTER + if (!bp) + asm("movl %%ebp, %0" : "=r" (bp):); +#endif printk("Pid: %d, comm: %.20s %s %s %.*s\n", current->pid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); - show_trace(current, NULL, &stack); + show_trace(current, NULL, &stack, bp); } EXPORT_SYMBOL(dump_stack); @@ -314,7 +309,7 @@ void show_registers(struct pt_regs *regs) unsigned char c; printk("\n" KERN_EMERG "Stack: "); - show_stack_log_lvl(NULL, regs, ®s->sp, KERN_EMERG); + show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); printk(KERN_EMERG "Code: "); |