diff options
Diffstat (limited to 'include/llvm/Object/COFF.h')
-rw-r--r-- | include/llvm/Object/COFF.h | 142 |
1 files changed, 134 insertions, 8 deletions
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 3e69c3e6e5d4f..dcc58b06e228d 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -169,6 +169,26 @@ struct import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; +struct debug_directory { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t Type; + support::ulittle32_t SizeOfData; + support::ulittle32_t AddressOfRawData; + support::ulittle32_t PointerToRawData; +}; + +/// Information that is resent in debug_directory::AddressOfRawData if Type is +/// IMAGE_DEBUG_TYPE_CODEVIEW. +struct debug_pdb_info { + support::ulittle32_t Signature; + uint8_t Guid[16]; + support::ulittle32_t Age; + // PDBFileName: The null-terminated PDB file name follows. +}; + template <typename IntTy> struct import_lookup_table_entry { IntTy Data; @@ -414,6 +434,18 @@ struct coff_section { return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && NumberOfRelocations == UINT16_MAX; } + uint32_t getAlignment() const { + // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to + // IMAGE_SCN_ALIGN_1BYTES. + if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) + return 1; + + // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1. + uint32_t Shift = (Characteristics >> 20) & 0xF; + if (Shift > 0) + return 1U << (Shift - 1); + return 1; + } }; struct coff_relocation { @@ -427,20 +459,32 @@ struct coff_aux_function_definition { support::ulittle32_t TotalSize; support::ulittle32_t PointerToLinenumber; support::ulittle32_t PointerToNextFunction; + char Unused1[2]; }; +static_assert(sizeof(coff_aux_function_definition) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_bf_and_ef_symbol { char Unused1[4]; support::ulittle16_t Linenumber; char Unused2[6]; support::ulittle32_t PointerToNextFunction; + char Unused3[2]; }; +static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_weak_external { support::ulittle32_t TagIndex; support::ulittle32_t Characteristics; + char Unused1[10]; }; +static_assert(sizeof(coff_aux_weak_external) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_section_definition { support::ulittle32_t Length; support::ulittle16_t NumberOfRelocations; @@ -458,12 +502,19 @@ struct coff_aux_section_definition { } }; +static_assert(sizeof(coff_aux_section_definition) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_clr_token { uint8_t AuxType; uint8_t Reserved; support::ulittle32_t SymbolTableIndex; + char MBZ[12]; }; +static_assert(sizeof(coff_aux_clr_token) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_import_header { support::ulittle16_t Sig1; support::ulittle16_t Sig2; @@ -485,6 +536,26 @@ struct coff_import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; +template <typename IntTy> +struct coff_tls_directory { + IntTy StartAddressOfRawData; + IntTy EndAddressOfRawData; + IntTy AddressOfIndex; + IntTy AddressOfCallBacks; + support::ulittle32_t SizeOfZeroFill; + support::ulittle32_t Characteristics; + uint32_t getAlignment() const { + // Bit [20:24] contains section alignment. + uint32_t Shift = (Characteristics & 0x00F00000) >> 20; + if (Shift > 0) + return 1U << (Shift - 1); + return 0; + } +}; + +typedef coff_tls_directory<support::little32_t> coff_tls_directory32; +typedef coff_tls_directory<support::little64_t> coff_tls_directory64; + struct coff_load_configuration32 { support::ulittle32_t Characteristics; support::ulittle32_t TimeDateStamp; @@ -563,12 +634,13 @@ private: const char *StringTable; uint32_t StringTableSize; const import_directory_table_entry *ImportDirectory; - uint32_t NumberOfImportDirectory; const delay_import_directory_table_entry *DelayImportDirectory; uint32_t NumberOfDelayImportDirectory; const export_directory_table_entry *ExportDirectory; const coff_base_reloc_block_header *BaseRelocHeader; const coff_base_reloc_block_header *BaseRelocEnd; + const debug_directory *DebugDirectoryBegin; + const debug_directory *DebugDirectoryEnd; std::error_code getString(uint32_t offset, StringRef &Res) const; @@ -582,6 +654,7 @@ private: std::error_code initDelayImportTablePtr(); std::error_code initExportTablePtr(); std::error_code initBaseRelocPtr(); + std::error_code initDebugDirectoryPtr(); public: uintptr_t getSymbolTable() const { @@ -647,13 +720,13 @@ public: } protected: void moveSymbolNext(DataRefImpl &Symb) const override; - ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; - ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; - ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; @@ -662,6 +735,7 @@ protected: std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; @@ -693,6 +767,7 @@ public: uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; + SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; @@ -702,12 +777,21 @@ public: export_directory_iterator export_directory_end() const; base_reloc_iterator base_reloc_begin() const; base_reloc_iterator base_reloc_end() const; + const debug_directory *debug_directory_begin() const { + return DebugDirectoryBegin; + } + const debug_directory *debug_directory_end() const { + return DebugDirectoryEnd; + } iterator_range<import_directory_iterator> import_directories() const; iterator_range<delay_import_directory_iterator> delay_import_directories() const; iterator_range<export_directory_iterator> export_directories() const; iterator_range<base_reloc_iterator> base_relocs() const; + iterator_range<const debug_directory *> debug_directories() const { + return make_range(debug_directory_begin(), debug_directory_end()); + } const dos_header *getDOSHeader() const { if (!PE32Header && !PE32PlusHeader) @@ -776,9 +860,28 @@ public: uint64_t getImageBase() const; std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + + /// Given an RVA base and size, returns a valid array of bytes or an error + /// code if the RVA and size is not contained completely within a valid + /// section. + std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, + ArrayRef<uint8_t> &Contents) const; + std::error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + /// Get PDB information out of a codeview debug directory entry. + std::error_code getDebugPDBInfo(const debug_directory *DebugDir, + const debug_pdb_info *&Info, + StringRef &PDBFileName) const; + + /// Get PDB information from an executable. If the information is not present, + /// Info will be set to nullptr and PDBFileName will be empty. An error is + /// returned only on corrupt object files. Convenience accessor that can be + /// used if the debug directory is not already handy. + std::error_code getDebugPDBInfo(const debug_pdb_info *&Info, + StringRef &PDBFileName) const; + bool isRelocatableObject() const override; bool is64() const { return PE32PlusHeader; } @@ -807,9 +910,6 @@ public: std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; - std::error_code - getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; - private: const import_directory_table_entry *ImportTable; uint32_t Index; @@ -881,7 +981,9 @@ public: void moveNext(); std::error_code getSymbolName(StringRef &Result) const; + std::error_code isOrdinal(bool &Result) const; std::error_code getOrdinal(uint16_t &Result) const; + std::error_code getHintNameRVA(uint32_t &Result) const; private: const import_lookup_table_entry32 *Entry32; @@ -909,6 +1011,30 @@ private: const COFFObjectFile *OwningObject; }; +// Corresponds to `_FPO_DATA` structure in the PE/COFF spec. +struct FpoData { + support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code + support::ulittle32_t Size; // cbProcSize: # bytes in function + support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 + support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 + support::ulittle16_t Attributes; + + // cbProlog: # bytes in prolog + int getPrologSize() const { return Attributes & 0xF; } + + // cbRegs: # regs saved + int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } + + // fHasSEH: true if seh is func + bool hasSEH() const { return (Attributes >> 9) & 1; } + + // fUseBP: true if EBP has been allocated + bool useBP() const { return (Attributes >> 10) & 1; } + + // cbFrame: frame pointer + int getFP() const { return Attributes >> 14; } +}; + } // end namespace object } // end namespace llvm |