/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Object/COFF.h
Line | Count | Source (jump to first uncovered line) |
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 | | |
17 | | #include "llvm/ADT/iterator_range.h" |
18 | | #include "llvm/BinaryFormat/COFF.h" |
19 | | #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" |
20 | | #include "llvm/MC/SubtargetFeature.h" |
21 | | #include "llvm/Object/Binary.h" |
22 | | #include "llvm/Object/Error.h" |
23 | | #include "llvm/Object/ObjectFile.h" |
24 | | #include "llvm/Support/BinaryByteStream.h" |
25 | | #include "llvm/Support/ConvertUTF.h" |
26 | | #include "llvm/Support/Endian.h" |
27 | | #include "llvm/Support/ErrorHandling.h" |
28 | | #include "llvm/Support/ErrorOr.h" |
29 | | #include <cassert> |
30 | | #include <cstddef> |
31 | | #include <cstdint> |
32 | | #include <system_error> |
33 | | |
34 | | namespace llvm { |
35 | | |
36 | | template <typename T> class ArrayRef; |
37 | | |
38 | | namespace object { |
39 | | |
40 | | class BaseRelocRef; |
41 | | class DelayImportDirectoryEntryRef; |
42 | | class ExportDirectoryEntryRef; |
43 | | class ImportDirectoryEntryRef; |
44 | | class ImportedSymbolRef; |
45 | | class ResourceSectionRef; |
46 | | |
47 | | using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>; |
48 | | using delay_import_directory_iterator = |
49 | | content_iterator<DelayImportDirectoryEntryRef>; |
50 | | using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>; |
51 | | using imported_symbol_iterator = content_iterator<ImportedSymbolRef>; |
52 | | using base_reloc_iterator = content_iterator<BaseRelocRef>; |
53 | | |
54 | | /// The DOS compatible header at the front of all PE/COFF executables. |
55 | | struct dos_header { |
56 | | char Magic[2]; |
57 | | support::ulittle16_t UsedBytesInTheLastPage; |
58 | | support::ulittle16_t FileSizeInPages; |
59 | | support::ulittle16_t NumberOfRelocationItems; |
60 | | support::ulittle16_t HeaderSizeInParagraphs; |
61 | | support::ulittle16_t MinimumExtraParagraphs; |
62 | | support::ulittle16_t MaximumExtraParagraphs; |
63 | | support::ulittle16_t InitialRelativeSS; |
64 | | support::ulittle16_t InitialSP; |
65 | | support::ulittle16_t Checksum; |
66 | | support::ulittle16_t InitialIP; |
67 | | support::ulittle16_t InitialRelativeCS; |
68 | | support::ulittle16_t AddressOfRelocationTable; |
69 | | support::ulittle16_t OverlayNumber; |
70 | | support::ulittle16_t Reserved[4]; |
71 | | support::ulittle16_t OEMid; |
72 | | support::ulittle16_t OEMinfo; |
73 | | support::ulittle16_t Reserved2[10]; |
74 | | support::ulittle32_t AddressOfNewExeHeader; |
75 | | }; |
76 | | |
77 | | struct coff_file_header { |
78 | | support::ulittle16_t Machine; |
79 | | support::ulittle16_t NumberOfSections; |
80 | | support::ulittle32_t TimeDateStamp; |
81 | | support::ulittle32_t PointerToSymbolTable; |
82 | | support::ulittle32_t NumberOfSymbols; |
83 | | support::ulittle16_t SizeOfOptionalHeader; |
84 | | support::ulittle16_t Characteristics; |
85 | | |
86 | 25.1k | bool isImportLibrary() const { return NumberOfSections == 0xffff; } |
87 | | }; |
88 | | |
89 | | struct coff_bigobj_file_header { |
90 | | support::ulittle16_t Sig1; |
91 | | support::ulittle16_t Sig2; |
92 | | support::ulittle16_t Version; |
93 | | support::ulittle16_t Machine; |
94 | | support::ulittle32_t TimeDateStamp; |
95 | | uint8_t UUID[16]; |
96 | | support::ulittle32_t unused1; |
97 | | support::ulittle32_t unused2; |
98 | | support::ulittle32_t unused3; |
99 | | support::ulittle32_t unused4; |
100 | | support::ulittle32_t NumberOfSections; |
101 | | support::ulittle32_t PointerToSymbolTable; |
102 | | support::ulittle32_t NumberOfSymbols; |
103 | | }; |
104 | | |
105 | | /// The 32-bit PE header that follows the COFF header. |
106 | | struct pe32_header { |
107 | | support::ulittle16_t Magic; |
108 | | uint8_t MajorLinkerVersion; |
109 | | uint8_t MinorLinkerVersion; |
110 | | support::ulittle32_t SizeOfCode; |
111 | | support::ulittle32_t SizeOfInitializedData; |
112 | | support::ulittle32_t SizeOfUninitializedData; |
113 | | support::ulittle32_t AddressOfEntryPoint; |
114 | | support::ulittle32_t BaseOfCode; |
115 | | support::ulittle32_t BaseOfData; |
116 | | support::ulittle32_t ImageBase; |
117 | | support::ulittle32_t SectionAlignment; |
118 | | support::ulittle32_t FileAlignment; |
119 | | support::ulittle16_t MajorOperatingSystemVersion; |
120 | | support::ulittle16_t MinorOperatingSystemVersion; |
121 | | support::ulittle16_t MajorImageVersion; |
122 | | support::ulittle16_t MinorImageVersion; |
123 | | support::ulittle16_t MajorSubsystemVersion; |
124 | | support::ulittle16_t MinorSubsystemVersion; |
125 | | support::ulittle32_t Win32VersionValue; |
126 | | support::ulittle32_t SizeOfImage; |
127 | | support::ulittle32_t SizeOfHeaders; |
128 | | support::ulittle32_t CheckSum; |
129 | | support::ulittle16_t Subsystem; |
130 | | // FIXME: This should be DllCharacteristics. |
131 | | support::ulittle16_t DLLCharacteristics; |
132 | | support::ulittle32_t SizeOfStackReserve; |
133 | | support::ulittle32_t SizeOfStackCommit; |
134 | | support::ulittle32_t SizeOfHeapReserve; |
135 | | support::ulittle32_t SizeOfHeapCommit; |
136 | | support::ulittle32_t LoaderFlags; |
137 | | // FIXME: This should be NumberOfRvaAndSizes. |
138 | | support::ulittle32_t NumberOfRvaAndSize; |
139 | | }; |
140 | | |
141 | | /// The 64-bit PE header that follows the COFF header. |
142 | | struct pe32plus_header { |
143 | | support::ulittle16_t Magic; |
144 | | uint8_t MajorLinkerVersion; |
145 | | uint8_t MinorLinkerVersion; |
146 | | support::ulittle32_t SizeOfCode; |
147 | | support::ulittle32_t SizeOfInitializedData; |
148 | | support::ulittle32_t SizeOfUninitializedData; |
149 | | support::ulittle32_t AddressOfEntryPoint; |
150 | | support::ulittle32_t BaseOfCode; |
151 | | support::ulittle64_t ImageBase; |
152 | | support::ulittle32_t SectionAlignment; |
153 | | support::ulittle32_t FileAlignment; |
154 | | support::ulittle16_t MajorOperatingSystemVersion; |
155 | | support::ulittle16_t MinorOperatingSystemVersion; |
156 | | support::ulittle16_t MajorImageVersion; |
157 | | support::ulittle16_t MinorImageVersion; |
158 | | support::ulittle16_t MajorSubsystemVersion; |
159 | | support::ulittle16_t MinorSubsystemVersion; |
160 | | support::ulittle32_t Win32VersionValue; |
161 | | support::ulittle32_t SizeOfImage; |
162 | | support::ulittle32_t SizeOfHeaders; |
163 | | support::ulittle32_t CheckSum; |
164 | | support::ulittle16_t Subsystem; |
165 | | support::ulittle16_t DLLCharacteristics; |
166 | | support::ulittle64_t SizeOfStackReserve; |
167 | | support::ulittle64_t SizeOfStackCommit; |
168 | | support::ulittle64_t SizeOfHeapReserve; |
169 | | support::ulittle64_t SizeOfHeapCommit; |
170 | | support::ulittle32_t LoaderFlags; |
171 | | support::ulittle32_t NumberOfRvaAndSize; |
172 | | }; |
173 | | |
174 | | struct data_directory { |
175 | | support::ulittle32_t RelativeVirtualAddress; |
176 | | support::ulittle32_t Size; |
177 | | }; |
178 | | |
179 | | struct debug_directory { |
180 | | support::ulittle32_t Characteristics; |
181 | | support::ulittle32_t TimeDateStamp; |
182 | | support::ulittle16_t MajorVersion; |
183 | | support::ulittle16_t MinorVersion; |
184 | | support::ulittle32_t Type; |
185 | | support::ulittle32_t SizeOfData; |
186 | | support::ulittle32_t AddressOfRawData; |
187 | | support::ulittle32_t PointerToRawData; |
188 | | }; |
189 | | |
190 | | template <typename IntTy> |
191 | | struct import_lookup_table_entry { |
192 | | IntTy Data; |
193 | | |
194 | 170 | bool isOrdinal() const { return Data < 0; } llvm::object::import_lookup_table_entry<llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> >::isOrdinal() const Line | Count | Source | 194 | 106 | bool isOrdinal() const { return Data < 0; } |
llvm::object::import_lookup_table_entry<llvm::support::detail::packed_endian_specific_integral<long long, (llvm::support::endianness)1, 1ul> >::isOrdinal() const Line | Count | Source | 194 | 64 | bool isOrdinal() const { return Data < 0; } |
|
195 | | |
196 | 6 | uint16_t getOrdinal() const { |
197 | 6 | assert(isOrdinal() && "ILT entry is not an ordinal!"); |
198 | 6 | return Data & 0xFFFF; |
199 | 6 | } llvm::object::import_lookup_table_entry<llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> >::getOrdinal() const Line | Count | Source | 196 | 1 | uint16_t getOrdinal() const { | 197 | 1 | assert(isOrdinal() && "ILT entry is not an ordinal!"); | 198 | 1 | return Data & 0xFFFF; | 199 | 1 | } |
llvm::object::import_lookup_table_entry<llvm::support::detail::packed_endian_specific_integral<long long, (llvm::support::endianness)1, 1ul> >::getOrdinal() const Line | Count | Source | 196 | 5 | uint16_t getOrdinal() const { | 197 | 5 | assert(isOrdinal() && "ILT entry is not an ordinal!"); | 198 | 5 | return Data & 0xFFFF; | 199 | 5 | } |
|
200 | | |
201 | 158 | uint32_t getHintNameRVA() const { |
202 | 158 | assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); |
203 | 158 | return Data & 0xFFFFFFFF; |
204 | 158 | } llvm::object::import_lookup_table_entry<llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> >::getHintNameRVA() const Line | Count | Source | 201 | 104 | uint32_t getHintNameRVA() const { | 202 | 104 | assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); | 203 | 104 | return Data & 0xFFFFFFFF; | 204 | 104 | } |
llvm::object::import_lookup_table_entry<llvm::support::detail::packed_endian_specific_integral<long long, (llvm::support::endianness)1, 1ul> >::getHintNameRVA() const Line | Count | Source | 201 | 54 | uint32_t getHintNameRVA() const { | 202 | 54 | assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); | 203 | 54 | return Data & 0xFFFFFFFF; | 204 | 54 | } |
|
205 | | }; |
206 | | |
207 | | using import_lookup_table_entry32 = |
208 | | import_lookup_table_entry<support::little32_t>; |
209 | | using import_lookup_table_entry64 = |
210 | | import_lookup_table_entry<support::little64_t>; |
211 | | |
212 | | struct delay_import_directory_table_entry { |
213 | | // dumpbin reports this field as "Characteristics" instead of "Attributes". |
214 | | support::ulittle32_t Attributes; |
215 | | support::ulittle32_t Name; |
216 | | support::ulittle32_t ModuleHandle; |
217 | | support::ulittle32_t DelayImportAddressTable; |
218 | | support::ulittle32_t DelayImportNameTable; |
219 | | support::ulittle32_t BoundDelayImportTable; |
220 | | support::ulittle32_t UnloadDelayImportTable; |
221 | | support::ulittle32_t TimeStamp; |
222 | | }; |
223 | | |
224 | | struct export_directory_table_entry { |
225 | | support::ulittle32_t ExportFlags; |
226 | | support::ulittle32_t TimeDateStamp; |
227 | | support::ulittle16_t MajorVersion; |
228 | | support::ulittle16_t MinorVersion; |
229 | | support::ulittle32_t NameRVA; |
230 | | support::ulittle32_t OrdinalBase; |
231 | | support::ulittle32_t AddressTableEntries; |
232 | | support::ulittle32_t NumberOfNamePointers; |
233 | | support::ulittle32_t ExportAddressTableRVA; |
234 | | support::ulittle32_t NamePointerRVA; |
235 | | support::ulittle32_t OrdinalTableRVA; |
236 | | }; |
237 | | |
238 | | union export_address_table_entry { |
239 | | support::ulittle32_t ExportRVA; |
240 | | support::ulittle32_t ForwarderRVA; |
241 | | }; |
242 | | |
243 | | using export_name_pointer_table_entry = support::ulittle32_t; |
244 | | using export_ordinal_table_entry = support::ulittle16_t; |
245 | | |
246 | | struct StringTableOffset { |
247 | | support::ulittle32_t Zeroes; |
248 | | support::ulittle32_t Offset; |
249 | | }; |
250 | | |
251 | | template <typename SectionNumberType> |
252 | | struct coff_symbol { |
253 | | union { |
254 | | char ShortName[COFF::NameSize]; |
255 | | StringTableOffset Offset; |
256 | | } Name; |
257 | | |
258 | | support::ulittle32_t Value; |
259 | | SectionNumberType SectionNumber; |
260 | | |
261 | | support::ulittle16_t Type; |
262 | | |
263 | | uint8_t StorageClass; |
264 | | uint8_t NumberOfAuxSymbols; |
265 | | }; |
266 | | |
267 | | using coff_symbol16 = coff_symbol<support::ulittle16_t>; |
268 | | using coff_symbol32 = coff_symbol<support::ulittle32_t>; |
269 | | |
270 | | // Contains only common parts of coff_symbol16 and coff_symbol32. |
271 | | struct coff_symbol_generic { |
272 | | union { |
273 | | char ShortName[COFF::NameSize]; |
274 | | StringTableOffset Offset; |
275 | | } Name; |
276 | | support::ulittle32_t Value; |
277 | | }; |
278 | | |
279 | | class COFFSymbolRef { |
280 | | public: |
281 | | COFFSymbolRef() = default; |
282 | 14.9k | COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {} |
283 | 4 | COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {} |
284 | | |
285 | 1.20k | const void *getRawPtr() const { |
286 | 1.20k | return CS16 ? static_cast<const void *>(CS16)1.19k : CS324 ; |
287 | 1.20k | } |
288 | | |
289 | 4.88k | const coff_symbol_generic *getGeneric() const { |
290 | 4.88k | if (CS16) |
291 | 4.88k | return reinterpret_cast<const coff_symbol_generic *>(CS16); |
292 | 4 | return reinterpret_cast<const coff_symbol_generic *>(CS32); |
293 | 4.88k | } |
294 | | |
295 | | friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { |
296 | | return A.getRawPtr() < B.getRawPtr(); |
297 | | } |
298 | | |
299 | | bool isBigObj() const { |
300 | | if (CS16) |
301 | | return false; |
302 | | if (CS32) |
303 | | return true; |
304 | | llvm_unreachable("COFFSymbolRef points to nothing!"); |
305 | | } |
306 | | |
307 | 0 | const char *getShortName() const { |
308 | 0 | return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; |
309 | 0 | } |
310 | | |
311 | 0 | const StringTableOffset &getStringTableOffset() const { |
312 | 0 | assert(isSet() && "COFFSymbolRef points to nothing!"); |
313 | 0 | return CS16 ? CS16->Name.Offset : CS32->Name.Offset; |
314 | 0 | } |
315 | | |
316 | 2.98k | uint32_t getValue() const { return CS16 ? 2.98k CS16->Value2.97k : CS32->Value4 ; } |
317 | | |
318 | 27.2k | int32_t getSectionNumber() const { |
319 | 27.2k | assert(isSet() && "COFFSymbolRef points to nothing!"); |
320 | 27.2k | if (CS1627.2k ) { |
321 | 27.1k | // Reserved sections are returned as negative numbers. |
322 | 27.1k | if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) |
323 | 26.3k | return CS16->SectionNumber; |
324 | 829 | return static_cast<int16_t>(CS16->SectionNumber); |
325 | 27.1k | } |
326 | 12 | return static_cast<int32_t>(CS32->SectionNumber); |
327 | 27.2k | } |
328 | | |
329 | 1.53k | uint16_t getType() const { |
330 | 1.53k | assert(isSet() && "COFFSymbolRef points to nothing!"); |
331 | 1.53k | return CS16 ? CS16->Type1.52k : CS32->Type8 ; |
332 | 1.53k | } |
333 | | |
334 | 55.8k | uint8_t getStorageClass() const { |
335 | 55.8k | assert(isSet() && "COFFSymbolRef points to nothing!"); |
336 | 55.8k | return CS16 ? CS16->StorageClass55.8k : CS32->StorageClass26 ; |
337 | 55.8k | } |
338 | | |
339 | 11.1k | uint8_t getNumberOfAuxSymbols() const { |
340 | 11.1k | assert(isSet() && "COFFSymbolRef points to nothing!"); |
341 | 11.1k | return CS16 ? CS16->NumberOfAuxSymbols11.0k : CS32->NumberOfAuxSymbols23 ; |
342 | 11.1k | } |
343 | | |
344 | 0 | uint8_t getBaseType() const { return getType() & 0x0F; } |
345 | | |
346 | 640 | uint8_t getComplexType() const { |
347 | 640 | return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; |
348 | 640 | } |
349 | | |
350 | 0 | bool isAbsolute() const { |
351 | 0 | return getSectionNumber() == -1; |
352 | 0 | } |
353 | | |
354 | 22.6k | bool isExternal() const { |
355 | 22.6k | return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; |
356 | 22.6k | } |
357 | | |
358 | 7.56k | bool isCommon() const { |
359 | 3.16k | return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && |
360 | 564 | getValue() != 0; |
361 | 7.56k | } |
362 | | |
363 | 8.06k | bool isUndefined() const { |
364 | 3.35k | return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && |
365 | 753 | getValue() == 0; |
366 | 8.06k | } |
367 | | |
368 | 15.4k | bool isWeakExternal() const { |
369 | 15.4k | return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; |
370 | 15.4k | } |
371 | | |
372 | | bool isFunctionDefinition() const { |
373 | | return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && |
374 | | getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && |
375 | | !COFF::isReservedSectionNumber(getSectionNumber()); |
376 | | } |
377 | | |
378 | 0 | bool isFunctionLineInfo() const { |
379 | 0 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; |
380 | 0 | } |
381 | | |
382 | 6.30k | bool isAnyUndefined() const { |
383 | 5.70k | return isUndefined() || isWeakExternal(); |
384 | 6.30k | } |
385 | | |
386 | 5.58k | bool isFileRecord() const { |
387 | 5.58k | return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; |
388 | 5.58k | } |
389 | | |
390 | 0 | bool isSection() const { |
391 | 0 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; |
392 | 0 | } |
393 | | |
394 | 5.62k | bool isSectionDefinition() const { |
395 | 5.62k | // C++/CLI creates external ABS symbols for non-const appdomain globals. |
396 | 5.62k | // These are also followed by an auxiliary section definition. |
397 | 5.62k | bool isAppdomainGlobal = |
398 | 5.62k | getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && |
399 | 2.44k | getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; |
400 | 5.62k | bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; |
401 | 5.62k | if (!getNumberOfAuxSymbols()) |
402 | 3.34k | return false; |
403 | 2.28k | return isAppdomainGlobal || 2.28k isOrdinarySection2.28k ; |
404 | 5.62k | } |
405 | | |
406 | 0 | bool isCLRToken() const { |
407 | 0 | return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; |
408 | 0 | } |
409 | | |
410 | | private: |
411 | 0 | bool isSet() const { return CS16 || CS32; } |
412 | | |
413 | | const coff_symbol16 *CS16 = nullptr; |
414 | | const coff_symbol32 *CS32 = nullptr; |
415 | | }; |
416 | | |
417 | | struct coff_section { |
418 | | char Name[COFF::NameSize]; |
419 | | support::ulittle32_t VirtualSize; |
420 | | support::ulittle32_t VirtualAddress; |
421 | | support::ulittle32_t SizeOfRawData; |
422 | | support::ulittle32_t PointerToRawData; |
423 | | support::ulittle32_t PointerToRelocations; |
424 | | support::ulittle32_t PointerToLinenumbers; |
425 | | support::ulittle16_t NumberOfRelocations; |
426 | | support::ulittle16_t NumberOfLinenumbers; |
427 | | support::ulittle32_t Characteristics; |
428 | | |
429 | | // Returns true if the actual number of relocations is stored in |
430 | | // VirtualAddress field of the first relocation table entry. |
431 | 4.95k | bool hasExtendedRelocations() const { |
432 | 4.95k | return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && |
433 | 10 | NumberOfRelocations == UINT16_MAX; |
434 | 4.95k | } |
435 | | |
436 | 864 | uint32_t getAlignment() const { |
437 | 864 | // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to |
438 | 864 | // IMAGE_SCN_ALIGN_1BYTES. |
439 | 864 | if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) |
440 | 0 | return 1; |
441 | 864 | |
442 | 864 | // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1. |
443 | 864 | uint32_t Shift = (Characteristics >> 20) & 0xF; |
444 | 864 | if (Shift > 0) |
445 | 860 | return 1U << (Shift - 1); |
446 | 4 | return 1; |
447 | 864 | } |
448 | | }; |
449 | | |
450 | | struct coff_relocation { |
451 | | support::ulittle32_t VirtualAddress; |
452 | | support::ulittle32_t SymbolTableIndex; |
453 | | support::ulittle16_t Type; |
454 | | }; |
455 | | |
456 | | struct coff_aux_function_definition { |
457 | | support::ulittle32_t TagIndex; |
458 | | support::ulittle32_t TotalSize; |
459 | | support::ulittle32_t PointerToLinenumber; |
460 | | support::ulittle32_t PointerToNextFunction; |
461 | | char Unused1[2]; |
462 | | }; |
463 | | |
464 | | static_assert(sizeof(coff_aux_function_definition) == 18, |
465 | | "auxiliary entry must be 18 bytes"); |
466 | | |
467 | | struct coff_aux_bf_and_ef_symbol { |
468 | | char Unused1[4]; |
469 | | support::ulittle16_t Linenumber; |
470 | | char Unused2[6]; |
471 | | support::ulittle32_t PointerToNextFunction; |
472 | | char Unused3[2]; |
473 | | }; |
474 | | |
475 | | static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, |
476 | | "auxiliary entry must be 18 bytes"); |
477 | | |
478 | | struct coff_aux_weak_external { |
479 | | support::ulittle32_t TagIndex; |
480 | | support::ulittle32_t Characteristics; |
481 | | char Unused1[10]; |
482 | | }; |
483 | | |
484 | | static_assert(sizeof(coff_aux_weak_external) == 18, |
485 | | "auxiliary entry must be 18 bytes"); |
486 | | |
487 | | struct coff_aux_section_definition { |
488 | | support::ulittle32_t Length; |
489 | | support::ulittle16_t NumberOfRelocations; |
490 | | support::ulittle16_t NumberOfLinenumbers; |
491 | | support::ulittle32_t CheckSum; |
492 | | support::ulittle16_t NumberLowPart; |
493 | | uint8_t Selection; |
494 | | uint8_t Unused; |
495 | | support::ulittle16_t NumberHighPart; |
496 | | int32_t getNumber(bool IsBigObj) const { |
497 | | uint32_t Number = static_cast<uint32_t>(NumberLowPart); |
498 | | if (IsBigObj) |
499 | | Number |= static_cast<uint32_t>(NumberHighPart) << 16; |
500 | | return static_cast<int32_t>(Number); |
501 | | } |
502 | | }; |
503 | | |
504 | | static_assert(sizeof(coff_aux_section_definition) == 18, |
505 | | "auxiliary entry must be 18 bytes"); |
506 | | |
507 | | struct coff_aux_clr_token { |
508 | | uint8_t AuxType; |
509 | | uint8_t Reserved; |
510 | | support::ulittle32_t SymbolTableIndex; |
511 | | char MBZ[12]; |
512 | | }; |
513 | | |
514 | | static_assert(sizeof(coff_aux_clr_token) == 18, |
515 | | "auxiliary entry must be 18 bytes"); |
516 | | |
517 | | struct coff_import_header { |
518 | | support::ulittle16_t Sig1; |
519 | | support::ulittle16_t Sig2; |
520 | | support::ulittle16_t Version; |
521 | | support::ulittle16_t Machine; |
522 | | support::ulittle32_t TimeDateStamp; |
523 | | support::ulittle32_t SizeOfData; |
524 | | support::ulittle16_t OrdinalHint; |
525 | | support::ulittle16_t TypeInfo; |
526 | | |
527 | 323 | int getType() const { return TypeInfo & 0x3; } |
528 | 0 | int getNameType() const { return (TypeInfo >> 2) & 0x7; } |
529 | | }; |
530 | | |
531 | | struct coff_import_directory_table_entry { |
532 | | support::ulittle32_t ImportLookupTableRVA; |
533 | | support::ulittle32_t TimeDateStamp; |
534 | | support::ulittle32_t ForwarderChain; |
535 | | support::ulittle32_t NameRVA; |
536 | | support::ulittle32_t ImportAddressTableRVA; |
537 | | |
538 | 35 | bool isNull() const { |
539 | 13 | return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && |
540 | 35 | ForwarderChain == 013 && NameRVA == 013 && ImportAddressTableRVA == 013 ; |
541 | 35 | } |
542 | | }; |
543 | | |
544 | | template <typename IntTy> |
545 | | struct coff_tls_directory { |
546 | | IntTy StartAddressOfRawData; |
547 | | IntTy EndAddressOfRawData; |
548 | | IntTy AddressOfIndex; |
549 | | IntTy AddressOfCallBacks; |
550 | | support::ulittle32_t SizeOfZeroFill; |
551 | | support::ulittle32_t Characteristics; |
552 | | |
553 | | uint32_t getAlignment() const { |
554 | | // Bit [20:24] contains section alignment. |
555 | | uint32_t Shift = (Characteristics & 0x00F00000) >> 20; |
556 | | if (Shift > 0) |
557 | | return 1U << (Shift - 1); |
558 | | return 0; |
559 | | } |
560 | | }; |
561 | | |
562 | | using coff_tls_directory32 = coff_tls_directory<support::little32_t>; |
563 | | using coff_tls_directory64 = coff_tls_directory<support::little64_t>; |
564 | | |
565 | | /// Bits in control flow guard flags as we understand them. |
566 | | enum class coff_guard_flags : uint32_t { |
567 | | CFInstrumented = 0x00000100, |
568 | | HasFidTable = 0x00000400, |
569 | | ProtectDelayLoadIAT = 0x00001000, |
570 | | DelayLoadIATSection = 0x00002000, // Delay load in separate section |
571 | | HasLongJmpTable = 0x00010000, |
572 | | FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes |
573 | | }; |
574 | | |
575 | | struct coff_load_config_code_integrity { |
576 | | support::ulittle16_t Flags; |
577 | | support::ulittle16_t Catalog; |
578 | | support::ulittle32_t CatalogOffset; |
579 | | support::ulittle32_t Reserved; |
580 | | }; |
581 | | |
582 | | /// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) |
583 | | struct coff_load_configuration32 { |
584 | | support::ulittle32_t Size; |
585 | | support::ulittle32_t TimeDateStamp; |
586 | | support::ulittle16_t MajorVersion; |
587 | | support::ulittle16_t MinorVersion; |
588 | | support::ulittle32_t GlobalFlagsClear; |
589 | | support::ulittle32_t GlobalFlagsSet; |
590 | | support::ulittle32_t CriticalSectionDefaultTimeout; |
591 | | support::ulittle32_t DeCommitFreeBlockThreshold; |
592 | | support::ulittle32_t DeCommitTotalFreeThreshold; |
593 | | support::ulittle32_t LockPrefixTable; |
594 | | support::ulittle32_t MaximumAllocationSize; |
595 | | support::ulittle32_t VirtualMemoryThreshold; |
596 | | support::ulittle32_t ProcessAffinityMask; |
597 | | support::ulittle32_t ProcessHeapFlags; |
598 | | support::ulittle16_t CSDVersion; |
599 | | support::ulittle16_t DependentLoadFlags; |
600 | | support::ulittle32_t EditList; |
601 | | support::ulittle32_t SecurityCookie; |
602 | | support::ulittle32_t SEHandlerTable; |
603 | | support::ulittle32_t SEHandlerCount; |
604 | | |
605 | | // Added in MSVC 2015 for /guard:cf. |
606 | | support::ulittle32_t GuardCFCheckFunction; |
607 | | support::ulittle32_t GuardCFCheckDispatch; |
608 | | support::ulittle32_t GuardCFFunctionTable; |
609 | | support::ulittle32_t GuardCFFunctionCount; |
610 | | support::ulittle32_t GuardFlags; // coff_guard_flags |
611 | | |
612 | | // Added in MSVC 2017 |
613 | | coff_load_config_code_integrity CodeIntegrity; |
614 | | support::ulittle32_t GuardAddressTakenIatEntryTable; |
615 | | support::ulittle32_t GuardAddressTakenIatEntryCount; |
616 | | support::ulittle32_t GuardLongJumpTargetTable; |
617 | | support::ulittle32_t GuardLongJumpTargetCount; |
618 | | support::ulittle32_t DynamicValueRelocTable; |
619 | | support::ulittle32_t CHPEMetadataPointer; |
620 | | support::ulittle32_t GuardRFFailureRoutine; |
621 | | support::ulittle32_t GuardRFFailureRoutineFunctionPointer; |
622 | | support::ulittle32_t DynamicValueRelocTableOffset; |
623 | | support::ulittle16_t DynamicValueRelocTableSection; |
624 | | support::ulittle16_t Reserved2; |
625 | | support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; |
626 | | support::ulittle32_t HotPatchTableOffset; |
627 | | }; |
628 | | |
629 | | /// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) |
630 | | struct coff_load_configuration64 { |
631 | | support::ulittle32_t Size; |
632 | | support::ulittle32_t TimeDateStamp; |
633 | | support::ulittle16_t MajorVersion; |
634 | | support::ulittle16_t MinorVersion; |
635 | | support::ulittle32_t GlobalFlagsClear; |
636 | | support::ulittle32_t GlobalFlagsSet; |
637 | | support::ulittle32_t CriticalSectionDefaultTimeout; |
638 | | support::ulittle64_t DeCommitFreeBlockThreshold; |
639 | | support::ulittle64_t DeCommitTotalFreeThreshold; |
640 | | support::ulittle64_t LockPrefixTable; |
641 | | support::ulittle64_t MaximumAllocationSize; |
642 | | support::ulittle64_t VirtualMemoryThreshold; |
643 | | support::ulittle64_t ProcessAffinityMask; |
644 | | support::ulittle32_t ProcessHeapFlags; |
645 | | support::ulittle16_t CSDVersion; |
646 | | support::ulittle16_t DependentLoadFlags; |
647 | | support::ulittle64_t EditList; |
648 | | support::ulittle64_t SecurityCookie; |
649 | | support::ulittle64_t SEHandlerTable; |
650 | | support::ulittle64_t SEHandlerCount; |
651 | | |
652 | | // Added in MSVC 2015 for /guard:cf. |
653 | | support::ulittle64_t GuardCFCheckFunction; |
654 | | support::ulittle64_t GuardCFCheckDispatch; |
655 | | support::ulittle64_t GuardCFFunctionTable; |
656 | | support::ulittle64_t GuardCFFunctionCount; |
657 | | support::ulittle32_t GuardFlags; |
658 | | |
659 | | // Added in MSVC 2017 |
660 | | coff_load_config_code_integrity CodeIntegrity; |
661 | | support::ulittle64_t GuardAddressTakenIatEntryTable; |
662 | | support::ulittle64_t GuardAddressTakenIatEntryCount; |
663 | | support::ulittle64_t GuardLongJumpTargetTable; |
664 | | support::ulittle64_t GuardLongJumpTargetCount; |
665 | | support::ulittle64_t DynamicValueRelocTable; |
666 | | support::ulittle64_t CHPEMetadataPointer; |
667 | | support::ulittle64_t GuardRFFailureRoutine; |
668 | | support::ulittle64_t GuardRFFailureRoutineFunctionPointer; |
669 | | support::ulittle32_t DynamicValueRelocTableOffset; |
670 | | support::ulittle16_t DynamicValueRelocTableSection; |
671 | | support::ulittle16_t Reserved2; |
672 | | support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; |
673 | | support::ulittle32_t HotPatchTableOffset; |
674 | | }; |
675 | | |
676 | | struct coff_runtime_function_x64 { |
677 | | support::ulittle32_t BeginAddress; |
678 | | support::ulittle32_t EndAddress; |
679 | | support::ulittle32_t UnwindInformation; |
680 | | }; |
681 | | |
682 | | struct coff_base_reloc_block_header { |
683 | | support::ulittle32_t PageRVA; |
684 | | support::ulittle32_t BlockSize; |
685 | | }; |
686 | | |
687 | | struct coff_base_reloc_block_entry { |
688 | | support::ulittle16_t Data; |
689 | | |
690 | 94 | int getType() const { return Data >> 12; } |
691 | 94 | int getOffset() const { return Data & ((1 << 12) - 1); } |
692 | | }; |
693 | | |
694 | | struct coff_resource_dir_entry { |
695 | | union { |
696 | | support::ulittle32_t NameOffset; |
697 | | support::ulittle32_t ID; |
698 | 28 | uint32_t getNameOffset() const { |
699 | 28 | return maskTrailingOnes<uint32_t>(31) & NameOffset; |
700 | 28 | } |
701 | | // Even though the PE/COFF spec doesn't mention this, the high bit of a name |
702 | | // offset is set. |
703 | 58 | void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); } |
704 | | } Identifier; |
705 | | union { |
706 | | support::ulittle32_t DataEntryOffset; |
707 | | support::ulittle32_t SubdirOffset; |
708 | | |
709 | 0 | bool isSubDir() const { return SubdirOffset >> 31; } |
710 | 222 | uint32_t value() const { |
711 | 222 | return maskTrailingOnes<uint32_t>(31) & SubdirOffset; |
712 | 222 | } |
713 | | |
714 | | } Offset; |
715 | | }; |
716 | | |
717 | | struct coff_resource_data_entry { |
718 | | support::ulittle32_t DataRVA; |
719 | | support::ulittle32_t DataSize; |
720 | | support::ulittle32_t Codepage; |
721 | | support::ulittle32_t Reserved; |
722 | | }; |
723 | | |
724 | | struct coff_resource_dir_table { |
725 | | support::ulittle32_t Characteristics; |
726 | | support::ulittle32_t TimeDateStamp; |
727 | | support::ulittle16_t MajorVersion; |
728 | | support::ulittle16_t MinorVersion; |
729 | | support::ulittle16_t NumberOfNameEntries; |
730 | | support::ulittle16_t NumberOfIDEntries; |
731 | | }; |
732 | | |
733 | | class COFFObjectFile : public ObjectFile { |
734 | | private: |
735 | | friend class ImportDirectoryEntryRef; |
736 | | friend class ExportDirectoryEntryRef; |
737 | | const coff_file_header *COFFHeader; |
738 | | const coff_bigobj_file_header *COFFBigObjHeader; |
739 | | const pe32_header *PE32Header; |
740 | | const pe32plus_header *PE32PlusHeader; |
741 | | const data_directory *DataDirectory; |
742 | | const coff_section *SectionTable; |
743 | | const coff_symbol16 *SymbolTable16; |
744 | | const coff_symbol32 *SymbolTable32; |
745 | | const char *StringTable; |
746 | | uint32_t StringTableSize; |
747 | | const coff_import_directory_table_entry *ImportDirectory; |
748 | | const delay_import_directory_table_entry *DelayImportDirectory; |
749 | | uint32_t NumberOfDelayImportDirectory; |
750 | | const export_directory_table_entry *ExportDirectory; |
751 | | const coff_base_reloc_block_header *BaseRelocHeader; |
752 | | const coff_base_reloc_block_header *BaseRelocEnd; |
753 | | const debug_directory *DebugDirectoryBegin; |
754 | | const debug_directory *DebugDirectoryEnd; |
755 | | // Either coff_load_configuration32 or coff_load_configuration64. |
756 | | const void *LoadConfig = nullptr; |
757 | | |
758 | | std::error_code getString(uint32_t offset, StringRef &Res) const; |
759 | | |
760 | | template <typename coff_symbol_type> |
761 | | const coff_symbol_type *toSymb(DataRefImpl Symb) const; |
762 | | const coff_section *toSec(DataRefImpl Sec) const; |
763 | | const coff_relocation *toRel(DataRefImpl Rel) const; |
764 | | |
765 | | std::error_code initSymbolTablePtr(); |
766 | | std::error_code initImportTablePtr(); |
767 | | std::error_code initDelayImportTablePtr(); |
768 | | std::error_code initExportTablePtr(); |
769 | | std::error_code initBaseRelocPtr(); |
770 | | std::error_code initDebugDirectoryPtr(); |
771 | | std::error_code initLoadConfigPtr(); |
772 | | |
773 | | public: |
774 | 3.20k | uintptr_t getSymbolTable() const { |
775 | 3.20k | if (SymbolTable16) |
776 | 3.17k | return reinterpret_cast<uintptr_t>(SymbolTable16); |
777 | 31 | if (31 SymbolTable3231 ) |
778 | 1 | return reinterpret_cast<uintptr_t>(SymbolTable32); |
779 | 30 | return uintptr_t(0); |
780 | 3.20k | } |
781 | | |
782 | 2.58k | uint16_t getMachine() const { |
783 | 2.58k | if (COFFHeader) |
784 | 2.58k | return COFFHeader->Machine; |
785 | 4 | if (4 COFFBigObjHeader4 ) |
786 | 4 | return COFFBigObjHeader->Machine; |
787 | 0 | llvm_unreachable0 ("no COFF header!"); |
788 | 4 | } |
789 | | |
790 | | uint16_t getSizeOfOptionalHeader() const { |
791 | | if (COFFHeader) |
792 | | return COFFHeader->isImportLibrary() ? 0 |
793 | | : COFFHeader->SizeOfOptionalHeader; |
794 | | // bigobj doesn't have this field. |
795 | | if (COFFBigObjHeader) |
796 | | return 0; |
797 | | llvm_unreachable("no COFF header!"); |
798 | | } |
799 | | |
800 | | uint16_t getCharacteristics() const { |
801 | | if (COFFHeader) |
802 | | return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; |
803 | | // bigobj doesn't have characteristics to speak of, |
804 | | // editbin will silently lie to you if you attempt to set any. |
805 | | if (COFFBigObjHeader) |
806 | | return 0; |
807 | | llvm_unreachable("no COFF header!"); |
808 | | } |
809 | | |
810 | | uint32_t getTimeDateStamp() const { |
811 | | if (COFFHeader) |
812 | | return COFFHeader->TimeDateStamp; |
813 | | if (COFFBigObjHeader) |
814 | | return COFFBigObjHeader->TimeDateStamp; |
815 | | llvm_unreachable("no COFF header!"); |
816 | | } |
817 | | |
818 | 10.3k | uint32_t getNumberOfSections() const { |
819 | 10.3k | if (COFFHeader) |
820 | 10.3k | return COFFHeader->isImportLibrary() ? 10.3k 00 : COFFHeader->NumberOfSections10.3k ; |
821 | 7 | if (7 COFFBigObjHeader7 ) |
822 | 7 | return COFFBigObjHeader->NumberOfSections; |
823 | 0 | llvm_unreachable0 ("no COFF header!"); |
824 | 7 | } |
825 | | |
826 | 3.11k | uint32_t getPointerToSymbolTable() const { |
827 | 3.11k | if (COFFHeader) |
828 | 3.11k | return COFFHeader->isImportLibrary() ? 3.11k 00 |
829 | 3.11k | : COFFHeader->PointerToSymbolTable; |
830 | 4 | if (4 COFFBigObjHeader4 ) |
831 | 4 | return COFFBigObjHeader->PointerToSymbolTable; |
832 | 0 | llvm_unreachable0 ("no COFF header!"); |
833 | 4 | } |
834 | | |
835 | 5.11k | uint32_t getRawNumberOfSymbols() const { |
836 | 5.11k | if (COFFHeader) |
837 | 5.10k | return COFFHeader->isImportLibrary() ? 5.10k 00 : COFFHeader->NumberOfSymbols5.10k ; |
838 | 2 | if (2 COFFBigObjHeader2 ) |
839 | 2 | return COFFBigObjHeader->NumberOfSymbols; |
840 | 0 | llvm_unreachable0 ("no COFF header!"); |
841 | 2 | } |
842 | | |
843 | 6.31k | uint32_t getNumberOfSymbols() const { |
844 | 6.31k | if (!SymbolTable16 && 6.31k !SymbolTable321.20k ) |
845 | 1.20k | return 0; |
846 | 5.11k | return getRawNumberOfSymbols(); |
847 | 6.31k | } |
848 | | |
849 | 0 | const coff_load_configuration32 *getLoadConfig32() const { |
850 | 0 | assert(!is64()); |
851 | 0 | return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig); |
852 | 0 | } |
853 | | |
854 | 0 | const coff_load_configuration64 *getLoadConfig64() const { |
855 | 0 | assert(is64()); |
856 | 0 | return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig); |
857 | 0 | } |
858 | | |
859 | | protected: |
860 | | void moveSymbolNext(DataRefImpl &Symb) const override; |
861 | | Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; |
862 | | Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; |
863 | | uint32_t getSymbolAlignment(DataRefImpl Symb) const override; |
864 | | uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; |
865 | | uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; |
866 | | uint32_t getSymbolFlags(DataRefImpl Symb) const override; |
867 | | Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; |
868 | | Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; |
869 | | void moveSectionNext(DataRefImpl &Sec) const override; |
870 | | std::error_code getSectionName(DataRefImpl Sec, |
871 | | StringRef &Res) const override; |
872 | | uint64_t getSectionAddress(DataRefImpl Sec) const override; |
873 | | uint64_t getSectionIndex(DataRefImpl Sec) const override; |
874 | | uint64_t getSectionSize(DataRefImpl Sec) const override; |
875 | | std::error_code getSectionContents(DataRefImpl Sec, |
876 | | StringRef &Res) const override; |
877 | | uint64_t getSectionAlignment(DataRefImpl Sec) const override; |
878 | | bool isSectionCompressed(DataRefImpl Sec) const override; |
879 | | bool isSectionText(DataRefImpl Sec) const override; |
880 | | bool isSectionData(DataRefImpl Sec) const override; |
881 | | bool isSectionBSS(DataRefImpl Sec) const override; |
882 | | bool isSectionVirtual(DataRefImpl Sec) const override; |
883 | | relocation_iterator section_rel_begin(DataRefImpl Sec) const override; |
884 | | relocation_iterator section_rel_end(DataRefImpl Sec) const override; |
885 | | |
886 | | void moveRelocationNext(DataRefImpl &Rel) const override; |
887 | | uint64_t getRelocationOffset(DataRefImpl Rel) const override; |
888 | | symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; |
889 | | uint64_t getRelocationType(DataRefImpl Rel) const override; |
890 | | void getRelocationTypeName(DataRefImpl Rel, |
891 | | SmallVectorImpl<char> &Result) const override; |
892 | | |
893 | | public: |
894 | | COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); |
895 | | |
896 | | basic_symbol_iterator symbol_begin() const override; |
897 | | basic_symbol_iterator symbol_end() const override; |
898 | | section_iterator section_begin() const override; |
899 | | section_iterator section_end() const override; |
900 | | |
901 | | const coff_section *getCOFFSection(const SectionRef &Section) const; |
902 | | COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; |
903 | | COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; |
904 | | const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; |
905 | | unsigned getSectionID(SectionRef Sec) const; |
906 | | unsigned getSymbolSectionID(SymbolRef Sym) const; |
907 | | |
908 | | uint8_t getBytesInAddress() const override; |
909 | | StringRef getFileFormatName() const override; |
910 | | unsigned getArch() const override; |
911 | 50 | SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } |
912 | | |
913 | | import_directory_iterator import_directory_begin() const; |
914 | | import_directory_iterator import_directory_end() const; |
915 | | delay_import_directory_iterator delay_import_directory_begin() const; |
916 | | delay_import_directory_iterator delay_import_directory_end() const; |
917 | | export_directory_iterator export_directory_begin() const; |
918 | | export_directory_iterator export_directory_end() const; |
919 | | base_reloc_iterator base_reloc_begin() const; |
920 | | base_reloc_iterator base_reloc_end() const; |
921 | 18 | const debug_directory *debug_directory_begin() const { |
922 | 18 | return DebugDirectoryBegin; |
923 | 18 | } |
924 | 18 | const debug_directory *debug_directory_end() const { |
925 | 18 | return DebugDirectoryEnd; |
926 | 18 | } |
927 | | |
928 | | iterator_range<import_directory_iterator> import_directories() const; |
929 | | iterator_range<delay_import_directory_iterator> |
930 | | delay_import_directories() const; |
931 | | iterator_range<export_directory_iterator> export_directories() const; |
932 | | iterator_range<base_reloc_iterator> base_relocs() const; |
933 | 18 | iterator_range<const debug_directory *> debug_directories() const { |
934 | 18 | return make_range(debug_directory_begin(), debug_directory_end()); |
935 | 18 | } |
936 | | |
937 | 151k | const dos_header *getDOSHeader() const { |
938 | 151k | if (!PE32Header && 151k !PE32PlusHeader151k ) |
939 | 1.75k | return nullptr; |
940 | 150k | return reinterpret_cast<const dos_header *>(base()); |
941 | 151k | } |
942 | | std::error_code getPE32Header(const pe32_header *&Res) const; |
943 | | std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; |
944 | | std::error_code getDataDirectory(uint32_t index, |
945 | | const data_directory *&Res) const; |
946 | | std::error_code getSection(int32_t index, const coff_section *&Res) const; |
947 | | |
948 | | template <typename coff_symbol_type> |
949 | | std::error_code getSymbol(uint32_t Index, |
950 | 0 | const coff_symbol_type *&Res) const { |
951 | 0 | if (Index >= getNumberOfSymbols()) |
952 | 0 | return object_error::parse_failed; |
953 | 0 |
|
954 | 0 | Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; |
955 | 0 | return std::error_code(); |
956 | 0 | } |
957 | | ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const { |
958 | | if (SymbolTable16) { |
959 | | const coff_symbol16 *Symb = nullptr; |
960 | | if (std::error_code EC = getSymbol(index, Symb)) |
961 | | return EC; |
962 | | return COFFSymbolRef(Symb); |
963 | | } |
964 | | if (SymbolTable32) { |
965 | | const coff_symbol32 *Symb = nullptr; |
966 | | if (std::error_code EC = getSymbol(index, Symb)) |
967 | | return EC; |
968 | | return COFFSymbolRef(Symb); |
969 | | } |
970 | | return object_error::parse_failed; |
971 | | } |
972 | | |
973 | | template <typename T> |
974 | | std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { |
975 | | ErrorOr<COFFSymbolRef> s = getSymbol(index); |
976 | | if (std::error_code EC = s.getError()) |
977 | | return EC; |
978 | | Res = reinterpret_cast<const T *>(s->getRawPtr()); |
979 | | return std::error_code(); |
980 | | } |
981 | | |
982 | | std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; |
983 | | std::error_code getSymbolName(const coff_symbol_generic *Symbol, |
984 | | StringRef &Res) const; |
985 | | |
986 | | ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; |
987 | | |
988 | 2.87k | size_t getSymbolTableEntrySize() const { |
989 | 2.87k | if (COFFHeader) |
990 | 2.86k | return sizeof(coff_symbol16); |
991 | 11 | if (11 COFFBigObjHeader11 ) |
992 | 11 | return sizeof(coff_symbol32); |
993 | 0 | llvm_unreachable0 ("null symbol table pointer!"); |
994 | 11 | } |
995 | | |
996 | | iterator_range<const coff_relocation *> |
997 | | getRelocations(const coff_section *Sec) const; |
998 | | |
999 | | std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; |
1000 | | uint64_t getSectionSize(const coff_section *Sec) const; |
1001 | | std::error_code getSectionContents(const coff_section *Sec, |
1002 | | ArrayRef<uint8_t> &Res) const; |
1003 | | |
1004 | | uint64_t getImageBase() const; |
1005 | | std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; |
1006 | | std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; |
1007 | | |
1008 | | /// Given an RVA base and size, returns a valid array of bytes or an error |
1009 | | /// code if the RVA and size is not contained completely within a valid |
1010 | | /// section. |
1011 | | std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, |
1012 | | ArrayRef<uint8_t> &Contents) const; |
1013 | | |
1014 | | std::error_code getHintName(uint32_t Rva, uint16_t &Hint, |
1015 | | StringRef &Name) const; |
1016 | | |
1017 | | /// Get PDB information out of a codeview debug directory entry. |
1018 | | std::error_code getDebugPDBInfo(const debug_directory *DebugDir, |
1019 | | const codeview::DebugInfo *&Info, |
1020 | | StringRef &PDBFileName) const; |
1021 | | |
1022 | | /// Get PDB information from an executable. If the information is not present, |
1023 | | /// Info will be set to nullptr and PDBFileName will be empty. An error is |
1024 | | /// returned only on corrupt object files. Convenience accessor that can be |
1025 | | /// used if the debug directory is not already handy. |
1026 | | std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info, |
1027 | | StringRef &PDBFileName) const; |
1028 | | |
1029 | | bool isRelocatableObject() const override; |
1030 | 33 | bool is64() const { return PE32PlusHeader; } |
1031 | | |
1032 | 5.57k | static bool classof(const Binary *v) { return v->isCOFF(); } |
1033 | | }; |
1034 | | |
1035 | | // The iterator for the import directory table. |
1036 | | class ImportDirectoryEntryRef { |
1037 | | public: |
1038 | | ImportDirectoryEntryRef() = default; |
1039 | | ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, |
1040 | | uint32_t I, const COFFObjectFile *Owner) |
1041 | 78 | : ImportTable(Table), Index(I), OwningObject(Owner) {} |
1042 | | |
1043 | | bool operator==(const ImportDirectoryEntryRef &Other) const; |
1044 | | void moveNext(); |
1045 | | |
1046 | | imported_symbol_iterator imported_symbol_begin() const; |
1047 | | imported_symbol_iterator imported_symbol_end() const; |
1048 | | iterator_range<imported_symbol_iterator> imported_symbols() const; |
1049 | | |
1050 | | imported_symbol_iterator lookup_table_begin() const; |
1051 | | imported_symbol_iterator lookup_table_end() const; |
1052 | | iterator_range<imported_symbol_iterator> lookup_table_symbols() const; |
1053 | | |
1054 | | std::error_code getName(StringRef &Result) const; |
1055 | | std::error_code getImportLookupTableRVA(uint32_t &Result) const; |
1056 | | std::error_code getImportAddressTableRVA(uint32_t &Result) const; |
1057 | | |
1058 | | std::error_code |
1059 | | getImportTableEntry(const coff_import_directory_table_entry *&Result) const; |
1060 | | |
1061 | | private: |
1062 | | const coff_import_directory_table_entry *ImportTable; |
1063 | | uint32_t Index; |
1064 | | const COFFObjectFile *OwningObject = nullptr; |
1065 | | }; |
1066 | | |
1067 | | class DelayImportDirectoryEntryRef { |
1068 | | public: |
1069 | | DelayImportDirectoryEntryRef() = default; |
1070 | | DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, |
1071 | | uint32_t I, const COFFObjectFile *Owner) |
1072 | 30 | : Table(T), Index(I), OwningObject(Owner) {} |
1073 | | |
1074 | | bool operator==(const DelayImportDirectoryEntryRef &Other) const; |
1075 | | void moveNext(); |
1076 | | |
1077 | | imported_symbol_iterator imported_symbol_begin() const; |
1078 | | imported_symbol_iterator imported_symbol_end() const; |
1079 | | iterator_range<imported_symbol_iterator> imported_symbols() const; |
1080 | | |
1081 | | std::error_code getName(StringRef &Result) const; |
1082 | | std::error_code getDelayImportTable( |
1083 | | const delay_import_directory_table_entry *&Result) const; |
1084 | | std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; |
1085 | | |
1086 | | private: |
1087 | | const delay_import_directory_table_entry *Table; |
1088 | | uint32_t Index; |
1089 | | const COFFObjectFile *OwningObject = nullptr; |
1090 | | }; |
1091 | | |
1092 | | // The iterator for the export directory table entry. |
1093 | | class ExportDirectoryEntryRef { |
1094 | | public: |
1095 | | ExportDirectoryEntryRef() = default; |
1096 | | ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, |
1097 | | const COFFObjectFile *Owner) |
1098 | 182 | : ExportTable(Table), Index(I), OwningObject(Owner) {} |
1099 | | |
1100 | | bool operator==(const ExportDirectoryEntryRef &Other) const; |
1101 | | void moveNext(); |
1102 | | |
1103 | | std::error_code getDllName(StringRef &Result) const; |
1104 | | std::error_code getOrdinalBase(uint32_t &Result) const; |
1105 | | std::error_code getOrdinal(uint32_t &Result) const; |
1106 | | std::error_code getExportRVA(uint32_t &Result) const; |
1107 | | std::error_code getSymbolName(StringRef &Result) const; |
1108 | | |
1109 | | std::error_code isForwarder(bool &Result) const; |
1110 | | std::error_code getForwardTo(StringRef &Result) const; |
1111 | | |
1112 | | private: |
1113 | | const export_directory_table_entry *ExportTable; |
1114 | | uint32_t Index; |
1115 | | const COFFObjectFile *OwningObject = nullptr; |
1116 | | }; |
1117 | | |
1118 | | class ImportedSymbolRef { |
1119 | | public: |
1120 | | ImportedSymbolRef() = default; |
1121 | | ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, |
1122 | | const COFFObjectFile *Owner) |
1123 | 24 | : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} |
1124 | | ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, |
1125 | | const COFFObjectFile *Owner) |
1126 | 26 | : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} |
1127 | | |
1128 | | bool operator==(const ImportedSymbolRef &Other) const; |
1129 | | void moveNext(); |
1130 | | |
1131 | | std::error_code getSymbolName(StringRef &Result) const; |
1132 | | std::error_code isOrdinal(bool &Result) const; |
1133 | | std::error_code getOrdinal(uint16_t &Result) const; |
1134 | | std::error_code getHintNameRVA(uint32_t &Result) const; |
1135 | | |
1136 | | private: |
1137 | | const import_lookup_table_entry32 *Entry32; |
1138 | | const import_lookup_table_entry64 *Entry64; |
1139 | | uint32_t Index; |
1140 | | const COFFObjectFile *OwningObject = nullptr; |
1141 | | }; |
1142 | | |
1143 | | class BaseRelocRef { |
1144 | | public: |
1145 | | BaseRelocRef() = default; |
1146 | | BaseRelocRef(const coff_base_reloc_block_header *Header, |
1147 | | const COFFObjectFile *Owner) |
1148 | 18 | : Header(Header), Index(0), OwningObject(Owner) {} |
1149 | | |
1150 | | bool operator==(const BaseRelocRef &Other) const; |
1151 | | void moveNext(); |
1152 | | |
1153 | | std::error_code getType(uint8_t &Type) const; |
1154 | | std::error_code getRVA(uint32_t &Result) const; |
1155 | | |
1156 | | private: |
1157 | | const coff_base_reloc_block_header *Header; |
1158 | | uint32_t Index; |
1159 | | const COFFObjectFile *OwningObject = nullptr; |
1160 | | }; |
1161 | | |
1162 | | class ResourceSectionRef { |
1163 | | public: |
1164 | | ResourceSectionRef() = default; |
1165 | 0 | explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} |
1166 | | |
1167 | | ErrorOr<ArrayRef<UTF16>> getEntryNameString(const coff_resource_dir_entry &Entry); |
1168 | | ErrorOr<const coff_resource_dir_table &> |
1169 | | getEntrySubDir(const coff_resource_dir_entry &Entry); |
1170 | | ErrorOr<const coff_resource_dir_table &> getBaseTable(); |
1171 | | |
1172 | | private: |
1173 | | BinaryByteStream BBS; |
1174 | | |
1175 | | ErrorOr<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); |
1176 | | ErrorOr<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); |
1177 | | }; |
1178 | | |
1179 | | // Corresponds to `_FPO_DATA` structure in the PE/COFF spec. |
1180 | | struct FpoData { |
1181 | | support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code |
1182 | | support::ulittle32_t Size; // cbProcSize: # bytes in function |
1183 | | support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 |
1184 | | support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 |
1185 | | support::ulittle16_t Attributes; |
1186 | | |
1187 | | // cbProlog: # bytes in prolog |
1188 | 0 | int getPrologSize() const { return Attributes & 0xF; } |
1189 | | |
1190 | | // cbRegs: # regs saved |
1191 | 0 | int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } |
1192 | | |
1193 | | // fHasSEH: true if seh is func |
1194 | 0 | bool hasSEH() const { return (Attributes >> 9) & 1; } |
1195 | | |
1196 | | // fUseBP: true if EBP has been allocated |
1197 | 0 | bool useBP() const { return (Attributes >> 10) & 1; } |
1198 | | |
1199 | | // cbFrame: frame pointer |
1200 | 0 | int getFP() const { return Attributes >> 14; } |
1201 | | }; |
1202 | | |
1203 | | } // end namespace object |
1204 | | |
1205 | | } // end namespace llvm |
1206 | | |
1207 | | #endif // LLVM_OBJECT_COFF_H |