~ [ 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.12.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); as well as from soft
233    process that collects coverage.             !! 221 interrupts.
234                                                !! 222 
235 Both ``kcov_remote_start`` and ``kcov_remote_s !! 223 To enable collecting coverage from a global background thread or from a
236 ``KCOV_REMOTE_ENABLE`` ioctl accept handles th !! 224 softirq, a unique global handle must be assigned and passed to the
237 collection sections. The way a handle is used  !! 225 corresponding kcov_remote_start() call. Then a userspace process can pass
238 matching code section executes.                !! 226 a list of such handles to the KCOV_REMOTE_ENABLE ioctl in the handles
239                                                !! 227 array field of the kcov_remote_arg struct. This will attach the used kcov
240 KCOV supports collecting remote coverage from  !! 228 device to the code sections, that are referenced by those handles.
241                                                !! 229 
242 1. Global kernel background tasks. These are t !! 230 Since there might be many local background threads spawned from different
243    kernel boot in a limited number of instance !! 231 userspace processes, we can't use a single global handle per annotation.
244    worker is spawned per one USB HCD).         !! 232 Instead, the userspace process passes a non-zero handle through the
245                                                !! 233 common_handle field of the kcov_remote_arg struct. This common handle gets
246 2. Local kernel background tasks. These are sp !! 234 saved to the kcov_handle field in the current task_struct and needs to be
247    interacts with some kernel interface and ar !! 235 passed to the newly spawned threads via custom annotations. Those threads
248    exits (e.g. vhost workers).                 !! 236 should in turn be annotated with kcov_remote_start()/kcov_remote_stop().
249                                                !! 237 
250 3. Soft interrupts.                            !! 238 Internally kcov stores handles as u64 integers. The top byte of a handle
251                                                !! 239 is used to denote the id of a subsystem that this handle belongs to, and
252 For #1 and #3, a unique global handle must be  !! 240 the lower 4 bytes are used to denote the id of a thread instance within
253 corresponding ``kcov_remote_start`` call. Then !! 241 that subsystem. A reserved value 0 is used as a subsystem id for common
254 this handle to ``KCOV_REMOTE_ENABLE`` in the ` !! 242 handles as they don't belong to a particular subsystem. The bytes 4-7 are
255 ``kcov_remote_arg`` struct. This will attach t !! 243 currently reserved and must be zero. In the future the number of bytes
256 section referenced by this handle. Multiple gl !! 244 used for the subsystem or handle ids might be increased.
257 different code sections can be passed at once. !! 245 
258                                                !! 246 When a particular userspace process collects coverage via a common
259 For #2, the userspace process instead must pas !! 247 handle, kcov will collect coverage for each code section that is annotated
260 ``common_handle`` field of the ``kcov_remote_a !! 248 to use the common handle obtained as kcov_handle from the current
261 gets saved to the ``kcov_handle`` field in the !! 249 task_struct. However non common handles allow to collect coverage
262 needs to be passed to the newly spawned local  !! 250 selectively from different subsystems.
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                                                   251 
290 .. code-block:: c                                 252 .. code-block:: c
291                                                << 
292     /* Same includes and defines as above. */  << 
293                                                   253 
294     struct kcov_remote_arg {                      254     struct kcov_remote_arg {
295         __u32           trace_mode;               255         __u32           trace_mode;
296         __u32           area_size;                256         __u32           area_size;
297         __u32           num_handles;              257         __u32           num_handles;
298         __aligned_u64   common_handle;            258         __aligned_u64   common_handle;
299         __aligned_u64   handles[0];               259         __aligned_u64   handles[0];
300     };                                            260     };
301                                                   261 
302     #define KCOV_INIT_TRACE                       262     #define KCOV_INIT_TRACE                     _IOR('c', 1, unsigned long)
303     #define KCOV_DISABLE                          263     #define KCOV_DISABLE                        _IO('c', 101)
304     #define KCOV_REMOTE_ENABLE          _IOW('    264     #define KCOV_REMOTE_ENABLE          _IOW('c', 102, struct kcov_remote_arg)
305                                                   265 
306     #define COVER_SIZE  (64 << 10)                266     #define COVER_SIZE  (64 << 10)
307                                                   267 
308     #define KCOV_TRACE_PC       0                 268     #define KCOV_TRACE_PC       0
309                                                   269 
310     #define KCOV_SUBSYSTEM_COMMON       (0x00u    270     #define KCOV_SUBSYSTEM_COMMON       (0x00ull << 56)
311     #define KCOV_SUBSYSTEM_USB  (0x01ull << 56    271     #define KCOV_SUBSYSTEM_USB  (0x01ull << 56)
312                                                   272 
313     #define KCOV_SUBSYSTEM_MASK (0xffull << 56    273     #define KCOV_SUBSYSTEM_MASK (0xffull << 56)
314     #define KCOV_INSTANCE_MASK  (0xffffffffull    274     #define KCOV_INSTANCE_MASK  (0xffffffffull)
315                                                   275 
316     static inline __u64 kcov_remote_handle(__u    276     static inline __u64 kcov_remote_handle(__u64 subsys, __u64 inst)
317     {                                             277     {
318         if (subsys & ~KCOV_SUBSYSTEM_MASK || i    278         if (subsys & ~KCOV_SUBSYSTEM_MASK || inst & ~KCOV_INSTANCE_MASK)
319                 return 0;                         279                 return 0;
320         return subsys | inst;                     280         return subsys | inst;
321     }                                             281     }
322                                                   282 
323     #define KCOV_COMMON_ID      0x42              283     #define KCOV_COMMON_ID      0x42
324     #define KCOV_USB_BUS_NUM    1                 284     #define KCOV_USB_BUS_NUM    1
325                                                   285 
326     int main(int argc, char **argv)               286     int main(int argc, char **argv)
327     {                                             287     {
328         int fd;                                   288         int fd;
329         unsigned long *cover, n, i;               289         unsigned long *cover, n, i;
330         struct kcov_remote_arg *arg;              290         struct kcov_remote_arg *arg;
331                                                   291 
332         fd = open("/sys/kernel/debug/kcov", O_    292         fd = open("/sys/kernel/debug/kcov", O_RDWR);
333         if (fd == -1)                             293         if (fd == -1)
334                 perror("open"), exit(1);          294                 perror("open"), exit(1);
335         if (ioctl(fd, KCOV_INIT_TRACE, COVER_S    295         if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE))
336                 perror("ioctl"), exit(1);         296                 perror("ioctl"), exit(1);
337         cover = (unsigned long*)mmap(NULL, COV    297         cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long),
338                                      PROT_READ    298                                      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
339         if ((void*)cover == MAP_FAILED)           299         if ((void*)cover == MAP_FAILED)
340                 perror("mmap"), exit(1);          300                 perror("mmap"), exit(1);
341                                                   301 
342         /* Enable coverage collection via comm    302         /* Enable coverage collection via common handle and from USB bus #1. */
343         arg = calloc(1, sizeof(*arg) + sizeof(    303         arg = calloc(1, sizeof(*arg) + sizeof(uint64_t));
344         if (!arg)                                 304         if (!arg)
345                 perror("calloc"), exit(1);        305                 perror("calloc"), exit(1);
346         arg->trace_mode = KCOV_TRACE_PC;          306         arg->trace_mode = KCOV_TRACE_PC;
347         arg->area_size = COVER_SIZE;              307         arg->area_size = COVER_SIZE;
348         arg->num_handles = 1;                     308         arg->num_handles = 1;
349         arg->common_handle = kcov_remote_handl    309         arg->common_handle = kcov_remote_handle(KCOV_SUBSYSTEM_COMMON,
350                                                   310                                                         KCOV_COMMON_ID);
351         arg->handles[0] = kcov_remote_handle(K    311         arg->handles[0] = kcov_remote_handle(KCOV_SUBSYSTEM_USB,
352                                                   312                                                 KCOV_USB_BUS_NUM);
353         if (ioctl(fd, KCOV_REMOTE_ENABLE, arg)    313         if (ioctl(fd, KCOV_REMOTE_ENABLE, arg))
354                 perror("ioctl"), free(arg), ex    314                 perror("ioctl"), free(arg), exit(1);
355         free(arg);                                315         free(arg);
356                                                   316 
357         /*                                        317         /*
358          * Here the user needs to trigger exec    318          * Here the user needs to trigger execution of a kernel code section
359          * that is either annotated with the c    319          * that is either annotated with the common handle, or to trigger some
360          * activity on USB bus #1.                320          * activity on USB bus #1.
361          */                                       321          */
362         sleep(2);                                 322         sleep(2);
363                                                   323 
364         n = __atomic_load_n(&cover[0], __ATOMI    324         n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
365         for (i = 0; i < n; i++)                   325         for (i = 0; i < n; i++)
366                 printf("0x%lx\n", cover[i + 1]    326                 printf("0x%lx\n", cover[i + 1]);
367         if (ioctl(fd, KCOV_DISABLE, 0))           327         if (ioctl(fd, KCOV_DISABLE, 0))
368                 perror("ioctl"), exit(1);         328                 perror("ioctl"), exit(1);
369         if (munmap(cover, COVER_SIZE * sizeof(    329         if (munmap(cover, COVER_SIZE * sizeof(unsigned long)))
370                 perror("munmap"), exit(1);        330                 perror("munmap"), exit(1);
371         if (close(fd))                            331         if (close(fd))
372                 perror("close"), exit(1);         332                 perror("close"), exit(1);
373         return 0;                                 333         return 0;
374     }                                             334     }
                                                      

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