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

fd = open("/dev/kcov", O_RDWR);
if (fd == -1)
	err(1, "open(/dev/kcov)");
sz = 1ul << 20; /* 1MB */
if (ioctl(fd, KIOSETBUFSIZE, sz / KCOV_ENTRY_SIZE) != 0)
	err(1, "ioctl(KIOSETBUFSIZE)");
buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED)
	err(1, "mmap");

/* Enable PC tracing. */
if (ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) != 0)
	err(1, "ioctl(KIOENABLE)");

/* Clear trace records from the preceding ioctl() call. */
buf[0] = 0;

printf("Hello, world!\\n");

/* Disable PC tracing. */
if (ioctl(fd, KIODISABLE, 0) != 0)
	err(1, "ioctl(KIODISABLE)");

for (uint64_t i = 1; i < buf[0]; i++)
	printf("%#jx\\n", (uintmax_t)buf[i]);
.Ed
The output of this program can be approximately mapped to line numbers
in kernel source code:
.Bd -literal
# ./kcov-test | sed 1d | addr2line -e /usr/lib/debug/boot/kernel/kernel.debug
.Ed
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr mmap 2
.Sh HISTORY
.Nm
first appeared in
.Fx 13.0 .
.Sh BUGS
The
.Fx
implementation of
.Nm
does not yet support remote tracing.