objtool: Remove instruction::list
[linux-2.6-block.git] / tools / objtool / include / objtool / check.h
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 <objtool/cfi.h>
11 #include <objtool/arch.h>
12
13 struct 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
22 struct 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, *nop;
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
39 #define INSN_CHUNK_BITS         8
40 #define INSN_CHUNK_SIZE         (1 << INSN_CHUNK_BITS)
41 #define INSN_CHUNK_MAX          (INSN_CHUNK_SIZE - 1)
42
43 struct instruction {
44         struct hlist_node hash;
45         struct list_head call_node;
46         struct section *sec;
47         unsigned long offset;
48         unsigned long immediate;
49
50         u8 len;
51         u8 prev_len;
52         u8 type;
53         s8 instr;
54
55         u32 idx                 : INSN_CHUNK_BITS,
56             dead_end            : 1,
57             ignore              : 1,
58             ignore_alts         : 1,
59             hint                : 1,
60             save                : 1,
61             restore             : 1,
62             retpoline_safe      : 1,
63             noendbr             : 1,
64             entry               : 1,
65             visited             : 4,
66             no_reloc            : 1;
67                 /* 10 bit hole */
68
69         struct alt_group *alt_group;
70         struct instruction *jump_dest;
71         struct instruction *first_jump_src;
72         union {
73                 struct symbol *_call_dest;
74                 struct reloc *_jump_table;
75         };
76         struct alternative *alts;
77         struct symbol *sym;
78         struct stack_op *stack_ops;
79         struct cfi_state *cfi;
80 };
81
82 static inline struct symbol *insn_func(struct instruction *insn)
83 {
84         struct symbol *sym = insn->sym;
85
86         if (sym && sym->type != STT_FUNC)
87                 sym = NULL;
88
89         return sym;
90 }
91
92 #define VISITED_BRANCH          0x01
93 #define VISITED_BRANCH_UACCESS  0x02
94 #define VISITED_BRANCH_MASK     0x03
95 #define VISITED_ENTRY           0x04
96
97 static inline bool is_static_jump(struct instruction *insn)
98 {
99         return insn->type == INSN_JUMP_CONDITIONAL ||
100                insn->type == INSN_JUMP_UNCONDITIONAL;
101 }
102
103 static inline bool is_dynamic_jump(struct instruction *insn)
104 {
105         return insn->type == INSN_JUMP_DYNAMIC ||
106                insn->type == INSN_JUMP_DYNAMIC_CONDITIONAL;
107 }
108
109 static inline bool is_jump(struct instruction *insn)
110 {
111         return is_static_jump(insn) || is_dynamic_jump(insn);
112 }
113
114 struct instruction *find_insn(struct objtool_file *file,
115                               struct section *sec, unsigned long offset);
116
117 struct instruction *next_insn_same_sec(struct objtool_file *file, struct instruction *insn);
118
119 #define sec_for_each_insn(file, _sec, insn)                             \
120         for (insn = find_insn(file, _sec, 0);                           \
121              insn && insn->sec == _sec;                                 \
122              insn = next_insn_same_sec(file, insn))
123
124 #endif /* _CHECK_H */