From patchwork Mon Aug 8 23:34:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Corbet X-Patchwork-Id: 73488 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp210071qga; Mon, 8 Aug 2016 16:36:03 -0700 (PDT) X-Received: by 10.98.36.15 with SMTP id r15mr167885335pfj.1.1470699363346; Mon, 08 Aug 2016 16:36:03 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b81si39367518pfb.21.2016.08.08.16.36.03; Mon, 08 Aug 2016 16:36:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752470AbcHHXf7 (ORCPT + 27 others); Mon, 8 Aug 2016 19:35:59 -0400 Received: from tex.lwn.net ([70.33.254.29]:44607 "EHLO vena.lwn.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932105AbcHHXfb (ORCPT ); Mon, 8 Aug 2016 19:35:31 -0400 Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by vena.lwn.net (Postfix) with ESMTP id D8CB01540047; Mon, 8 Aug 2016 17:35:24 -0600 (MDT) From: Jonathan Corbet To: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Jani Nikula , Jonathan Corbet , Dmitry Vyukov Subject: [PATCH 04/10] docs: sphinxify kcov.txt and move to dev-tools Date: Mon, 8 Aug 2016 17:34:56 -0600 Message-Id: <20160808233502.16950-5-corbet@lwn.net> X-Mailer: git-send-email 2.9.2 In-Reply-To: <20160808233502.16950-1-corbet@lwn.net> References: <20160808233502.16950-1-corbet@lwn.net> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Another document added to the dev-tools collection. Cc: Dmitry Vyukov Signed-off-by: Jonathan Corbet --- Documentation/dev-tools/kcov.rst | 111 ++++++++++++++++++++++++++++++++++++++ Documentation/dev-tools/tools.rst | 1 + Documentation/kcov.txt | 111 -------------------------------------- 3 files changed, 112 insertions(+), 111 deletions(-) create mode 100644 Documentation/dev-tools/kcov.rst delete mode 100644 Documentation/kcov.txt -- 2.9.2 diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst new file mode 100644 index 0000000..01d652a --- /dev/null +++ b/Documentation/dev-tools/kcov.rst @@ -0,0 +1,111 @@ +kcov: code coverage for fuzzing +=============================== + +kcov exposes kernel code coverage information in a form suitable for coverage- +guided fuzzing (randomized testing). Coverage data of a running kernel is +exported via the "kcov" debugfs file. Coverage collection is enabled on a task +basis, and thus it can capture precise coverage of a single system call. + +Note that kcov does not aim to collect as much coverage as possible. It aims +to collect more or less stable coverage that is function of syscall inputs. +To achieve this goal it does not collect coverage in soft/hard interrupts +and instrumentation of some inherently non-deterministic parts of kernel is +disbled (e.g. scheduler, locking). + +Usage +----- + +Configure the kernel with:: + + CONFIG_KCOV=y + +CONFIG_KCOV requires gcc built on revision 231296 or later. +Profiling data will only become accessible once debugfs has been mounted:: + + mount -t debugfs none /sys/kernel/debug + +The following program demonstrates kcov usage from within a test program:: + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long) + #define KCOV_ENABLE _IO('c', 100) + #define KCOV_DISABLE _IO('c', 101) + #define COVER_SIZE (64<<10) + + int main(int argc, char **argv) + { + int fd; + unsigned long *cover, n, i; + + /* A single fd descriptor allows coverage collection on a single + * thread. + */ + fd = open("/sys/kernel/debug/kcov", O_RDWR); + if (fd == -1) + perror("open"), exit(1); + /* Setup trace mode and trace size. */ + if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE)) + perror("ioctl"), exit(1); + /* Mmap buffer shared between kernel- and user-space. */ + cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if ((void*)cover == MAP_FAILED) + perror("mmap"), exit(1); + /* Enable coverage collection on the current thread. */ + if (ioctl(fd, KCOV_ENABLE, 0)) + perror("ioctl"), exit(1); + /* Reset coverage from the tail of the ioctl() call. */ + __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); + /* That's the target syscal call. */ + read(-1, NULL, 0); + /* Read number of PCs collected. */ + n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED); + for (i = 0; i < n; i++) + printf("0x%lx\n", cover[i + 1]); + /* Disable coverage collection for the current thread. After this call + * coverage can be enabled for a different thread. + */ + if (ioctl(fd, KCOV_DISABLE, 0)) + perror("ioctl"), exit(1); + /* Free resources. */ + if (munmap(cover, COVER_SIZE * sizeof(unsigned long))) + perror("munmap"), exit(1); + if (close(fd)) + perror("close"), exit(1); + return 0; + } + +After piping through addr2line output of the program looks as follows:: + + SyS_read + fs/read_write.c:562 + __fdget_pos + fs/file.c:774 + __fget_light + fs/file.c:746 + __fget_light + fs/file.c:750 + __fget_light + fs/file.c:760 + __fdget_pos + fs/file.c:784 + SyS_read + fs/read_write.c:562 + +If a program needs to collect coverage from several threads (independently), +it needs to open /sys/kernel/debug/kcov in each thread separately. + +The interface is fine-grained to allow efficient forking of test processes. +That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode, +mmaps coverage buffer and then forks child processes in a loop. Child processes +only need to enable coverage (disable happens automatically on thread end). diff --git a/Documentation/dev-tools/tools.rst b/Documentation/dev-tools/tools.rst index d4bbda3..9dcd023 100644 --- a/Documentation/dev-tools/tools.rst +++ b/Documentation/dev-tools/tools.rst @@ -16,3 +16,4 @@ whole; patches welcome! coccinelle sparse + kcov diff --git a/Documentation/kcov.txt b/Documentation/kcov.txt deleted file mode 100644 index 779ff4a..0000000 --- a/Documentation/kcov.txt +++ /dev/null @@ -1,111 +0,0 @@ -kcov: code coverage for fuzzing -=============================== - -kcov exposes kernel code coverage information in a form suitable for coverage- -guided fuzzing (randomized testing). Coverage data of a running kernel is -exported via the "kcov" debugfs file. Coverage collection is enabled on a task -basis, and thus it can capture precise coverage of a single system call. - -Note that kcov does not aim to collect as much coverage as possible. It aims -to collect more or less stable coverage that is function of syscall inputs. -To achieve this goal it does not collect coverage in soft/hard interrupts -and instrumentation of some inherently non-deterministic parts of kernel is -disbled (e.g. scheduler, locking). - -Usage: -====== - -Configure kernel with: - - CONFIG_KCOV=y - -CONFIG_KCOV requires gcc built on revision 231296 or later. -Profiling data will only become accessible once debugfs has been mounted: - - mount -t debugfs none /sys/kernel/debug - -The following program demonstrates kcov usage from within a test program: - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long) -#define KCOV_ENABLE _IO('c', 100) -#define KCOV_DISABLE _IO('c', 101) -#define COVER_SIZE (64<<10) - -int main(int argc, char **argv) -{ - int fd; - unsigned long *cover, n, i; - - /* A single fd descriptor allows coverage collection on a single - * thread. - */ - fd = open("/sys/kernel/debug/kcov", O_RDWR); - if (fd == -1) - perror("open"), exit(1); - /* Setup trace mode and trace size. */ - if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE)) - perror("ioctl"), exit(1); - /* Mmap buffer shared between kernel- and user-space. */ - cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if ((void*)cover == MAP_FAILED) - perror("mmap"), exit(1); - /* Enable coverage collection on the current thread. */ - if (ioctl(fd, KCOV_ENABLE, 0)) - perror("ioctl"), exit(1); - /* Reset coverage from the tail of the ioctl() call. */ - __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); - /* That's the target syscal call. */ - read(-1, NULL, 0); - /* Read number of PCs collected. */ - n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED); - for (i = 0; i < n; i++) - printf("0x%lx\n", cover[i + 1]); - /* Disable coverage collection for the current thread. After this call - * coverage can be enabled for a different thread. - */ - if (ioctl(fd, KCOV_DISABLE, 0)) - perror("ioctl"), exit(1); - /* Free resources. */ - if (munmap(cover, COVER_SIZE * sizeof(unsigned long))) - perror("munmap"), exit(1); - if (close(fd)) - perror("close"), exit(1); - return 0; -} - -After piping through addr2line output of the program looks as follows: - -SyS_read -fs/read_write.c:562 -__fdget_pos -fs/file.c:774 -__fget_light -fs/file.c:746 -__fget_light -fs/file.c:750 -__fget_light -fs/file.c:760 -__fdget_pos -fs/file.c:784 -SyS_read -fs/read_write.c:562 - -If a program needs to collect coverage from several threads (independently), -it needs to open /sys/kernel/debug/kcov in each thread separately. - -The interface is fine-grained to allow efficient forking of test processes. -That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode, -mmaps coverage buffer and then forks child processes in a loop. Child processes -only need to enable coverage (disable happens automatically on thread end).