1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
|
#pragma once
// ============================================================================
// elf.h - ELF format definitions
// https://refspecs.linuxbase.org/elf/elf.pdf
// https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779
// https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcoblh/index.html
// ============================================================================
#include <stdint.h>
/* ELF Types */
#pragma message("TODO: describe ELF types from specification")
// ============================================================================
// =================================== ELF Header =============================
// ============================================================================
#define EI_NIDENT (16)
/* e_ident offset (https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#ELF_header) */
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_ABIVERSION 8
#define EI_PAD 9
/* ELF Magic value */
#define ELF_MAGIC 0x464C457F // "\x7FELF" little-endian
/* ELF Class */
#define ELFCLASS32 0x1
#define ELFCLASS64 0x2
/* Data format: or LSB(Least Significant Bit, little-endian) or MSB(Most Significant Bit, big-endian) */
#define ELFDATA2LSB 0x1
#define ELFDATA2MSB 0x2
/* ELF version */
#define ELFVERSION 0x1
/* Target ABI */
#define ELFABISYSTEMV 0x00
#define ELFABIHPUX 0x01
#define ELFABINETBSD 0x02
#define ELFABILINUX 0x03
#define ELFABIGNUHURD 0x04
#define ELFABISOLARIS 0x06
#define ELFABIAIX 0x07
#define ELFABIIRIX 0x08
#define ELFABIFREEBSD 0x09
#define ELFABITRU64 0x0A
#define ELFABINM 0x0B
#define ELFABIOPENBSD 0x0C
#define ELFABIOPENVMS 0x0D
#define ELFABINSKERNEL 0x0E
#define ELFABIAROS 0x0F
#define ELFABIFENIXOS 0x10
#define ELFABICLOUDABI 0x11
#define ELFABISTOPENVOS 0x12
/* ABI version */
#pragma message("TODO: do something with ABI version")
/* Currently i don't use ABI version */
/* Object File Types, e_type field */
#define ET_NONE 0x0 /* Unknown */
#define ET_REL 0x1 /* Relocatable. (output of gcc -c). Contains sections + symbol tables + relocations. No program header */
#define ET_EXEC 0x2 /* Executable. Statically-linked executable with fixed virtual addresses. Has program headers. */
#define ET_DYN 0x3 /* Shared object. Shared library or PIE executable. Postitoin-independent, relocated at load time. */
#define ET_CORE 0x4 /* Core dump. Process memory image for post-mortem debugging */
#define ET_LOOS 0xFE00 /* Reserved inclusive range. Operating system specific */
#define ET_HIOS 0xFEFF /* Reserved inclusive range. Operating system specific */
#define ET_LOPROC 0xFF00 /* Reserved inclusive range. Processor specific */
#define ET_HIPROC 0xFFFF /* Reserved inclusive range. Processor specific */
/* Arch types, e_machine field */
#pragma message("TODO: add other architecture defines, copy from github")
#define EM_X86 0x03
#define EM_X86_64 0x3E
#define EM_ARM 0x28 /* up to Armv7/AArch32 */
#define EM_AARCH64 0xB7 /* Armv8/AArch64 */
/* Version value, e_version field */
#define EV_NONE 0x00
#define EV_CURRENT 0x01
#define EV_NUM 0x02
/* Other header fields:
e_entry: Memory address of the entry point.
e_phoff: Pointer to the start of the program header table.
e_shoff: Pointer to the start of section header table.
e_flags: Interpretation of this field depends on the target arch.
e_ehsize: Contains the size of header (normally 64 bytes for 64-bit and 52 Bytes for 32-bit)
e_phentsize: Contains the size of program header table entry. Or 0x20 (for 32-bit) or 0x38 (for 64-bit).
e_phnum: Contains the number of entries in the program header table.
e_shentsize: Contains the size of a section header table entry. Or 0x28 (for 32-bit) or 0x40 (for 64-bit)
e_shnum: Contains the number of entries in the section header table.
e_shstrndx: Contains index of the section header table entry, that contains the section names.
*/
/* ELF header (atm only for 64 bit) */
#pragma message("TODO: add elf header for 32 bit")
struct Elf64_Ehdr {
uint8_t e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
};
// ============================================================================
// =================================== Program Header =========================
// ============================================================================
/* Type, p_type field */
#define PT_NULL 0x00000000 /* Program header table entry unused */
#define PT_LOAD 0x00000001 /* Loadable segment */
#define PT_DYNAMIC 0x00000002 /* Dynamic linking information */
#define PT_INTERP 0x00000003 /* Interpreter information */
#define PT_NOTE 0x00000004 /* Auxiliary information */
#define PT_SHLIB 0x00000005 /* Reserved */
#define PT_PHDR 0x00000006 /* Segment containing program header table itself */
#define PT_TLS 0x00000007 /* Thread-Local Storage template */
#define PT_NUM 0x00000008 /* Number of defined types */
#define PT_LOOS 0x60000000 /* Reserved inclusive range. Operating system specific: */
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
#define PT_HISUNW 0x6fffffff
#define PT_HIOS 0x6FFFFFFF /* Reserved inclusive range. Operating system specific end*/
#define PT_LOPROC 0x70000000 /* Reserved inclusive range. Processor specific */
#define PT_HIPROC 0x7FFFFFFF /* Reserved inclusive range. Processor specific */
/* Flags, p_flags 64-bit field */
#define PF_X 0x1 /* Executable segment */
#define PF_W 0x2 /* Writeable segment */
#define PF_R 0x4 /* Readable segment */
#define PF_MASKOS 0x0FF00000 /* OS-specific */
#define PF_MASKPROC 0xF0000000 /* Processor-specific */
/* Other Program Header fields:
p_offset: Offset of the segment in the file image.
p_vaddr: Virtual address of the segment in memory.
p_paddr: On systems where physical address is relevant, reserved for segment's physical address.
p_filesz: Size in bytes of the segment in the file image. May be 0.
p_memsz: Size in bytes of the segment in memory. May be 0.
p_flags: 32-bit flags (don't exist on 64 bit header)
p_align: 0 and 1 specify no alignment. Otherwise should be a positive, integral power of 2, with p_vaddr equating p_offset modules p_align
*/
/* Elf64 Program Header */
struct Elf64_Phdr {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset;
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
};
// ============================================================================
// =================================== Section Header =============================
// ============================================================================
/* Section Header Type, sh_type field */
#define SHT_NULL 0x0 /* Section header table entry unused. First entry in the section table must be SHT_NULL according the stanard */
#define SHT_PROGBITS 0x1 /* Program data */
#define SHT_SYMTAB 0x2 /* Symbol table */
#define SHT_STRTAB 0x3 /* String table */
#define SHT_RELA 0x4 /* Relocation entries with addends */
#define SHT_HASH 0x5 /* Symbol hash table */
#define SHT_DYNAMIC 0x6 /* Dynamic linking information */
#define SHT_NOTE 0x7 /* Notes */
#define SHT_NOBITS 0x8 /* Program space with no data (bss) */
#define SHT_REL 0x9 /* Relocation entries, no addends */
#define SHT_SHLIB 0x0A /* Reserved */
#define SHT_DYNSYM 0x0B /* Dynamic linker symbol table */
#define SHT_INIT_ARRAY 0x0E /* Array of constructors */
#define SHT_FINI_ARRAY 0x0F /* Array of destructors */
#define SHT_PREINIT_ARRAY 0x10 /* Array of pre-constructors */
#define SHT_GROUP 0x11 /* Section group */
#define SHT_SYMTAB_SHNDX 0x12 /* Extended section indices */
#define SHT_NUM 0x13 /* Number of defined types */
#define SHT_LOOS 0x60000000 /* Start OS-specific */
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
#define SHT_SUNW_move 0x6ffffffa
#define SHT_SUNW_COMDAT 0x6ffffffb
#define SHT_SUNW_syminfo 0x6ffffffc
#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
#define SHT_HIOS 0x6fffffff /* End OS-specific type */
#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
#define SHT_LOUSER 0x80000000 /* Start of application-specific */
#define SHT_HIUSER 0x8fffffff /* End of application-specific */
/* Section Header flags, sh_flags field */
#define SHF_WRITE 0x1 /*Writable*/
#define SHF_ALLOC 0x2 /*Occupies memory during execution*/
#define SHF_EXECINSTR 0x4 /*Executable*/
#define SHF_MERGE 0x10 /*Might be merged*/
#define SHF_STRINGS 0x20 /*Contains null-terminated strings*/
#define SHF_INFO_LINK 0x40 /*'sh_info' contains SHT index*/
#define SHF_LINK_ORDER 0x80 /*Preserve order after combining*/
#define SHF_OS_NONCONFORMING 0x100 /*Non-standard OS specific handling required*/
#define SHF_GROUP 0x200 /*Section is member of a group*/
#define SHF_TLS 0x400 /*Section hold thread-local data*/
#define SHF_COMPRESSED 0x800 /*Section with compressed data*/
#define SHF_MASKOS 0x0FF00000 /*OS-specific*/
#define SHF_MASKPROC 0xF0000000 /*Processor-specific*/
#define SHF_ORDERED 0x4000000 /*Special ordering requirement (Solaris)*/
#define SHF_EXCLUDE 0x8000000 /*Section is excluded unless referenced or allocated (Solaris)*/
/* Other Section Header fields:
sh_name: An offset to a string in the .shstrab section that represents the name of this section. Zero means no name.
sh_addr: Virtual address of the section in memory, for sections that are loaded.
sh_offset: Offset of the section in the file image.
sh_size: Size in bytes of the section. May be 0.
sh_link: Contains the section index of an associated section. This field is used for several purposes, depending on the type of section.
sh_info: Contains extra information about the section. This field is used for several purposes, depending on the type of section.
sh_addralign: Contains the required alignment of the section. This field must be a power of two.
sh_entsize: Contains the size, in bytes, of each entry, for sections that contain fixed-size entries. Otherwise, this field contains zero.
*/
/*
The most common ELF sections:
.text - contains executable code. Packed with Read and Execute flags. Load only one times. Can't be changed.
.data - initalized data. Read and Write flags.
.rodata - initalized read only data. Read flag.
.bss - unititlized data. Read and Write flags.
other sections you can see here: https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779#sections
Also, there is something like "group of sections" (readelf -g), but it's very rare.
*/
/* Elf64 Section Header */
struct Elf64_Shdr {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
};
// ============================================================================
// =================================== Symbols ================================
// ============================================================================
// https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-79797/index.html
#pragma message("TODO: do")
/* Symbol fields:
st_name: Symbol name
st_info: Symbol type and binding. It is calculated using macros
st_other: Symbol visibility.
st_shndx: Section index.
st_value: Symbol value.
st_size: Symbol size;
*/
/* Symbol struct */
struct Elf64_Sym {
uint32_t st_name;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
uint64_t st_value;
uint64_t st_size;
};
// ============================================================================
// =================================== ELF Page size ==========================
// ============================================================================
#define ELF_PAGE_SIZE 0x1000
#define ELF_PAGE_MASK (ELF_PAGE_SIZE - 1)
// ============================================================================
// =================================== ELF Load Result ========================
// ============================================================================
// ATM it uses in efi_elf_parser.cpp
/* Error codes for ElfLoadResult.error */
#define ELF_ERR_NONE 0 /* success */
#define ELF_ERR_FILE_TOO_SMALL 1 /* file smaller than ELF header */
#define ELF_ERR_INVALID_MAGIC 2 /* bad magic */
#define ELF_ERR_INVALID_CLASS 3 /* bad class */
#define ELF_ERR_INVALID_IDENT 4 /* bad ident */
#define ELF_ERR_INVALID_ARCH 5 /* bad machine */
#define ELF_ERR_INVALID_TYPE 6 /* bad type */
#define ELF_ERR_NO_LOAD_SEGS 7 /* no PT_LOAD segments found */
#define ELF_ERR_ALLOC_FAILED 8 /* AllocatePages failed (check efi_alloc_status) */
/* Elf Load Result object */
struct ElfLoadResult {
uint64_t entry_point;
uint64_t phys_base;
uint64_t virt_base;
uint64_t total_size;
uint64_t efi_alloc_status; /* EFI_STATUS from AllocatePages, valid when error == ELF_ERR_ALLOC_FAILED */
uint8_t error; /* ELF_ERR_* code above */
bool success;
};
|