xref: /freebsd/share/man/man4/kcov.4 (revision fa9896e082a1046ff4fbc75fcba4d18d1f2efc19)
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.Dd August 18, 2020
29*7d604fb5SMark Johnston.Dt KCOV 4
30*7d604fb5SMark Johnston.Os
31*7d604fb5SMark Johnston.Sh NAME
32*7d604fb5SMark Johnston.Nm kcov
33*7d604fb5SMark Johnston.Nd interface for collecting kernel code coverage information
34*7d604fb5SMark Johnston.Sh SYNOPSIS
35*7d604fb5SMark JohnstonTo compile KCOV into the kernel, place the following lines in your kernel
36*7d604fb5SMark Johnstonconfiguration file:
37*7d604fb5SMark Johnston.Bd -ragged -offset indent
38*7d604fb5SMark Johnston.Cd "options COVERAGE"
39*7d604fb5SMark Johnston.Cd "options KCOV"
40*7d604fb5SMark Johnston.Ed
41*7d604fb5SMark Johnston.Pp
42*7d604fb5SMark JohnstonThe following header file defines the application interface provided
43*7d604fb5SMark Johnstonby KCOV:
44*7d604fb5SMark Johnston.Pp
45*7d604fb5SMark Johnston.In sys/kcov.h
46*7d604fb5SMark Johnston.Sh DESCRIPTION
47*7d604fb5SMark Johnston.Nm
48*7d604fb5SMark Johnstonis a module that enables collection of code coverage information from the
49*7d604fb5SMark Johnstonkernel.
50*7d604fb5SMark JohnstonIt relies on code instrumentation enabled by the
51*7d604fb5SMark Johnston.Dv COVERAGE
52*7d604fb5SMark Johnstonkernel option.
53*7d604fb5SMark JohnstonWhen
54*7d604fb5SMark Johnston.Nm
55*7d604fb5SMark Johnstonis enabled by a user-mode thread, it collects coverage information only for
56*7d604fb5SMark Johnstonthat thread, excluding hard interrupt handlers.
57*7d604fb5SMark JohnstonAs a result,
58*7d604fb5SMark Johnston.Nm
59*7d604fb5SMark Johnstonis not suited to collect comprehensive coverage data for the entire kernel;
60*7d604fb5SMark Johnstonits main purpose is to provide input for coverage-guided system call fuzzers.
61*7d604fb5SMark Johnston.Pp
62*7d604fb5SMark JohnstonIn typical usage, a user-mode thread first allocates a chunk of memory to be
63*7d604fb5SMark Johnstonshared with
64*7d604fb5SMark Johnston.Nm .
65*7d604fb5SMark JohnstonThe thread then enables coverage tracing, with coverage data being written by
66*7d604fb5SMark Johnstonthe kernel to the shared memory region.
67*7d604fb5SMark JohnstonWhen tracing is disabled, the kernel relinquishes its access to the shared
68*7d604fb5SMark Johnstonmemory region, and the written coverage data may be consumed.
69*7d604fb5SMark Johnston.Pp
70*7d604fb5SMark JohnstonThe shared memory buffer can be treated as a 64-bit unsigned integer followed
71*7d604fb5SMark Johnstonby an array of records.
72*7d604fb5SMark JohnstonThe integer records the number of valid records and is updated by the kernel as
73*7d604fb5SMark Johnstoncoverage information is recorded.
74*7d604fb5SMark JohnstonThe state of the tracing buffer can be reset by writing the value 0 to this
75*7d604fb5SMark Johnstonfield.
76*7d604fb5SMark JohnstonThe record layout depends on the tracing mode set using the
77*7d604fb5SMark Johnston.Dv KIOENABLE
78*7d604fb5SMark Johnstonioctl.
79*7d604fb5SMark Johnston.Pp
80*7d604fb5SMark JohnstonTwo tracing modes are implemented,
81*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_PC
82*7d604fb5SMark Johnstonand
83*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_CMP .
84*7d604fb5SMark JohnstonPC-tracing records a program counter value for each basic block executed while
85*7d604fb5SMark Johnstontracing is enabled.
86*7d604fb5SMark JohnstonIn this mode, each record is a single 64-bit unsigned integer containing the
87*7d604fb5SMark Johnstonprogram counter value.
88*7d604fb5SMark JohnstonComparison tracing provides information about data flow; information about
89*7d604fb5SMark Johnstondynamic variable comparisons is recorded.
90*7d604fb5SMark JohnstonSuch records provide information about the results of
91*7d604fb5SMark Johnston.Xr c 7
92*7d604fb5SMark Johnston.Ql if
93*7d604fb5SMark Johnstonor
94*7d604fb5SMark Johnston.Ql switch
95*7d604fb5SMark Johnstonstatements, for example.
96*7d604fb5SMark JohnstonIn this mode each record consists of four 64-bit unsigned integers.
97*7d604fb5SMark JohnstonThe first integer is a bitmask defining attributes of the variables involved in
98*7d604fb5SMark Johnstonthe comparison.
99*7d604fb5SMark Johnston.Dv KCOV_CMP_CONST
100*7d604fb5SMark Johnstonis set if one of the variables has a constant value at compile-time, and
101*7d604fb5SMark Johnston.Dv KCOV_CMP_SIZE(n)
102*7d604fb5SMark Johnstonspecifies the width of the variables:
103*7d604fb5SMark Johnston.Pp
104*7d604fb5SMark Johnston.Bl -inset -offset indent -compact
105*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(0) :
106*7d604fb5SMark Johnstona comparison of 8-bit integers
107*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(1) :
108*7d604fb5SMark Johnstona comparison of 16-bit integers
109*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(2) :
110*7d604fb5SMark Johnstona comparison of 32-bit integers
111*7d604fb5SMark Johnston.It Dv KCOV_CMP_SIZE(3) :
112*7d604fb5SMark Johnstona comparison of 64-bit integers
113*7d604fb5SMark Johnston.El
114*7d604fb5SMark Johnston.Pp
115*7d604fb5SMark JohnstonThe second and third fields record the values of the two variables, and the
116*7d604fb5SMark Johnstonfourth and final field stores the program counter value of the comparison.
117*7d604fb5SMark Johnston.Sh IOCTL INTERFACE
118*7d604fb5SMark JohnstonApplications interact with
119*7d604fb5SMark Johnston.Nm
120*7d604fb5SMark Johnstonusing the
121*7d604fb5SMark Johnston.Xr ioctl 2
122*7d604fb5SMark Johnstonsystem call.
123*7d604fb5SMark JohnstonEach thread making use of
124*7d604fb5SMark Johnston.Nm
125*7d604fb5SMark Johnstonmust use a separate file descriptor for
126*7d604fb5SMark Johnston.Fa /dev/kcov .
127*7d604fb5SMark JohnstonThe following ioctls are defined:
128*7d604fb5SMark Johnston.Bl -tag -width indent
129*7d604fb5SMark Johnston.It Dv KIOSETBUFSIZE Fa size_t entries
130*7d604fb5SMark JohnstonSet the size of the tracing buffer in units of
131*7d604fb5SMark Johnston.Dv KCOV_ENTRY_SIZE .
132*7d604fb5SMark JohnstonThe buffer may then be mapped into the calling thread's address space by
133*7d604fb5SMark Johnstoncalling
134*7d604fb5SMark Johnston.Xr mmap 2
135*7d604fb5SMark Johnstonon the
136*7d604fb5SMark Johnston.Nm
137*7d604fb5SMark Johnstondevice file.
138*7d604fb5SMark Johnston.It Dv KIOENABLE Fa int mode
139*7d604fb5SMark JohnstonEnable coverage tracing for the calling thread.
140*7d604fb5SMark JohnstonValid modes are
141*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_PC
142*7d604fb5SMark Johnstonand
143*7d604fb5SMark Johnston.Dv KCOV_MODE_TRACE_CMP .
144*7d604fb5SMark Johnston.It Dv KIODISABLE
145*7d604fb5SMark JohnstonDisable coverage tracing for the calling thread.
146*7d604fb5SMark Johnston.El
147*7d604fb5SMark Johnston.Sh FILES
148*7d604fb5SMark Johnston.Nm
149*7d604fb5SMark Johnstoncreates the
150*7d604fb5SMark Johnston.Pa /dev/kcov
151*7d604fb5SMark Johnstondevice file.
152*7d604fb5SMark Johnston.Sh EXAMPLES
153*7d604fb5SMark JohnstonThe following code sample collects information about basic block coverage for
154*7d604fb5SMark Johnstonkernel code executed while printing
155*7d604fb5SMark Johnston.Ql "Hello, world" .
156*7d604fb5SMark Johnston.Bd -literal
157*7d604fb5SMark Johnstonsize_t sz;
158*7d604fb5SMark Johnstonuint64_t *buf;
159*7d604fb5SMark Johnstonint fd;
160*7d604fb5SMark Johnston
161*7d604fb5SMark Johnstonfd = open("/dev/kcov", O_RDWR);
162*7d604fb5SMark Johnstonif (fd == -1)
163*7d604fb5SMark Johnston	err(1, "open(/dev/kcov)");
164*7d604fb5SMark Johnstonsz = 1ul << 20; /* 1MB */
165*7d604fb5SMark Johnstonif (ioctl(fd, KIOSETBUFSIZE, sz / KCOV_ENTRY_SIZE) != 0)
166*7d604fb5SMark Johnston	err(1, "ioctl(KIOSETBUFSIZE)");
167*7d604fb5SMark Johnstonbuf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
168*7d604fb5SMark Johnstonif (buf == MAP_FAILED)
169*7d604fb5SMark Johnston	err(1, "mmap");
170*7d604fb5SMark Johnston
171*7d604fb5SMark Johnston/* Enable PC tracing. */
172*7d604fb5SMark Johnstonif (ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) != 0)
173*7d604fb5SMark Johnston	err(1, "ioctl(KIOENABLE)");
174*7d604fb5SMark Johnston
175*7d604fb5SMark Johnston/* Clear trace records from the preceding ioctl() call. */
176*7d604fb5SMark Johnstonbuf[0] = 0;
177*7d604fb5SMark Johnston
178*7d604fb5SMark Johnstonprintf("Hello, world!\\n");
179*7d604fb5SMark Johnston
180*7d604fb5SMark Johnston/* Disable PC tracing. */
181*7d604fb5SMark Johnstonif (ioctl(fd, KIODISABLE, 0) != 0)
182*7d604fb5SMark Johnston	err(1, "ioctl(KIODISABLE)");
183*7d604fb5SMark Johnston
184*7d604fb5SMark Johnstonfor (uint64_t i = 1; i < buf[0]; i++)
185*7d604fb5SMark Johnston	printf("%#jx\\n", (uintmax_t)buf[i]);
186*7d604fb5SMark Johnston.Ed
187*7d604fb5SMark JohnstonThe output of this program can be approximately mapped to line numbers
188*7d604fb5SMark Johnstonin kernel source code:
189*7d604fb5SMark Johnston.Bd -literal
190*7d604fb5SMark Johnston# ./kcov-test | sed 1d | addr2line -e /usr/lib/debug/boot/kernel/kernel.debug
191*7d604fb5SMark Johnston.Ed
192*7d604fb5SMark Johnston.Sh SEE ALSO
193*7d604fb5SMark Johnston.Xr ioctl 2 ,
194*7d604fb5SMark Johnston.Xr mmap 2
195*7d604fb5SMark Johnston.Sh HISTORY
196*7d604fb5SMark Johnston.Nm
197*7d604fb5SMark Johnstonfirst appeared in
198*7d604fb5SMark Johnston.Fx 13.0 .
199*7d604fb5SMark Johnston.Sh BUGS
200*7d604fb5SMark JohnstonThe
201*7d604fb5SMark Johnston.Fx
202*7d604fb5SMark Johnstonimplementation of
203*7d604fb5SMark Johnston.Nm
204*7d604fb5SMark Johnstondoes not yet support remote tracing.
205