summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/sanitizer_coverage_libcdep.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_coverage_libcdep.cc94
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);
}