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