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/string.h>
12 #include <linux/list.h>
13 #include <linux/hashtable.h>
14 #include <linux/rbtree.h>
15 #include <linux/jhash.h>
16
17 #include <objtool/endianness.h>
18 #include <objtool/checksum_types.h>
19 #include <arch/elf.h>
20
21 #define SEC_NAME_LEN 1024
22 #define SYM_NAME_LEN 512
23
24 #define bswap_if_needed(elf, val) __bswap_if_needed(&elf->ehdr, val)
25
26 #ifdef LIBELF_USE_DEPRECATED
27 # define elf_getshdrnum elf_getshnum
28 # define elf_getshdrstrndx elf_getshstrndx
29 #endif
30
31 /*
32 * Fallback for systems without this "read, mmaping if possible" cmd.
33 */
34 #ifndef ELF_C_READ_MMAP
35 #define ELF_C_READ_MMAP ELF_C_READ
36 #endif
37
38 struct elf_hash_node {
39 struct elf_hash_node *next;
40 };
41
42 struct section {
43 struct list_head list;
44 struct elf_hash_node hash;
45 struct elf_hash_node name_hash;
46 GElf_Shdr sh;
47 struct rb_root_cached symbol_tree;
48 struct list_head symbol_list;
49 struct section *base, *rsec;
50 struct symbol *sym;
51 Elf_Data *data;
52 const char *name;
53 int idx;
54 bool _changed, text, rodata, noinstr, init, truncate;
55 struct reloc *relocs;
56 unsigned long nr_alloc_relocs;
57 struct section *twin;
58 };
59
60 struct symbol {
61 struct list_head list;
62 struct list_head global_list;
63 struct rb_node node;
64 struct elf_hash_node hash;
65 struct elf_hash_node name_hash;
66 GElf_Sym sym;
67 struct section *sec;
68 const char *name, *demangled_name;
69 unsigned int idx, len;
70 unsigned long offset;
71 unsigned long __subtree_last;
72 struct symbol *pfunc, *cfunc, *alias, *file;
73 unsigned char bind, type;
74 u8 uaccess_safe : 1;
75 u8 static_call_tramp : 1;
76 u8 retpoline_thunk : 1;
77 u8 return_thunk : 1;
78 u8 fentry : 1;
79 u8 profiling_func : 1;
80 u8 warned : 1;
81 u8 embedded_insn : 1;
82 u8 local_label : 1;
83 u8 frame_pointer : 1;
84 u8 ignore : 1;
85 u8 nocfi : 1;
86 u8 cold : 1;
87 u8 prefix : 1;
88 u8 debug_checksum : 1;
89 u8 changed : 1;
90 u8 included : 1;
91 u8 klp : 1;
92 struct list_head pv_target;
93 struct reloc *relocs;
94 struct section *group_sec;
95 struct checksum csum;
96 struct symbol *twin, *clone;
97 };
98
99 struct reloc {
100 struct elf_hash_node hash;
101 struct section *sec;
102 struct symbol *sym;
103 unsigned long _sym_next_reloc;
104 };
105
106 struct elf {
107 Elf *elf;
108 GElf_Ehdr ehdr;
109 int fd;
110 bool changed;
111 const char *name, *tmp_name;
112 unsigned int num_files;
113 struct list_head sections;
114 struct list_head symbols;
115 unsigned long num_relocs;
116
117 int symbol_bits;
118 int symbol_name_bits;
119 int section_bits;
120 int section_name_bits;
121 int reloc_bits;
122
123 struct elf_hash_node **symbol_hash;
124 struct elf_hash_node **symbol_name_hash;
125 struct elf_hash_node **section_hash;
126 struct elf_hash_node **section_name_hash;
127 struct elf_hash_node **reloc_hash;
128
129 struct section *section_data;
130 struct symbol *symbol_data;
131 };
132
133 struct elf *elf_open_read(const char *name, int flags);
134 struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name);
135
136 struct section *elf_create_section(struct elf *elf, const char *name,
137 size_t size, size_t entsize,
138 unsigned int type, unsigned int align,
139 unsigned int flags);
140 struct section *elf_create_section_pair(struct elf *elf, const char *name,
141 size_t entsize, unsigned int nr,
142 unsigned int reloc_nr);
143
144 struct section *elf_create_rela_section(struct elf *elf, struct section *sec,
145 unsigned int reloc_nr);
146
147 struct symbol *elf_create_symbol(struct elf *elf, const char *name,
148 struct section *sec, unsigned int bind,
149 unsigned int type, unsigned long offset,
150 size_t size);
151 struct symbol *elf_create_section_symbol(struct elf *elf, struct section *sec);
152
153 void *elf_add_data(struct elf *elf, struct section *sec, const void *data,
154 size_t size);
155
156 unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str);
157
158 struct reloc *elf_create_reloc(struct elf *elf, struct section *sec,
159 unsigned long offset, struct symbol *sym,
160 s64 addend, unsigned int type);
161
162 struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
163 unsigned int reloc_idx, unsigned long offset,
164 struct symbol *sym, s64 addend, unsigned int type);
165
166 struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
167 unsigned long offset,
168 unsigned int reloc_idx,
169 struct section *insn_sec,
170 unsigned long insn_off);
171
172 struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
173 unsigned long offset,
174 unsigned int reloc_idx,
175 struct symbol *sym,
176 s64 addend);
177
178 int elf_write_insn(struct elf *elf, struct section *sec, unsigned long offset,
179 unsigned int len, const char *insn);
180
181 int elf_write(struct elf *elf);
182 int elf_close(struct elf *elf);
183
184 struct section *find_section_by_name(const struct elf *elf, const char *name);
185 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
186 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
187 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
188 struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name);
189 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
190 int find_symbol_hole_containing(const struct section *sec, unsigned long offset);
191 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
192 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
193 unsigned long offset, unsigned int len);
194 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
195
196 /*
197 * Try to see if it's a whole archive (vmlinux.o or module).
198 *
199 * Note this will miss the case where a module only has one source file.
200 */
has_multiple_files(struct elf * elf)201 static inline bool has_multiple_files(struct elf *elf)
202 {
203 return elf->num_files > 1;
204 }
205
elf_addr_size(struct elf * elf)206 static inline size_t elf_addr_size(struct elf *elf)
207 {
208 return elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
209 }
210
elf_rela_size(struct elf * elf)211 static inline size_t elf_rela_size(struct elf *elf)
212 {
213 return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
214 }
215
elf_data_rela_type(struct elf * elf)216 static inline unsigned int elf_data_rela_type(struct elf *elf)
217 {
218 return elf_addr_size(elf) == 4 ? R_DATA32 : R_DATA64;
219 }
220
elf_text_rela_type(struct elf * elf)221 static inline unsigned int elf_text_rela_type(struct elf *elf)
222 {
223 return elf_addr_size(elf) == 4 ? R_TEXT32 : R_TEXT64;
224 }
225
is_undef_sym(struct symbol * sym)226 static inline bool is_undef_sym(struct symbol *sym)
227 {
228 return !sym->sec->idx;
229 }
230
is_null_sym(struct symbol * sym)231 static inline bool is_null_sym(struct symbol *sym)
232 {
233 return !sym->idx;
234 }
235
is_sec_sym(struct symbol * sym)236 static inline bool is_sec_sym(struct symbol *sym)
237 {
238 return sym->type == STT_SECTION;
239 }
240
is_object_sym(struct symbol * sym)241 static inline bool is_object_sym(struct symbol *sym)
242 {
243 return sym->type == STT_OBJECT;
244 }
245
is_func_sym(struct symbol * sym)246 static inline bool is_func_sym(struct symbol *sym)
247 {
248 return sym->type == STT_FUNC;
249 }
250
is_file_sym(struct symbol * sym)251 static inline bool is_file_sym(struct symbol *sym)
252 {
253 return sym->type == STT_FILE;
254 }
255
is_notype_sym(struct symbol * sym)256 static inline bool is_notype_sym(struct symbol *sym)
257 {
258 return sym->type == STT_NOTYPE;
259 }
260
is_global_sym(struct symbol * sym)261 static inline bool is_global_sym(struct symbol *sym)
262 {
263 return sym->bind == STB_GLOBAL;
264 }
265
is_weak_sym(struct symbol * sym)266 static inline bool is_weak_sym(struct symbol *sym)
267 {
268 return sym->bind == STB_WEAK;
269 }
270
is_local_sym(struct symbol * sym)271 static inline bool is_local_sym(struct symbol *sym)
272 {
273 return sym->bind == STB_LOCAL;
274 }
275
is_prefix_func(struct symbol * sym)276 static inline bool is_prefix_func(struct symbol *sym)
277 {
278 return sym->prefix;
279 }
280
is_reloc_sec(struct section * sec)281 static inline bool is_reloc_sec(struct section *sec)
282 {
283 return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
284 }
285
is_string_sec(struct section * sec)286 static inline bool is_string_sec(struct section *sec)
287 {
288 return sec->sh.sh_flags & SHF_STRINGS;
289 }
290
is_text_sec(struct section * sec)291 static inline bool is_text_sec(struct section *sec)
292 {
293 return sec->sh.sh_flags & SHF_EXECINSTR;
294 }
295
sec_changed(struct section * sec)296 static inline bool sec_changed(struct section *sec)
297 {
298 return sec->_changed;
299 }
300
mark_sec_changed(struct elf * elf,struct section * sec,bool changed)301 static inline void mark_sec_changed(struct elf *elf, struct section *sec,
302 bool changed)
303 {
304 sec->_changed = changed;
305 elf->changed |= changed;
306 }
307
sec_num_entries(struct section * sec)308 static inline unsigned int sec_num_entries(struct section *sec)
309 {
310 return sec->sh.sh_size / sec->sh.sh_entsize;
311 }
312
reloc_idx(struct reloc * reloc)313 static inline unsigned int reloc_idx(struct reloc *reloc)
314 {
315 return reloc - reloc->sec->relocs;
316 }
317
reloc_rel(struct reloc * reloc)318 static inline void *reloc_rel(struct reloc *reloc)
319 {
320 struct section *rsec = reloc->sec;
321
322 return rsec->data->d_buf + (reloc_idx(reloc) * rsec->sh.sh_entsize);
323 }
324
is_32bit_reloc(struct reloc * reloc)325 static inline bool is_32bit_reloc(struct reloc *reloc)
326 {
327 /*
328 * Elf32_Rel: 8 bytes
329 * Elf32_Rela: 12 bytes
330 * Elf64_Rel: 16 bytes
331 * Elf64_Rela: 24 bytes
332 */
333 return reloc->sec->sh.sh_entsize < 16;
334 }
335
sec_size(struct section * sec)336 static inline unsigned long sec_size(struct section *sec)
337 {
338 return sec->sh.sh_size;
339 }
340
341 #define __get_reloc_field(reloc, field) \
342 ({ \
343 is_32bit_reloc(reloc) ? \
344 ((Elf32_Rela *)reloc_rel(reloc))->field : \
345 ((Elf64_Rela *)reloc_rel(reloc))->field; \
346 })
347
348 #define __set_reloc_field(reloc, field, val) \
349 ({ \
350 if (is_32bit_reloc(reloc)) \
351 ((Elf32_Rela *)reloc_rel(reloc))->field = val; \
352 else \
353 ((Elf64_Rela *)reloc_rel(reloc))->field = val; \
354 })
355
reloc_offset(struct reloc * reloc)356 static inline u64 reloc_offset(struct reloc *reloc)
357 {
358 return __get_reloc_field(reloc, r_offset);
359 }
360
set_reloc_offset(struct elf * elf,struct reloc * reloc,u64 offset)361 static inline void set_reloc_offset(struct elf *elf, struct reloc *reloc, u64 offset)
362 {
363 __set_reloc_field(reloc, r_offset, offset);
364 mark_sec_changed(elf, reloc->sec, true);
365 }
366
reloc_addend(struct reloc * reloc)367 static inline s64 reloc_addend(struct reloc *reloc)
368 {
369 return __get_reloc_field(reloc, r_addend);
370 }
371
set_reloc_addend(struct elf * elf,struct reloc * reloc,s64 addend)372 static inline void set_reloc_addend(struct elf *elf, struct reloc *reloc, s64 addend)
373 {
374 __set_reloc_field(reloc, r_addend, addend);
375 mark_sec_changed(elf, reloc->sec, true);
376 }
377
378
reloc_sym(struct reloc * reloc)379 static inline unsigned int reloc_sym(struct reloc *reloc)
380 {
381 u64 info = __get_reloc_field(reloc, r_info);
382
383 return is_32bit_reloc(reloc) ?
384 ELF32_R_SYM(info) :
385 ELF64_R_SYM(info);
386 }
387
reloc_type(struct reloc * reloc)388 static inline unsigned int reloc_type(struct reloc *reloc)
389 {
390 u64 info = __get_reloc_field(reloc, r_info);
391
392 return is_32bit_reloc(reloc) ?
393 ELF32_R_TYPE(info) :
394 ELF64_R_TYPE(info);
395 }
396
set_reloc_sym(struct elf * elf,struct reloc * reloc,unsigned int sym)397 static inline void set_reloc_sym(struct elf *elf, struct reloc *reloc, unsigned int sym)
398 {
399 u64 info = is_32bit_reloc(reloc) ?
400 ELF32_R_INFO(sym, reloc_type(reloc)) :
401 ELF64_R_INFO(sym, reloc_type(reloc));
402
403 __set_reloc_field(reloc, r_info, info);
404
405 mark_sec_changed(elf, reloc->sec, true);
406 }
set_reloc_type(struct elf * elf,struct reloc * reloc,unsigned int type)407 static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned int type)
408 {
409 u64 info = is_32bit_reloc(reloc) ?
410 ELF32_R_INFO(reloc_sym(reloc), type) :
411 ELF64_R_INFO(reloc_sym(reloc), type);
412
413 __set_reloc_field(reloc, r_info, info);
414
415 mark_sec_changed(elf, reloc->sec, true);
416 }
417
annotype(struct elf * elf,struct section * sec,struct reloc * reloc)418 static inline unsigned int annotype(struct elf *elf, struct section *sec,
419 struct reloc *reloc)
420 {
421 unsigned int type;
422
423 type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * 8) + 4);
424 return bswap_if_needed(elf, type);
425 }
426
427 #define RELOC_JUMP_TABLE_BIT 1UL
428
429 /* Does reloc mark the beginning of a jump table? */
is_jump_table(struct reloc * reloc)430 static inline bool is_jump_table(struct reloc *reloc)
431 {
432 return reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT;
433 }
434
set_jump_table(struct reloc * reloc)435 static inline void set_jump_table(struct reloc *reloc)
436 {
437 reloc->_sym_next_reloc |= RELOC_JUMP_TABLE_BIT;
438 }
439
sym_next_reloc(struct reloc * reloc)440 static inline struct reloc *sym_next_reloc(struct reloc *reloc)
441 {
442 return (struct reloc *)(reloc->_sym_next_reloc & ~RELOC_JUMP_TABLE_BIT);
443 }
444
set_sym_next_reloc(struct reloc * reloc,struct reloc * next)445 static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next)
446 {
447 unsigned long bit = reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT;
448
449 reloc->_sym_next_reloc = (unsigned long)next | bit;
450 }
451
452 #define for_each_sec(elf, sec) \
453 list_for_each_entry(sec, &elf->sections, list)
454
455 #define sec_for_each_sym(sec, sym) \
456 list_for_each_entry(sym, &sec->symbol_list, list)
457
458 #define sec_prev_sym(sym) \
459 sym->sec && sym->list.prev != &sym->sec->symbol_list ? \
460 list_prev_entry(sym, list) : NULL
461
462 #define for_each_sym(elf, sym) \
463 list_for_each_entry(sym, &elf->symbols, global_list)
464
465 #define for_each_sym_continue(elf, sym) \
466 list_for_each_entry_continue(sym, &elf->symbols, global_list)
467
468 #define rsec_next_reloc(rsec, reloc) \
469 reloc_idx(reloc) < sec_num_entries(rsec) - 1 ? reloc + 1 : NULL
470
471 #define for_each_reloc(rsec, reloc) \
472 for (reloc = rsec->relocs; reloc; reloc = rsec_next_reloc(rsec, reloc))
473
474 #define for_each_reloc_from(rsec, reloc) \
475 for (; reloc; reloc = rsec_next_reloc(rsec, reloc))
476
477 #define for_each_reloc_continue(rsec, reloc) \
478 for (reloc = rsec_next_reloc(rsec, reloc); reloc; \
479 reloc = rsec_next_reloc(rsec, reloc))
480
481 #define sym_for_each_reloc(elf, sym, reloc) \
482 for (reloc = find_reloc_by_dest_range(elf, sym->sec, \
483 sym->offset, sym->len); \
484 reloc && reloc_offset(reloc) < sym->offset + sym->len; \
485 reloc = rsec_next_reloc(sym->sec->rsec, reloc))
486
get_func_prefix(struct symbol * func)487 static inline struct symbol *get_func_prefix(struct symbol *func)
488 {
489 struct symbol *prev;
490
491 if (!is_func_sym(func))
492 return NULL;
493
494 prev = sec_prev_sym(func);
495 if (prev && is_prefix_func(prev))
496 return prev;
497
498 return NULL;
499 }
500
501 #define OFFSET_STRIDE_BITS 4
502 #define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS)
503 #define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1))
504
505 #define for_offset_range(_offset, _start, _end) \
506 for (_offset = ((_start) & OFFSET_STRIDE_MASK); \
507 _offset >= ((_start) & OFFSET_STRIDE_MASK) && \
508 _offset <= ((_end) & OFFSET_STRIDE_MASK); \
509 _offset += OFFSET_STRIDE)
510
sec_offset_hash(struct section * sec,unsigned long offset)511 static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
512 {
513 u32 ol, oh, idx = sec->idx;
514
515 offset &= OFFSET_STRIDE_MASK;
516
517 ol = offset;
518 oh = (offset >> 16) >> 16;
519
520 __jhash_mix(ol, oh, idx);
521
522 return ol;
523 }
524
reloc_hash(struct reloc * reloc)525 static inline u32 reloc_hash(struct reloc *reloc)
526 {
527 return sec_offset_hash(reloc->sec, reloc_offset(reloc));
528 }
529
530 #endif /* _OBJTOOL_ELF_H */
531