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 #define SHT_INIT_ARRAY 0xe      /**< Array of pointers to init functions */
210 #define SHT_FINI_ARRAY 0xf      /**< Array of pointers to termination functions */
211 #define SHT_PREINIT_ARRAY 0x10  /**< Array of pointers to early init functions */
212 
213 /** ELF section flags */
214 #define SHF_WRITE 0x1           /**< Section is writable */
215 #define SHF_ALLOC 0x2           /**< Section is present in memory */
216 #define SHF_EXECINSTR 0x4       /**< Section contains executable instructions */
217 
218 #define SHF_BASIC_TYPE_MASK	(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)
219 
220 /**
221  * @brief Symbol table entry(32-bit)
222  */
223 struct elf32_sym {
224 	/** Name of the symbol as an index into the symbol string table */
225 	elf32_word st_name;
226 	/** Value or location of the symbol */
227 	elf32_addr st_value;
228 	/** Size of the symbol */
229 	elf32_word st_size;
230 	/** Symbol binding and type information */
231 	unsigned char st_info;
232 	/** Symbol visibility */
233 	unsigned char st_other;
234 	/** Symbols related section given by section header index */
235 	elf32_half st_shndx;
236 };
237 
238 /**
239  * @brief Symbol table entry(64-bit)
240  */
241 struct elf64_sym {
242 	/** Name of the symbol as an index into the symbol string table */
243 	elf64_word st_name;
244 	/** Symbol binding and type information */
245 	unsigned char st_info;
246 	/** Symbol visibility */
247 	unsigned char st_other;
248 	/** Symbols related section given by section header index */
249 	elf64_half st_shndx;
250 	/** Value or location of the symbol */
251 	elf64_addr st_value;
252 	/** Size of the symbol */
253 	elf64_xword st_size;
254 };
255 
256 /** ELF section numbers */
257 #define SHN_UNDEF 0             /**< Undefined section */
258 #define SHN_LORESERVE 0xff00    /**< Start of reserved section numbers */
259 #define SHN_ABS 0xfff1          /**< Special value for absolute symbols */
260 #define SHN_COMMON 0xfff2       /**< Common block */
261 #define SHN_HIRESERVE 0xffff    /**< End of reserved section numbers */
262 
263 /** Symbol table entry types */
264 #define STT_NOTYPE 0            /**< No type */
265 #define STT_OBJECT 1            /**< Data or object */
266 #define STT_FUNC 2              /**< Function */
267 #define STT_SECTION 3           /**< Section */
268 #define STT_FILE 4              /**< File name */
269 #define STT_COMMON 5            /**< Common block */
270 #define STT_LOOS 10             /**< Start of OS specific */
271 #define STT_HIOS 12             /**< End of OS specific */
272 #define STT_LOPROC 13           /**< Start of processor specific */
273 #define STT_HIPROC 15           /**< End of processor specific */
274 
275 /** Symbol table entry bindings */
276 #define STB_LOCAL 0             /**< Local symbol */
277 #define STB_GLOBAL 1            /**< Global symbol */
278 #define STB_WEAK 2              /**< Weak symbol */
279 #define STB_LOOS 10             /**< Start of OS specific */
280 #define STB_HIOS 12             /**< End of OS specific */
281 #define STB_LOPROC 13           /**< Start of processor specific */
282 #define STB_HIPROC 15           /**< End of processor specific */
283 
284 /**
285  * @brief Symbol binding from 32bit st_info
286  *
287  * @param i Value of st_info
288  */
289 #define ELF32_ST_BIND(i) ((i) >> 4)
290 
291 /**
292  * @brief Symbol type from 32bit st_info
293  *
294  * @param i Value of st_info
295  */
296 #define ELF32_ST_TYPE(i) ((i) & 0xf)
297 
298 /**
299  * @brief Symbol binding from 32bit st_info
300  *
301  * @param i Value of st_info
302  */
303 #define ELF64_ST_BIND(i) ((i) >> 4)
304 
305 
306 /**
307  * @brief Symbol type from 32bit st_info
308  *
309  * @param i Value of st_info
310  */
311 #define ELF64_ST_TYPE(i) ((i) & 0xf)
312 
313 /**
314  * @brief Relocation entry for 32-bit ELFs.
315  *
316  * This structure stores information describing a relocation to be performed.
317  * Additional information about the relocation is stored at the location
318  * pointed to by @ref r_offset.
319  */
320 struct elf32_rel {
321 	/** Offset in the section to perform a relocation */
322 	elf32_addr r_offset;
323 	/** Information about the relocation, related symbol and type */
324 	elf32_word r_info;
325 };
326 
327 /**
328  * @brief Relocation entry for 32-bit ELFs with addend.
329  *
330  * This structure stores information describing a relocation to be performed.
331  */
332 struct elf32_rela {
333 	/** Offset in the section to perform a relocation */
334 	elf32_addr r_offset;
335 	/** Information about the relocation, related symbol and type */
336 	elf32_word r_info;
337 	/** Offset to be applied to the symbol address */
338 	elf32_sword r_addend;
339 };
340 
341 /**
342  * @brief Relocation symbol index from r_info
343  *
344  * @param i Value of r_info
345  */
346 #define ELF32_R_SYM(i) ((i) >> 8)
347 
348 /**
349  * @brief Relocation type from r_info
350  *
351  * @param i Value of r_info
352  */
353 #define ELF32_R_TYPE(i) ((i) & 0xff)
354 
355 /**
356  * @brief Relocation entry for 64-bit ELFs.
357  *
358  * This structure stores information describing a relocation to be performed.
359  * Additional information about the relocation is stored at the location
360  * pointed to by @ref r_offset.
361  */
362 struct elf64_rel {
363 	/** Offset in the section to perform a relocation */
364 	elf64_addr r_offset;
365 	/** Information about the relocation, related symbol and type */
366 	elf64_xword r_info;
367 };
368 
369 /**
370  * @brief Relocation entry for 64-bit ELFs with addend.
371  *
372  * This structure stores information describing a relocation to be performed.
373  */
374 struct elf64_rela {
375 	/** Offset in the section to perform a relocation */
376 	elf64_addr r_offset;
377 	/** Information about the relocation, related symbol and type */
378 	elf64_xword r_info;
379 	/** Offset to be applied to the symbol address */
380 	elf64_sxword r_addend;
381 };
382 
383 /** @brief Relocation symbol from r_info
384  *
385  * @param i Value of r_info
386  */
387 #define ELF64_R_SYM(i) ((i) >> 32)
388 
389 /**
390  * @brief Relocation type from r_info
391  *
392  * @param i Value of r_info
393  */
394 #define ELF64_R_TYPE(i) ((i) & 0xffffffff)
395 
396 /**
397  * Dynamic features currently not used by LLEXT
398  * @cond ignore
399  */
400 
401 /**
402  * @brief Program header(32-bit)
403  */
404 struct elf32_phdr {
405 	elf32_word p_type;      /**< Type of segment */
406 	elf32_off p_offset;     /**< Offset in file */
407 	elf32_addr p_vaddr;     /**< Virtual address in memory */
408 	elf32_addr p_paddr;     /**< Physical address (usually reserved) */
409 	elf32_word p_filesz;    /**< Size of segment in file */
410 	elf32_word p_memsz;     /**< Size of segment in memory */
411 	elf32_word p_flags;     /**< Segment flags */
412 	elf32_word p_align;     /**< Alignment of segment */
413 };
414 
415 /**
416  * @brief Program header(64-bit)
417  */
418 struct elf64_phdr {
419 	elf64_word p_type;      /**< Type of segment */
420 	elf64_off p_offset;     /**< Offset in file */
421 	elf64_addr p_vaddr;     /**< Virtual address in memory */
422 	elf64_addr p_paddr;     /**< Physical address (usually reserved) */
423 	elf64_xword p_filesz;   /**< Size of segment in file */
424 	elf64_xword p_memsz;    /**< Size of segment in memory */
425 	elf64_word p_flags;     /**< Segment flags */
426 	elf64_xword p_align;    /**< Alignment of segment */
427 };
428 
429 /**
430  * @brief Program segment type
431  */
432 #define PT_LOAD 1
433 
434 /**
435  * @brief Dynamic section entry(32-bit)
436  */
437 struct elf32_dyn {
438 	elf32_sword d_tag;              /**< Entry tag */
439 	union {
440 		elf32_word d_val;       /**< Integer value */
441 		elf32_addr d_ptr;       /**< Address value */
442 	} d_un;
443 };
444 
445 /**
446  * @brief Dynamic section entry(64-bit)
447  */
448 struct elf64_dyn {
449 	elf64_sxword d_tag;             /**< Entry tag */
450 	union {
451 		elf64_xword d_val;      /**< Integer value */
452 		elf64_addr d_ptr;       /**< Address value */
453 	} d_un;
454 };
455 /** @endcond */
456 
457 #if defined(CONFIG_64BIT) || defined(__DOXYGEN__)
458 /** Machine sized elf header structure */
459 typedef struct elf64_ehdr elf_ehdr_t;
460 /** Machine sized section header structure */
461 typedef struct elf64_shdr elf_shdr_t;
462 /** Machine sized program header structure */
463 typedef struct elf64_phdr elf_phdr_t;
464 /** Machine sized program address */
465 typedef elf64_addr elf_addr;
466 /** Machine sized small integer */
467 typedef elf64_half elf_half;
468 /** Machine sized integer */
469 typedef elf64_xword elf_word;
470 /** Machine sized relocation struct */
471 typedef struct elf64_rel elf_rel_t;
472 /** Machine sized relocation struct with addend */
473 typedef struct elf64_rela elf_rela_t;
474 /** Machine sized symbol struct */
475 typedef struct elf64_sym elf_sym_t;
476 /** Machine sized macro alias for obtaining a relocation symbol */
477 #define ELF_R_SYM ELF64_R_SYM
478 /** Machine sized macro alias for obtaining a relocation type */
479 #define ELF_R_TYPE ELF64_R_TYPE
480 /** Machine sized macro alias for obtaining a symbol bind */
481 #define ELF_ST_BIND ELF64_ST_BIND
482 /** Machine sized macro alias for obtaining a symbol type */
483 #define ELF_ST_TYPE ELF64_ST_TYPE
484 #else
485 /** Machine sized elf header structure */
486 typedef struct elf32_ehdr elf_ehdr_t;
487 /** Machine sized section header structure */
488 typedef struct elf32_shdr elf_shdr_t;
489 /** Machine sized program header structure */
490 typedef struct elf32_phdr elf_phdr_t;
491 /** Machine sized program address */
492 typedef elf32_addr elf_addr;
493 /** Machine sized small integer */
494 typedef elf32_half elf_half;
495 /** Machine sized integer */
496 typedef elf32_word elf_word;
497 /** Machine sized relocation struct */
498 typedef struct elf32_rel elf_rel_t;
499 /** Machine sized relocation struct with addend */
500 typedef struct elf32_rela elf_rela_t;
501 /** Machine sized symbol struct */
502 typedef struct elf32_sym elf_sym_t;
503 /** Machine sized macro alias for obtaining a relocation symbol */
504 #define ELF_R_SYM ELF32_R_SYM
505 /** Machine sized macro alias for obtaining a relocation type */
506 #define ELF_R_TYPE ELF32_R_TYPE
507 /** Machine sized macro alias for obtaining a symbol bind */
508 #define ELF_ST_BIND ELF32_ST_BIND
509 /** Machine sized macro alias for obtaining a symbol type */
510 #define ELF_ST_TYPE ELF32_ST_TYPE
511 #endif
512 
513 #ifdef __cplusplus
514 }
515 #endif
516 
517 /**
518  * @}
519  */
520 
521 #endif /* ZEPHYR_LLEXT_ELF_H */
522