]>
Commit | Line | Data |
---|---|---|
1ccea77e | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
442f04c3 JP |
2 | /* |
3 | * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> | |
442f04c3 JP |
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> | |
042ba73f | 12 | #include <linux/hashtable.h> |
2a362ecc | 13 | #include <linux/rbtree.h> |
ae358196 | 14 | #include <linux/jhash.h> |
442f04c3 | 15 | |
2e51f262 JB |
16 | #ifdef LIBELF_USE_DEPRECATED |
17 | # define elf_getshdrnum elf_getshnum | |
18 | # define elf_getshdrstrndx elf_getshstrndx | |
19 | #endif | |
20 | ||
627fce14 JP |
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 | ||
442f04c3 JP |
28 | struct section { |
29 | struct list_head list; | |
53038996 | 30 | struct hlist_node hash; |
ae358196 | 31 | struct hlist_node name_hash; |
442f04c3 | 32 | GElf_Shdr sh; |
2a362ecc | 33 | struct rb_root symbol_tree; |
a196e171 JP |
34 | struct list_head symbol_list; |
35 | struct list_head rela_list; | |
442f04c3 JP |
36 | struct section *base, *rela; |
37 | struct symbol *sym; | |
baa41469 | 38 | Elf_Data *data; |
442f04c3 JP |
39 | char *name; |
40 | int idx; | |
442f04c3 | 41 | unsigned int len; |
4a60aa05 | 42 | bool changed, text, rodata; |
442f04c3 JP |
43 | }; |
44 | ||
45 | struct symbol { | |
46 | struct list_head list; | |
2a362ecc | 47 | struct rb_node node; |
042ba73f | 48 | struct hlist_node hash; |
cdb3d057 | 49 | struct hlist_node name_hash; |
442f04c3 JP |
50 | GElf_Sym sym; |
51 | struct section *sec; | |
52 | char *name; | |
042ba73f | 53 | unsigned int idx; |
442f04c3 JP |
54 | unsigned char bind, type; |
55 | unsigned long offset; | |
56 | unsigned int len; | |
09f30d83 | 57 | struct symbol *pfunc, *cfunc, *alias; |
ea24213d | 58 | bool uaccess_safe; |
442f04c3 JP |
59 | }; |
60 | ||
61 | struct rela { | |
62 | struct list_head list; | |
042ba73f | 63 | struct hlist_node hash; |
442f04c3 | 64 | GElf_Rela rela; |
e7c2bc37 | 65 | struct section *sec; |
442f04c3 JP |
66 | struct symbol *sym; |
67 | unsigned int type; | |
042ba73f | 68 | unsigned long offset; |
442f04c3 | 69 | int addend; |
bd98c813 | 70 | bool jump_table_start; |
442f04c3 JP |
71 | }; |
72 | ||
73 | struct elf { | |
74 | Elf *elf; | |
75 | GElf_Ehdr ehdr; | |
76 | int fd; | |
77 | char *name; | |
78 | struct list_head sections; | |
65fb11a7 | 79 | DECLARE_HASHTABLE(symbol_hash, 20); |
cdb3d057 | 80 | DECLARE_HASHTABLE(symbol_name_hash, 20); |
53038996 | 81 | DECLARE_HASHTABLE(section_hash, 16); |
ae358196 | 82 | DECLARE_HASHTABLE(section_name_hash, 16); |
8b5fa6bc | 83 | DECLARE_HASHTABLE(rela_hash, 20); |
442f04c3 JP |
84 | }; |
85 | ||
74b873e4 PZ |
86 | #define OFFSET_STRIDE_BITS 4 |
87 | #define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS) | |
88 | #define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1)) | |
89 | ||
90 | #define for_offset_range(_offset, _start, _end) \ | |
91 | for (_offset = ((_start) & OFFSET_STRIDE_MASK); \ | |
92 | _offset <= ((_end) & OFFSET_STRIDE_MASK); \ | |
93 | _offset += OFFSET_STRIDE) | |
94 | ||
8b5fa6bc PZ |
95 | static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) |
96 | { | |
74b873e4 PZ |
97 | u32 ol, oh, idx = sec->idx; |
98 | ||
99 | offset &= OFFSET_STRIDE_MASK; | |
100 | ||
101 | ol = offset; | |
df2b3843 | 102 | oh = (offset >> 16) >> 16; |
8b5fa6bc PZ |
103 | |
104 | __jhash_mix(ol, oh, idx); | |
105 | ||
106 | return ol; | |
107 | } | |
108 | ||
109 | static inline u32 rela_hash(struct rela *rela) | |
110 | { | |
111 | return sec_offset_hash(rela->sec, rela->offset); | |
112 | } | |
442f04c3 | 113 | |
8e144797 | 114 | struct elf *elf_read(const char *name, int flags); |
442f04c3 | 115 | struct section *find_section_by_name(struct elf *elf, const char *name); |
7acfe531 | 116 | struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); |
442f04c3 | 117 | struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); |
13810435 | 118 | struct symbol *find_symbol_by_name(struct elf *elf, const char *name); |
5c51f4ae | 119 | struct symbol *find_symbol_containing(struct section *sec, unsigned long offset); |
8b5fa6bc PZ |
120 | struct rela *find_rela_by_dest(struct elf *elf, struct section *sec, unsigned long offset); |
121 | struct rela *find_rela_by_dest_range(struct elf *elf, struct section *sec, | |
122 | unsigned long offset, unsigned int len); | |
53d20720 | 123 | struct symbol *find_func_containing(struct section *sec, unsigned long offset); |
627fce14 JP |
124 | struct section *elf_create_section(struct elf *elf, const char *name, size_t |
125 | entsize, int nr); | |
126 | struct section *elf_create_rela_section(struct elf *elf, struct section *base); | |
127 | int elf_rebuild_rela_section(struct section *sec); | |
128 | int elf_write(struct elf *elf); | |
442f04c3 JP |
129 | void elf_close(struct elf *elf); |
130 | ||
baa41469 JP |
131 | #define for_each_sec(file, sec) \ |
132 | list_for_each_entry(sec, &file->elf->sections, list) | |
442f04c3 JP |
133 | |
134 | #endif /* _OBJTOOL_ELF_H */ |