diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp | 319 |
1 files changed, 247 insertions, 72 deletions
diff --git a/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 7d40447..5b4b1fb 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -67,11 +67,23 @@ static const char *const SanCovTraceEnterName = static const char *const SanCovTraceBBName = "__sanitizer_cov_trace_basic_block"; static const char *const SanCovTracePCName = "__sanitizer_cov_trace_pc"; -static const char *const SanCovTraceCmpName = "__sanitizer_cov_trace_cmp"; +static const char *const SanCovTraceCmp1 = "__sanitizer_cov_trace_cmp1"; +static const char *const SanCovTraceCmp2 = "__sanitizer_cov_trace_cmp2"; +static const char *const SanCovTraceCmp4 = "__sanitizer_cov_trace_cmp4"; +static const char *const SanCovTraceCmp8 = "__sanitizer_cov_trace_cmp8"; +static const char *const SanCovTraceDiv4 = "__sanitizer_cov_trace_div4"; +static const char *const SanCovTraceDiv8 = "__sanitizer_cov_trace_div8"; +static const char *const SanCovTraceGep = "__sanitizer_cov_trace_gep"; static const char *const SanCovTraceSwitchName = "__sanitizer_cov_trace_switch"; static const char *const SanCovModuleCtorName = "sancov.module_ctor"; static const uint64_t SanCtorAndDtorPriority = 2; +static const char *const SanCovTracePCGuardSection = "__sancov_guards"; +static const char *const SanCovTracePCGuardName = + "__sanitizer_cov_trace_pc_guard"; +static const char *const SanCovTracePCGuardInitName = + "__sanitizer_cov_trace_pc_guard_init"; + static cl::opt<int> ClCoverageLevel( "sanitizer-coverage-level", cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, " @@ -95,11 +107,22 @@ static cl::opt<bool> ClExperimentalTracePC("sanitizer-coverage-trace-pc", cl::desc("Experimental pc tracing"), cl::Hidden, cl::init(false)); +static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard", + cl::desc("pc tracing with a guard"), + cl::Hidden, cl::init(false)); + static cl::opt<bool> - ClExperimentalCMPTracing("sanitizer-coverage-experimental-trace-compares", - cl::desc("Experimental tracing of CMP and similar " - "instructions"), - cl::Hidden, cl::init(false)); + ClCMPTracing("sanitizer-coverage-trace-compares", + cl::desc("Tracing of CMP and similar instructions"), + cl::Hidden, cl::init(false)); + +static cl::opt<bool> ClDIVTracing("sanitizer-coverage-trace-divs", + cl::desc("Tracing of DIV instructions"), + cl::Hidden, cl::init(false)); + +static cl::opt<bool> ClGEPTracing("sanitizer-coverage-trace-geps", + cl::desc("Tracing of GEP instructions"), + cl::Hidden, cl::init(false)); static cl::opt<bool> ClPruneBlocks("sanitizer-coverage-prune-blocks", @@ -147,9 +170,12 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { Options.CoverageType = std::max(Options.CoverageType, CLOpts.CoverageType); Options.IndirectCalls |= CLOpts.IndirectCalls; Options.TraceBB |= ClExperimentalTracing; - Options.TraceCmp |= ClExperimentalCMPTracing; + Options.TraceCmp |= ClCMPTracing; + Options.TraceDiv |= ClDIVTracing; + Options.TraceGep |= ClGEPTracing; Options.Use8bitCounters |= ClUse8bitCounters; Options.TracePC |= ClExperimentalTracePC; + Options.TracePCGuard |= ClTracePCGuard; return Options; } @@ -163,7 +189,7 @@ public: bool runOnModule(Module &M) override; bool runOnFunction(Function &F); static char ID; // Pass identification, replacement for typeid - const char *getPassName() const override { return "SanitizerCoverageModule"; } + StringRef getPassName() const override { return "SanitizerCoverageModule"; } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<DominatorTreeWrapperPass>(); @@ -174,11 +200,17 @@ private: void InjectCoverageForIndirectCalls(Function &F, ArrayRef<Instruction *> IndirCalls); void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets); + void InjectTraceForDiv(Function &F, + ArrayRef<BinaryOperator *> DivTraceTargets); + void InjectTraceForGep(Function &F, + ArrayRef<GetElementPtrInst *> GepTraceTargets); void InjectTraceForSwitch(Function &F, ArrayRef<Instruction *> SwitchTraceTargets); bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks); + void CreateFunctionGuardArray(size_t NumGuards, Function &F); void SetNoSanitizeMetadata(Instruction *I); - void InjectCoverageAtBlock(Function &F, BasicBlock &BB, bool UseCalls); + void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, + bool UseCalls); unsigned NumberOfInstrumentedBlocks() { return SanCovFunction->getNumUses() + SanCovWithCheckFunction->getNumUses() + SanCovTraceBB->getNumUses() + @@ -187,17 +219,21 @@ private: Function *SanCovFunction; Function *SanCovWithCheckFunction; Function *SanCovIndirCallFunction, *SanCovTracePCIndir; - Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC; - Function *SanCovTraceCmpFunction; + Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC, *SanCovTracePCGuard; + Function *SanCovTraceCmpFunction[4]; + Function *SanCovTraceDivFunction[2]; + Function *SanCovTraceGepFunction; Function *SanCovTraceSwitchFunction; InlineAsm *EmptyAsm; - Type *IntptrTy, *Int64Ty, *Int64PtrTy; + Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy; Module *CurModule; LLVMContext *C; const DataLayout *DL; GlobalVariable *GuardArray; + GlobalVariable *FunctionGuardArray; // for trace-pc-guard. GlobalVariable *EightBitCounterArray; + bool HasSancovGuardsSection; SanitizerCoverageOptions Options; }; @@ -210,13 +246,16 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { C = &(M.getContext()); DL = &M.getDataLayout(); CurModule = &M; + HasSancovGuardsSection = false; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); + IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); - Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); + Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int64Ty = IRB.getInt64Ty(); + Int32Ty = IRB.getInt32Ty(); SanCovFunction = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovName, VoidTy, Int32PtrTy, nullptr)); @@ -227,9 +266,28 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { SanCovIndirCallFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); - SanCovTraceCmpFunction = + SanCovTraceCmpFunction[0] = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + SanCovTraceCmp1, VoidTy, IRB.getInt8Ty(), IRB.getInt8Ty(), nullptr)); + SanCovTraceCmpFunction[1] = checkSanitizerInterfaceFunction( + M.getOrInsertFunction(SanCovTraceCmp2, VoidTy, IRB.getInt16Ty(), + IRB.getInt16Ty(), nullptr)); + SanCovTraceCmpFunction[2] = checkSanitizerInterfaceFunction( + M.getOrInsertFunction(SanCovTraceCmp4, VoidTy, IRB.getInt32Ty(), + IRB.getInt32Ty(), nullptr)); + SanCovTraceCmpFunction[3] = checkSanitizerInterfaceFunction(M.getOrInsertFunction( - SanCovTraceCmpName, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr)); + SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty, nullptr)); + + SanCovTraceDivFunction[0] = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + SanCovTraceDiv4, VoidTy, IRB.getInt32Ty(), nullptr)); + SanCovTraceDivFunction[1] = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + SanCovTraceDiv8, VoidTy, Int64Ty, nullptr)); + SanCovTraceGepFunction = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + SanCovTraceGep, VoidTy, IntptrTy, nullptr)); SanCovTraceSwitchFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy, nullptr)); @@ -241,6 +299,8 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { SanCovTracePC = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr)); + SanCovTracePCGuard = checkSanitizerInterfaceFunction(M.getOrInsertFunction( + SanCovTracePCGuardName, VoidTy, Int32PtrTy, nullptr)); SanCovTraceEnter = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr)); SanCovTraceBB = checkSanitizerInterfaceFunction( @@ -251,9 +311,10 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { Type *Int32Ty = IRB.getInt32Ty(); Type *Int8Ty = IRB.getInt8Ty(); - GuardArray = - new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, - nullptr, "__sancov_gen_cov_tmp"); + if (!Options.TracePCGuard) + GuardArray = + new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, + nullptr, "__sancov_gen_cov_tmp"); if (Options.Use8bitCounters) EightBitCounterArray = new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage, @@ -264,17 +325,20 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { auto N = NumberOfInstrumentedBlocks(); - // Now we know how many elements we need. Create an array of guards - // with one extra element at the beginning for the size. - Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1); - GlobalVariable *RealGuardArray = new GlobalVariable( - M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage, - Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov"); - - // Replace the dummy array with the real one. - GuardArray->replaceAllUsesWith( - IRB.CreatePointerCast(RealGuardArray, Int32PtrTy)); - GuardArray->eraseFromParent(); + GlobalVariable *RealGuardArray = nullptr; + if (!Options.TracePCGuard) { + // Now we know how many elements we need. Create an array of guards + // with one extra element at the beginning for the size. + Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1); + RealGuardArray = new GlobalVariable( + M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage, + Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov"); + + // Replace the dummy array with the real one. + GuardArray->replaceAllUsesWith( + IRB.CreatePointerCast(RealGuardArray, Int32PtrTy)); + GuardArray->eraseFromParent(); + } GlobalVariable *RealEightBitCounterArray; if (Options.Use8bitCounters) { @@ -293,11 +357,30 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { // Create variable for module (compilation unit) name Constant *ModNameStrConst = ConstantDataArray::getString(M.getContext(), M.getName(), true); - GlobalVariable *ModuleName = - new GlobalVariable(M, ModNameStrConst->getType(), true, - GlobalValue::PrivateLinkage, ModNameStrConst); + GlobalVariable *ModuleName = new GlobalVariable( + M, ModNameStrConst->getType(), true, GlobalValue::PrivateLinkage, + ModNameStrConst, "__sancov_gen_modname"); + if (Options.TracePCGuard) { + if (HasSancovGuardsSection) { + Function *CtorFunc; + std::string SectionName(SanCovTracePCGuardSection); + GlobalVariable *Bounds[2]; + const char *Prefix[2] = {"__start_", "__stop_"}; + for (int i = 0; i < 2; i++) { + Bounds[i] = new GlobalVariable(M, Int32PtrTy, false, + GlobalVariable::ExternalLinkage, nullptr, + Prefix[i] + SectionName); + Bounds[i]->setVisibility(GlobalValue::HiddenVisibility); + } + std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( + M, SanCovModuleCtorName, SanCovTracePCGuardInitName, + {Int32PtrTy, Int32PtrTy}, + {IRB.CreatePointerCast(Bounds[0], Int32PtrTy), + IRB.CreatePointerCast(Bounds[1], Int32PtrTy)}); - if (!Options.TracePC) { + appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); + } + } else if (!Options.TracePC) { Function *CtorFunc; std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( M, SanCovModuleCtorName, SanCovModuleInitName, @@ -344,6 +427,14 @@ static bool isFullPostDominator(const BasicBlock *BB, static bool shouldInstrumentBlock(const Function& F, const BasicBlock *BB, const DominatorTree *DT, const PostDominatorTree *PDT) { + // Don't insert coverage for unreachable blocks: we will never call + // __sanitizer_cov() for them, so counting them in + // NumberOfInstrumentedBlocks() might complicate calculation of code coverage + // percentage. Also, unreachable instructions frequently have no debug + // locations. + if (isa<UnreachableInst>(BB->getTerminator())) + return false; + if (!ClPruneBlocks || &F.getEntryBlock() == BB) return true; @@ -355,6 +446,13 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { return false; if (F.getName().find(".module_ctor") != std::string::npos) return false; // Should not instrument sanitizer init functions. + if (F.getName().startswith("__sanitizer_")) + return false; // Don't instrument __sanitizer_* callbacks. + // Don't instrument MSVC CRT configuration helpers. They may run before normal + // initialization. + if (F.getName() == "__local_stdio_printf_options" || + F.getName() == "__local_stdio_scanf_options") + return false; // Don't instrument functions using SEH for now. Splitting basic blocks like // we do for coverage breaks WinEHPrepare. // FIXME: Remove this when SEH no longer uses landingpad pattern matching. @@ -367,6 +465,8 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { SmallVector<BasicBlock *, 16> BlocksToInstrument; SmallVector<Instruction *, 8> CmpTraceTargets; SmallVector<Instruction *, 8> SwitchTraceTargets; + SmallVector<BinaryOperator *, 8> DivTraceTargets; + SmallVector<GetElementPtrInst *, 8> GepTraceTargets; const DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); @@ -388,28 +488,53 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { if (isa<SwitchInst>(&Inst)) SwitchTraceTargets.push_back(&Inst); } - } + if (Options.TraceDiv) + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&Inst)) + if (BO->getOpcode() == Instruction::SDiv || + BO->getOpcode() == Instruction::UDiv) + DivTraceTargets.push_back(BO); + if (Options.TraceGep) + if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&Inst)) + GepTraceTargets.push_back(GEP); + } } InjectCoverage(F, BlocksToInstrument); InjectCoverageForIndirectCalls(F, IndirCalls); InjectTraceForCmp(F, CmpTraceTargets); InjectTraceForSwitch(F, SwitchTraceTargets); + InjectTraceForDiv(F, DivTraceTargets); + InjectTraceForGep(F, GepTraceTargets); return true; } +void SanitizerCoverageModule::CreateFunctionGuardArray(size_t NumGuards, + Function &F) { + if (!Options.TracePCGuard) return; + HasSancovGuardsSection = true; + ArrayType *ArrayOfInt32Ty = ArrayType::get(Int32Ty, NumGuards); + FunctionGuardArray = new GlobalVariable( + *CurModule, ArrayOfInt32Ty, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(ArrayOfInt32Ty), "__sancov_gen_"); + if (auto Comdat = F.getComdat()) + FunctionGuardArray->setComdat(Comdat); + FunctionGuardArray->setSection(SanCovTracePCGuardSection); +} bool SanitizerCoverageModule::InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks) { + if (AllBlocks.empty()) return false; switch (Options.CoverageType) { case SanitizerCoverageOptions::SCK_None: return false; case SanitizerCoverageOptions::SCK_Function: - InjectCoverageAtBlock(F, F.getEntryBlock(), false); + CreateFunctionGuardArray(1, F); + InjectCoverageAtBlock(F, F.getEntryBlock(), 0, false); return true; default: { bool UseCalls = ClCoverageBlockThreshold < AllBlocks.size(); - for (auto BB : AllBlocks) - InjectCoverageAtBlock(F, *BB, UseCalls); + CreateFunctionGuardArray(AllBlocks.size(), F); + for (size_t i = 0, N = AllBlocks.size(); i < N; i++) + InjectCoverageAtBlock(F, *AllBlocks[i], i, UseCalls); return true; } } @@ -439,7 +564,7 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls( *F.getParent(), Ty, false, GlobalValue::PrivateLinkage, Constant::getNullValue(Ty), "__sancov_gen_callee_cache"); CalleeCache->setAlignment(CacheAlignment); - if (Options.TracePC) + if (Options.TracePC || Options.TracePCGuard) IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy)); else @@ -476,6 +601,11 @@ void SanitizerCoverageModule::InjectTraceForSwitch( C = ConstantExpr::getCast(CastInst::ZExt, It.getCaseValue(), Int64Ty); Initializers.push_back(C); } + std::sort(Initializers.begin() + 2, Initializers.end(), + [](const Constant *A, const Constant *B) { + return cast<ConstantInt>(A)->getLimitedValue() < + cast<ConstantInt>(B)->getLimitedValue(); + }); ArrayType *ArrayOfInt64Ty = ArrayType::get(Int64Ty, Initializers.size()); GlobalVariable *GV = new GlobalVariable( *CurModule, ArrayOfInt64Ty, false, GlobalVariable::InternalLinkage, @@ -487,6 +617,35 @@ void SanitizerCoverageModule::InjectTraceForSwitch( } } +void SanitizerCoverageModule::InjectTraceForDiv( + Function &, ArrayRef<BinaryOperator *> DivTraceTargets) { + for (auto BO : DivTraceTargets) { + IRBuilder<> IRB(BO); + Value *A1 = BO->getOperand(1); + if (isa<ConstantInt>(A1)) continue; + if (!A1->getType()->isIntegerTy()) + continue; + uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType()); + int CallbackIdx = TypeSize == 32 ? 0 : + TypeSize == 64 ? 1 : -1; + if (CallbackIdx < 0) continue; + auto Ty = Type::getIntNTy(*C, TypeSize); + IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx], + {IRB.CreateIntCast(A1, Ty, true)}); + } +} + +void SanitizerCoverageModule::InjectTraceForGep( + Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) { + for (auto GEP : GepTraceTargets) { + IRBuilder<> IRB(GEP); + for (auto I = GEP->idx_begin(); I != GEP->idx_end(); ++I) + if (!isa<ConstantInt>(*I) && (*I)->getType()->isIntegerTy()) + IRB.CreateCall(SanCovTraceGepFunction, + {IRB.CreateIntCast(*I, IntptrTy, true)}); + } +} + void SanitizerCoverageModule::InjectTraceForCmp( Function &, ArrayRef<Instruction *> CmpTraceTargets) { for (auto I : CmpTraceTargets) { @@ -497,12 +656,16 @@ void SanitizerCoverageModule::InjectTraceForCmp( if (!A0->getType()->isIntegerTy()) continue; uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType()); + int CallbackIdx = TypeSize == 8 ? 0 : + TypeSize == 16 ? 1 : + TypeSize == 32 ? 2 : + TypeSize == 64 ? 3 : -1; + if (CallbackIdx < 0) continue; // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1); + auto Ty = Type::getIntNTy(*C, TypeSize); IRB.CreateCall( - SanCovTraceCmpFunction, - {ConstantInt::get(Int64Ty, (TypeSize << 32) | ICMP->getPredicate()), - IRB.CreateIntCast(A0, Int64Ty, true), - IRB.CreateIntCast(A1, Int64Ty, true)}); + SanCovTraceCmpFunction[CallbackIdx], + {IRB.CreateIntCast(A0, Ty, true), IRB.CreateIntCast(A1, Ty, true)}); } } } @@ -513,16 +676,8 @@ void SanitizerCoverageModule::SetNoSanitizeMetadata(Instruction *I) { } void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, - bool UseCalls) { - // Don't insert coverage for unreachable blocks: we will never call - // __sanitizer_cov() for them, so counting them in - // NumberOfInstrumentedBlocks() might complicate calculation of code coverage - // percentage. Also, unreachable instructions frequently have no debug - // locations. - if (isa<UnreachableInst>(BB.getTerminator())) - return; + size_t Idx, bool UseCalls) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); - bool IsEntryBB = &BB == &F.getEntryBlock(); DebugLoc EntryLoc; if (IsEntryBB) { @@ -538,32 +693,52 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, IRBuilder<> IRB(&*IP); IRB.SetCurrentDebugLocation(EntryLoc); - Value *GuardP = IRB.CreateAdd( - IRB.CreatePointerCast(GuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4)); - Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); - GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy); if (Options.TracePC) { IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC. IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge. - } else if (Options.TraceBB) { - IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP); - } else if (UseCalls) { - IRB.CreateCall(SanCovWithCheckFunction, GuardP); - } else { - LoadInst *Load = IRB.CreateLoad(GuardP); - Load->setAtomic(AtomicOrdering::Monotonic); - Load->setAlignment(4); - SetNoSanitizeMetadata(Load); - 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); + } else if (Options.TracePCGuard) { + auto GuardPtr = IRB.CreateIntToPtr( + IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, Idx * 4)), + Int32PtrTy); + if (!UseCalls) { + auto GuardLoad = IRB.CreateLoad(GuardPtr); + GuardLoad->setAtomic(AtomicOrdering::Monotonic); + GuardLoad->setAlignment(8); + SetNoSanitizeMetadata(GuardLoad); // Don't instrument with e.g. asan. + auto Cmp = IRB.CreateICmpNE( + GuardLoad, Constant::getNullValue(GuardLoad->getType())); + auto Ins = SplitBlockAndInsertIfThen( + Cmp, &*IP, false, MDBuilder(*C).createBranchWeights(1, 100000)); + IRB.SetInsertPoint(Ins); + IRB.SetCurrentDebugLocation(EntryLoc); + } + IRB.CreateCall(SanCovTracePCGuard, GuardPtr); IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge. + } else { + Value *GuardP = IRB.CreateAdd( + IRB.CreatePointerCast(GuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4)); + GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy); + if (Options.TraceBB) { + IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP); + } else if (UseCalls) { + IRB.CreateCall(SanCovWithCheckFunction, GuardP); + } else { + LoadInst *Load = IRB.CreateLoad(GuardP); + Load->setAtomic(AtomicOrdering::Monotonic); + Load->setAlignment(4); + SetNoSanitizeMetadata(Load); + 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 (Options.Use8bitCounters) { |