1 /// Copyright: Copyright (c) 2020 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 5 /// Resources: 6 /// - https://www.muppetlabs.com/~breadbox/software/ELF.txt 7 /// - ELF-64 Object File Format: Version 1.5 Draft 2, May 27, 1998 8 /// - http://www.skyfree.org/linux/references/ELF_Format.pdf 9 /// - https://github.com/aspieln3r/spergland/wiki/ELF-File-:-short-summary 10 /// - https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html 11 12 /// An ELF object file consists of the following parts: 13 /// * File header, which must appear at the beginning of the file. 14 /// * Section table, required for relocatable files, and optional for loadable files. 15 /// * Program header table, required for loadable files, and optional for 16 /// relocatable files. This table describes the loadable segments and other 17 /// data structures required for loading a program or dynamically-linked 18 /// library in preparation for execution. 19 /// * Contents of the sections or segments, including loadable data, relocations, 20 /// and string and symbol tables. 21 module vox.be.elf64; 22 23 /// The file header is located at the beginning of the file, and is used to locate the other parts of the file. 24 struct Elf64Header { 25 char[4] magic = "\x7FELF"; 26 ElfObjectFileClass file_class = ElfObjectFileClass.ELFCLASS64; 27 ElfDataEncoding data_encoding = ElfDataEncoding.ELFDATA2LSB; 28 ubyte file_version = 1; // Object file format version, always 1 29 ElfOsAbi os_abi; // Identifies the operating system and ABI for which the object is prepared 30 // Specifies version of the ABI in os_abi field 31 // For applications conforming to the System V ABI, third edition, this field should contain 0. 32 ubyte abi_version = 0; 33 ubyte[7] pad; 34 35 ElfObjectFileType file_type; // Object file type 36 ElfMachineType machine; // Machine type. These values are defined in the processor-specific supplements. 37 uint _version = 1; // Object file format version 38 // Contains the virtual address of the program entry point. If there is no entry point, this field contains zero. 39 ulong entry; // Entry point address 40 ulong phoff = 64; // Program header file offset in bytes 41 ulong shoff; // Section header file offset in bytes 42 uint flags; // Processor-specific flags 43 ushort ehsize = 64; // ELF header size in bytes 44 ushort phentsize = 56; // Program header table single entry size in bytes. 45 ushort phnum; // Program header table number of entries. 46 ushort shentsize = 64; // Section header table single entry size in bytes. 47 ushort shnum; // Section header table number of entries. 48 // Contains the section header table index of the section containing 49 // the section name string table. If there is no section name string 50 // table, this field has the value SHN_UNDEF (0) 51 ushort shstrndx; // String table index 52 } 53 static assert(Elf64Header.sizeof == 64); 54 55 // Object File Classes, identifies the class of the object file, or its capacity. 56 enum ElfObjectFileClass : ubyte { 57 ELFCLASSNONE = 0, /// Invalid class 58 ELFCLASS32 = 1, /// 32-bit objects 59 ELFCLASS64 = 2, /// 64-bit objects 60 } 61 62 // Data Encodings 63 enum ElfDataEncoding : ubyte { 64 ELFDATA2LSB = 1, /// Object file data structures are little-endian 65 ELFDATA2MSB = 2, /// Object file data structures are big-endian 66 } 67 68 // Operating System and ABI Identifiers, 69 enum ElfOsAbi : ubyte { 70 ELFOSABI_SYSV = 0, /// System V ABI 71 ELFOSABI_HPUX = 1, /// HP-UX operating system 72 ELFOSABI_STANDALONE = 255, /// Standalone (embedded) application 73 } 74 75 // Object File Types 76 enum ElfObjectFileType : ushort { 77 ET_NONE = 0, /// No file type 78 ET_REL = 1, /// Relocatable object file 79 ET_EXEC = 2, /// Executable file 80 ET_DYN = 3, /// Shared object file 81 ET_CORE = 4, /// Core file 82 ET_LOOS = 0xFE00, /// Environment-specific use 83 ET_HIOS = 0xFEFF, /// 84 ET_LOPROC = 0xFF00, /// Processor-specific use 85 ET_HIPROC = 0xFFFF, /// 86 } 87 88 enum ElfMachineType : ushort { 89 x86 = 0x03, /// x86 90 x86_64 = 0x3E, /// amd64 91 arm = 0x28, 92 arm64 = 0xB7, /// aarch64 93 riscv = 0xF3, /// RISC-V 94 } 95 96 // Section index 0, and indices in the range 0xFF00–0xFFFF are reserved for special purposes. 97 // The first entry in the section header table (with an index of 0) is reserved, and must contain all zeroes. 98 enum ElfSectionIndicies : ushort { 99 SHN_UNDEF = 0, /// Used to mark an undefined or meaningless section reference 100 SHN_LOPROC = 0xFF00, /// Processor-specific use 101 SHN_HIPROC = 0xFF1F, 102 SHN_LOOS = 0xFF20, /// Environment-specific use 103 SHN_HIOS = 0xFF3F, 104 SHN_ABS = 0xFFF1, /// Indicates that the corresponding reference is an absolute value 105 SHN_COMMON = 0xFFF2, /// Indicates a symbol that has been declared as a common block (Fortran COMMON or C tentative declaration) 106 } 107 108 struct Elf64SectionHeader { 109 uint sh_name; /// Section name 110 uint sh_type; /// Section type 111 ulong sh_flags; /// Section attributes 112 ulong sh_addr; /// Virtual address in memory 113 ulong sh_offset; /// Offset in file 114 ulong sh_size; /// Size of section 115 uint sh_link; /// Link to other section 116 uint sh_info; /// Miscellaneous information 117 ulong sh_addralign; /// Address alignment boundary 118 ulong sh_entsize; /// Size of entries, if section has table 119 } 120 121 struct Elf64ProgramHeader { 122 Elf64SegmentType type; /// Type of segment 123 uint flags; /// Segment attributes (set of Elf64SegmentAttributes) 124 ulong offset; /// Offset in file 125 ulong vaddr; /// Virtual address in memory 126 ulong paddr; /// Reserved 127 ulong filesz; /// Size of segment in file 128 ulong memsz; /// Size of segment in memory 129 ulong alignment; /// Alignment of segment 130 } 131 132 enum Elf64SegmentType : uint { 133 PT_NULL = 0, /// Unused entry 134 PT_LOAD = 1, /// Loadable segment 135 PT_DYNAMIC = 2, /// Dynamic linking tables 136 /// If PT_INTERP segment is added, then PT_DYNAMIC must be present too 137 /// Otherwise it is invalid executable 138 PT_INTERP = 3, /// Program interpreter path name 139 PT_NOTE = 4, /// Note sections 140 PT_SHLIB = 5, /// Reserved 141 PT_PHDR = 6, /// Program header table 142 PT_TLS = 7, /// Thread Local Storage http://www.sco.com/developers/gabi/latest/ch5.pheader.html#tls 143 PT_LOOS = 0x6000_0000, /// Environment-specific use 144 PT_HIOS = 0x6FFF_FFFF, 145 PT_LOPROC = 0x7000_0000, /// Processor-specific use 146 PT_HIPROC = 0X7FFF_FFFF, 147 /// The array element specifies the location and size of the 148 /// exception handling information as defined by the .eh_frame_hdr section. 149 PT_GNU_EH_FRAME = 0X6474E550, 150 /// The p_flags member specifies the permissions on the segment containing the stack and 151 /// is used to indicate wether the stack should be executable. The absense of this header 152 /// indicates that the stack will be executable. 153 PT_GNU_STACK = 0X6474E551, 154 /// The array element specifies the location and size of a segment which may be made 155 /// read-only after relocation shave been processed. 156 PT_GNU_RELRO = 0X6474E552, 157 } 158 159 enum Elf64SegmentAttributes : uint { 160 EXECUTE = 0x1, /// Execute permission 161 WRITE = 0x2, /// Write permission 162 READ = 0x4, /// Read permission 163 PF_MASKOS = 0x00FF_0000, /// These flag bits are reserved for environment-specific use 164 PF_MASKPROC = 0xFF00_0000, /// These flag bits are reserved for processor-specific use 165 }