Commit af5329cdf51cdd208a323e521faa46800a16d2ec
Exists in
master
and in
20 other branches
Merge branch 'core/stacktrace' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'core/stacktrace' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: generic-ipi: powerpc/generic-ipi tree build failure stacktrace: fix build failure on sparc64 stacktrace: export save_stack_trace[_tsk] stacktrace: fix modular build, export print_stack_trace and save_stack_trace backtrace: replace timer with tasklet + completions stacktrace: add saved stack traces to backtrace self-test stacktrace: print_stack_trace() cleanup debugging: make stacktrace independent from DEBUG_KERNEL stacktrace: don't crash on invalid stack trace structs
Showing 11 changed files Side-by-side Diff
- arch/arm/kernel/stacktrace.c
- arch/avr32/kernel/stacktrace.c
- arch/mips/kernel/stacktrace.c
- arch/powerpc/kernel/stacktrace.c
- arch/s390/kernel/stacktrace.c
- arch/sh/kernel/stacktrace.c
- arch/sparc64/kernel/stacktrace.c
- arch/x86/kernel/stacktrace.c
- kernel/backtracetest.c
- kernel/stacktrace.c
- lib/Kconfig.debug
arch/arm/kernel/stacktrace.c
arch/avr32/kernel/stacktrace.c
arch/mips/kernel/stacktrace.c
arch/powerpc/kernel/stacktrace.c
arch/s390/kernel/stacktrace.c
... | ... | @@ -81,6 +81,7 @@ |
81 | 81 | S390_lowcore.thread_info, |
82 | 82 | S390_lowcore.thread_info + THREAD_SIZE, 1); |
83 | 83 | } |
84 | +EXPORT_SYMBOL_GPL(save_stack_trace); | |
84 | 85 | |
85 | 86 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) |
86 | 87 | { |
... | ... | @@ -93,4 +94,5 @@ |
93 | 94 | if (trace->nr_entries < trace->max_entries) |
94 | 95 | trace->entries[trace->nr_entries++] = ULONG_MAX; |
95 | 96 | } |
97 | +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |
arch/sh/kernel/stacktrace.c
arch/sparc64/kernel/stacktrace.c
1 | 1 | #include <linux/sched.h> |
2 | 2 | #include <linux/stacktrace.h> |
3 | 3 | #include <linux/thread_info.h> |
4 | +#include <linux/module.h> | |
4 | 5 | #include <asm/ptrace.h> |
5 | 6 | #include <asm/stacktrace.h> |
6 | 7 | |
... | ... | @@ -47,4 +48,5 @@ |
47 | 48 | trace->entries[trace->nr_entries++] = pc; |
48 | 49 | } while (trace->nr_entries < trace->max_entries); |
49 | 50 | } |
51 | +EXPORT_SYMBOL_GPL(save_stack_trace); |
arch/x86/kernel/stacktrace.c
... | ... | @@ -74,6 +74,7 @@ |
74 | 74 | if (trace->nr_entries < trace->max_entries) |
75 | 75 | trace->entries[trace->nr_entries++] = ULONG_MAX; |
76 | 76 | } |
77 | +EXPORT_SYMBOL_GPL(save_stack_trace); | |
77 | 78 | |
78 | 79 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) |
79 | 80 | { |
... | ... | @@ -81,4 +82,5 @@ |
81 | 82 | if (trace->nr_entries < trace->max_entries) |
82 | 83 | trace->entries[trace->nr_entries++] = ULONG_MAX; |
83 | 84 | } |
85 | +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |
kernel/backtracetest.c
... | ... | @@ -10,30 +10,73 @@ |
10 | 10 | * of the License. |
11 | 11 | */ |
12 | 12 | |
13 | +#include <linux/completion.h> | |
14 | +#include <linux/delay.h> | |
15 | +#include <linux/interrupt.h> | |
13 | 16 | #include <linux/module.h> |
14 | 17 | #include <linux/sched.h> |
15 | -#include <linux/delay.h> | |
18 | +#include <linux/stacktrace.h> | |
16 | 19 | |
17 | -static struct timer_list backtrace_timer; | |
20 | +static void backtrace_test_normal(void) | |
21 | +{ | |
22 | + printk("Testing a backtrace from process context.\n"); | |
23 | + printk("The following trace is a kernel self test and not a bug!\n"); | |
18 | 24 | |
19 | -static void backtrace_test_timer(unsigned long data) | |
25 | + dump_stack(); | |
26 | +} | |
27 | + | |
28 | +static DECLARE_COMPLETION(backtrace_work); | |
29 | + | |
30 | +static void backtrace_test_irq_callback(unsigned long data) | |
20 | 31 | { |
32 | + dump_stack(); | |
33 | + complete(&backtrace_work); | |
34 | +} | |
35 | + | |
36 | +static DECLARE_TASKLET(backtrace_tasklet, &backtrace_test_irq_callback, 0); | |
37 | + | |
38 | +static void backtrace_test_irq(void) | |
39 | +{ | |
21 | 40 | printk("Testing a backtrace from irq context.\n"); |
22 | 41 | printk("The following trace is a kernel self test and not a bug!\n"); |
23 | - dump_stack(); | |
42 | + | |
43 | + init_completion(&backtrace_work); | |
44 | + tasklet_schedule(&backtrace_tasklet); | |
45 | + wait_for_completion(&backtrace_work); | |
24 | 46 | } |
47 | + | |
48 | +#ifdef CONFIG_STACKTRACE | |
49 | +static void backtrace_test_saved(void) | |
50 | +{ | |
51 | + struct stack_trace trace; | |
52 | + unsigned long entries[8]; | |
53 | + | |
54 | + printk("Testing a saved backtrace.\n"); | |
55 | + printk("The following trace is a kernel self test and not a bug!\n"); | |
56 | + | |
57 | + trace.nr_entries = 0; | |
58 | + trace.max_entries = ARRAY_SIZE(entries); | |
59 | + trace.entries = entries; | |
60 | + trace.skip = 0; | |
61 | + | |
62 | + save_stack_trace(&trace); | |
63 | + print_stack_trace(&trace, 0); | |
64 | +} | |
65 | +#else | |
66 | +static void backtrace_test_saved(void) | |
67 | +{ | |
68 | + printk("Saved backtrace test skipped.\n"); | |
69 | +} | |
70 | +#endif | |
71 | + | |
25 | 72 | static int backtrace_regression_test(void) |
26 | 73 | { |
27 | 74 | printk("====[ backtrace testing ]===========\n"); |
28 | - printk("Testing a backtrace from process context.\n"); | |
29 | - printk("The following trace is a kernel self test and not a bug!\n"); | |
30 | - dump_stack(); | |
31 | 75 | |
32 | - init_timer(&backtrace_timer); | |
33 | - backtrace_timer.function = backtrace_test_timer; | |
34 | - mod_timer(&backtrace_timer, jiffies + 10); | |
76 | + backtrace_test_normal(); | |
77 | + backtrace_test_irq(); | |
78 | + backtrace_test_saved(); | |
35 | 79 | |
36 | - msleep(10); | |
37 | 80 | printk("====[ end of backtrace testing ]====\n"); |
38 | 81 | return 0; |
39 | 82 | } |
kernel/stacktrace.c
... | ... | @@ -6,19 +6,21 @@ |
6 | 6 | * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> |
7 | 7 | */ |
8 | 8 | #include <linux/sched.h> |
9 | +#include <linux/module.h> | |
9 | 10 | #include <linux/kallsyms.h> |
10 | 11 | #include <linux/stacktrace.h> |
11 | 12 | |
12 | 13 | void print_stack_trace(struct stack_trace *trace, int spaces) |
13 | 14 | { |
14 | - int i, j; | |
15 | + int i; | |
15 | 16 | |
16 | - for (i = 0; i < trace->nr_entries; i++) { | |
17 | - unsigned long ip = trace->entries[i]; | |
17 | + if (WARN_ON(!trace->entries)) | |
18 | + return; | |
18 | 19 | |
19 | - for (j = 0; j < spaces + 1; j++) | |
20 | - printk(" "); | |
21 | - print_ip_sym(ip); | |
20 | + for (i = 0; i < trace->nr_entries; i++) { | |
21 | + printk("%*c", 1 + spaces, ' '); | |
22 | + print_ip_sym(trace->entries[i]); | |
22 | 23 | } |
23 | 24 | } |
25 | +EXPORT_SYMBOL_GPL(print_stack_trace); |
lib/Kconfig.debug
... | ... | @@ -419,7 +419,6 @@ |
419 | 419 | |
420 | 420 | config STACKTRACE |
421 | 421 | bool |
422 | - depends on DEBUG_KERNEL | |
423 | 422 | depends on STACKTRACE_SUPPORT |
424 | 423 | |
425 | 424 | config DEBUG_KOBJECT |
... | ... | @@ -562,6 +561,9 @@ |
562 | 561 | the kernel stack backtrace code. This option is not useful |
563 | 562 | for distributions or general kernels, but only for kernel |
564 | 563 | developers working on architecture code. |
564 | + | |
565 | + Note that if you want to also test saved backtraces, you will | |
566 | + have to enable STACKTRACE as well. | |
565 | 567 | |
566 | 568 | Say N if you are unsure. |
567 | 569 |