Index: compiler-rt/include/sanitizer/coverage_interface.h =================================================================== --- compiler-rt/include/sanitizer/coverage_interface.h +++ compiler-rt/include/sanitizer/coverage_interface.h @@ -22,8 +22,11 @@ // Record and dump coverage info. void __sanitizer_cov_dump(); - // Dump collected coverage info. Sorts pcs by module into individual - // .sancov files. + // Clear collected coverage info. + void __sanitizer_cov_reset(); + + // Dump collected coverage info. Sorts pcs by module into individual .sancov + // files. void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len); #ifdef __cplusplus Index: compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc +++ compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc @@ -9,6 +9,7 @@ // Sanitizer Coverage interface list. //===----------------------------------------------------------------------===// INTERFACE_FUNCTION(__sanitizer_cov_dump) +INTERFACE_FUNCTION(__sanitizer_cov_reset) INTERFACE_FUNCTION(__sanitizer_dump_coverage) INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage) INTERFACE_WEAK_FUNCTION(__sancov_default_options) Index: compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc @@ -111,6 +111,7 @@ initialized = true; InitializeSancovFlags(); + SpinMutexLock l(&pc_vector_mtx); pc_vector.Initialize(0); } @@ -119,26 +120,36 @@ CHECK(!*start); CHECK_NE(start, end); + SpinMutexLock l(&pc_vector_mtx); u32 i = pc_vector.size(); for (u32* p = start; p < end; p++) *p = ++i; pc_vector.resize(i); } void TracePcGuard(u32* guard, uptr pc) { - atomic_uint32_t* guard_ptr = reinterpret_cast(guard); - u32 idx = atomic_exchange(guard_ptr, 0, memory_order_relaxed); + u32 idx = *guard; if (!idx) return; // we start indices from 1. - pc_vector[idx - 1] = pc; + atomic_uintptr_t* pc_ptr = + reinterpret_cast(&pc_vector[idx - 1]); + if (atomic_load(pc_ptr, memory_order_relaxed) == 0) + atomic_store(pc_ptr, pc, memory_order_relaxed); + } + + void Reset() { + SpinMutexLock l(&pc_vector_mtx); + internal_memset(&pc_vector[0], 0, sizeof(pc_vector[0]) * pc_vector.size()); } void Dump() { if (!initialized || !common_flags()->coverage) return; + SpinMutexLock l(&pc_vector_mtx); __sanitizer_dump_coverage(pc_vector.data(), pc_vector.size()); } private: bool initialized; + StaticSpinMutex pc_vector_mtx; InternalMmapVectorNoCtor pc_vector; }; @@ -181,6 +192,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { __sanitizer_dump_trace_pc_guard_coverage(); } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_reset() { + __sancov::pc_guard_controller.Reset(); +} // Default empty implementations (weak). Users should redefine them. SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} Index: compiler-rt/test/asan/TestCases/Posix/coverage-reset.cc =================================================================== --- /dev/null +++ compiler-rt/test/asan/TestCases/Posix/coverage-reset.cc @@ -0,0 +1,65 @@ +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %ld_flags_rpath_exe -o %t +// RUN: rm -rf %T/coverage-reset && mkdir -p %T/coverage-reset && cd %T/coverage-reset +// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: ios + +#include + +#include + +#ifdef SHARED +void bar1() { printf("bar1\n"); } +void bar2() { printf("bar2\n"); } +#else +__attribute__((noinline)) void foo1() { printf("foo1\n"); } +__attribute__((noinline)) void foo2() { printf("foo2\n"); } +void bar1(); +void bar2(); + +int main(int argc, char **argv) { + fprintf(stderr, "RESET"); + __sanitizer_cov_reset(); + foo1(); + foo2(); + bar1(); + bar2(); + __sanitizer_cov_dump(); +// CHECK: RESET +// CHECK: SanitizerCoverage: ./coverage-reset.cc{{.*}}.sancov: 2 PCs written +// CHECK: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 2 PCs written + + fprintf(stderr, "RESET"); + __sanitizer_cov_reset(); + foo1(); + bar1(); + __sanitizer_cov_dump(); +// CHECK: RESET +// CHECK: SanitizerCoverage: ./coverage-reset.cc{{.*}}.sancov: 1 PCs written +// CHECK: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 1 PCs written + + fprintf(stderr, "RESET"); + __sanitizer_cov_reset(); + foo1(); + foo2(); + __sanitizer_cov_dump(); +// CHECK: RESET +// CHECK: SanitizerCoverage: ./coverage-reset.cc{{.*}}.sancov: 2 PCs written + + fprintf(stderr, "RESET"); + __sanitizer_cov_reset(); + bar1(); + bar2(); + __sanitizer_cov_dump(); +// CHECK: RESET +// CHECK: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 2 PCs written + + fprintf(stderr, "RESET"); + __sanitizer_cov_reset(); +// CHECK: RESET + + bar2(); +// CHECK: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 1 PCs written +} +#endif