~ [ 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-5.7.19)


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

~ [ 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