From 8b5a561a18eb053740c5308722046716eb70156b Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 11 Nov 2014 22:15:07 +0000 Subject: [PATCH] Introduce -fsanitize-coverage=N flag Summary: This change makes the asan-coverge (formerly -mllvm -asan-coverge) accessible via a clang flag. Companion patch to LLVM is http://reviews.llvm.org/D6152 Test Plan: regression tests, chromium Reviewers: samsonov Reviewed By: samsonov Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D6153 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@221719 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 3 +++ include/clang/Driver/SanitizerArgs.h | 1 + include/clang/Frontend/CodeGenOptions.def | 1 + lib/CodeGen/BackendUtil.cpp | 15 +++++++++++++++ lib/Driver/SanitizerArgs.cpp | 15 +++++++++++++++ lib/Frontend/CompilerInvocation.cpp | 2 ++ test/Driver/fsanitize.c | 10 ++++++++++ 7 files changed, 47 insertions(+) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index db0fce98b1..8b4aba4ebd 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -519,6 +519,9 @@ 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]>, + HelpText<"Enable 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/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index 46fd4b6d5e..6a1a78adbd 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -48,6 +48,7 @@ class SanitizerArgs { unsigned Kind; std::string BlacklistFile; + int SanitizeCoverage; int MsanTrackOrigins; int AsanFieldPadding; bool AsanZeroBaseShadow; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 8a9ddd4422..8e0c78a7bd 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -107,6 +107,7 @@ 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(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 57675b1fe1..41f21312bc 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -179,6 +179,14 @@ static void addBoundsCheckingPass(const PassManagerBuilder &Builder, PM.add(createBoundsCheckingPass()); } +static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, + PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast(Builder); + const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); + PM.add(createSanitizerCoverageModulePass(CGOpts.SanitizeCoverage)); +} + static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, PassManagerBase &PM) { PM.add(createAddressSanitizerFunctionPass()); @@ -274,6 +282,13 @@ void EmitAssemblyHelper::CreatePasses() { addBoundsCheckingPass); } + if (CodeGenOpts.SanitizeCoverage) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addSanitizerCoveragePass); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addSanitizerCoveragePass); + } + if (LangOpts.Sanitize.has(SanitizerKind::Address)) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addAddressSanitizerPasses); diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index a920ff9567..24057c5cc1 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -24,6 +24,7 @@ using namespace llvm::opt; void SanitizerArgs::clear() { Kind = 0; BlacklistFile = ""; + SanitizeCoverage = 0; MsanTrackOrigins = 0; AsanFieldPadding = 0; AsanZeroBaseShadow = false; @@ -159,6 +160,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } } + // Parse -fsanitize-coverage=N + if (NeedsAsan) { // Currently asan is required. + if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) { + StringRef S = A->getValue(); + // Legal values are 0..4. + if (S.getAsInteger(0, SanitizeCoverage) || SanitizeCoverage < 0 || + SanitizeCoverage > 4) + D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << S; + } + } + if (NeedsAsan) { AsanSharedRuntime = Args.hasArg(options::OPT_shared_libasan) || @@ -219,6 +231,9 @@ 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))); // Workaround for PR16386. if (needsMsanRt()) CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new")); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index add0c9bdb2..6531a403f4 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -488,6 +488,8 @@ 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.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeUndefinedTrapOnError = diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 8fec80d697..b01b3f0eaa 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -80,6 +80,16 @@ // 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 +// 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=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 -- 2.40.0