diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1786,7 +1786,7 @@ // Add the ehcont target table unless the user told us not to. if (config->guardCF & GuardCFLevel::EHCont) maybeAddRVATable(std::move(ehContTargets), "__guard_eh_cont_table", - "__guard_eh_cont_count", true); + "__guard_eh_cont_count"); // Set __guard_flags, which will be used in the load config to indicate that // /guard:cf was enabled. diff --git a/lld/test/COFF/guard-ehcont-seh.s b/lld/test/COFF/guard-ehcont-seh.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/guard-ehcont-seh.s @@ -0,0 +1,98 @@ +# REQUIRES: x86 +# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj +# RUN: lld-link %t.obj -guard:cf -guard:ehcont -out:%t.exe -entry:main +# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s + +# CHECK: ImageBase: 0x140000000 +# CHECK: LoadConfig [ +# CHECK: SEHandlerTable: 0x0 +# CHECK: SEHandlerCount: 0 +# CHECK: GuardCFCheckFunction: 0x0 +# CHECK: GuardCFCheckDispatch: 0x0 +# CHECK: GuardCFFunctionTable: 0x14000{{.*}} +# CHECK: GuardCFFunctionCount: 1 +# 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{{.*}} +# CHECK: GuardEHContinuationCount: 2 +# CHECK: ] +# CHECK: GuardEHContTable [ +# CHECK-NEXT: 0x14000{{.*}} +# CHECK-NEXT: 0x14000{{.*}} +# CHECK-NEXT: ] + +# We need @feat.00 to have 0x4000 to indicate /guard:ehcont. + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 0x4000 + .def main; .scl 2; .type 32; .endef + .globl main # -- Begin function main + .p2align 4, 0x90 +main: +.seh_proc main + .seh_handler __C_specific_handler, @unwind, @except + .seh_handlerdata + .long 2 + .long (seh_begin)@IMGREL + .long (seh_end)@IMGREL + .long 1 + .long (seh_except)@IMGREL + .long (seh2_begin)@IMGREL + .long (seh2_end)@IMGREL + .long 1 + .long (seh2_except)@IMGREL + .text + seh_begin: + nop + int3 + nop + seh_end: + nop + seh_except: + nop + + seh2_begin: + nop + int3 + nop + seh2_end: + nop + seh2_except: + nop + + xor %eax, %eax + ret +.seh_endproc + +__C_specific_handler: + ret + +.section .gehcont$y,"dr" +.symidx seh_except +.symidx seh2_except + +.section .rdata,"dr" +.globl _load_config_used +_load_config_used: + .long 312 + .fill 124, 1, 0 + .quad __guard_fids_table + .quad __guard_fids_count + .long __guard_flags + .fill 12, 1, 0 + .quad __guard_iat_table + .quad __guard_iat_count + .quad __guard_longjmp_table + .quad __guard_longjmp_count + .fill 72, 1, 0 + .quad __guard_eh_cont_table + .quad __guard_eh_cont_count + .fill 32, 1, 0 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 @@ -851,17 +851,16 @@ OS << " flags " << utohexstr(Flags); }; + // The stride gives the number of extra bytes in addition to the 4-byte + // RVA of each entry in the table. As of writing only a 1-byte extra flag + // has been defined. + uint32_t Stride = Tables.GuardFlags >> 28; + if (Tables.GuardFidTableVA) { ListScope LS(W, "GuardFidTable"); - if (uint32_t Size = - Tables.GuardFlags & - uint32_t(COFF::GuardFlags::CF_FUNCTION_TABLE_SIZE_MASK)) { - // The size mask gives the number of extra bytes in addition to the 4-byte - // RVA of each entry in the table. As of writing only a 1-byte extra flag - // has been defined. - Size = (Size >> 28) + 4; - printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, Size, - PrintGuardFlags); + if (Stride) { + printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, + 4 + Stride, PrintGuardFlags); } else { printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4); } @@ -869,18 +868,32 @@ if (Tables.GuardIatTableVA) { ListScope LS(W, "GuardIatTable"); - printRVATable(Tables.GuardIatTableVA, Tables.GuardIatTableCount, 4); + if (Stride) { + printRVATable(Tables.GuardIatTableVA, Tables.GuardIatTableCount, + 4 + Stride, PrintGuardFlags); + } else { + printRVATable(Tables.GuardIatTableVA, Tables.GuardIatTableCount, 4); + } } if (Tables.GuardLJmpTableVA) { ListScope LS(W, "GuardLJmpTable"); - printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount, 4); + if (Stride) { + printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount, + 4 + Stride, PrintGuardFlags); + } else { + printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount, 4); + } } if (Tables.GuardEHContTableVA) { ListScope LS(W, "GuardEHContTable"); - printRVATable(Tables.GuardEHContTableVA, Tables.GuardEHContTableCount, 5, - PrintGuardFlags); + if (Stride) { + printRVATable(Tables.GuardEHContTableVA, Tables.GuardEHContTableCount, + 4 + Stride, PrintGuardFlags); + } else { + printRVATable(Tables.GuardEHContTableVA, Tables.GuardEHContTableCount, 4); + } } }