diff options
| author | Victor Chibotaru <tchibo@google.com> | 2017-11-17 18:30:53 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-17 19:10:04 -0500 |
| commit | c512ac01d8a841033da8ec538a83f80fb0b4d1fe (patch) | |
| tree | 061061c976f2cb1de50170092710ced6a5ac6401 /Documentation/dev-tools | |
| parent | d677a4d6019385488e794cc47bd3d6f9c2aab874 (diff) | |
kcov: update documentation
The updated documentation describes new KCOV mode for collecting
comparison operands.
Link: http://lkml.kernel.org/r/20171011095459.70721-3-glider@google.com
Signed-off-by: Victor Chibotaru <tchibo@google.com>
Signed-off-by: Alexander Potapenko <glider@google.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Popov <alex.popov@linux.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Cc: <syzkaller@googlegroups.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'Documentation/dev-tools')
| -rw-r--r-- | Documentation/dev-tools/kcov.rst | 99 |
1 files changed, 95 insertions, 4 deletions
diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst index 44886c91e112..c2f6452e38ed 100644 --- a/Documentation/dev-tools/kcov.rst +++ b/Documentation/dev-tools/kcov.rst | |||
| @@ -12,19 +12,30 @@ To achieve this goal it does not collect coverage in soft/hard interrupts | |||
| 12 | and instrumentation of some inherently non-deterministic parts of kernel is | 12 | and instrumentation of some inherently non-deterministic parts of kernel is |
| 13 | disabled (e.g. scheduler, locking). | 13 | disabled (e.g. scheduler, locking). |
| 14 | 14 | ||
| 15 | Usage | 15 | kcov is also able to collect comparison operands from the instrumented code |
| 16 | ----- | 16 | (this feature currently requires that the kernel is compiled with clang). |
| 17 | |||
| 18 | Prerequisites | ||
| 19 | ------------- | ||
| 17 | 20 | ||
| 18 | Configure the kernel with:: | 21 | Configure the kernel with:: |
| 19 | 22 | ||
| 20 | CONFIG_KCOV=y | 23 | CONFIG_KCOV=y |
| 21 | 24 | ||
| 22 | CONFIG_KCOV requires gcc built on revision 231296 or later. | 25 | CONFIG_KCOV requires gcc built on revision 231296 or later. |
| 26 | |||
| 27 | If the comparison operands need to be collected, set:: | ||
| 28 | |||
| 29 | CONFIG_KCOV_ENABLE_COMPARISONS=y | ||
| 30 | |||
| 23 | Profiling data will only become accessible once debugfs has been mounted:: | 31 | Profiling data will only become accessible once debugfs has been mounted:: |
| 24 | 32 | ||
| 25 | mount -t debugfs none /sys/kernel/debug | 33 | mount -t debugfs none /sys/kernel/debug |
| 26 | 34 | ||
| 27 | The following program demonstrates kcov usage from within a test program: | 35 | Coverage collection |
| 36 | ------------------- | ||
| 37 | The following program demonstrates coverage collection from within a test | ||
| 38 | program using kcov: | ||
| 28 | 39 | ||
| 29 | .. code-block:: c | 40 | .. code-block:: c |
| 30 | 41 | ||
| @@ -44,6 +55,9 @@ The following program demonstrates kcov usage from within a test program: | |||
| 44 | #define KCOV_DISABLE _IO('c', 101) | 55 | #define KCOV_DISABLE _IO('c', 101) |
| 45 | #define COVER_SIZE (64<<10) | 56 | #define COVER_SIZE (64<<10) |
| 46 | 57 | ||
| 58 | #define KCOV_TRACE_PC 0 | ||
| 59 | #define KCOV_TRACE_CMP 1 | ||
| 60 | |||
| 47 | int main(int argc, char **argv) | 61 | int main(int argc, char **argv) |
| 48 | { | 62 | { |
| 49 | int fd; | 63 | int fd; |
| @@ -64,7 +78,7 @@ The following program demonstrates kcov usage from within a test program: | |||
| 64 | if ((void*)cover == MAP_FAILED) | 78 | if ((void*)cover == MAP_FAILED) |
| 65 | perror("mmap"), exit(1); | 79 | perror("mmap"), exit(1); |
| 66 | /* Enable coverage collection on the current thread. */ | 80 | /* Enable coverage collection on the current thread. */ |
| 67 | if (ioctl(fd, KCOV_ENABLE, 0)) | 81 | if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_PC)) |
| 68 | perror("ioctl"), exit(1); | 82 | perror("ioctl"), exit(1); |
| 69 | /* Reset coverage from the tail of the ioctl() call. */ | 83 | /* Reset coverage from the tail of the ioctl() call. */ |
| 70 | __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); | 84 | __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); |
| @@ -111,3 +125,80 @@ The interface is fine-grained to allow efficient forking of test processes. | |||
| 111 | That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode, | 125 | That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode, |
| 112 | mmaps coverage buffer and then forks child processes in a loop. Child processes | 126 | mmaps coverage buffer and then forks child processes in a loop. Child processes |
| 113 | only need to enable coverage (disable happens automatically on thread end). | 127 | only need to enable coverage (disable happens automatically on thread end). |
| 128 | |||
| 129 | Comparison operands collection | ||
| 130 | ------------------------------ | ||
| 131 | Comparison operands collection is similar to coverage collection: | ||
| 132 | |||
| 133 | .. code-block:: c | ||
| 134 | |||
| 135 | /* Same includes and defines as above. */ | ||
| 136 | |||
| 137 | /* Number of 64-bit words per record. */ | ||
| 138 | #define KCOV_WORDS_PER_CMP 4 | ||
| 139 | |||
| 140 | /* | ||
| 141 | * The format for the types of collected comparisons. | ||
| 142 | * | ||
| 143 | * Bit 0 shows whether one of the arguments is a compile-time constant. | ||
| 144 | * Bits 1 & 2 contain log2 of the argument size, up to 8 bytes. | ||
| 145 | */ | ||
| 146 | |||
| 147 | #define KCOV_CMP_CONST (1 << 0) | ||
| 148 | #define KCOV_CMP_SIZE(n) ((n) << 1) | ||
| 149 | #define KCOV_CMP_MASK KCOV_CMP_SIZE(3) | ||
| 150 | |||
| 151 | int main(int argc, char **argv) | ||
| 152 | { | ||
| 153 | int fd; | ||
| 154 | uint64_t *cover, type, arg1, arg2, is_const, size; | ||
| 155 | unsigned long n, i; | ||
| 156 | |||
| 157 | fd = open("/sys/kernel/debug/kcov", O_RDWR); | ||
| 158 | if (fd == -1) | ||
| 159 | perror("open"), exit(1); | ||
| 160 | if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE)) | ||
| 161 | perror("ioctl"), exit(1); | ||
| 162 | /* | ||
| 163 | * Note that the buffer pointer is of type uint64_t*, because all | ||
| 164 | * the comparison operands are promoted to uint64_t. | ||
| 165 | */ | ||
| 166 | cover = (uint64_t *)mmap(NULL, COVER_SIZE * sizeof(unsigned long), | ||
| 167 | PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | ||
| 168 | if ((void*)cover == MAP_FAILED) | ||
| 169 | perror("mmap"), exit(1); | ||
| 170 | /* Note KCOV_TRACE_CMP instead of KCOV_TRACE_PC. */ | ||
| 171 | if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_CMP)) | ||
| 172 | perror("ioctl"), exit(1); | ||
| 173 | __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); | ||
| 174 | read(-1, NULL, 0); | ||
| 175 | /* Read number of comparisons collected. */ | ||
| 176 | n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED); | ||
| 177 | for (i = 0; i < n; i++) { | ||
| 178 | type = cover[i * KCOV_WORDS_PER_CMP + 1]; | ||
| 179 | /* arg1 and arg2 - operands of the comparison. */ | ||
| 180 | arg1 = cover[i * KCOV_WORDS_PER_CMP + 2]; | ||
| 181 | arg2 = cover[i * KCOV_WORDS_PER_CMP + 3]; | ||
| 182 | /* ip - caller address. */ | ||
| 183 | ip = cover[i * KCOV_WORDS_PER_CMP + 4]; | ||
| 184 | /* size of the operands. */ | ||
| 185 | size = 1 << ((type & KCOV_CMP_MASK) >> 1); | ||
| 186 | /* is_const - true if either operand is a compile-time constant.*/ | ||
| 187 | is_const = type & KCOV_CMP_CONST; | ||
| 188 | printf("ip: 0x%lx type: 0x%lx, arg1: 0x%lx, arg2: 0x%lx, " | ||
| 189 | "size: %lu, %s\n", | ||
| 190 | ip, type, arg1, arg2, size, | ||
| 191 | is_const ? "const" : "non-const"); | ||
| 192 | } | ||
| 193 | if (ioctl(fd, KCOV_DISABLE, 0)) | ||
| 194 | perror("ioctl"), exit(1); | ||
| 195 | /* Free resources. */ | ||
| 196 | if (munmap(cover, COVER_SIZE * sizeof(unsigned long))) | ||
| 197 | perror("munmap"), exit(1); | ||
| 198 | if (close(fd)) | ||
| 199 | perror("close"), exit(1); | ||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | Note that the kcov modes (coverage collection or comparison operands) are | ||
| 204 | mutually exclusive. | ||
