summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/docs/ClangCommandLineReference.rst6
-rw-r--r--clang/include/clang/Basic/CodeGenOptions.def1
-rw-r--r--clang/include/clang/Driver/CC1Options.td4
-rw-r--r--clang/include/clang/Driver/Options.td2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp31
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp22
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp1
-rw-r--r--clang/test/CodeGen/cfguardtable.c14
-rw-r--r--clang/test/Driver/cl-fallback.c3
-rw-r--r--clang/test/Driver/cl-options.c9
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:'
OpenPOWER on IntegriCloud