[asan] simplify the tracing code, make it use the same guard variables as coverage
authorKostya Serebryany <kcc@google.com>
Sat, 3 Jan 2015 00:54:43 +0000 (00:54 +0000)
committerKostya Serebryany <kcc@google.com>
Sat, 3 Jan 2015 00:54:43 +0000 (00:54 +0000)
llvm-svn: 225103

compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
compiler-rt/test/asan/TestCases/Linux/coverage-tracing.cc
llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
llvm/test/Instrumentation/SanitizerCoverage/tracing.ll

index dbb7f97..0639dc0 100644 (file)
@@ -77,7 +77,7 @@ class CoverageData {
   void DumpTrace();
 
   ALWAYS_INLINE
-  void TraceBasicBlock(uptr *cache);
+  void TraceBasicBlock(s32 *id);
 
   void InitializeGuardArray(s32 *guards);
   void InitializeGuards(s32 *guards, uptr n);
@@ -113,26 +113,18 @@ class CoverageData {
   atomic_uintptr_t cc_array_index;
   atomic_uintptr_t cc_array_size;
 
-  // Tracing (tr) pc and event arrays, their size and current index.
+  // Tracing event array, size and current index.
   // We record all events (basic block entries) in a global buffer of u32
-  // values. Each such value is an index in the table of TracedPc objects.
+  // values. Each such value is the index in pc_array (incremented by one).
   // So far the tracing is highly experimental:
   //   - not thread-safe;
   //   - does not support long traces;
   //   - not tuned for performance.
-  struct TracedPc {
-    uptr pc;
-    const char *module_name;
-    uptr module_offset;
-  };
   static const uptr kTrEventArrayMaxSize = FIRST_32_SECOND_64(1 << 22, 1 << 30);
   u32 *tr_event_array;
   uptr tr_event_array_size;
   uptr tr_event_array_index;
   static const uptr kTrPcArrayMaxSize    = FIRST_32_SECOND_64(1 << 22, 1 << 27);
-  TracedPc *tr_pc_array;
-  uptr tr_pc_array_size;
-  uptr tr_pc_array_index;
 
   StaticSpinMutex mu;
 
@@ -178,11 +170,6 @@ void CoverageData::Init() {
                          "CovInit::tr_event_array"));
   tr_event_array_size = kTrEventArrayMaxSize;
   tr_event_array_index = 0;
-
-  tr_pc_array = reinterpret_cast<TracedPc *>(MmapNoReserveOrDie(
-      sizeof(tr_pc_array[0]) * kTrEventArrayMaxSize, "CovInit::tr_pc_array"));
-  tr_pc_array_size = kTrEventArrayMaxSize;
-  tr_pc_array_index = 0;
 }
 
 void CoverageData::InitializeGuardArray(s32 *guards) {
@@ -415,17 +402,12 @@ void CoverageData::DumpTrace() {
   if (!sym)
     return;
   InternalScopedString out(32 << 20);
-  for (uptr i = 0; i < max_idx; i++) {
-    u32 pc_idx = tr_event_array[i];
-    TracedPc *t = &tr_pc_array[pc_idx];
-    if (!t->module_name) {
-      const char *module_name = "<unknown>";
-      uptr module_address = 0;
-      sym->GetModuleNameAndOffsetForPC(t->pc, &module_name, &module_address);
-      t->module_name = internal_strdup(module_name);
-      t->module_offset = module_address;
-      out.append("%s 0x%zx\n", t->module_name, t->module_offset);
-    }
+  for (uptr i = 0, n = size(); i < n; i++) {
+    const char *module_name = "<unknown>";
+    uptr module_address = 0;
+    sym->GetModuleNameAndOffsetForPC(pc_array[i], &module_name,
+                                     &module_address);
+    out.append("%s 0x%zx\n", module_name, module_address);
   }
   int fd = CovOpenFile(false, "trace-points");
   if (fd < 0) return;
@@ -436,7 +418,7 @@ void CoverageData::DumpTrace() {
   if (fd < 0) return;
   internal_write(fd, tr_event_array, max_idx * sizeof(tr_event_array[0]));
   internal_close(fd);
-  VReport(1, " CovDump: Trace: %zd PCs written\n", tr_pc_array_index);
+  VReport(1, " CovDump: Trace: %zd PCs written\n", size());
   VReport(1, " CovDump: Trace: %zd Events written\n", tr_event_array_index);
 }
 
@@ -482,17 +464,9 @@ void CoverageData::DumpCallerCalleePairs() {
 // Record the current PC into the event buffer.
 // Every event is a u32 value (index in tr_pc_array_index) so we compute
 // it once and then cache in the provided 'cache' storage.
-void CoverageData::TraceBasicBlock(uptr *cache) {
+void CoverageData::TraceBasicBlock(s32 *id) {
   CHECK(coverage_enabled);
-  uptr idx = *cache;
-  if (!idx) {
-    CHECK_LT(tr_pc_array_index, kTrPcArrayMaxSize);
-    idx = tr_pc_array_index++;
-    TracedPc *t = &tr_pc_array[idx];
-    t->pc = GET_CALLER_PC();
-    *cache = idx;
-    CHECK_LT(idx, 1U << 31);
-  }
+  uptr idx = *id;
   CHECK_LT(tr_event_array_index, tr_event_array_size);
   tr_event_array[tr_event_array_index] = static_cast<u32>(idx);
   tr_event_array_index++;
@@ -525,6 +499,7 @@ static void CovDump() {
   if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
     return;
   CovDumpAsBitSet();
+  coverage_data.DumpTrace();
   if (!common_flags()->coverage_pcs) return;
   uptr size = coverage_data.size();
   InternalMmapVector<u32> offsets(size);
@@ -576,7 +551,6 @@ static void CovDump() {
   if (cov_fd >= 0)
     internal_close(cov_fd);
   coverage_data.DumpCallerCalleePairs();
-  coverage_data.DumpTrace();
 #endif  // !SANITIZER_WINDOWS
 }
 
@@ -665,11 +639,11 @@ uptr __sanitizer_get_total_unique_coverage() {
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_cov_trace_func_enter(uptr *cache) {
-  coverage_data.TraceBasicBlock(cache);
+void __sanitizer_cov_trace_func_enter(s32 *id) {
+  coverage_data.TraceBasicBlock(id);
 }
 SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_cov_trace_basic_block(uptr *cache) {
-  coverage_data.TraceBasicBlock(cache);
+void __sanitizer_cov_trace_basic_block(s32 *id) {
+  coverage_data.TraceBasicBlock(id);
 }
 }  // extern "C"
index 89ab0d2..4467673 100644 (file)
@@ -1,6 +1,6 @@
 // Test -mllvm -sanitizer-coverage-experimental-tracing
 //
-// RUN: %clangxx_asan -O1 -fsanitize-coverage=1 -mllvm -sanitizer-coverage-experimental-tracing %s -o %t
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=2 -mllvm -sanitizer-coverage-experimental-tracing %s -o %t
 // RUN: rm -rf   %T/coverage-tracing
 // RUN: mkdir -p %T/coverage-tracing
 // RUN: ASAN_OPTIONS=coverage=1:coverage_dir=%T/coverage-tracing:verbosity=1 %run %t 1 2 3 4 2>&1 | FileCheck %s
index bf04bb1..c048a99 100644 (file)
@@ -102,7 +102,6 @@ class SanitizerCoverageModule : public ModulePass {
                                       ArrayRef<Instruction *> IndirCalls);
   bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,
                       ArrayRef<Instruction *> IndirCalls);
-  bool InjectTracing(Function &F, ArrayRef<BasicBlock *> AllBlocks);
   void InjectCoverageAtBlock(Function &F, BasicBlock &BB);
   Function *SanCovFunction;
   Function *SanCovIndirCallFunction;
@@ -159,9 +158,9 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
 
   if (ClExperimentalTracing) {
     SanCovTraceEnter = checkInterfaceFunction(
-        M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, IntptrTy, nullptr));
+        M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr));
     SanCovTraceBB = checkInterfaceFunction(
-        M.getOrInsertFunction(kSanCovTraceBB, VoidTy, IntptrTy, nullptr));
+        M.getOrInsertFunction(kSanCovTraceBB, VoidTy, Int32PtrTy, nullptr));
   }
 
   // At this point we create a dummy array of guards because we don't
@@ -213,25 +212,6 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
       }
   }
   InjectCoverage(F, AllBlocks, IndirCalls);
-  InjectTracing(F, AllBlocks);
-  return true;
-}
-
-// Experimental support for tracing.
-// Basicaly, insert a callback at the beginning of every basic block.
-// Every callback gets a pointer to a uniqie global for internal storage.
-bool SanitizerCoverageModule::InjectTracing(Function &F,
-                                            ArrayRef<BasicBlock *> AllBlocks) {
-  if (!ClExperimentalTracing) return false;
-  Type *Ty = ArrayType::get(IntptrTy, 1);  // May need to use more words later.
-  for (auto BB : AllBlocks) {
-    IRBuilder<> IRB(BB->getFirstInsertionPt());
-    GlobalVariable *TraceCache = new GlobalVariable(
-        *F.getParent(), Ty, false, GlobalValue::PrivateLinkage,
-        Constant::getNullValue(Ty), "__sancov_gen_trace_cache");
-    IRB.CreateCall(&F.getEntryBlock() == BB ? SanCovTraceEnter : SanCovTraceBB,
-                   IRB.CreatePointerCast(TraceCache, IntptrTy));
-  }
   return true;
 }
 
@@ -292,9 +272,9 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F,
       break;
   }
 
-  DebugLoc EntryLoc = &BB == &F.getEntryBlock()
-                          ? IP->getDebugLoc().getFnDebugLoc(*C)
-                          : IP->getDebugLoc();
+  bool IsEntryBB = &BB == &F.getEntryBlock();
+  DebugLoc EntryLoc =
+      IsEntryBB ? IP->getDebugLoc().getFnDebugLoc(*C) : IP->getDebugLoc();
   IRBuilder<> IRB(IP);
   IRB.SetCurrentDebugLocation(EntryLoc);
   SmallVector<Value *, 1> Indices;
@@ -316,6 +296,13 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F,
   // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
   IRB.CreateCall(SanCovFunction, GuardP);
   IRB.CreateCall(EmptyAsm);  // Avoids callback merge.
+
+  if (ClExperimentalTracing) {
+    // Experimental support for tracing.
+    // Insert a callback with the same guard variable as used for coverage.
+    IRB.SetInsertPoint(IP);
+    IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
+  }
 }
 
 char SanitizerCoverageModule::ID = 0;
index c39cb1c..8c3a6df 100644 (file)
@@ -1,5 +1,5 @@
 ; Test -sanitizer-coverage-experimental-tracing
-; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-experimental-tracing  -S | FileCheck %s --check-prefix=CHECK1
+; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-experimental-tracing  -S | FileCheck %s --check-prefix=CHECK1
 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-experimental-tracing  -S | FileCheck %s --check-prefix=CHECK3
 
 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"