~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/dev-tools/kcov.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /Documentation/dev-tools/kcov.rst (Version linux-6.12-rc7) and /Documentation/dev-tools/kcov.rst (Version linux-4.11.12)


  1 KCOV: code coverage for fuzzing                !!   1 kcov: code coverage for fuzzing
  2 ===============================                     2 ===============================
  3                                                     3 
  4 KCOV collects and exposes kernel code coverage !!   4 kcov exposes kernel code coverage information in a form suitable for coverage-
  5 for coverage-guided fuzzing. Coverage data of  !!   5 guided fuzzing (randomized testing). Coverage data of a running kernel is
  6 the ``kcov`` debugfs file. Coverage collection !!   6 exported via the "kcov" debugfs file. Coverage collection is enabled on a task
  7 thus KCOV can capture precise coverage of a si !!   7 basis, and thus it can capture precise coverage of a single system call.
  8                                                !!   8 
  9 Note that KCOV does not aim to collect as much !!   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 i !!  10 to collect more or less stable coverage that is function of syscall inputs.
 11 To achieve this goal, it does not collect cove !!  11 To achieve this goal it does not collect coverage in soft/hard interrupts
 12 (unless remove coverage collection is enabled, !!  12 and instrumentation of some inherently non-deterministic parts of kernel is
 13 inherently non-deterministic parts of the kern !!  13 disabled (e.g. scheduler, locking).
 14                                                << 
 15 Besides collecting code coverage, KCOV can als << 
 16 See the "Comparison operands collection" secti << 
 17                                                << 
 18 Besides collecting coverage data from syscall  << 
 19 coverage for annotated parts of the kernel exe << 
 20 tasks or soft interrupts. See the "Remote cove << 
 21 details.                                       << 
 22                                                << 
 23 Prerequisites                                  << 
 24 -------------                                  << 
 25                                                    14 
 26 KCOV relies on compiler instrumentation and re !!  15 Usage
 27 or any Clang version supported by the kernel.  !!  16 -----
 28                                                    17 
 29 Collecting comparison operands is supported wi !!  18 Configure the kernel with::
 30                                                << 
 31 To enable KCOV, configure the kernel with::    << 
 32                                                    19 
 33         CONFIG_KCOV=y                              20         CONFIG_KCOV=y
 34                                                    21 
 35 To enable comparison operands collection, set: !!  22 CONFIG_KCOV requires gcc built on revision 231296 or later.
 36                                                !!  23 Profiling data will only become accessible once debugfs has been mounted::
 37         CONFIG_KCOV_ENABLE_COMPARISONS=y       << 
 38                                                << 
 39 Coverage data only becomes accessible once deb << 
 40                                                    24 
 41         mount -t debugfs none /sys/kernel/debu     25         mount -t debugfs none /sys/kernel/debug
 42                                                    26 
 43 Coverage collection                            !!  27 The following program demonstrates kcov usage from within a test program:
 44 -------------------                            << 
 45                                                << 
 46 The following program demonstrates how to use  << 
 47 single syscall from within a test program:     << 
 48                                                    28 
 49 .. code-block:: c                                  29 .. code-block:: c
 50                                                    30 
 51     #include <stdio.h>                             31     #include <stdio.h>
 52     #include <stddef.h>                            32     #include <stddef.h>
 53     #include <stdint.h>                            33     #include <stdint.h>
 54     #include <stdlib.h>                            34     #include <stdlib.h>
 55     #include <sys/types.h>                         35     #include <sys/types.h>
 56     #include <sys/stat.h>                          36     #include <sys/stat.h>
 57     #include <sys/ioctl.h>                         37     #include <sys/ioctl.h>
 58     #include <sys/mman.h>                          38     #include <sys/mman.h>
 59     #include <unistd.h>                            39     #include <unistd.h>
 60     #include <fcntl.h>                             40     #include <fcntl.h>
 61     #include <linux/types.h>                   << 
 62                                                    41 
 63     #define KCOV_INIT_TRACE                        42     #define KCOV_INIT_TRACE                     _IOR('c', 1, unsigned long)
 64     #define KCOV_ENABLE                 _IO('c     43     #define KCOV_ENABLE                 _IO('c', 100)
 65     #define KCOV_DISABLE                           44     #define KCOV_DISABLE                        _IO('c', 101)
 66     #define COVER_SIZE                  (64<<1     45     #define COVER_SIZE                  (64<<10)
 67                                                    46 
 68     #define KCOV_TRACE_PC  0                   << 
 69     #define KCOV_TRACE_CMP 1                   << 
 70                                                << 
 71     int main(int argc, char **argv)                47     int main(int argc, char **argv)
 72     {                                              48     {
 73         int fd;                                    49         int fd;
 74         unsigned long *cover, n, i;                50         unsigned long *cover, n, i;
 75                                                    51 
 76         /* A single fd descriptor allows cover     52         /* A single fd descriptor allows coverage collection on a single
 77          * thread.                                 53          * thread.
 78          */                                        54          */
 79         fd = open("/sys/kernel/debug/kcov", O_     55         fd = open("/sys/kernel/debug/kcov", O_RDWR);
 80         if (fd == -1)                              56         if (fd == -1)
 81                 perror("open"), exit(1);           57                 perror("open"), exit(1);
 82         /* Setup trace mode and trace size. */     58         /* Setup trace mode and trace size. */
 83         if (ioctl(fd, KCOV_INIT_TRACE, COVER_S     59         if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE))
 84                 perror("ioctl"), exit(1);          60                 perror("ioctl"), exit(1);
 85         /* Mmap buffer shared between kernel-      61         /* Mmap buffer shared between kernel- and user-space. */
 86         cover = (unsigned long*)mmap(NULL, COV     62         cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long),
 87                                      PROT_READ     63                                      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 88         if ((void*)cover == MAP_FAILED)            64         if ((void*)cover == MAP_FAILED)
 89                 perror("mmap"), exit(1);           65                 perror("mmap"), exit(1);
 90         /* Enable coverage collection on the c     66         /* Enable coverage collection on the current thread. */
 91         if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_ !!  67         if (ioctl(fd, KCOV_ENABLE, 0))
 92                 perror("ioctl"), exit(1);          68                 perror("ioctl"), exit(1);
 93         /* Reset coverage from the tail of the     69         /* Reset coverage from the tail of the ioctl() call. */
 94         __atomic_store_n(&cover[0], 0, __ATOMI     70         __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED);
 95         /* Call the target syscall call. */    !!  71         /* That's the target syscal call. */
 96         read(-1, NULL, 0);                         72         read(-1, NULL, 0);
 97         /* Read number of PCs collected. */        73         /* Read number of PCs collected. */
 98         n = __atomic_load_n(&cover[0], __ATOMI     74         n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
 99         for (i = 0; i < n; i++)                    75         for (i = 0; i < n; i++)
100                 printf("0x%lx\n", cover[i + 1]     76                 printf("0x%lx\n", cover[i + 1]);
101         /* Disable coverage collection for the     77         /* Disable coverage collection for the current thread. After this call
102          * coverage can be enabled for a diffe     78          * coverage can be enabled for a different thread.
103          */                                        79          */
104         if (ioctl(fd, KCOV_DISABLE, 0))            80         if (ioctl(fd, KCOV_DISABLE, 0))
105                 perror("ioctl"), exit(1);          81                 perror("ioctl"), exit(1);
106         /* Free resources. */                      82         /* Free resources. */
107         if (munmap(cover, COVER_SIZE * sizeof(     83         if (munmap(cover, COVER_SIZE * sizeof(unsigned long)))
108                 perror("munmap"), exit(1);         84                 perror("munmap"), exit(1);
109         if (close(fd))                             85         if (close(fd))
110                 perror("close"), exit(1);          86                 perror("close"), exit(1);
111         return 0;                                  87         return 0;
112     }                                              88     }
113                                                    89 
114 After piping through ``addr2line`` the output  !!  90 After piping through addr2line output of the program looks as follows::
115                                                    91 
116     SyS_read                                       92     SyS_read
117     fs/read_write.c:562                            93     fs/read_write.c:562
118     __fdget_pos                                    94     __fdget_pos
119     fs/file.c:774                                  95     fs/file.c:774
120     __fget_light                                   96     __fget_light
121     fs/file.c:746                                  97     fs/file.c:746
122     __fget_light                                   98     __fget_light
123     fs/file.c:750                                  99     fs/file.c:750
124     __fget_light                                  100     __fget_light
125     fs/file.c:760                                 101     fs/file.c:760
126     __fdget_pos                                   102     __fdget_pos
127     fs/file.c:784                                 103     fs/file.c:784
128     SyS_read                                      104     SyS_read
129     fs/read_write.c:562                           105     fs/read_write.c:562
130                                                   106 
131 If a program needs to collect coverage from se    107 If a program needs to collect coverage from several threads (independently),
132 it needs to open ``/sys/kernel/debug/kcov`` in !! 108 it needs to open /sys/kernel/debug/kcov in each thread separately.
133                                                   109 
134 The interface is fine-grained to allow efficie    110 The interface is fine-grained to allow efficient forking of test processes.
135 That is, a parent process opens ``/sys/kernel/ !! 111 That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode,
136 mmaps coverage buffer, and then forks child pr !! 112 mmaps coverage buffer and then forks child processes in a loop. Child processes
137 processes only need to enable coverage (it get !! 113 only need to enable coverage (disable happens automatically on thread end).
138 a thread exits).                               << 
139                                                << 
140 Comparison operands collection                 << 
141 ------------------------------                 << 
142                                                << 
143 Comparison operands collection is similar to c << 
144                                                << 
145 .. code-block:: c                              << 
146                                                << 
147     /* Same includes and defines as above. */  << 
148                                                << 
149     /* Number of 64-bit words per record. */   << 
150     #define KCOV_WORDS_PER_CMP 4               << 
151                                                << 
152     /*                                         << 
153      * The format for the types of collected c << 
154      *                                         << 
155      * Bit 0 shows whether one of the argument << 
156      * Bits 1 & 2 contain log2 of the argument << 
157      */                                        << 
158                                                << 
159     #define KCOV_CMP_CONST          (1 << 0)   << 
160     #define KCOV_CMP_SIZE(n)        ((n) << 1) << 
161     #define KCOV_CMP_MASK           KCOV_CMP_S << 
162                                                << 
163     int main(int argc, char **argv)            << 
164     {                                          << 
165         int fd;                                << 
166         uint64_t *cover, type, arg1, arg2, is_ << 
167         unsigned long n, i;                    << 
168                                                << 
169         fd = open("/sys/kernel/debug/kcov", O_ << 
170         if (fd == -1)                          << 
171                 perror("open"), exit(1);       << 
172         if (ioctl(fd, KCOV_INIT_TRACE, COVER_S << 
173                 perror("ioctl"), exit(1);      << 
174         /*                                     << 
175         * Note that the buffer pointer is of t << 
176         * the comparison operands are promoted << 
177         */                                     << 
178         cover = (uint64_t *)mmap(NULL, COVER_S << 
179                                      PROT_READ << 
180         if ((void*)cover == MAP_FAILED)        << 
181                 perror("mmap"), exit(1);       << 
182         /* Note KCOV_TRACE_CMP instead of KCOV << 
183         if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_ << 
184                 perror("ioctl"), exit(1);      << 
185         __atomic_store_n(&cover[0], 0, __ATOMI << 
186         read(-1, NULL, 0);                     << 
187         /* Read number of comparisons collecte << 
188         n = __atomic_load_n(&cover[0], __ATOMI << 
189         for (i = 0; i < n; i++) {              << 
190                 uint64_t ip;                   << 
191                                                << 
192                 type = cover[i * KCOV_WORDS_PE << 
193                 /* arg1 and arg2 - operands of << 
194                 arg1 = cover[i * KCOV_WORDS_PE << 
195                 arg2 = cover[i * KCOV_WORDS_PE << 
196                 /* ip - caller address. */     << 
197                 ip = cover[i * KCOV_WORDS_PER_ << 
198                 /* size of the operands. */    << 
199                 size = 1 << ((type & KCOV_CMP_ << 
200                 /* is_const - true if either o << 
201                 is_const = type & KCOV_CMP_CON << 
202                 printf("ip: 0x%lx type: 0x%lx, << 
203                         "size: %lu, %s\n",     << 
204                         ip, type, arg1, arg2,  << 
205                 is_const ? "const" : "non-cons << 
206         }                                      << 
207         if (ioctl(fd, KCOV_DISABLE, 0))        << 
208                 perror("ioctl"), exit(1);      << 
209         /* Free resources. */                  << 
210         if (munmap(cover, COVER_SIZE * sizeof( << 
211                 perror("munmap"), exit(1);     << 
212         if (close(fd))                         << 
213                 perror("close"), exit(1);      << 
214         return 0;                              << 
215     }                                          << 
216                                                << 
217 Note that the KCOV modes (collection of code c << 
218 are mutually exclusive.                        << 
219                                                << 
220 Remote coverage collection                     << 
221 --------------------------                     << 
222                                                << 
223 Besides collecting coverage data from handlers << 
224 userspace process, KCOV can also collect cover << 
225 executing in other contexts - so-called "remot << 
226                                                << 
227 Using KCOV to collect remote coverage requires << 
228                                                << 
229 1. Modifying kernel code to annotate the code  << 
230    should be collected with ``kcov_remote_star << 
231                                                << 
232 2. Using ``KCOV_REMOTE_ENABLE`` instead of ``K << 
233    process that collects coverage.             << 
234                                                << 
235 Both ``kcov_remote_start`` and ``kcov_remote_s << 
236 ``KCOV_REMOTE_ENABLE`` ioctl accept handles th << 
237 collection sections. The way a handle is used  << 
238 matching code section executes.                << 
239                                                << 
240 KCOV supports collecting remote coverage from  << 
241                                                << 
242 1. Global kernel background tasks. These are t << 
243    kernel boot in a limited number of instance << 
244    worker is spawned per one USB HCD).         << 
245                                                << 
246 2. Local kernel background tasks. These are sp << 
247    interacts with some kernel interface and ar << 
248    exits (e.g. vhost workers).                 << 
249                                                << 
250 3. Soft interrupts.                            << 
251                                                << 
252 For #1 and #3, a unique global handle must be  << 
253 corresponding ``kcov_remote_start`` call. Then << 
254 this handle to ``KCOV_REMOTE_ENABLE`` in the ` << 
255 ``kcov_remote_arg`` struct. This will attach t << 
256 section referenced by this handle. Multiple gl << 
257 different code sections can be passed at once. << 
258                                                << 
259 For #2, the userspace process instead must pas << 
260 ``common_handle`` field of the ``kcov_remote_a << 
261 gets saved to the ``kcov_handle`` field in the << 
262 needs to be passed to the newly spawned local  << 
263 modifications. Those tasks should in turn use  << 
264 ``kcov_remote_start`` and ``kcov_remote_stop`` << 
265                                                << 
266 KCOV follows a predefined format for both glob << 
267 handle is a ``u64`` integer. Currently, only t << 
268 are used. Bytes 4-7 are reserved and must be z << 
269                                                << 
270 For global handles, the top byte of the handle << 
271 this handle belongs to. For example, KCOV uses << 
272 The lower 4 bytes of a global handle denote th << 
273 that subsystem. For example, each ``hub_event` << 
274 as the task instance id.                       << 
275                                                << 
276 For common handles, a reserved value ``0`` is  << 
277 handles don't belong to a particular subsystem << 
278 handle identify a collective instance of all l << 
279 userspace process that passed a common handle  << 
280                                                << 
281 In practice, any value can be used for common  << 
282 is only collected from a single userspace proc << 
283 common handles are used by multiple processes, << 
284 used for each process. One option is to use th << 
285 handle instance id.                            << 
286                                                << 
287 The following program demonstrates using KCOV  << 
288 local tasks spawned by the process and the glo << 
289                                                << 
290 .. code-block:: c                              << 
291                                                << 
292     /* Same includes and defines as above. */  << 
293                                                << 
294     struct kcov_remote_arg {                   << 
295         __u32           trace_mode;            << 
296         __u32           area_size;             << 
297         __u32           num_handles;           << 
298         __aligned_u64   common_handle;         << 
299         __aligned_u64   handles[0];            << 
300     };                                         << 
301                                                << 
302     #define KCOV_INIT_TRACE                    << 
303     #define KCOV_DISABLE                       << 
304     #define KCOV_REMOTE_ENABLE          _IOW(' << 
305                                                << 
306     #define COVER_SIZE  (64 << 10)             << 
307                                                << 
308     #define KCOV_TRACE_PC       0              << 
309                                                << 
310     #define KCOV_SUBSYSTEM_COMMON       (0x00u << 
311     #define KCOV_SUBSYSTEM_USB  (0x01ull << 56 << 
312                                                << 
313     #define KCOV_SUBSYSTEM_MASK (0xffull << 56 << 
314     #define KCOV_INSTANCE_MASK  (0xffffffffull << 
315                                                << 
316     static inline __u64 kcov_remote_handle(__u << 
317     {                                          << 
318         if (subsys & ~KCOV_SUBSYSTEM_MASK || i << 
319                 return 0;                      << 
320         return subsys | inst;                  << 
321     }                                          << 
322                                                << 
323     #define KCOV_COMMON_ID      0x42           << 
324     #define KCOV_USB_BUS_NUM    1              << 
325                                                << 
326     int main(int argc, char **argv)            << 
327     {                                          << 
328         int fd;                                << 
329         unsigned long *cover, n, i;            << 
330         struct kcov_remote_arg *arg;           << 
331                                                << 
332         fd = open("/sys/kernel/debug/kcov", O_ << 
333         if (fd == -1)                          << 
334                 perror("open"), exit(1);       << 
335         if (ioctl(fd, KCOV_INIT_TRACE, COVER_S << 
336                 perror("ioctl"), exit(1);      << 
337         cover = (unsigned long*)mmap(NULL, COV << 
338                                      PROT_READ << 
339         if ((void*)cover == MAP_FAILED)        << 
340                 perror("mmap"), exit(1);       << 
341                                                << 
342         /* Enable coverage collection via comm << 
343         arg = calloc(1, sizeof(*arg) + sizeof( << 
344         if (!arg)                              << 
345                 perror("calloc"), exit(1);     << 
346         arg->trace_mode = KCOV_TRACE_PC;       << 
347         arg->area_size = COVER_SIZE;           << 
348         arg->num_handles = 1;                  << 
349         arg->common_handle = kcov_remote_handl << 
350                                                << 
351         arg->handles[0] = kcov_remote_handle(K << 
352                                                << 
353         if (ioctl(fd, KCOV_REMOTE_ENABLE, arg) << 
354                 perror("ioctl"), free(arg), ex << 
355         free(arg);                             << 
356                                                << 
357         /*                                     << 
358          * Here the user needs to trigger exec << 
359          * that is either annotated with the c << 
360          * activity on USB bus #1.             << 
361          */                                    << 
362         sleep(2);                              << 
363                                                << 
364         n = __atomic_load_n(&cover[0], __ATOMI << 
365         for (i = 0; i < n; i++)                << 
366                 printf("0x%lx\n", cover[i + 1] << 
367         if (ioctl(fd, KCOV_DISABLE, 0))        << 
368                 perror("ioctl"), exit(1);      << 
369         if (munmap(cover, COVER_SIZE * sizeof( << 
370                 perror("munmap"), exit(1);     << 
371         if (close(fd))                         << 
372                 perror("close"), exit(1);      << 
373         return 0;                              << 
374     }                                          << 
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php