[llvm] r309335 - [sanitizer-coverage] add a feature sanitizer-coverage-create-pc-table=1 (works with trace-pc-guard and inline-8bit-counters) that adds a static table of instrumented PCs to be used at run-time

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 27 16:36:49 PDT 2017


Author: kcc
Date: Thu Jul 27 16:36:49 2017
New Revision: 309335

URL: http://llvm.org/viewvc/llvm-project?rev=309335&view=rev
Log:
[sanitizer-coverage] add a feature sanitizer-coverage-create-pc-table=1 (works with trace-pc-guard and inline-8bit-counters) that adds a static table of instrumented PCs to be used at run-time 

Added:
    llvm/trunk/test/Instrumentation/SanitizerCoverage/pc-table.ll
Modified:
    llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp

Modified: llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp?rev=309335&r1=309334&r2=309335&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp Thu Jul 27 16:36:49 2017
@@ -57,11 +57,13 @@ static const char *const SanCovTracePCGu
     "__sanitizer_cov_trace_pc_guard";
 static const char *const SanCovTracePCGuardInitName =
     "__sanitizer_cov_trace_pc_guard_init";
-static const char *const SanCov8bitCountersInitName = 
+static const char *const SanCov8bitCountersInitName =
     "__sanitizer_cov_8bit_counters_init";
+static const char *const SanCovPCsInitName = "__sanitizer_cov_pcs_init";
 
 static const char *const SanCovGuardsSectionName = "sancov_guards";
 static const char *const SanCovCountersSectionName = "sancov_cntrs";
+static const char *const SanCovPCsSectionName = "sancov_pcs";
 
 static cl::opt<int> ClCoverageLevel(
     "sanitizer-coverage-level",
@@ -77,9 +79,19 @@ static cl::opt<bool> ClTracePCGuard("san
                                     cl::desc("pc tracing with a guard"),
                                     cl::Hidden, cl::init(false));
 
-static cl::opt<bool> ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters",
-                                    cl::desc("increments 8-bit counter for every edge"),
-                                    cl::Hidden, cl::init(false));
+// If true, we create a global variable that contains PCs of all instrumented
+// BBs, put this global into a named section, and pass this section's bounds
+// to __sanitizer_cov_pcs_init.
+// This way the coverage instrumentation does not need to acquire the PCs
+// at run-time. Works with trace-pc-guard and inline-8bit-counters.
+static cl::opt<bool> ClCreatePCTable("sanitizer-coverage-create-pc-table",
+                                     cl::desc("create a static PC table"),
+                                     cl::Hidden, cl::init(false));
+
+static cl::opt<bool>
+    ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters",
+                         cl::desc("increments 8-bit counter for every edge"),
+                         cl::Hidden, cl::init(false));
 
 static cl::opt<bool>
     ClCMPTracing("sanitizer-coverage-trace-compares",
@@ -172,10 +184,13 @@ private:
   GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements,
                                                     Function &F, Type *Ty,
                                                     const char *Section);
-  void CreateFunctionLocalArrays(size_t NumGuards, Function &F);
+  void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks);
+  void CreatePCArray(Function &F, ArrayRef<BasicBlock *> AllBlocks);
   void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx);
-  void CreateInitCallForSection(Module &M, const char *InitFunctionName,
-                                Type *Ty, const std::string &Section);
+  Function *CreateInitCallsForSections(Module &M, const char *InitFunctionName,
+                                       Type *Ty, const char *Section);
+  std::pair<GlobalVariable *, GlobalVariable *>
+  CreateSecStartEnd(Module &M, const char *Section, Type *Ty);
 
   void SetNoSanitizeMetadata(Instruction *I) {
     I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
@@ -201,17 +216,16 @@ private:
 
   GlobalVariable *FunctionGuardArray;  // for trace-pc-guard.
   GlobalVariable *Function8bitCounterArray;  // for inline-8bit-counters.
+  GlobalVariable *FunctionPCsArray;  // for create-pc-table.
 
   SanitizerCoverageOptions Options;
 };
 
 } // namespace
 
-void SanitizerCoverageModule::CreateInitCallForSection(
-    Module &M, const char *InitFunctionName, Type *Ty,
-    const std::string &Section) {
-  IRBuilder<> IRB(M.getContext());
-  Function *CtorFunc;
+std::pair<GlobalVariable *, GlobalVariable *>
+SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section,
+                                           Type *Ty) {
   GlobalVariable *SecStart =
       new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr,
                          getSectionStart(Section));
@@ -221,6 +235,18 @@ void SanitizerCoverageModule::CreateInit
                          nullptr, getSectionEnd(Section));
   SecEnd->setVisibility(GlobalValue::HiddenVisibility);
 
+  return std::make_pair(SecStart, SecEnd);
+}
+
+
+Function *SanitizerCoverageModule::CreateInitCallsForSections(
+    Module &M, const char *InitFunctionName, Type *Ty,
+    const char *Section) {
+  IRBuilder<> IRB(M.getContext());
+  auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);
+  auto SecStart = SecStartEnd.first;
+  auto SecEnd = SecStartEnd.second;
+  Function *CtorFunc;
   std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
       M, SanCovModuleCtorName, InitFunctionName, {Ty, Ty},
       {IRB.CreatePointerCast(SecStart, Ty), IRB.CreatePointerCast(SecEnd, Ty)});
@@ -232,6 +258,7 @@ void SanitizerCoverageModule::CreateInit
   } else {
     appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
   }
+  return CtorFunc;
 }
 
 bool SanitizerCoverageModule::runOnModule(Module &M) {
@@ -243,6 +270,7 @@ bool SanitizerCoverageModule::runOnModul
   TargetTriple = Triple(M.getTargetTriple());
   FunctionGuardArray = nullptr;
   Function8bitCounterArray = nullptr;
+  FunctionPCsArray = nullptr;
   IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
   IntptrPtrTy = PointerType::getUnqual(IntptrTy);
   Type *VoidTy = Type::getVoidTy(*C);
@@ -305,13 +333,23 @@ bool SanitizerCoverageModule::runOnModul
   for (auto &F : M)
     runOnFunction(F);
 
+  Function *Ctor = nullptr;
+
   if (FunctionGuardArray)
-    CreateInitCallForSection(M, SanCovTracePCGuardInitName, Int32PtrTy,
-                             SanCovGuardsSectionName);
+    Ctor = CreateInitCallsForSections(M, SanCovTracePCGuardInitName, Int32PtrTy,
+                                      SanCovGuardsSectionName);
   if (Function8bitCounterArray)
-    CreateInitCallForSection(M, SanCov8bitCountersInitName, Int8PtrTy,
-                             SanCovCountersSectionName);
-
+    Ctor = CreateInitCallsForSections(M, SanCov8bitCountersInitName, Int8PtrTy,
+                                      SanCovCountersSectionName);
+  if (Ctor && ClCreatePCTable) {
+    auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, Int8PtrTy);
+    Function *InitFunction = declareSanitizerInitFunction(
+        M, SanCovPCsInitName, {Int8PtrTy, Int8PtrTy});
+    IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
+    IRBCtor.CreateCall(InitFunction,
+                       {IRB.CreatePointerCast(SecStartEnd.first, Int8PtrTy),
+                        IRB.CreatePointerCast(SecStartEnd.second, Int8PtrTy)});
+  }
   return true;
 }
 
@@ -450,20 +488,41 @@ GlobalVariable *SanitizerCoverageModule:
   Array->setSection(getSectionName(Section));
   return Array;
 }
-void SanitizerCoverageModule::CreateFunctionLocalArrays(size_t NumGuards,
-                                                       Function &F) {
+
+void SanitizerCoverageModule::CreatePCArray(Function &F,
+                                            ArrayRef<BasicBlock *> AllBlocks) {
+  size_t N = AllBlocks.size();
+  assert(N);
+  assert(&F.getEntryBlock() == AllBlocks[0]);
+  SmallVector<Constant *, 16> PCs;
+  IRBuilder<> IRB(&*F.getEntryBlock().getFirstInsertionPt());
+  PCs.push_back((Constant *)IRB.CreatePointerCast(&F, Int8PtrTy));
+  for (size_t i = 1; i < N; i++)
+    PCs.push_back(BlockAddress::get(AllBlocks[i]));
+  FunctionPCsArray =
+      CreateFunctionLocalArrayInSection(N, F, Int8PtrTy, SanCovPCsSectionName);
+  FunctionPCsArray->setInitializer(
+      ConstantArray::get(ArrayType::get(Int8PtrTy, N), PCs));
+  FunctionPCsArray->setConstant(true);
+  FunctionPCsArray->setAlignment(DL->getPointerSize());
+}
+
+void SanitizerCoverageModule::CreateFunctionLocalArrays(
+    Function &F, ArrayRef<BasicBlock *> AllBlocks) {
   if (Options.TracePCGuard)
     FunctionGuardArray = CreateFunctionLocalArrayInSection(
-        NumGuards, F, Int32Ty, SanCovGuardsSectionName);
+        AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName);
   if (Options.Inline8bitCounters)
     Function8bitCounterArray = CreateFunctionLocalArrayInSection(
-        NumGuards, F, Int8Ty, SanCovCountersSectionName);
+        AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName);
+  if (ClCreatePCTable)
+    CreatePCArray(F, AllBlocks);
 }
 
 bool SanitizerCoverageModule::InjectCoverage(Function &F,
                                              ArrayRef<BasicBlock *> AllBlocks) {
   if (AllBlocks.empty()) return false;
-  CreateFunctionLocalArrays(AllBlocks.size(), F);
+  CreateFunctionLocalArrays(F, AllBlocks);
   for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
     InjectCoverageAtBlock(F, *AllBlocks[i], i);
   return true;

Added: llvm/trunk/test/Instrumentation/SanitizerCoverage/pc-table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/SanitizerCoverage/pc-table.ll?rev=309335&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/SanitizerCoverage/pc-table.ll (added)
+++ llvm/trunk/test/Instrumentation/SanitizerCoverage/pc-table.ll Thu Jul 27 16:36:49 2017
@@ -0,0 +1,23 @@
+; Test -sanitizer-coverage-create-pc-table=1
+; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard       -sanitizer-coverage-create-pc-table=1 -S | FileCheck %s
+; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-create-pc-table=1 -S | FileCheck %s
+
+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 void @foo(i32* %a) sanitize_address {
+entry:
+  %tobool = icmp eq i32* %a, null
+  br i1 %tobool, label %if.end, label %if.then
+
+  if.then:                                          ; preds = %entry
+  store i32 0, i32* %a, align 4
+  br label %if.end
+
+  if.end:                                           ; preds = %entry, %if.then
+  ret void
+}
+
+; CHECK: private constant [3 x i8*] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}], section "__sancov_pcs", align 8
+; CHECK: define internal void @sancov.module_ctor
+; CHECK: call void @__sanitizer_cov
+; CHECK: call void @__sanitizer_cov_pcs_init




More information about the llvm-commits mailing list