Merge tag 'powerpc-6.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-block.git] / tools / objtool / include / objtool / elf.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
4  */
5
6 #ifndef _OBJTOOL_ELF_H
7 #define _OBJTOOL_ELF_H
8
9 #include <stdio.h>
10 #include <gelf.h>
11 #include <linux/list.h>
12 #include <linux/hashtable.h>
13 #include <linux/rbtree.h>
14 #include <linux/jhash.h>
15
16 #ifdef LIBELF_USE_DEPRECATED
17 # define elf_getshdrnum    elf_getshnum
18 # define elf_getshdrstrndx elf_getshstrndx
19 #endif
20
21 /*
22  * Fallback for systems without this "read, mmaping if possible" cmd.
23  */
24 #ifndef ELF_C_READ_MMAP
25 #define ELF_C_READ_MMAP ELF_C_READ
26 #endif
27
28 struct section {
29         struct list_head list;
30         struct hlist_node hash;
31         struct hlist_node name_hash;
32         GElf_Shdr sh;
33         struct rb_root_cached symbol_tree;
34         struct list_head symbol_list;
35         struct list_head reloc_list;
36         struct section *base, *reloc;
37         struct symbol *sym;
38         Elf_Data *data;
39         char *name;
40         int idx;
41         bool changed, text, rodata, noinstr, init, truncate;
42 };
43
44 struct symbol {
45         struct list_head list;
46         struct rb_node node;
47         struct hlist_node hash;
48         struct hlist_node name_hash;
49         GElf_Sym sym;
50         struct section *sec;
51         char *name;
52         unsigned int idx;
53         unsigned char bind, type;
54         unsigned long offset;
55         unsigned int len;
56         unsigned long __subtree_last;
57         struct symbol *pfunc, *cfunc, *alias;
58         u8 uaccess_safe      : 1;
59         u8 static_call_tramp : 1;
60         u8 retpoline_thunk   : 1;
61         u8 return_thunk      : 1;
62         u8 fentry            : 1;
63         u8 profiling_func    : 1;
64         struct list_head pv_target;
65         struct list_head reloc_list;
66 };
67
68 struct reloc {
69         struct list_head list;
70         struct hlist_node hash;
71         union {
72                 GElf_Rela rela;
73                 GElf_Rel  rel;
74         };
75         struct section *sec;
76         struct symbol *sym;
77         struct list_head sym_reloc_entry;
78         unsigned long offset;
79         unsigned int type;
80         s64 addend;
81         int idx;
82         bool jump_table_start;
83 };
84
85 #define ELF_HASH_BITS   20
86
87 struct elf {
88         Elf *elf;
89         GElf_Ehdr ehdr;
90         int fd;
91         bool changed;
92         char *name;
93         unsigned int text_size, num_files;
94         struct list_head sections;
95
96         int symbol_bits;
97         int symbol_name_bits;
98         int section_bits;
99         int section_name_bits;
100         int reloc_bits;
101
102         struct hlist_head *symbol_hash;
103         struct hlist_head *symbol_name_hash;
104         struct hlist_head *section_hash;
105         struct hlist_head *section_name_hash;
106         struct hlist_head *reloc_hash;
107 };
108
109 #define OFFSET_STRIDE_BITS      4
110 #define OFFSET_STRIDE           (1UL << OFFSET_STRIDE_BITS)
111 #define OFFSET_STRIDE_MASK      (~(OFFSET_STRIDE - 1))
112
113 #define for_offset_range(_offset, _start, _end)                 \
114         for (_offset = ((_start) & OFFSET_STRIDE_MASK);         \
115              _offset >= ((_start) & OFFSET_STRIDE_MASK) &&      \
116              _offset <= ((_end) & OFFSET_STRIDE_MASK);          \
117              _offset += OFFSET_STRIDE)
118
119 static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
120 {
121         u32 ol, oh, idx = sec->idx;
122
123         offset &= OFFSET_STRIDE_MASK;
124
125         ol = offset;
126         oh = (offset >> 16) >> 16;
127
128         __jhash_mix(ol, oh, idx);
129
130         return ol;
131 }
132
133 static inline u32 reloc_hash(struct reloc *reloc)
134 {
135         return sec_offset_hash(reloc->sec, reloc->offset);
136 }
137
138 /*
139  * Try to see if it's a whole archive (vmlinux.o or module).
140  *
141  * Note this will miss the case where a module only has one source file.
142  */
143 static inline bool has_multiple_files(struct elf *elf)
144 {
145         return elf->num_files > 1;
146 }
147
148 static inline int elf_class_addrsize(struct elf *elf)
149 {
150         if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
151                 return sizeof(u32);
152         else
153                 return sizeof(u64);
154 }
155
156 struct elf *elf_open_read(const char *name, int flags);
157 struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
158
159 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size);
160
161 int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
162                   unsigned int type, struct symbol *sym, s64 addend);
163 int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
164                           unsigned long offset, unsigned int type,
165                           struct section *insn_sec, unsigned long insn_off);
166
167 int elf_write_insn(struct elf *elf, struct section *sec,
168                    unsigned long offset, unsigned int len,
169                    const char *insn);
170 int elf_write_reloc(struct elf *elf, struct reloc *reloc);
171 int elf_write(struct elf *elf);
172 void elf_close(struct elf *elf);
173
174 struct section *find_section_by_name(const struct elf *elf, const char *name);
175 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
176 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
177 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
178 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
179 int find_symbol_hole_containing(const struct section *sec, unsigned long offset);
180 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
181 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
182                                      unsigned long offset, unsigned int len);
183 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
184
185 #define for_each_sec(file, sec)                                         \
186         list_for_each_entry(sec, &file->elf->sections, list)
187
188 #endif /* _OBJTOOL_ELF_H */