]> granicus.if.org Git - clang/commitdiff
clang-cl: Support /guard:cf,nochecks
authorHans Wennborg <hans@hanshq.net>
Fri, 10 Aug 2018 09:49:21 +0000 (09:49 +0000)
committerHans Wennborg <hans@hanshq.net>
Fri, 10 Aug 2018 09:49:21 +0000 (09:49 +0000)
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

include/clang/Driver/CLCompatOptions.td
lib/CodeGen/CodeGenModule.cpp
lib/Driver/ToolChains/Clang.cpp
test/CodeGen/cfguardtable.c [new file with mode: 0644]
test/Driver/cl-options.c

index 92be95212a8f618d2cd2b4234bb84139d00206a5..46435d927467ea1f07dd430f24f7411e7267c722 100644 (file)
@@ -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<"<file or directory>">;
-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-">,
index 8baa7a58429ab4dfefc84591559d2e38ed6d458a..72fa799a541a6137e5fa2959ee1d1fc6539190ab 100644 (file)
@@ -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
index 7685606ecbc8ea0a534860bfffa97e5ddac82896..fc7e8610826ea041032c7df52ee6a4c206c1b3e2 100644 (file)
@@ -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<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)
+      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 (file)
index 0000000..9649292
--- /dev/null
@@ -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}
index 3e2960fc471d4324b748c482285589c19f080b6f..9680560851952df2bb1ac372cacde0f08eabc263 100644 (file)
 // RUN:     /Gr \
 // RUN:     /GS \
 // RUN:     /GT \
-// RUN:     /guard:cf \
-// RUN:     /guard:cf- \
 // RUN:     /GX \
 // RUN:     /Gv \
 // RUN:     /Gz \
 // 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 \