[asan] change the coverage collection scheme so that we can easily emit coverage...
authorKostya Serebryany <kcc@google.com>
Tue, 23 Dec 2014 22:32:17 +0000 (22:32 +0000)
committerKostya Serebryany <kcc@google.com>
Tue, 23 Dec 2014 22:32:17 +0000 (22:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224789 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Instrumentation/SanitizerCoverage.cpp
test/Instrumentation/SanitizerCoverage/coverage-dbg.ll
test/Instrumentation/SanitizerCoverage/coverage.ll
test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll

index 9293362235b8842a7ecbeb46767697ad64271e67..8600f9183e0c9f32230bba0682875acf0984d086 100644 (file)
 // Coverage instrumentation that works with AddressSanitizer
 // and potentially with other Sanitizers.
 //
-// We create a Guard boolean variable with the same linkage
+// We create a Guard variable with the same linkage
 // as the function and inject this code into the entry block (CoverageLevel=1)
 // or all blocks (CoverageLevel>=2):
-// if (Guard) {
+// if (Guard < 0) {
 //    __sanitizer_cov(&Guard);
 // }
 // The accesses to Guard are atomic. The rest of the logic is
@@ -112,6 +112,8 @@ class SanitizerCoverageModule : public ModulePass {
   Type *IntptrTy;
   LLVMContext *C;
 
+  SmallVector<Constant *, 16> Guards;
+
   int CoverageLevel;
 };
 
@@ -134,6 +136,8 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
   IntptrTy = Type::getIntNTy(*C, DLP->getDataLayout().getPointerSizeInBits());
   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),
@@ -142,11 +146,12 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
   appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority);
 
   SanCovFunction = checkInterfaceFunction(
-      M.getOrInsertFunction(kSanCovName, VoidTy, IRB.getInt8PtrTy(), nullptr));
+      M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr));
   SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction(
       kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
-  SanCovModuleInit = checkInterfaceFunction(M.getOrInsertFunction(
-      kSanCovModuleInitName, Type::getVoidTy(*C), IntptrTy, nullptr));
+  SanCovModuleInit = checkInterfaceFunction(
+      M.getOrInsertFunction(kSanCovModuleInitName, Type::getVoidTy(*C),
+                            Int32PtrPtrTy, 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),
@@ -163,9 +168,15 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
   for (auto &F : M)
     runOnFunction(F);
 
+  ArrayType *ArrayOfInt32PtrTy = ArrayType::get(Int32PtrTy, Guards.size());
   IRB.SetInsertPoint(CtorFunc->getEntryBlock().getTerminator());
-  IRB.CreateCall(SanCovModuleInit,
-                 ConstantInt::get(IntptrTy, SanCovFunction->getNumUses()));
+  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()));
   return true;
 }
 
@@ -271,16 +282,16 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F,
                           : IP->getDebugLoc();
   IRBuilder<> IRB(IP);
   IRB.SetCurrentDebugLocation(EntryLoc);
-  Type *Int8Ty = IRB.getInt8Ty();
+  Type *Int32Ty = IRB.getInt32Ty();
   GlobalVariable *Guard = new GlobalVariable(
-      *F.getParent(), Int8Ty, false, GlobalValue::PrivateLinkage,
-      Constant::getNullValue(Int8Ty), "__sancov_gen_cov_" + F.getName());
+      *F.getParent(), Int32Ty, false, GlobalValue::PrivateLinkage,
+      Constant::getNullValue(Int32Ty), "__sancov_gen_cov_" + F.getName());
   LoadInst *Load = IRB.CreateLoad(Guard);
   Load->setAtomic(Monotonic);
-  Load->setAlignment(1);
+  Load->setAlignment(4);
   Load->setMetadata(F.getParent()->getMDKindID("nosanitize"),
                     MDNode::get(*C, None));
-  Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load);
+  Value *Cmp = IRB.CreateICmpSGE(Constant::getNullValue(Int32Ty), Load);
   Instruction *Ins = SplitBlockAndInsertIfThen(
       Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
   IRB.SetInsertPoint(Ins);
@@ -288,6 +299,7 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F,
   // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
   IRB.CreateCall(SanCovFunction, Guard);
   IRB.CreateCall(EmptyAsm);  // Avoids callback merge.
+  Guards.push_back(Guard);  // Save the guard for later.
 }
 
 char SanitizerCoverageModule::ID = 0;
index 22151ba8836f094b48ad3eb8f1f22107c5efa1ab..9115fec3339defc03c7eaa280c178a92ed0d6c27 100644 (file)
@@ -15,7 +15,7 @@
 ; and add sanitize_address to @_ZN1A1fEv
 
 ; Test that __sanitizer_cov call has !dbg pointing to the opening { of A::f().
-; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[A:!.*]]
+; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[A:!.*]]
 ; CHECK: [[A]] = !{i32 6, i32 0, !{{.*}}, null}
 
 
index 68e7fc0ef3201b51c9df4c229533eb5fbd1e1446..9a05fa8c083c4d278f2d11b6e8c82d7a363c426f 100644 (file)
@@ -33,17 +33,17 @@ entry:
 ; CHECK0-NOT: call void @__sanitizer_cov_module_init(
 
 ; CHECK1-LABEL: define void @foo
-; CHECK1: %0 = load atomic i8* @__sancov_gen_cov_foo monotonic, align 1, !nosanitize
-; CHECK1: %1 = icmp eq i8 0, %0
+; CHECK1: %0 = load atomic i32* @__sancov_gen_cov_foo monotonic, align 4, !nosanitize
+; CHECK1: %1 = icmp sge i32 0, %0
 ; CHECK1: br i1 %1, label %2, label %3
-; CHECK1: call void @__sanitizer_cov(i8*{{.*}})
+; CHECK1: call void @__sanitizer_cov(i32*{{.*}})
 ; CHECK1: call void asm sideeffect "", ""()
 ; CHECK1-NOT: call void @__sanitizer_cov
 ; CHECK1: ret void
 
 ; CHECK1-LABEL: define internal void @sancov.module_ctor
 ; CHECK1-NOT: ret
-; CHECK1: call void @__sanitizer_cov_module_init(i64 2)
+; CHECK1: call void @__sanitizer_cov_module_init({{.*}}, i64 2)
 ; CHECK1: ret
 
 
@@ -59,7 +59,7 @@ entry:
 
 ; CHECK2-LABEL: define internal void @sancov.module_ctor
 ; CHECK2-NOT: ret
-; CHECK2: call void @__sanitizer_cov_module_init(i64 4)
+; CHECK2: call void @__sanitizer_cov_module_init({{.*}}, i64 4)
 ; CHECK2: ret
 
 ; CHECK3-LABEL: define void @foo
index f78d61fac1559eca196e8edb37f6a0905baf1e4e..54e0e6a48515d55e6c6fbdd84c04305160122376 100644 (file)
@@ -17,9 +17,9 @@ target triple = "x86_64-unknown-linux-gnu"
 ; Check that __sanitizer_cov call has !dgb pointing to the beginning
 ; of appropriate basic blocks.
 ; CHECK-LABEL:_Z3fooPi
-; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[A:!.*]]
-; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[B:!.*]]
-; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[C:!.*]]
+; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[A:!.*]]
+; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[B:!.*]]
+; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[C:!.*]]
 ; CHECK: ret void
 ; CHECK: [[A]] = !{i32 1, i32 0, !{{.*}}, null}
 ; CHECK: [[B]] = !{i32 3, i32 5, !{{.*}}, null}