From d421db05bb7e7a9dc6223869447a64c36350922d Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Sat, 3 Jan 2015 00:54:43 +0000 Subject: [PATCH] [asan] simplify the tracing code, make it use the same guard variables as coverage llvm-svn: 225103 --- .../sanitizer_common/sanitizer_coverage_libcdep.cc | 60 ++++++---------------- .../test/asan/TestCases/Linux/coverage-tracing.cc | 2 +- .../Instrumentation/SanitizerCoverage.cpp | 37 +++++-------- .../Instrumentation/SanitizerCoverage/tracing.ll | 2 +- 4 files changed, 31 insertions(+), 70 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index dbb7f97..0639dc0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -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(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 = ""; - 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 = ""; + 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(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 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" diff --git a/compiler-rt/test/asan/TestCases/Linux/coverage-tracing.cc b/compiler-rt/test/asan/TestCases/Linux/coverage-tracing.cc index 89ab0d2..4467673 100644 --- a/compiler-rt/test/asan/TestCases/Linux/coverage-tracing.cc +++ b/compiler-rt/test/asan/TestCases/Linux/coverage-tracing.cc @@ -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 diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index bf04bb1..c048a99 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -102,7 +102,6 @@ class SanitizerCoverageModule : public ModulePass { ArrayRef IndirCalls); bool InjectCoverage(Function &F, ArrayRef AllBlocks, ArrayRef IndirCalls); - bool InjectTracing(Function &F, ArrayRef 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 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 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; diff --git a/llvm/test/Instrumentation/SanitizerCoverage/tracing.ll b/llvm/test/Instrumentation/SanitizerCoverage/tracing.ll index c39cb1cf..8c3a6df 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/tracing.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/tracing.ll @@ -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" -- 2.7.4