aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2025-08-01 15:51:36 +0200
committerAlexander Potapenko <glider@google.com>2025-08-05 13:16:45 +0000
commit1458b364e100752374725b0cbf83b70a54b327d3 (patch)
tree4437ea4df3ad5d08a0b052ed22a1152fcbe011ea /executor
parenta4acbebb7c7f9bc7ff56c2e6a0e452aa6438fc11 (diff)
executor: introduce cover_close()
Right now closing a kcov fd on Linux won't disable coverage, so further attempts to open an fd and enable coverage on the same thread will not work. Add cover_close() which will disable the coverage if necessary, and close the file descriptor.
Diffstat (limited to 'executor')
-rw-r--r--executor/executor.cc2
-rw-r--r--executor/executor_linux.h19
2 files changed, 19 insertions, 2 deletions
diff --git a/executor/executor.cc b/executor/executor.cc
index 704a284a9..53c52efc3 100644
--- a/executor/executor.cc
+++ b/executor/executor.cc
@@ -376,6 +376,8 @@ struct cover_t {
intptr_t pc_offset;
// The coverage buffer has overflowed and we have truncated coverage.
bool overflow;
+ // True if cover_enable() was called for this object.
+ bool enabled;
};
struct thread_t {
diff --git a/executor/executor_linux.h b/executor/executor_linux.h
index e13f7bd8d..bbc5dfff0 100644
--- a/executor/executor_linux.h
+++ b/executor/executor_linux.h
@@ -119,6 +119,19 @@ static void cover_open(cover_t* cov, bool extra)
debug("pkey protection enabled\n");
}
+static void cover_close(cover_t* cov)
+{
+ if (cov->fd == -1)
+ fail("attempting to close an invalid cover fd");
+ if (cov->enabled) {
+ if (ioctl(cov->fd, KCOV_DISABLE, 0))
+ fail("KCOV_DISABLE failed");
+ cov->enabled = false;
+ }
+ close(cov->fd);
+ cov->fd = -1;
+}
+
static void cover_protect(cover_t* cov)
{
if (pkeys_enabled && pkey_set(RESERVED_PKEY, PKEY_DISABLE_WRITE))
@@ -175,6 +188,7 @@ static void cover_enable(cover_t* cov, bool collect_comps, bool extra)
if (!extra) {
if (ioctl(cov->fd, KCOV_ENABLE, kcov_mode))
exitf("cover enable write trace failed, mode=%d", kcov_mode);
+ cov->enabled = true;
return;
}
kcov_remote_arg<1> arg = {
@@ -187,6 +201,7 @@ static void cover_enable(cover_t* cov, bool collect_comps, bool extra)
arg.handles[0] = kcov_remote_handle(KCOV_SUBSYSTEM_USB, procid + 1);
if (ioctl(cov->fd, KCOV_REMOTE_ENABLE, &arg))
exitf("remote cover enable write trace failed");
+ cov->enabled = true;
}
static void cover_reset(cover_t* cov)
@@ -321,7 +336,7 @@ static const char* setup_delay_kcov()
munmap(cov.mmap_alloc_ptr, cov.mmap_alloc_size);
}
munmap(first, cov.mmap_alloc_size);
- close(cov.fd);
+ cover_close(&cov);
return error;
}
@@ -347,7 +362,7 @@ static const char* setup_kcov_reset_ioctl()
error = "kernel does not support ioctl(KCOV_RESET_TRACE)";
}
cover_munmap(&cov);
- close(cov.fd);
+ cover_close(&cov);
return error;
}