diff options
-rw-r--r-- | include/linux/stacktrace.h | 5 | ||||
-rw-r--r-- | kernel/stacktrace.c | 32 |
2 files changed, 37 insertions, 0 deletions
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h index 115b570e3bff..669045ab73f3 100644 --- a/include/linux/stacktrace.h +++ b/include/linux/stacktrace.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __LINUX_STACKTRACE_H | 1 | #ifndef __LINUX_STACKTRACE_H |
2 | #define __LINUX_STACKTRACE_H | 2 | #define __LINUX_STACKTRACE_H |
3 | 3 | ||
4 | #include <linux/types.h> | ||
5 | |||
4 | struct task_struct; | 6 | struct task_struct; |
5 | struct pt_regs; | 7 | struct pt_regs; |
6 | 8 | ||
@@ -20,6 +22,8 @@ extern void save_stack_trace_tsk(struct task_struct *tsk, | |||
20 | struct stack_trace *trace); | 22 | struct stack_trace *trace); |
21 | 23 | ||
22 | extern void print_stack_trace(struct stack_trace *trace, int spaces); | 24 | extern void print_stack_trace(struct stack_trace *trace, int spaces); |
25 | extern int snprint_stack_trace(char *buf, size_t size, | ||
26 | struct stack_trace *trace, int spaces); | ||
23 | 27 | ||
24 | #ifdef CONFIG_USER_STACKTRACE_SUPPORT | 28 | #ifdef CONFIG_USER_STACKTRACE_SUPPORT |
25 | extern void save_stack_trace_user(struct stack_trace *trace); | 29 | extern void save_stack_trace_user(struct stack_trace *trace); |
@@ -32,6 +36,7 @@ extern void save_stack_trace_user(struct stack_trace *trace); | |||
32 | # define save_stack_trace_tsk(tsk, trace) do { } while (0) | 36 | # define save_stack_trace_tsk(tsk, trace) do { } while (0) |
33 | # define save_stack_trace_user(trace) do { } while (0) | 37 | # define save_stack_trace_user(trace) do { } while (0) |
34 | # define print_stack_trace(trace, spaces) do { } while (0) | 38 | # define print_stack_trace(trace, spaces) do { } while (0) |
39 | # define snprint_stack_trace(buf, size, trace, spaces) do { } while (0) | ||
35 | #endif | 40 | #endif |
36 | 41 | ||
37 | #endif | 42 | #endif |
diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c index 00fe55cc5a82..b6e4c16377c7 100644 --- a/kernel/stacktrace.c +++ b/kernel/stacktrace.c | |||
@@ -25,6 +25,38 @@ void print_stack_trace(struct stack_trace *trace, int spaces) | |||
25 | } | 25 | } |
26 | EXPORT_SYMBOL_GPL(print_stack_trace); | 26 | EXPORT_SYMBOL_GPL(print_stack_trace); |
27 | 27 | ||
28 | int snprint_stack_trace(char *buf, size_t size, | ||
29 | struct stack_trace *trace, int spaces) | ||
30 | { | ||
31 | int i; | ||
32 | unsigned long ip; | ||
33 | int generated; | ||
34 | int total = 0; | ||
35 | |||
36 | if (WARN_ON(!trace->entries)) | ||
37 | return 0; | ||
38 | |||
39 | for (i = 0; i < trace->nr_entries; i++) { | ||
40 | ip = trace->entries[i]; | ||
41 | generated = snprintf(buf, size, "%*c[<%p>] %pS\n", | ||
42 | 1 + spaces, ' ', (void *) ip, (void *) ip); | ||
43 | |||
44 | total += generated; | ||
45 | |||
46 | /* Assume that generated isn't a negative number */ | ||
47 | if (generated >= size) { | ||
48 | buf += size; | ||
49 | size = 0; | ||
50 | } else { | ||
51 | buf += generated; | ||
52 | size -= generated; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | return total; | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(snprint_stack_trace); | ||
59 | |||
28 | /* | 60 | /* |
29 | * Architectures that do not implement save_stack_trace_tsk or | 61 | * Architectures that do not implement save_stack_trace_tsk or |
30 | * save_stack_trace_regs get this weak alias and a once-per-bootup warning | 62 | * save_stack_trace_regs get this weak alias and a once-per-bootup warning |