1 /*
2  * Copyright (c) 2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  */
7 #ifndef ZEPHYR_LLEXT_ELF_H
8 #define ZEPHYR_LLEXT_ELF_H
9 
10 #include <stdint.h>
11 
12 /**
13  * @brief ELF types and parsing
14  *
15  * Reference documents can be found here https://refspecs.linuxfoundation.org/elf/
16  *
17  * @defgroup elf ELF data types and defines
18  * @ingroup llext
19  * @{
20  */
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /** Unsigned program address */
27 typedef uint32_t elf32_addr;
28 /** Unsigned medium integer */
29 typedef uint16_t elf32_half;
30 /** Unsigned file offset */
31 typedef uint32_t elf32_off;
32 /** Signed integer */
33 typedef int32_t elf32_sword;
34 /** Unsigned integer */
35 typedef uint32_t elf32_word;
36 
37 /** Unsigned program address */
38 typedef uint64_t elf64_addr;
39 /** Unsigned medium integer */
40 typedef uint16_t elf64_half;
41 /** Unsigned file offset */
42 typedef uint64_t elf64_off;
43 /** Signed integer */
44 typedef int32_t elf64_sword;
45 /** Unsigned integer */
46 typedef uint32_t elf64_word;
47 /** Signed long integer */
48 typedef int64_t elf64_sxword;
49 /** Unsigned long integer */
50 typedef uint64_t elf64_xword;
51 
52 
53 /**
54  * @brief ELF identifier block
55  *
56  * 4 byte magic (.ELF)
57  * 1 byte class (Invalid, 32 bit, 64 bit)
58  * 1 byte endianness (Invalid, LSB, MSB)
59  * 1 byte version (1)
60  * 1 byte OS ABI (0 None, 1 HP-UX, 2 NetBSD, 3 Linux)
61  * 1 byte ABI (0)
62  * 7 bytes padding
63  */
64 #define EI_NIDENT 16
65 
66 /**
67  * @brief ELF Header(32-bit)
68  */
69 struct elf32_ehdr {
70 	/** Magic string identifying ELF binary */
71 	unsigned char e_ident[EI_NIDENT];
72 	/** Type of ELF */
73 	elf32_half e_type;
74 	/** Machine type */
75 	elf32_half e_machine;
76 	/** Object file version */
77 	elf32_word e_version;
78 	/** Virtual address of entry */
79 	elf32_addr e_entry;
80 	/** Program header table offset */
81 	elf32_off e_phoff;
82 	/** Section header table offset */
83 	elf32_off e_shoff;
84 	/** Processor specific flags */
85 	elf32_word e_flags;
86 	/** ELF header size */
87 	elf32_half e_ehsize;
88 	/** Program header count */
89 	elf32_half e_phentsize;
90 	/** Program header count */
91 	elf32_half e_phnum;
92 	/** Section header size */
93 	elf32_half e_shentsize;
94 	/** Section header count */
95 	elf32_half e_shnum;
96 	/** Section header containing section header string table */
97 	elf32_half e_shstrndx;
98 };
99 
100 /**
101  * @brief ELF Header(64-bit)
102  */
103 struct elf64_ehdr {
104 	/** Magic string identifying ELF binary */
105 	unsigned char e_ident[EI_NIDENT];
106 	/** Type of ELF */
107 	elf64_half e_type;
108 	/** Machine type */
109 	elf64_half e_machine;
110 	/** Object file version */
111 	elf64_word e_version;
112 	/** Virtual address of entry */
113 	elf64_addr e_entry;
114 	/** Program header table offset */
115 	elf64_off e_phoff;
116 	/** Section header table offset */
117 	elf64_off e_shoff;
118 	/** Processor specific flags */
119 	elf64_word e_flags;
120 	/** ELF header size */
121 	elf64_half e_ehsize;
122 	/** Program header size */
123 	elf64_half e_phentsize;
124 	/** Program header count */
125 	elf64_half e_phnum;
126 	/** Section header size */
127 	elf64_half e_shentsize;
128 	/** Section header count */
129 	elf64_half e_shnum;
130 	/** Section header containing section header string table */
131 	elf64_half e_shstrndx;
132 };
133 
134 /** Relocatable (unlinked) ELF */
135 #define ET_REL  1
136 
137 /** Executable (without PIC/PIE) ELF */
138 #define ET_EXEC 2
139 
140 /** Dynamic (executable with PIC/PIE or shared lib) ELF */
141 #define ET_DYN  3
142 
143 /** Core Dump */
144 #define ET_CORE 4
145 
146 /**
147  * @brief Section Header(32-bit)
148  */
149 struct elf32_shdr {
150 	/** Section header name index in section header string table */
151 	elf32_word sh_name;
152 	/** Section type */
153 	elf32_word sh_type;
154 	/** Section header attributes */
155 	elf32_word sh_flags;
156 	/** Address of section in the image */
157 	elf32_addr sh_addr;
158 	/** Location of section in the ELF binary in bytes */
159 	elf32_off sh_offset;
160 	/** Section size in bytes */
161 	elf32_word sh_size;
162 	/** Section header table link index, depends on section type */
163 	elf32_word sh_link;
164 	/** Section info, depends on section type */
165 	elf32_word sh_info;
166 	/** Section address alignment */
167 	elf32_word sh_addralign;
168 	/** Section contains table of fixed size entries sh_entsize bytes large */
169 	elf32_word sh_entsize;
170 };
171 
172 /**
173  * @brief Section Header(64-bit)
174  */
175 struct elf64_shdr {
176 	/** Section header name index in section header string table */
177 	elf64_word sh_name;
178 	/** Section type */
179 	elf64_word sh_type;
180 	/** Section header attributes */
181 	elf64_xword sh_flags;
182 	/** Address of section in the image */
183 	elf64_addr sh_addr;
184 	/** Location of section in the ELF binary in bytes */
185 	elf64_off sh_offset;
186 	/** Section size in bytes */
187 	elf64_xword sh_size;
188 	/** Section header table link index, depends on section type */
189 	elf64_word sh_link;
190 	/** Section info, depends on section type */
191 	elf64_word sh_info;
192 	/** Section address alignment */
193 	elf64_xword sh_addralign;
194 	/** Section contains table of fixed size entries sh_entsize bytes large */
195 	elf64_xword sh_entsize;
196 };
197 
198 #define SHT_PROGBITS 0x1
199 #define SHT_SYMTAB 0x2
200 #define SHT_STRTAB 0x3
201 #define SHT_RELA 0x4
202 #define SHT_NOBITS 0x8
203 #define SHT_REL 0x9
204 #define SHT_DYNSYM 0xB
205 
206 #define SHF_WRITE 0x1
207 #define SHF_ALLOC 0x2
208 #define SHF_EXECINSTR 0x4
209 
210 /**
211  * @brief Symbol table entry(32-bit)
212  */
213 struct elf32_sym {
214 	/** Name of the symbol as an index into the symbol string table */
215 	elf32_word st_name;
216 	/** Value or location of the symbol */
217 	elf32_addr st_value;
218 	/** Size of the symbol */
219 	elf32_word st_size;
220 	/** Symbol binding and type information */
221 	unsigned char st_info;
222 	/** Symbol visibility */
223 	unsigned char st_other;
224 	/** Symbols related section given by section header index */
225 	elf32_half st_shndx;
226 };
227 
228 /**
229  * @brief Symbol table entry(64-bit)
230  */
231 struct elf64_sym {
232 	/** Name of the symbol as an index into the symbol string table */
233 	elf64_word st_name;
234 	/** Symbol binding and type information */
235 	unsigned char st_info;
236 	/** Symbol visibility */
237 	unsigned char st_other;
238 	/** Symbols related section given by section header index */
239 	elf64_half st_shndx;
240 	/** Value or location of the symbol */
241 	elf64_addr st_value;
242 	/** Size of the symbol */
243 	elf64_xword st_size;
244 };
245 
246 #define SHN_UNDEF 0
247 #define SHN_ABS 0xfff1
248 #define SHN_COMMON 0xfff2
249 
250 #define STT_NOTYPE 0
251 #define STT_OBJECT 1
252 #define STT_FUNC 2
253 #define STT_SECTION 3
254 #define STT_FILE 4
255 #define STT_COMMON 5
256 #define STT_LOOS 10
257 #define STT_HIOS 12
258 #define STT_LOPROC 13
259 #define STT_HIPROC 15
260 
261 #define STB_LOCAL 0
262 #define STB_GLOBAL 1
263 #define STB_WEAK 2
264 #define STB_LOOS 10
265 #define STB_HIOS 12
266 #define STB_LOPROC 13
267 #define STB_HIPROC 15
268 
269 /**
270  * @brief Symbol binding from 32bit st_info
271  *
272  * @param i Value of st_info
273  */
274 #define ELF32_ST_BIND(i) ((i) >> 4)
275 
276 /**
277  * @brief Symbol type from 32bit st_info
278  *
279  * @param i Value of st_info
280  */
281 #define ELF32_ST_TYPE(i) ((i) & 0xf)
282 
283 /**
284  * @brief Symbol binding from 32bit st_info
285  *
286  * @param i Value of st_info
287  */
288 #define ELF64_ST_BIND(i) ((i) >> 4)
289 
290 
291 /**
292  * @brief Symbol type from 32bit st_info
293  *
294  * @param i Value of st_info
295  */
296 #define ELF64_ST_TYPE(i) ((i) & 0xf)
297 
298 /**
299  * @brief Relocation entry for 32-bit ELFs
300  */
301 struct elf32_rel {
302 	/** Offset in the section to perform a relocation */
303 	elf32_addr r_offset;
304 
305 	/** Information about the relocation, related symbol and type */
306 	elf32_word r_info;
307 };
308 
309 struct elf32_rela {
310 	elf32_addr r_offset;
311 	elf32_word r_info;
312 	elf32_word r_addend;
313 };
314 
315 /**
316  * @brief Relocation symbol index from r_info
317  *
318  * @param i Value of r_info
319  */
320 #define ELF32_R_SYM(i) ((i) >> 8)
321 
322 /**
323  * @brief Relocation type from r_info
324  *
325  * @param i Value of r_info
326  */
327 #define ELF32_R_TYPE(i) ((i) & 0xff)
328 
329 /**
330  * @brief Relocation entry for 64-bit ELFs
331  */
332 struct elf64_rel {
333 	/** Offset in section to perform a relocation */
334 	elf64_addr r_offset;
335 	/** Information about relocation, related symbol and type */
336 	elf64_xword r_info;
337 };
338 
339 struct elf64_rela {
340 	elf64_addr r_offset;
341 	elf64_word r_info;
342 	elf64_word r_addend;
343 };
344 
345 /** @brief Relocation symbol from r_info
346  *
347  * @param i Value of r_info
348  */
349 #define ELF64_R_SYM(i) ((i) >> 32)
350 
351 /**
352  * @brief Relocation type from r_info
353  *
354  * @param i Value of r_info
355  */
356 #define ELF64_R_TYPE(i) ((i) & 0xffffffff)
357 
358 #define R_386_NONE 0
359 #define R_386_32 1
360 #define R_386_PC32 2
361 #define R_386_GOT32 3
362 #define R_386_PLT32 4
363 #define R_386_COPY 5
364 #define R_386_GLOB_DAT 6
365 #define R_386_JMP_SLOT 7
366 #define R_386_RELATIVE 8
367 #define R_386_GOTOFF 9
368 
369 #define R_ARM_NONE 0
370 #define R_ARM_PC24 1
371 #define R_ARM_ABS32 2
372 #define R_ARM_REL32 3
373 #define R_ARM_COPY 4
374 #define R_ARM_CALL 28
375 #define R_ARM_V4BX 40
376 
377 #define R_XTENSA_NONE 0
378 #define R_XTENSA_32 1
379 #define R_XTENSA_SLOT0_OP 20
380 
381 /**
382  * @brief Program header(32-bit)
383  */
384 struct elf32_phdr {
385 	elf32_word p_type;
386 	elf32_off p_offset;
387 	elf32_addr p_vaddr;
388 	elf32_addr p_paddr;
389 	elf32_word p_filesz;
390 	elf32_word p_memsz;
391 	elf32_word p_flags;
392 	elf32_word p_align;
393 };
394 
395 /**
396  * @brief Program header(64-bit)
397  */
398 struct elf64_phdr {
399 	elf64_word p_type;
400 	elf64_off p_offset;
401 	elf64_addr p_vaddr;
402 	elf64_addr p_paddr;
403 	elf64_xword p_filesz;
404 	elf64_xword p_memsz;
405 	elf64_word p_flags;
406 	elf64_xword p_align;
407 };
408 
409 /**
410  * @brief Program segment type
411  */
412 #define PT_LOAD 1
413 
414 /**
415  * @brief Dynamic section entry(32-bit)
416  */
417 struct elf32_dyn {
418 	elf32_sword d_tag;
419 	union {
420 		elf32_word d_val;
421 		elf32_addr d_ptr;
422 	} d_un;
423 };
424 
425 /**
426  * @brief Dynamic section entry(64-bit)
427  */
428 struct elf64_dyn {
429 	elf64_sxword d_tag;
430 	union {
431 		elf64_xword d_val;
432 		elf64_addr d_ptr;
433 	} d_un;
434 };
435 
436 #if defined(CONFIG_64BIT) || defined(__DOXYGEN__)
437 /** Machine sized elf header structure */
438 typedef struct elf64_ehdr elf_ehdr_t;
439 /** Machine sized section header structure */
440 typedef struct elf64_shdr elf_shdr_t;
441 /** Machine sized program header structure */
442 typedef struct elf64_phdr elf_phdr_t;
443 /** Machine sized program address */
444 typedef elf64_addr elf_addr;
445 /** Machine sized small integer */
446 typedef elf64_half elf_half;
447 /** Machine sized integer */
448 typedef elf64_xword elf_word;
449 /** Machine sized relocation struct */
450 typedef struct elf64_rel elf_rel_t;
451 typedef struct elf64_rela elf_rela_t;
452 /** Machine sized symbol struct */
453 typedef struct elf64_sym elf_sym_t;
454 /** Machine sized macro alias for obtaining a relocation symbol */
455 #define ELF_R_SYM ELF64_R_SYM
456 /** Machine sized macro alias for obtaining a relocation type */
457 #define ELF_R_TYPE ELF64_R_TYPE
458 /** Machine sized macro alias for obtaining a symbol bind */
459 #define ELF_ST_BIND ELF64_ST_BIND
460 /** Machine sized macro alias for obtaining a symbol type */
461 #define ELF_ST_TYPE ELF64_ST_TYPE
462 #else
463 /** Machine sized elf header structure */
464 typedef struct elf32_ehdr elf_ehdr_t;
465 /** Machine sized section header structure */
466 typedef struct elf32_shdr elf_shdr_t;
467 /** Machine sized program header structure */
468 typedef struct elf32_phdr elf_phdr_t;
469 /** Machine sized program address */
470 typedef elf32_addr elf_addr;
471 /** Machine sized small integer */
472 typedef elf32_half elf_half;
473 /** Machine sized integer */
474 typedef elf32_word elf_word;
475 /** Machine sized relocation struct */
476 typedef struct elf32_rel elf_rel_t;
477 typedef struct elf32_rela elf_rela_t;
478 /** Machine sized symbol struct */
479 typedef struct elf32_sym elf_sym_t;
480 /** Machine sized macro alias for obtaining a relocation symbol */
481 #define ELF_R_SYM ELF32_R_SYM
482 /** Machine sized macro alias for obtaining a relocation type */
483 #define ELF_R_TYPE ELF32_R_TYPE
484 /** Machine sized macro alias for obtaining a symbol bind */
485 #define ELF_ST_BIND ELF32_ST_BIND
486 /** Machine sized macro alias for obtaining a symbol type */
487 #define ELF_ST_TYPE ELF32_ST_TYPE
488 #endif
489 
490 #ifdef __cplusplus
491 }
492 #endif
493 
494 /**
495  * @}
496  */
497 
498 #endif /* ZEPHYR_LLEXT_ELF_H */
499