diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/process_32.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/stacktrace.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/traps_32.c | 39 | ||||
-rw-r--r-- | arch/x86/oprofile/backtrace.c | 2 |
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) | |||
379 | void show_regs(struct pt_regs *regs) | 379 | void show_regs(struct pt_regs *regs) |
380 | { | 380 | { |
381 | __show_registers(regs, 1); | 381 | __show_registers(regs, 1); |
382 | show_trace(NULL, regs, ®s->sp); | 382 | show_trace(NULL, regs, ®s->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 | ||
36 | static void save_stack_address_nosched(void *data, unsigned long addr) | 36 | static void |
37 | save_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 | */ |
66 | void save_stack_trace(struct stack_trace *trace) | 67 | void 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 | ||
73 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | 74 | void 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 | ||
152 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | 143 | void 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 | ||
235 | static void | 224 | static void |
236 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | 225 | show_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 | ||
243 | void show_trace(struct task_struct *task, struct pt_regs *regs, | 232 | void 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 | ||
249 | static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | 238 | static 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 | ||
274 | void show_stack(struct task_struct *task, unsigned long *sp) | 263 | void 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) | |||
283 | void dump_stack(void) | 272 | void 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 | ||
295 | EXPORT_SYMBOL(dump_stack); | 290 | EXPORT_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, ®s->sp, KERN_EMERG); | 312 | show_stack_log_lvl(NULL, regs, ®s->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 | } |