From 38c228a8427d3765bb393258806213ed6a8566c0 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 5 Jun 2014 14:38:53 +0000 Subject: [PATCH] [asancov] Faster coverage in memory-mapped mode. Use caller pc of __sanitizer_cov_module_init to figure out when 2 sequential calls are from the same module; skip .sancov.map file update in this case. llvm-svn: 210267 --- .../lib/sanitizer_common/sanitizer_common.h | 2 +- .../sanitizer_common/sanitizer_coverage_libcdep.cc | 12 ++++---- .../sanitizer_coverage_mapping_libcdep.cc | 33 +++++++++++++--------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 435e1fa..02271e7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -192,7 +192,7 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args); void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args); void SetSandboxingCallback(void (*f)()); -void CovUpdateMapping(); +void CovUpdateMapping(uptr caller_pc = 0); void CovBeforeFork(); void CovAfterFork(int child_pid); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 206d07c..ba6c58c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -174,12 +174,6 @@ void CoverageData::Extend(uptr npcs) { } atomic_store(&pc_array_size, size, memory_order_release); - - if (SANITIZER_ANDROID) { - // dlopen/dlclose interceptors do not work on Android, so we rely on - // Extend() calls to update .sancov.map. - CovUpdateMapping(); - } } // Simply add the pc into the vector under lock. If the function is called more @@ -371,6 +365,12 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { coverage_data.Init(); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init(uptr npcs) { + if (SANITIZER_ANDROID && common_flags()->coverage && + common_flags()->coverage_direct) { + // dlopen/dlclose interceptors do not work on Android, so we rely on + // Extend() calls to update .sancov.map. + CovUpdateMapping(GET_CALLER_PC()); + } coverage_data.Extend(npcs); } SANITIZER_INTERFACE_ATTRIBUTE diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc index bfeb321..28c9369 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc @@ -40,30 +40,36 @@ static const uptr kMaxTextSize = 64 * 1024; struct CachedMapping { public: - bool TestAndUpdate(const char *new_mapping) { + bool NeedsUpdate(uptr pc) { int new_pid = internal_getpid(); - if (last_mapping && last_pid == new_pid && - internal_strcmp(last_mapping, new_mapping) == 0) + if (last_pid == new_pid && pc && pc >= last_range_start && + pc < last_range_end) return false; - if (!last_mapping) last_mapping = (char *)InternalAlloc(kMaxTextSize); last_pid = new_pid; - internal_strncpy(last_mapping, new_mapping, kMaxTextSize); return true; } + void SetModuleRange(uptr start, uptr end) { + last_range_start = start; + last_range_end = end; + } + private: - char *last_mapping; + uptr last_range_start, last_range_end; int last_pid; }; static CachedMapping cached_mapping; static StaticSpinMutex mapping_mu; -void CovUpdateMapping() { +void CovUpdateMapping(uptr caller_pc) { if (!common_flags()->coverage || !common_flags()->coverage_direct) return; SpinMutexLock l(&mapping_mu); + if (!cached_mapping.NeedsUpdate(caller_pc)) + return; + InternalScopedString text(kMaxTextSize); InternalScopedBuffer modules_data(kMaxNumberOfModules * sizeof(LoadedModule)); @@ -76,17 +82,16 @@ void CovUpdateMapping() { for (int i = 0; i < n_modules; ++i) { char *module_name = StripModuleName(modules[i].full_name()); for (unsigned j = 0; j < modules[i].n_ranges(); ++j) { - text.append("%zx %zx %zx %s\n", modules[i].address_range_start(j), - modules[i].address_range_end(j), modules[i].base_address(), - module_name); + uptr start = modules[i].address_range_start(j); + uptr end = modules[i].address_range_end(j); + uptr base = modules[i].base_address(); + text.append("%zx %zx %zx %s\n", start, end, base, module_name); + if (caller_pc && caller_pc >= start && caller_pc < end) + cached_mapping.SetModuleRange(start, end); } InternalFree(module_name); } - // Do not write mapping if it is the same as the one we've wrote last time. - if (!cached_mapping.TestAndUpdate(text.data())) - return; - int err; InternalScopedString tmp_path(64 + internal_strlen(common_flags()->coverage_dir)); -- 2.7.4