| 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 |