unwind_prologue.c (5bb8d34449c4a2eb94d657b992170afafac274f9) | unwind_prologue.c (c5ac25e0d78a6f63446b8fef4d8630ccd7a2663d) |
---|---|
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> --- 5 unchanged lines hidden (view full) --- 14#ifdef CONFIG_DYNAMIC_FTRACE 15 static unsigned long ftrace = (unsigned long)ftrace_call + 4; 16 17 if (state->pc == ftrace) 18 state->is_ftrace = true; 19#endif 20} 21 | 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> --- 5 unchanged lines hidden (view full) --- 14#ifdef CONFIG_DYNAMIC_FTRACE 15 static unsigned long ftrace = (unsigned long)ftrace_call + 4; 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 if (unwind_done(state)) 25 return 0; 26 27 return state->pc; 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); 40 state->pc = unwind_graph_addr(state, addr, state->sp + 8); 41 if (__kernel_text_address(state->pc)) 42 return true; 43 } 44 45 return false; 46} 47 | 22/* 23 * LoongArch function prologue is like follows, 24 * [instructions not use stack var] 25 * addi.d sp, sp, -imm 26 * st.d xx, sp, offset <- save callee saved regs and 27 * st.d yy, sp, offset save ra if function is nest. 28 * [others instructions] 29 */ |
48static bool unwind_by_prologue(struct unwind_state *state) 49{ 50 long frame_ra = -1; 51 unsigned long frame_size = 0; 52 unsigned long size, offset, pc; 53 struct pt_regs *regs; 54 struct stack_info *info = &state->stack_info; 55 union loongarch_instruction *ip, *ip_end; --- 30 unchanged lines hidden (view full) --- 86 if (is_stack_alloc_ins(ip)) { 87 frame_size = (1 << 12) - ip->reg2i12_format.immediate; 88 ip++; 89 break; 90 } 91 ip++; 92 } 93 | 30static bool unwind_by_prologue(struct unwind_state *state) 31{ 32 long frame_ra = -1; 33 unsigned long frame_size = 0; 34 unsigned long size, offset, pc; 35 struct pt_regs *regs; 36 struct stack_info *info = &state->stack_info; 37 union loongarch_instruction *ip, *ip_end; --- 30 unchanged lines hidden (view full) --- 68 if (is_stack_alloc_ins(ip)) { 69 frame_size = (1 << 12) - ip->reg2i12_format.immediate; 70 ip++; 71 break; 72 } 73 ip++; 74 } 75 |
76 /* 77 * Can't find stack alloc action, PC may be in a leaf function. Only the 78 * first being true is reasonable, otherwise indicate analysis is broken. 79 */ |
|
94 if (!frame_size) { 95 if (state->first) 96 goto first; 97 98 return false; 99 } 100 101 while (ip < ip_end) { 102 if (is_ra_save_ins(ip)) { 103 frame_ra = ip->reg2i12_format.immediate; 104 break; 105 } 106 if (is_branch_ins(ip)) 107 break; 108 ip++; 109 } 110 | 80 if (!frame_size) { 81 if (state->first) 82 goto first; 83 84 return false; 85 } 86 87 while (ip < ip_end) { 88 if (is_ra_save_ins(ip)) { 89 frame_ra = ip->reg2i12_format.immediate; 90 break; 91 } 92 if (is_branch_ins(ip)) 93 break; 94 ip++; 95 } 96 |
97 /* Can't find save $ra action, PC may be in a leaf function, too. */ |
|
111 if (frame_ra < 0) { 112 if (state->first) { 113 state->sp = state->sp + frame_size; 114 goto first; 115 } 116 return false; 117 } 118 | 98 if (frame_ra < 0) { 99 if (state->first) { 100 state->sp = state->sp + frame_size; 101 goto first; 102 } 103 return false; 104 } 105 |
119 if (state->first) 120 state->first = false; 121 | |
122 state->pc = *(unsigned long *)(state->sp + frame_ra); 123 state->sp = state->sp + frame_size; 124 goto out; 125 126first: | 106 state->pc = *(unsigned long *)(state->sp + frame_ra); 107 state->sp = state->sp + frame_size; 108 goto out; 109 110first: |
127 state->first = false; 128 if (state->pc == state->ra) 129 return false; 130 | |
131 state->pc = state->ra; 132 133out: | 111 state->pc = state->ra; 112 113out: |
114 state->first = false; |
|
134 unwind_state_fixup(state); 135 return !!__kernel_text_address(state->pc); 136} 137 | 115 unwind_state_fixup(state); 116 return !!__kernel_text_address(state->pc); 117} 118 |
138void unwind_start(struct unwind_state *state, struct task_struct *task, 139 struct pt_regs *regs) | 119static bool next_frame(struct unwind_state *state) |
140{ | 120{ |
141 memset(state, 0, sizeof(*state)); 142 state->type = UNWINDER_PROLOGUE; 143 144 if (regs) { 145 state->sp = regs->regs[3]; 146 state->pc = regs->csr_era; 147 state->ra = regs->regs[1]; 148 if (!__kernel_text_address(state->pc)) 149 state->type = UNWINDER_GUESS; 150 } else if (task && task != current) { 151 state->sp = thread_saved_fp(task); 152 state->pc = thread_saved_ra(task); 153 state->ra = 0; 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; 162 state->pc = unwind_graph_addr(state, state->pc, state->sp); 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) 171{ 172 struct stack_info *info = &state->stack_info; 173 struct pt_regs *regs; | |
174 unsigned long pc; | 121 unsigned long pc; |
122 struct pt_regs *regs; 123 struct stack_info *info = &state->stack_info; |
|
175 176 if (unwind_done(state)) 177 return false; 178 179 do { | 124 125 if (unwind_done(state)) 126 return false; 127 128 do { |
180 switch (state->type) { 181 case UNWINDER_GUESS: 182 state->first = false; 183 if (unwind_by_guess(state)) 184 return true; 185 break; | 129 if (unwind_by_prologue(state)) { 130 state->pc = unwind_graph_addr(state, state->pc, state->sp); 131 return true; 132 } |
186 | 133 |
187 case UNWINDER_PROLOGUE: 188 if (unwind_by_prologue(state)) { 189 state->pc = unwind_graph_addr(state, state->pc, state->sp); 190 return true; 191 } | 134 if (info->type == STACK_TYPE_IRQ && info->end == state->sp) { 135 regs = (struct pt_regs *)info->next_sp; 136 pc = regs->csr_era; |
192 | 137 |
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; | 138 if (user_mode(regs) || !__kernel_text_address(pc)) 139 return false; |
197 | 140 |
198 if (user_mode(regs) || !__kernel_text_address(pc)) 199 return false; | 141 state->first = true; 142 state->pc = pc; 143 state->ra = regs->regs[1]; 144 state->sp = regs->regs[3]; 145 get_stack_info(state->sp, state->task, info); |
200 | 146 |
201 state->first = true; 202 state->ra = regs->regs[1]; 203 state->sp = regs->regs[3]; 204 state->pc = pc; 205 get_stack_info(state->sp, state->task, info); 206 207 return true; 208 } | 147 return true; |
209 } 210 211 state->sp = info->next_sp; 212 213 } while (!get_stack_info(state->sp, state->task, info)); 214 215 return false; 216} | 148 } 149 150 state->sp = info->next_sp; 151 152 } while (!get_stack_info(state->sp, state->task, info)); 153 154 return false; 155} |
156 157unsigned long unwind_get_return_address(struct unwind_state *state) 158{ 159 return __unwind_get_return_address(state); 160} 161EXPORT_SYMBOL_GPL(unwind_get_return_address); 162 163void unwind_start(struct unwind_state *state, struct task_struct *task, 164 struct pt_regs *regs) 165{ 166 __unwind_start(state, task, regs); 167 state->type = UNWINDER_PROLOGUE; 168 state->first = true; 169 170 /* 171 * The current PC is not kernel text address, we cannot find its 172 * relative symbol. Thus, prologue analysis will be broken. Luckily, 173 * we can use the default_next_frame(). 174 */ 175 if (!__kernel_text_address(state->pc)) { 176 state->type = UNWINDER_GUESS; 177 if (!unwind_done(state)) 178 unwind_next_frame(state); 179 } 180} 181EXPORT_SYMBOL_GPL(unwind_start); 182 183bool unwind_next_frame(struct unwind_state *state) 184{ 185 return state->type == UNWINDER_PROLOGUE ? 186 next_frame(state) : default_next_frame(state); 187} |
|
217EXPORT_SYMBOL_GPL(unwind_next_frame); | 188EXPORT_SYMBOL_GPL(unwind_next_frame); |