xref: /openbsd-src/share/man/man4/kcov.4 (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1.\"	$OpenBSD: kcov.4,v 1.7 2019/01/20 09:57:23 anton Exp $
2.\"
3.\" Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: January 20 2019 $
18.Dt KCOV 4
19.Os
20.Sh NAME
21.Nm kcov
22.Nd kernel code coverage tracing
23.Sh SYNOPSIS
24.Cd pseudo-device kcov 1
25.Pp
26.In sys/kcov.h
27.Sh DESCRIPTION
28The
29.Nm
30driver implements collection of code coverage inside the kernel.
31It can be enabled on a per thread basis from userland,
32allowing the kernel program counter to be collected during syscalls triggered by
33the same thread.
34The collected coverage can be accessed by mapping the device
35using
36.Xr mmap 2 .
37.Pp
38By default,
39.Nm
40is not enabled but instead requires the following line to be present in the
41kernel configuration:
42.Bd -literal -offset indent
43pseudo-device kcov 1
44.Ed
45.Pp
46The following
47.Xr ioctl 2
48calls are provided:
49.Bl -tag -width 4n
50.It Dv KIOSETBUFSIZE Fa unsigned long *nentries
51Allocate a coverage buffer with a capacity of
52.Fa nentries .
53The buffer can be accessed using
54.Xr mmap 2 ,
55whereas the returned pointer must be interpreted as an array of
56.Vt unsigned long
57entries.
58The first entry contains the number of entries in the array,
59excluding the first entry.
60.It Dv KIOENABLE Fa int *mode
61Enable code coverage tracing for the current thread.
62The
63.Fa mode
64must be one of the following:
65.Bl -ohang
66.It Dv KCOV_MODE_TRACE_PC
67Trace the kernel program counter.
68.It Dv KCOV_MODE_TRACE_CMP
69Trace comparison instructions and switch statements.
70For switch statements, the number of traced comparison instructions is equal to
71the number of switch cases.
72Each traced comparison instruction is represented by 4 entries in the coverage
73buffer:
74.Bl -enum
75.It
76A mask where the least significant bit is set if one of the comparison operands
77is a compile-time constant, which is always true for switch statements.
78The remaining bits represents the log2 size of the operands, ranging from 0 to
793.
80.It
81First comparison operand.
82For switch statements, this operand corresponds to the case value.
83.It
84Second comparison operand.
85For switch statements, this operand corresponds to the value passed to switch.
86.It
87Kernel program counter where the comparison instruction took place.
88.El
89.Pp
90In this mode, the first entry in the coverage buffer reflects the number of
91traced comparison instructions.
92Thus, the effective number of entries in the coverage buffer is given by
93multiplying the first entry by 4.
94.El
95.It Dv KIODISABLE Fa void
96Disable code coverage tracing for the current thread.
97.El
98.Sh FILES
99.Bl -tag -width /dev/kcov -compact
100.It Pa /dev/kcov
101Default device node.
102.El
103.Sh EXAMPLES
104In the following example,
105the
106.Xr read 2
107syscall is traced and the coverage displayed, which in turn can be passed to
108.Xr addr2line 1
109in order to translate the kernel program counter into the file name and line
110number it corresponds to.
111.Bd -literal
112#include <sys/ioctl.h>
113#include <sys/kcov.h>
114#include <sys/mman.h>
115
116#include <err.h>
117#include <fcntl.h>
118#include <stdio.h>
119#include <stdlib.h>
120#include <unistd.h>
121
122int
123main(void)
124{
125	unsigned long *cover, i;
126	unsigned long size = 1024;
127	int fd, mode;
128
129	fd = open("/dev/kcov", O_RDWR);
130	if (fd == -1)
131		err(1, "open");
132
133	if (ioctl(fd, KIOSETBUFSIZE, &size) == -1)
134		err(1, "ioctl: KIOSETBUFSIZE");
135	cover = mmap(NULL, size * sizeof(unsigned long),
136	    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
137	if (cover == MAP_FAILED)
138		err(1, "mmap");
139
140	mode = KCOV_MODE_TRACE_PC;
141	if (ioctl(fd, KIOENABLE, &mode) == -1)
142		err(1, "ioctl: KIOENABLE");
143	read(-1, NULL, 0);
144	if (ioctl(fd, KIODISABLE) == -1)
145		err(1, "ioctl: KIODISABLE");
146
147	for (i = 0; i < cover[0]; i++)
148		printf("%p\en", (void *)cover[i + 1]);
149
150	if (munmap(cover, size * sizeof(unsigned long)) == -1)
151		err(1, "munmap");
152	close(fd);
153
154	return 0;
155}
156.Ed
157.Sh SEE ALSO
158.Xr files.conf 5
159.Sh HISTORY
160The
161.Nm
162driver first appeared in
163.Ox 6.4 .
164.Sh AUTHORS
165The
166.Nm
167driver was written by
168.An Anton Lindqvist Aq Mt anton@openbsd.org .
169.Sh CAVEATS
170The
171.Nm
172driver is limited to architectures using
173.Xr clang 1
174as their default compiler.
175