0001
0002 #include <linux/sched.h>
0003 #include <linux/ftrace.h>
0004 #include <asm/ptrace.h>
0005 #include <asm/bitops.h>
0006 #include <asm/stacktrace.h>
0007 #include <asm/unwind.h>
0008
0009 unsigned long unwind_get_return_address(struct unwind_state *state)
0010 {
0011 unsigned long addr;
0012
0013 if (unwind_done(state))
0014 return 0;
0015
0016 addr = READ_ONCE_NOCHECK(*state->sp);
0017
0018 return unwind_recover_ret_addr(state, addr, state->sp);
0019 }
0020 EXPORT_SYMBOL_GPL(unwind_get_return_address);
0021
0022 unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
0023 {
0024 return NULL;
0025 }
0026
0027 bool unwind_next_frame(struct unwind_state *state)
0028 {
0029 struct stack_info *info = &state->stack_info;
0030
0031 if (unwind_done(state))
0032 return false;
0033
0034 do {
0035 for (state->sp++; state->sp < info->end; state->sp++) {
0036 unsigned long addr = READ_ONCE_NOCHECK(*state->sp);
0037
0038 if (__kernel_text_address(addr))
0039 return true;
0040 }
0041
0042 state->sp = PTR_ALIGN(info->next_sp, sizeof(long));
0043
0044 } while (!get_stack_info(state->sp, state->task, info,
0045 &state->stack_mask));
0046
0047 return false;
0048 }
0049 EXPORT_SYMBOL_GPL(unwind_next_frame);
0050
0051 void __unwind_start(struct unwind_state *state, struct task_struct *task,
0052 struct pt_regs *regs, unsigned long *first_frame)
0053 {
0054 memset(state, 0, sizeof(*state));
0055
0056 state->task = task;
0057 state->sp = PTR_ALIGN(first_frame, sizeof(long));
0058
0059 get_stack_info(first_frame, state->task, &state->stack_info,
0060 &state->stack_mask);
0061
0062
0063
0064
0065
0066
0067 if (!unwind_done(state) &&
0068 (!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
0069 !__kernel_text_address(*first_frame)))
0070 unwind_next_frame(state);
0071 }
0072 EXPORT_SYMBOL_GPL(__unwind_start);