]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file declares the COFFObjectFile class. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #ifndef LLVM_OBJECT_COFF_H | |
15 | #define LLVM_OBJECT_COFF_H | |
16 | ||
1a4d82fc | 17 | #include "llvm/ADT/PointerUnion.h" |
223e47cc LB |
18 | #include "llvm/Object/ObjectFile.h" |
19 | #include "llvm/Support/COFF.h" | |
20 | #include "llvm/Support/Endian.h" | |
1a4d82fc | 21 | #include "llvm/Support/ErrorOr.h" |
223e47cc LB |
22 | |
23 | namespace llvm { | |
1a4d82fc | 24 | template <typename T> class ArrayRef; |
223e47cc LB |
25 | |
26 | namespace object { | |
1a4d82fc | 27 | class ImportDirectoryEntryRef; |
85aaf69f | 28 | class DelayImportDirectoryEntryRef; |
1a4d82fc | 29 | class ExportDirectoryEntryRef; |
85aaf69f SL |
30 | class ImportedSymbolRef; |
31 | class BaseRelocRef; | |
1a4d82fc | 32 | typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; |
85aaf69f SL |
33 | typedef content_iterator<DelayImportDirectoryEntryRef> |
34 | delay_import_directory_iterator; | |
1a4d82fc | 35 | typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator; |
85aaf69f SL |
36 | typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator; |
37 | typedef content_iterator<BaseRelocRef> base_reloc_iterator; | |
1a4d82fc JJ |
38 | |
39 | /// The DOS compatible header at the front of all PE/COFF executables. | |
40 | struct dos_header { | |
85aaf69f | 41 | char Magic[2]; |
1a4d82fc JJ |
42 | support::ulittle16_t UsedBytesInTheLastPage; |
43 | support::ulittle16_t FileSizeInPages; | |
44 | support::ulittle16_t NumberOfRelocationItems; | |
45 | support::ulittle16_t HeaderSizeInParagraphs; | |
46 | support::ulittle16_t MinimumExtraParagraphs; | |
47 | support::ulittle16_t MaximumExtraParagraphs; | |
48 | support::ulittle16_t InitialRelativeSS; | |
49 | support::ulittle16_t InitialSP; | |
50 | support::ulittle16_t Checksum; | |
51 | support::ulittle16_t InitialIP; | |
52 | support::ulittle16_t InitialRelativeCS; | |
53 | support::ulittle16_t AddressOfRelocationTable; | |
54 | support::ulittle16_t OverlayNumber; | |
55 | support::ulittle16_t Reserved[4]; | |
56 | support::ulittle16_t OEMid; | |
57 | support::ulittle16_t OEMinfo; | |
58 | support::ulittle16_t Reserved2[10]; | |
59 | support::ulittle32_t AddressOfNewExeHeader; | |
60 | }; | |
223e47cc LB |
61 | |
62 | struct coff_file_header { | |
63 | support::ulittle16_t Machine; | |
64 | support::ulittle16_t NumberOfSections; | |
65 | support::ulittle32_t TimeDateStamp; | |
66 | support::ulittle32_t PointerToSymbolTable; | |
67 | support::ulittle32_t NumberOfSymbols; | |
68 | support::ulittle16_t SizeOfOptionalHeader; | |
69 | support::ulittle16_t Characteristics; | |
1a4d82fc JJ |
70 | |
71 | bool isImportLibrary() const { return NumberOfSections == 0xffff; } | |
223e47cc LB |
72 | }; |
73 | ||
1a4d82fc JJ |
74 | struct coff_bigobj_file_header { |
75 | support::ulittle16_t Sig1; | |
76 | support::ulittle16_t Sig2; | |
77 | support::ulittle16_t Version; | |
78 | support::ulittle16_t Machine; | |
79 | support::ulittle32_t TimeDateStamp; | |
80 | uint8_t UUID[16]; | |
81 | support::ulittle32_t unused1; | |
82 | support::ulittle32_t unused2; | |
83 | support::ulittle32_t unused3; | |
84 | support::ulittle32_t unused4; | |
85 | support::ulittle32_t NumberOfSections; | |
86 | support::ulittle32_t PointerToSymbolTable; | |
87 | support::ulittle32_t NumberOfSymbols; | |
88 | }; | |
89 | ||
90 | /// The 32-bit PE header that follows the COFF header. | |
91 | struct pe32_header { | |
92 | support::ulittle16_t Magic; | |
93 | uint8_t MajorLinkerVersion; | |
94 | uint8_t MinorLinkerVersion; | |
95 | support::ulittle32_t SizeOfCode; | |
96 | support::ulittle32_t SizeOfInitializedData; | |
97 | support::ulittle32_t SizeOfUninitializedData; | |
98 | support::ulittle32_t AddressOfEntryPoint; | |
99 | support::ulittle32_t BaseOfCode; | |
100 | support::ulittle32_t BaseOfData; | |
101 | support::ulittle32_t ImageBase; | |
102 | support::ulittle32_t SectionAlignment; | |
103 | support::ulittle32_t FileAlignment; | |
104 | support::ulittle16_t MajorOperatingSystemVersion; | |
105 | support::ulittle16_t MinorOperatingSystemVersion; | |
106 | support::ulittle16_t MajorImageVersion; | |
107 | support::ulittle16_t MinorImageVersion; | |
108 | support::ulittle16_t MajorSubsystemVersion; | |
109 | support::ulittle16_t MinorSubsystemVersion; | |
110 | support::ulittle32_t Win32VersionValue; | |
111 | support::ulittle32_t SizeOfImage; | |
112 | support::ulittle32_t SizeOfHeaders; | |
113 | support::ulittle32_t CheckSum; | |
114 | support::ulittle16_t Subsystem; | |
85aaf69f | 115 | // FIXME: This should be DllCharacteristics. |
1a4d82fc JJ |
116 | support::ulittle16_t DLLCharacteristics; |
117 | support::ulittle32_t SizeOfStackReserve; | |
118 | support::ulittle32_t SizeOfStackCommit; | |
119 | support::ulittle32_t SizeOfHeapReserve; | |
120 | support::ulittle32_t SizeOfHeapCommit; | |
121 | support::ulittle32_t LoaderFlags; | |
85aaf69f | 122 | // FIXME: This should be NumberOfRvaAndSizes. |
1a4d82fc JJ |
123 | support::ulittle32_t NumberOfRvaAndSize; |
124 | }; | |
125 | ||
126 | /// The 64-bit PE header that follows the COFF header. | |
127 | struct pe32plus_header { | |
128 | support::ulittle16_t Magic; | |
129 | uint8_t MajorLinkerVersion; | |
130 | uint8_t MinorLinkerVersion; | |
131 | support::ulittle32_t SizeOfCode; | |
132 | support::ulittle32_t SizeOfInitializedData; | |
133 | support::ulittle32_t SizeOfUninitializedData; | |
134 | support::ulittle32_t AddressOfEntryPoint; | |
135 | support::ulittle32_t BaseOfCode; | |
136 | support::ulittle64_t ImageBase; | |
137 | support::ulittle32_t SectionAlignment; | |
138 | support::ulittle32_t FileAlignment; | |
139 | support::ulittle16_t MajorOperatingSystemVersion; | |
140 | support::ulittle16_t MinorOperatingSystemVersion; | |
141 | support::ulittle16_t MajorImageVersion; | |
142 | support::ulittle16_t MinorImageVersion; | |
143 | support::ulittle16_t MajorSubsystemVersion; | |
144 | support::ulittle16_t MinorSubsystemVersion; | |
145 | support::ulittle32_t Win32VersionValue; | |
146 | support::ulittle32_t SizeOfImage; | |
147 | support::ulittle32_t SizeOfHeaders; | |
148 | support::ulittle32_t CheckSum; | |
149 | support::ulittle16_t Subsystem; | |
150 | support::ulittle16_t DLLCharacteristics; | |
151 | support::ulittle64_t SizeOfStackReserve; | |
152 | support::ulittle64_t SizeOfStackCommit; | |
153 | support::ulittle64_t SizeOfHeapReserve; | |
154 | support::ulittle64_t SizeOfHeapCommit; | |
155 | support::ulittle32_t LoaderFlags; | |
156 | support::ulittle32_t NumberOfRvaAndSize; | |
157 | }; | |
158 | ||
159 | struct data_directory { | |
160 | support::ulittle32_t RelativeVirtualAddress; | |
161 | support::ulittle32_t Size; | |
162 | }; | |
163 | ||
164 | struct import_directory_table_entry { | |
165 | support::ulittle32_t ImportLookupTableRVA; | |
166 | support::ulittle32_t TimeDateStamp; | |
167 | support::ulittle32_t ForwarderChain; | |
168 | support::ulittle32_t NameRVA; | |
169 | support::ulittle32_t ImportAddressTableRVA; | |
170 | }; | |
171 | ||
85aaf69f SL |
172 | template <typename IntTy> |
173 | struct import_lookup_table_entry { | |
174 | IntTy Data; | |
1a4d82fc | 175 | |
85aaf69f | 176 | bool isOrdinal() const { return Data < 0; } |
1a4d82fc JJ |
177 | |
178 | uint16_t getOrdinal() const { | |
179 | assert(isOrdinal() && "ILT entry is not an ordinal!"); | |
85aaf69f | 180 | return Data & 0xFFFF; |
1a4d82fc JJ |
181 | } |
182 | ||
183 | uint32_t getHintNameRVA() const { | |
184 | assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); | |
85aaf69f | 185 | return Data & 0xFFFFFFFF; |
1a4d82fc JJ |
186 | } |
187 | }; | |
188 | ||
85aaf69f SL |
189 | typedef import_lookup_table_entry<support::little32_t> |
190 | import_lookup_table_entry32; | |
191 | typedef import_lookup_table_entry<support::little64_t> | |
192 | import_lookup_table_entry64; | |
193 | ||
194 | struct delay_import_directory_table_entry { | |
195 | // dumpbin reports this field as "Characteristics" instead of "Attributes". | |
196 | support::ulittle32_t Attributes; | |
197 | support::ulittle32_t Name; | |
198 | support::ulittle32_t ModuleHandle; | |
199 | support::ulittle32_t DelayImportAddressTable; | |
200 | support::ulittle32_t DelayImportNameTable; | |
201 | support::ulittle32_t BoundDelayImportTable; | |
202 | support::ulittle32_t UnloadDelayImportTable; | |
203 | support::ulittle32_t TimeStamp; | |
204 | }; | |
205 | ||
1a4d82fc JJ |
206 | struct export_directory_table_entry { |
207 | support::ulittle32_t ExportFlags; | |
208 | support::ulittle32_t TimeDateStamp; | |
209 | support::ulittle16_t MajorVersion; | |
210 | support::ulittle16_t MinorVersion; | |
211 | support::ulittle32_t NameRVA; | |
212 | support::ulittle32_t OrdinalBase; | |
213 | support::ulittle32_t AddressTableEntries; | |
214 | support::ulittle32_t NumberOfNamePointers; | |
215 | support::ulittle32_t ExportAddressTableRVA; | |
216 | support::ulittle32_t NamePointerRVA; | |
217 | support::ulittle32_t OrdinalTableRVA; | |
218 | }; | |
223e47cc | 219 | |
1a4d82fc JJ |
220 | union export_address_table_entry { |
221 | support::ulittle32_t ExportRVA; | |
222 | support::ulittle32_t ForwarderRVA; | |
223 | }; | |
224 | ||
225 | typedef support::ulittle32_t export_name_pointer_table_entry; | |
226 | typedef support::ulittle16_t export_ordinal_table_entry; | |
227 | ||
228 | struct StringTableOffset { | |
229 | support::ulittle32_t Zeroes; | |
230 | support::ulittle32_t Offset; | |
231 | }; | |
232 | ||
233 | template <typename SectionNumberType> | |
234 | struct coff_symbol { | |
223e47cc | 235 | union { |
1a4d82fc | 236 | char ShortName[COFF::NameSize]; |
223e47cc LB |
237 | StringTableOffset Offset; |
238 | } Name; | |
239 | ||
240 | support::ulittle32_t Value; | |
1a4d82fc | 241 | SectionNumberType SectionNumber; |
223e47cc LB |
242 | |
243 | support::ulittle16_t Type; | |
244 | ||
1a4d82fc JJ |
245 | uint8_t StorageClass; |
246 | uint8_t NumberOfAuxSymbols; | |
247 | }; | |
248 | ||
249 | typedef coff_symbol<support::ulittle16_t> coff_symbol16; | |
250 | typedef coff_symbol<support::ulittle32_t> coff_symbol32; | |
251 | ||
252 | class COFFSymbolRef { | |
253 | public: | |
254 | COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {} | |
255 | COFFSymbolRef(const coff_symbol32 *CS) : CS16(nullptr), CS32(CS) {} | |
256 | COFFSymbolRef() : CS16(nullptr), CS32(nullptr) {} | |
257 | ||
258 | const void *getRawPtr() const { | |
259 | return CS16 ? static_cast<const void *>(CS16) : CS32; | |
260 | } | |
261 | ||
262 | friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { | |
263 | return A.getRawPtr() < B.getRawPtr(); | |
264 | } | |
265 | ||
266 | bool isBigObj() const { | |
267 | if (CS16) | |
268 | return false; | |
269 | if (CS32) | |
270 | return true; | |
271 | llvm_unreachable("COFFSymbolRef points to nothing!"); | |
272 | } | |
273 | ||
274 | const char *getShortName() const { | |
275 | return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; | |
276 | } | |
277 | ||
278 | const StringTableOffset &getStringTableOffset() const { | |
85aaf69f | 279 | assert(isSet() && "COFFSymbolRef points to nothing!"); |
1a4d82fc JJ |
280 | return CS16 ? CS16->Name.Offset : CS32->Name.Offset; |
281 | } | |
282 | ||
283 | uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } | |
284 | ||
285 | int32_t getSectionNumber() const { | |
85aaf69f | 286 | assert(isSet() && "COFFSymbolRef points to nothing!"); |
1a4d82fc JJ |
287 | if (CS16) { |
288 | // Reserved sections are returned as negative numbers. | |
289 | if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) | |
290 | return CS16->SectionNumber; | |
291 | return static_cast<int16_t>(CS16->SectionNumber); | |
292 | } | |
293 | return static_cast<int32_t>(CS32->SectionNumber); | |
294 | } | |
295 | ||
85aaf69f SL |
296 | uint16_t getType() const { |
297 | assert(isSet() && "COFFSymbolRef points to nothing!"); | |
298 | return CS16 ? CS16->Type : CS32->Type; | |
299 | } | |
1a4d82fc JJ |
300 | |
301 | uint8_t getStorageClass() const { | |
85aaf69f | 302 | assert(isSet() && "COFFSymbolRef points to nothing!"); |
1a4d82fc JJ |
303 | return CS16 ? CS16->StorageClass : CS32->StorageClass; |
304 | } | |
305 | ||
306 | uint8_t getNumberOfAuxSymbols() const { | |
85aaf69f | 307 | assert(isSet() && "COFFSymbolRef points to nothing!"); |
1a4d82fc JJ |
308 | return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; |
309 | } | |
310 | ||
311 | uint8_t getBaseType() const { return getType() & 0x0F; } | |
312 | ||
85aaf69f SL |
313 | uint8_t getComplexType() const { |
314 | return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; | |
315 | } | |
316 | ||
317 | bool isExternal() const { | |
318 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; | |
319 | } | |
320 | ||
321 | bool isCommon() const { | |
322 | return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && | |
323 | getValue() != 0; | |
324 | } | |
325 | ||
326 | bool isUndefined() const { | |
327 | return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && | |
328 | getValue() == 0; | |
329 | } | |
330 | ||
331 | bool isWeakExternal() const { | |
332 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; | |
333 | } | |
1a4d82fc JJ |
334 | |
335 | bool isFunctionDefinition() const { | |
85aaf69f | 336 | return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && |
1a4d82fc JJ |
337 | getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && |
338 | !COFF::isReservedSectionNumber(getSectionNumber()); | |
339 | } | |
223e47cc | 340 | |
1a4d82fc JJ |
341 | bool isFunctionLineInfo() const { |
342 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; | |
223e47cc LB |
343 | } |
344 | ||
85aaf69f SL |
345 | bool isAnyUndefined() const { |
346 | return isUndefined() || isWeakExternal(); | |
223e47cc | 347 | } |
1a4d82fc JJ |
348 | |
349 | bool isFileRecord() const { | |
350 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; | |
351 | } | |
352 | ||
353 | bool isSectionDefinition() const { | |
354 | // C++/CLI creates external ABS symbols for non-const appdomain globals. | |
355 | // These are also followed by an auxiliary section definition. | |
356 | bool isAppdomainGlobal = | |
357 | getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && | |
358 | getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; | |
85aaf69f SL |
359 | bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; |
360 | if (!getNumberOfAuxSymbols()) | |
361 | return false; | |
1a4d82fc JJ |
362 | return isAppdomainGlobal || isOrdinarySection; |
363 | } | |
364 | ||
365 | bool isCLRToken() const { | |
366 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; | |
367 | } | |
368 | ||
369 | private: | |
85aaf69f SL |
370 | bool isSet() const { return CS16 || CS32; } |
371 | ||
1a4d82fc JJ |
372 | const coff_symbol16 *CS16; |
373 | const coff_symbol32 *CS32; | |
223e47cc LB |
374 | }; |
375 | ||
376 | struct coff_section { | |
1a4d82fc | 377 | char Name[COFF::NameSize]; |
223e47cc LB |
378 | support::ulittle32_t VirtualSize; |
379 | support::ulittle32_t VirtualAddress; | |
380 | support::ulittle32_t SizeOfRawData; | |
381 | support::ulittle32_t PointerToRawData; | |
382 | support::ulittle32_t PointerToRelocations; | |
383 | support::ulittle32_t PointerToLinenumbers; | |
384 | support::ulittle16_t NumberOfRelocations; | |
385 | support::ulittle16_t NumberOfLinenumbers; | |
386 | support::ulittle32_t Characteristics; | |
1a4d82fc JJ |
387 | |
388 | // Returns true if the actual number of relocations is stored in | |
389 | // VirtualAddress field of the first relocation table entry. | |
390 | bool hasExtendedRelocations() const { | |
85aaf69f SL |
391 | return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && |
392 | NumberOfRelocations == UINT16_MAX; | |
393 | } | |
223e47cc LB |
394 | }; |
395 | ||
396 | struct coff_relocation { | |
397 | support::ulittle32_t VirtualAddress; | |
398 | support::ulittle32_t SymbolTableIndex; | |
399 | support::ulittle16_t Type; | |
400 | }; | |
401 | ||
1a4d82fc JJ |
402 | struct coff_aux_function_definition { |
403 | support::ulittle32_t TagIndex; | |
404 | support::ulittle32_t TotalSize; | |
405 | support::ulittle32_t PointerToLinenumber; | |
406 | support::ulittle32_t PointerToNextFunction; | |
407 | }; | |
408 | ||
409 | struct coff_aux_bf_and_ef_symbol { | |
410 | char Unused1[4]; | |
411 | support::ulittle16_t Linenumber; | |
412 | char Unused2[6]; | |
413 | support::ulittle32_t PointerToNextFunction; | |
414 | }; | |
415 | ||
416 | struct coff_aux_weak_external { | |
417 | support::ulittle32_t TagIndex; | |
418 | support::ulittle32_t Characteristics; | |
419 | }; | |
420 | ||
223e47cc LB |
421 | struct coff_aux_section_definition { |
422 | support::ulittle32_t Length; | |
423 | support::ulittle16_t NumberOfRelocations; | |
424 | support::ulittle16_t NumberOfLinenumbers; | |
425 | support::ulittle32_t CheckSum; | |
1a4d82fc JJ |
426 | support::ulittle16_t NumberLowPart; |
427 | uint8_t Selection; | |
428 | uint8_t Unused; | |
429 | support::ulittle16_t NumberHighPart; | |
430 | int32_t getNumber(bool IsBigObj) const { | |
431 | uint32_t Number = static_cast<uint32_t>(NumberLowPart); | |
432 | if (IsBigObj) | |
433 | Number |= static_cast<uint32_t>(NumberHighPart) << 16; | |
434 | return static_cast<int32_t>(Number); | |
435 | } | |
436 | }; | |
437 | ||
438 | struct coff_aux_clr_token { | |
439 | uint8_t AuxType; | |
440 | uint8_t Reserved; | |
441 | support::ulittle32_t SymbolTableIndex; | |
442 | }; | |
443 | ||
444 | struct coff_load_configuration32 { | |
445 | support::ulittle32_t Characteristics; | |
446 | support::ulittle32_t TimeDateStamp; | |
447 | support::ulittle16_t MajorVersion; | |
448 | support::ulittle16_t MinorVersion; | |
449 | support::ulittle32_t GlobalFlagsClear; | |
450 | support::ulittle32_t GlobalFlagsSet; | |
451 | support::ulittle32_t CriticalSectionDefaultTimeout; | |
452 | support::ulittle32_t DeCommitFreeBlockThreshold; | |
453 | support::ulittle32_t DeCommitTotalFreeThreshold; | |
454 | support::ulittle32_t LockPrefixTable; | |
455 | support::ulittle32_t MaximumAllocationSize; | |
456 | support::ulittle32_t VirtualMemoryThreshold; | |
457 | support::ulittle32_t ProcessAffinityMask; | |
458 | support::ulittle32_t ProcessHeapFlags; | |
459 | support::ulittle16_t CSDVersion; | |
460 | support::ulittle16_t Reserved; | |
461 | support::ulittle32_t EditList; | |
462 | support::ulittle32_t SecurityCookie; | |
463 | support::ulittle32_t SEHandlerTable; | |
464 | support::ulittle32_t SEHandlerCount; | |
465 | }; | |
466 | ||
467 | struct coff_runtime_function_x64 { | |
468 | support::ulittle32_t BeginAddress; | |
469 | support::ulittle32_t EndAddress; | |
470 | support::ulittle32_t UnwindInformation; | |
223e47cc LB |
471 | }; |
472 | ||
85aaf69f SL |
473 | struct coff_base_reloc_block_header { |
474 | support::ulittle32_t PageRVA; | |
475 | support::ulittle32_t BlockSize; | |
476 | }; | |
477 | ||
478 | struct coff_base_reloc_block_entry { | |
479 | support::ulittle16_t Data; | |
480 | int getType() const { return Data >> 12; } | |
481 | int getOffset() const { return Data & ((1 << 12) - 1); } | |
482 | }; | |
483 | ||
223e47cc LB |
484 | class COFFObjectFile : public ObjectFile { |
485 | private: | |
1a4d82fc JJ |
486 | friend class ImportDirectoryEntryRef; |
487 | friend class ExportDirectoryEntryRef; | |
488 | const coff_file_header *COFFHeader; | |
489 | const coff_bigobj_file_header *COFFBigObjHeader; | |
490 | const pe32_header *PE32Header; | |
491 | const pe32plus_header *PE32PlusHeader; | |
492 | const data_directory *DataDirectory; | |
493 | const coff_section *SectionTable; | |
494 | const coff_symbol16 *SymbolTable16; | |
495 | const coff_symbol32 *SymbolTable32; | |
496 | const char *StringTable; | |
497 | uint32_t StringTableSize; | |
498 | const import_directory_table_entry *ImportDirectory; | |
499 | uint32_t NumberOfImportDirectory; | |
85aaf69f SL |
500 | const delay_import_directory_table_entry *DelayImportDirectory; |
501 | uint32_t NumberOfDelayImportDirectory; | |
1a4d82fc | 502 | const export_directory_table_entry *ExportDirectory; |
85aaf69f SL |
503 | const coff_base_reloc_block_header *BaseRelocHeader; |
504 | const coff_base_reloc_block_header *BaseRelocEnd; | |
1a4d82fc JJ |
505 | |
506 | std::error_code getString(uint32_t offset, StringRef &Res) const; | |
223e47cc | 507 | |
1a4d82fc JJ |
508 | template <typename coff_symbol_type> |
509 | const coff_symbol_type *toSymb(DataRefImpl Symb) const; | |
510 | const coff_section *toSec(DataRefImpl Sec) const; | |
511 | const coff_relocation *toRel(DataRefImpl Rel) const; | |
223e47cc | 512 | |
1a4d82fc JJ |
513 | std::error_code initSymbolTablePtr(); |
514 | std::error_code initImportTablePtr(); | |
85aaf69f | 515 | std::error_code initDelayImportTablePtr(); |
1a4d82fc | 516 | std::error_code initExportTablePtr(); |
85aaf69f | 517 | std::error_code initBaseRelocPtr(); |
223e47cc | 518 | |
1a4d82fc JJ |
519 | public: |
520 | uintptr_t getSymbolTable() const { | |
521 | if (SymbolTable16) | |
522 | return reinterpret_cast<uintptr_t>(SymbolTable16); | |
523 | if (SymbolTable32) | |
524 | return reinterpret_cast<uintptr_t>(SymbolTable32); | |
525 | return uintptr_t(0); | |
526 | } | |
527 | uint16_t getMachine() const { | |
528 | if (COFFHeader) | |
529 | return COFFHeader->Machine; | |
530 | if (COFFBigObjHeader) | |
531 | return COFFBigObjHeader->Machine; | |
532 | llvm_unreachable("no COFF header!"); | |
533 | } | |
534 | uint16_t getSizeOfOptionalHeader() const { | |
535 | if (COFFHeader) | |
85aaf69f SL |
536 | return COFFHeader->isImportLibrary() ? 0 |
537 | : COFFHeader->SizeOfOptionalHeader; | |
1a4d82fc JJ |
538 | // bigobj doesn't have this field. |
539 | if (COFFBigObjHeader) | |
540 | return 0; | |
541 | llvm_unreachable("no COFF header!"); | |
542 | } | |
543 | uint16_t getCharacteristics() const { | |
544 | if (COFFHeader) | |
85aaf69f | 545 | return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; |
1a4d82fc JJ |
546 | // bigobj doesn't have characteristics to speak of, |
547 | // editbin will silently lie to you if you attempt to set any. | |
548 | if (COFFBigObjHeader) | |
549 | return 0; | |
550 | llvm_unreachable("no COFF header!"); | |
551 | } | |
552 | uint32_t getTimeDateStamp() const { | |
553 | if (COFFHeader) | |
554 | return COFFHeader->TimeDateStamp; | |
555 | if (COFFBigObjHeader) | |
556 | return COFFBigObjHeader->TimeDateStamp; | |
557 | llvm_unreachable("no COFF header!"); | |
558 | } | |
559 | uint32_t getNumberOfSections() const { | |
560 | if (COFFHeader) | |
85aaf69f | 561 | return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; |
1a4d82fc JJ |
562 | if (COFFBigObjHeader) |
563 | return COFFBigObjHeader->NumberOfSections; | |
564 | llvm_unreachable("no COFF header!"); | |
565 | } | |
566 | uint32_t getPointerToSymbolTable() const { | |
567 | if (COFFHeader) | |
85aaf69f SL |
568 | return COFFHeader->isImportLibrary() ? 0 |
569 | : COFFHeader->PointerToSymbolTable; | |
1a4d82fc JJ |
570 | if (COFFBigObjHeader) |
571 | return COFFBigObjHeader->PointerToSymbolTable; | |
572 | llvm_unreachable("no COFF header!"); | |
573 | } | |
574 | uint32_t getNumberOfSymbols() const { | |
575 | if (COFFHeader) | |
85aaf69f | 576 | return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; |
1a4d82fc JJ |
577 | if (COFFBigObjHeader) |
578 | return COFFBigObjHeader->NumberOfSymbols; | |
579 | llvm_unreachable("no COFF header!"); | |
580 | } | |
223e47cc | 581 | protected: |
1a4d82fc JJ |
582 | void moveSymbolNext(DataRefImpl &Symb) const override; |
583 | std::error_code getSymbolName(DataRefImpl Symb, | |
584 | StringRef &Res) const override; | |
585 | std::error_code getSymbolAddress(DataRefImpl Symb, | |
586 | uint64_t &Res) const override; | |
587 | std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; | |
588 | uint32_t getSymbolFlags(DataRefImpl Symb) const override; | |
589 | std::error_code getSymbolType(DataRefImpl Symb, | |
590 | SymbolRef::Type &Res) const override; | |
591 | std::error_code getSymbolSection(DataRefImpl Symb, | |
592 | section_iterator &Res) const override; | |
593 | void moveSectionNext(DataRefImpl &Sec) const override; | |
594 | std::error_code getSectionName(DataRefImpl Sec, | |
595 | StringRef &Res) const override; | |
85aaf69f SL |
596 | uint64_t getSectionAddress(DataRefImpl Sec) const override; |
597 | uint64_t getSectionSize(DataRefImpl Sec) const override; | |
1a4d82fc JJ |
598 | std::error_code getSectionContents(DataRefImpl Sec, |
599 | StringRef &Res) const override; | |
85aaf69f SL |
600 | uint64_t getSectionAlignment(DataRefImpl Sec) const override; |
601 | bool isSectionText(DataRefImpl Sec) const override; | |
602 | bool isSectionData(DataRefImpl Sec) const override; | |
603 | bool isSectionBSS(DataRefImpl Sec) const override; | |
604 | bool isSectionVirtual(DataRefImpl Sec) const override; | |
605 | bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; | |
1a4d82fc JJ |
606 | relocation_iterator section_rel_begin(DataRefImpl Sec) const override; |
607 | relocation_iterator section_rel_end(DataRefImpl Sec) const override; | |
608 | ||
609 | void moveRelocationNext(DataRefImpl &Rel) const override; | |
610 | std::error_code getRelocationAddress(DataRefImpl Rel, | |
611 | uint64_t &Res) const override; | |
612 | std::error_code getRelocationOffset(DataRefImpl Rel, | |
613 | uint64_t &Res) const override; | |
614 | symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; | |
615 | std::error_code getRelocationType(DataRefImpl Rel, | |
616 | uint64_t &Res) const override; | |
617 | std::error_code | |
618 | getRelocationTypeName(DataRefImpl Rel, | |
619 | SmallVectorImpl<char> &Result) const override; | |
620 | std::error_code | |
621 | getRelocationValueString(DataRefImpl Rel, | |
622 | SmallVectorImpl<char> &Result) const override; | |
223e47cc LB |
623 | |
624 | public: | |
1a4d82fc JJ |
625 | COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); |
626 | basic_symbol_iterator symbol_begin_impl() const override; | |
627 | basic_symbol_iterator symbol_end_impl() const override; | |
628 | section_iterator section_begin() const override; | |
629 | section_iterator section_end() const override; | |
630 | ||
631 | const coff_section *getCOFFSection(const SectionRef &Section) const; | |
632 | COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; | |
633 | COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; | |
634 | const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; | |
635 | ||
636 | uint8_t getBytesInAddress() const override; | |
637 | StringRef getFileFormatName() const override; | |
638 | unsigned getArch() const override; | |
639 | ||
640 | import_directory_iterator import_directory_begin() const; | |
641 | import_directory_iterator import_directory_end() const; | |
85aaf69f SL |
642 | delay_import_directory_iterator delay_import_directory_begin() const; |
643 | delay_import_directory_iterator delay_import_directory_end() const; | |
1a4d82fc JJ |
644 | export_directory_iterator export_directory_begin() const; |
645 | export_directory_iterator export_directory_end() const; | |
85aaf69f SL |
646 | base_reloc_iterator base_reloc_begin() const; |
647 | base_reloc_iterator base_reloc_end() const; | |
648 | ||
649 | iterator_range<import_directory_iterator> import_directories() const; | |
650 | iterator_range<delay_import_directory_iterator> | |
651 | delay_import_directories() const; | |
652 | iterator_range<export_directory_iterator> export_directories() const; | |
653 | iterator_range<base_reloc_iterator> base_relocs() const; | |
654 | ||
655 | const dos_header *getDOSHeader() const { | |
656 | if (!PE32Header && !PE32PlusHeader) | |
657 | return nullptr; | |
658 | return reinterpret_cast<const dos_header *>(base()); | |
659 | } | |
1a4d82fc JJ |
660 | std::error_code getPE32Header(const pe32_header *&Res) const; |
661 | std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; | |
662 | std::error_code getDataDirectory(uint32_t index, | |
663 | const data_directory *&Res) const; | |
664 | std::error_code getSection(int32_t index, const coff_section *&Res) const; | |
665 | template <typename coff_symbol_type> | |
666 | std::error_code getSymbol(uint32_t Index, | |
667 | const coff_symbol_type *&Res) const { | |
668 | if (Index >= getNumberOfSymbols()) | |
669 | return object_error::parse_failed; | |
670 | ||
671 | Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; | |
672 | return object_error::success; | |
673 | } | |
674 | ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const { | |
675 | if (SymbolTable16) { | |
676 | const coff_symbol16 *Symb = nullptr; | |
677 | if (std::error_code EC = getSymbol(index, Symb)) | |
678 | return EC; | |
679 | return COFFSymbolRef(Symb); | |
680 | } | |
681 | if (SymbolTable32) { | |
682 | const coff_symbol32 *Symb = nullptr; | |
683 | if (std::error_code EC = getSymbol(index, Symb)) | |
684 | return EC; | |
685 | return COFFSymbolRef(Symb); | |
686 | } | |
85aaf69f | 687 | return object_error::parse_failed; |
1a4d82fc | 688 | } |
223e47cc | 689 | template <typename T> |
1a4d82fc JJ |
690 | std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { |
691 | ErrorOr<COFFSymbolRef> s = getSymbol(index); | |
692 | if (std::error_code EC = s.getError()) | |
693 | return EC; | |
694 | Res = reinterpret_cast<const T *>(s->getRawPtr()); | |
695 | return object_error::success; | |
223e47cc | 696 | } |
1a4d82fc | 697 | std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; |
223e47cc | 698 | |
1a4d82fc | 699 | ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; |
223e47cc | 700 | |
1a4d82fc JJ |
701 | size_t getSymbolTableEntrySize() const { |
702 | if (COFFHeader) | |
703 | return sizeof(coff_symbol16); | |
704 | if (COFFBigObjHeader) | |
705 | return sizeof(coff_symbol32); | |
706 | llvm_unreachable("null symbol table pointer!"); | |
223e47cc | 707 | } |
1a4d82fc JJ |
708 | |
709 | std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; | |
85aaf69f | 710 | uint64_t getSectionSize(const coff_section *Sec) const; |
1a4d82fc JJ |
711 | std::error_code getSectionContents(const coff_section *Sec, |
712 | ArrayRef<uint8_t> &Res) const; | |
713 | ||
714 | std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; | |
715 | std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; | |
716 | std::error_code getHintName(uint32_t Rva, uint16_t &Hint, | |
717 | StringRef &Name) const; | |
718 | ||
719 | bool isRelocatableObject() const override; | |
85aaf69f | 720 | bool is64() const { return PE32PlusHeader; } |
1a4d82fc JJ |
721 | |
722 | static inline bool classof(const Binary *v) { return v->isCOFF(); } | |
223e47cc LB |
723 | }; |
724 | ||
1a4d82fc JJ |
725 | // The iterator for the import directory table. |
726 | class ImportDirectoryEntryRef { | |
727 | public: | |
728 | ImportDirectoryEntryRef() : OwningObject(nullptr) {} | |
729 | ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I, | |
730 | const COFFObjectFile *Owner) | |
731 | : ImportTable(Table), Index(I), OwningObject(Owner) {} | |
732 | ||
733 | bool operator==(const ImportDirectoryEntryRef &Other) const; | |
734 | void moveNext(); | |
85aaf69f SL |
735 | |
736 | imported_symbol_iterator imported_symbol_begin() const; | |
737 | imported_symbol_iterator imported_symbol_end() const; | |
738 | iterator_range<imported_symbol_iterator> imported_symbols() const; | |
739 | ||
1a4d82fc | 740 | std::error_code getName(StringRef &Result) const; |
85aaf69f SL |
741 | std::error_code getImportLookupTableRVA(uint32_t &Result) const; |
742 | std::error_code getImportAddressTableRVA(uint32_t &Result) const; | |
1a4d82fc JJ |
743 | |
744 | std::error_code | |
745 | getImportTableEntry(const import_directory_table_entry *&Result) const; | |
746 | ||
747 | std::error_code | |
748 | getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; | |
749 | ||
750 | private: | |
751 | const import_directory_table_entry *ImportTable; | |
752 | uint32_t Index; | |
753 | const COFFObjectFile *OwningObject; | |
754 | }; | |
755 | ||
85aaf69f SL |
756 | class DelayImportDirectoryEntryRef { |
757 | public: | |
758 | DelayImportDirectoryEntryRef() : OwningObject(nullptr) {} | |
759 | DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, | |
760 | uint32_t I, const COFFObjectFile *Owner) | |
761 | : Table(T), Index(I), OwningObject(Owner) {} | |
762 | ||
763 | bool operator==(const DelayImportDirectoryEntryRef &Other) const; | |
764 | void moveNext(); | |
765 | ||
766 | imported_symbol_iterator imported_symbol_begin() const; | |
767 | imported_symbol_iterator imported_symbol_end() const; | |
768 | iterator_range<imported_symbol_iterator> imported_symbols() const; | |
769 | ||
770 | std::error_code getName(StringRef &Result) const; | |
771 | std::error_code getDelayImportTable( | |
772 | const delay_import_directory_table_entry *&Result) const; | |
773 | std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; | |
774 | ||
775 | private: | |
776 | const delay_import_directory_table_entry *Table; | |
777 | uint32_t Index; | |
778 | const COFFObjectFile *OwningObject; | |
779 | }; | |
780 | ||
1a4d82fc JJ |
781 | // The iterator for the export directory table entry. |
782 | class ExportDirectoryEntryRef { | |
783 | public: | |
784 | ExportDirectoryEntryRef() : OwningObject(nullptr) {} | |
785 | ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, | |
786 | const COFFObjectFile *Owner) | |
787 | : ExportTable(Table), Index(I), OwningObject(Owner) {} | |
788 | ||
789 | bool operator==(const ExportDirectoryEntryRef &Other) const; | |
790 | void moveNext(); | |
791 | ||
792 | std::error_code getDllName(StringRef &Result) const; | |
793 | std::error_code getOrdinalBase(uint32_t &Result) const; | |
794 | std::error_code getOrdinal(uint32_t &Result) const; | |
795 | std::error_code getExportRVA(uint32_t &Result) const; | |
796 | std::error_code getSymbolName(StringRef &Result) const; | |
797 | ||
798 | private: | |
799 | const export_directory_table_entry *ExportTable; | |
800 | uint32_t Index; | |
801 | const COFFObjectFile *OwningObject; | |
802 | }; | |
85aaf69f SL |
803 | |
804 | class ImportedSymbolRef { | |
805 | public: | |
806 | ImportedSymbolRef() : OwningObject(nullptr) {} | |
807 | ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, | |
808 | const COFFObjectFile *Owner) | |
809 | : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} | |
810 | ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, | |
811 | const COFFObjectFile *Owner) | |
812 | : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} | |
813 | ||
814 | bool operator==(const ImportedSymbolRef &Other) const; | |
815 | void moveNext(); | |
816 | ||
817 | std::error_code getSymbolName(StringRef &Result) const; | |
818 | std::error_code getOrdinal(uint16_t &Result) const; | |
819 | ||
820 | private: | |
821 | const import_lookup_table_entry32 *Entry32; | |
822 | const import_lookup_table_entry64 *Entry64; | |
823 | uint32_t Index; | |
824 | const COFFObjectFile *OwningObject; | |
825 | }; | |
826 | ||
827 | class BaseRelocRef { | |
828 | public: | |
829 | BaseRelocRef() : OwningObject(nullptr) {} | |
830 | BaseRelocRef(const coff_base_reloc_block_header *Header, | |
831 | const COFFObjectFile *Owner) | |
832 | : Header(Header), Index(0), OwningObject(Owner) {} | |
833 | ||
834 | bool operator==(const BaseRelocRef &Other) const; | |
835 | void moveNext(); | |
836 | ||
837 | std::error_code getType(uint8_t &Type) const; | |
838 | std::error_code getRVA(uint32_t &Result) const; | |
839 | ||
840 | private: | |
841 | const coff_base_reloc_block_header *Header; | |
842 | uint32_t Index; | |
843 | const COFFObjectFile *OwningObject; | |
844 | }; | |
845 | ||
1a4d82fc JJ |
846 | } // end namespace object |
847 | } // end namespace llvm | |
223e47cc LB |
848 | |
849 | #endif |