1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef _SCRIPTS_ELF_PARSE_H
3 #define _SCRIPTS_ELF_PARSE_H
4
5 #include <elf.h>
6
7 #include <tools/be_byteshift.h>
8 #include <tools/le_byteshift.h>
9
10 typedef union {
11 Elf32_Ehdr e32;
12 Elf64_Ehdr e64;
13 } Elf_Ehdr;
14
15 typedef union {
16 Elf32_Shdr e32;
17 Elf64_Shdr e64;
18 } Elf_Shdr;
19
20 typedef union {
21 Elf32_Sym e32;
22 Elf64_Sym e64;
23 } Elf_Sym;
24
25 typedef union {
26 Elf32_Rela e32;
27 Elf64_Rela e64;
28 } Elf_Rela;
29
30 struct elf_funcs {
31 int (*compare_extable)(const void *a, const void *b);
32 uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
33 uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
34 uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
35 uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
36 uint64_t (*shdr_addr)(Elf_Shdr *shdr);
37 uint64_t (*shdr_offset)(Elf_Shdr *shdr);
38 uint64_t (*shdr_size)(Elf_Shdr *shdr);
39 uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
40 uint32_t (*shdr_link)(Elf_Shdr *shdr);
41 uint32_t (*shdr_name)(Elf_Shdr *shdr);
42 uint32_t (*shdr_type)(Elf_Shdr *shdr);
43 uint8_t (*sym_type)(Elf_Sym *sym);
44 uint32_t (*sym_name)(Elf_Sym *sym);
45 uint64_t (*sym_value)(Elf_Sym *sym);
46 uint16_t (*sym_shndx)(Elf_Sym *sym);
47 uint64_t (*rela_offset)(Elf_Rela *rela);
48 uint64_t (*rela_info)(Elf_Rela *rela);
49 uint64_t (*rela_addend)(Elf_Rela *rela);
50 void (*rela_write_addend)(Elf_Rela *rela, uint64_t val);
51 uint32_t (*r)(const uint32_t *);
52 uint16_t (*r2)(const uint16_t *);
53 uint64_t (*r8)(const uint64_t *);
54 void (*w)(uint32_t, uint32_t *);
55 void (*w8)(uint64_t, uint64_t *);
56 };
57
58 extern struct elf_funcs elf_parser;
59
ehdr64_shoff(Elf_Ehdr * ehdr)60 static inline uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
61 {
62 return elf_parser.r8(&ehdr->e64.e_shoff);
63 }
64
ehdr32_shoff(Elf_Ehdr * ehdr)65 static inline uint64_t ehdr32_shoff(Elf_Ehdr *ehdr)
66 {
67 return elf_parser.r(&ehdr->e32.e_shoff);
68 }
69
ehdr_shoff(Elf_Ehdr * ehdr)70 static inline uint64_t ehdr_shoff(Elf_Ehdr *ehdr)
71 {
72 return elf_parser.ehdr_shoff(ehdr);
73 }
74
75 #define EHDR_HALF(fn_name) \
76 static inline uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \
77 { \
78 return elf_parser.r2(&ehdr->e64.e_##fn_name); \
79 } \
80 \
81 static inline uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \
82 { \
83 return elf_parser.r2(&ehdr->e32.e_##fn_name); \
84 } \
85 \
86 static inline uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \
87 { \
88 return elf_parser.ehdr_##fn_name(ehdr); \
89 }
90
91 EHDR_HALF(shentsize)
EHDR_HALF(shstrndx)92 EHDR_HALF(shstrndx)
93 EHDR_HALF(shnum)
94
95 #define SHDR_WORD(fn_name) \
96 static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
97 { \
98 return elf_parser.r(&shdr->e64.sh_##fn_name); \
99 } \
100 \
101 static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
102 { \
103 return elf_parser.r(&shdr->e32.sh_##fn_name); \
104 } \
105 \
106 static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
107 { \
108 return elf_parser.shdr_##fn_name(shdr); \
109 }
110
111 #define SHDR_ADDR(fn_name) \
112 static inline uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \
113 { \
114 return elf_parser.r8(&shdr->e64.sh_##fn_name); \
115 } \
116 \
117 static inline uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \
118 { \
119 return elf_parser.r(&shdr->e32.sh_##fn_name); \
120 } \
121 \
122 static inline uint64_t shdr_##fn_name(Elf_Shdr *shdr) \
123 { \
124 return elf_parser.shdr_##fn_name(shdr); \
125 }
126
127 #define SHDR_WORD(fn_name) \
128 static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
129 { \
130 return elf_parser.r(&shdr->e64.sh_##fn_name); \
131 } \
132 \
133 static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
134 { \
135 return elf_parser.r(&shdr->e32.sh_##fn_name); \
136 } \
137 static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
138 { \
139 return elf_parser.shdr_##fn_name(shdr); \
140 }
141
142 SHDR_ADDR(addr)
143 SHDR_ADDR(offset)
144 SHDR_ADDR(size)
145 SHDR_ADDR(entsize)
146
147 SHDR_WORD(link)
148 SHDR_WORD(name)
149 SHDR_WORD(type)
150
151 #define SYM_ADDR(fn_name) \
152 static inline uint64_t sym64_##fn_name(Elf_Sym *sym) \
153 { \
154 return elf_parser.r8(&sym->e64.st_##fn_name); \
155 } \
156 \
157 static inline uint64_t sym32_##fn_name(Elf_Sym *sym) \
158 { \
159 return elf_parser.r(&sym->e32.st_##fn_name); \
160 } \
161 \
162 static inline uint64_t sym_##fn_name(Elf_Sym *sym) \
163 { \
164 return elf_parser.sym_##fn_name(sym); \
165 }
166
167 #define SYM_WORD(fn_name) \
168 static inline uint32_t sym64_##fn_name(Elf_Sym *sym) \
169 { \
170 return elf_parser.r(&sym->e64.st_##fn_name); \
171 } \
172 \
173 static inline uint32_t sym32_##fn_name(Elf_Sym *sym) \
174 { \
175 return elf_parser.r(&sym->e32.st_##fn_name); \
176 } \
177 \
178 static inline uint32_t sym_##fn_name(Elf_Sym *sym) \
179 { \
180 return elf_parser.sym_##fn_name(sym); \
181 }
182
183 #define SYM_HALF(fn_name) \
184 static inline uint16_t sym64_##fn_name(Elf_Sym *sym) \
185 { \
186 return elf_parser.r2(&sym->e64.st_##fn_name); \
187 } \
188 \
189 static inline uint16_t sym32_##fn_name(Elf_Sym *sym) \
190 { \
191 return elf_parser.r2(&sym->e32.st_##fn_name); \
192 } \
193 \
194 static inline uint16_t sym_##fn_name(Elf_Sym *sym) \
195 { \
196 return elf_parser.sym_##fn_name(sym); \
197 }
198
199 static inline uint8_t sym64_type(Elf_Sym *sym)
200 {
201 return ELF64_ST_TYPE(sym->e64.st_info);
202 }
203
sym32_type(Elf_Sym * sym)204 static inline uint8_t sym32_type(Elf_Sym *sym)
205 {
206 return ELF32_ST_TYPE(sym->e32.st_info);
207 }
208
sym_type(Elf_Sym * sym)209 static inline uint8_t sym_type(Elf_Sym *sym)
210 {
211 return elf_parser.sym_type(sym);
212 }
213
214 SYM_ADDR(value)
SYM_WORD(name)215 SYM_WORD(name)
216 SYM_HALF(shndx)
217
218 #define __maybe_unused __attribute__((__unused__))
219
220 #define RELA_ADDR(fn_name) \
221 static inline uint64_t rela64_##fn_name(Elf_Rela *rela) \
222 { \
223 return elf_parser.r8((uint64_t *)&rela->e64.r_##fn_name); \
224 } \
225 \
226 static inline uint64_t rela32_##fn_name(Elf_Rela *rela) \
227 { \
228 return elf_parser.r((uint32_t *)&rela->e32.r_##fn_name); \
229 } \
230 \
231 static inline uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \
232 { \
233 return elf_parser.rela_##fn_name(rela); \
234 }
235
236 RELA_ADDR(offset)
237 RELA_ADDR(info)
238 RELA_ADDR(addend)
239
240 static inline void rela64_write_addend(Elf_Rela *rela, uint64_t val)
241 {
242 elf_parser.w8(val, (uint64_t *)&rela->e64.r_addend);
243 }
244
rela32_write_addend(Elf_Rela * rela,uint64_t val)245 static inline void rela32_write_addend(Elf_Rela *rela, uint64_t val)
246 {
247 elf_parser.w(val, (uint32_t *)&rela->e32.r_addend);
248 }
249
rbe(const uint32_t * x)250 static inline uint32_t rbe(const uint32_t *x)
251 {
252 return get_unaligned_be32(x);
253 }
254
r2be(const uint16_t * x)255 static inline uint16_t r2be(const uint16_t *x)
256 {
257 return get_unaligned_be16(x);
258 }
259
r8be(const uint64_t * x)260 static inline uint64_t r8be(const uint64_t *x)
261 {
262 return get_unaligned_be64(x);
263 }
264
rle(const uint32_t * x)265 static inline uint32_t rle(const uint32_t *x)
266 {
267 return get_unaligned_le32(x);
268 }
269
r2le(const uint16_t * x)270 static inline uint16_t r2le(const uint16_t *x)
271 {
272 return get_unaligned_le16(x);
273 }
274
r8le(const uint64_t * x)275 static inline uint64_t r8le(const uint64_t *x)
276 {
277 return get_unaligned_le64(x);
278 }
279
wbe(uint32_t val,uint32_t * x)280 static inline void wbe(uint32_t val, uint32_t *x)
281 {
282 put_unaligned_be32(val, x);
283 }
284
wle(uint32_t val,uint32_t * x)285 static inline void wle(uint32_t val, uint32_t *x)
286 {
287 put_unaligned_le32(val, x);
288 }
289
w8be(uint64_t val,uint64_t * x)290 static inline void w8be(uint64_t val, uint64_t *x)
291 {
292 put_unaligned_be64(val, x);
293 }
294
w8le(uint64_t val,uint64_t * x)295 static inline void w8le(uint64_t val, uint64_t *x)
296 {
297 put_unaligned_le64(val, x);
298 }
299
300 void *elf_map(char const *fname, size_t *size, uint32_t types);
301 void elf_unmap(void *addr, size_t size);
302 int elf_map_machine(void *addr);
303 int elf_map_long_size(void *addr);
304
305 #endif /* _SCRIPTS_ELF_PARSE_H */
306