From 367f21dc721cc8cfd6c75b3a1cf6b28fbb482c04 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 22 Jun 2017 01:10:29 +0000 Subject: [PATCH] [llvm-readobj] Dump the COFF image load config This includes the safe SEH tables and the control flow guard function table. LLD will emit the guard table soon, and I need a tool that dumps them for testing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305979 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 100 +++++++++++-- lib/Object/COFFObjectFile.cpp | 20 +++ .../Inputs/coff-load-config-x64.dll | Bin 0 -> 9728 bytes .../Inputs/coff-load-config-x86.dll | Bin 0 -> 8704 bytes test/tools/llvm-readobj/coff-load-config.test | 87 ++++++++++++ tools/llvm-readobj/COFFDumper.cpp | 133 ++++++++++++++++++ tools/llvm-readobj/ObjDumper.h | 1 + tools/llvm-readobj/llvm-readobj.cpp | 7 + 8 files changed, 337 insertions(+), 11 deletions(-) create mode 100644 test/tools/llvm-readobj/Inputs/coff-load-config-x64.dll create mode 100644 test/tools/llvm-readobj/Inputs/coff-load-config-x86.dll create mode 100644 test/tools/llvm-readobj/coff-load-config.test diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index ae695a52959..bf0172822d3 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -562,8 +562,26 @@ struct coff_tls_directory { using coff_tls_directory32 = coff_tls_directory; using coff_tls_directory64 = coff_tls_directory; +/// Bits in control flow guard flags as we understand them. +enum class coff_guard_flags : uint32_t { + CFInstrumented = 0x00000100, + HasFidTable = 0x00000400, + ProtectDelayLoadIAT = 0x00001000, + DelayLoadIATSection = 0x00002000, // Delay load in separate section + HasLongJmpTable = 0x00010000, + FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes +}; + +struct coff_load_config_code_integrity { + support::ulittle16_t Flags; + support::ulittle16_t Catalog; + support::ulittle32_t CatalogOffset; + support::ulittle32_t Reserved; +}; + +/// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) struct coff_load_configuration32 { - support::ulittle32_t Characteristics; + support::ulittle32_t Size; support::ulittle32_t TimeDateStamp; support::ulittle16_t MajorVersion; support::ulittle16_t MinorVersion; @@ -578,34 +596,81 @@ struct coff_load_configuration32 { support::ulittle32_t ProcessAffinityMask; support::ulittle32_t ProcessHeapFlags; support::ulittle16_t CSDVersion; - support::ulittle16_t Reserved; + support::ulittle16_t DependentLoadFlags; support::ulittle32_t EditList; support::ulittle32_t SecurityCookie; support::ulittle32_t SEHandlerTable; support::ulittle32_t SEHandlerCount; + + // Added in MSVC 2015 for /guard:cf. + support::ulittle32_t GuardCFCheckFunction; + support::ulittle32_t GuardCFCheckDispatch; + support::ulittle32_t GuardCFFunctionTable; + support::ulittle32_t GuardCFFunctionCount; + support::ulittle32_t GuardFlags; // coff_guard_flags + + // Added in MSVC 2017 + coff_load_config_code_integrity CodeIntegrity; + support::ulittle32_t GuardAddressTakenIatEntryTable; + support::ulittle32_t GuardAddressTakenIatEntryCount; + support::ulittle32_t GuardLongJumpTargetTable; + support::ulittle32_t GuardLongJumpTargetCount; + support::ulittle32_t DynamicValueRelocTable; + support::ulittle32_t CHPEMetadataPointer; + support::ulittle32_t GuardRFFailureRoutine; + support::ulittle32_t GuardRFFailureRoutineFunctionPointer; + support::ulittle32_t DynamicValueRelocTableOffset; + support::ulittle16_t DynamicValueRelocTableSection; + support::ulittle16_t Reserved2; + support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; + support::ulittle32_t HotPatchTableOffset; }; +/// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) struct coff_load_configuration64 { - support::ulittle32_t Characteristics; + support::ulittle32_t Size; support::ulittle32_t TimeDateStamp; support::ulittle16_t MajorVersion; support::ulittle16_t MinorVersion; support::ulittle32_t GlobalFlagsClear; support::ulittle32_t GlobalFlagsSet; support::ulittle32_t CriticalSectionDefaultTimeout; - support::ulittle32_t DeCommitFreeBlockThreshold; - support::ulittle32_t DeCommitTotalFreeThreshold; - support::ulittle32_t LockPrefixTable; - support::ulittle32_t MaximumAllocationSize; - support::ulittle32_t VirtualMemoryThreshold; - support::ulittle32_t ProcessAffinityMask; + support::ulittle64_t DeCommitFreeBlockThreshold; + support::ulittle64_t DeCommitTotalFreeThreshold; + support::ulittle64_t LockPrefixTable; + support::ulittle64_t MaximumAllocationSize; + support::ulittle64_t VirtualMemoryThreshold; + support::ulittle64_t ProcessAffinityMask; support::ulittle32_t ProcessHeapFlags; support::ulittle16_t CSDVersion; - support::ulittle16_t Reserved; - support::ulittle32_t EditList; + support::ulittle16_t DependentLoadFlags; + support::ulittle64_t EditList; support::ulittle64_t SecurityCookie; support::ulittle64_t SEHandlerTable; support::ulittle64_t SEHandlerCount; + + // Added in MSVC 2015 for /guard:cf. + support::ulittle64_t GuardCFCheckFunction; + support::ulittle64_t GuardCFCheckDispatch; + support::ulittle64_t GuardCFFunctionTable; + support::ulittle64_t GuardCFFunctionCount; + support::ulittle32_t GuardFlags; + + // Added in MSVC 2017 + coff_load_config_code_integrity CodeIntegrity; + support::ulittle64_t GuardAddressTakenIatEntryTable; + support::ulittle64_t GuardAddressTakenIatEntryCount; + support::ulittle64_t GuardLongJumpTargetTable; + support::ulittle64_t GuardLongJumpTargetCount; + support::ulittle64_t DynamicValueRelocTable; + support::ulittle64_t CHPEMetadataPointer; + support::ulittle64_t GuardRFFailureRoutine; + support::ulittle64_t GuardRFFailureRoutineFunctionPointer; + support::ulittle32_t DynamicValueRelocTableOffset; + support::ulittle16_t DynamicValueRelocTableSection; + support::ulittle16_t Reserved2; + support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; + support::ulittle32_t HotPatchTableOffset; }; struct coff_runtime_function_x64 { @@ -684,6 +749,8 @@ private: const coff_base_reloc_block_header *BaseRelocEnd; const debug_directory *DebugDirectoryBegin; const debug_directory *DebugDirectoryEnd; + // Either coff_load_configuration32 or coff_load_configuration64. + const void *LoadConfig; std::error_code getString(uint32_t offset, StringRef &Res) const; @@ -698,6 +765,7 @@ private: std::error_code initExportTablePtr(); std::error_code initBaseRelocPtr(); std::error_code initDebugDirectoryPtr(); + std::error_code initLoadConfigPtr(); public: uintptr_t getSymbolTable() const { @@ -775,6 +843,16 @@ public: return getRawNumberOfSymbols(); } + const coff_load_configuration32 *getLoadConfig32() const { + assert(!is64()); + return reinterpret_cast(LoadConfig); + } + + const coff_load_configuration64 *getLoadConfig64() const { + assert(is64()); + return reinterpret_cast(LoadConfig); + } + protected: void moveSymbolNext(DataRefImpl &Symb) const override; Expected getSymbolName(DataRefImpl Symb) const override; diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 579c8dde366..9a760d86e7e 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -650,6 +650,23 @@ std::error_code COFFObjectFile::initDebugDirectoryPtr() { return std::error_code(); } +std::error_code COFFObjectFile::initLoadConfigPtr() { + // Get the RVA of the debug directory. Do nothing if it does not exist. + const data_directory *DataEntry; + if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry)) + return std::error_code(); + + // Do nothing if the RVA is NULL. + if (DataEntry->RelativeVirtualAddress == 0) + return std::error_code(); + uintptr_t IntPtr = 0; + if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return EC; + + LoadConfig = (const void *)IntPtr; + return std::error_code(); +} + COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), @@ -784,6 +801,9 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) if ((EC = initDebugDirectoryPtr())) return; + if ((EC = initLoadConfigPtr())) + return; + EC = std::error_code(); } diff --git a/test/tools/llvm-readobj/Inputs/coff-load-config-x64.dll b/test/tools/llvm-readobj/Inputs/coff-load-config-x64.dll new file mode 100644 index 0000000000000000000000000000000000000000..26101f93c41fce7c07b63a8b2dfa83b4cec76943 GIT binary patch literal 9728 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 void printPEHeader(const PEHeader *Hdr); void printBaseOfDataField(const pe32_header *Hdr); void printBaseOfDataField(const pe32plus_header *Hdr); + template + void printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables); + typedef void (*PrintExtraCB)(raw_ostream &, const uint8_t *); + void printRVATable(uint64_t TableVA, uint64_t Count, uint64_t EntrySize, + PrintExtraCB PrintExtra = 0); void printCodeViewSymbolSection(StringRef SectionName, const SectionRef &Section); void printCodeViewTypeSection(StringRef SectionName, const SectionRef &Section); @@ -745,6 +759,125 @@ void COFFDumper::printCOFFDebugDirectory() { } } +void COFFDumper::printRVATable(uint64_t TableVA, uint64_t Count, + uint64_t EntrySize, PrintExtraCB PrintExtra) { + uintptr_t TableStart, TableEnd; + error(Obj->getVaPtr(TableVA, TableStart)); + error(Obj->getVaPtr(TableVA + Count * EntrySize, TableEnd)); + for (uintptr_t I = TableStart; I < TableEnd; I += EntrySize) { + uint32_t RVA = *reinterpret_cast(I); + raw_ostream &OS = W.startLine(); + OS << "0x" << utohexstr(Obj->getImageBase() + RVA); + if (PrintExtra) + PrintExtra(OS, reinterpret_cast(I)); + OS << '\n'; + } +} + +void COFFDumper::printCOFFLoadConfig() { + LoadConfigTables Tables; + if (Obj->is64()) + printCOFFLoadConfig(Obj->getLoadConfig64(), Tables); + else + printCOFFLoadConfig(Obj->getLoadConfig32(), Tables); + + if (Tables.SEHTableVA) { + ListScope LS(W, "SEHTable"); + printRVATable(Tables.SEHTableVA, Tables.SEHTableCount, 4); + } + + if (Tables.GuardFidTableVA) { + ListScope LS(W, "GuardFidTable"); + if (Tables.GuardFlags & uint32_t(coff_guard_flags::FidTableHasFlags)) { + auto PrintGuardFlags = [](raw_ostream &OS, const uint8_t *Entry) { + uint8_t Flags = *reinterpret_cast(Entry + 4); + if (Flags) + OS << " flags " << utohexstr(Flags); + }; + printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 5, + PrintGuardFlags); + } else { + printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4); + } + } +} + +template +void COFFDumper::printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables) { + ListScope LS(W, "LoadConfig"); + char FormattedTime[20] = {}; + time_t TDS = Conf->TimeDateStamp; + strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); + W.printHex("Size", Conf->Size); + + // Print everything before SecurityCookie. The vast majority of images today + // have all these fields. + if (Conf->Size < offsetof(T, SEHandlerTable)) + return; + W.printHex("TimeDateStamp", FormattedTime, TDS); + W.printHex("MajorVersion", Conf->MajorVersion); + W.printHex("MinorVersion", Conf->MinorVersion); + W.printHex("GlobalFlagsClear", Conf->GlobalFlagsClear); + W.printHex("GlobalFlagsSet", Conf->GlobalFlagsSet); + W.printHex("CriticalSectionDefaultTimeout", + Conf->CriticalSectionDefaultTimeout); + W.printHex("DeCommitFreeBlockThreshold", Conf->DeCommitFreeBlockThreshold); + W.printHex("DeCommitTotalFreeThreshold", Conf->DeCommitTotalFreeThreshold); + W.printHex("LockPrefixTable", Conf->LockPrefixTable); + W.printHex("MaximumAllocationSize", Conf->MaximumAllocationSize); + W.printHex("VirtualMemoryThreshold", Conf->VirtualMemoryThreshold); + W.printHex("ProcessHeapFlags", Conf->ProcessHeapFlags); + W.printHex("ProcessAffinityMask", Conf->ProcessAffinityMask); + W.printHex("CSDVersion", Conf->CSDVersion); + W.printHex("DependentLoadFlags", Conf->DependentLoadFlags); + W.printHex("EditList", Conf->EditList); + W.printHex("SecurityCookie", Conf->SecurityCookie); + + // Print the safe SEH table if present. + if (Conf->Size < offsetof(coff_load_configuration32, GuardCFCheckFunction)) + return; + W.printHex("SEHandlerTable", Conf->SEHandlerTable); + W.printNumber("SEHandlerCount", Conf->SEHandlerCount); + + Tables.SEHTableVA = Conf->SEHandlerTable; + Tables.SEHTableCount = Conf->SEHandlerCount; + + // Print everything before CodeIntegrity. (2015) + if (Conf->Size < offsetof(T, CodeIntegrity)) + return; + W.printHex("GuardCFCheckFunction", Conf->GuardCFCheckFunction); + W.printHex("GuardCFCheckDispatch", Conf->GuardCFCheckDispatch); + W.printHex("GuardCFFunctionTable", Conf->GuardCFFunctionTable); + W.printNumber("GuardCFFunctionCount", Conf->GuardCFFunctionCount); + W.printHex("GuardFlags", Conf->GuardFlags); + + Tables.GuardFidTableVA = Conf->GuardCFFunctionTable; + Tables.GuardFidTableCount = Conf->GuardCFFunctionCount; + Tables.GuardFlags = Conf->GuardFlags; + + // Print the rest. (2017) + if (Conf->Size < sizeof(T)) + return; + W.printHex("GuardAddressTakenIatEntryTable", + Conf->GuardAddressTakenIatEntryTable); + W.printNumber("GuardAddressTakenIatEntryCount", + Conf->GuardAddressTakenIatEntryCount); + W.printHex("GuardLongJumpTargetTable", Conf->GuardLongJumpTargetTable); + W.printNumber("GuardLongJumpTargetCount", Conf->GuardLongJumpTargetCount); + W.printHex("DynamicValueRelocTable", Conf->DynamicValueRelocTable); + W.printHex("CHPEMetadataPointer", Conf->CHPEMetadataPointer); + W.printHex("GuardRFFailureRoutine", Conf->GuardRFFailureRoutine); + W.printHex("GuardRFFailureRoutineFunctionPointer", + Conf->GuardRFFailureRoutineFunctionPointer); + W.printHex("DynamicValueRelocTableOffset", + Conf->DynamicValueRelocTableOffset); + W.printNumber("DynamicValueRelocTableSection", + Conf->DynamicValueRelocTableSection); + W.printHex("GuardRFVerifyStackPointerFunctionPointer", + Conf->GuardRFVerifyStackPointerFunctionPointer); + W.printHex("HotPatchTableOffset", Conf->HotPatchTableOffset); +} + void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) { W.printHex("BaseOfData", Hdr->BaseOfData); } diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 48f825c527c..43883c2d217 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -68,6 +68,7 @@ public: virtual void printCOFFBaseReloc() { } virtual void printCOFFDebugDirectory() { } virtual void printCOFFResources() {} + virtual void printCOFFLoadConfig() { } virtual void printCodeViewDebugInfo() { } virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs, llvm::codeview::TypeTableBuilder &CVTypes) {} diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index cd7244a8f97..51991a3f067 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -218,6 +218,11 @@ namespace opts { cl::opt COFFResources("coff-resources", cl::desc("Display the PE/COFF .rsrc section")); + // -coff-load-config + cl::opt + COFFLoadConfig("coff-load-config", + cl::desc("Display the PE/COFF load config")); + // -macho-data-in-code cl::opt MachODataInCode("macho-data-in-code", @@ -444,6 +449,8 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printCOFFDebugDirectory(); if (opts::COFFResources) Dumper->printCOFFResources(); + if (opts::COFFLoadConfig) + Dumper->printCOFFLoadConfig(); if (opts::CodeView) Dumper->printCodeViewDebugInfo(); if (opts::CodeViewMergedTypes) -- 2.50.1