1*7d604fb5SMark Johnston.\"- 2*7d604fb5SMark Johnston.\" Copyright (c) 2020 The FreeBSD Foundation 3*7d604fb5SMark Johnston.\" 4*7d604fb5SMark Johnston.\" This documentation was written by Mark Johnston under sponsorship from 5*7d604fb5SMark Johnston.\" the FreeBSD Foundation. 6*7d604fb5SMark Johnston.\" 7*7d604fb5SMark Johnston.\" Redistribution and use in source and binary forms, with or without 8*7d604fb5SMark Johnston.\" modification, are permitted provided that the following conditions 9*7d604fb5SMark Johnston.\" are met: 10*7d604fb5SMark Johnston.\" 1. Redistributions of source code must retain the above copyright 11*7d604fb5SMark Johnston.\" notice, this list of conditions and the following disclaimer. 12*7d604fb5SMark Johnston.\" 2. Redistributions in binary form must reproduce the above copyright 13*7d604fb5SMark Johnston.\" notice, this list of conditions and the following disclaimer in the 14*7d604fb5SMark Johnston.\" documentation and/or other materials provided with the distribution. 15*7d604fb5SMark Johnston.\" 16*7d604fb5SMark Johnston.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*7d604fb5SMark Johnston.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*7d604fb5SMark Johnston.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*7d604fb5SMark Johnston.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*7d604fb5SMark Johnston.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*7d604fb5SMark Johnston.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*7d604fb5SMark Johnston.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*7d604fb5SMark Johnston.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*7d604fb5SMark Johnston.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*7d604fb5SMark Johnston.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*7d604fb5SMark Johnston.\" SUCH DAMAGE. 27*7d604fb5SMark Johnston.\" 28*7d604fb5SMark Johnston.\" $FreeBSD$ 29*7d604fb5SMark Johnston.\" 30*7d604fb5SMark Johnston.Dd August 18, 2020 31*7d604fb5SMark Johnston.Dt KCOV 4 32*7d604fb5SMark Johnston.Os 33*7d604fb5SMark Johnston.Sh NAME 34*7d604fb5SMark Johnston.Nm kcov 35*7d604fb5SMark Johnston.Nd interface for collecting kernel code coverage information 36*7d604fb5SMark Johnston.Sh SYNOPSIS 37*7d604fb5SMark JohnstonTo compile KCOV into the kernel, place the following lines in your kernel 38*7d604fb5SMark Johnstonconfiguration file: 39*7d604fb5SMark Johnston.Bd -ragged -offset indent 40*7d604fb5SMark Johnston.Cd "options COVERAGE" 41*7d604fb5SMark Johnston.Cd "options KCOV" 42*7d604fb5SMark Johnston.Ed 43*7d604fb5SMark Johnston.Pp 44*7d604fb5SMark JohnstonThe following header file defines the application interface provided 45*7d604fb5SMark Johnstonby KCOV: 46*7d604fb5SMark Johnston.Pp 47*7d604fb5SMark Johnston.In sys/kcov.h 48*7d604fb5SMark Johnston.Sh DESCRIPTION 49*7d604fb5SMark Johnston.Nm 50*7d604fb5SMark Johnstonis a module that enables collection of code coverage information from the 51*7d604fb5SMark Johnstonkernel. 52*7d604fb5SMark JohnstonIt relies on code instrumentation enabled by the 53*7d604fb5SMark Johnston.Dv COVERAGE 54*7d604fb5SMark Johnstonkernel option. 55*7d604fb5SMark JohnstonWhen 56*7d604fb5SMark Johnston.Nm 57*7d604fb5SMark Johnstonis enabled by a user-mode thread, it collects coverage information only for 58*7d604fb5SMark Johnstonthat thread, excluding hard interrupt handlers. 59*7d604fb5SMark JohnstonAs a result, 60*7d604fb5SMark Johnston.Nm 61*7d604fb5SMark Johnstonis not suited to collect comprehensive coverage data for the entire kernel; 62*7d604fb5SMark Johnstonits main purpose is to provide input for coverage-guided system call fuzzers. 63*7d604fb5SMark Johnston.Pp 64*7d604fb5SMark JohnstonIn typical usage, a user-mode thread first allocates a chunk of memory to be 65*7d604fb5SMark Johnstonshared with 66*7d604fb5SMark Johnston.Nm . 67*7d604fb5SMark JohnstonThe thread then enables coverage tracing, with coverage data being written by 68*7d604fb5SMark Johnstonthe kernel to the shared memory region. 69*7d604fb5SMark JohnstonWhen tracing is disabled, the kernel relinquishes its access to the shared 70*7d604fb5SMark Johnstonmemory region, and the written coverage data may be consumed. 71*7d604fb5SMark Johnston.Pp 72*7d604fb5SMark JohnstonThe shared memory buffer can be treated as a 64-bit unsigned integer followed 73*7d604fb5SMark Johnstonby an array of records. 74*7d604fb5SMark JohnstonThe integer records the number of valid records and is updated by the kernel as 75*7d604fb5SMark Johnstoncoverage information is recorded. 76*7d604fb5SMark JohnstonThe state of the tracing buffer can be reset by writing the value 0 to this 77*7d604fb5SMark Johnstonfield. 78*7d604fb5SMark JohnstonThe record layout depends on the tracing mode set using the 79*7d604fb5SMark Johnston.Dv KIOENABLE 80*7d604fb5SMark Johnstonioctl. 81*7d604fb5SMark Johnston.Pp 82*7d604fb5SMark JohnstonTwo tracing modes are implemented, 83*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_PC 84*7d604fb5SMark Johnstonand 85*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_CMP . 86*7d604fb5SMark JohnstonPC-tracing records a program counter value for each basic block executed while 87*7d604fb5SMark Johnstontracing is enabled. 88*7d604fb5SMark JohnstonIn this mode, each record is a single 64-bit unsigned integer containing the 89*7d604fb5SMark Johnstonprogram counter value. 90*7d604fb5SMark JohnstonComparison tracing provides information about data flow; information about 91*7d604fb5SMark Johnstondynamic variable comparisons is recorded. 92*7d604fb5SMark JohnstonSuch records provide information about the results of 93*7d604fb5SMark Johnston.Xr c 7 94*7d604fb5SMark Johnston.Ql if 95*7d604fb5SMark Johnstonor 96*7d604fb5SMark Johnston.Ql switch 97*7d604fb5SMark Johnstonstatements, for example. 98*7d604fb5SMark JohnstonIn this mode each record consists of four 64-bit unsigned integers. 99*7d604fb5SMark JohnstonThe first integer is a bitmask defining attributes of the variables involved in 100*7d604fb5SMark Johnstonthe comparison. 101*7d604fb5SMark Johnston.Dv KCOV_CMP_CONST 102*7d604fb5SMark Johnstonis set if one of the variables has a constant value at compile-time, and 103*7d604fb5SMark Johnston.Dv KCOV_CMP_SIZE(n) 104*7d604fb5SMark Johnstonspecifies the width of the variables: 105*7d604fb5SMark Johnston.Pp 106*7d604fb5SMark Johnston.Bl -inset -offset indent -compact 107*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(0) : 108*7d604fb5SMark Johnstona comparison of 8-bit integers 109*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(1) : 110*7d604fb5SMark Johnstona comparison of 16-bit integers 111*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(2) : 112*7d604fb5SMark Johnstona comparison of 32-bit integers 113*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(3) : 114*7d604fb5SMark Johnstona comparison of 64-bit integers 115*7d604fb5SMark Johnston.El 116*7d604fb5SMark Johnston.Pp 117*7d604fb5SMark JohnstonThe second and third fields record the values of the two variables, and the 118*7d604fb5SMark Johnstonfourth and final field stores the program counter value of the comparison. 119*7d604fb5SMark Johnston.Sh IOCTL INTERFACE 120*7d604fb5SMark JohnstonApplications interact with 121*7d604fb5SMark Johnston.Nm 122*7d604fb5SMark Johnstonusing the 123*7d604fb5SMark Johnston.Xr ioctl 2 124*7d604fb5SMark Johnstonsystem call. 125*7d604fb5SMark JohnstonEach thread making use of 126*7d604fb5SMark Johnston.Nm 127*7d604fb5SMark Johnstonmust use a separate file descriptor for 128*7d604fb5SMark Johnston.Fa /dev/kcov . 129*7d604fb5SMark JohnstonThe following ioctls are defined: 130*7d604fb5SMark Johnston.Bl -tag -width indent 131*7d604fb5SMark Johnston.It Dv KIOSETBUFSIZE Fa size_t entries 132*7d604fb5SMark JohnstonSet the size of the tracing buffer in units of 133*7d604fb5SMark Johnston.Dv KCOV_ENTRY_SIZE . 134*7d604fb5SMark JohnstonThe buffer may then be mapped into the calling thread's address space by 135*7d604fb5SMark Johnstoncalling 136*7d604fb5SMark Johnston.Xr mmap 2 137*7d604fb5SMark Johnstonon the 138*7d604fb5SMark Johnston.Nm 139*7d604fb5SMark Johnstondevice file. 140*7d604fb5SMark Johnston.It Dv KIOENABLE Fa int mode 141*7d604fb5SMark JohnstonEnable coverage tracing for the calling thread. 142*7d604fb5SMark JohnstonValid modes are 143*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_PC 144*7d604fb5SMark Johnstonand 145*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_CMP . 146*7d604fb5SMark Johnston.It Dv KIODISABLE 147*7d604fb5SMark JohnstonDisable coverage tracing for the calling thread. 148*7d604fb5SMark Johnston.El 149*7d604fb5SMark Johnston.Sh FILES 150*7d604fb5SMark Johnston.Nm 151*7d604fb5SMark Johnstoncreates the 152*7d604fb5SMark Johnston.Pa /dev/kcov 153*7d604fb5SMark Johnstondevice file. 154*7d604fb5SMark Johnston.Sh EXAMPLES 155*7d604fb5SMark JohnstonThe following code sample collects information about basic block coverage for 156*7d604fb5SMark Johnstonkernel code executed while printing 157*7d604fb5SMark Johnston.Ql "Hello, world" . 158*7d604fb5SMark Johnston.Bd -literal 159*7d604fb5SMark Johnstonsize_t sz; 160*7d604fb5SMark Johnstonuint64_t *buf; 161*7d604fb5SMark Johnstonint fd; 162*7d604fb5SMark Johnston 163*7d604fb5SMark Johnstonfd = open("/dev/kcov", O_RDWR); 164*7d604fb5SMark Johnstonif (fd == -1) 165*7d604fb5SMark Johnston err(1, "open(/dev/kcov)"); 166*7d604fb5SMark Johnstonsz = 1ul << 20; /* 1MB */ 167*7d604fb5SMark Johnstonif (ioctl(fd, KIOSETBUFSIZE, sz / KCOV_ENTRY_SIZE) != 0) 168*7d604fb5SMark Johnston err(1, "ioctl(KIOSETBUFSIZE)"); 169*7d604fb5SMark Johnstonbuf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 170*7d604fb5SMark Johnstonif (buf == MAP_FAILED) 171*7d604fb5SMark Johnston err(1, "mmap"); 172*7d604fb5SMark Johnston 173*7d604fb5SMark Johnston/* Enable PC tracing. */ 174*7d604fb5SMark Johnstonif (ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) != 0) 175*7d604fb5SMark Johnston err(1, "ioctl(KIOENABLE)"); 176*7d604fb5SMark Johnston 177*7d604fb5SMark Johnston/* Clear trace records from the preceding ioctl() call. */ 178*7d604fb5SMark Johnstonbuf[0] = 0; 179*7d604fb5SMark Johnston 180*7d604fb5SMark Johnstonprintf("Hello, world!\\n"); 181*7d604fb5SMark Johnston 182*7d604fb5SMark Johnston/* Disable PC tracing. */ 183*7d604fb5SMark Johnstonif (ioctl(fd, KIODISABLE, 0) != 0) 184*7d604fb5SMark Johnston err(1, "ioctl(KIODISABLE)"); 185*7d604fb5SMark Johnston 186*7d604fb5SMark Johnstonfor (uint64_t i = 1; i < buf[0]; i++) 187*7d604fb5SMark Johnston printf("%#jx\\n", (uintmax_t)buf[i]); 188*7d604fb5SMark Johnston.Ed 189*7d604fb5SMark JohnstonThe output of this program can be approximately mapped to line numbers 190*7d604fb5SMark Johnstonin kernel source code: 191*7d604fb5SMark Johnston.Bd -literal 192*7d604fb5SMark Johnston# ./kcov-test | sed 1d | addr2line -e /usr/lib/debug/boot/kernel/kernel.debug 193*7d604fb5SMark Johnston.Ed 194*7d604fb5SMark Johnston.Sh SEE ALSO 195*7d604fb5SMark Johnston.Xr ioctl 2 , 196*7d604fb5SMark Johnston.Xr mmap 2 197*7d604fb5SMark Johnston.Sh HISTORY 198*7d604fb5SMark Johnston.Nm 199*7d604fb5SMark Johnstonfirst appeared in 200*7d604fb5SMark Johnston.Fx 13.0 . 201*7d604fb5SMark Johnston.Sh BUGS 202*7d604fb5SMark JohnstonThe 203*7d604fb5SMark Johnston.Fx 204*7d604fb5SMark Johnstonimplementation of 205*7d604fb5SMark Johnston.Nm 206*7d604fb5SMark Johnstondoes not yet support remote tracing. 207