KCOV(4) | Device Drivers Manual | KCOV(4) |
kcov
—
options KCOV
#include <sys/kcov.h>
kcov
driver implements collection of code coverage
inside the kernel. It can be enabled on a per thread basis from userland,
allowing the kernel program counter to be collected during syscalls triggered
by the same thread.
The kcov
descriptors (KD) are allocated
during open(2), and are
associated with a file descriptor. A thread can enable the
kcov
device. When this happens, this thread becomes
the owner of the kcov
descriptors (KD), and no
thread can disable this KD except the owner.
A kcov
descriptor (KD) is freed when its
file descriptor is closed iff the KD is not active on a thread. If it is, we
ask the thread to free it when it exits.
The collected coverage can be accessed by mapping the device using mmap(2). The buffers are mapped without risk that the kernel frees a buffer still mapped in a process.
By default, kcov
is not enabled but
requires the compile-time configuration makeoptions
KCOV
options KCOV
to be present, see
options(4).
The following ioctl(2) calls are provided:
KCOV_IOC_SETBUFSIZE
uint64_t *nentriesKCOV_IOC_ENABLE
int *modeKCOV_MODE_NONE
kcov
device.KCOV_MODE_TRACE_PC
KCOV_MODE_TRACE_CMP
In this mode, the first entry in the coverage buffer reflects the number of traced comparison instructions. Thus, the effective number of entries in the coverage buffer is given by multiplying the first entry by 4.
KCOV_IOC_DISABLE
void#include <err.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioccom.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/kcov.h> int main(void) { kcov_int_t *cover, i, n; uint64_t size = 1024 * 100; int fd; int mode; fd = open("/dev/kcov", O_RDWR); if (fd == -1) err(1, "open"); if (ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) == -1) err(1, "ioctl: KCOV_IOC_SETBUFSIZE"); cover = mmap(NULL, size * KCOV_ENTRY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (cover == MAP_FAILED) err(1, "mmap"); mode = KCOV_MODE_TRACE_PC; if (ioctl(fd, KCOV_IOC_ENABLE, &mode) == -1) err(1, "ioctl: KCOV_IOC_ENABLE"); cover[0] = 0; read(-1, NULL, 0); /* syscall paths to be traced */ n = cover[0]; if (ioctl(fd, KCOV_IOC_DISABLE) == -1) err(1, "ioctl: KCOV_IOC_DISABLE"); for (i = 0; i < n; i++) printf("%p\n", (void *)cover[i + 1]); if (munmap(cover, size * KCOV_ENTRY_SIZE) == -1) err(1, "munmap"); close(fd); return 0; }
kcov
driver was initially developed in Linux. A
driver based on the same concept was then implemented in
NetBSD 9.
May 28, 2019 | NetBSD 9.4 |