diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -2489,7 +2489,8 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *, u32 *) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg, + const uptr *end) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp @@ -151,6 +151,44 @@ static TracePcGuardController pc_guard_controller; +// A basic default implementation of callbacks for +// -fsanitize-coverage=inline-8bit-counters,pc-table. +// Use TOOL_OPTIONS (UBSAN_OPTIONS, etc) to dump the coverage data: +// * cov_8bit_counters_out=PATH to dump the 8bit counters. +// * cov_pcs_out=PATH to dump the pc table. +// +// Most users will still need to define their own callbacks for greater +// flexibility. +namespace SingletonCounterCoverage { + +static char *counters_start, *counters_end; + +static void DumpCoverage() { + const char* file_path = common_flags()->cov_8bit_counters_out; + if (!file_path || !internal_strlen(file_path)) + return; + fd_t fd = OpenFile(file_path); + FileCloser file_closer(fd); + WriteToFile(fd, counters_start, counters_end - counters_start); +} + +static void Cov8bitCountersInit(char* beg, char* end) { + counters_start = beg; + counters_end = end; + Atexit(DumpCoverage); +} + +static void CovPcsInit(const uptr* pcs_beg, const uptr* pcs_end) { + const char* file_path = common_flags()->cov_pcs_out; + if (!file_path || !internal_strlen(file_path)) + return; + fd_t fd = OpenFile(file_path); + FileCloser file_closer(fd); + WriteToFile(fd, pcs_beg, (pcs_end - pcs_beg) * sizeof(uptr)); +} + +} // namespace SingletonCounterCoverage + } // namespace } // namespace __sancov @@ -191,7 +229,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_reset() { __sancov::pc_guard_controller.Reset(); } -// Default empty implementations (weak). Users should redefine them. +// Default implementations (weak). +// Either empty or very simple. +// Most users should redefine them. SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} @@ -206,9 +246,15 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_8bit_counters_init, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_8bit_counters_init, + char* start, char* end) { + __sancov::SingletonCounterCoverage::Cov8bitCountersInit(start, end); +} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_bool_flag_init, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr* beg, + const uptr* end) { + __sancov::SingletonCounterCoverage::CovPcsInit(beg, end); +} } // extern "C" // Weak definition for code instrumented with -fsanitize-coverage=stack-depth // and later linked with code containing a strong definition. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -160,6 +160,10 @@ COMMON_FLAG(const char *, coverage_dir, ".", "Target directory for coverage dumps. Defaults to the current " "directory.") +COMMON_FLAG(const char *, cov_8bit_counters_out, "", + "If non-empty, write 8bit counters to this file. ") +COMMON_FLAG(const char *, cov_pcs_out, "", + "If non-empty, write the coverage pc table to this file. ") COMMON_FLAG(bool, full_address_space, false, "Sanitize complete address space; " "by default kernel area on 32-bit platforms will not be sanitized") diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h @@ -111,12 +111,13 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_cov_trace_pc_guard_init(__sanitizer::u32*, __sanitizer::u32*); - SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE - void __sanitizer_cov_8bit_counters_init(); + SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void + __sanitizer_cov_8bit_counters_init(char *, char *); SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_cov_bool_flag_init(); SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void - __sanitizer_cov_pcs_init(); + __sanitizer_cov_pcs_init(const __sanitizer::uptr *, + const __sanitizer::uptr *); } // extern "C" #endif // SANITIZER_INTERFACE_INTERNAL_H diff --git a/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp @@ -0,0 +1,22 @@ +// Tests the default implementation of callbacks for +// -fsanitize-coverage=inline-8bit-counters,pc-table + +// REQUIRES: has_sancovcc,stable-runtime,linux,x86_64-target-arch + +// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters,pc-table -o %t +// RUN: rm -f %t-counters %t-pcs +// RUN: env %tool_options="cov_8bit_counters_out=%t-counters cov_pcs_out=%t-pcs" %run %t 2>&1 | FileCheck %s + +// Check the file sizes +// RUN: wc -c %t-counters | grep "^2 " +// RUN: wc -c %t-pcs | grep "^32 " + +#include + +__attribute__((noinline)) void foo() {} +int main() { + foo(); + foo(); + fprintf(stderr, "PASS\n"); + // CHECK: PASS +}