KCOV(4) | Device Drivers Manual | KCOV(4) |
kcov
— kernel code
coverage tracing
pseudo-device kcov 1
#include <sys/kcov.h>
The 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 collected coverage can be
accessed by mapping the device using
mmap(2).
By default, kcov
is not enabled but
instead requires the following line to be present in the kernel
configuration:
pseudo-device kcov 1
The following ioctl(2) calls are provided:
KIOSETBUFSIZE
unsigned long *nentriesKIOENABLE
int *modeKIOREMOTEATTACH
. The
mode must be one of the following:
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.
KIODISABLE
voidKIOREMOTEATTACH
struct kio_remote_attach *remotestruct kio_remote_attach { int subsystem; int id; };
The subsystem field must be one of the following:
KCOV_REMOTE_COMMON
In the following example, the read(2) syscall is traced and the coverage displayed, which in turn can be passed to addr2line(1) in order to translate the kernel program counter into the file name and line number it corresponds to.
#include <sys/ioctl.h> #include <sys/kcov.h> #include <sys/mman.h> #include <err.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { unsigned long *cover, i; unsigned long size = 1024; int fd, mode; fd = open("/dev/kcov", O_RDWR); if (fd == -1) err(1, "open"); if (ioctl(fd, KIOSETBUFSIZE, &size) == -1) err(1, "ioctl: KIOSETBUFSIZE"); cover = mmap(NULL, size * sizeof(unsigned long), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (cover == MAP_FAILED) err(1, "mmap"); mode = KCOV_MODE_TRACE_PC; if (ioctl(fd, KIOENABLE, &mode) == -1) err(1, "ioctl: KIOENABLE"); read(-1, NULL, 0); if (ioctl(fd, KIODISABLE) == -1) err(1, "ioctl: KIODISABLE"); for (i = 0; i < cover[0]; i++) printf("%p\n", (void *)cover[i + 1]); if (munmap(cover, size * sizeof(unsigned long)) == -1) err(1, "munmap"); close(fd); return 0; }
The kcov
driver first appeared in
OpenBSD 6.4.
The kcov
driver was written by
Anton Lindqvist
<anton@openbsd.org>.
The kcov
driver is limited to
architectures using clang(1)
as their default compiler.
August 1, 2020 | OpenBSD-6.8 |