aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/process_32.c2
-rw-r--r--arch/x86/kernel/stacktrace.c7
-rw-r--r--arch/x86/kernel/traps_32.c39
-rw-r--r--arch/x86/oprofile/backtrace.c2
4 files changed, 23 insertions, 27 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 35a6f318c541..7a61b54649de 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -379,7 +379,7 @@ void __show_registers(struct pt_regs *regs, int all)
379void show_regs(struct pt_regs *regs) 379void show_regs(struct pt_regs *regs)
380{ 380{
381 __show_registers(regs, 1); 381 __show_registers(regs, 1);
382 show_trace(NULL, regs, &regs->sp); 382 show_trace(NULL, regs, &regs->sp, regs->bp);
383} 383}
384 384
385/* 385/*
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 8c4e4f5bf040..4f4021b5bfb5 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -33,7 +33,8 @@ static void save_stack_address(void *data, unsigned long addr, int reliable)
33 trace->entries[trace->nr_entries++] = addr; 33 trace->entries[trace->nr_entries++] = addr;
34} 34}
35 35
36static void save_stack_address_nosched(void *data, unsigned long addr) 36static void
37save_stack_address_nosched(void *data, unsigned long addr, int reliable)
37{ 38{
38 struct stack_trace *trace = (struct stack_trace *)data; 39 struct stack_trace *trace = (struct stack_trace *)data;
39 if (in_sched_functions(addr)) 40 if (in_sched_functions(addr))
@@ -65,14 +66,14 @@ static const struct stacktrace_ops save_stack_ops_nosched = {
65 */ 66 */
66void save_stack_trace(struct stack_trace *trace) 67void save_stack_trace(struct stack_trace *trace)
67{ 68{
68 dump_trace(current, NULL, NULL, &save_stack_ops, trace); 69 dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace);
69 if (trace->nr_entries < trace->max_entries) 70 if (trace->nr_entries < trace->max_entries)
70 trace->entries[trace->nr_entries++] = ULONG_MAX; 71 trace->entries[trace->nr_entries++] = ULONG_MAX;
71} 72}
72 73
73void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 74void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
74{ 75{
75 dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace); 76 dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
76 if (trace->nr_entries < trace->max_entries) 77 if (trace->nr_entries < trace->max_entries)
77 trace->entries[trace->nr_entries++] = ULONG_MAX; 78 trace->entries[trace->nr_entries++] = ULONG_MAX;
78} 79}
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 959d40edecd5..6f3bb287c702 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,
120{ 120{
121 struct stack_frame *frame = (struct stack_frame *)bp; 121 struct stack_frame *frame = (struct stack_frame *)bp;
122 122
123 /*
124 * if EBP is "deeper" into the stack than the actual stack pointer,
125 * we need to rewind the stack pointer a little to start at the
126 * first stack frame, but only if EBP is in this stack frame.
127 */
128 if (stack > (unsigned long *) bp
129 && valid_stack_ptr(tinfo, frame, sizeof(*frame)))
130 stack = (unsigned long *) bp;
131
132 while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { 123 while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) {
133 unsigned long addr; 124 unsigned long addr;
134 125
@@ -139,7 +130,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
139 frame = frame->next_frame; 130 frame = frame->next_frame;
140 bp = (unsigned long) frame; 131 bp = (unsigned long) frame;
141 } else { 132 } else {
142 ops->address(data, addr, 0); 133 ops->address(data, addr, bp == 0);
143 } 134 }
144 } 135 }
145 stack++; 136 stack++;
@@ -150,11 +141,9 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
150#define MSG(msg) ops->warning(data, msg) 141#define MSG(msg) ops->warning(data, msg)
151 142
152void dump_trace(struct task_struct *task, struct pt_regs *regs, 143void dump_trace(struct task_struct *task, struct pt_regs *regs,
153 unsigned long *stack, 144 unsigned long *stack, unsigned long bp,
154 const struct stacktrace_ops *ops, void *data) 145 const struct stacktrace_ops *ops, void *data)
155{ 146{
156 unsigned long bp = 0;
157
158 if (!task) 147 if (!task)
159 task = current; 148 task = current;
160 149
@@ -234,20 +223,20 @@ static const struct stacktrace_ops print_trace_ops = {
234 223
235static void 224static void
236show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, 225show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
237 unsigned long * stack, char *log_lvl) 226 unsigned long *stack, unsigned long bp, char *log_lvl)
238{ 227{
239 dump_trace(task, regs, stack, &print_trace_ops, log_lvl); 228 dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
240 printk("%s =======================\n", log_lvl); 229 printk("%s =======================\n", log_lvl);
241} 230}
242 231
243void show_trace(struct task_struct *task, struct pt_regs *regs, 232void show_trace(struct task_struct *task, struct pt_regs *regs,
244 unsigned long * stack) 233 unsigned long *stack, unsigned long bp)
245{ 234{
246 show_trace_log_lvl(task, regs, stack, ""); 235 show_trace_log_lvl(task, regs, stack, bp, "");
247} 236}
248 237
249static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, 238static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
250 unsigned long *sp, char *log_lvl) 239 unsigned long *sp, unsigned long bp, char *log_lvl)
251{ 240{
252 unsigned long *stack; 241 unsigned long *stack;
253 int i; 242 int i;
@@ -268,13 +257,13 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
268 printk("%08lx ", *stack++); 257 printk("%08lx ", *stack++);
269 } 258 }
270 printk("\n%sCall Trace:\n", log_lvl); 259 printk("\n%sCall Trace:\n", log_lvl);
271 show_trace_log_lvl(task, regs, sp, log_lvl); 260 show_trace_log_lvl(task, regs, sp, bp, log_lvl);
272} 261}
273 262
274void show_stack(struct task_struct *task, unsigned long *sp) 263void show_stack(struct task_struct *task, unsigned long *sp)
275{ 264{
276 printk(" "); 265 printk(" ");
277 show_stack_log_lvl(task, NULL, sp, ""); 266 show_stack_log_lvl(task, NULL, sp, 0, "");
278} 267}
279 268
280/* 269/*
@@ -283,13 +272,19 @@ void show_stack(struct task_struct *task, unsigned long *sp)
283void dump_stack(void) 272void dump_stack(void)
284{ 273{
285 unsigned long stack; 274 unsigned long stack;
275 unsigned long bp = 0;
276
277#ifdef CONFIG_FRAME_POINTER
278 if (!bp)
279 asm("movl %%ebp, %0" : "=r" (bp):);
280#endif
286 281
287 printk("Pid: %d, comm: %.20s %s %s %.*s\n", 282 printk("Pid: %d, comm: %.20s %s %s %.*s\n",
288 current->pid, current->comm, print_tainted(), 283 current->pid, current->comm, print_tainted(),
289 init_utsname()->release, 284 init_utsname()->release,
290 (int)strcspn(init_utsname()->version, " "), 285 (int)strcspn(init_utsname()->version, " "),
291 init_utsname()->version); 286 init_utsname()->version);
292 show_trace(current, NULL, &stack); 287 show_trace(current, NULL, &stack, bp);
293} 288}
294 289
295EXPORT_SYMBOL(dump_stack); 290EXPORT_SYMBOL(dump_stack);
@@ -314,7 +309,7 @@ void show_registers(struct pt_regs *regs)
314 unsigned char c; 309 unsigned char c;
315 310
316 printk("\n" KERN_EMERG "Stack: "); 311 printk("\n" KERN_EMERG "Stack: ");
317 show_stack_log_lvl(NULL, regs, &regs->sp, KERN_EMERG); 312 show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
318 313
319 printk(KERN_EMERG "Code: "); 314 printk(KERN_EMERG "Code: ");
320 315
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index 671a7ecf11aa..0ca4815a2938 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -81,7 +81,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
81 81
82 if (!user_mode_vm(regs)) { 82 if (!user_mode_vm(regs)) {
83 if (depth) 83 if (depth)
84 dump_trace(NULL, regs, (unsigned long *)stack, 84 dump_trace(NULL, regs, (unsigned long *)stack, 0,
85 &backtrace_ops, &depth); 85 &backtrace_ops, &depth);
86 return; 86 return;
87 } 87 }