~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/include/asm/unwind.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php