KCOV(4)                 NetBSD Kernel Interfaces Manual                KCOV(4)

     kcov -- kernel code coverage tracing

     options KCOV

     #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 ker-
     nel program counter to be collected during syscalls triggered by the same

     The kcov descriptors (KD) are allocated during open(2), and are associ-
     ated 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 configura-
     tion makeoptions KCOV options KCOV to be present, see options(4).

     The following ioctl(2) calls are provided:

     KCOV_IOC_SETBUFSIZE uint64_t *nentries
           Allocate a coverage buffer with a capacity of nentries.  The buffer
           can be accessed using mmap(2) whereas the returned pointer must be
           interpreted as an array of kcov_int_t entries.  Note that
           kcov_int_t is volatile.  The first entry contains the number of
           entries in the array, excluding the first entry.

     KCOV_IOC_ENABLE int *mode
           Enable code coverage tracing for the current thread.  The mode must
           be one of the following:

           No trace selected.  This option is useful for testing the kcov

           Trace the kernel program counter.

           Trace comparison instructions and switch statements.  For switch
           statements, the number of traced comparison instructions is equal
           to the number of switch cases.  Each traced comparison instruction
           is represented by 4 entries in the coverage buffer:

           1.   A mask where the least significant bit is set if one of the
                comparison operands is a compile-time constant, which is
                always true for switch statements.  The remaining bits repre-
                sents the log2 size of the operands, ranging from 0 to 3.

           2.   First comparison operand.  For switch statements, this operand
                corresponds to the case value.

           3.   Second comparison operand.  For switch statements, this oper-
                and corresponds to the value passed to switch.

           4.   Kernel program counter where the comparison instruction took

           In this mode, the first entry in the coverage buffer reflects the
           number of traced comparison instructions.  Thus, the effective num-
           ber of entries in the coverage buffer is given by multiplying the
           first entry by 4.

           Disable code coverage tracing for the current thread.

     /dev/kcov  Default device node.

     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 trans-
     late the kernel program counter into the file name and line number it
     corresponds to.

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

             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");

             return 0;


     The kcov driver was initially developed in Linux.  A driver based on the
     same concept was then implemented in NetBSD 9.

     Siddharth Muralee <siddharth.muralee@gmail.com>

NetBSD 9.0                       May 28, 2019                       NetBSD 9.0

You can also request any man page by name and (optionally) by section:


Use the DEFAULT collection to view manual pages for third-party software.

©1994 Man-cgi 1.15, Panagiotis Christias
©1996-2019 Modified for NetBSD by Kimmo Suominen