1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com> 4 */ 5 6#ifndef _CHECK_H 7#define _CHECK_H 8 9#include <stdbool.h> 10#include "cfi.h" 11#include "arch.h" 12 13struct insn_state { 14 struct cfi_state cfi; 15 unsigned int uaccess_stack; 16 bool uaccess; 17 bool df; 18 bool noinstr; 19 s8 instr; 20}; 21 22struct alt_group { 23 /* 24 * Pointer from a replacement group to the original group. NULL if it 25 * *is* the original group. 26 */ 27 struct alt_group *orig_group; 28 29 /* First and last instructions in the group */ 30 struct instruction *first_insn, *last_insn; 31 32 /* 33 * Byte-offset-addressed len-sized array of pointers to CFI structs. 34 * This is shared with the other alt_groups in the same alternative. 35 */ 36 struct cfi_state **cfi; 37}; 38 39struct instruction { 40 struct list_head list; 41 struct hlist_node hash; 42 struct list_head call_node; 43 struct section *sec; 44 unsigned long offset; 45 unsigned int len; 46 enum insn_type type; 47 unsigned long immediate; 48 bool dead_end, ignore, ignore_alts; 49 bool hint; 50 bool save, restore; 51 bool retpoline_safe; 52 bool entry; 53 s8 instr; 54 u8 visited; 55 struct alt_group *alt_group; 56 struct symbol *call_dest; 57 struct instruction *jump_dest; 58 struct instruction *first_jump_src; 59 struct reloc *jump_table; 60 struct reloc *reloc; 61 struct list_head alts; 62 struct symbol *func; 63 struct list_head stack_ops; 64 struct cfi_state *cfi; 65}; 66 67#define VISITED_BRANCH 0x01 68#define VISITED_BRANCH_UACCESS 0x02 69#define VISITED_BRANCH_MASK 0x03 70#define VISITED_ENTRY 0x04 71 72static inline bool is_static_jump(struct instruction *insn) 73{ 74 return insn->type == INSN_JUMP_CONDITIONAL || 75 insn->type == INSN_JUMP_UNCONDITIONAL; 76} 77 78static inline bool is_dynamic_jump(struct instruction *insn) 79{ 80 return insn->type == INSN_JUMP_DYNAMIC || 81 insn->type == INSN_JUMP_DYNAMIC_CONDITIONAL; 82} 83 84static inline bool is_jump(struct instruction *insn) 85{ 86 return is_static_jump(insn) || is_dynamic_jump(insn); 87} 88 89struct instruction *find_insn(struct objtool_file *file, 90 struct section *sec, unsigned long offset); 91 92#define for_each_insn(file, insn) \ 93 list_for_each_entry(insn, &file->insn_list, list) 94 95#define sec_for_each_insn(file, sec, insn) \ 96 for (insn = find_insn(file, sec, 0); \ 97 insn && &insn->list != &file->insn_list && \ 98 insn->sec == sec; \ 99 insn = list_next_entry(insn, list)) 100 101#endif /* _CHECK_H */ 102