From: Kostya Serebryany Date: Sat, 21 Mar 2015 01:29:36 +0000 (+0000) Subject: [sanitizer] experimental tracing for cmp instructions X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=a1ea57a185a254102bffbca5f531353678f7beaf [sanitizer] experimental tracing for cmp instructions git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232873 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 9f534e4f51d..289675ec834 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -59,6 +59,7 @@ 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"; +static const char *const kSanCovTraceCmp = "__sanitizer_cov_trace_cmp"; static const char *const kSanCovModuleCtorName = "sancov.module_ctor"; static const uint64_t kSanCtorAndDtorPriority = 2; @@ -80,6 +81,12 @@ static cl::opt "callbacks at every basic block"), cl::Hidden, cl::init(false)); +static cl::opt + ClExperimentalCMPTracing("sanitizer-coverage-experimental-trace-compares", + cl::desc("Experimental tracing of CMP and similar " + "instructions"), + cl::Hidden, cl::init(false)); + // Experimental 8-bit counters used as an additional search heuristic during // coverage-guided fuzzing. // The counters are not thread-friendly: @@ -107,8 +114,8 @@ class SanitizerCoverageModule : public ModulePass { private: void InjectCoverageForIndirectCalls(Function &F, ArrayRef IndirCalls); - bool InjectCoverage(Function &F, ArrayRef AllBlocks, - ArrayRef IndirCalls); + void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets); + bool InjectCoverage(Function &F, ArrayRef AllBlocks); void SetNoSanitizeMetada(Instruction *I); void InjectCoverageAtBlock(Function &F, BasicBlock &BB, bool UseCalls); unsigned NumberOfInstrumentedBlocks() { @@ -119,9 +126,11 @@ class SanitizerCoverageModule : public ModulePass { Function *SanCovIndirCallFunction; Function *SanCovModuleInit; Function *SanCovTraceEnter, *SanCovTraceBB; + Function *SanCovTraceCmpFunction; InlineAsm *EmptyAsm; - Type *IntptrTy; + Type *IntptrTy, *Int64Ty; LLVMContext *C; + const DataLayout *DL; GlobalVariable *GuardArray; GlobalVariable *EightBitCounterArray; @@ -144,12 +153,13 @@ static Function *checkInterfaceFunction(Constant *FuncOrBitcast) { bool SanitizerCoverageModule::runOnModule(Module &M) { if (!CoverageLevel) return false; C = &(M.getContext()); - auto &DL = M.getDataLayout(); - IntptrTy = Type::getIntNTy(*C, DL.getPointerSizeInBits()); + DL = &M.getDataLayout(); + IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); + Int64Ty = IRB.getInt64Ty(); Function *CtorFunc = Function::Create(FunctionType::get(VoidTy, false), @@ -163,6 +173,9 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr)); SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction( kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); + SanCovTraceCmpFunction = checkInterfaceFunction(M.getOrInsertFunction( + kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr)); + SanCovModuleInit = checkInterfaceFunction(M.getOrInsertFunction( kSanCovModuleInitName, Type::getVoidTy(*C), Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy, nullptr)); @@ -252,23 +265,28 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { SplitAllCriticalEdges(F); SmallVector IndirCalls; SmallVector AllBlocks; + SmallVector CmpTraceTargets; for (auto &BB : F) { AllBlocks.push_back(&BB); - if (CoverageLevel >= 4) - for (auto &Inst : BB) { + for (auto &Inst : BB) { + if (CoverageLevel >= 4) { CallSite CS(&Inst); if (CS && !CS.getCalledFunction()) IndirCalls.push_back(&Inst); } + if (ClExperimentalCMPTracing) + if (isa(&Inst)) + CmpTraceTargets.push_back(&Inst); + } } - InjectCoverage(F, AllBlocks, IndirCalls); + InjectCoverage(F, AllBlocks); + InjectCoverageForIndirectCalls(F, IndirCalls); + InjectTraceForCmp(F, CmpTraceTargets); return true; } -bool -SanitizerCoverageModule::InjectCoverage(Function &F, - ArrayRef AllBlocks, - ArrayRef IndirCalls) { +bool SanitizerCoverageModule::InjectCoverage(Function &F, + ArrayRef AllBlocks) { if (!CoverageLevel) return false; if (CoverageLevel == 1) { @@ -278,7 +296,6 @@ SanitizerCoverageModule::InjectCoverage(Function &F, InjectCoverageAtBlock(F, *BB, ClCoverageBlockThreshold < AllBlocks.size()); } - InjectCoverageForIndirectCalls(F, IndirCalls); return true; } @@ -310,6 +327,26 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls( } } +void SanitizerCoverageModule::InjectTraceForCmp( + Function &F, ArrayRef CmpTraceTargets) { + if (!ClExperimentalCMPTracing) return; + for (auto I : CmpTraceTargets) { + if (ICmpInst *ICMP = dyn_cast(I)) { + IRBuilder<> IRB(ICMP); + Value *A0 = ICMP->getOperand(0); + Value *A1 = ICMP->getOperand(1); + if (!A0->getType()->isIntegerTy()) continue; + uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType()); + // __sanitizer_cov_indir_call((type_size << 32) | predicate, A0, A1); + IRB.CreateCall3( + SanCovTraceCmpFunction, + ConstantInt::get(Int64Ty, (TypeSize << 32) | ICMP->getPredicate()), + IRB.CreateIntCast(A0, Int64Ty, true), + IRB.CreateIntCast(A1, Int64Ty, true)); + } + } +} + void SanitizerCoverageModule::SetNoSanitizeMetada(Instruction *I) { I->setMetadata( I->getParent()->getParent()->getParent()->getMDKindID("nosanitize"), diff --git a/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll b/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll new file mode 100644 index 00000000000..a37cdec985e --- /dev/null +++ b/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll @@ -0,0 +1,13 @@ +; Test -sanitizer-coverage-experimental-trace-compares=1 +; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-experimental-trace-compares=1 -S | FileCheck %s --check-prefix=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" +define i32 @foo(i32 %a, i32 %b) #0 { +entry: + %cmp = icmp slt i32 %a, %b +; CHECK: call void @__sanitizer_cov_trace_cmp +; CHECK-NEXT: icmp slt i32 %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +}