diff --git a/lld/test/COFF/gfids-corrupt.s b/lld/test/COFF/gfids-corrupt.s --- a/lld/test/COFF/gfids-corrupt.s +++ b/lld/test/COFF/gfids-corrupt.s @@ -15,7 +15,10 @@ # CHECK: GuardCFCheckDispatch: 0x0 # CHECK: GuardCFFunctionTable: 0x14000{{.*}} # CHECK: GuardCFFunctionCount: 2 -# CHECK: GuardFlags: 0x500 +# CHECK: GuardFlags [ (0x500) +# CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK: CF_INSTRUMENTED (0x100) +# CHECK: ] # CHECK: GuardAddressTakenIatEntryTable: 0x0 # CHECK: GuardAddressTakenIatEntryCount: 0 # CHECK: GuardLongJumpTargetTable: 0x0 diff --git a/lld/test/COFF/gfids-fallback.s b/lld/test/COFF/gfids-fallback.s --- a/lld/test/COFF/gfids-fallback.s +++ b/lld/test/COFF/gfids-fallback.s @@ -12,7 +12,10 @@ # CHECK: GuardCFCheckDispatch: 0x0 # CHECK: GuardCFFunctionTable: 0x14000{{.*}} # CHECK: GuardCFFunctionCount: 3 -# CHECK: GuardFlags: 0x500 +# CHECK: GuardFlags [ (0x500) +# CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK: CF_INSTRUMENTED (0x100) +# CHECK: ] # CHECK: GuardAddressTakenIatEntryTable: 0x0 # CHECK: GuardAddressTakenIatEntryCount: 0 # CHECK: GuardLongJumpTargetTable: 0x0 diff --git a/lld/test/COFF/gfids-gc.s b/lld/test/COFF/gfids-gc.s --- a/lld/test/COFF/gfids-gc.s +++ b/lld/test/COFF/gfids-gc.s @@ -29,7 +29,10 @@ # CHECK-NOGC: GuardCFCheckDispatch: 0x0 # CHECK-NOGC: GuardCFFunctionTable: 0x14000{{.*}} # CHECK-NOGC: GuardCFFunctionCount: 3 -# CHECK-NOGC: GuardFlags: 0x500 +# CHECK-NOGC: GuardFlags [ (0x500) +# CHECK-NOGC: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK-NOGC: CF_INSTRUMENTED (0x100) +# CHECK-NOGC: ] # CHECK-NOGC: GuardAddressTakenIatEntryTable: 0x0 # CHECK-NOGC: GuardAddressTakenIatEntryCount: 0 # CHECK-NOGC: GuardLongJumpTargetTable: 0x0 @@ -52,7 +55,10 @@ # CHECK-GC: GuardCFCheckDispatch: 0x0 # CHECK-GC: GuardCFFunctionTable: 0x14000{{.*}} # CHECK-GC: GuardCFFunctionCount: 2 -# CHECK-GC: GuardFlags: 0x500 +# CHECK-GC: GuardFlags [ (0x500) +# CHECK-GC: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK-GC: CF_INSTRUMENTED (0x100) +# CHECK-GC: ] # CHECK-GC: GuardAddressTakenIatEntryTable: 0x0 # CHECK-GC: GuardAddressTakenIatEntryCount: 0 # CHECK-GC: GuardLongJumpTargetTable: 0x0 diff --git a/lld/test/COFF/gfids-icf.s b/lld/test/COFF/gfids-icf.s --- a/lld/test/COFF/gfids-icf.s +++ b/lld/test/COFF/gfids-icf.s @@ -24,7 +24,10 @@ # CHECK: GuardCFCheckDispatch: 0x0 # CHECK: GuardCFFunctionTable: 0x14000{{.*}} # CHECK: GuardCFFunctionCount: 2 -# CHECK: GuardFlags: 0x500 +# CHECK: GuardFlags [ (0x500) +# CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK: CF_INSTRUMENTED (0x100) +# CHECK: ] # CHECK: GuardAddressTakenIatEntryTable: 0x0 # CHECK: GuardAddressTakenIatEntryCount: 0 # CHECK: GuardLongJumpTargetTable: 0x0 diff --git a/lld/test/COFF/giats.s b/lld/test/COFF/giats.s --- a/lld/test/COFF/giats.s +++ b/lld/test/COFF/giats.s @@ -15,7 +15,11 @@ # CHECK: LoadConfig [ # CHECK: GuardCFFunctionTable: 0x140002114 # CHECK: GuardCFFunctionCount: 1 -# CHECK: GuardFlags: 0x10500 +# CHECK: GuardFlags [ (0x10500) +# CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK: CF_INSTRUMENTED (0x100) +# CHECK: CF_LONGJUMP_TABLE_PRESENT (0x10000) +# CHECK: ] # CHECK: GuardAddressTakenIatEntryTable: 0x140002118 # CHECK: GuardAddressTakenIatEntryCount: 1 # CHECK: ] @@ -35,7 +39,11 @@ # DELAY-CHECK: LoadConfig [ # DELAY-CHECK: GuardCFFunctionTable: 0x140002114 # DELAY-CHECK: GuardCFFunctionCount: 2 -# DELAY-CHECK: GuardFlags: 0x10500 +# DELAY-CHECK: GuardFlags [ (0x10500) +# DELAY-CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# DELAY-CHECK: CF_INSTRUMENTED (0x100) +# DELAY-CHECK: CF_LONGJUMP_TABLE_PRESENT (0x10000) +# DELAY-CHECK: ] # DELAY-CHECK: GuardAddressTakenIatEntryTable: 0x14000211C # DELAY-CHECK: GuardAddressTakenIatEntryCount: 1 # DELAY-CHECK: ] diff --git a/lld/test/COFF/guard-ehcont.s b/lld/test/COFF/guard-ehcont.s --- a/lld/test/COFF/guard-ehcont.s +++ b/lld/test/COFF/guard-ehcont.s @@ -11,7 +11,11 @@ # CHECK: GuardCFCheckDispatch: 0x0 # CHECK: GuardCFFunctionTable: 0x14000{{.*}} # CHECK: GuardCFFunctionCount: 1 -# CHECK: GuardFlags: 0x400500 +# CHECK: GuardFlags [ (0x400500) +# CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK: CF_INSTRUMENTED (0x100) +# CHECK: EH_CONTINUATION_TABLE_PRESENT (0x400000) +# CHECK: ] # CHECK: GuardAddressTakenIatEntryTable: 0x0 # CHECK: GuardAddressTakenIatEntryCount: 0 # CHECK: GuardEHContinuationTable: 0x14000{{.*}} diff --git a/lld/test/COFF/guard-longjmp.s b/lld/test/COFF/guard-longjmp.s --- a/lld/test/COFF/guard-longjmp.s +++ b/lld/test/COFF/guard-longjmp.s @@ -11,7 +11,11 @@ # CHECK: GuardCFCheckDispatch: 0x0 # CHECK: GuardCFFunctionTable: 0x14000{{.*}} # CHECK: GuardCFFunctionCount: 1 -# CHECK: GuardFlags: 0x10500 +# CHECK: GuardFlags [ (0x10500) +# CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) +# CHECK: CF_INSTRUMENTED (0x100) +# CHECK: CF_LONGJUMP_TABLE_PRESENT (0x10000) +# CHECK: ] # CHECK: GuardAddressTakenIatEntryTable: 0x0 # CHECK: GuardAddressTakenIatEntryCount: 0 # CHECK: GuardLongJumpTargetTable: 0x14000{{.*}} diff --git a/lld/test/COFF/guardcf-lto.ll b/lld/test/COFF/guardcf-lto.ll --- a/lld/test/COFF/guardcf-lto.ll +++ b/lld/test/COFF/guardcf-lto.ll @@ -16,7 +16,11 @@ ; CHECK: LoadConfig [ ; CHECK: GuardCFFunctionTable: 0x{{[^0].*}} ; CHECK-NEXT: GuardCFFunctionCount: 2 -; CHECK-NEXT: GuardFlags: 0x10500 +; CHECK-NEXT: GuardFlags [ (0x10500) +; CHECK-NEXT: CF_FUNCTION_TABLE_PRESENT (0x400) +; CHECK-NEXT: CF_INSTRUMENTED (0x100) +; CHECK-NEXT: CF_LONGJUMP_TABLE_PRESENT (0x10000) +; CHECK-NEXT: ] ; CHECK: ] ; CHECK: GuardFidTable [ ; CHECK-NEXT: 0x180{{.*}} diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -704,6 +704,51 @@ IMPORT_NAME_UNDECORATE = 3 }; +enum class GuardFlags : uint32_t { + /// Module performs control flow integrity checks using system-supplied + /// support. + CF_INSTRUMENTED = 0x100, + /// Module performs control flow and write integrity checks. + CFW_INSTRUMENTED = 0x200, + /// Module contains valid control flow target metadata. + CF_FUNCTION_TABLE_PRESENT = 0x400, + /// Module does not make use of the /GS security cookie. + SECURITY_COOKIE_UNUSED = 0x800, + /// Module supports read only delay load IAT. + PROTECT_DELAYLOAD_IAT = 0x1000, + /// Delayload import table in its own .didat section (with nothing else in it) + /// that can be freely reprotected. + DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x2000, + /// Module contains suppressed export information. This also infers that the + /// address taken IAT table is also present in the load config. + CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x4000, + /// Module enables suppression of exports. + CF_ENABLE_EXPORT_SUPPRESSION = 0x8000, + /// Module contains longjmp target information. + CF_LONGJUMP_TABLE_PRESENT = 0x10000, + /// Module contains EH continuation target information. + EH_CONTINUATION_TABLE_PRESENT = 0x400000, + /// Mask for the subfield that contains the stride of Control Flow Guard + /// function table entries (that is, the additional count of bytes per table + /// entry). + CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000, + CF_FUNCTION_TABLE_SIZE_5BYTES = 0x10000000, + CF_FUNCTION_TABLE_SIZE_6BYTES = 0x20000000, + CF_FUNCTION_TABLE_SIZE_7BYTES = 0x30000000, + CF_FUNCTION_TABLE_SIZE_8BYTES = 0x40000000, + CF_FUNCTION_TABLE_SIZE_9BYTES = 0x50000000, + CF_FUNCTION_TABLE_SIZE_10BYTES = 0x60000000, + CF_FUNCTION_TABLE_SIZE_11BYTES = 0x70000000, + CF_FUNCTION_TABLE_SIZE_12BYTES = 0x80000000, + CF_FUNCTION_TABLE_SIZE_13BYTES = 0x90000000, + CF_FUNCTION_TABLE_SIZE_14BYTES = 0xA0000000, + CF_FUNCTION_TABLE_SIZE_15BYTES = 0xB0000000, + CF_FUNCTION_TABLE_SIZE_16BYTES = 0xC0000000, + CF_FUNCTION_TABLE_SIZE_17BYTES = 0xD0000000, + CF_FUNCTION_TABLE_SIZE_18BYTES = 0xE0000000, + CF_FUNCTION_TABLE_SIZE_19BYTES = 0xF0000000, +}; + struct ImportHeader { uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). uint16_t Sig2; ///< Must be 0xFFFF. diff --git a/llvm/test/tools/llvm-readobj/COFF/load-config.test b/llvm/test/tools/llvm-readobj/COFF/load-config.test --- a/llvm/test/tools/llvm-readobj/COFF/load-config.test +++ b/llvm/test/tools/llvm-readobj/COFF/load-config.test @@ -30,7 +30,13 @@ X86: GuardCFCheckDispatch: 0x0 X86: GuardCFFunctionTable: 0x100020A4 X86: GuardCFFunctionCount: 11 -X86: GuardFlags: 0x13500 +X86: GuardFlags [ (0x13500) +X86: CF_FUNCTION_TABLE_PRESENT (0x400) +X86: CF_INSTRUMENTED (0x100) +X86: CF_LONGJUMP_TABLE_PRESENT (0x10000) +X86: DELAYLOAD_IAT_IN_ITS_OWN_SECTION (0x2000) +X86: PROTECT_DELAYLOAD_IAT (0x1000) +X86: ] X86: ] X86: SEHTable [ X86: 0x10001BE0 @@ -75,7 +81,13 @@ X64: GuardCFCheckDispatch: 0x180002108 X64: GuardCFFunctionTable: 0x180002158 X64: GuardCFFunctionCount: 9 -X64: GuardFlags: 0x13500 +X64: GuardFlags [ (0x13500) +X64: CF_FUNCTION_TABLE_PRESENT (0x400) +X64: CF_INSTRUMENTED (0x100) +X64: CF_LONGJUMP_TABLE_PRESENT (0x10000) +X64: DELAYLOAD_IAT_IN_ITS_OWN_SECTION (0x2000) +X64: PROTECT_DELAYLOAD_IAT (0x1000) +X64: ] X64: ] X64-NOT: SEHTable X64: GuardFidTable [ diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -577,6 +577,52 @@ LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA256), }; +const EnumEntry PELoadConfigGuardFlags[] = { + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_INSTRUMENTED), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CFW_INSTRUMENTED), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_FUNCTION_TABLE_PRESENT), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, SECURITY_COOKIE_UNUSED), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, PROTECT_DELAYLOAD_IAT), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + DELAYLOAD_IAT_IN_ITS_OWN_SECTION), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_EXPORT_SUPPRESSION_INFO_PRESENT), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_ENABLE_EXPORT_SUPPRESSION), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_LONGJUMP_TABLE_PRESENT), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + EH_CONTINUATION_TABLE_PRESENT), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_5BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_6BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_7BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_8BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_9BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_10BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_11BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_12BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_13BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_14BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_15BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_16BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_17BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_18BYTES), + LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, + CF_FUNCTION_TABLE_SIZE_19BYTES), +}; + template static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, COFFSymbolRef Symbol, @@ -880,7 +926,9 @@ W.printHex("GuardCFCheckDispatch", Conf->GuardCFCheckDispatch); W.printHex("GuardCFFunctionTable", Conf->GuardCFFunctionTable); W.printNumber("GuardCFFunctionCount", Conf->GuardCFFunctionCount); - W.printHex("GuardFlags", Conf->GuardFlags); + W.printFlags("GuardFlags", Conf->GuardFlags, + makeArrayRef(PELoadConfigGuardFlags), + (uint32_t)COFF::GuardFlags::CF_FUNCTION_TABLE_SIZE_MASK); Tables.GuardFidTableVA = Conf->GuardCFFunctionTable; Tables.GuardFidTableCount = Conf->GuardCFFunctionCount;