]> granicus.if.org Git - clang/commitdiff
[esan] EfficiencySanitizer driver flags
authorDerek Bruening <bruening@google.com>
Thu, 21 Apr 2016 21:32:04 +0000 (21:32 +0000)
committerDerek Bruening <bruening@google.com>
Thu, 21 Apr 2016 21:32:04 +0000 (21:32 +0000)
Summary:
Adds a framework to enable the instrumentation pass for the new
EfficiencySanitizer ("esan") family of tools.  Adds a flag for esan's
cache fragmentation tool via -fsanitize=efficiency-cache-frag.
Adds appropriate tests for the new flag.

Reviewers: eugenis, vitalybuka, aizatsky, filcab

Subscribers: filcab, kubabrecka, llvm-commits, zhaoqin, kcc

Differential Revision: http://reviews.llvm.org/D19169

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@267059 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/Basic/Sanitizers.def
include/clang/Driver/SanitizerArgs.h
lib/CodeGen/BackendUtil.cpp
lib/Driver/SanitizerArgs.cpp
lib/Driver/ToolChains.cpp
lib/Driver/Tools.cpp
lib/Lex/PPMacroExpansion.cpp
test/Driver/esan.c [new file with mode: 0644]
test/Driver/fsanitize.c
test/Driver/sanitize_unwind_tables.c
test/Driver/sanitizer-ld.c
test/Lexer/has_feature_efficiency_sanitizer.cpp [new file with mode: 0644]

index 4b685936291099ce3b3c5db970842a1276173942..3bf289ca7d035caaa6dfdd56bc8cd855e9f959f9 100644 (file)
@@ -114,6 +114,11 @@ SANITIZER_GROUP("integer", Integer,
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
 
+// EfficiencySanitizer
+SANITIZER("efficiency-cache-frag", EfficiencyCacheFrag)
+// Meta-group only used internally.
+SANITIZER_GROUP("efficiency-all", Efficiency, EfficiencyCacheFrag)
+
 // Magic group, containing all sanitizers. For example, "-fno-sanitize=all"
 // can be used to disable all the sanitizers.
 SANITIZER_GROUP("all", All, ~0ULL)
index 072ddee17f7cb116c6b6975d63931333c5a44191..c365644a4b88eabf2325d76c349a73d04e383528 100644 (file)
@@ -58,6 +58,9 @@ class SanitizerArgs {
   bool needsCfiRt() const;
   bool needsCfiDiagRt() const;
   bool needsStatsRt() const { return Stats; }
+  bool needsEsanRt() const {
+    return Sanitizers.hasOneOf(SanitizerKind::Efficiency);
+  }
 
   bool requiresPIE() const;
   bool needsUnwindTables() const;
index f09182f565d62c0f2d72073600e526bf1649aae0..148c0a09f9eb98769f922b87d5ece488b8b1688d 100644 (file)
@@ -248,6 +248,17 @@ static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder,
   PM.add(createDataFlowSanitizerPass(LangOpts.SanitizerBlacklistFiles));
 }
 
+static void addEfficiencySanitizerPass(const PassManagerBuilder &Builder,
+                                       legacy::PassManagerBase &PM) {
+  const PassManagerBuilderWrapper &BuilderWrapper =
+      static_cast<const PassManagerBuilderWrapper&>(Builder);
+  const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
+  EfficiencySanitizerOptions Opts;
+  if (LangOpts.Sanitize.has(SanitizerKind::EfficiencyCacheFrag))
+    Opts.ToolType = EfficiencySanitizerOptions::ESAN_CacheFrag;
+  PM.add(createEfficiencySanitizerPass(Opts));
+}
+
 static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
                                          const CodeGenOptions &CodeGenOpts) {
   TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
@@ -407,6 +418,13 @@ void EmitAssemblyHelper::CreatePasses(ModuleSummaryIndex *ModuleSummary) {
                            addDataFlowSanitizerPass);
   }
 
+  if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) {
+    PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+                           addEfficiencySanitizerPass);
+    PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+                           addEfficiencySanitizerPass);
+  }
+
   // Set up the per-function pass manager.
   legacy::FunctionPassManager *FPM = getPerFunctionPasses();
   if (CodeGenOpts.VerifyModule)
index ff9a0b4ca4af5f3c80e4e289db9061e7f101828b..50a93a8d431c0723739262a4d8c661fbe922020d 100644 (file)
@@ -311,7 +311,12 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
       std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
       std::make_pair(KernelAddress, Leak),
       std::make_pair(KernelAddress, Thread),
-      std::make_pair(KernelAddress, Memory)};
+      std::make_pair(KernelAddress, Memory),
+      std::make_pair(Efficiency, Address),
+      std::make_pair(Efficiency, Leak),
+      std::make_pair(Efficiency, Thread),
+      std::make_pair(Efficiency, Memory),
+      std::make_pair(Efficiency, KernelAddress)};
   for (auto G : IncompatibleGroups) {
     SanitizerMask Group = G.first;
     if (Kinds & Group) {
@@ -695,6 +700,10 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
     if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
         0 == strcmp("all", Value))
       Kind = 0;
+    // Similarly, don't accept -fsanitize=efficiency-all.
+    else if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
+        0 == strcmp("efficiency-all", Value))
+      Kind = 0;
     else
       Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
 
index 8420fd8fbd6e8b4451d9a029e4de4506b52ab930..f02b5fb0b9ef06b25daf41b10347f3f6fe7ef04c 100644 (file)
@@ -422,6 +422,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
                       /*AlwaysLink=*/true);
     AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
   }
+  if (Sanitize.needsEsanRt())
+    AddLinkSanitizerLibArgs(Args, CmdArgs, "esan");
 
   // Otherwise link libSystem, then the dynamic runtime library, and finally any
   // target specific static runtime library.
@@ -4152,6 +4154,8 @@ SanitizerMask Linux::getSupportedSanitizers() const {
     Res |= SanitizerKind::Thread;
   if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64)
     Res |= SanitizerKind::Memory;
+  if (IsX86_64)
+    Res |= SanitizerKind::Efficiency;
   if (IsX86 || IsX86_64) {
     Res |= SanitizerKind::Function;
   }
index e1d0ffb296822165ce268d27a84b45ef15ef7686..74ac807056125bf3c767bab87680cedf49171376 100644 (file)
@@ -3013,6 +3013,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
     NonWholeStaticRuntimes.push_back("stats");
     RequiredSymbols.push_back("__sanitizer_stats_register");
   }
+  if (SanArgs.needsEsanRt())
+    StaticRuntimes.push_back("esan");
 }
 
 // Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
index 0655c1f08e19e87cac893cd5d21962fbf3d3d5c0..df4fdbaa96e6021fe12a0669ec7c16b1628a3756 100644 (file)
@@ -1093,6 +1093,8 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
       .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))
       .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread))
       .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
+      .Case("efficiency_sanitizer",
+            LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
       // Objective-C features
       .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
       .Case("objc_arc", LangOpts.ObjCAutoRefCount)
diff --git a/test/Driver/esan.c b/test/Driver/esan.c
new file mode 100644 (file)
index 0000000..834daec
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang     -target x86_64-unknown-linux -fsanitize=efficiency-cache-frag %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=efficiency-cache-frag %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=efficiency-cache-frag %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=efficiency-cache-frag %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang     -target x86_64-unknown-linux -fsanitize=efficiency-cache-frag  %s -S -emit-llvm -o - | FileCheck %s
+// Verify that -fsanitize=efficiency-cache-frag invokes esan instrumentation.
+
+int foo(int *a) { return *a; }
+// CHECK: __esan_init
index d9bf342f3f9d225db9b90ca13950f06f1b041ea4..7c1b9be793a5d0c4f8b24e7af9b950c4908a5266 100644 (file)
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL
 // CHECK-SANKA-SANL: '-fsanitize=kernel-address' not allowed with '-fsanitize=leak'
 
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANA
+// CHECK-SANE-SANA: '-fsanitize=efficiency-cache-frag' not allowed with '-fsanitize=address'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANL
+// CHECK-SANE-SANL: '-fsanitize=efficiency-cache-frag' not allowed with '-fsanitize=leak'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,thread -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANT
+// CHECK-SANE-SANT: '-fsanitize=efficiency-cache-frag' not allowed with '-fsanitize=thread'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANM
+// CHECK-SANE-SANM: '-fsanitize=efficiency-cache-frag' not allowed with '-fsanitize=memory'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKA
+// CHECK-SANE-SANKA: '-fsanitize=efficiency-cache-frag' not allowed with '-fsanitize=kernel-address'
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS
 // CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins'
 
 // RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD
 // CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd'
 
+// RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86
+// CHECK-ESAN-X86: error: unsupported option '-fsanitize=efficiency-cache-frag' for target 'i686--linux-gnu'
+
+// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-DARWIN
+// CHECK-ESAN-DARWIN: unsupported option '-fsanitize=efficiency-cache-frag' for target 'x86_64-apple-darwin10'
+
+// RUN: %clang -target i386-apple-darwin -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-I386-DARWIN
+// CHECK-ESAN-I386-DARWIN: unsupported option '-fsanitize=efficiency-cache-frag' for target 'i386-apple-darwin'
+
+// RUN: %clang -target arm-apple-ios -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-ARM-IOS
+// CHECK-ESAN-ARM-IOS: unsupported option '-fsanitize=efficiency-cache-frag' for target 'arm-apple-ios'
+
+// RUN: %clang -target i386-apple-iossimulator -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-I386-IOSSIMULATOR
+// CHECK-ESAN-I386-IOSSIMULATOR: unsupported option '-fsanitize=efficiency-cache-frag' for target 'i386-apple-iossimulator'
+
+// RUN: %clang -target i386-apple-tvossimulator -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-I386-TVOSSIMULATOR
+// CHECK-ESAN-I386-TVOSSIMULATOR: unsupported option '-fsanitize=efficiency-cache-frag' for target 'i386-apple-tvossimulator'
+
+
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
 // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-derived-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST
 // CHECK-MSAN-PS4: unsupported option '-fsanitize=memory' for target 'x86_64-scei-ps4'
 // RUN: %clang -target x86_64-scei-ps4 -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-PS4
 // CHECK-TSAN-PS4: unsupported option '-fsanitize=thread' for target 'x86_64-scei-ps4'
+// RUN: %clang -target x86_64-scei-ps4 -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-PS4
+// CHECK-ESAN-PS4: unsupported option '-fsanitize=efficiency-cache-frag' for target 'x86_64-scei-ps4'
 // RUN: %clang -target x86_64-scei-ps4 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-PS4
 // Make sure there are no *.{o,bc} or -l passed before the ASan library.
 // CHECK-ASAN-PS4-NOT: {{(\.(o|bc)"? |-l).*-lSceDbgAddressSanitizer_stub_weak}}
index 8b7889966657c65c73be8288862516888d2fc89c..43a922d8fbfa0957088bae9db7b0a02468348ff2 100644 (file)
@@ -7,5 +7,6 @@
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=memory %s -### 2>&1 |  FileCheck %s
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread %s -### 2>&1 |  FileCheck %s
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=dataflow %s -### 2>&1 |  FileCheck %s
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 |  FileCheck %s
 
 // CHECK: -munwind-tables
index 6b7dde1569cacf10b240a4b8a26033a6ad16ad0b..733cfcc8a1381792dc29d15403da289af3d9d5cd 100644 (file)
 // RUN:   | FileCheck --check-prefix=CHECK-AUBSAN-PS4 %s
 // CHECK-AUBSAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}"
 // CHECK-AUBSAN-PS4: -lSceDbgAddressSanitizer_stub_weak
+
+// RUN: %clang -fsanitize=efficiency-cache-frag %s -### -o %t.o 2>&1 \
+// RUN:     -target x86_64-unknown-linux \
+// RUN:   | FileCheck --check-prefix=CHECK-ESAN-LINUX %s
+//
+// CHECK-ESAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-ESAN-LINUX: libclang_rt.esan-x86_64.a
diff --git a/test/Lexer/has_feature_efficiency_sanitizer.cpp b/test/Lexer/has_feature_efficiency_sanitizer.cpp
new file mode 100644 (file)
index 0000000..a1b0f06
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -E -fsanitize=efficiency-cache-frag %s -o - | FileCheck --check-prefix=CHECK-ESAN %s
+// RUN: %clang_cc1 -E  %s -o - | FileCheck --check-prefix=CHECK-NO-ESAN %s
+
+#if __has_feature(efficiency_sanitizer)
+int EfficiencySanitizerEnabled();
+#else
+int EfficiencySanitizerDisabled();
+#endif
+
+// CHECK-ESAN: EfficiencySanitizerEnabled
+// CHECK-NO-ESAN: EfficiencySanitizerDisabled