diff options
author | Jinyang He <hejinyang@loongson.cn> | 2023-01-17 04:42:16 +0100 |
---|---|---|
committer | Huacai Chen <chenhuacai@loongson.cn> | 2023-01-17 04:42:16 +0100 |
commit | 5bb8d34449c4a2eb94d657b992170afafac274f9 (patch) | |
tree | 4f63968d33455e8d61c205c9e957bf93e02b9cc8 /arch/loongarch/kernel/unwind_guess.c | |
parent | LoongArch: Get frame info in unwind_start() when regs is not available (diff) | |
download | linux-5bb8d34449c4a2eb94d657b992170afafac274f9.tar.xz linux-5bb8d34449c4a2eb94d657b992170afafac274f9.zip |
LoongArch: Use correct sp value to get graph addr in stack unwinders
The stack frame when function_graph enable like follows,
--------- <- function sp_on_entry
|
|
|
FAKE_RA <- sp_on_entry - sizeof(pt_regs) + PT_R1
|
--------- <- sp_on_entry - sizeof(pt_regs)
So if we want to get the &FAKE_RA we should get sp_on_entry first. In
the unwinder_prologue case, we can get the sp_on_entry as state->sp,
because we try to calculate each CFA and the ra saved address. But in
the unwinder_guess case, we cannot get it because we do not try to
calculate the CFA. Although LoongArch have not fixed frame, the $ra is
saved at CFA - 8 in most cases, we can try guess, too. As we store the
pc in state, we not need to dereference state->sp, too.
Signed-off-by: Jinyang He <hejinyang@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/kernel/unwind_guess.c')
-rw-r--r-- | arch/loongarch/kernel/unwind_guess.c | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/unwind_guess.c index 9ef5f2a47f88..e7e637bdba17 100644 --- a/arch/loongarch/kernel/unwind_guess.c +++ b/arch/loongarch/kernel/unwind_guess.c @@ -11,10 +11,8 @@ unsigned long unwind_get_return_address(struct unwind_state *state) { if (unwind_done(state)) return 0; - else if (state->first) - return state->pc; - return *(unsigned long *)(state->sp); + return state->pc; } EXPORT_SYMBOL_GPL(unwind_get_return_address); @@ -36,7 +34,7 @@ void unwind_start(struct unwind_state *state, struct task_struct *task, state->task = task; state->first = true; - + state->pc = unwind_graph_addr(state, state->pc, state->sp); get_stack_info(state->sp, state->task, &state->stack_info); if (!unwind_done(state) && !__kernel_text_address(state->pc)) @@ -60,9 +58,8 @@ bool unwind_next_frame(struct unwind_state *state) state->sp < info->end; state->sp += sizeof(unsigned long)) { addr = *(unsigned long *)(state->sp); - state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx, - addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); - if (__kernel_text_address(addr)) + state->pc = unwind_graph_addr(state, addr, state->sp + 8); + if (__kernel_text_address(state->pc)) return true; } |