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