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