diff options
Diffstat (limited to 'kernel/trace/trace_stack.c')
| -rw-r--r-- | kernel/trace/trace_stack.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index dc02e29d8255..ea28e4b0ed58 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c | |||
| @@ -20,13 +20,27 @@ | |||
| 20 | 20 | ||
| 21 | #define STACK_TRACE_ENTRIES 500 | 21 | #define STACK_TRACE_ENTRIES 500 |
| 22 | 22 | ||
| 23 | /* | ||
| 24 | * If fentry is used, then the function being traced will | ||
| 25 | * jump to fentry directly before it sets up its stack frame. | ||
| 26 | * We need to ignore that one and record the parent. Since | ||
| 27 | * the stack frame for the traced function wasn't set up yet, | ||
| 28 | * the stack_trace wont see the parent. That needs to be added | ||
| 29 | * manually to stack_dump_trace[] as the first element. | ||
| 30 | */ | ||
| 31 | #ifdef CC_USING_FENTRY | ||
| 32 | # define add_func 1 | ||
| 33 | #else | ||
| 34 | # define add_func 0 | ||
| 35 | #endif | ||
| 36 | |||
| 23 | static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = | 37 | static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = |
| 24 | { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; | 38 | { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; |
| 25 | static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; | 39 | static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; |
| 26 | 40 | ||
| 27 | static struct stack_trace max_stack_trace = { | 41 | static struct stack_trace max_stack_trace = { |
| 28 | .max_entries = STACK_TRACE_ENTRIES, | 42 | .max_entries = STACK_TRACE_ENTRIES - add_func, |
| 29 | .entries = stack_dump_trace, | 43 | .entries = &stack_dump_trace[add_func], |
| 30 | }; | 44 | }; |
| 31 | 45 | ||
| 32 | static unsigned long max_stack_size; | 46 | static unsigned long max_stack_size; |
| @@ -40,7 +54,7 @@ int stack_tracer_enabled; | |||
| 40 | static int last_stack_tracer_enabled; | 54 | static int last_stack_tracer_enabled; |
| 41 | 55 | ||
| 42 | static inline void | 56 | static inline void |
| 43 | check_stack(unsigned long *stack) | 57 | check_stack(unsigned long ip, unsigned long *stack) |
| 44 | { | 58 | { |
| 45 | unsigned long this_size, flags; | 59 | unsigned long this_size, flags; |
| 46 | unsigned long *p, *top, *start; | 60 | unsigned long *p, *top, *start; |
| @@ -71,6 +85,17 @@ check_stack(unsigned long *stack) | |||
| 71 | save_stack_trace(&max_stack_trace); | 85 | save_stack_trace(&max_stack_trace); |
| 72 | 86 | ||
| 73 | /* | 87 | /* |
| 88 | * When fentry is used, the traced function does not get | ||
| 89 | * its stack frame set up, and we lose the parent. | ||
| 90 | * Add that one in manally. We set up save_stack_trace() | ||
| 91 | * to not touch the first element in this case. | ||
| 92 | */ | ||
| 93 | if (add_func) { | ||
| 94 | stack_dump_trace[0] = ip; | ||
| 95 | max_stack_trace.nr_entries++; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 74 | * Now find where in the stack these are. | 99 | * Now find where in the stack these are. |
| 75 | */ | 100 | */ |
| 76 | i = 0; | 101 | i = 0; |
| @@ -124,7 +149,7 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip, | |||
| 124 | if (per_cpu(trace_active, cpu)++ != 0) | 149 | if (per_cpu(trace_active, cpu)++ != 0) |
| 125 | goto out; | 150 | goto out; |
| 126 | 151 | ||
| 127 | check_stack(&stack); | 152 | check_stack(parent_ip, &stack); |
| 128 | 153 | ||
| 129 | out: | 154 | out: |
| 130 | per_cpu(trace_active, cpu)--; | 155 | per_cpu(trace_active, cpu)--; |
