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/Object/ObjectFile.h"
     18 #include "llvm/Support/COFF.h"
     19 #include "llvm/Support/Endian.h"
     20 
     21 namespace llvm {
     22 template <typename T> class ArrayRef;
     23 
     24 namespace object {
     25 class ImportDirectoryEntryRef;
     26 class ExportDirectoryEntryRef;
     27 typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
     28 typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
     29 
     30 /// The DOS compatible header at the front of all PE/COFF executables.
     31 struct dos_header {
     32   support::ulittle16_t Magic;
     33   support::ulittle16_t UsedBytesInTheLastPage;
     34   support::ulittle16_t FileSizeInPages;
     35   support::ulittle16_t NumberOfRelocationItems;
     36   support::ulittle16_t HeaderSizeInParagraphs;
     37   support::ulittle16_t MinimumExtraParagraphs;
     38   support::ulittle16_t MaximumExtraParagraphs;
     39   support::ulittle16_t InitialRelativeSS;
     40   support::ulittle16_t InitialSP;
     41   support::ulittle16_t Checksum;
     42   support::ulittle16_t InitialIP;
     43   support::ulittle16_t InitialRelativeCS;
     44   support::ulittle16_t AddressOfRelocationTable;
     45   support::ulittle16_t OverlayNumber;
     46   support::ulittle16_t Reserved[4];
     47   support::ulittle16_t OEMid;
     48   support::ulittle16_t OEMinfo;
     49   support::ulittle16_t Reserved2[10];
     50   support::ulittle32_t AddressOfNewExeHeader;
     51 };
     52 
     53 struct coff_file_header {
     54   support::ulittle16_t Machine;
     55   support::ulittle16_t NumberOfSections;
     56   support::ulittle32_t TimeDateStamp;
     57   support::ulittle32_t PointerToSymbolTable;
     58   support::ulittle32_t NumberOfSymbols;
     59   support::ulittle16_t SizeOfOptionalHeader;
     60   support::ulittle16_t Characteristics;
     61 
     62   bool isImportLibrary() const { return NumberOfSections == 0xffff; }
     63 };
     64 
     65 /// The 32-bit PE header that follows the COFF header.
     66 struct pe32_header {
     67   support::ulittle16_t Magic;
     68   uint8_t MajorLinkerVersion;
     69   uint8_t MinorLinkerVersion;
     70   support::ulittle32_t SizeOfCode;
     71   support::ulittle32_t SizeOfInitializedData;
     72   support::ulittle32_t SizeOfUninitializedData;
     73   support::ulittle32_t AddressOfEntryPoint;
     74   support::ulittle32_t BaseOfCode;
     75   support::ulittle32_t BaseOfData;
     76   support::ulittle32_t ImageBase;
     77   support::ulittle32_t SectionAlignment;
     78   support::ulittle32_t FileAlignment;
     79   support::ulittle16_t MajorOperatingSystemVersion;
     80   support::ulittle16_t MinorOperatingSystemVersion;
     81   support::ulittle16_t MajorImageVersion;
     82   support::ulittle16_t MinorImageVersion;
     83   support::ulittle16_t MajorSubsystemVersion;
     84   support::ulittle16_t MinorSubsystemVersion;
     85   support::ulittle32_t Win32VersionValue;
     86   support::ulittle32_t SizeOfImage;
     87   support::ulittle32_t SizeOfHeaders;
     88   support::ulittle32_t CheckSum;
     89   support::ulittle16_t Subsystem;
     90   support::ulittle16_t DLLCharacteristics;
     91   support::ulittle32_t SizeOfStackReserve;
     92   support::ulittle32_t SizeOfStackCommit;
     93   support::ulittle32_t SizeOfHeapReserve;
     94   support::ulittle32_t SizeOfHeapCommit;
     95   support::ulittle32_t LoaderFlags;
     96   support::ulittle32_t NumberOfRvaAndSize;
     97 };
     98 
     99 /// The 64-bit PE header that follows the COFF header.
    100 struct pe32plus_header {
    101   support::ulittle16_t Magic;
    102   uint8_t MajorLinkerVersion;
    103   uint8_t MinorLinkerVersion;
    104   support::ulittle32_t SizeOfCode;
    105   support::ulittle32_t SizeOfInitializedData;
    106   support::ulittle32_t SizeOfUninitializedData;
    107   support::ulittle32_t AddressOfEntryPoint;
    108   support::ulittle32_t BaseOfCode;
    109   support::ulittle64_t ImageBase;
    110   support::ulittle32_t SectionAlignment;
    111   support::ulittle32_t FileAlignment;
    112   support::ulittle16_t MajorOperatingSystemVersion;
    113   support::ulittle16_t MinorOperatingSystemVersion;
    114   support::ulittle16_t MajorImageVersion;
    115   support::ulittle16_t MinorImageVersion;
    116   support::ulittle16_t MajorSubsystemVersion;
    117   support::ulittle16_t MinorSubsystemVersion;
    118   support::ulittle32_t Win32VersionValue;
    119   support::ulittle32_t SizeOfImage;
    120   support::ulittle32_t SizeOfHeaders;
    121   support::ulittle32_t CheckSum;
    122   support::ulittle16_t Subsystem;
    123   support::ulittle16_t DLLCharacteristics;
    124   support::ulittle64_t SizeOfStackReserve;
    125   support::ulittle64_t SizeOfStackCommit;
    126   support::ulittle64_t SizeOfHeapReserve;
    127   support::ulittle64_t SizeOfHeapCommit;
    128   support::ulittle32_t LoaderFlags;
    129   support::ulittle32_t NumberOfRvaAndSize;
    130 };
    131 
    132 struct data_directory {
    133   support::ulittle32_t RelativeVirtualAddress;
    134   support::ulittle32_t Size;
    135 };
    136 
    137 struct import_directory_table_entry {
    138   support::ulittle32_t ImportLookupTableRVA;
    139   support::ulittle32_t TimeDateStamp;
    140   support::ulittle32_t ForwarderChain;
    141   support::ulittle32_t NameRVA;
    142   support::ulittle32_t ImportAddressTableRVA;
    143 };
    144 
    145 struct import_lookup_table_entry32 {
    146   support::ulittle32_t data;
    147 
    148   bool isOrdinal() const { return data & 0x80000000; }
    149 
    150   uint16_t getOrdinal() const {
    151     assert(isOrdinal() && "ILT entry is not an ordinal!");
    152     return data & 0xFFFF;
    153   }
    154 
    155   uint32_t getHintNameRVA() const {
    156     assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
    157     return data;
    158   }
    159 };
    160 
    161 struct export_directory_table_entry {
    162   support::ulittle32_t ExportFlags;
    163   support::ulittle32_t TimeDateStamp;
    164   support::ulittle16_t MajorVersion;
    165   support::ulittle16_t MinorVersion;
    166   support::ulittle32_t NameRVA;
    167   support::ulittle32_t OrdinalBase;
    168   support::ulittle32_t AddressTableEntries;
    169   support::ulittle32_t NumberOfNamePointers;
    170   support::ulittle32_t ExportAddressTableRVA;
    171   support::ulittle32_t NamePointerRVA;
    172   support::ulittle32_t OrdinalTableRVA;
    173 };
    174 
    175 union export_address_table_entry {
    176   support::ulittle32_t ExportRVA;
    177   support::ulittle32_t ForwarderRVA;
    178 };
    179 
    180 typedef support::ulittle32_t export_name_pointer_table_entry;
    181 typedef support::ulittle16_t export_ordinal_table_entry;
    182 
    183 struct coff_symbol {
    184   struct StringTableOffset {
    185     support::ulittle32_t Zeroes;
    186     support::ulittle32_t Offset;
    187   };
    188 
    189   union {
    190     char ShortName[8];
    191     StringTableOffset Offset;
    192   } Name;
    193 
    194   support::ulittle32_t Value;
    195   support::ulittle16_t SectionNumber;
    196 
    197   support::ulittle16_t Type;
    198 
    199   support::ulittle8_t StorageClass;
    200   support::ulittle8_t NumberOfAuxSymbols;
    201 
    202   uint8_t getBaseType() const { return Type & 0x0F; }
    203 
    204   uint8_t getComplexType() const { return (Type & 0xF0) >> 4; }
    205 
    206   bool isFunctionDefinition() const {
    207     return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
    208            getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
    209            getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
    210            !COFF::isReservedSectionNumber(SectionNumber);
    211   }
    212 
    213   bool isFunctionLineInfo() const {
    214     return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION;
    215   }
    216 
    217   bool isWeakExternal() const {
    218     return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
    219            (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
    220             SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0);
    221   }
    222 
    223   bool isFileRecord() const {
    224     return StorageClass == COFF::IMAGE_SYM_CLASS_FILE;
    225   }
    226 
    227   bool isSectionDefinition() const {
    228     // C++/CLI creates external ABS symbols for non-const appdomain globals.
    229     // These are also followed by an auxiliary section definition.
    230     bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
    231                              SectionNumber == COFF::IMAGE_SYM_ABSOLUTE;
    232     bool isOrdinarySection =
    233         StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0;
    234     return isAppdomainGlobal || isOrdinarySection;
    235   }
    236 
    237   bool isCLRToken() const {
    238     return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
    239   }
    240 };
    241 
    242 struct coff_section {
    243   char Name[8];
    244   support::ulittle32_t VirtualSize;
    245   support::ulittle32_t VirtualAddress;
    246   support::ulittle32_t SizeOfRawData;
    247   support::ulittle32_t PointerToRawData;
    248   support::ulittle32_t PointerToRelocations;
    249   support::ulittle32_t PointerToLinenumbers;
    250   support::ulittle16_t NumberOfRelocations;
    251   support::ulittle16_t NumberOfLinenumbers;
    252   support::ulittle32_t Characteristics;
    253 
    254   // Returns true if the actual number of relocations is stored in
    255   // VirtualAddress field of the first relocation table entry.
    256   bool hasExtendedRelocations() const {
    257     return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL &&
    258         NumberOfRelocations == UINT16_MAX;
    259   };
    260 };
    261 
    262 struct coff_relocation {
    263   support::ulittle32_t VirtualAddress;
    264   support::ulittle32_t SymbolTableIndex;
    265   support::ulittle16_t Type;
    266 };
    267 
    268 struct coff_aux_function_definition {
    269   support::ulittle32_t TagIndex;
    270   support::ulittle32_t TotalSize;
    271   support::ulittle32_t PointerToLinenumber;
    272   support::ulittle32_t PointerToNextFunction;
    273   char Unused[2];
    274 };
    275 
    276 struct coff_aux_bf_and_ef_symbol {
    277   char Unused1[4];
    278   support::ulittle16_t Linenumber;
    279   char Unused2[6];
    280   support::ulittle32_t PointerToNextFunction;
    281   char Unused3[2];
    282 };
    283 
    284 struct coff_aux_weak_external {
    285   support::ulittle32_t TagIndex;
    286   support::ulittle32_t Characteristics;
    287   char Unused[10];
    288 };
    289 
    290 struct coff_aux_file {
    291   char FileName[18];
    292 };
    293 
    294 struct coff_aux_section_definition {
    295   support::ulittle32_t Length;
    296   support::ulittle16_t NumberOfRelocations;
    297   support::ulittle16_t NumberOfLinenumbers;
    298   support::ulittle32_t CheckSum;
    299   support::ulittle16_t Number;
    300   support::ulittle8_t Selection;
    301   char Unused[3];
    302 };
    303 
    304 struct coff_aux_clr_token {
    305   support::ulittle8_t AuxType;
    306   support::ulittle8_t Reserved;
    307   support::ulittle32_t SymbolTableIndex;
    308   char Unused[12];
    309 };
    310 
    311 struct coff_load_configuration32 {
    312   support::ulittle32_t Characteristics;
    313   support::ulittle32_t TimeDateStamp;
    314   support::ulittle16_t MajorVersion;
    315   support::ulittle16_t MinorVersion;
    316   support::ulittle32_t GlobalFlagsClear;
    317   support::ulittle32_t GlobalFlagsSet;
    318   support::ulittle32_t CriticalSectionDefaultTimeout;
    319   support::ulittle32_t DeCommitFreeBlockThreshold;
    320   support::ulittle32_t DeCommitTotalFreeThreshold;
    321   support::ulittle32_t LockPrefixTable;
    322   support::ulittle32_t MaximumAllocationSize;
    323   support::ulittle32_t VirtualMemoryThreshold;
    324   support::ulittle32_t ProcessAffinityMask;
    325   support::ulittle32_t ProcessHeapFlags;
    326   support::ulittle16_t CSDVersion;
    327   uint16_t Reserved;
    328   support::ulittle32_t EditList;
    329   support::ulittle32_t SecurityCookie;
    330   support::ulittle32_t SEHandlerTable;
    331   support::ulittle32_t SEHandlerCount;
    332 };
    333 
    334 struct coff_runtime_function_x64 {
    335   support::ulittle32_t BeginAddress;
    336   support::ulittle32_t EndAddress;
    337   support::ulittle32_t UnwindInformation;
    338 };
    339 
    340 class COFFObjectFile : public ObjectFile {
    341 private:
    342   friend class ImportDirectoryEntryRef;
    343   friend class ExportDirectoryEntryRef;
    344   const coff_file_header *COFFHeader;
    345   const pe32_header *PE32Header;
    346   const pe32plus_header *PE32PlusHeader;
    347   const data_directory *DataDirectory;
    348   const coff_section *SectionTable;
    349   const coff_symbol *SymbolTable;
    350   const char *StringTable;
    351   uint32_t StringTableSize;
    352   const import_directory_table_entry *ImportDirectory;
    353   uint32_t NumberOfImportDirectory;
    354   const export_directory_table_entry *ExportDirectory;
    355 
    356   std::error_code getString(uint32_t offset, StringRef &Res) const;
    357 
    358   const coff_symbol *toSymb(DataRefImpl Symb) const;
    359   const coff_section *toSec(DataRefImpl Sec) const;
    360   const coff_relocation *toRel(DataRefImpl Rel) const;
    361 
    362   std::error_code initSymbolTablePtr();
    363   std::error_code initImportTablePtr();
    364   std::error_code initExportTablePtr();
    365 
    366 protected:
    367   void moveSymbolNext(DataRefImpl &Symb) const override;
    368   std::error_code getSymbolName(DataRefImpl Symb,
    369                                 StringRef &Res) const override;
    370   std::error_code getSymbolAddress(DataRefImpl Symb,
    371                                    uint64_t &Res) const override;
    372   std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
    373   uint32_t getSymbolFlags(DataRefImpl Symb) const override;
    374   std::error_code getSymbolType(DataRefImpl Symb,
    375                                 SymbolRef::Type &Res) const override;
    376   std::error_code getSymbolSection(DataRefImpl Symb,
    377                                    section_iterator &Res) const override;
    378   void moveSectionNext(DataRefImpl &Sec) const override;
    379   std::error_code getSectionName(DataRefImpl Sec,
    380                                  StringRef &Res) const override;
    381   std::error_code getSectionAddress(DataRefImpl Sec,
    382                                     uint64_t &Res) const override;
    383   std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override;
    384   std::error_code getSectionContents(DataRefImpl Sec,
    385                                      StringRef &Res) const override;
    386   std::error_code getSectionAlignment(DataRefImpl Sec,
    387                                       uint64_t &Res) const override;
    388   std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override;
    389   std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override;
    390   std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override;
    391   std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override;
    392   std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override;
    393   std::error_code isSectionReadOnlyData(DataRefImpl Sec,
    394                                         bool &Res) const override;
    395   std::error_code isSectionRequiredForExecution(DataRefImpl Sec,
    396                                                 bool &Res) const override;
    397   std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
    398                                         bool &Result) const override;
    399   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
    400   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
    401 
    402   void moveRelocationNext(DataRefImpl &Rel) const override;
    403   std::error_code getRelocationAddress(DataRefImpl Rel,
    404                                        uint64_t &Res) const override;
    405   std::error_code getRelocationOffset(DataRefImpl Rel,
    406                                       uint64_t &Res) const override;
    407   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
    408   std::error_code getRelocationType(DataRefImpl Rel,
    409                                     uint64_t &Res) const override;
    410   std::error_code
    411   getRelocationTypeName(DataRefImpl Rel,
    412                         SmallVectorImpl<char> &Result) const override;
    413   std::error_code
    414   getRelocationValueString(DataRefImpl Rel,
    415                            SmallVectorImpl<char> &Result) const override;
    416 
    417   std::error_code getLibraryNext(DataRefImpl LibData,
    418                                  LibraryRef &Result) const override;
    419   std::error_code getLibraryPath(DataRefImpl LibData,
    420                                  StringRef &Result) const override;
    421 
    422 public:
    423   COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC);
    424   basic_symbol_iterator symbol_begin_impl() const override;
    425   basic_symbol_iterator symbol_end_impl() const override;
    426   library_iterator needed_library_begin() const override;
    427   library_iterator needed_library_end() const override;
    428   section_iterator section_begin() const override;
    429   section_iterator section_end() const override;
    430 
    431   const coff_section *getCOFFSection(const SectionRef &Section) const;
    432   const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const;
    433   const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
    434 
    435   uint8_t getBytesInAddress() const override;
    436   StringRef getFileFormatName() const override;
    437   unsigned getArch() const override;
    438   StringRef getLoadName() const override;
    439 
    440   import_directory_iterator import_directory_begin() const;
    441   import_directory_iterator import_directory_end() const;
    442   export_directory_iterator export_directory_begin() const;
    443   export_directory_iterator export_directory_end() const;
    444 
    445   std::error_code getHeader(const coff_file_header *&Res) const;
    446   std::error_code getCOFFHeader(const coff_file_header *&Res) const;
    447   std::error_code getPE32Header(const pe32_header *&Res) const;
    448   std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
    449   std::error_code getDataDirectory(uint32_t index,
    450                                    const data_directory *&Res) const;
    451   std::error_code getSection(int32_t index, const coff_section *&Res) const;
    452   std::error_code getSymbol(uint32_t index, const coff_symbol *&Res) const;
    453   template <typename T>
    454   std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
    455     const coff_symbol *s;
    456     std::error_code ec = getSymbol(index, s);
    457     Res = reinterpret_cast<const T *>(s);
    458     return ec;
    459   }
    460   std::error_code getSymbolName(const coff_symbol *symbol,
    461                                 StringRef &Res) const;
    462   ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const;
    463 
    464   std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
    465   std::error_code getSectionContents(const coff_section *Sec,
    466                                      ArrayRef<uint8_t> &Res) const;
    467 
    468   std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
    469   std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
    470   std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
    471                               StringRef &Name) const;
    472 
    473   static inline bool classof(const Binary *v) { return v->isCOFF(); }
    474 };
    475 
    476 // The iterator for the import directory table.
    477 class ImportDirectoryEntryRef {
    478 public:
    479   ImportDirectoryEntryRef() : OwningObject(nullptr) {}
    480   ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I,
    481                           const COFFObjectFile *Owner)
    482       : ImportTable(Table), Index(I), OwningObject(Owner) {}
    483 
    484   bool operator==(const ImportDirectoryEntryRef &Other) const;
    485   void moveNext();
    486   std::error_code getName(StringRef &Result) const;
    487 
    488   std::error_code
    489   getImportTableEntry(const import_directory_table_entry *&Result) const;
    490 
    491   std::error_code
    492   getImportLookupEntry(const import_lookup_table_entry32 *&Result) const;
    493 
    494 private:
    495   const import_directory_table_entry *ImportTable;
    496   uint32_t Index;
    497   const COFFObjectFile *OwningObject;
    498 };
    499 
    500 // The iterator for the export directory table entry.
    501 class ExportDirectoryEntryRef {
    502 public:
    503   ExportDirectoryEntryRef() : OwningObject(nullptr) {}
    504   ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
    505                           const COFFObjectFile *Owner)
    506       : ExportTable(Table), Index(I), OwningObject(Owner) {}
    507 
    508   bool operator==(const ExportDirectoryEntryRef &Other) const;
    509   void moveNext();
    510 
    511   std::error_code getDllName(StringRef &Result) const;
    512   std::error_code getOrdinalBase(uint32_t &Result) const;
    513   std::error_code getOrdinal(uint32_t &Result) const;
    514   std::error_code getExportRVA(uint32_t &Result) const;
    515   std::error_code getSymbolName(StringRef &Result) const;
    516 
    517 private:
    518   const export_directory_table_entry *ExportTable;
    519   uint32_t Index;
    520   const COFFObjectFile *OwningObject;
    521 };
    522 } // end namespace object
    523 } // end namespace llvm
    524 
    525 #endif
    526