diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/docs/ClangCommandLineReference.rst | 6 | ||||
| -rw-r--r-- | clang/include/clang/Basic/CodeGenOptions.def | 1 | ||||
| -rw-r--r-- | clang/include/clang/Driver/CC1Options.td | 4 | ||||
| -rw-r--r-- | clang/include/clang/Driver/Options.td | 2 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 31 | ||||
| -rw-r--r-- | clang/lib/Driver/ToolChains/MSVC.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 1 | ||||
| -rw-r--r-- | clang/test/CodeGen/cfguardtable.c | 14 | ||||
| -rw-r--r-- | clang/test/Driver/cl-fallback.c | 3 | ||||
| -rw-r--r-- | clang/test/Driver/cl-options.c | 9 |
11 files changed, 67 insertions, 33 deletions
diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 5f6bb9829f5..e8d561fae95 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -124,7 +124,11 @@ Output path for the plist report .. option:: -cfguard -Emit tables required for Windows Control Flow Guard. +Emit tables and checks for Windows Control Flow Guard. + +.. option:: -cfguard-no-checks + +Emit tables required for Windows Control Flow Guard without checks. .. option:: -client\_name<arg> diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index d2266cc2d61..f8d94e352f2 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -37,6 +37,7 @@ CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) o CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. CODEGENOPT(Backchain , 1, 0) ///< -mbackchain +CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files. CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files. diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 72019aa2a01..1d550eb15ea 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -400,6 +400,10 @@ def msign_return_address_key_EQ : Joined<["-"], "msign-return-address-key=">, Values<"a_key,b_key">; def mbranch_target_enforce : Flag<["-"], "mbranch-target-enforce">; def fno_dllexport_inlines : Flag<["-"], "fno-dllexport-inlines">; +def cfguard_no_checks : Flag<["-"], "cfguard-no-checks">, + HelpText<"Emit Windows Control Flow Guard tables only (no checks)">; +def cfguard : Flag<["-"], "cfguard">, + HelpText<"Emit Windows Control Flow Guard tables and checks">; //===----------------------------------------------------------------------===// // Dependency Output Options diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1c3d7f77707..2401a31ceb9 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -503,8 +503,6 @@ def bind__at__load : Flag<["-"], "bind_at_load">; def bundle__loader : Separate<["-"], "bundle_loader">; def bundle : Flag<["-"], "bundle">; def b : JoinedOrSeparate<["-"], "b">, Flags<[Unsupported]>; -def cfguard : Flag<["-"], "cfguard">, Flags<[CC1Option]>, - HelpText<"Emit tables required for Windows Control Flow Guard.">; def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>, Flags<[CC1Option]>, HelpText<"OpenCL only. This option disables all optimizations. By default optimizations are enabled.">; def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">, Group<opencl_Group>, Flags<[CC1Option]>, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 75708d6e496..480a33f2728 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -482,8 +482,11 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Warning, "CodeViewGHash", 1); } if (CodeGenOpts.ControlFlowGuard) { - // We want function ID tables for Control Flow Guard. - getModule().addModuleFlag(llvm::Module::Warning, "cfguardtable", 1); + // Function ID tables and checks for Control Flow Guard (cfguard=2). + getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 2); + } else if (CodeGenOpts.ControlFlowGuardNoChecks) { + // Function ID tables for Control Flow Guard (cfguard=1). + getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1); } if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) { // We don't support LTO with 2 with different StrictVTablePointers diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index ae12465d3f8..c60dc76ae1b 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5975,26 +5975,19 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, } if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { - SmallVector<StringRef, 1> 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) + StringRef GuardArgs = A->getValue(); + // The only valid options are "cf", "cf,nochecks", and "cf-". + if (GuardArgs.equals_lower("cf")) { + // Emit CFG instrumentation and the table of address-taken functions. CmdArgs.push_back("-cfguard"); + } else if (GuardArgs.equals_lower("cf,nochecks")) { + // Emit only the table of address-taken functions. + CmdArgs.push_back("-cfguard-no-checks"); + } else if (GuardArgs.equals_lower("cf-")) { + // Do nothing, but we might want to emit a security warning in future. + } else { + D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs; + } } } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 1d31844bfcc..4e143f6a5d3 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -422,6 +422,17 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); + // Control Flow Guard checks + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) { + // MSVC doesn't yet support the "nochecks" modifier. + CmdArgs.push_back("-guard:cf"); + } else if (GuardArgs.equals_lower("cf-")) { + CmdArgs.push_back("-guard:cf-"); + } + } + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) { CmdArgs.push_back("-nodefaultlib:vcomp.lib"); @@ -679,6 +690,17 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand( : "/Zc:threadSafeInit-"); } + // Control Flow Guard checks + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) { + // MSVC doesn't yet support the "nochecks" modifier. + CmdArgs.push_back("/guard:cf"); + } else if (GuardArgs.equals_lower("cf-")) { + CmdArgs.push_back("/guard:cf-"); + } + } + // Pass through all unknown arguments so that the fallback command can see // them too. Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f6e6f71b280..f197a67e7a3 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1003,6 +1003,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); + Opts.ControlFlowGuardNoChecks = Args.hasArg(OPT_cfguard_no_checks); Opts.ControlFlowGuard = Args.hasArg(OPT_cfguard); Opts.DisableGCov = Args.hasArg(OPT_test_coverage); diff --git a/clang/test/CodeGen/cfguardtable.c b/clang/test/CodeGen/cfguardtable.c index 96492926129..05284f6d23a 100644 --- a/clang/test/CodeGen/cfguardtable.c +++ b/clang/test/CodeGen/cfguardtable.c @@ -1,6 +1,8 @@ -// 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} +// RUN: %clang_cc1 -cfguard-no-checks -emit-llvm %s -o - | FileCheck %s -check-prefix=CFGUARDNOCHECKS
+// RUN: %clang_cc1 -cfguard -emit-llvm %s -o - | FileCheck %s -check-prefix=CFGUARD
+
+void f() {}
+
+// Check that the cfguard metadata flag gets correctly set on the module.
+// CFGUARDNOCHECKS: !"cfguard", i32 1}
+// CFGUARD: !"cfguard", i32 2}
diff --git a/clang/test/Driver/cl-fallback.c b/clang/test/Driver/cl-fallback.c index 2e5698ce9f9..a840883255f 100644 --- a/clang/test/Driver/cl-fallback.c +++ b/clang/test/Driver/cl-fallback.c @@ -2,7 +2,7 @@ // command-line option, e.g. on Mac where %s is commonly under /Users. // RUN: %clang_cl --target=i686-pc-win32 /fallback /Dfoo=bar /Ubaz /Ifoo /O0 /Ox /GR /GR- /GS /GS- /Gy /Gy- \ -// RUN: /Gw /Gw- /LD /LDd /EHs /EHs- /Zl /MD /MDd /MTd /MT /FImyheader.h /Zi \ +// RUN: /Gw /Gw- /LD /LDd /EHs /EHs- /Zl /MD /MDd /MTd /MT /guard:cf /guard:cf- /FImyheader.h /Zi \ // RUN: -garbage -moregarbage \ // RUN: -### -- %s 2>&1 \ // RUN: | FileCheck %s @@ -33,6 +33,7 @@ // CHECK: "/EHs-" // CHECK: "/Zl" // CHECK: "/MT" +// CHECK: "/guard:cf-" // CHECK: "-garbage" // CHECK: "-moregarbage" // CHECK: "/Tc" "{{.*cl-fallback.c}}" diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 354ed998f6f..b82d69b6430 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -597,9 +597,14 @@ // NOCFGUARD-NOT: -cfguard // 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 +// CFGUARD-NOT: -cfguard-no-checks + +// RUN: %clang_cl /guard:cf,nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDNOCHECKS %s +// CFGUARDNOCHECKS: -cfguard-no-checks + +// RUN: %clang_cl /guard:nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDNOCHECKSINVALID %s +// CFGUARDNOCHECKSINVALID: invalid value 'nochecks' in '/guard:' // RUN: %clang_cl /guard:foo -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDINVALID %s // CFGUARDINVALID: invalid value 'foo' in '/guard:' |

