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 	/** Value or location of the symbol */
235 	elf64_addr st_value;
236 	/** Size of the symbol */
237 	elf64_xword st_size;
238 	/** Symbol binding and type information */
239 	unsigned char st_info;
240 	/** Symbol visibility */
241 	unsigned char st_other;
242 	/** Symbols related section given by section header index */
243 	elf64_half st_shndx;
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 /**
310  * @brief Relocation symbol index from r_info
311  *
312  * @param i Value of r_info
313  */
314 #define ELF32_R_SYM(i) ((i) >> 8)
315 
316 /**
317  * @brief Relocation type from r_info
318  *
319  * @param i Value of r_info
320  */
321 #define ELF32_R_TYPE(i) ((i) & 0xff)
322 
323 /**
324  * @brief Relocation entry for 64-bit ELFs
325  */
326 struct elf64_rel {
327 	/** Offset in section to perform a relocation */
328 	elf64_addr r_offset;
329 	/** Information about relocation, related symbol and type */
330 	elf64_xword r_info;
331 };
332 
333 /** @brief Relocation symbol from r_info
334  *
335  * @param i Value of r_info
336  */
337 #define ELF64_R_SYM(i) ((i) >> 32)
338 
339 /**
340  * @brief Relocation type from r_info
341  *
342  * @param i Value of r_info
343  */
344 #define ELF64_R_TYPE(i) ((i) & 0xffffffff)
345 
346 #define R_386_NONE 0
347 #define R_386_32 1
348 #define R_386_PC32 2
349 #define R_386_GOT32 3
350 #define R_386_PLT32 4
351 #define R_386_COPY 5
352 #define R_386_GLOB_DAT 6
353 #define R_386_JMP_SLOT 7
354 #define R_386_RELATIVE 8
355 #define R_386_GOTOFF 9
356 
357 #define R_ARM_NONE 0
358 #define R_ARM_PC24 1
359 #define R_ARM_ABS32 2
360 #define R_ARM_REL32 3
361 #define R_ARM_COPY 4
362 #define R_ARM_CALL 28
363 #define R_ARM_V4BX 40
364 
365 #define R_XTENSA_NONE 0
366 #define R_XTENSA_32 1
367 #define R_XTENSA_SLOT0_OP 20
368 
369 /**
370  * @brief Program header(32-bit)
371  */
372 struct elf32_phdr {
373 	elf32_word p_type;
374 	elf32_off p_offset;
375 	elf32_addr p_vaddr;
376 	elf32_addr p_paddr;
377 	elf32_word p_filesz;
378 	elf32_word p_memsz;
379 	elf32_word p_flags;
380 	elf32_word p_align;
381 };
382 
383 /**
384  * @brief Program header(64-bit)
385  */
386 struct elf64_phdr {
387 	elf64_word p_type;
388 	elf64_off p_offset;
389 	elf64_addr p_vaddr;
390 	elf64_addr p_paddr;
391 	elf64_xword p_filesz;
392 	elf64_xword p_memsz;
393 	elf64_word p_flags;
394 	elf64_xword p_align;
395 };
396 
397 /**
398  * @brief Program segment type
399  */
400 #define PT_LOAD 1
401 
402 /**
403  * @brief Dynamic section entry(32-bit)
404  */
405 struct elf32_dyn {
406 	elf32_sword d_tag;
407 	union {
408 		elf32_word d_val;
409 		elf32_addr d_ptr;
410 	} d_un;
411 };
412 
413 /**
414  * @brief Dynamic section entry(64-bit)
415  */
416 struct elf64_dyn {
417 	elf64_sxword d_tag;
418 	union {
419 		elf64_xword d_val;
420 		elf64_addr d_ptr;
421 	} d_un;
422 };
423 
424 #if defined(CONFIG_64BIT) || defined(__DOXYGEN__)
425 /** Machine sized elf header structure */
426 typedef struct elf64_ehdr elf_ehdr_t;
427 /** Machine sized section header structure */
428 typedef struct elf64_shdr elf_shdr_t;
429 /** Machine sized program header structure */
430 typedef struct elf64_phdr elf_phdr_t;
431 /** Machine sized program address */
432 typedef elf64_addr elf_addr;
433 /** Machine sized small integer */
434 typedef elf64_half elf_half;
435 /** Machine sized integer */
436 typedef elf64_xword elf_word;
437 /** Machine sized relocation struct */
438 typedef struct elf64_rela elf_rel_t;
439 /** Machine sized symbol struct */
440 typedef struct elf64_sym elf_sym_t;
441 /** Machine sized macro alias for obtaining a relocation symbol */
442 #define ELF_R_SYM ELF64_R_SYM
443 /** Machine sized macro alias for obtaining a relocation type */
444 #define ELF_R_TYPE ELF64_R_TYPE
445 /** Machine sized macro alias for obtaining a symbol bind */
446 #define ELF_ST_BIND ELF64_ST_BIND
447 /** Machine sized macro alias for obtaining a symbol type */
448 #define ELF_ST_TYPE ELF64_ST_TYPE
449 #else
450 /** Machine sized elf header structure */
451 typedef struct elf32_ehdr elf_ehdr_t;
452 /** Machine sized section header structure */
453 typedef struct elf32_shdr elf_shdr_t;
454 /** Machine sized program header structure */
455 typedef struct elf32_phdr elf_phdr_t;
456 /** Machine sized program address */
457 typedef elf32_addr elf_addr;
458 /** Machine sized small integer */
459 typedef elf32_half elf_half;
460 /** Machine sized integer */
461 typedef elf32_word elf_word;
462 /** Machine sized relocation struct */
463 typedef struct elf32_rel elf_rel_t;
464 /** Machine sized symbol struct */
465 typedef struct elf32_sym elf_sym_t;
466 /** Machine sized macro alias for obtaining a relocation symbol */
467 #define ELF_R_SYM ELF32_R_SYM
468 /** Machine sized macro alias for obtaining a relocation type */
469 #define ELF_R_TYPE ELF32_R_TYPE
470 /** Machine sized macro alias for obtaining a symbol bind */
471 #define ELF_ST_BIND ELF32_ST_BIND
472 /** Machine sized macro alias for obtaining a symbol type */
473 #define ELF_ST_TYPE ELF32_ST_TYPE
474 #endif
475 
476 #ifdef __cplusplus
477 }
478 #endif
479 
480 /**
481  * @}
482  */
483 
484 #endif /* ZEPHYR_LLEXT_ELF_H */
485