diff options
author | Kostya Serebryany <kcc@google.com> | 2014-12-30 19:29:28 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2014-12-30 19:29:28 +0000 |
commit | aa185bfc4b70e7329f2e98b5e685d18b9668ace4 (patch) | |
tree | 82be4cc8914b8144c74d289cf6ccd03c9ef3048d | |
parent | c43b063358a8b307b17faecae850e6d3d8b5ff49 (diff) | |
download | bcm5719-llvm-aa185bfc4b70e7329f2e98b5e685d18b9668ace4.tar.gz bcm5719-llvm-aa185bfc4b70e7329f2e98b5e685d18b9668ace4.zip |
[asan] change _sanitizer_cov_module_init to accept int* instead of int**
llvm-svn: 224999
3 files changed, 46 insertions, 27 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index a00109a4299..e28a6aee375 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -79,7 +79,7 @@ class CoverageData { ALWAYS_INLINE void TraceBasicBlock(uptr *cache); - void InitializeGuards(s32 **guards, uptr n); + void InitializeGuards(s32 *guards, uptr n); uptr *data(); uptr size(); @@ -246,16 +246,19 @@ void CoverageData::Extend(uptr npcs) { atomic_store(&pc_array_size, size, memory_order_release); } -void CoverageData::InitializeGuards(s32 **guards, uptr n) { - for (uptr i = 0; i < n; i++) { +void CoverageData::InitializeGuards(s32 *guards, uptr n) { + // The array 'guards' has n+1 elements, we use the element zero + // to store 'n'. + CHECK_LT(n, 1 << 30); + guards[0] = static_cast<s32>(n); + for (uptr i = 1; i <= n; i++) { uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed); - *guards[i] = -static_cast<s32>(idx + 1); + guards[i] = -static_cast<s32>(idx + 1); } } -// Atomically add the pc to the vector. The atomically set the guard to 1. -// If the function is called more than once for a given PC it will -// be inserted multiple times, which is fine. +// If guard is negative, atomically set it to -guard and store the PC in +// pc_array. void CoverageData::Add(uptr pc, u32 *guard) { atomic_uint32_t *atomic_guard = reinterpret_cast<atomic_uint32_t*>(guard); s32 guard_value = atomic_load(atomic_guard, memory_order_relaxed); @@ -624,7 +627,7 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { coverage_data.Init(); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); } -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init(s32 **guards, +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init(s32 *guards, uptr npcs) { coverage_data.InitializeGuards(guards, npcs); if (!common_flags()->coverage_direct) return; diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 8600f9183e0..bf04bb17fc4 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -112,7 +112,7 @@ class SanitizerCoverageModule : public ModulePass { Type *IntptrTy; LLVMContext *C; - SmallVector<Constant *, 16> Guards; + GlobalVariable *GuardArray; int CoverageLevel; }; @@ -137,7 +137,6 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); - Type *Int32PtrPtrTy = PointerType::getUnqual(Int32PtrTy); Function *CtorFunc = Function::Create(FunctionType::get(VoidTy, false), @@ -151,7 +150,7 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); SanCovModuleInit = checkInterfaceFunction( M.getOrInsertFunction(kSanCovModuleInitName, Type::getVoidTy(*C), - Int32PtrPtrTy, IntptrTy, nullptr)); + Int32PtrTy, IntptrTy, nullptr)); SanCovModuleInit->setLinkage(Function::ExternalLinkage); // We insert an empty inline asm after cov callbacks to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), @@ -165,18 +164,34 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { M.getOrInsertFunction(kSanCovTraceBB, VoidTy, IntptrTy, nullptr)); } + // At this point we create a dummy array of guards because we don't + // know how many elements we will need. + Type *Int32Ty = IRB.getInt32Ty(); + GuardArray = + new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, + nullptr, "__sancov_gen_cov_tmp"); + for (auto &F : M) runOnFunction(F); - ArrayType *ArrayOfInt32PtrTy = ArrayType::get(Int32PtrTy, Guards.size()); + // 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, SanCovFunction->getNumUses() + 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(); + + // Call __sanitizer_cov_module_init IRB.SetInsertPoint(CtorFunc->getEntryBlock().getTerminator()); - GlobalVariable *AllGuards = new GlobalVariable( - M, ArrayOfInt32PtrTy, false, GlobalVariable::InternalLinkage, - ConstantArray::get(ArrayOfInt32PtrTy, Guards), ""); - assert(SanCovFunction->getNumUses() == Guards.size()); IRB.CreateCall2(SanCovModuleInit, - IRB.CreatePointerCast(AllGuards, Int32PtrPtrTy), - ConstantInt::get(IntptrTy, Guards.size())); + IRB.CreatePointerCast(RealGuardArray, Int32PtrTy), + ConstantInt::get(IntptrTy, SanCovFunction->getNumUses())); return true; } @@ -282,24 +297,25 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, : IP->getDebugLoc(); IRBuilder<> IRB(IP); IRB.SetCurrentDebugLocation(EntryLoc); - Type *Int32Ty = IRB.getInt32Ty(); - GlobalVariable *Guard = new GlobalVariable( - *F.getParent(), Int32Ty, false, GlobalValue::PrivateLinkage, - Constant::getNullValue(Int32Ty), "__sancov_gen_cov_" + F.getName()); - LoadInst *Load = IRB.CreateLoad(Guard); + SmallVector<Value *, 1> Indices; + Value *GuardP = IRB.CreateAdd( + IRB.CreatePointerCast(GuardArray, IntptrTy), + 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(Int32Ty), 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, Guard); + IRB.CreateCall(SanCovFunction, GuardP); IRB.CreateCall(EmptyAsm); // Avoids callback merge. - Guards.push_back(Guard); // Save the guard for later. } char SanitizerCoverageModule::ID = 0; diff --git a/llvm/test/Instrumentation/SanitizerCoverage/coverage.ll b/llvm/test/Instrumentation/SanitizerCoverage/coverage.ll index 9a05fa8c083..77e781e5474 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/coverage.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/coverage.ll @@ -33,7 +33,7 @@ entry: ; CHECK0-NOT: call void @__sanitizer_cov_module_init( ; CHECK1-LABEL: define void @foo -; CHECK1: %0 = load atomic i32* @__sancov_gen_cov_foo monotonic, align 4, !nosanitize +; CHECK1: %0 = load atomic i32* {{.*}} monotonic, align 4, !nosanitize ; CHECK1: %1 = icmp sge i32 0, %0 ; CHECK1: br i1 %1, label %2, label %3 ; CHECK1: call void @__sanitizer_cov(i32*{{.*}}) |