]>
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 | 34 | struct list_head symbol_list; |
f1974222 MH |
35 | struct list_head reloc_list; |
36 | struct section *base, *reloc; | |
442f04c3 | 37 | struct symbol *sym; |
baa41469 | 38 | Elf_Data *data; |
442f04c3 JP |
39 | char *name; |
40 | int idx; | |
442f04c3 | 41 | unsigned int len; |
c4a33939 | 42 | bool changed, text, rodata, noinstr; |
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 | ||
f1974222 | 61 | struct reloc { |
442f04c3 | 62 | struct list_head list; |
042ba73f | 63 | struct hlist_node hash; |
fb414783 MH |
64 | union { |
65 | GElf_Rela rela; | |
66 | GElf_Rel rel; | |
67 | }; | |
e7c2bc37 | 68 | struct section *sec; |
442f04c3 | 69 | struct symbol *sym; |
042ba73f | 70 | unsigned long offset; |
fdabdd0b | 71 | unsigned int type; |
442f04c3 | 72 | int addend; |
fdabdd0b | 73 | int idx; |
bd98c813 | 74 | bool jump_table_start; |
442f04c3 JP |
75 | }; |
76 | ||
34f7c96d PZ |
77 | #define ELF_HASH_BITS 20 |
78 | ||
442f04c3 JP |
79 | struct elf { |
80 | Elf *elf; | |
81 | GElf_Ehdr ehdr; | |
82 | int fd; | |
2b10be23 | 83 | bool changed; |
442f04c3 JP |
84 | char *name; |
85 | struct list_head sections; | |
34f7c96d PZ |
86 | DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS); |
87 | DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS); | |
88 | DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS); | |
89 | DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS); | |
f1974222 | 90 | DECLARE_HASHTABLE(reloc_hash, ELF_HASH_BITS); |
442f04c3 JP |
91 | }; |
92 | ||
74b873e4 PZ |
93 | #define OFFSET_STRIDE_BITS 4 |
94 | #define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS) | |
95 | #define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1)) | |
96 | ||
53fb6e99 JP |
97 | #define for_offset_range(_offset, _start, _end) \ |
98 | for (_offset = ((_start) & OFFSET_STRIDE_MASK); \ | |
99 | _offset >= ((_start) & OFFSET_STRIDE_MASK) && \ | |
100 | _offset <= ((_end) & OFFSET_STRIDE_MASK); \ | |
74b873e4 PZ |
101 | _offset += OFFSET_STRIDE) |
102 | ||
8b5fa6bc PZ |
103 | static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) |
104 | { | |
74b873e4 PZ |
105 | u32 ol, oh, idx = sec->idx; |
106 | ||
107 | offset &= OFFSET_STRIDE_MASK; | |
108 | ||
109 | ol = offset; | |
963d5669 | 110 | oh = (offset >> 16) >> 16; |
8b5fa6bc PZ |
111 | |
112 | __jhash_mix(ol, oh, idx); | |
113 | ||
114 | return ol; | |
115 | } | |
116 | ||
f1974222 | 117 | static inline u32 reloc_hash(struct reloc *reloc) |
8b5fa6bc | 118 | { |
f1974222 | 119 | return sec_offset_hash(reloc->sec, reloc->offset); |
8b5fa6bc | 120 | } |
442f04c3 | 121 | |
bc359ff2 | 122 | struct elf *elf_open_read(const char *name, int flags); |
894e48ca | 123 | struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr); |
fb414783 | 124 | struct section *elf_create_reloc_section(struct elf *elf, struct section *base, int reltype); |
f1974222 | 125 | void elf_add_reloc(struct elf *elf, struct reloc *reloc); |
fdabdd0b PZ |
126 | int elf_write_insn(struct elf *elf, struct section *sec, |
127 | unsigned long offset, unsigned int len, | |
128 | const char *insn); | |
d832c005 | 129 | int elf_write_reloc(struct elf *elf, struct reloc *reloc); |
2b10be23 | 130 | int elf_write(struct elf *elf); |
894e48ca IM |
131 | void elf_close(struct elf *elf); |
132 | ||
133 | struct section *find_section_by_name(const struct elf *elf, const char *name); | |
7acfe531 | 134 | struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); |
442f04c3 | 135 | struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); |
894e48ca | 136 | struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); |
b490f453 | 137 | struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); |
f1974222 MH |
138 | struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); |
139 | struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, | |
8b5fa6bc | 140 | unsigned long offset, unsigned int len); |
53d20720 | 141 | struct symbol *find_func_containing(struct section *sec, unsigned long offset); |
d832c005 | 142 | int elf_rebuild_reloc_section(struct elf *elf, struct section *sec); |
442f04c3 | 143 | |
baa41469 JP |
144 | #define for_each_sec(file, sec) \ |
145 | list_for_each_entry(sec, &file->elf->sections, list) | |
442f04c3 JP |
146 | |
147 | #endif /* _OBJTOOL_ELF_H */ |