^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #ifndef _CHECK_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #define _CHECK_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "cfi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "arch.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct insn_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct cfi_state cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) unsigned int uaccess_stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) bool uaccess;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) bool df;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) bool noinstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) s8 instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct instruction {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct hlist_node hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct list_head static_call_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct list_head mcount_loc_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) enum insn_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned long immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) bool dead_end, ignore, ignore_alts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) bool hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) bool retpoline_safe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) s8 instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u8 visited;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u8 ret_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int alt_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct symbol *call_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct instruction *jump_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct instruction *first_jump_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct reloc *jump_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct list_head alts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct list_head stack_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct cfi_state cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #ifdef INSN_USE_ORC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct orc_entry orc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static inline bool is_static_jump(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return insn->type == INSN_JUMP_CONDITIONAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) insn->type == INSN_JUMP_UNCONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static inline bool is_dynamic_jump(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return insn->type == INSN_JUMP_DYNAMIC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) insn->type == INSN_JUMP_DYNAMIC_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static inline bool is_jump(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return is_static_jump(insn) || is_dynamic_jump(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct instruction *find_insn(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct section *sec, unsigned long offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define for_each_insn(file, insn) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) list_for_each_entry(insn, &file->insn_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define sec_for_each_insn(file, sec, insn) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) for (insn = find_insn(file, sec, 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) insn && &insn->list != &file->insn_list && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) insn->sec == sec; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) insn = list_next_entry(insn, list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #endif /* _CHECK_H */