From: Hans Wennborg Date: Fri, 10 Aug 2018 09:49:21 +0000 (+0000) Subject: clang-cl: Support /guard:cf,nochecks X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b8e7405c9212854b19fa1e958ada73220eed5b2;p=clang clang-cl: Support /guard:cf,nochecks This extension emits the guard cf table without inserting the instrumentation. Currently that's what clang-cl does with /guard:cf anyway, but this allows a user to request that explicitly. Differential Revision: https://reviews.llvm.org/D50513 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339420 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index 92be95212a..46435d9274 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -240,8 +240,8 @@ def _SLASH_Fi : CLCompileJoined<"Fi">, def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">, MetaVarName<"">; -def _SLASH_Guard : CLJoined<"guard:">, - HelpText<"Enable Control Flow Guard with /guard:cf">; +def _SLASH_guard : CLJoined<"guard:">, + HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks">; def _SLASH_GX : CLFlag<"GX">, HelpText<"Enable exception handling">; def _SLASH_GX_ : CLFlag<"GX-">, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 8baa7a5842..72fa799a54 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -460,7 +460,7 @@ void CodeGenModule::Release() { } if (CodeGenOpts.ControlFlowGuard) { // We want function ID tables for Control Flow Guard. - getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1); + getModule().addModuleFlag(llvm::Module::Warning, "cfguardtable", 1); } if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) { // We don't support LTO with 2 with different StrictVTablePointers diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 7685606ecb..fc7e861082 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -5273,9 +5273,28 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("msvc"); } - if (Args.hasArg(options::OPT__SLASH_Guard) && - Args.getLastArgValue(options::OPT__SLASH_Guard).equals_lower("cf")) - CmdArgs.push_back("-cfguard"); + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { + SmallVector SplitArgs; + StringRef(A->getValue()).split(SplitArgs, ","); + bool Instrument = false; + bool NoChecks = false; + for (StringRef Arg : SplitArgs) { + if (Arg.equals_lower("cf")) + Instrument = true; + else if (Arg.equals_lower("cf-")) + Instrument = false; + else if (Arg.equals_lower("nochecks")) + NoChecks = true; + else if (Arg.equals_lower("nochecks-")) + NoChecks = false; + else + D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Arg; + } + // Currently there's no support emitting CFG instrumentation; the flag only + // emits the table of address-taken functions. + if (Instrument || NoChecks) + CmdArgs.push_back("-cfguard"); + } } visualstudio::Compiler *Clang::getCLFallback() const { diff --git a/test/CodeGen/cfguardtable.c b/test/CodeGen/cfguardtable.c new file mode 100644 index 0000000000..9649292612 --- /dev/null +++ b/test/CodeGen/cfguardtable.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -cfguard -emit-llvm %s -o - | FileCheck %s + +void f() {} + +// Check that the cfguardtable metadata flag gets set on the module. +// CHECK: !"cfguardtable", i32 1} diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c index 3e2960fc47..9680560851 100644 --- a/test/Driver/cl-options.c +++ b/test/Driver/cl-options.c @@ -420,8 +420,6 @@ // RUN: /Gr \ // RUN: /GS \ // RUN: /GT \ -// RUN: /guard:cf \ -// RUN: /guard:cf- \ // RUN: /GX \ // RUN: /Gv \ // RUN: /Gz \ @@ -562,6 +560,18 @@ // RUN: %clang_cl -### -Fe%t.exe -entry:main -flto -- %s 2>&1 | FileCheck -check-prefix=LTO-WITHOUT-LLD %s // LTO-WITHOUT-LLD: LTO requires -fuse-ld=lld +// RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=NOCFGUARD %s +// RUN: %clang_cl /guard:cf- -### -- %s 2>&1 | FileCheck -check-prefix=NOCFGUARD %s +// NOCFGUARD-NOT: -guardcf + +// RUN: %clang_cl /guard:cf -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARD %s +// RUN: %clang_cl /guard:cf,nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARD %s +// RUN: %clang_cl /guard:nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARD %s +// CFGUARD: -cfguard + +// RUN: %clang_cl /guard:foo -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDINVALID %s +// CFGUARDINVALID: invalid value 'foo' in '/guard:' + // Accept "core" clang options. // (/Zs is for syntax-only, -Werror makes it fail hard on unknown options) // RUN: %clang_cl \