Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:17

0001 //===- COFF.h - COFF object file implementation -----------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the COFFObjectFile class.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_OBJECT_COFF_H
0014 #define LLVM_OBJECT_COFF_H
0015 
0016 #include "llvm/ADT/iterator_range.h"
0017 #include "llvm/BinaryFormat/COFF.h"
0018 #include "llvm/Object/Binary.h"
0019 #include "llvm/Object/CVDebugRecord.h"
0020 #include "llvm/Object/Error.h"
0021 #include "llvm/Object/ObjectFile.h"
0022 #include "llvm/Support/BinaryByteStream.h"
0023 #include "llvm/Support/ConvertUTF.h"
0024 #include "llvm/Support/Endian.h"
0025 #include "llvm/Support/ErrorHandling.h"
0026 #include "llvm/TargetParser/SubtargetFeature.h"
0027 #include <cassert>
0028 #include <cstddef>
0029 #include <cstdint>
0030 #include <system_error>
0031 
0032 namespace llvm {
0033 
0034 template <typename T> class ArrayRef;
0035 
0036 namespace object {
0037 
0038 class Arm64XRelocRef;
0039 class BaseRelocRef;
0040 class DelayImportDirectoryEntryRef;
0041 class DynamicRelocRef;
0042 class ExportDirectoryEntryRef;
0043 class ImportDirectoryEntryRef;
0044 class ImportedSymbolRef;
0045 class ResourceSectionRef;
0046 
0047 using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>;
0048 using delay_import_directory_iterator =
0049     content_iterator<DelayImportDirectoryEntryRef>;
0050 using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>;
0051 using imported_symbol_iterator = content_iterator<ImportedSymbolRef>;
0052 using base_reloc_iterator = content_iterator<BaseRelocRef>;
0053 using dynamic_reloc_iterator = content_iterator<DynamicRelocRef>;
0054 using arm64x_reloc_iterator = content_iterator<Arm64XRelocRef>;
0055 
0056 /// The DOS compatible header at the front of all PE/COFF executables.
0057 struct dos_header {
0058   char                 Magic[2];
0059   support::ulittle16_t UsedBytesInTheLastPage;
0060   support::ulittle16_t FileSizeInPages;
0061   support::ulittle16_t NumberOfRelocationItems;
0062   support::ulittle16_t HeaderSizeInParagraphs;
0063   support::ulittle16_t MinimumExtraParagraphs;
0064   support::ulittle16_t MaximumExtraParagraphs;
0065   support::ulittle16_t InitialRelativeSS;
0066   support::ulittle16_t InitialSP;
0067   support::ulittle16_t Checksum;
0068   support::ulittle16_t InitialIP;
0069   support::ulittle16_t InitialRelativeCS;
0070   support::ulittle16_t AddressOfRelocationTable;
0071   support::ulittle16_t OverlayNumber;
0072   support::ulittle16_t Reserved[4];
0073   support::ulittle16_t OEMid;
0074   support::ulittle16_t OEMinfo;
0075   support::ulittle16_t Reserved2[10];
0076   support::ulittle32_t AddressOfNewExeHeader;
0077 };
0078 
0079 struct coff_file_header {
0080   support::ulittle16_t Machine;
0081   support::ulittle16_t NumberOfSections;
0082   support::ulittle32_t TimeDateStamp;
0083   support::ulittle32_t PointerToSymbolTable;
0084   support::ulittle32_t NumberOfSymbols;
0085   support::ulittle16_t SizeOfOptionalHeader;
0086   support::ulittle16_t Characteristics;
0087 
0088   bool isImportLibrary() const { return NumberOfSections == 0xffff; }
0089 };
0090 
0091 struct coff_bigobj_file_header {
0092   support::ulittle16_t Sig1;
0093   support::ulittle16_t Sig2;
0094   support::ulittle16_t Version;
0095   support::ulittle16_t Machine;
0096   support::ulittle32_t TimeDateStamp;
0097   uint8_t              UUID[16];
0098   support::ulittle32_t unused1;
0099   support::ulittle32_t unused2;
0100   support::ulittle32_t unused3;
0101   support::ulittle32_t unused4;
0102   support::ulittle32_t NumberOfSections;
0103   support::ulittle32_t PointerToSymbolTable;
0104   support::ulittle32_t NumberOfSymbols;
0105 };
0106 
0107 /// The 32-bit PE header that follows the COFF header.
0108 struct pe32_header {
0109   support::ulittle16_t Magic;
0110   uint8_t MajorLinkerVersion;
0111   uint8_t MinorLinkerVersion;
0112   support::ulittle32_t SizeOfCode;
0113   support::ulittle32_t SizeOfInitializedData;
0114   support::ulittle32_t SizeOfUninitializedData;
0115   support::ulittle32_t AddressOfEntryPoint;
0116   support::ulittle32_t BaseOfCode;
0117   support::ulittle32_t BaseOfData;
0118   support::ulittle32_t ImageBase;
0119   support::ulittle32_t SectionAlignment;
0120   support::ulittle32_t FileAlignment;
0121   support::ulittle16_t MajorOperatingSystemVersion;
0122   support::ulittle16_t MinorOperatingSystemVersion;
0123   support::ulittle16_t MajorImageVersion;
0124   support::ulittle16_t MinorImageVersion;
0125   support::ulittle16_t MajorSubsystemVersion;
0126   support::ulittle16_t MinorSubsystemVersion;
0127   support::ulittle32_t Win32VersionValue;
0128   support::ulittle32_t SizeOfImage;
0129   support::ulittle32_t SizeOfHeaders;
0130   support::ulittle32_t CheckSum;
0131   support::ulittle16_t Subsystem;
0132   // FIXME: This should be DllCharacteristics.
0133   support::ulittle16_t DLLCharacteristics;
0134   support::ulittle32_t SizeOfStackReserve;
0135   support::ulittle32_t SizeOfStackCommit;
0136   support::ulittle32_t SizeOfHeapReserve;
0137   support::ulittle32_t SizeOfHeapCommit;
0138   support::ulittle32_t LoaderFlags;
0139   // FIXME: This should be NumberOfRvaAndSizes.
0140   support::ulittle32_t NumberOfRvaAndSize;
0141 };
0142 
0143 /// The 64-bit PE header that follows the COFF header.
0144 struct pe32plus_header {
0145   support::ulittle16_t Magic;
0146   uint8_t MajorLinkerVersion;
0147   uint8_t MinorLinkerVersion;
0148   support::ulittle32_t SizeOfCode;
0149   support::ulittle32_t SizeOfInitializedData;
0150   support::ulittle32_t SizeOfUninitializedData;
0151   support::ulittle32_t AddressOfEntryPoint;
0152   support::ulittle32_t BaseOfCode;
0153   support::ulittle64_t ImageBase;
0154   support::ulittle32_t SectionAlignment;
0155   support::ulittle32_t FileAlignment;
0156   support::ulittle16_t MajorOperatingSystemVersion;
0157   support::ulittle16_t MinorOperatingSystemVersion;
0158   support::ulittle16_t MajorImageVersion;
0159   support::ulittle16_t MinorImageVersion;
0160   support::ulittle16_t MajorSubsystemVersion;
0161   support::ulittle16_t MinorSubsystemVersion;
0162   support::ulittle32_t Win32VersionValue;
0163   support::ulittle32_t SizeOfImage;
0164   support::ulittle32_t SizeOfHeaders;
0165   support::ulittle32_t CheckSum;
0166   support::ulittle16_t Subsystem;
0167   support::ulittle16_t DLLCharacteristics;
0168   support::ulittle64_t SizeOfStackReserve;
0169   support::ulittle64_t SizeOfStackCommit;
0170   support::ulittle64_t SizeOfHeapReserve;
0171   support::ulittle64_t SizeOfHeapCommit;
0172   support::ulittle32_t LoaderFlags;
0173   support::ulittle32_t NumberOfRvaAndSize;
0174 };
0175 
0176 struct data_directory {
0177   support::ulittle32_t RelativeVirtualAddress;
0178   support::ulittle32_t Size;
0179 };
0180 
0181 struct debug_directory {
0182   support::ulittle32_t Characteristics;
0183   support::ulittle32_t TimeDateStamp;
0184   support::ulittle16_t MajorVersion;
0185   support::ulittle16_t MinorVersion;
0186   support::ulittle32_t Type;
0187   support::ulittle32_t SizeOfData;
0188   support::ulittle32_t AddressOfRawData;
0189   support::ulittle32_t PointerToRawData;
0190 };
0191 
0192 template <typename IntTy>
0193 struct import_lookup_table_entry {
0194   IntTy Data;
0195 
0196   bool isOrdinal() const { return Data < 0; }
0197 
0198   uint16_t getOrdinal() const {
0199     assert(isOrdinal() && "ILT entry is not an ordinal!");
0200     return Data & 0xFFFF;
0201   }
0202 
0203   uint32_t getHintNameRVA() const {
0204     assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
0205     return Data & 0xFFFFFFFF;
0206   }
0207 };
0208 
0209 using import_lookup_table_entry32 =
0210     import_lookup_table_entry<support::little32_t>;
0211 using import_lookup_table_entry64 =
0212     import_lookup_table_entry<support::little64_t>;
0213 
0214 struct delay_import_directory_table_entry {
0215   // dumpbin reports this field as "Characteristics" instead of "Attributes".
0216   support::ulittle32_t Attributes;
0217   support::ulittle32_t Name;
0218   support::ulittle32_t ModuleHandle;
0219   support::ulittle32_t DelayImportAddressTable;
0220   support::ulittle32_t DelayImportNameTable;
0221   support::ulittle32_t BoundDelayImportTable;
0222   support::ulittle32_t UnloadDelayImportTable;
0223   support::ulittle32_t TimeStamp;
0224 };
0225 
0226 struct export_directory_table_entry {
0227   support::ulittle32_t ExportFlags;
0228   support::ulittle32_t TimeDateStamp;
0229   support::ulittle16_t MajorVersion;
0230   support::ulittle16_t MinorVersion;
0231   support::ulittle32_t NameRVA;
0232   support::ulittle32_t OrdinalBase;
0233   support::ulittle32_t AddressTableEntries;
0234   support::ulittle32_t NumberOfNamePointers;
0235   support::ulittle32_t ExportAddressTableRVA;
0236   support::ulittle32_t NamePointerRVA;
0237   support::ulittle32_t OrdinalTableRVA;
0238 };
0239 
0240 union export_address_table_entry {
0241   support::ulittle32_t ExportRVA;
0242   support::ulittle32_t ForwarderRVA;
0243 };
0244 
0245 using export_name_pointer_table_entry = support::ulittle32_t;
0246 using export_ordinal_table_entry = support::ulittle16_t;
0247 
0248 struct StringTableOffset {
0249   support::ulittle32_t Zeroes;
0250   support::ulittle32_t Offset;
0251 };
0252 
0253 template <typename SectionNumberType>
0254 struct coff_symbol {
0255   union {
0256     char ShortName[COFF::NameSize];
0257     StringTableOffset Offset;
0258   } Name;
0259 
0260   support::ulittle32_t Value;
0261   SectionNumberType SectionNumber;
0262 
0263   support::ulittle16_t Type;
0264 
0265   uint8_t StorageClass;
0266   uint8_t NumberOfAuxSymbols;
0267 };
0268 
0269 using coff_symbol16 = coff_symbol<support::ulittle16_t>;
0270 using coff_symbol32 = coff_symbol<support::ulittle32_t>;
0271 
0272 // Contains only common parts of coff_symbol16 and coff_symbol32.
0273 struct coff_symbol_generic {
0274   union {
0275     char ShortName[COFF::NameSize];
0276     StringTableOffset Offset;
0277   } Name;
0278   support::ulittle32_t Value;
0279 };
0280 
0281 struct coff_aux_section_definition;
0282 struct coff_aux_weak_external;
0283 
0284 class COFFSymbolRef {
0285 public:
0286   COFFSymbolRef() = default;
0287   COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {}
0288   COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {}
0289 
0290   const void *getRawPtr() const {
0291     return CS16 ? static_cast<const void *>(CS16) : CS32;
0292   }
0293 
0294   const coff_symbol_generic *getGeneric() const {
0295     if (CS16)
0296       return reinterpret_cast<const coff_symbol_generic *>(CS16);
0297     return reinterpret_cast<const coff_symbol_generic *>(CS32);
0298   }
0299 
0300   friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) {
0301     return A.getRawPtr() < B.getRawPtr();
0302   }
0303 
0304   bool isBigObj() const {
0305     if (CS16)
0306       return false;
0307     if (CS32)
0308       return true;
0309     llvm_unreachable("COFFSymbolRef points to nothing!");
0310   }
0311 
0312   const char *getShortName() const {
0313     return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName;
0314   }
0315 
0316   const StringTableOffset &getStringTableOffset() const {
0317     assert(isSet() && "COFFSymbolRef points to nothing!");
0318     return CS16 ? CS16->Name.Offset : CS32->Name.Offset;
0319   }
0320 
0321   uint32_t getValue() const {
0322     assert(isSet() && "COFFSymbolRef points to nothing!");
0323     return CS16 ? CS16->Value : CS32->Value;
0324   }
0325 
0326   int32_t getSectionNumber() const {
0327     assert(isSet() && "COFFSymbolRef points to nothing!");
0328     if (CS16) {
0329       // Reserved sections are returned as negative numbers.
0330       if (CS16->SectionNumber <= COFF::MaxNumberOfSections16)
0331         return CS16->SectionNumber;
0332       return static_cast<int16_t>(CS16->SectionNumber);
0333     }
0334     return static_cast<int32_t>(CS32->SectionNumber);
0335   }
0336 
0337   uint16_t getType() const {
0338     assert(isSet() && "COFFSymbolRef points to nothing!");
0339     return CS16 ? CS16->Type : CS32->Type;
0340   }
0341 
0342   uint8_t getStorageClass() const {
0343     assert(isSet() && "COFFSymbolRef points to nothing!");
0344     return CS16 ? CS16->StorageClass : CS32->StorageClass;
0345   }
0346 
0347   uint8_t getNumberOfAuxSymbols() const {
0348     assert(isSet() && "COFFSymbolRef points to nothing!");
0349     return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols;
0350   }
0351 
0352   uint8_t getBaseType() const { return getType() & 0x0F; }
0353 
0354   uint8_t getComplexType() const {
0355     return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
0356   }
0357 
0358   template <typename T> const T *getAux() const {
0359     return CS16 ? reinterpret_cast<const T *>(CS16 + 1)
0360                 : reinterpret_cast<const T *>(CS32 + 1);
0361   }
0362 
0363   const coff_aux_section_definition *getSectionDefinition() const {
0364     if (!getNumberOfAuxSymbols() ||
0365         getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC)
0366       return nullptr;
0367     return getAux<coff_aux_section_definition>();
0368   }
0369 
0370   const coff_aux_weak_external *getWeakExternal() const {
0371     if (!getNumberOfAuxSymbols() ||
0372         getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
0373       return nullptr;
0374     return getAux<coff_aux_weak_external>();
0375   }
0376 
0377   bool isAbsolute() const {
0378     return getSectionNumber() == -1;
0379   }
0380 
0381   bool isExternal() const {
0382     return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
0383   }
0384 
0385   bool isCommon() const {
0386     return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
0387            getValue() != 0;
0388   }
0389 
0390   bool isUndefined() const {
0391     return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
0392            getValue() == 0;
0393   }
0394 
0395   bool isEmptySectionDeclaration() const {
0396     return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED;
0397   }
0398 
0399   bool isWeakExternal() const {
0400     return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
0401   }
0402 
0403   bool isFunctionDefinition() const {
0404     return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
0405            getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
0406            !COFF::isReservedSectionNumber(getSectionNumber());
0407   }
0408 
0409   bool isFunctionLineInfo() const {
0410     return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
0411   }
0412 
0413   bool isAnyUndefined() const {
0414     return isUndefined() || isWeakExternal();
0415   }
0416 
0417   bool isFileRecord() const {
0418     return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
0419   }
0420 
0421   bool isSection() const {
0422     return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
0423   }
0424 
0425   bool isSectionDefinition() const {
0426     // C++/CLI creates external ABS symbols for non-const appdomain globals.
0427     // These are also followed by an auxiliary section definition.
0428     bool isAppdomainGlobal =
0429         getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
0430         getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
0431     bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
0432     if (!getNumberOfAuxSymbols())
0433       return false;
0434     return isAppdomainGlobal || isOrdinarySection;
0435   }
0436 
0437   bool isCLRToken() const {
0438     return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
0439   }
0440 
0441 private:
0442   bool isSet() const { return CS16 || CS32; }
0443 
0444   const coff_symbol16 *CS16 = nullptr;
0445   const coff_symbol32 *CS32 = nullptr;
0446 };
0447 
0448 struct coff_section {
0449   char Name[COFF::NameSize];
0450   support::ulittle32_t VirtualSize;
0451   support::ulittle32_t VirtualAddress;
0452   support::ulittle32_t SizeOfRawData;
0453   support::ulittle32_t PointerToRawData;
0454   support::ulittle32_t PointerToRelocations;
0455   support::ulittle32_t PointerToLinenumbers;
0456   support::ulittle16_t NumberOfRelocations;
0457   support::ulittle16_t NumberOfLinenumbers;
0458   support::ulittle32_t Characteristics;
0459 
0460   // Returns true if the actual number of relocations is stored in
0461   // VirtualAddress field of the first relocation table entry.
0462   bool hasExtendedRelocations() const {
0463     return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
0464            NumberOfRelocations == UINT16_MAX;
0465   }
0466 
0467   uint32_t getAlignment() const {
0468     // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to
0469     // IMAGE_SCN_ALIGN_1BYTES.
0470     if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
0471       return 1;
0472 
0473     // Bit [20:24] contains section alignment. 0 means use a default alignment
0474     // of 16.
0475     uint32_t Shift = (Characteristics >> 20) & 0xF;
0476     if (Shift > 0)
0477       return 1U << (Shift - 1);
0478     return 16;
0479   }
0480 };
0481 
0482 struct coff_relocation {
0483   support::ulittle32_t VirtualAddress;
0484   support::ulittle32_t SymbolTableIndex;
0485   support::ulittle16_t Type;
0486 };
0487 
0488 struct coff_aux_function_definition {
0489   support::ulittle32_t TagIndex;
0490   support::ulittle32_t TotalSize;
0491   support::ulittle32_t PointerToLinenumber;
0492   support::ulittle32_t PointerToNextFunction;
0493   char Unused1[2];
0494 };
0495 
0496 static_assert(sizeof(coff_aux_function_definition) == 18,
0497               "auxiliary entry must be 18 bytes");
0498 
0499 struct coff_aux_bf_and_ef_symbol {
0500   char Unused1[4];
0501   support::ulittle16_t Linenumber;
0502   char Unused2[6];
0503   support::ulittle32_t PointerToNextFunction;
0504   char Unused3[2];
0505 };
0506 
0507 static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18,
0508               "auxiliary entry must be 18 bytes");
0509 
0510 struct coff_aux_weak_external {
0511   support::ulittle32_t TagIndex;
0512   support::ulittle32_t Characteristics;
0513   char Unused1[10];
0514 };
0515 
0516 static_assert(sizeof(coff_aux_weak_external) == 18,
0517               "auxiliary entry must be 18 bytes");
0518 
0519 struct coff_aux_section_definition {
0520   support::ulittle32_t Length;
0521   support::ulittle16_t NumberOfRelocations;
0522   support::ulittle16_t NumberOfLinenumbers;
0523   support::ulittle32_t CheckSum;
0524   support::ulittle16_t NumberLowPart;
0525   uint8_t              Selection;
0526   uint8_t              Unused;
0527   support::ulittle16_t NumberHighPart;
0528   int32_t getNumber(bool IsBigObj) const {
0529     uint32_t Number = static_cast<uint32_t>(NumberLowPart);
0530     if (IsBigObj)
0531       Number |= static_cast<uint32_t>(NumberHighPart) << 16;
0532     return static_cast<int32_t>(Number);
0533   }
0534 };
0535 
0536 static_assert(sizeof(coff_aux_section_definition) == 18,
0537               "auxiliary entry must be 18 bytes");
0538 
0539 struct coff_aux_clr_token {
0540   uint8_t              AuxType;
0541   uint8_t              Reserved;
0542   support::ulittle32_t SymbolTableIndex;
0543   char                 MBZ[12];
0544 };
0545 
0546 static_assert(sizeof(coff_aux_clr_token) == 18,
0547               "auxiliary entry must be 18 bytes");
0548 
0549 struct coff_import_header {
0550   support::ulittle16_t Sig1;
0551   support::ulittle16_t Sig2;
0552   support::ulittle16_t Version;
0553   support::ulittle16_t Machine;
0554   support::ulittle32_t TimeDateStamp;
0555   support::ulittle32_t SizeOfData;
0556   support::ulittle16_t OrdinalHint;
0557   support::ulittle16_t TypeInfo;
0558 
0559   int getType() const { return TypeInfo & 0x3; }
0560   int getNameType() const { return (TypeInfo >> 2) & 0x7; }
0561 };
0562 
0563 struct coff_import_directory_table_entry {
0564   support::ulittle32_t ImportLookupTableRVA;
0565   support::ulittle32_t TimeDateStamp;
0566   support::ulittle32_t ForwarderChain;
0567   support::ulittle32_t NameRVA;
0568   support::ulittle32_t ImportAddressTableRVA;
0569 
0570   bool isNull() const {
0571     return ImportLookupTableRVA == 0 && TimeDateStamp == 0 &&
0572            ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0;
0573   }
0574 };
0575 
0576 template <typename IntTy>
0577 struct coff_tls_directory {
0578   IntTy StartAddressOfRawData;
0579   IntTy EndAddressOfRawData;
0580   IntTy AddressOfIndex;
0581   IntTy AddressOfCallBacks;
0582   support::ulittle32_t SizeOfZeroFill;
0583   support::ulittle32_t Characteristics;
0584 
0585   uint32_t getAlignment() const {
0586     // Bit [20:24] contains section alignment.
0587     uint32_t Shift = (Characteristics & COFF::IMAGE_SCN_ALIGN_MASK) >> 20;
0588     if (Shift > 0)
0589       return 1U << (Shift - 1);
0590     return 0;
0591   }
0592 
0593   void setAlignment(uint32_t Align) {
0594     uint32_t AlignBits = 0;
0595     if (Align) {
0596       assert(llvm::isPowerOf2_32(Align) && "alignment is not a power of 2");
0597       assert(llvm::Log2_32(Align) <= 13 && "alignment requested is too large");
0598       AlignBits = (llvm::Log2_32(Align) + 1) << 20;
0599     }
0600     Characteristics =
0601         (Characteristics & ~COFF::IMAGE_SCN_ALIGN_MASK) | AlignBits;
0602   }
0603 };
0604 
0605 using coff_tls_directory32 = coff_tls_directory<support::little32_t>;
0606 using coff_tls_directory64 = coff_tls_directory<support::little64_t>;
0607 
0608 enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 };
0609 
0610 struct coff_load_config_code_integrity {
0611   support::ulittle16_t Flags;
0612   support::ulittle16_t Catalog;
0613   support::ulittle32_t CatalogOffset;
0614   support::ulittle32_t Reserved;
0615 };
0616 
0617 /// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32)
0618 struct coff_load_configuration32 {
0619   support::ulittle32_t Size;
0620   support::ulittle32_t TimeDateStamp;
0621   support::ulittle16_t MajorVersion;
0622   support::ulittle16_t MinorVersion;
0623   support::ulittle32_t GlobalFlagsClear;
0624   support::ulittle32_t GlobalFlagsSet;
0625   support::ulittle32_t CriticalSectionDefaultTimeout;
0626   support::ulittle32_t DeCommitFreeBlockThreshold;
0627   support::ulittle32_t DeCommitTotalFreeThreshold;
0628   support::ulittle32_t LockPrefixTable;
0629   support::ulittle32_t MaximumAllocationSize;
0630   support::ulittle32_t VirtualMemoryThreshold;
0631   support::ulittle32_t ProcessAffinityMask;
0632   support::ulittle32_t ProcessHeapFlags;
0633   support::ulittle16_t CSDVersion;
0634   support::ulittle16_t DependentLoadFlags;
0635   support::ulittle32_t EditList;
0636   support::ulittle32_t SecurityCookie;
0637   support::ulittle32_t SEHandlerTable;
0638   support::ulittle32_t SEHandlerCount;
0639 
0640   // Added in MSVC 2015 for /guard:cf.
0641   support::ulittle32_t GuardCFCheckFunction;
0642   support::ulittle32_t GuardCFCheckDispatch;
0643   support::ulittle32_t GuardCFFunctionTable;
0644   support::ulittle32_t GuardCFFunctionCount;
0645   support::ulittle32_t GuardFlags; // coff_guard_flags
0646 
0647   // Added in MSVC 2017
0648   coff_load_config_code_integrity CodeIntegrity;
0649   support::ulittle32_t GuardAddressTakenIatEntryTable;
0650   support::ulittle32_t GuardAddressTakenIatEntryCount;
0651   support::ulittle32_t GuardLongJumpTargetTable;
0652   support::ulittle32_t GuardLongJumpTargetCount;
0653   support::ulittle32_t DynamicValueRelocTable;
0654   support::ulittle32_t CHPEMetadataPointer;
0655   support::ulittle32_t GuardRFFailureRoutine;
0656   support::ulittle32_t GuardRFFailureRoutineFunctionPointer;
0657   support::ulittle32_t DynamicValueRelocTableOffset;
0658   support::ulittle16_t DynamicValueRelocTableSection;
0659   support::ulittle16_t Reserved2;
0660   support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer;
0661   support::ulittle32_t HotPatchTableOffset;
0662 
0663   // Added in MSVC 2019
0664   support::ulittle32_t Reserved3;
0665   support::ulittle32_t EnclaveConfigurationPointer;
0666   support::ulittle32_t VolatileMetadataPointer;
0667   support::ulittle32_t GuardEHContinuationTable;
0668   support::ulittle32_t GuardEHContinuationCount;
0669   support::ulittle32_t GuardXFGCheckFunctionPointer;
0670   support::ulittle32_t GuardXFGDispatchFunctionPointer;
0671   support::ulittle32_t GuardXFGTableDispatchFunctionPointer;
0672   support::ulittle32_t CastGuardOsDeterminedFailureMode;
0673 };
0674 
0675 /// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64)
0676 struct coff_load_configuration64 {
0677   support::ulittle32_t Size;
0678   support::ulittle32_t TimeDateStamp;
0679   support::ulittle16_t MajorVersion;
0680   support::ulittle16_t MinorVersion;
0681   support::ulittle32_t GlobalFlagsClear;
0682   support::ulittle32_t GlobalFlagsSet;
0683   support::ulittle32_t CriticalSectionDefaultTimeout;
0684   support::ulittle64_t DeCommitFreeBlockThreshold;
0685   support::ulittle64_t DeCommitTotalFreeThreshold;
0686   support::ulittle64_t LockPrefixTable;
0687   support::ulittle64_t MaximumAllocationSize;
0688   support::ulittle64_t VirtualMemoryThreshold;
0689   support::ulittle64_t ProcessAffinityMask;
0690   support::ulittle32_t ProcessHeapFlags;
0691   support::ulittle16_t CSDVersion;
0692   support::ulittle16_t DependentLoadFlags;
0693   support::ulittle64_t EditList;
0694   support::ulittle64_t SecurityCookie;
0695   support::ulittle64_t SEHandlerTable;
0696   support::ulittle64_t SEHandlerCount;
0697 
0698   // Added in MSVC 2015 for /guard:cf.
0699   support::ulittle64_t GuardCFCheckFunction;
0700   support::ulittle64_t GuardCFCheckDispatch;
0701   support::ulittle64_t GuardCFFunctionTable;
0702   support::ulittle64_t GuardCFFunctionCount;
0703   support::ulittle32_t GuardFlags;
0704 
0705   // Added in MSVC 2017
0706   coff_load_config_code_integrity CodeIntegrity;
0707   support::ulittle64_t GuardAddressTakenIatEntryTable;
0708   support::ulittle64_t GuardAddressTakenIatEntryCount;
0709   support::ulittle64_t GuardLongJumpTargetTable;
0710   support::ulittle64_t GuardLongJumpTargetCount;
0711   support::ulittle64_t DynamicValueRelocTable;
0712   support::ulittle64_t CHPEMetadataPointer;
0713   support::ulittle64_t GuardRFFailureRoutine;
0714   support::ulittle64_t GuardRFFailureRoutineFunctionPointer;
0715   support::ulittle32_t DynamicValueRelocTableOffset;
0716   support::ulittle16_t DynamicValueRelocTableSection;
0717   support::ulittle16_t Reserved2;
0718   support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer;
0719   support::ulittle32_t HotPatchTableOffset;
0720 
0721   // Added in MSVC 2019
0722   support::ulittle32_t Reserved3;
0723   support::ulittle64_t EnclaveConfigurationPointer;
0724   support::ulittle64_t VolatileMetadataPointer;
0725   support::ulittle64_t GuardEHContinuationTable;
0726   support::ulittle64_t GuardEHContinuationCount;
0727   support::ulittle64_t GuardXFGCheckFunctionPointer;
0728   support::ulittle64_t GuardXFGDispatchFunctionPointer;
0729   support::ulittle64_t GuardXFGTableDispatchFunctionPointer;
0730   support::ulittle64_t CastGuardOsDeterminedFailureMode;
0731 };
0732 
0733 struct chpe_metadata {
0734   support::ulittle32_t Version;
0735   support::ulittle32_t CodeMap;
0736   support::ulittle32_t CodeMapCount;
0737   support::ulittle32_t CodeRangesToEntryPoints;
0738   support::ulittle32_t RedirectionMetadata;
0739   support::ulittle32_t __os_arm64x_dispatch_call_no_redirect;
0740   support::ulittle32_t __os_arm64x_dispatch_ret;
0741   support::ulittle32_t __os_arm64x_dispatch_call;
0742   support::ulittle32_t __os_arm64x_dispatch_icall;
0743   support::ulittle32_t __os_arm64x_dispatch_icall_cfg;
0744   support::ulittle32_t AlternateEntryPoint;
0745   support::ulittle32_t AuxiliaryIAT;
0746   support::ulittle32_t CodeRangesToEntryPointsCount;
0747   support::ulittle32_t RedirectionMetadataCount;
0748   support::ulittle32_t GetX64InformationFunctionPointer;
0749   support::ulittle32_t SetX64InformationFunctionPointer;
0750   support::ulittle32_t ExtraRFETable;
0751   support::ulittle32_t ExtraRFETableSize;
0752   support::ulittle32_t __os_arm64x_dispatch_fptr;
0753   support::ulittle32_t AuxiliaryIATCopy;
0754 
0755   // Added in CHPE metadata v2
0756   support::ulittle32_t AuxiliaryDelayloadIAT;
0757   support::ulittle32_t AuxiliaryDelayloadIATCopy;
0758   support::ulittle32_t HybridImageInfoBitfield;
0759 };
0760 
0761 enum chpe_range_type { Arm64 = 0, Arm64EC = 1, Amd64 = 2 };
0762 
0763 struct chpe_range_entry {
0764   support::ulittle32_t StartOffset;
0765   support::ulittle32_t Length;
0766 
0767   // The two low bits of StartOffset contain a range type.
0768   static constexpr uint32_t TypeMask = 3;
0769 
0770   uint32_t getStart() const { return StartOffset & ~TypeMask; }
0771   uint16_t getType() const { return StartOffset & TypeMask; }
0772 };
0773 
0774 struct chpe_code_range_entry {
0775   support::ulittle32_t StartRva;
0776   support::ulittle32_t EndRva;
0777   support::ulittle32_t EntryPoint;
0778 };
0779 
0780 struct chpe_redirection_entry {
0781   support::ulittle32_t Source;
0782   support::ulittle32_t Destination;
0783 };
0784 
0785 struct coff_runtime_function_x64 {
0786   support::ulittle32_t BeginAddress;
0787   support::ulittle32_t EndAddress;
0788   support::ulittle32_t UnwindInformation;
0789 };
0790 
0791 struct coff_base_reloc_block_header {
0792   support::ulittle32_t PageRVA;
0793   support::ulittle32_t BlockSize;
0794 };
0795 
0796 struct coff_base_reloc_block_entry {
0797   support::ulittle16_t Data;
0798 
0799   int getType() const { return Data >> 12; }
0800   int getOffset() const { return Data & ((1 << 12) - 1); }
0801 };
0802 
0803 struct coff_resource_dir_entry {
0804   union {
0805     support::ulittle32_t NameOffset;
0806     support::ulittle32_t ID;
0807     uint32_t getNameOffset() const {
0808       return maskTrailingOnes<uint32_t>(31) & NameOffset;
0809     }
0810     // Even though the PE/COFF spec doesn't mention this, the high bit of a name
0811     // offset is set.
0812     void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); }
0813   } Identifier;
0814   union {
0815     support::ulittle32_t DataEntryOffset;
0816     support::ulittle32_t SubdirOffset;
0817 
0818     bool isSubDir() const { return SubdirOffset >> 31; }
0819     uint32_t value() const {
0820       return maskTrailingOnes<uint32_t>(31) & SubdirOffset;
0821     }
0822 
0823   } Offset;
0824 };
0825 
0826 struct coff_resource_data_entry {
0827   support::ulittle32_t DataRVA;
0828   support::ulittle32_t DataSize;
0829   support::ulittle32_t Codepage;
0830   support::ulittle32_t Reserved;
0831 };
0832 
0833 struct coff_resource_dir_table {
0834   support::ulittle32_t Characteristics;
0835   support::ulittle32_t TimeDateStamp;
0836   support::ulittle16_t MajorVersion;
0837   support::ulittle16_t MinorVersion;
0838   support::ulittle16_t NumberOfNameEntries;
0839   support::ulittle16_t NumberOfIDEntries;
0840 };
0841 
0842 struct debug_h_header {
0843   support::ulittle32_t Magic;
0844   support::ulittle16_t Version;
0845   support::ulittle16_t HashAlgorithm;
0846 };
0847 
0848 struct coff_dynamic_reloc_table {
0849   support::ulittle32_t Version;
0850   support::ulittle32_t Size;
0851 };
0852 
0853 struct coff_dynamic_relocation32 {
0854   support::ulittle32_t Symbol;
0855   support::ulittle32_t BaseRelocSize;
0856 };
0857 
0858 struct coff_dynamic_relocation64 {
0859   support::ulittle64_t Symbol;
0860   support::ulittle32_t BaseRelocSize;
0861 };
0862 
0863 struct coff_dynamic_relocation32_v2 {
0864   support::ulittle32_t HeaderSize;
0865   support::ulittle32_t FixupInfoSize;
0866   support::ulittle32_t Symbol;
0867   support::ulittle32_t SymbolGroup;
0868   support::ulittle32_t Flags;
0869 };
0870 
0871 struct coff_dynamic_relocation64_v2 {
0872   support::ulittle32_t HeaderSize;
0873   support::ulittle32_t FixupInfoSize;
0874   support::ulittle64_t Symbol;
0875   support::ulittle32_t SymbolGroup;
0876   support::ulittle32_t Flags;
0877 };
0878 
0879 class COFFObjectFile : public ObjectFile {
0880 private:
0881   COFFObjectFile(MemoryBufferRef Object);
0882 
0883   friend class ImportDirectoryEntryRef;
0884   friend class ExportDirectoryEntryRef;
0885   const coff_file_header *COFFHeader;
0886   const coff_bigobj_file_header *COFFBigObjHeader;
0887   const pe32_header *PE32Header;
0888   const pe32plus_header *PE32PlusHeader;
0889   const data_directory *DataDirectory;
0890   const coff_section *SectionTable;
0891   const coff_symbol16 *SymbolTable16;
0892   const coff_symbol32 *SymbolTable32;
0893   const char *StringTable;
0894   uint32_t StringTableSize;
0895   const coff_import_directory_table_entry *ImportDirectory;
0896   const delay_import_directory_table_entry *DelayImportDirectory;
0897   uint32_t NumberOfDelayImportDirectory;
0898   const export_directory_table_entry *ExportDirectory;
0899   const coff_base_reloc_block_header *BaseRelocHeader;
0900   const coff_base_reloc_block_header *BaseRelocEnd;
0901   const debug_directory *DebugDirectoryBegin;
0902   const debug_directory *DebugDirectoryEnd;
0903   const coff_tls_directory32 *TLSDirectory32;
0904   const coff_tls_directory64 *TLSDirectory64;
0905   // Either coff_load_configuration32 or coff_load_configuration64.
0906   const void *LoadConfig = nullptr;
0907   const chpe_metadata *CHPEMetadata = nullptr;
0908   const coff_dynamic_reloc_table *DynamicRelocTable = nullptr;
0909 
0910   Expected<StringRef> getString(uint32_t offset) const;
0911 
0912   template <typename coff_symbol_type>
0913   const coff_symbol_type *toSymb(DataRefImpl Symb) const;
0914   const coff_section *toSec(DataRefImpl Sec) const;
0915   const coff_relocation *toRel(DataRefImpl Rel) const;
0916 
0917   // Finish initializing the object and return success or an error.
0918   Error initialize();
0919 
0920   Error initSymbolTablePtr();
0921   Error initImportTablePtr();
0922   Error initDelayImportTablePtr();
0923   Error initExportTablePtr();
0924   Error initBaseRelocPtr();
0925   Error initDebugDirectoryPtr();
0926   Error initTLSDirectoryPtr();
0927   Error initLoadConfigPtr();
0928   Error initDynamicRelocPtr(uint32_t SectionIndex, uint32_t SectionOffset);
0929 
0930 public:
0931   static Expected<std::unique_ptr<COFFObjectFile>>
0932   create(MemoryBufferRef Object);
0933 
0934   uintptr_t getSymbolTable() const {
0935     if (SymbolTable16)
0936       return reinterpret_cast<uintptr_t>(SymbolTable16);
0937     if (SymbolTable32)
0938       return reinterpret_cast<uintptr_t>(SymbolTable32);
0939     return uintptr_t(0);
0940   }
0941 
0942   uint16_t getMachine() const {
0943     if (COFFHeader) {
0944       if (CHPEMetadata) {
0945         switch (COFFHeader->Machine) {
0946         case COFF::IMAGE_FILE_MACHINE_AMD64:
0947           return COFF::IMAGE_FILE_MACHINE_ARM64EC;
0948         case COFF::IMAGE_FILE_MACHINE_ARM64:
0949           return COFF::IMAGE_FILE_MACHINE_ARM64X;
0950         }
0951       }
0952       return COFFHeader->Machine;
0953     }
0954     if (COFFBigObjHeader)
0955       return COFFBigObjHeader->Machine;
0956     llvm_unreachable("no COFF header!");
0957   }
0958 
0959   uint16_t getSizeOfOptionalHeader() const {
0960     if (COFFHeader)
0961       return COFFHeader->isImportLibrary() ? 0
0962                                            : COFFHeader->SizeOfOptionalHeader;
0963     // bigobj doesn't have this field.
0964     if (COFFBigObjHeader)
0965       return 0;
0966     llvm_unreachable("no COFF header!");
0967   }
0968 
0969   uint16_t getCharacteristics() const {
0970     if (COFFHeader)
0971       return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics;
0972     // bigobj doesn't have characteristics to speak of,
0973     // editbin will silently lie to you if you attempt to set any.
0974     if (COFFBigObjHeader)
0975       return 0;
0976     llvm_unreachable("no COFF header!");
0977   }
0978 
0979   uint32_t getTimeDateStamp() const {
0980     if (COFFHeader)
0981       return COFFHeader->TimeDateStamp;
0982     if (COFFBigObjHeader)
0983       return COFFBigObjHeader->TimeDateStamp;
0984     llvm_unreachable("no COFF header!");
0985   }
0986 
0987   uint32_t getNumberOfSections() const {
0988     if (COFFHeader)
0989       return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections;
0990     if (COFFBigObjHeader)
0991       return COFFBigObjHeader->NumberOfSections;
0992     llvm_unreachable("no COFF header!");
0993   }
0994 
0995   uint32_t getPointerToSymbolTable() const {
0996     if (COFFHeader)
0997       return COFFHeader->isImportLibrary() ? 0
0998                                            : COFFHeader->PointerToSymbolTable;
0999     if (COFFBigObjHeader)
1000       return COFFBigObjHeader->PointerToSymbolTable;
1001     llvm_unreachable("no COFF header!");
1002   }
1003 
1004   uint32_t getRawNumberOfSymbols() const {
1005     if (COFFHeader)
1006       return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols;
1007     if (COFFBigObjHeader)
1008       return COFFBigObjHeader->NumberOfSymbols;
1009     llvm_unreachable("no COFF header!");
1010   }
1011 
1012   uint32_t getNumberOfSymbols() const {
1013     if (!SymbolTable16 && !SymbolTable32)
1014       return 0;
1015     return getRawNumberOfSymbols();
1016   }
1017 
1018   uint32_t getStringTableSize() const { return StringTableSize; }
1019 
1020   const export_directory_table_entry *getExportTable() const {
1021     return ExportDirectory;
1022   }
1023 
1024   const coff_load_configuration32 *getLoadConfig32() const {
1025     assert(!is64());
1026     return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig);
1027   }
1028 
1029   const coff_load_configuration64 *getLoadConfig64() const {
1030     assert(is64());
1031     return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig);
1032   }
1033 
1034   const chpe_metadata *getCHPEMetadata() const { return CHPEMetadata; }
1035   const coff_dynamic_reloc_table *getDynamicRelocTable() const {
1036     return DynamicRelocTable;
1037   }
1038 
1039   StringRef getRelocationTypeName(uint16_t Type) const;
1040 
1041 protected:
1042   void moveSymbolNext(DataRefImpl &Symb) const override;
1043   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
1044   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
1045   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
1046   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
1047   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
1048   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
1049   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
1050   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
1051   void moveSectionNext(DataRefImpl &Sec) const override;
1052   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
1053   uint64_t getSectionAddress(DataRefImpl Sec) const override;
1054   uint64_t getSectionIndex(DataRefImpl Sec) const override;
1055   uint64_t getSectionSize(DataRefImpl Sec) const override;
1056   Expected<ArrayRef<uint8_t>>
1057   getSectionContents(DataRefImpl Sec) const override;
1058   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
1059   bool isSectionCompressed(DataRefImpl Sec) const override;
1060   bool isSectionText(DataRefImpl Sec) const override;
1061   bool isSectionData(DataRefImpl Sec) const override;
1062   bool isSectionBSS(DataRefImpl Sec) const override;
1063   bool isSectionVirtual(DataRefImpl Sec) const override;
1064   bool isDebugSection(DataRefImpl Sec) const override;
1065   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
1066   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
1067 
1068   void moveRelocationNext(DataRefImpl &Rel) const override;
1069   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
1070   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
1071   uint64_t getRelocationType(DataRefImpl Rel) const override;
1072   void getRelocationTypeName(DataRefImpl Rel,
1073                              SmallVectorImpl<char> &Result) const override;
1074 
1075 public:
1076   basic_symbol_iterator symbol_begin() const override;
1077   basic_symbol_iterator symbol_end() const override;
1078   section_iterator section_begin() const override;
1079   section_iterator section_end() const override;
1080 
1081   bool is64Bit() const override { return false; }
1082 
1083   const coff_section *getCOFFSection(const SectionRef &Section) const;
1084   COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
1085   COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
1086   const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
1087   unsigned getSectionID(SectionRef Sec) const;
1088   unsigned getSymbolSectionID(SymbolRef Sym) const;
1089 
1090   uint8_t getBytesInAddress() const override;
1091   StringRef getFileFormatName() const override;
1092   Triple::ArchType getArch() const override;
1093   Expected<uint64_t> getStartAddress() const override;
1094   Expected<SubtargetFeatures> getFeatures() const override {
1095     return SubtargetFeatures();
1096   }
1097   std::unique_ptr<MemoryBuffer> getHybridObjectView() const;
1098 
1099   import_directory_iterator import_directory_begin() const;
1100   import_directory_iterator import_directory_end() const;
1101   delay_import_directory_iterator delay_import_directory_begin() const;
1102   delay_import_directory_iterator delay_import_directory_end() const;
1103   export_directory_iterator export_directory_begin() const;
1104   export_directory_iterator export_directory_end() const;
1105   base_reloc_iterator base_reloc_begin() const;
1106   base_reloc_iterator base_reloc_end() const;
1107   dynamic_reloc_iterator dynamic_reloc_begin() const;
1108   dynamic_reloc_iterator dynamic_reloc_end() const;
1109   const debug_directory *debug_directory_begin() const {
1110     return DebugDirectoryBegin;
1111   }
1112   const debug_directory *debug_directory_end() const {
1113     return DebugDirectoryEnd;
1114   }
1115 
1116   iterator_range<import_directory_iterator> import_directories() const;
1117   iterator_range<delay_import_directory_iterator>
1118       delay_import_directories() const;
1119   iterator_range<export_directory_iterator> export_directories() const;
1120   iterator_range<base_reloc_iterator> base_relocs() const;
1121   iterator_range<dynamic_reloc_iterator> dynamic_relocs() const;
1122   iterator_range<const debug_directory *> debug_directories() const {
1123     return make_range(debug_directory_begin(), debug_directory_end());
1124   }
1125 
1126   const coff_tls_directory32 *getTLSDirectory32() const {
1127     return TLSDirectory32;
1128   }
1129   const coff_tls_directory64 *getTLSDirectory64() const {
1130     return TLSDirectory64;
1131   }
1132 
1133   const dos_header *getDOSHeader() const {
1134     if (!PE32Header && !PE32PlusHeader)
1135       return nullptr;
1136     return reinterpret_cast<const dos_header *>(base());
1137   }
1138 
1139   const coff_file_header *getCOFFHeader() const { return COFFHeader; }
1140   const coff_bigobj_file_header *getCOFFBigObjHeader() const {
1141     return COFFBigObjHeader;
1142   }
1143   const pe32_header *getPE32Header() const { return PE32Header; }
1144   const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; }
1145 
1146   const data_directory *getDataDirectory(uint32_t index) const;
1147   Expected<const coff_section *> getSection(int32_t index) const;
1148 
1149   Expected<COFFSymbolRef> getSymbol(uint32_t index) const {
1150     if (index >= getNumberOfSymbols())
1151       return errorCodeToError(object_error::parse_failed);
1152     if (SymbolTable16)
1153       return COFFSymbolRef(SymbolTable16 + index);
1154     if (SymbolTable32)
1155       return COFFSymbolRef(SymbolTable32 + index);
1156     return errorCodeToError(object_error::parse_failed);
1157   }
1158 
1159   template <typename T>
1160   Error getAuxSymbol(uint32_t index, const T *&Res) const {
1161     Expected<COFFSymbolRef> S = getSymbol(index);
1162     if (Error E = S.takeError())
1163       return E;
1164     Res = reinterpret_cast<const T *>(S->getRawPtr());
1165     return Error::success();
1166   }
1167 
1168   Expected<StringRef> getSymbolName(COFFSymbolRef Symbol) const;
1169   Expected<StringRef> getSymbolName(const coff_symbol_generic *Symbol) const;
1170 
1171   ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
1172 
1173   uint32_t getSymbolIndex(COFFSymbolRef Symbol) const;
1174 
1175   size_t getSymbolTableEntrySize() const {
1176     if (COFFHeader)
1177       return sizeof(coff_symbol16);
1178     if (COFFBigObjHeader)
1179       return sizeof(coff_symbol32);
1180     llvm_unreachable("null symbol table pointer!");
1181   }
1182 
1183   ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const;
1184 
1185   Expected<StringRef> getSectionName(const coff_section *Sec) const;
1186   uint64_t getSectionSize(const coff_section *Sec) const;
1187   Error getSectionContents(const coff_section *Sec,
1188                            ArrayRef<uint8_t> &Res) const;
1189 
1190   uint64_t getImageBase() const;
1191   Error getVaPtr(uint64_t VA, uintptr_t &Res) const;
1192   Error getRvaPtr(uint32_t Rva, uintptr_t &Res,
1193                   const char *ErrorContext = nullptr) const;
1194 
1195   /// Given an RVA base and size, returns a valid array of bytes or an error
1196   /// code if the RVA and size is not contained completely within a valid
1197   /// section.
1198   Error getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
1199                              ArrayRef<uint8_t> &Contents,
1200                              const char *ErrorContext = nullptr) const;
1201 
1202   Error getHintName(uint32_t Rva, uint16_t &Hint,
1203                               StringRef &Name) const;
1204 
1205   /// Get PDB information out of a codeview debug directory entry.
1206   Error getDebugPDBInfo(const debug_directory *DebugDir,
1207                         const codeview::DebugInfo *&Info,
1208                         StringRef &PDBFileName) const;
1209 
1210   /// Get PDB information from an executable. If the information is not present,
1211   /// Info will be set to nullptr and PDBFileName will be empty. An error is
1212   /// returned only on corrupt object files. Convenience accessor that can be
1213   /// used if the debug directory is not already handy.
1214   Error getDebugPDBInfo(const codeview::DebugInfo *&Info,
1215                         StringRef &PDBFileName) const;
1216 
1217   bool isRelocatableObject() const override;
1218   bool is64() const { return PE32PlusHeader; }
1219 
1220   StringRef mapDebugSectionName(StringRef Name) const override;
1221 
1222   static bool classof(const Binary *v) { return v->isCOFF(); }
1223 };
1224 
1225 // The iterator for the import directory table.
1226 class ImportDirectoryEntryRef {
1227 public:
1228   ImportDirectoryEntryRef() = default;
1229   ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table,
1230                           uint32_t I, const COFFObjectFile *Owner)
1231       : ImportTable(Table), Index(I), OwningObject(Owner) {}
1232 
1233   bool operator==(const ImportDirectoryEntryRef &Other) const;
1234   void moveNext();
1235 
1236   imported_symbol_iterator imported_symbol_begin() const;
1237   imported_symbol_iterator imported_symbol_end() const;
1238   iterator_range<imported_symbol_iterator> imported_symbols() const;
1239 
1240   imported_symbol_iterator lookup_table_begin() const;
1241   imported_symbol_iterator lookup_table_end() const;
1242   iterator_range<imported_symbol_iterator> lookup_table_symbols() const;
1243 
1244   Error getName(StringRef &Result) const;
1245   Error getImportLookupTableRVA(uint32_t &Result) const;
1246   Error getImportAddressTableRVA(uint32_t &Result) const;
1247 
1248   Error
1249   getImportTableEntry(const coff_import_directory_table_entry *&Result) const;
1250 
1251 private:
1252   const coff_import_directory_table_entry *ImportTable;
1253   uint32_t Index;
1254   const COFFObjectFile *OwningObject = nullptr;
1255 };
1256 
1257 class DelayImportDirectoryEntryRef {
1258 public:
1259   DelayImportDirectoryEntryRef() = default;
1260   DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
1261                                uint32_t I, const COFFObjectFile *Owner)
1262       : Table(T), Index(I), OwningObject(Owner) {}
1263 
1264   bool operator==(const DelayImportDirectoryEntryRef &Other) const;
1265   void moveNext();
1266 
1267   imported_symbol_iterator imported_symbol_begin() const;
1268   imported_symbol_iterator imported_symbol_end() const;
1269   iterator_range<imported_symbol_iterator> imported_symbols() const;
1270 
1271   Error getName(StringRef &Result) const;
1272   Error getDelayImportTable(
1273       const delay_import_directory_table_entry *&Result) const;
1274   Error getImportAddress(int AddrIndex, uint64_t &Result) const;
1275 
1276 private:
1277   const delay_import_directory_table_entry *Table;
1278   uint32_t Index;
1279   const COFFObjectFile *OwningObject = nullptr;
1280 };
1281 
1282 // The iterator for the export directory table entry.
1283 class ExportDirectoryEntryRef {
1284 public:
1285   ExportDirectoryEntryRef() = default;
1286   ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
1287                           const COFFObjectFile *Owner)
1288       : ExportTable(Table), Index(I), OwningObject(Owner) {}
1289 
1290   bool operator==(const ExportDirectoryEntryRef &Other) const;
1291   void moveNext();
1292 
1293   Error getDllName(StringRef &Result) const;
1294   Error getOrdinalBase(uint32_t &Result) const;
1295   Error getOrdinal(uint32_t &Result) const;
1296   Error getExportRVA(uint32_t &Result) const;
1297   Error getSymbolName(StringRef &Result) const;
1298 
1299   Error isForwarder(bool &Result) const;
1300   Error getForwardTo(StringRef &Result) const;
1301 
1302 private:
1303   const export_directory_table_entry *ExportTable;
1304   uint32_t Index;
1305   const COFFObjectFile *OwningObject = nullptr;
1306 };
1307 
1308 class ImportedSymbolRef {
1309 public:
1310   ImportedSymbolRef() = default;
1311   ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
1312                     const COFFObjectFile *Owner)
1313       : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
1314   ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
1315                     const COFFObjectFile *Owner)
1316       : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}
1317 
1318   bool operator==(const ImportedSymbolRef &Other) const;
1319   void moveNext();
1320 
1321   Error getSymbolName(StringRef &Result) const;
1322   Error isOrdinal(bool &Result) const;
1323   Error getOrdinal(uint16_t &Result) const;
1324   Error getHintNameRVA(uint32_t &Result) const;
1325 
1326 private:
1327   const import_lookup_table_entry32 *Entry32;
1328   const import_lookup_table_entry64 *Entry64;
1329   uint32_t Index;
1330   const COFFObjectFile *OwningObject = nullptr;
1331 };
1332 
1333 class BaseRelocRef {
1334 public:
1335   BaseRelocRef() = default;
1336   BaseRelocRef(const coff_base_reloc_block_header *Header,
1337                const COFFObjectFile *Owner)
1338       : Header(Header), Index(0) {}
1339 
1340   bool operator==(const BaseRelocRef &Other) const;
1341   void moveNext();
1342 
1343   Error getType(uint8_t &Type) const;
1344   Error getRVA(uint32_t &Result) const;
1345 
1346 private:
1347   const coff_base_reloc_block_header *Header;
1348   uint32_t Index;
1349 };
1350 
1351 class DynamicRelocRef {
1352 public:
1353   DynamicRelocRef() = default;
1354   DynamicRelocRef(const void *Header, const COFFObjectFile *Owner)
1355       : Obj(Owner), Header(reinterpret_cast<const uint8_t *>(Header)) {}
1356 
1357   bool operator==(const DynamicRelocRef &Other) const;
1358   void moveNext();
1359   uint32_t getType() const;
1360   void getContents(ArrayRef<uint8_t> &Ref) const;
1361 
1362   arm64x_reloc_iterator arm64x_reloc_begin() const;
1363   arm64x_reloc_iterator arm64x_reloc_end() const;
1364   iterator_range<arm64x_reloc_iterator> arm64x_relocs() const;
1365 
1366 private:
1367   Error validate() const;
1368 
1369   const COFFObjectFile *Obj;
1370   const uint8_t *Header;
1371 
1372   friend class COFFObjectFile;
1373 };
1374 
1375 class Arm64XRelocRef {
1376 public:
1377   Arm64XRelocRef() = default;
1378   Arm64XRelocRef(const coff_base_reloc_block_header *Header, uint32_t Index = 0)
1379       : Header(Header), Index(Index) {}
1380 
1381   bool operator==(const Arm64XRelocRef &Other) const;
1382   void moveNext();
1383 
1384   COFF::Arm64XFixupType getType() const {
1385     return COFF::Arm64XFixupType((getReloc() >> 12) & 3);
1386   }
1387   uint32_t getRVA() const { return Header->PageRVA + (getReloc() & 0xfff); }
1388   uint8_t getSize() const;
1389   uint64_t getValue() const;
1390 
1391 private:
1392   const support::ulittle16_t &getReloc(uint32_t Offset = 0) const {
1393     return reinterpret_cast<const support::ulittle16_t *>(Header +
1394                                                           1)[Index + Offset];
1395   }
1396 
1397   uint16_t getArg() const { return getReloc() >> 14; }
1398   uint8_t getEntrySize() const;
1399   Error validate(const COFFObjectFile *Obj) const;
1400 
1401   const coff_base_reloc_block_header *Header;
1402   uint32_t Index;
1403 
1404   friend class DynamicRelocRef;
1405 };
1406 
1407 class ResourceSectionRef {
1408 public:
1409   ResourceSectionRef() = default;
1410   explicit ResourceSectionRef(StringRef Ref)
1411       : BBS(Ref, llvm::endianness::little) {}
1412 
1413   Error load(const COFFObjectFile *O);
1414   Error load(const COFFObjectFile *O, const SectionRef &S);
1415 
1416   Expected<ArrayRef<UTF16>>
1417   getEntryNameString(const coff_resource_dir_entry &Entry);
1418   Expected<const coff_resource_dir_table &>
1419   getEntrySubDir(const coff_resource_dir_entry &Entry);
1420   Expected<const coff_resource_data_entry &>
1421   getEntryData(const coff_resource_dir_entry &Entry);
1422   Expected<const coff_resource_dir_table &> getBaseTable();
1423   Expected<const coff_resource_dir_entry &>
1424   getTableEntry(const coff_resource_dir_table &Table, uint32_t Index);
1425 
1426   Expected<StringRef> getContents(const coff_resource_data_entry &Entry);
1427 
1428 private:
1429   BinaryByteStream BBS;
1430 
1431   SectionRef Section;
1432   const COFFObjectFile *Obj = nullptr;
1433 
1434   std::vector<const coff_relocation *> Relocs;
1435 
1436   Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
1437   Expected<const coff_resource_dir_entry &>
1438   getTableEntryAtOffset(uint32_t Offset);
1439   Expected<const coff_resource_data_entry &>
1440   getDataEntryAtOffset(uint32_t Offset);
1441   Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
1442 };
1443 
1444 // Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
1445 struct FpoData {
1446   support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
1447   support::ulittle32_t Size;   // cbProcSize: # bytes in function
1448   support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
1449   support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
1450   support::ulittle16_t Attributes;
1451 
1452   // cbProlog: # bytes in prolog
1453   int getPrologSize() const { return Attributes & 0xF; }
1454 
1455   // cbRegs: # regs saved
1456   int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
1457 
1458   // fHasSEH: true if seh is func
1459   bool hasSEH() const { return (Attributes >> 9) & 1; }
1460 
1461   // fUseBP: true if EBP has been allocated
1462   bool useBP() const { return (Attributes >> 10) & 1; }
1463 
1464   // cbFrame: frame pointer
1465   frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); }
1466 };
1467 
1468 class SectionStrippedError
1469     : public ErrorInfo<SectionStrippedError, BinaryError> {
1470 public:
1471   SectionStrippedError() { setErrorCode(object_error::section_stripped); }
1472 };
1473 
1474 } // end namespace object
1475 
1476 } // end namespace llvm
1477 
1478 #endif // LLVM_OBJECT_COFF_H