diff options
Diffstat (limited to 'arch/x86/kernel')
| -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 |
3 files changed, 22 insertions, 26 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 | ||
