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

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