diff options
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index bf9ecccd46d..5a70598329a 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -71,6 +71,9 @@ 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; @@ -99,10 +102,17 @@ static cl::opt<bool> ClExperimentalTracePC("sanitizer-coverage-trace-pc", 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", @@ -150,7 +160,9 @@ 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; return Options; @@ -177,6 +189,10 @@ 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); @@ -192,6 +208,8 @@ private: Function *SanCovIndirCallFunction, *SanCovTracePCIndir; Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC; Function *SanCovTraceCmpFunction[4]; + Function *SanCovTraceDivFunction[2]; + Function *SanCovTraceGepFunction; Function *SanCovTraceSwitchFunction; InlineAsm *EmptyAsm; Type *IntptrTy, *Int64Ty, *Int64PtrTy; @@ -242,6 +260,16 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { SanCovTraceCmpFunction[3] = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 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)); @@ -379,6 +407,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(); @@ -400,13 +430,23 @@ 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; } @@ -499,6 +539,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)) + IRB.CreateCall(SanCovTraceGepFunction, + {IRB.CreateIntCast(*I, IntptrTy, true)}); + } +} + void SanitizerCoverageModule::InjectTraceForCmp( Function &, ArrayRef<Instruction *> CmpTraceTargets) { for (auto I : CmpTraceTargets) { |