diff options
Diffstat (limited to 'lib/sanitizer_common/sanitizer_coverage_libcdep.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_coverage_libcdep.cc | 94 |
1 files changed, 61 insertions, 33 deletions
diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 8f0076f2c..47ddba423 100644 --- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -58,12 +58,15 @@ static atomic_uintptr_t coverage_counter; static bool cov_sandboxed = false; static int cov_fd = kInvalidFd; static unsigned int cov_max_block_size = 0; +static bool coverage_enabled = false; +static const char *coverage_dir; namespace __sanitizer { class CoverageData { public: void Init(); + void ReInit(); void BeforeFork(); void AfterFork(int child_pid); void Extend(uptr npcs); @@ -130,15 +133,16 @@ class CoverageData { StaticSpinMutex mu; void DirectOpen(); - void ReInit(); }; static CoverageData coverage_data; +void CovUpdateMapping(const char *path, uptr caller_pc = 0); + void CoverageData::DirectOpen() { InternalScopedString path(kMaxPathLength); internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.raw", - common_flags()->coverage_dir, internal_getpid()); + coverage_dir, internal_getpid()); pc_fd = OpenFile(path.data(), true); if (internal_iserror(pc_fd)) { Report(" Coverage: failed to open %s for writing\n", path.data()); @@ -146,7 +150,7 @@ void CoverageData::DirectOpen() { } pc_array_mapped_size = 0; - CovUpdateMapping(); + CovUpdateMapping(coverage_dir); } void CoverageData::Init() { @@ -178,16 +182,22 @@ void CoverageData::Init() { } void CoverageData::ReInit() { - internal_munmap(pc_array, sizeof(uptr) * kPcArrayMaxSize); + if (pc_array) { + internal_munmap(pc_array, sizeof(uptr) * kPcArrayMaxSize); + pc_array = nullptr; + } if (pc_fd != kInvalidFd) internal_close(pc_fd); - if (common_flags()->coverage_direct) { - // In memory-mapped mode we must extend the new file to the known array - // size. - uptr size = atomic_load(&pc_array_size, memory_order_relaxed); - Init(); - if (size) Extend(size); - } else { - Init(); + if (coverage_enabled) { + if (common_flags()->coverage_direct) { + // In memory-mapped mode we must extend the new file to the known array + // size. + uptr size = atomic_load(&pc_array_size, memory_order_relaxed); + Init(); + if (size) Extend(size); + if (coverage_enabled) CovUpdateMapping(coverage_dir); + } else { + Init(); + } } } @@ -206,13 +216,13 @@ void CoverageData::Extend(uptr npcs) { if (!common_flags()->coverage_direct) return; SpinMutexLock l(&mu); - if (pc_fd == kInvalidFd) DirectOpen(); - CHECK_NE(pc_fd, kInvalidFd); - uptr size = atomic_load(&pc_array_size, memory_order_relaxed); size += npcs * sizeof(uptr); - if (size > pc_array_mapped_size) { + if (coverage_enabled && size > pc_array_mapped_size) { + if (pc_fd == kInvalidFd) DirectOpen(); + CHECK_NE(pc_fd, kInvalidFd); + uptr new_mapped_size = pc_array_mapped_size; while (size > new_mapped_size) new_mapped_size += kPcArrayMmapSize; CHECK_LE(new_mapped_size, sizeof(uptr) * kPcArrayMaxSize); @@ -361,15 +371,14 @@ static int CovOpenFile(bool packed, const char *name, InternalScopedString path(kMaxPathLength); if (!packed) { CHECK(name); - path.append("%s/%s.%zd.%s", common_flags()->coverage_dir, name, - internal_getpid(), extension); + path.append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(), + extension); } else { if (!name) - path.append("%s/%zd.%s.packed", common_flags()->coverage_dir, - internal_getpid(), extension); - else - path.append("%s/%s.%s.packed", common_flags()->coverage_dir, name, + path.append("%s/%zd.%s.packed", coverage_dir, internal_getpid(), extension); + else + path.append("%s/%s.%s.packed", coverage_dir, name, extension); } uptr fd = OpenFile(path.data(), true); if (internal_iserror(fd)) { @@ -455,7 +464,7 @@ void CoverageData::DumpCallerCalleePairs() { // 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) { - CHECK(common_flags()->coverage); + CHECK(coverage_enabled); uptr idx = *cache; if (!idx) { CHECK_LT(tr_pc_array_index, kTrPcArrayMaxSize); @@ -492,7 +501,7 @@ static void CovDumpAsBitSet() { // Dump the coverage on disk. static void CovDump() { - if (!common_flags()->coverage || common_flags()->coverage_direct) return; + if (!coverage_enabled || common_flags()->coverage_direct) return; #if !SANITIZER_WINDOWS if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed)) return; @@ -532,8 +541,8 @@ static void CovDump() { } else { // One file per module per process. path.clear(); - path.append("%s/%s.%zd.sancov", common_flags()->coverage_dir, - module_name, internal_getpid()); + path.append("%s/%s.%zd.sancov", coverage_dir, module_name, + internal_getpid()); int fd = CovOpenFile(false /* packed */, module_name); if (fd > 0) { internal_write(fd, offsets.data(), offsets.size() * sizeof(u32)); @@ -553,7 +562,7 @@ static void CovDump() { void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) { if (!args) return; - if (!common_flags()->coverage) return; + if (!coverage_enabled) return; cov_sandboxed = args->coverage_sandboxed; if (!cov_sandboxed) return; cov_fd = args->coverage_fd; @@ -565,7 +574,7 @@ void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) { int MaybeOpenCovFile(const char *name) { CHECK(name); - if (!common_flags()->coverage) return -1; + if (!coverage_enabled) return -1; return CovOpenFile(true /* packed */, name); } @@ -577,6 +586,24 @@ void CovAfterFork(int child_pid) { coverage_data.AfterFork(child_pid); } +void InitializeCoverage(bool enabled, const char *dir) { + coverage_enabled = enabled; + coverage_dir = dir; + if (enabled) coverage_data.Init(); + if (!common_flags()->coverage_direct) Atexit(__sanitizer_cov_dump); +} + +void ReInitializeCoverage(bool enabled, const char *dir) { + coverage_enabled = enabled; + coverage_dir = dir; + coverage_data.ReInit(); +} + +void CoverageUpdateMapping() { + if (coverage_enabled) + CovUpdateMapping(coverage_dir); +} + } // namespace __sanitizer extern "C" { @@ -589,19 +616,20 @@ __sanitizer_cov_indir_call16(uptr callee, uptr callee_cache16[]) { coverage_data.IndirCall(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()), callee, callee_cache16, 16); } -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { + coverage_enabled = true; + coverage_dir = common_flags()->coverage_dir; coverage_data.Init(); } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init(s32 **guards, uptr npcs) { coverage_data.InitializeGuards(guards, npcs); - if (!common_flags()->coverage || !common_flags()->coverage_direct) - return; - if (SANITIZER_ANDROID) { + if (!common_flags()->coverage_direct) return; + if (SANITIZER_ANDROID && coverage_enabled) { // dlopen/dlclose interceptors do not work on Android, so we rely on // Extend() calls to update .sancov.map. - CovUpdateMapping(GET_CALLER_PC()); + CovUpdateMapping(coverage_dir, GET_CALLER_PC()); } coverage_data.Extend(npcs); } |