|
@@ -68,6 +68,14 @@ using namespace llvm::Win64EH;
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
+struct LoadConfigTables {
|
|
|
+ uint64_t SEHTableVA = 0;
|
|
|
+ uint64_t SEHTableCount = 0;
|
|
|
+ uint32_t GuardFlags = 0;
|
|
|
+ uint64_t GuardFidTableVA = 0;
|
|
|
+ uint64_t GuardFidTableCount = 0;
|
|
|
+};
|
|
|
+
|
|
|
class COFFDumper : public ObjDumper {
|
|
|
public:
|
|
|
friend class COFFObjectDumpDelegate;
|
|
@@ -86,6 +94,7 @@ public:
|
|
|
void printCOFFBaseReloc() override;
|
|
|
void printCOFFDebugDirectory() override;
|
|
|
void printCOFFResources() override;
|
|
|
+ void printCOFFLoadConfig() override;
|
|
|
void printCodeViewDebugInfo() override;
|
|
|
void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs,
|
|
|
llvm::codeview::TypeTableBuilder &CVTypes) override;
|
|
@@ -100,6 +109,11 @@ private:
|
|
|
template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
|
|
|
void printBaseOfDataField(const pe32_header *Hdr);
|
|
|
void printBaseOfDataField(const pe32plus_header *Hdr);
|
|
|
+ template <typename T>
|
|
|
+ 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<const ulittle32_t *>(I);
|
|
|
+ raw_ostream &OS = W.startLine();
|
|
|
+ OS << "0x" << utohexstr(Obj->getImageBase() + RVA);
|
|
|
+ if (PrintExtra)
|
|
|
+ PrintExtra(OS, reinterpret_cast<const uint8_t *>(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<const uint8_t *>(Entry + 4);
|
|
|
+ if (Flags)
|
|
|
+ OS << " flags " << utohexstr(Flags);
|
|
|
+ };
|
|
|
+ printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 5,
|
|
|
+ PrintGuardFlags);
|
|
|
+ } else {
|
|
|
+ printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+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);
|
|
|
}
|