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