unwind_prologue.c (429a9671f235c94fc4b5d6687308714b74adc820) unwind_prologue.c (5bb8d34449c4a2eb94d657b992170afafac274f9)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
4 */
5#include <linux/ftrace.h>
6#include <linux/kallsyms.h>
7
8#include <asm/inst.h>

--- 7 unchanged lines hidden (view full) ---

16
17 if (state->pc == ftrace)
18 state->is_ftrace = true;
19#endif
20}
21
22unsigned long unwind_get_return_address(struct unwind_state *state)
23{
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
4 */
5#include <linux/ftrace.h>
6#include <linux/kallsyms.h>
7
8#include <asm/inst.h>

--- 7 unchanged lines hidden (view full) ---

16
17 if (state->pc == ftrace)
18 state->is_ftrace = true;
19#endif
20}
21
22unsigned long unwind_get_return_address(struct unwind_state *state)
23{
24
25 if (unwind_done(state))
26 return 0;
24 if (unwind_done(state))
25 return 0;
27 else if (state->type)
28 return state->pc;
29 else if (state->first)
30 return state->pc;
31
26
32 return *(unsigned long *)(state->sp);
33
27 return state->pc;
34}
35EXPORT_SYMBOL_GPL(unwind_get_return_address);
36
37static bool unwind_by_guess(struct unwind_state *state)
38{
39 struct stack_info *info = &state->stack_info;
40 unsigned long addr;
41
42 for (state->sp += sizeof(unsigned long);
43 state->sp < info->end;
44 state->sp += sizeof(unsigned long)) {
45 addr = *(unsigned long *)(state->sp);
28}
29EXPORT_SYMBOL_GPL(unwind_get_return_address);
30
31static bool unwind_by_guess(struct unwind_state *state)
32{
33 struct stack_info *info = &state->stack_info;
34 unsigned long addr;
35
36 for (state->sp += sizeof(unsigned long);
37 state->sp < info->end;
38 state->sp += sizeof(unsigned long)) {
39 addr = *(unsigned long *)(state->sp);
46 state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
47 addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
48 if (__kernel_text_address(addr))
40 state->pc = unwind_graph_addr(state, addr, state->sp + 8);
41 if (__kernel_text_address(state->pc))
49 return true;
50 }
51
52 return false;
53}
54
55static bool unwind_by_prologue(struct unwind_state *state)
56{

--- 104 unchanged lines hidden (view full) ---

161 } else {
162 state->sp = (unsigned long)__builtin_frame_address(0);
163 state->pc = (unsigned long)__builtin_return_address(0);
164 state->ra = 0;
165 }
166
167 state->task = task;
168 state->first = true;
42 return true;
43 }
44
45 return false;
46}
47
48static bool unwind_by_prologue(struct unwind_state *state)
49{

--- 104 unchanged lines hidden (view full) ---

154 } else {
155 state->sp = (unsigned long)__builtin_frame_address(0);
156 state->pc = (unsigned long)__builtin_return_address(0);
157 state->ra = 0;
158 }
159
160 state->task = task;
161 state->first = true;
169
162 state->pc = unwind_graph_addr(state, state->pc, state->sp);
170 get_stack_info(state->sp, state->task, &state->stack_info);
171
172 if (!unwind_done(state) && !__kernel_text_address(state->pc))
173 unwind_next_frame(state);
174}
175EXPORT_SYMBOL_GPL(unwind_start);
176
177bool unwind_next_frame(struct unwind_state *state)

--- 10 unchanged lines hidden (view full) ---

188 case UNWINDER_GUESS:
189 state->first = false;
190 if (unwind_by_guess(state))
191 return true;
192 break;
193
194 case UNWINDER_PROLOGUE:
195 if (unwind_by_prologue(state)) {
163 get_stack_info(state->sp, state->task, &state->stack_info);
164
165 if (!unwind_done(state) && !__kernel_text_address(state->pc))
166 unwind_next_frame(state);
167}
168EXPORT_SYMBOL_GPL(unwind_start);
169
170bool unwind_next_frame(struct unwind_state *state)

--- 10 unchanged lines hidden (view full) ---

181 case UNWINDER_GUESS:
182 state->first = false;
183 if (unwind_by_guess(state))
184 return true;
185 break;
186
187 case UNWINDER_PROLOGUE:
188 if (unwind_by_prologue(state)) {
196 state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
197 state->pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
189 state->pc = unwind_graph_addr(state, state->pc, state->sp);
198 return true;
199 }
200
201 if (info->type == STACK_TYPE_IRQ &&
202 info->end == state->sp) {
203 regs = (struct pt_regs *)info->next_sp;
204 pc = regs->csr_era;
205
206 if (user_mode(regs) || !__kernel_text_address(pc))
207 return false;
208
209 state->first = true;
210 state->ra = regs->regs[1];
211 state->sp = regs->regs[3];
190 return true;
191 }
192
193 if (info->type == STACK_TYPE_IRQ &&
194 info->end == state->sp) {
195 regs = (struct pt_regs *)info->next_sp;
196 pc = regs->csr_era;
197
198 if (user_mode(regs) || !__kernel_text_address(pc))
199 return false;
200
201 state->first = true;
202 state->ra = regs->regs[1];
203 state->sp = regs->regs[3];
212 state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
213 pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
204 state->pc = pc;
214 get_stack_info(state->sp, state->task, info);
215
216 return true;
217 }
218 }
219
220 state->sp = info->next_sp;
221
222 } while (!get_stack_info(state->sp, state->task, info));
223
224 return false;
225}
226EXPORT_SYMBOL_GPL(unwind_next_frame);
205 get_stack_info(state->sp, state->task, info);
206
207 return true;
208 }
209 }
210
211 state->sp = info->next_sp;
212
213 } while (!get_stack_info(state->sp, state->task, info));
214
215 return false;
216}
217EXPORT_SYMBOL_GPL(unwind_next_frame);