Skip to content

Commit 7b32137

Browse files
xairyakpm00
authored andcommitted
kcov: improve documentation
Improve KCOV documentation: - Use KCOV instead of kcov, as the former is more widely-used. - Mention Clang in compiler requirements. - Use ``annotations`` for inline code. - Rework remote coverage collection documentation for better clarity. - Various smaller changes. [andreyknvl@google.com: v2] Link: https://lkml.kernel.org/r/583f41c49eef15210fa813e8229730d11427efa7.1677614637.git.andreyknvl@google.com [andreyknvl@google.com: fix ``annotation`` for KCOV_REMOTE_ENABLE] Link: https://lkml.kernel.org/r/72be5c215c275f35891229b90622ed859f196a46.1677684837.git.andreyknvl@google.com Link: https://lkml.kernel.org/r/0b5efd70e31bba7912cf9a6c951f0e76a8df27df.1677517724.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Reviewed-by: Dmitry Vyukov <dvyukov@google.com> Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com> Cc: Alexander Potapenko <glider@google.com> Cc: Marco Elver <elver@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent f9641a3 commit 7b32137

File tree

1 file changed

+102
-67
lines changed

1 file changed

+102
-67
lines changed

Documentation/dev-tools/kcov.rst

Lines changed: 102 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,50 @@
1-
kcov: code coverage for fuzzing
1+
KCOV: code coverage for fuzzing
22
===============================
33

4-
kcov exposes kernel code coverage information in a form suitable for coverage-
5-
guided fuzzing (randomized testing). Coverage data of a running kernel is
6-
exported via the "kcov" debugfs file. Coverage collection is enabled on a task
7-
basis, and thus it can capture precise coverage of a single system call.
4+
KCOV collects and exposes kernel code coverage information in a form suitable
5+
for coverage-guided fuzzing. Coverage data of a running kernel is exported via
6+
the ``kcov`` debugfs file. Coverage collection is enabled on a task basis, and
7+
thus KCOV can capture precise coverage of a single system call.
88

9-
Note that kcov does not aim to collect as much coverage as possible. It aims
10-
to collect more or less stable coverage that is function of syscall inputs.
11-
To achieve this goal it does not collect coverage in soft/hard interrupts
12-
and instrumentation of some inherently non-deterministic parts of kernel is
13-
disabled (e.g. scheduler, locking).
9+
Note that KCOV does not aim to collect as much coverage as possible. It aims
10+
to collect more or less stable coverage that is a function of syscall inputs.
11+
To achieve this goal, it does not collect coverage in soft/hard interrupts
12+
(unless remove coverage collection is enabled, see below) and from some
13+
inherently non-deterministic parts of the kernel (e.g. scheduler, locking).
1414

15-
kcov is also able to collect comparison operands from the instrumented code
16-
(this feature currently requires that the kernel is compiled with clang).
15+
Besides collecting code coverage, KCOV can also collect comparison operands.
16+
See the "Comparison operands collection" section for details.
17+
18+
Besides collecting coverage data from syscall handlers, KCOV can also collect
19+
coverage for annotated parts of the kernel executing in background kernel
20+
tasks or soft interrupts. See the "Remote coverage collection" section for
21+
details.
1722

1823
Prerequisites
1924
-------------
2025

21-
Configure the kernel with::
26+
KCOV relies on compiler instrumentation and requires GCC 6.1.0 or later
27+
or any Clang version supported by the kernel.
2228

23-
CONFIG_KCOV=y
29+
Collecting comparison operands is supported with GCC 8+ or with Clang.
2430

25-
CONFIG_KCOV requires gcc 6.1.0 or later.
31+
To enable KCOV, configure the kernel with::
2632

27-
If the comparison operands need to be collected, set::
33+
CONFIG_KCOV=y
34+
35+
To enable comparison operands collection, set::
2836

2937
CONFIG_KCOV_ENABLE_COMPARISONS=y
3038

31-
Profiling data will only become accessible once debugfs has been mounted::
39+
Coverage data only becomes accessible once debugfs has been mounted::
3240

3341
mount -t debugfs none /sys/kernel/debug
3442

3543
Coverage collection
3644
-------------------
3745

38-
The following program demonstrates coverage collection from within a test
39-
program using kcov:
46+
The following program demonstrates how to use KCOV to collect coverage for a
47+
single syscall from within a test program:
4048

4149
.. code-block:: c
4250
@@ -84,7 +92,7 @@ program using kcov:
8492
perror("ioctl"), exit(1);
8593
/* Reset coverage from the tail of the ioctl() call. */
8694
__atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED);
87-
/* That's the target syscal call. */
95+
/* Call the target syscall call. */
8896
read(-1, NULL, 0);
8997
/* Read number of PCs collected. */
9098
n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
@@ -103,7 +111,7 @@ program using kcov:
103111
return 0;
104112
}
105113
106-
After piping through addr2line output of the program looks as follows::
114+
After piping through ``addr2line`` the output of the program looks as follows::
107115

108116
SyS_read
109117
fs/read_write.c:562
@@ -121,12 +129,13 @@ After piping through addr2line output of the program looks as follows::
121129
fs/read_write.c:562
122130

123131
If a program needs to collect coverage from several threads (independently),
124-
it needs to open /sys/kernel/debug/kcov in each thread separately.
132+
it needs to open ``/sys/kernel/debug/kcov`` in each thread separately.
125133

126134
The interface is fine-grained to allow efficient forking of test processes.
127-
That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode,
128-
mmaps coverage buffer and then forks child processes in a loop. Child processes
129-
only need to enable coverage (disable happens automatically on thread end).
135+
That is, a parent process opens ``/sys/kernel/debug/kcov``, enables trace mode,
136+
mmaps coverage buffer, and then forks child processes in a loop. The child
137+
processes only need to enable coverage (it gets disabled automatically when
138+
a thread exits).
130139

131140
Comparison operands collection
132141
------------------------------
@@ -205,52 +214,78 @@ Comparison operands collection is similar to coverage collection:
205214
return 0;
206215
}
207216
208-
Note that the kcov modes (coverage collection or comparison operands) are
209-
mutually exclusive.
217+
Note that the KCOV modes (collection of code coverage or comparison operands)
218+
are mutually exclusive.
210219

211220
Remote coverage collection
212221
--------------------------
213222

214-
With KCOV_ENABLE coverage is collected only for syscalls that are issued
215-
from the current process. With KCOV_REMOTE_ENABLE it's possible to collect
216-
coverage for arbitrary parts of the kernel code, provided that those parts
217-
are annotated with kcov_remote_start()/kcov_remote_stop().
218-
219-
This allows to collect coverage from two types of kernel background
220-
threads: the global ones, that are spawned during kernel boot in a limited
221-
number of instances (e.g. one USB hub_event() worker thread is spawned per
222-
USB HCD); and the local ones, that are spawned when a user interacts with
223-
some kernel interface (e.g. vhost workers); as well as from soft
224-
interrupts.
225-
226-
To enable collecting coverage from a global background thread or from a
227-
softirq, a unique global handle must be assigned and passed to the
228-
corresponding kcov_remote_start() call. Then a userspace process can pass
229-
a list of such handles to the KCOV_REMOTE_ENABLE ioctl in the handles
230-
array field of the kcov_remote_arg struct. This will attach the used kcov
231-
device to the code sections, that are referenced by those handles.
232-
233-
Since there might be many local background threads spawned from different
234-
userspace processes, we can't use a single global handle per annotation.
235-
Instead, the userspace process passes a non-zero handle through the
236-
common_handle field of the kcov_remote_arg struct. This common handle gets
237-
saved to the kcov_handle field in the current task_struct and needs to be
238-
passed to the newly spawned threads via custom annotations. Those threads
239-
should in turn be annotated with kcov_remote_start()/kcov_remote_stop().
240-
241-
Internally kcov stores handles as u64 integers. The top byte of a handle
242-
is used to denote the id of a subsystem that this handle belongs to, and
243-
the lower 4 bytes are used to denote the id of a thread instance within
244-
that subsystem. A reserved value 0 is used as a subsystem id for common
245-
handles as they don't belong to a particular subsystem. The bytes 4-7 are
246-
currently reserved and must be zero. In the future the number of bytes
247-
used for the subsystem or handle ids might be increased.
248-
249-
When a particular userspace process collects coverage via a common
250-
handle, kcov will collect coverage for each code section that is annotated
251-
to use the common handle obtained as kcov_handle from the current
252-
task_struct. However non common handles allow to collect coverage
253-
selectively from different subsystems.
223+
Besides collecting coverage data from handlers of syscalls issued from a
224+
userspace process, KCOV can also collect coverage for parts of the kernel
225+
executing in other contexts - so-called "remote" coverage.
226+
227+
Using KCOV to collect remote coverage requires:
228+
229+
1. Modifying kernel code to annotate the code section from where coverage
230+
should be collected with ``kcov_remote_start`` and ``kcov_remote_stop``.
231+
232+
2. Using ``KCOV_REMOTE_ENABLE`` instead of ``KCOV_ENABLE`` in the userspace
233+
process that collects coverage.
234+
235+
Both ``kcov_remote_start`` and ``kcov_remote_stop`` annotations and the
236+
``KCOV_REMOTE_ENABLE`` ioctl accept handles that identify particular coverage
237+
collection sections. The way a handle is used depends on the context where the
238+
matching code section executes.
239+
240+
KCOV supports collecting remote coverage from the following contexts:
241+
242+
1. Global kernel background tasks. These are the tasks that are spawned during
243+
kernel boot in a limited number of instances (e.g. one USB ``hub_event``
244+
worker is spawned per one USB HCD).
245+
246+
2. Local kernel background tasks. These are spawned when a userspace process
247+
interacts with some kernel interface and are usually killed when the process
248+
exits (e.g. vhost workers).
249+
250+
3. Soft interrupts.
251+
252+
For #1 and #3, a unique global handle must be chosen and passed to the
253+
corresponding ``kcov_remote_start`` call. Then a userspace process must pass
254+
this handle to ``KCOV_REMOTE_ENABLE`` in the ``handles`` array field of the
255+
``kcov_remote_arg`` struct. This will attach the used KCOV device to the code
256+
section referenced by this handle. Multiple global handles identifying
257+
different code sections can be passed at once.
258+
259+
For #2, the userspace process instead must pass a non-zero handle through the
260+
``common_handle`` field of the ``kcov_remote_arg`` struct. This common handle
261+
gets saved to the ``kcov_handle`` field in the current ``task_struct`` and
262+
needs to be passed to the newly spawned local tasks via custom kernel code
263+
modifications. Those tasks should in turn use the passed handle in their
264+
``kcov_remote_start`` and ``kcov_remote_stop`` annotations.
265+
266+
KCOV follows a predefined format for both global and common handles. Each
267+
handle is a ``u64`` integer. Currently, only the one top and the lower 4 bytes
268+
are used. Bytes 4-7 are reserved and must be zero.
269+
270+
For global handles, the top byte of the handle denotes the id of a subsystem
271+
this handle belongs to. For example, KCOV uses ``1`` as the USB subsystem id.
272+
The lower 4 bytes of a global handle denote the id of a task instance within
273+
that subsystem. For example, each ``hub_event`` worker uses the USB bus number
274+
as the task instance id.
275+
276+
For common handles, a reserved value ``0`` is used as a subsystem id, as such
277+
handles don't belong to a particular subsystem. The lower 4 bytes of a common
278+
handle identify a collective instance of all local tasks spawned by the
279+
userspace process that passed a common handle to ``KCOV_REMOTE_ENABLE``.
280+
281+
In practice, any value can be used for common handle instance id if coverage
282+
is only collected from a single userspace process on the system. However, if
283+
common handles are used by multiple processes, unique instance ids must be
284+
used for each process. One option is to use the process id as the common
285+
handle instance id.
286+
287+
The following program demonstrates using KCOV to collect coverage from both
288+
local tasks spawned by the process and the global task that handles USB bus #1:
254289

255290
.. code-block:: c
256291

0 commit comments

Comments
 (0)