1 /**
2  * Microsoft COFF object file format
3  *
4  * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/mscoff.d, backend/_mscoff.d)
5  */
6 
7 module dmd.backend.mscoff;
8 
9 // Online documentation: https://dlang.org/phobos/dmd_backend_mscoff.html
10 
11 @safe:
12 align (1):
13 
14 /***********************************************/
15 
16 struct BIGOBJ_HEADER
17 {
18     ushort Sig1;                 // IMAGE_FILE_MACHINE_UNKNOWN
19     ushort Sig2;                 // 0xFFFF
20     ushort Version;              // 2
21     ushort Machine;              // identifies type of target machine
22     uint TimeDateStamp;          // creation date, number of seconds since 1970
23     ubyte[16] UUID;              //  { '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b',
24                                  //    '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8' };
25     uint[4] unused;              // { 0, 0, 0, 0 }
26     uint NumberOfSections;       // number of sections
27     uint PointerToSymbolTable;   // file offset of symbol table
28     uint NumberOfSymbols;        // number of entries in the symbol table
29 }
30 
31 static assert(BIGOBJ_HEADER.sizeof == 56);
32 
33 enum
34 {
35     IMAGE_FILE_MACHINE_UNKNOWN            = 0,           // applies to any machine type
36     IMAGE_FILE_MACHINE_I386               = 0x14C,       // x86
37     IMAGE_FILE_MACHINE_AMD64              = 0x8664,      // x86_64
38 
39     IMAGE_FILE_RELOCS_STRIPPED            = 1,
40     IMAGE_FILE_EXECUTABLE_IMAGE           = 2,
41     IMAGE_FILE_LINE_NUMS_STRIPPED         = 4,
42     IMAGE_FILE_LOCAL_SYMS_STRIPPED        = 8,
43     IMAGE_FILE_AGGRESSIVE_WS_TRIM         = 0x10,
44     IMAGE_FILE_LARGE_ADDRESS_AWARE        = 0x20,
45     IMAGE_FILE_BYTES_REVERSED_LO          = 0x80,
46     IMAGE_FILE_32BIT_MACHINE              = 0x100,
47     IMAGE_FILE_DEBUG_STRIPPED             = 0x200,
48     IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP    = 0x400,
49     IMAGE_FILE_NET_RUN_FROM_SWAP          = 0x800,
50     IMAGE_FILE_SYSTEM                     = 0x1000,
51     IMAGE_FILE_DLL                        = 0x2000,
52     IMAGE_FILE_UP_SYSTEM_ONLY             = 0x4000,
53     IMAGE_FILE_BYTES_REVERSED_HI          = 0x8000,
54 }
55 
56 struct IMAGE_FILE_HEADER
57 {
58     ushort Machine;
59     ushort NumberOfSections;
60     uint TimeDateStamp;
61     uint PointerToSymbolTable;
62     uint NumberOfSymbols;
63     ushort SizeOfOptionalHeader;
64     ushort Characteristics;
65 }
66 
67 static assert(IMAGE_FILE_HEADER.sizeof == 20);
68 
69 /***********************************************/
70 
71 enum IMAGE_SIZEOF_SHORT_NAME = 8;
72 
73 struct IMAGE_SECTION_HEADER
74 {
75     ubyte[IMAGE_SIZEOF_SHORT_NAME] Name;
76     uint VirtualSize;
77     uint VirtualAddress;
78     uint SizeOfRawData;
79     uint PointerToRawData;
80     uint PointerToRelocations;
81     uint PointerToLinenumbers;
82     ushort NumberOfRelocations;
83     ushort NumberOfLinenumbers;
84     uint Characteristics;
85 }
86 
87 enum
88 {
89     IMAGE_SCN_TYPE_NO_PAD           = 8,       // obsolete
90     IMAGE_SCN_CNT_CODE              = 0x20,    // code section
91     IMAGE_SCN_CNT_INITIALIZED_DATA  = 0x40,
92     IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80,
93     IMAGE_SCN_LNK_OTHER             = 0x100,
94     IMAGE_SCN_LNK_INFO              = 0x200,   // comments; for .drectve section
95     IMAGE_SCN_LNK_REMOVE            = 0x800,   // do not put in image file
96     IMAGE_SCN_LNK_COMDAT            = 0x1000,  // COMDAT section
97     IMAGE_SCN_GPREL                 = 0x8000,  // data referenced through global pointer GP
98     IMAGE_SCN_MEM_PURGEABLE         = 0x20000,
99     IMAGE_SCN_MEM_16BIT             = 0x20000,
100     IMAGE_SCN_MEM_LOCKED            = 0x40000,
101     IMAGE_SCN_MEM_PRELOAD           = 0x80000,
102     IMAGE_SCN_ALIGN_1BYTES          = 0x100000,
103     IMAGE_SCN_ALIGN_2BYTES          = 0x200000,
104     IMAGE_SCN_ALIGN_4BYTES          = 0x300000,
105     IMAGE_SCN_ALIGN_8BYTES          = 0x400000,
106     IMAGE_SCN_ALIGN_16BYTES         = 0x500000,
107     IMAGE_SCN_ALIGN_32BYTES         = 0x600000,
108     IMAGE_SCN_ALIGN_64BYTES         = 0x700000,
109     IMAGE_SCN_ALIGN_128BYTES        = 0x800000,
110     IMAGE_SCN_ALIGN_256BYTES        = 0x900000,
111     IMAGE_SCN_ALIGN_512BYTES        = 0xA00000,
112     IMAGE_SCN_ALIGN_1024BYTES       = 0xB00000,
113     IMAGE_SCN_ALIGN_2048BYTES       = 0xC00000,
114     IMAGE_SCN_ALIGN_4096BYTES       = 0xD00000,
115     IMAGE_SCN_ALIGN_8192BYTES       = 0xE00000,
116     IMAGE_SCN_LNK_NRELOC_OVFL       = 0x1000000,     // more than 0xFFFF relocations
117     IMAGE_SCN_MEM_DISCARDABLE       = 0x2000000,     // can be discarded
118     IMAGE_SCN_MEM_NOT_CACHED        = 0x4000000,     // cannot be cached
119     IMAGE_SCN_MEM_NOT_PAGED         = 0x8000000,     // cannot be paged
120     IMAGE_SCN_MEM_SHARED            = 0x10000000,    // can be shared
121     IMAGE_SCN_MEM_EXECUTE           = 0x20000000,    // executable code
122     IMAGE_SCN_MEM_READ              = 0x40000000,    // readable
123     IMAGE_SCN_MEM_WRITE             = 0x80000000,    // writeable
124 }
125 
126 /***********************************************/
127 
128 enum SYMNMLEN = 8;
129 
130 enum
131 {
132     IMAGE_SYM_DEBUG                 = -2,
133     IMAGE_SYM_ABSOLUTE              = -1,
134     IMAGE_SYM_UNDEFINED             = 0,
135 
136 /* Values for n_sclass  */
137     IMAGE_SYM_CLASS_EXTERNAL        = 2,
138     IMAGE_SYM_CLASS_STATIC          = 3,
139     IMAGE_SYM_CLASS_LABEL           = 6,
140     IMAGE_SYM_CLASS_FUNCTION        = 101,
141     IMAGE_SYM_CLASS_FILE            = 103,
142 }
143 
144 struct SymbolTable32
145 {
146     union
147     {
148         ubyte[SYMNMLEN] Name;
149         struct
150         {
151             uint Zeros;
152             uint Offset;
153         }
154     }
155     uint Value;
156     int SectionNumber;
157     ushort Type;
158     ubyte StorageClass;
159     ubyte NumberOfAuxSymbols;
160 }
161 
162 static assert(SymbolTable32.sizeof == 20);
163 
164 struct SymbolTable
165 {
166     ubyte[SYMNMLEN] Name;
167     uint Value;
168     short SectionNumber;
169     ushort Type;
170     ubyte StorageClass;
171     ubyte NumberOfAuxSymbols;
172 }
173 
174 static assert(SymbolTable.sizeof == 18);
175 
176 /***********************************************/
177 
178 struct reloc
179 {
180   align (1):
181     uint r_vaddr;           // file offset of relocation
182     uint r_symndx;          // symbol table index
183     ushort r_type;          // IMAGE_REL_XXX kind of relocation to be performed
184 }
185 
186 static assert(reloc.sizeof == 10);
187 
188 enum
189 {
190     IMAGE_REL_AMD64_ABSOLUTE        = 0,
191     IMAGE_REL_AMD64_ADDR64          = 1,
192     IMAGE_REL_AMD64_ADDR32          = 2,
193     IMAGE_REL_AMD64_ADDR32NB        = 3,
194     IMAGE_REL_AMD64_REL32           = 4,
195     IMAGE_REL_AMD64_REL32_1         = 5,
196     IMAGE_REL_AMD64_REL32_2         = 6,
197     IMAGE_REL_AMD64_REL32_3         = 7,
198     IMAGE_REL_AMD64_REL32_4         = 8,
199     IMAGE_REL_AMD64_REL32_5         = 9,
200     IMAGE_REL_AMD64_SECTION         = 0xA,
201     IMAGE_REL_AMD64_SECREL          = 0xB,
202     IMAGE_REL_AMD64_SECREL7         = 0xC,
203     IMAGE_REL_AMD64_TOKEN           = 0xD,
204     IMAGE_REL_AMD64_SREL32          = 0xE,
205     IMAGE_REL_AMD64_PAIR            = 0xF,
206     IMAGE_REL_AMD64_SSPAN32         = 0x10,
207 
208     IMAGE_REL_I386_ABSOLUTE         = 0,
209     IMAGE_REL_I386_DIR16            = 1,
210     IMAGE_REL_I386_REL16            = 2,
211     IMAGE_REL_I386_DIR32            = 6,
212     IMAGE_REL_I386_DIR32NB          = 7,
213     IMAGE_REL_I386_SEG12            = 9,
214     IMAGE_REL_I386_SECTION          = 0xA,
215     IMAGE_REL_I386_SECREL           = 0xB,
216     IMAGE_REL_I386_TOKEN            = 0xC,
217     IMAGE_REL_I386_SECREL7          = 0xD,
218     IMAGE_REL_I386_REL32            = 0x14,
219 }
220 
221 /***********************************************/
222 
223 struct lineno
224 {
225     union U
226     {
227         uint l_symndx;
228         uint l_paddr;
229     }
230     U l_addr;
231     ushort l_lnno;
232 }
233 
234 static assert(lineno.sizeof == 6);
235 
236 /***********************************************/
237 
238 union auxent
239 {
240   align (1):
241     // Function definitions
242     struct FD
243     {   uint TagIndex;
244         uint TotalSize;
245         uint PointerToLinenumber;
246         uint PointerToNextFunction;
247         ushort Zeros;
248     }
249     FD x_fd;
250 
251     // .bf symbols
252     struct BF
253     {
254       align (1):
255         uint Unused;
256         ushort Linenumber;
257         char[6] filler;
258         uint PointerToNextFunction;
259         ushort Zeros;
260     }
261     BF x_bf;
262 
263     // .ef symbols
264     struct EF
265     {   uint Unused;
266         ushort Linenumber;
267         ushort Zeros;
268     }
269     EF x_ef;
270 
271     // Weak externals
272     struct WE
273     {   uint TagIndex;
274         uint Characteristics;
275         ushort Zeros;
276         // IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY
277         // IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
278         // IMAGE_WEAK_EXTERN_SEARCH_ALIAS
279     }
280     WE x_weak;
281 
282     // Section definitions
283     struct S
284     {
285         uint length;
286         ushort NumberOfRelocations;
287         ushort NumberOfLinenumbers;
288         uint CheckSum;
289         ushort NumberLowPart;
290         ubyte Selection;
291         ubyte Unused;
292         ushort NumberHighPart;
293     }
294     S x_section;
295 
296     char[18] filler;
297 }
298 
299 static assert(auxent.sizeof == 18);
300 
301 // auxent.x_section.Zeros
302 enum
303 {
304     IMAGE_COMDAT_SELECT_NODUPLICATES        = 1,
305     IMAGE_COMDAT_SELECT_ANY                 = 2,
306     IMAGE_COMDAT_SELECT_SAME_SIZE           = 3,
307     IMAGE_COMDAT_SELECT_EXACT_MATCH         = 4,
308     IMAGE_COMDAT_SELECT_ASSOCIATIVE         = 5,
309     IMAGE_COMDAT_SELECT_LARGEST             = 6,
310 }
311 
312 /***********************************************/