summaryrefslogtreecommitdiff
path: root/include/elf/elf.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/elf/elf.h')
-rw-r--r--include/elf/elf.h331
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;
+};