1 2 /** 3 * Compiler implementation of the 4 * $(LINK2 http://www.dlang.org, D programming language). 5 * 6 * Translation to D of Linux's melf.h 7 * 8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/melf.d, backend/melf.d) 9 */ 10 11 module dmd.backend.melf; 12 13 /* ELF file format */ 14 15 alias Elf32_Half = ushort; 16 alias Elf32_Word = uint; 17 alias Elf32_Sword = int; 18 alias Elf32_Addr = uint; 19 alias Elf32_Off = uint; 20 alias elf_u8_f32 = uint; 21 22 enum EI_NIDENT = 16; 23 24 nothrow: 25 26 // EHident 27 enum EI_MAG0 = 0; /* Identification byte offset 0*/ 28 enum EI_MAG1 = 1; /* Identification byte offset 1*/ 29 enum EI_MAG2 = 2; /* Identification byte offset 2*/ 30 enum EI_MAG3 = 3; /* Identification byte offset 3*/ 31 enum ELFMAG0 = 0x7f; /* Magic number byte 0 */ 32 enum ELFMAG1 = 'E'; /* Magic number byte 1 */ 33 enum ELFMAG2 = 'L'; /* Magic number byte 2 */ 34 enum ELFMAG3 = 'F'; /* Magic number byte 3 */ 35 36 enum EI_CLASS = 4; /* File class byte offset 4 */ 37 enum ELFCLASSNONE = 0; // invalid 38 enum ELFCLASS32 = 1; /* 32-bit objects */ 39 enum ELFCLASS64 = 2; /* 64-bit objects */ 40 41 enum EI_DATA = 5; /* Data encoding byte offset 5 */ 42 enum ELFDATANONE = 0; // invalid 43 enum ELFDATA2LSB = 1; /* 2's comp,lsb low address */ 44 enum ELFDATA2MSB = 2; /* 2's comp,msb low address */ 45 46 enum EI_VERSION = 6; /* Header version byte offset 6 */ 47 //enum EV_CURRENT = 1; /* Current header format */ 48 49 enum EI_OSABI = 7; /* OS ABI byte offset 7 */ 50 enum ELFOSABI_SYSV = 0; /* UNIX System V ABI */ 51 enum ELFOSABI_HPUX = 1; /* HP-UX */ 52 enum ELFOSABI_NETBSD = 2; 53 enum ELFOSABI_LINUX = 3; 54 enum ELFOSABI_FREEBSD = 9; 55 enum ELFOSABI_OPENBSD = 12; 56 enum ELFOSABI_ARM = 97; /* ARM */ 57 enum ELFOSABI_STANDALONE = 255; /* Standalone/embedded */ 58 59 enum EI_ABIVERSION = 8; /* ABI version byte offset 8 */ 60 61 enum EI_PAD = 9; /* Byte to start of padding */ 62 63 // e_type 64 enum ET_NONE = 0; /* No specified file type */ 65 enum ET_REL = 1; /* Relocatable object file */ 66 enum ET_EXEC = 2; /* Executable file */ 67 enum ET_DYN = 3; /* Dynamic link object file */ 68 enum ET_CORE = 4; /* Core file */ 69 enum ET_LOPROC = 0xff00; /* Processor low index */ 70 enum ET_HIPROC = 0xffff; /* Processor hi index */ 71 72 // e_machine 73 enum EM_386 = 3; /* Intel 80386 */ 74 enum EM_486 = 6; /* Intel 80486 */ 75 enum EM_X86_64 = 62; // Advanced Micro Devices X86-64 processor 76 77 // e_version 78 enum EV_NONE = 0; // invalid version 79 enum EV_CURRENT = 1; // Current file format 80 81 // e_ehsize 82 enum EH_HEADER_SIZE = 0x34; 83 84 // e_phentsize 85 enum EH_PHTENT_SIZE = 0x20; 86 87 // e_shentsize 88 enum EH_SHTENT_SIZE = 0x28; 89 90 struct Elf32_Ehdr 91 { 92 ubyte[EI_NIDENT] EHident; /* Header identification info */ 93 Elf32_Half e_type; /* Object file type */ 94 Elf32_Half e_machine; /* Machine architecture */ 95 Elf32_Word e_version; /* File format version */ 96 Elf32_Addr e_entry; /* Entry point virtual address */ 97 Elf32_Off e_phoff; /* Program header table(PHT)offset */ 98 Elf32_Off e_shoff; /* Section header table(SHT)offset */ 99 Elf32_Word e_flags; /* Processor-specific flags */ 100 Elf32_Half e_ehsize; /* Size of ELF header (bytes) */ 101 Elf32_Half e_phentsize; /* Size of PHT (bytes) */ 102 Elf32_Half e_phnum; /* Number of PHT entries */ 103 Elf32_Half e_shentsize; /* Size of SHT entry in bytes */ 104 Elf32_Half e_shnum; /* Number of SHT entries */ 105 Elf32_Half e_shstrndx; /* SHT index for string table */ 106 } 107 108 109 /* Section header. */ 110 111 // sh_type 112 enum SHT_NULL = 0; /* SHT entry unused */ 113 enum SHT_PROGBITS = 1; /* Program defined data */ 114 enum SHT_SYMTAB = 2; /* Symbol table */ 115 enum SHT_STRTAB = 3; /* String table */ 116 enum SHT_RELA = 4; /* Relocations with addends */ 117 enum SHT_HASHTAB = 5; /* Symbol hash table */ 118 enum SHT_DYNAMIC = 6; /* String table for dynamic symbols */ 119 enum SHT_NOTE = 7; /* Notes */ 120 enum SHT_RESDATA = 8; /* Reserved data space */ 121 enum SHT_NOBITS = SHT_RESDATA; 122 enum SHT_REL = 9; /* Relocations no addends */ 123 enum SHT_RESTYPE = 10; /* Reserved section type*/ 124 enum SHT_DYNTAB = 11; /* Dynamic linker symbol table */ 125 enum SHT_INIT_ARRAY = 14; /* Array of constructors */ 126 enum SHT_FINI_ARRAY = 15; /* Array of destructors */ 127 enum SHT_GROUP = 17; /* Section group (COMDAT) */ 128 enum SHT_SYMTAB_SHNDX = 18; /* Extended section indices */ 129 130 // sh_flags 131 enum SHF_WRITE = (1 << 0); /* Writable during execution */ 132 enum SHF_ALLOC = (1 << 1); /* In memory during execution */ 133 enum SHF_EXECINSTR = (1 << 2); /* Executable machine instructions*/ 134 enum SHF_MERGE = 0x10; 135 enum SHF_STRINGS = 0x20; 136 enum SHF_INFO_LINK = 0x40; 137 enum SHF_LINK_ORDER = 0x80; 138 enum SHF_OS_NONCONFORMING = 0x100; 139 enum SHF_GROUP = 0x200; // Member of a section group 140 enum SHF_TLS = 0x400; /* Thread local */ 141 enum SHF_MASKPROC = 0xf0000000; /* Mask for processor-specific */ 142 143 struct Elf32_Shdr 144 { 145 Elf32_Word sh_name; /* String table offset for section name */ 146 Elf32_Word sh_type; /* Section type */ 147 Elf32_Word sh_flags; /* Section attribute flags */ 148 Elf32_Addr sh_addr; /* Starting virtual memory address */ 149 Elf32_Off sh_offset; /* Offset to section in file */ 150 Elf32_Word sh_size; /* Size of section */ 151 Elf32_Word sh_link; /* Index to optional related section */ 152 Elf32_Word sh_info; /* Optional extra section information */ 153 Elf32_Word sh_addralign; /* Required section alignment */ 154 Elf32_Word sh_entsize; /* Size of fixed size section entries */ 155 } 156 157 // Special Section Header Table Indices 158 enum SHN_UNDEF = 0; /* Undefined section */ 159 enum SHN_LORESERVE = 0xff00; /* Start of reserved indices */ 160 enum SHN_LOPROC = 0xff00; /* Start of processor-specific */ 161 enum SHN_HIPROC = 0xff1f; /* End of processor-specific */ 162 enum SHN_LOOS = 0xff20; /* Start of OS-specific */ 163 enum SHN_HIOS = 0xff3f; /* End of OS-specific */ 164 enum SHN_ABS = 0xfff1; /* Absolute value for symbol references */ 165 enum SHN_COMMON = 0xfff2; /* Symbol defined in common section */ 166 enum SHN_XINDEX = 0xffff; /* Index is in extra table. */ 167 enum SHN_HIRESERVE = 0xffff; /* End of reserved indices */ 168 169 170 /* Symbol Table */ 171 172 // st_info 173 174 ubyte ELF32_ST_BIND(ubyte s) { return s >> 4; } 175 ubyte ELF32_ST_TYPE(ubyte s) { return s & 0xf; } 176 ubyte ELF32_ST_INFO(ubyte b, ubyte t) { return cast(ubyte)((b << 4) + (t & 0xf)); } 177 178 enum STB_LOCAL = 0; /* Local symbol */ 179 enum STB_GLOBAL = 1; /* Global symbol */ 180 enum STB_WEAK = 2; /* Weak symbol */ 181 enum ST_NUM_BINDINGS = 3; /* Number of defined types. */ 182 enum STB_LOOS = 10; /* Start of OS-specific */ 183 enum STB_HIOS = 12; /* End of OS-specific */ 184 enum STB_LOPROC = 13; /* Start of processor-specific */ 185 enum STB_HIPROC = 15; /* End of processor-specific */ 186 187 enum STT_NOTYPE = 0; /* Symbol type is unspecified */ 188 enum STT_OBJECT = 1; /* Symbol is a data object */ 189 enum STT_FUNC = 2; /* Symbol is a code object */ 190 enum STT_SECTION = 3; /* Symbol associated with a section */ 191 enum STT_FILE = 4; /* Symbol's name is file name */ 192 enum STT_COMMON = 5; 193 enum STT_TLS = 6; 194 enum STT_NUM = 5; /* Number of defined types. */ 195 enum STT_LOOS = 11; /* Start of OS-specific */ 196 enum STT_HIOS = 12; /* End of OS-specific */ 197 enum STT_LOPROC = 13; /* Start of processor-specific */ 198 enum STT_HIPROC = 15; /* End of processor-specific */ 199 200 enum STV_DEFAULT = 0; /* Default symbol visibility rules */ 201 enum STV_INTERNAL = 1; /* Processor specific hidden class */ 202 enum STV_HIDDEN = 2; /* Sym unavailable in other modules */ 203 enum STV_PROTECTED = 3; /* Not preemptible, not exported */ 204 205 206 struct Elf32_Sym 207 { 208 Elf32_Word st_name; /* string table index for symbol name */ 209 Elf32_Addr st_value; /* Associated symbol value */ 210 Elf32_Word st_size; /* Symbol size */ 211 ubyte st_info; /* Symbol type and binding */ 212 ubyte st_other; /* Currently not defined */ 213 Elf32_Half st_shndx; /* SHT index for symbol definition */ 214 } 215 216 217 /* Relocation table entry without addend (in section of type SHT_REL). */ 218 219 220 // r_info 221 222 // 386 Relocation types 223 224 uint ELF32_R_SYM(uint i) { return i >> 8; } /* Symbol idx */ 225 uint ELF32_R_TYPE(uint i) { return i & 0xff; } /* Type of relocation */ 226 uint ELF32_R_INFO(uint i, uint t) { return ((i << 8) + (t & 0xff)); } 227 228 enum R_386_NONE = 0; /* No reloc */ 229 enum R_386_32 = 1; /* Symbol value 32 bit */ 230 enum R_386_PC32 = 2; /* PC relative 32 bit */ 231 enum R_386_GOT32 = 3; /* 32 bit GOT entry */ 232 enum R_386_PLT32 = 4; /* 32 bit PLT address */ 233 enum R_386_COPY = 5; /* Copy symbol at runtime */ 234 enum R_386_GLOB_DAT = 6; /* Create GOT entry */ 235 enum R_386_JMP_SLOT = 7; /* Create PLT entry */ 236 enum R_386_RELATIVE = 8; /* Adjust by program base */ 237 enum R_386_GOTOFF = 9; /* 32 bit offset to GOT */ 238 enum R_386_GOTPC = 10; /* 32 bit PC relative offset to GOT */ 239 enum R_386_TLS_TPOFF = 14; 240 enum R_386_TLS_IE = 15; 241 enum R_386_TLS_GOTIE = 16; 242 enum R_386_TLS_LE = 17; /* negative offset relative to static TLS */ 243 enum R_386_TLS_GD = 18; 244 enum R_386_TLS_LDM = 19; 245 enum R_386_TLS_GD_32 = 24; 246 enum R_386_TLS_GD_PUSH = 25; 247 enum R_386_TLS_GD_CALL = 26; 248 enum R_386_TLS_GD_POP = 27; 249 enum R_386_TLS_LDM_32 = 28; 250 enum R_386_TLS_LDM_PUSH = 29; 251 enum R_386_TLS_LDM_CALL = 30; 252 enum R_386_TLS_LDM_POP = 31; 253 enum R_386_TLS_LDO_32 = 32; 254 enum R_386_TLS_IE_32 = 33; 255 enum R_386_TLS_LE_32 = 34; 256 enum R_386_TLS_DTPMOD32 = 35; 257 enum R_386_TLS_DTPOFF32 = 36; 258 enum R_386_TLS_TPOFF32 = 37; 259 260 struct Elf32_Rel 261 { 262 Elf32_Addr r_offset; /* Address */ 263 Elf32_Word r_info; /* Relocation type and symbol index */ 264 } 265 266 /* stabs debug records */ 267 268 // DBtype 269 enum DBT_UNDEF = 0x00; /* undefined symbol */ 270 enum DBT_EXT = 0x01; /* exernal modifier */ 271 enum DBT_ABS = 0x02; /* absolute */ 272 enum DBT_TEXT = 0x04; /* code text */ 273 enum DBT_DATA = 0x06; /* data */ 274 enum DBT_BSS = 0x08; /* BSS */ 275 enum DBT_INDR = 0x0a; /* indirect to another symbol */ 276 enum DBT_COMM = 0x12; /* common -visible after shr'd lib link */ 277 enum DBT_SETA = 0x14; /* Absolue set element */ 278 enum DBT_SETT = 0x16; /* code text segment set element */ 279 enum DBT_SETD = 0x18; /* data segment set element */ 280 enum DBT_SETB = 0x1a; /* BSS segment set element */ 281 enum DBT_SETV = 0x1c; /* Pointer to set vector */ 282 enum DBT_WARNING = 0x1e; /* print warning during link */ 283 enum DBT_FN = 0x1f; /* name of object file */ 284 285 enum DBT_GSYM = 0x20; /* global symbol */ 286 enum DBT_FUN = 0x24; /* function name */ 287 enum DBT_STSYM = 0x26; /* static data */ 288 enum DBT_LCSYM = 0x28; /* static bss */ 289 enum DBT_MAIN = 0x2a; /* main routine */ 290 enum DBT_RO = 0x2c; /* read only */ 291 enum DBT_OPT = 0x3c; /* target option? */ 292 enum DBT_REG = 0x40; /* register variable */ 293 enum DBT_TLINE = 0x44; /* text line number */ 294 enum DBT_DLINE = 0x46; /* dat line number */ 295 enum DBT_BLINE = 0x48; /* bss line number */ 296 enum DBT_STUN = 0x62; /* structure or union */ 297 enum DBT_SRCF = 0x64; /* source file */ 298 enum DBT_AUTO = 0x80; /* stack variable */ 299 enum DBT_TYPE = 0x80; /* type definition */ 300 enum DBT_INCS = 0x84; /* include file start */ 301 enum DBT_PARAM = 0xa0; /* parameter */ 302 enum DBT_INCE = 0xa2; /* include file end */ 303 304 305 struct elf_stab 306 { 307 Elf32_Word DBstring; /* string table index for the symbol */ 308 elf_u8_f32 DBtype; /* type of the symbol */ 309 elf_u8_f32 DBmisc; /* misc. info */ 310 Elf32_Half DBdesc; /* description field */ 311 Elf32_Word DBvalu; /* symbol value */ 312 } 313 314 315 /* Program header. */ 316 317 // PHtype 318 enum PHT_NULL = 0; /* SHT entry unused */ 319 320 struct Elf32_Phdr 321 { 322 Elf32_Word PHtype; /* Program type */ 323 Elf32_Off PHoff; /* Offset to segment in file */ 324 Elf32_Addr PHvaddr; /* Starting virtual memory address */ 325 Elf32_Addr PHpaddr; /* Starting absolute memory address */ 326 Elf32_Word PHfilesz; /* Size of file image */ 327 Elf32_Word PHmemsz; /* Size of memory image */ 328 Elf32_Word PHflags; /* Program attribute flags */ 329 Elf32_Word PHalign; /* Program loading alignment */ 330 } 331 332 333 334 /* Legal values for sh_flags (section flags). */ 335 336 /***************************** 64 bit Elf *****************************************/ 337 338 alias Elf64_Addr = ulong; 339 alias Elf64_Off = ulong; 340 alias Elf64_Xword = ulong; 341 alias Elf64_Sxword = long; 342 alias Elf64_Sword = int; 343 alias Elf64_Word = uint; 344 alias Elf64_Half = ushort; 345 346 struct Elf64_Ehdr 347 { 348 ubyte[EI_NIDENT] EHident; /* Header identification info */ 349 Elf64_Half e_type; 350 Elf64_Half e_machine; 351 Elf64_Word e_version; 352 Elf64_Addr e_entry; 353 Elf64_Off e_phoff; 354 Elf64_Off e_shoff; 355 Elf64_Word e_flags; 356 Elf64_Half e_ehsize; 357 Elf64_Half e_phentsize; 358 Elf64_Half e_phnum; 359 Elf64_Half e_shentsize; 360 Elf64_Half e_shnum; 361 Elf64_Half e_shstrndx; 362 } 363 364 struct Elf64_Shdr 365 { 366 Elf64_Word sh_name; 367 Elf64_Word sh_type; 368 Elf64_Xword sh_flags; 369 Elf64_Addr sh_addr; 370 Elf64_Off sh_offset; 371 Elf64_Xword sh_size; 372 Elf64_Word sh_link; 373 Elf64_Word sh_info; 374 Elf64_Xword sh_addralign; 375 Elf64_Xword sh_entsize; 376 } 377 378 struct Elf64_Phdr 379 { 380 Elf64_Word p_type; 381 Elf64_Word p_flags; 382 Elf64_Off p_offset; 383 Elf64_Addr p_vaddr; 384 Elf64_Addr p_paddr; 385 Elf64_Xword p_filesz; 386 Elf64_Xword p_memsz; 387 Elf64_Xword p_align; 388 } 389 390 struct Elf64_Sym 391 { 392 Elf64_Word st_name; 393 ubyte st_info; 394 ubyte st_other; 395 Elf64_Half st_shndx; 396 Elf64_Addr st_value; 397 Elf64_Xword st_size; 398 } 399 400 ubyte ELF64_ST_BIND(ubyte s) { return ELF32_ST_BIND(s); } 401 ubyte ELF64_ST_TYPE(ubyte s) { return ELF32_ST_TYPE(s); } 402 ubyte ELF64_ST_INFO(ubyte b, ubyte t) { return ELF32_ST_INFO(b,t); } 403 404 // r_info 405 uint ELF64_R_SYM(ulong i) { return cast(Elf64_Word)(i>>32); } 406 uint ELF64_R_TYPE(ulong i) { return cast(Elf64_Word)(i & 0xFFFF_FFFF); } 407 ulong ELF64_R_INFO(ulong s, ulong t) { return ((cast(Elf64_Xword)s)<<32)|cast(Elf64_Word)t; } 408 409 // X86-64 Relocation types 410 411 enum R_X86_64_NONE = 0; // -- No relocation 412 enum R_X86_64_64 = 1; // 64 Direct 64 bit 413 enum R_X86_64_PC32 = 2; // 32 PC relative 32 bit signed 414 enum R_X86_64_GOT32 = 3; // 32 32 bit GOT entry 415 enum R_X86_64_PLT32 = 4; // 32 bit PLT address 416 enum R_X86_64_COPY = 5; // -- Copy symbol at runtime 417 enum R_X86_64_GLOB_DAT = 6; // 64 Create GOT entry 418 enum R_X86_64_JUMP_SLOT = 7; // 64 Create PLT entry 419 enum R_X86_64_RELATIVE = 8; // 64 Adjust by program base 420 enum R_X86_64_GOTPCREL = 9; // 32 32 bit signed pc relative offset to GOT 421 enum R_X86_64_32 = 10; // 32 Direct 32 bit zero extended 422 enum R_X86_64_32S = 11; // 32 Direct 32 bit sign extended 423 enum R_X86_64_16 = 12; // 16 Direct 16 bit zero extended 424 enum R_X86_64_PC16 = 13; // 16 16 bit sign extended pc relative 425 enum R_X86_64_8 = 14; // 8 Direct 8 bit sign extended 426 enum R_X86_64_PC8 = 15; // 8 8 bit sign extended pc relative 427 enum R_X86_64_DTPMOD64 = 16; // 64 ID of module containing symbol 428 enum R_X86_64_DTPOFF64 = 17; // 64 Offset in TLS block 429 enum R_X86_64_TPOFF64 = 18; // 64 Offset in initial TLS block 430 enum R_X86_64_TLSGD = 19; // 32 PC relative offset to GD GOT block 431 enum R_X86_64_TLSLD = 20; // 32 PC relative offset to LD GOT block 432 enum R_X86_64_DTPOFF32 = 21; // 32 Offset in TLS block 433 enum R_X86_64_GOTTPOFF = 22; // 32 PC relative offset to IE GOT entry 434 enum R_X86_64_TPOFF32 = 23; // 32 Offset in initial TLS block 435 enum R_X86_64_PC64 = 24; // 64 436 enum R_X86_64_GOTOFF64 = 25; // 64 437 enum R_X86_64_GOTPC32 = 26; // 32 438 enum R_X86_64_GNU_VTINHERIT = 250; // GNU C++ hack 439 enum R_X86_64_GNU_VTENTRY = 251; // GNU C++ hack 440 441 struct Elf64_Rel 442 { 443 Elf64_Addr r_offset; 444 Elf64_Xword r_info; 445 446 } 447 448 struct Elf64_Rela 449 { 450 Elf64_Addr r_offset; 451 Elf64_Xword r_info; 452 Elf64_Sxword r_addend; 453 } 454 455 // Section Group Flags 456 enum GRP_COMDAT = 1; 457 enum GRP_MASKOS = 0x0ff0_0000; 458 enum GRP_MASKPROC = 0xf000_0000; 459 460