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