| 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_NONEkcov device.KCOV_MODE_TRACE_PCKCOV_MODE_TRACE_CMPIn 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 |