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
|
.\" $OpenBSD: kcov.4,v 1.6 2018/12/27 19:33:08 anton Exp $
.\"
.\" Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: December 27 2018 $
.Dt KCOV 4
.Os
.Sh NAME
.Nm kcov
.Nd kernel code coverage tracing
.Sh SYNOPSIS
.Cd pseudo-device kcov 1
.Pp
.In sys/kcov.h
.Sh DESCRIPTION
The
.Nm
driver implements collection of code coverage inside the kernel.
It can be enabled on a per thread basis from userland,
allowing the kernel program counter to be collected during syscalls triggered by
the same thread.
The collected coverage can be accessed by mapping the device
using
.Xr mmap 2 .
.Pp
By default,
.Nm
is not enabled but instead requires the following line to be present in the
kernel configuration:
.Bd -literal -offset indent
pseudo-device kcov 1
.Ed
.Pp
The following
.Xr ioctl 2
calls are provided:
.Bl -tag -width 4n
.It Dv KIOSETBUFSIZE Fa unsigned long *nentries
Allocate a coverage buffer with a capacity of
.Fa nentries .
The buffer can be accessed using
.Xr mmap 2 ,
whereas the returned pointer must be interpreted as an array of
.Vt unsigned long
entries.
The first entry contains the number of entries in the array,
excluding the first entry.
.It Dv KIOENABLE Fa int *mode
Enable code coverage tracing for the current thread.
The
.Fa mode
must be one of the following:
.Bl -tag -width KCOV_MODE_TRACE_PC
.It Dv KCOV_MODE_TRACE_PC
Trace the kernel program counter.
.El
.It Dv KIODISABLE Fa void
Disable code coverage tracing for the current thread.
.El
.Sh FILES
.Bl -tag -width /dev/kcov -compact
.It Pa /dev/kcov
Default device node.
.El
.Sh EXAMPLES
In the following example,
the
.Xr read 2
syscall is traced and the coverage displayed, which in turn can be passed to
.Xr addr2line 1
in order to translate the kernel program counter into the file name and line
number it corresponds to.
.Bd -literal
#include <sys/ioctl.h>
#include <sys/kcov.h>
#include <sys/mman.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(void)
{
unsigned long *cover, i;
unsigned long size = 1024;
int fd, mode;
fd = open("/dev/kcov", O_RDWR);
if (fd == -1)
err(1, "open");
if (ioctl(fd, KIOSETBUFSIZE, &size) == -1)
err(1, "ioctl: KIOSETBUFSIZE");
cover = mmap(NULL, size * sizeof(unsigned long),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (cover == MAP_FAILED)
err(1, "mmap");
mode = KCOV_MODE_TRACE_PC;
if (ioctl(fd, KIOENABLE, &mode) == -1)
err(1, "ioctl: KIOENABLE");
read(-1, NULL, 0);
if (ioctl(fd, KIODISABLE) == -1)
err(1, "ioctl: KIODISABLE");
for (i = 0; i < cover[0]; i++)
printf("%p\en", (void *)cover[i + 1]);
if (munmap(cover, size * sizeof(unsigned long)) == -1)
err(1, "munmap");
close(fd);
return 0;
}
.Ed
.Sh SEE ALSO
.Xr files.conf 5
.Sh HISTORY
The
.Nm
driver first appeared in
.Ox 6.4 .
.Sh AUTHORS
The
.Nm
driver was written by
.An Anton Lindqvist Aq Mt anton@openbsd.org .
.Sh CAVEATS
The
.Nm
driver is limited to architectures using
.Xr clang 1
as their default compiler.
|