aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-01-30 07:33:07 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:07 -0500
commit5bc27dc2f55fd3043597b5a8de6536183f28a449 (patch)
treedca83b12fb2f01f85a9e31bf1fb3802bd2cfef2a
parente9d4efddbec3d852d435b370b9c40ff7ac24afe6 (diff)
x86: pull bp calculation earlier into the backtrace path
Right now, we take the stack pointer early during the backtrace path, but only calculate bp several functions deep later, making it hard to reconcile the stack and bp backtraces (as well as showing several internal backtrace functions on the stack with bp based backtracing). This patch moves the bp taking to the same place we take the stack pointer; sadly this ripples through several layers of the back tracing stack, but it's not all that bad in the end I hope. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-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 }