xref: /linux/scripts/elf-parse.h (revision 5005f8043c092777b853663845da8facb5eb1385)
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 	uint64_t (*shdr_flags)(Elf_Shdr *shdr);
41 	uint32_t (*shdr_link)(Elf_Shdr *shdr);
42 	uint32_t (*shdr_name)(Elf_Shdr *shdr);
43 	uint32_t (*shdr_type)(Elf_Shdr *shdr);
44 	uint8_t (*sym_type)(Elf_Sym *sym);
45 	uint8_t (*sym_bind)(Elf_Sym *sym);
46 	uint32_t (*sym_name)(Elf_Sym *sym);
47 	uint64_t (*sym_value)(Elf_Sym *sym);
48 	uint16_t (*sym_shndx)(Elf_Sym *sym);
49 	uint64_t (*rela_offset)(Elf_Rela *rela);
50 	uint64_t (*rela_info)(Elf_Rela *rela);
51 	uint64_t (*rela_addend)(Elf_Rela *rela);
52 	void (*rela_write_addend)(Elf_Rela *rela, uint64_t val);
53 	uint32_t (*r)(const uint32_t *);
54 	uint16_t (*r2)(const uint16_t *);
55 	uint64_t (*r8)(const uint64_t *);
56 	void (*w)(uint32_t, uint32_t *);
57 	void (*w8)(uint64_t, uint64_t *);
58 };
59 
60 extern struct elf_funcs elf_parser;
61 
62 static inline uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
63 {
64 	return elf_parser.r8(&ehdr->e64.e_shoff);
65 }
66 
67 static inline uint64_t ehdr32_shoff(Elf_Ehdr *ehdr)
68 {
69 	return elf_parser.r(&ehdr->e32.e_shoff);
70 }
71 
72 static inline uint64_t ehdr_shoff(Elf_Ehdr *ehdr)
73 {
74 	return elf_parser.ehdr_shoff(ehdr);
75 }
76 
77 #define EHDR_HALF(fn_name)				\
78 static inline uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr)	\
79 {							\
80 	return elf_parser.r2(&ehdr->e64.e_##fn_name);	\
81 }							\
82 							\
83 static inline uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr)	\
84 {							\
85 	return elf_parser.r2(&ehdr->e32.e_##fn_name);	\
86 }							\
87 							\
88 static inline uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr)	\
89 {							\
90 	return elf_parser.ehdr_##fn_name(ehdr);		\
91 }
92 
93 EHDR_HALF(shentsize)
94 EHDR_HALF(shstrndx)
95 EHDR_HALF(shnum)
96 
97 #define SHDR_WORD(fn_name)				\
98 static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr)	\
99 {							\
100 	return elf_parser.r(&shdr->e64.sh_##fn_name);	\
101 }							\
102 							\
103 static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr)	\
104 {							\
105 	return elf_parser.r(&shdr->e32.sh_##fn_name);	\
106 }							\
107 							\
108 static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr)	\
109 {							\
110 	return elf_parser.shdr_##fn_name(shdr);	\
111 }
112 
113 #define SHDR_ADDR(fn_name)				\
114 static inline uint64_t shdr64_##fn_name(Elf_Shdr *shdr)	\
115 {							\
116 	return elf_parser.r8(&shdr->e64.sh_##fn_name);	\
117 }							\
118 							\
119 static inline uint64_t shdr32_##fn_name(Elf_Shdr *shdr)	\
120 {							\
121 	return elf_parser.r(&shdr->e32.sh_##fn_name);	\
122 }							\
123 							\
124 static inline uint64_t shdr_##fn_name(Elf_Shdr *shdr)	\
125 {							\
126 	return elf_parser.shdr_##fn_name(shdr);		\
127 }
128 
129 #define SHDR_WORD(fn_name)				\
130 static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr)	\
131 {							\
132 	return elf_parser.r(&shdr->e64.sh_##fn_name);	\
133 }							\
134 							\
135 static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr)	\
136 {							\
137 	return elf_parser.r(&shdr->e32.sh_##fn_name);	\
138 }							\
139 static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr)	\
140 {							\
141 	return elf_parser.shdr_##fn_name(shdr);		\
142 }
143 
144 SHDR_ADDR(addr)
145 SHDR_ADDR(offset)
146 SHDR_ADDR(size)
147 SHDR_ADDR(entsize)
148 SHDR_ADDR(flags)
149 
150 SHDR_WORD(link)
151 SHDR_WORD(name)
152 SHDR_WORD(type)
153 
154 #define SYM_ADDR(fn_name)				\
155 static inline uint64_t sym64_##fn_name(Elf_Sym *sym)	\
156 {							\
157 	return elf_parser.r8(&sym->e64.st_##fn_name);	\
158 }							\
159 							\
160 static inline uint64_t sym32_##fn_name(Elf_Sym *sym)	\
161 {							\
162 	return elf_parser.r(&sym->e32.st_##fn_name);	\
163 }							\
164 							\
165 static inline uint64_t sym_##fn_name(Elf_Sym *sym)	\
166 {							\
167 	return elf_parser.sym_##fn_name(sym);		\
168 }
169 
170 #define SYM_WORD(fn_name)				\
171 static inline uint32_t sym64_##fn_name(Elf_Sym *sym)	\
172 {							\
173 	return elf_parser.r(&sym->e64.st_##fn_name);	\
174 }							\
175 							\
176 static inline uint32_t sym32_##fn_name(Elf_Sym *sym)	\
177 {							\
178 	return elf_parser.r(&sym->e32.st_##fn_name);	\
179 }							\
180 							\
181 static inline uint32_t sym_##fn_name(Elf_Sym *sym)	\
182 {							\
183 	return elf_parser.sym_##fn_name(sym);		\
184 }
185 
186 #define SYM_HALF(fn_name)				\
187 static inline uint16_t sym64_##fn_name(Elf_Sym *sym)	\
188 {							\
189 	return elf_parser.r2(&sym->e64.st_##fn_name);	\
190 }							\
191 							\
192 static inline uint16_t sym32_##fn_name(Elf_Sym *sym)	\
193 {							\
194 	return elf_parser.r2(&sym->e32.st_##fn_name);	\
195 }							\
196 							\
197 static inline uint16_t sym_##fn_name(Elf_Sym *sym)	\
198 {							\
199 	return elf_parser.sym_##fn_name(sym);		\
200 }
201 
202 static inline uint8_t sym64_type(Elf_Sym *sym)
203 {
204 	return ELF64_ST_TYPE(sym->e64.st_info);
205 }
206 
207 static inline uint8_t sym32_type(Elf_Sym *sym)
208 {
209 	return ELF32_ST_TYPE(sym->e32.st_info);
210 }
211 
212 static inline uint8_t sym_type(Elf_Sym *sym)
213 {
214 	return elf_parser.sym_type(sym);
215 }
216 
217 static inline uint8_t sym64_bind(Elf_Sym *sym)
218 {
219 	return ELF64_ST_BIND(sym->e64.st_info);
220 }
221 
222 static inline uint8_t sym32_bind(Elf_Sym *sym)
223 {
224 	return ELF32_ST_BIND(sym->e32.st_info);
225 }
226 
227 static inline uint8_t sym_bind(Elf_Sym *sym)
228 {
229 	return elf_parser.sym_bind(sym);
230 }
231 
232 SYM_ADDR(value)
233 SYM_WORD(name)
234 SYM_HALF(shndx)
235 
236 #define __maybe_unused			__attribute__((__unused__))
237 
238 #define RELA_ADDR(fn_name)						\
239 static inline uint64_t rela64_##fn_name(Elf_Rela *rela)			\
240 {									\
241 	return elf_parser.r8((uint64_t *)&rela->e64.r_##fn_name);	\
242 }									\
243 									\
244 static inline uint64_t rela32_##fn_name(Elf_Rela *rela)			\
245 {									\
246 	return elf_parser.r((uint32_t *)&rela->e32.r_##fn_name);	\
247 }									\
248 									\
249 static inline uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela)	\
250 {									\
251 	return elf_parser.rela_##fn_name(rela);				\
252 }
253 
254 RELA_ADDR(offset)
255 RELA_ADDR(info)
256 RELA_ADDR(addend)
257 
258 static inline void rela64_write_addend(Elf_Rela *rela, uint64_t val)
259 {
260 	elf_parser.w8(val, (uint64_t *)&rela->e64.r_addend);
261 }
262 
263 static inline void rela32_write_addend(Elf_Rela *rela, uint64_t val)
264 {
265 	elf_parser.w(val, (uint32_t *)&rela->e32.r_addend);
266 }
267 
268 static inline uint32_t rbe(const uint32_t *x)
269 {
270 	return get_unaligned_be32(x);
271 }
272 
273 static inline uint16_t r2be(const uint16_t *x)
274 {
275 	return get_unaligned_be16(x);
276 }
277 
278 static inline uint64_t r8be(const uint64_t *x)
279 {
280 	return get_unaligned_be64(x);
281 }
282 
283 static inline uint32_t rle(const uint32_t *x)
284 {
285 	return get_unaligned_le32(x);
286 }
287 
288 static inline uint16_t r2le(const uint16_t *x)
289 {
290 	return get_unaligned_le16(x);
291 }
292 
293 static inline uint64_t r8le(const uint64_t *x)
294 {
295 	return get_unaligned_le64(x);
296 }
297 
298 static inline void wbe(uint32_t val, uint32_t *x)
299 {
300 	put_unaligned_be32(val, x);
301 }
302 
303 static inline void wle(uint32_t val, uint32_t *x)
304 {
305 	put_unaligned_le32(val, x);
306 }
307 
308 static inline void w8be(uint64_t val, uint64_t *x)
309 {
310 	put_unaligned_be64(val, x);
311 }
312 
313 static inline void w8le(uint64_t val, uint64_t *x)
314 {
315 	put_unaligned_le64(val, x);
316 }
317 
318 void *elf_map(char const *fname, size_t *size, uint32_t types);
319 void *elf_map_ro(char const *fname, size_t *size, uint32_t types);
320 void elf_unmap(void *addr, size_t size);
321 int elf_map_machine(void *addr);
322 int elf_map_long_size(void *addr);
323 
324 /* A mapped file with its section headers, section names and symbol table. */
325 struct elf_file {
326 	void *base;
327 	size_t size;
328 	const char *shdrs;
329 	unsigned int shnum, shentsize;
330 	const char *shstrtab;
331 	Elf_Shdr *symtab;
332 	const char *strtab;
333 	size_t nr_syms;
334 };
335 
336 int elf_open_ro(char const *fname, uint32_t types, struct elf_file *elf);
337 void elf_close(struct elf_file *elf);
338 
339 static inline Elf_Shdr *elf_section(const struct elf_file *elf,
340 				    unsigned int index)
341 {
342 	return (Elf_Shdr *)(elf->shdrs + (size_t)index * elf->shentsize);
343 }
344 
345 static inline const char *elf_section_name(const struct elf_file *elf,
346 					   Elf_Shdr *shdr)
347 {
348 	return elf->shstrtab + shdr_name(shdr);
349 }
350 
351 static inline Elf_Sym *elf_symbol(const struct elf_file *elf, size_t index)
352 {
353 	const char *base = elf->base;
354 
355 	return (Elf_Sym *)(base + shdr_offset(elf->symtab) +
356 			   index * shdr_entsize(elf->symtab));
357 }
358 
359 #endif /* _SCRIPTS_ELF_PARSE_H */
360