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); |