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