diff options
| -rw-r--r-- | arch/x86/oprofile/backtrace.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c index 75391488130b..a2488b6e27d6 100644 --- a/arch/x86/oprofile/backtrace.c +++ b/arch/x86/oprofile/backtrace.c | |||
| @@ -16,27 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> |
| 18 | #include <asm/stacktrace.h> | 18 | #include <asm/stacktrace.h> |
| 19 | 19 | #include <asm/unwind.h> | |
| 20 | static int backtrace_stack(void *data, const char *name) | ||
| 21 | { | ||
| 22 | /* Yes, we want all stacks */ | ||
| 23 | return 0; | ||
| 24 | } | ||
| 25 | |||
| 26 | static int backtrace_address(void *data, unsigned long addr, int reliable) | ||
| 27 | { | ||
| 28 | unsigned int *depth = data; | ||
| 29 | |||
| 30 | if ((*depth)--) | ||
| 31 | oprofile_add_trace(addr); | ||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | |||
| 35 | static struct stacktrace_ops backtrace_ops = { | ||
| 36 | .stack = backtrace_stack, | ||
| 37 | .address = backtrace_address, | ||
| 38 | .walk_stack = print_context_stack, | ||
| 39 | }; | ||
| 40 | 20 | ||
| 41 | #ifdef CONFIG_COMPAT | 21 | #ifdef CONFIG_COMPAT |
| 42 | static struct stack_frame_ia32 * | 22 | static struct stack_frame_ia32 * |
| @@ -113,14 +93,29 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) | |||
| 113 | struct stack_frame *head = (struct stack_frame *)frame_pointer(regs); | 93 | struct stack_frame *head = (struct stack_frame *)frame_pointer(regs); |
| 114 | 94 | ||
| 115 | if (!user_mode(regs)) { | 95 | if (!user_mode(regs)) { |
| 96 | struct unwind_state state; | ||
| 97 | unsigned long addr; | ||
| 98 | |||
| 116 | if (!depth) | 99 | if (!depth) |
| 117 | return; | 100 | return; |
| 118 | 101 | ||
| 119 | oprofile_add_trace(regs->ip); | 102 | oprofile_add_trace(regs->ip); |
| 103 | |||
| 120 | if (!--depth) | 104 | if (!--depth) |
| 121 | return; | 105 | return; |
| 122 | 106 | ||
| 123 | dump_trace(NULL, regs, NULL, 0, &backtrace_ops, &depth); | 107 | for (unwind_start(&state, current, regs, NULL); |
| 108 | !unwind_done(&state); unwind_next_frame(&state)) { | ||
| 109 | addr = unwind_get_return_address(&state); | ||
| 110 | if (!addr) | ||
| 111 | break; | ||
| 112 | |||
| 113 | oprofile_add_trace(addr); | ||
| 114 | |||
| 115 | if (!--depth) | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | |||
| 124 | return; | 119 | return; |
| 125 | } | 120 | } |
| 126 | 121 | ||
