From a3e7a4fe794d510ea65eae30fffd63f66418bbb6 Mon Sep 17 00:00:00 2001 From: Derek Bruening Date: Thu, 21 Apr 2016 21:32:04 +0000 Subject: [PATCH] [esan] EfficiencySanitizer driver flags 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 --- include/clang/Basic/Sanitizers.def | 5 +++ include/clang/Driver/SanitizerArgs.h | 3 ++ lib/CodeGen/BackendUtil.cpp | 18 +++++++++ lib/Driver/SanitizerArgs.cpp | 11 +++++- lib/Driver/ToolChains.cpp | 4 ++ lib/Driver/Tools.cpp | 2 + lib/Lex/PPMacroExpansion.cpp | 2 + test/Driver/esan.c | 9 +++++ test/Driver/fsanitize.c | 37 +++++++++++++++++++ test/Driver/sanitize_unwind_tables.c | 1 + test/Driver/sanitizer-ld.c | 7 ++++ .../has_feature_efficiency_sanitizer.cpp | 11 ++++++ 12 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/Driver/esan.c create mode 100644 test/Lexer/has_feature_efficiency_sanitizer.cpp diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 4b68593629..3bf289ca7d 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -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) diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index 072ddee17f..c365644a4b 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -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; diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index f09182f565..148c0a09f9 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -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(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) diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index ff9a0b4ca4..50a93a8d43 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -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); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 8420fd8fbd..f02b5fb0b9 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -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; } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index e1d0ffb296..74ac807056 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -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++, diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 0655c1f08e..df4fdbaa96 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -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 index 0000000000..834daec559 --- /dev/null +++ b/test/Driver/esan.c @@ -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 diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index d9bf342f3f..7c1b9be793 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -83,6 +83,21 @@ // 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' @@ -256,6 +271,26 @@ // 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 @@ -353,6 +388,8 @@ // 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}} diff --git a/test/Driver/sanitize_unwind_tables.c b/test/Driver/sanitize_unwind_tables.c index 8b78899666..43a922d8fb 100644 --- a/test/Driver/sanitize_unwind_tables.c +++ b/test/Driver/sanitize_unwind_tables.c @@ -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 diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index 6b7dde1569..733cfcc8a1 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -424,3 +424,10 @@ // 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 index 0000000000..a1b0f06102 --- /dev/null +++ b/test/Lexer/has_feature_efficiency_sanitizer.cpp @@ -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 -- 2.50.1