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