From: Kostya Serebryany Date: Wed, 4 Feb 2015 01:21:45 +0000 (+0000) Subject: [sanitizer] add another workaround for PR 17409: when over a threshold emit coverage... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0013784dd349be98b1ab59431cc82a74ad23194b;p=oota-llvm.git [sanitizer] add another workaround for PR 17409: when over a threshold emit coverage instrumentation as calls. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index afff81cdc59..798cd55f87e 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -55,6 +55,7 @@ using namespace llvm; static const char *const kSanCovModuleInitName = "__sanitizer_cov_module_init"; static const char *const kSanCovName = "__sanitizer_cov"; +static const char *const kSanCovWithCheckName = "__sanitizer_cov_with_check"; static const char *const kSanCovIndirCallName = "__sanitizer_cov_indir_call16"; static const char *const kSanCovTraceEnter = "__sanitizer_cov_trace_func_enter"; static const char *const kSanCovTraceBB = "__sanitizer_cov_trace_basic_block"; @@ -67,11 +68,11 @@ static cl::opt ClCoverageLevel("sanitizer-coverage-level", "4: above plus indirect calls"), cl::Hidden, cl::init(0)); -static cl::opt ClCoverageBlockThreshold( +static cl::opt ClCoverageBlockThreshold( "sanitizer-coverage-block-threshold", - cl::desc("Add coverage instrumentation only to the entry block if there " - "are more than this number of blocks."), - cl::Hidden, cl::init(1500)); + cl::desc("Use a callback with a guard check inside it if there are" + " more than this number of blocks."), + cl::Hidden, cl::init(1000)); static cl::opt ClExperimentalTracing("sanitizer-coverage-experimental-tracing", @@ -102,8 +103,9 @@ class SanitizerCoverageModule : public ModulePass { ArrayRef IndirCalls); bool InjectCoverage(Function &F, ArrayRef AllBlocks, ArrayRef IndirCalls); - void InjectCoverageAtBlock(Function &F, BasicBlock &BB); + void InjectCoverageAtBlock(Function &F, BasicBlock &BB, bool UseCalls); Function *SanCovFunction; + Function *SanCovWithCheckFunction; Function *SanCovIndirCallFunction; Function *SanCovModuleInit; Function *SanCovTraceEnter, *SanCovTraceBB; @@ -145,6 +147,8 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { SanCovFunction = checkInterfaceFunction( M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr)); + SanCovWithCheckFunction = checkInterfaceFunction( + M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr)); SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction( kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); SanCovModuleInit = checkInterfaceFunction( @@ -221,12 +225,12 @@ SanitizerCoverageModule::InjectCoverage(Function &F, ArrayRef IndirCalls) { if (!CoverageLevel) return false; - if (CoverageLevel == 1 || - (unsigned)ClCoverageBlockThreshold < AllBlocks.size()) { - InjectCoverageAtBlock(F, F.getEntryBlock()); + if (CoverageLevel == 1) { + InjectCoverageAtBlock(F, F.getEntryBlock(), false); } else { for (auto BB : AllBlocks) - InjectCoverageAtBlock(F, *BB); + InjectCoverageAtBlock(F, *BB, + ClCoverageBlockThreshold < AllBlocks.size()); } InjectCoverageForIndirectCalls(F, IndirCalls); return true; @@ -260,8 +264,8 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls( } } -void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, - BasicBlock &BB) { +void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, + bool UseCalls) { BasicBlock::iterator IP = BB.getFirstInsertionPt(), BE = BB.end(); // Skip static allocas at the top of the entry block so they don't become // dynamic when we split the block. If we used our optimized stack layout, @@ -283,19 +287,23 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, ConstantInt::get(IntptrTy, (1 + SanCovFunction->getNumUses()) * 4)); Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy); - LoadInst *Load = IRB.CreateLoad(GuardP); - Load->setAtomic(Monotonic); - Load->setAlignment(4); - Load->setMetadata(F.getParent()->getMDKindID("nosanitize"), - MDNode::get(*C, None)); - Value *Cmp = IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load); - Instruction *Ins = SplitBlockAndInsertIfThen( - Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000)); - IRB.SetInsertPoint(Ins); - IRB.SetCurrentDebugLocation(EntryLoc); - // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC. - IRB.CreateCall(SanCovFunction, GuardP); - IRB.CreateCall(EmptyAsm); // Avoids callback merge. + if (UseCalls) { + IRB.CreateCall(SanCovWithCheckFunction, GuardP); + } else { + LoadInst *Load = IRB.CreateLoad(GuardP); + Load->setAtomic(Monotonic); + Load->setAlignment(4); + Load->setMetadata(F.getParent()->getMDKindID("nosanitize"), + MDNode::get(*C, None)); + Value *Cmp = IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load); + Instruction *Ins = SplitBlockAndInsertIfThen( + Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000)); + IRB.SetInsertPoint(Ins); + IRB.SetCurrentDebugLocation(EntryLoc); + // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC. + IRB.CreateCall(SanCovFunction, GuardP); + IRB.CreateCall(EmptyAsm); // Avoids callback merge. + } if (ClExperimentalTracing) { // Experimental support for tracing. diff --git a/test/Instrumentation/SanitizerCoverage/coverage.ll b/test/Instrumentation/SanitizerCoverage/coverage.ll index ae93a0b2e39..ed249c1d3e4 100644 --- a/test/Instrumentation/SanitizerCoverage/coverage.ll +++ b/test/Instrumentation/SanitizerCoverage/coverage.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s --check-prefix=CHECK1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s --check-prefix=CHECK2 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=10 -S | FileCheck %s --check-prefix=CHECK2 -; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=1 -S | FileCheck %s --check-prefix=CHECK1 +; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=1 -S | FileCheck %s --check-prefix=CHECK_WITH_CHECK ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-block-threshold=10 -S | FileCheck %s --check-prefix=CHECK3 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -S | FileCheck %s --check-prefix=CHECK4 @@ -12,7 +12,7 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=10 \ ; RUN: -S | FileCheck %s --check-prefix=CHECK2 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=1 \ -; RUN: -S | FileCheck %s --check-prefix=CHECK1 +; RUN: -S | FileCheck %s --check-prefix=CHECK_WITH_CHECK target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" @@ -50,6 +50,9 @@ entry: ; CHECK1: call void @__sanitizer_cov_module_init({{.*}}, i64 2) ; CHECK1: ret +; CHECK_WITH_CHECK-LABEL: define void @foo +; CHECK_WITH_CHECK: __sanitizer_cov_with_check +; CHECK_WITH_CHECK: ret void ; CHECK2-LABEL: define void @foo ; CHECK2: call void @__sanitizer_cov