diff options
Diffstat (limited to 'include/elf/elf.h')
| -rw-r--r-- | include/elf/elf.h | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/include/elf/elf.h b/include/elf/elf.h new file mode 100644 index 0000000..512ba14 --- /dev/null +++ b/include/elf/elf.h @@ -0,0 +1,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; +}; |
