From 06e8ae74b426e03e1e1b11e29894917d21412adf Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Thu, 7 May 2015 18:31:29 +0000 Subject: [PATCH] [SanitizerCoverage] Give clang-cc1 the power to precisly specify needed sanitizier coverage mode. Summary: The next step is to add user-friendly control over these options to driver via -fsanitize-coverage= option. Test Plan: regression test suite Reviewers: kcc Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D9545 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236756 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 14 ++++++++++++ include/clang/Driver/Options.td | 7 +++--- include/clang/Frontend/CodeGenOptions.def | 11 +++++++++- lib/CodeGen/BackendUtil.cpp | 11 ++++++++-- lib/Driver/SanitizerArgs.cpp | 11 +++++++--- lib/Frontend/CompilerInvocation.cpp | 10 +++++++-- test/Driver/fsanitize-coverage.c | 26 +++++++++++++++++++++++ test/Driver/fsanitize.c | 26 ----------------------- 8 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 test/Driver/fsanitize-coverage.c diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 196035e2ef..4db07772f0 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -241,6 +241,20 @@ def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">, HelpText<"Run the BB vectorization passes">; def dependent_lib : Joined<["--"], "dependent-lib=">, HelpText<"Add dependent library">; +def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">, + HelpText<"Sanitizer coverage type">; +def fsanitize_coverage_indirect_calls + : Flag<["-"], "fsanitize-coverage-indirect-calls">, + HelpText<"Enable sanitizer coverage for indirect calls">; +def fsanitize_coverage_trace_bb + : Flag<["-"], "fsanitize-coverage-trace-bb">, + HelpText<"Enable basic block tracing in sanitizer coverage">; +def fsanitize_coverage_trace_cmp + : Flag<["-"], "fsanitize-coverage-trace-cmp">, + HelpText<"Enable cmp instruction tracing in sanitizer coverage">; +def fsanitize_coverage_8bit_counters + : Flag<["-"], "fsanitize-coverage-8bit-counters">, + HelpText<"Enable frequency counters in sanitizer coverage">; //===----------------------------------------------------------------------===// // Dependency Output Options diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index cef5cc3452..38368654d4 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -529,9 +529,10 @@ def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">, Group, HelpText<"Don't use blacklist file for sanitizers">; -def fsanitize_coverage : Joined<["-"], "fsanitize-coverage=">, - Group, Flags<[CC1Option, CoreOption]>, - HelpText<"Enable coverage instrumentation for Sanitizers">; +def fsanitize_coverage + : Joined<["-"], "fsanitize-coverage=">, + Group, Flags<[CoreOption]>, + HelpText<"Specify the type of coverage instrumentation for Sanitizers">; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, Group, Flags<[CC1Option]>, HelpText<"Enable origins tracking in MemorySanitizer">; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index cd42c72068..adf1c879d4 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -110,7 +110,16 @@ CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in ///< MemorySanitizer -CODEGENOPT(SanitizeCoverage, 3, 0) ///< Enable sanitizer coverage instrumentation. +CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage + ///< instrumentation. +CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage + ///< for indirect calls. +CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters + ///< in sanitizer coverage. CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on /// -fsanitize-undefined-trap-on-error CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index c8894553bc..0206ad5838 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -189,7 +189,14 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, const PassManagerBuilderWrapper &BuilderWrapper = static_cast(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - PM.add(createSanitizerCoverageModulePass(CGOpts.SanitizeCoverage)); + SanitizerCoverageOptions Opts; + Opts.CoverageType = + static_cast(CGOpts.SanitizeCoverageType); + Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls; + Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB; + Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp; + Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters; + PM.add(createSanitizerCoverageModulePass(Opts)); } static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, @@ -306,7 +313,7 @@ void EmitAssemblyHelper::CreatePasses() { addBoundsCheckingPass); } - if (CodeGenOpts.SanitizeCoverage) { + if (CodeGenOpts.SanitizeCoverageType) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addSanitizerCoveragePass); PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index f453208503..528b7243c5 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -482,9 +482,14 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, if (AsanFieldPadding) CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + llvm::utostr(AsanFieldPadding))); - if (SanitizeCoverage) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-coverage=" + - llvm::utostr(SanitizeCoverage))); + if (SanitizeCoverage) { + int CoverageType = std::min(SanitizeCoverage, 3); + CmdArgs.push_back(Args.MakeArgString("-fsanitize-coverage-type=" + + llvm::utostr(CoverageType))); + if (SanitizeCoverage == 4) + CmdArgs.push_back( + Args.MakeArgString("-fsanitize-coverage-indirect-calls")); + } // MSan: Workaround for PR16386. // ASan: This is mainly to help LSan with cases such as // https://code.google.com/p/address-sanitizer/issues/detail?id=373 diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 79f80d0df7..d0cb17baaa 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -529,8 +529,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file); - Opts.SanitizeCoverage = - getLastArgIntValue(Args, OPT_fsanitize_coverage, 0, Diags); + Opts.SanitizeCoverageType = + getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags); + Opts.SanitizeCoverageIndirectCalls = + Args.hasArg(OPT_fsanitize_coverage_indirect_calls); + Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb); + Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp); + Opts.SanitizeCoverage8bitCounters = + Args.hasArg(OPT_fsanitize_coverage_8bit_counters); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeUndefinedTrapOnError = diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c new file mode 100644 index 0000000000..5e71901024 --- /dev/null +++ b/test/Driver/fsanitize-coverage.c @@ -0,0 +1,26 @@ +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-0 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-0 +// CHECK-SANITIZE-COVERAGE-0-NOT: fsanitize-coverage-type +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=bool -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=dataflow -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 +// CHECK-SANITIZE-COVERAGE-1: fsanitize-coverage-type=1 +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=4 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-4 +// CHECK-SANITIZE-COVERAGE-4: fsanitize-coverage-type=3 +// CHECK-SANITIZE-COVERAGE-4: fsanitize-coverage-indirect-calls +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=5 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-5 +// CHECK-SANITIZE-COVERAGE-5: error: invalid value '5' in '-fsanitize-coverage=5' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-UNUSED +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-UNUSED +// CHECK-SANITIZE-COVERAGE-UNUSED: argument unused during compilation: '-fsanitize-coverage=1' + +// RUN: %clang_cl -fsanitize=address -fsanitize-coverage=1 -c -### -- %s 2>&1 | FileCheck %s -check-prefix=CLANG-CL-COVERAGE +// CLANG-CL-COVERAGE-NOT: error: +// CLANG-CL-COVERAGE-NOT: warning: +// CLANG-CL-COVERAGE-NOT: argument unused +// CLANG-CL-COVERAGE-NOT: unknown argument +// CLANG-CL-COVERAGE: -fsanitize=address +// CLANG-CL-COVERAGE: -fsanitize-coverage-type=1 diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 280b6e6e31..a36e12abfd 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -93,24 +93,6 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-memory-track-origins=3 -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TRACK-ORIGINS-3 // CHECK-TRACK-ORIGINS-3: error: invalid value '3' in '-fsanitize-memory-track-origins=3' -// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-0 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-0 -// CHECK-SANITIZE-COVERAGE-0-NOT: fsanitize-coverage -// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=bool -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=dataflow -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1 -// CHECK-SANITIZE-COVERAGE-1: fsanitize-coverage=1 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=4 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-4 -// CHECK-SANITIZE-COVERAGE-4: fsanitize-coverage=4 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=5 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-5 -// CHECK-SANITIZE-COVERAGE-5: error: invalid value '5' in '-fsanitize-coverage=5' -// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-UNUSED -// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-UNUSED -// CHECK-SANITIZE-COVERAGE-UNUSED: argument unused during compilation: '-fsanitize-coverage=1' - // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-field-padding=0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FIELD-PADDING-0 // CHECK-ASAN-FIELD-PADDING-0-NOT: -fsanitize-address-field-padding // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-field-padding=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FIELD-PADDING-1 @@ -228,11 +210,3 @@ // RUN: %clang_cl -fsanitize=address -c -MDd -MD -### -- %s 2>&1 | FileCheck %s -check-prefix=CHECK-ASAN-RELEASERTL // RUN: %clang_cl -fsanitize=address -c -LDd -LD -### -- %s 2>&1 | FileCheck %s -check-prefix=CHECK-ASAN-RELEASERTL // CHECK-ASAN-RELEASERTL-NOT: error: invalid argument - -// RUN: %clang_cl -fsanitize=address -fsanitize-coverage=1 -c -### -- %s 2>&1 | FileCheck %s -check-prefix=CLANG-CL-COVERAGE -// CLANG-CL-COVERAGE-NOT: error: -// CLANG-CL-COVERAGE-NOT: warning: -// CLANG-CL-COVERAGE-NOT: argument unused -// CLANG-CL-COVERAGE-NOT: unknown argument -// CLANG-CL-COVERAGE: -fsanitize=address -// CLANG-CL-COVERAGE: -fsanitize-coverage=1 -- 2.50.1