1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_X86_UNWIND_H 3 #define _ASM_X86_UNWIND_H 4 5 #include <linux/sched.h> 6 #include <linux/ftrace.h> 7 #include <linux/kprobes.h> 8 #include <linux/rethook.h> 9 #include <asm/ptrace.h> 10 #include <asm/stacktrace.h> 11 12 #define IRET_FRAME_OFFSET (offsetof(struct pt_regs, ip)) 13 #define IRET_FRAME_SIZE (sizeof(struct pt_regs) - IRET_FRAME_OFFSET) 14 15 struct unwind_state { 16 struct stack_info stack_info; 17 unsigned long stack_mask; 18 struct task_struct *task; 19 int graph_idx; 20 #if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK) 21 struct llist_node *kr_cur; 22 #endif 23 bool error; 24 #if defined(CONFIG_UNWINDER_ORC) 25 bool signal, full_regs; 26 unsigned long sp, bp, ip; 27 struct pt_regs *regs, *prev_regs; 28 #elif defined(CONFIG_UNWINDER_FRAME_POINTER) 29 bool got_irq; 30 unsigned long *bp, *orig_sp, ip; 31 /* 32 * If non-NULL: The current frame is incomplete and doesn't contain a 33 * valid BP. When looking for the next frame, use this instead of the 34 * non-existent saved BP. 35 */ 36 unsigned long *next_bp; 37 struct pt_regs *regs; 38 #else 39 unsigned long *sp; 40 #endif 41 }; 42 43 void __unwind_start(struct unwind_state *state, struct task_struct *task, 44 struct pt_regs *regs, unsigned long *first_frame); 45 bool unwind_next_frame(struct unwind_state *state); 46 unsigned long unwind_get_return_address(struct unwind_state *state); 47 unsigned long *unwind_get_return_address_ptr(struct unwind_state *state); 48 49 static inline bool unwind_done(struct unwind_state *state) 50 { 51 return state->stack_info.type == STACK_TYPE_UNKNOWN; 52 } 53 54 static inline bool unwind_error(struct unwind_state *state) 55 { 56 return state->error; 57 } 58 59 static inline 60 void unwind_start(struct unwind_state *state, struct task_struct *task, 61 struct pt_regs *regs, unsigned long *first_frame) 62 { 63 first_frame = first_frame ? : get_stack_pointer(task, regs); 64 65 __unwind_start(state, task, regs, first_frame); 66 } 67 68 #if defined(CONFIG_UNWINDER_ORC) || defined(CONFIG_UNWINDER_FRAME_POINTER) 69 /* 70 * If 'partial' returns true, only the iret frame registers are valid. 71 */ 72 static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state, 73 bool *partial) 74 { 75 if (unwind_done(state)) 76 return NULL; 77 78 if (partial) { 79 #ifdef CONFIG_UNWINDER_ORC 80 *partial = !state->full_regs; 81 #else 82 *partial = false; 83 #endif 84 } 85 86 return state->regs; 87 } 88 #else 89 static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state, 90 bool *partial) 91 { 92 return NULL; 93 } 94 #endif 95 96 #ifdef CONFIG_UNWINDER_ORC 97 void unwind_init(void); 98 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size, 99 void *orc, size_t orc_size); 100 #else 101 static inline void unwind_init(void) {} 102 static inline 103 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size, 104 void *orc, size_t orc_size) {} 105 #endif 106 107 static inline 108 unsigned long unwind_recover_kretprobe(struct unwind_state *state, 109 unsigned long addr, unsigned long *addr_p) 110 { 111 #ifdef CONFIG_RETHOOK 112 if (is_rethook_trampoline(addr)) 113 return rethook_find_ret_addr(state->task, (unsigned long)addr_p, 114 &state->kr_cur); 115 #endif 116 #ifdef CONFIG_KRETPROBES 117 return is_kretprobe_trampoline(addr) ? 118 kretprobe_find_ret_addr(state->task, addr_p, &state->kr_cur) : 119 addr; 120 #else 121 return addr; 122 #endif 123 } 124 125 /* Recover the return address modified by kretprobe and ftrace_graph. */ 126 static inline 127 unsigned long unwind_recover_ret_addr(struct unwind_state *state, 128 unsigned long addr, unsigned long *addr_p) 129 { 130 unsigned long ret; 131 132 ret = ftrace_graph_ret_addr(state->task, &state->graph_idx, 133 addr, addr_p); 134 return unwind_recover_kretprobe(state, ret, addr_p); 135 } 136 137 /* 138 * This disables KASAN checking when reading a value from another task's stack, 139 * since the other task could be running on another CPU and could have poisoned 140 * the stack in the meantime. 141 */ 142 #define READ_ONCE_TASK_STACK(task, x) \ 143 ({ \ 144 unsigned long val; \ 145 if (task == current) \ 146 val = READ_ONCE(x); \ 147 else \ 148 val = READ_ONCE_NOCHECK(x); \ 149 val; \ 150 }) 151 152 static inline bool task_on_another_cpu(struct task_struct *task) 153 { 154 #ifdef CONFIG_SMP 155 return task != current && task->on_cpu; 156 #else 157 return false; 158 #endif 159 } 160 161 #endif /* _ASM_X86_UNWIND_H */ 162