mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Htmldocs does not display the chapter number, convert the two manual chapter number tags to ref tags. Signed-off-by: Wu XiangCheng <bobwxc@email.cn> Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com> Link: https://lore.kernel.org/r/20210403113752.GA32236@mipc Signed-off-by: Jonathan Corbet <corbet@lwn.net>
		
			
				
	
	
		
			274 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			274 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
Using gcov with the Linux kernel
 | 
						|
================================
 | 
						|
 | 
						|
gcov profiling kernel support enables the use of GCC's coverage testing
 | 
						|
tool gcov_ with the Linux kernel. Coverage data of a running kernel
 | 
						|
is exported in gcov-compatible format via the "gcov" debugfs directory.
 | 
						|
To get coverage data for a specific file, change to the kernel build
 | 
						|
directory and use gcov with the ``-o`` option as follows (requires root)::
 | 
						|
 | 
						|
    # cd /tmp/linux-out
 | 
						|
    # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
 | 
						|
 | 
						|
This will create source code files annotated with execution counts
 | 
						|
in the current directory. In addition, graphical gcov front-ends such
 | 
						|
as lcov_ can be used to automate the process of collecting data
 | 
						|
for the entire kernel and provide coverage overviews in HTML format.
 | 
						|
 | 
						|
Possible uses:
 | 
						|
 | 
						|
* debugging (has this line been reached at all?)
 | 
						|
* test improvement (how do I change my test to cover these lines?)
 | 
						|
* minimizing kernel configurations (do I need this option if the
 | 
						|
  associated code is never run?)
 | 
						|
 | 
						|
.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
 | 
						|
.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
 | 
						|
 | 
						|
 | 
						|
Preparation
 | 
						|
-----------
 | 
						|
 | 
						|
Configure the kernel with::
 | 
						|
 | 
						|
        CONFIG_DEBUG_FS=y
 | 
						|
        CONFIG_GCOV_KERNEL=y
 | 
						|
 | 
						|
and to get coverage data for the entire kernel::
 | 
						|
 | 
						|
        CONFIG_GCOV_PROFILE_ALL=y
 | 
						|
 | 
						|
Note that kernels compiled with profiling flags will be significantly
 | 
						|
larger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported
 | 
						|
on all architectures.
 | 
						|
 | 
						|
Profiling data will only become accessible once debugfs has been
 | 
						|
mounted::
 | 
						|
 | 
						|
        mount -t debugfs none /sys/kernel/debug
 | 
						|
 | 
						|
 | 
						|
Customization
 | 
						|
-------------
 | 
						|
 | 
						|
To enable profiling for specific files or directories, add a line
 | 
						|
similar to the following to the respective kernel Makefile:
 | 
						|
 | 
						|
- For a single file (e.g. main.o)::
 | 
						|
 | 
						|
	GCOV_PROFILE_main.o := y
 | 
						|
 | 
						|
- For all files in one directory::
 | 
						|
 | 
						|
	GCOV_PROFILE := y
 | 
						|
 | 
						|
To exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL
 | 
						|
is specified, use::
 | 
						|
 | 
						|
	GCOV_PROFILE_main.o := n
 | 
						|
 | 
						|
and::
 | 
						|
 | 
						|
	GCOV_PROFILE := n
 | 
						|
 | 
						|
Only files which are linked to the main kernel image or are compiled as
 | 
						|
kernel modules are supported by this mechanism.
 | 
						|
 | 
						|
 | 
						|
Files
 | 
						|
-----
 | 
						|
 | 
						|
The gcov kernel support creates the following files in debugfs:
 | 
						|
 | 
						|
``/sys/kernel/debug/gcov``
 | 
						|
	Parent directory for all gcov-related files.
 | 
						|
 | 
						|
``/sys/kernel/debug/gcov/reset``
 | 
						|
	Global reset file: resets all coverage data to zero when
 | 
						|
        written to.
 | 
						|
 | 
						|
``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda``
 | 
						|
	The actual gcov data file as understood by the gcov
 | 
						|
        tool. Resets file coverage data to zero when written to.
 | 
						|
 | 
						|
``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno``
 | 
						|
	Symbolic link to a static data file required by the gcov
 | 
						|
        tool. This file is generated by gcc when compiling with
 | 
						|
        option ``-ftest-coverage``.
 | 
						|
 | 
						|
 | 
						|
Modules
 | 
						|
-------
 | 
						|
 | 
						|
Kernel modules may contain cleanup code which is only run during
 | 
						|
module unload time. The gcov mechanism provides a means to collect
 | 
						|
coverage data for such code by keeping a copy of the data associated
 | 
						|
with the unloaded module. This data remains available through debugfs.
 | 
						|
Once the module is loaded again, the associated coverage counters are
 | 
						|
initialized with the data from its previous instantiation.
 | 
						|
 | 
						|
This behavior can be deactivated by specifying the gcov_persist kernel
 | 
						|
parameter::
 | 
						|
 | 
						|
        gcov_persist=0
 | 
						|
 | 
						|
At run-time, a user can also choose to discard data for an unloaded
 | 
						|
module by writing to its data file or the global reset file.
 | 
						|
 | 
						|
 | 
						|
Separated build and test machines
 | 
						|
---------------------------------
 | 
						|
 | 
						|
The gcov kernel profiling infrastructure is designed to work out-of-the
 | 
						|
box for setups where kernels are built and run on the same machine. In
 | 
						|
cases where the kernel runs on a separate machine, special preparations
 | 
						|
must be made, depending on where the gcov tool is used:
 | 
						|
 | 
						|
.. _gcov-test:
 | 
						|
 | 
						|
a) gcov is run on the TEST machine
 | 
						|
 | 
						|
    The gcov tool version on the test machine must be compatible with the
 | 
						|
    gcc version used for kernel build. Also the following files need to be
 | 
						|
    copied from build to test machine:
 | 
						|
 | 
						|
    from the source tree:
 | 
						|
      - all C source files + headers
 | 
						|
 | 
						|
    from the build tree:
 | 
						|
      - all C source files + headers
 | 
						|
      - all .gcda and .gcno files
 | 
						|
      - all links to directories
 | 
						|
 | 
						|
    It is important to note that these files need to be placed into the
 | 
						|
    exact same file system location on the test machine as on the build
 | 
						|
    machine. If any of the path components is symbolic link, the actual
 | 
						|
    directory needs to be used instead (due to make's CURDIR handling).
 | 
						|
 | 
						|
.. _gcov-build:
 | 
						|
 | 
						|
b) gcov is run on the BUILD machine
 | 
						|
 | 
						|
    The following files need to be copied after each test case from test
 | 
						|
    to build machine:
 | 
						|
 | 
						|
    from the gcov directory in sysfs:
 | 
						|
      - all .gcda files
 | 
						|
      - all links to .gcno files
 | 
						|
 | 
						|
    These files can be copied to any location on the build machine. gcov
 | 
						|
    must then be called with the -o option pointing to that directory.
 | 
						|
 | 
						|
    Example directory setup on the build machine::
 | 
						|
 | 
						|
      /tmp/linux:    kernel source tree
 | 
						|
      /tmp/out:      kernel build directory as specified by make O=
 | 
						|
      /tmp/coverage: location of the files copied from the test machine
 | 
						|
 | 
						|
      [user@build] cd /tmp/out
 | 
						|
      [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
 | 
						|
 | 
						|
 | 
						|
Note on compilers
 | 
						|
-----------------
 | 
						|
 | 
						|
GCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with
 | 
						|
GCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang.
 | 
						|
 | 
						|
.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
 | 
						|
.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html
 | 
						|
 | 
						|
Build differences between GCC and Clang gcov are handled by Kconfig. It
 | 
						|
automatically selects the appropriate gcov format depending on the detected
 | 
						|
toolchain.
 | 
						|
 | 
						|
 | 
						|
Troubleshooting
 | 
						|
---------------
 | 
						|
 | 
						|
Problem
 | 
						|
    Compilation aborts during linker step.
 | 
						|
 | 
						|
Cause
 | 
						|
    Profiling flags are specified for source files which are not
 | 
						|
    linked to the main kernel or which are linked by a custom
 | 
						|
    linker procedure.
 | 
						|
 | 
						|
Solution
 | 
						|
    Exclude affected source files from profiling by specifying
 | 
						|
    ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the
 | 
						|
    corresponding Makefile.
 | 
						|
 | 
						|
Problem
 | 
						|
    Files copied from sysfs appear empty or incomplete.
 | 
						|
 | 
						|
Cause
 | 
						|
    Due to the way seq_file works, some tools such as cp or tar
 | 
						|
    may not correctly copy files from sysfs.
 | 
						|
 | 
						|
Solution
 | 
						|
    Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links.
 | 
						|
    Alternatively use the mechanism shown in Appendix B.
 | 
						|
 | 
						|
 | 
						|
Appendix A: gather_on_build.sh
 | 
						|
------------------------------
 | 
						|
 | 
						|
Sample script to gather coverage meta files on the build machine
 | 
						|
(see :ref:`Separated build and test machines a. <gcov-test>`):
 | 
						|
 | 
						|
.. code-block:: sh
 | 
						|
 | 
						|
    #!/bin/bash
 | 
						|
 | 
						|
    KSRC=$1
 | 
						|
    KOBJ=$2
 | 
						|
    DEST=$3
 | 
						|
 | 
						|
    if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then
 | 
						|
      echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2
 | 
						|
      exit 1
 | 
						|
    fi
 | 
						|
 | 
						|
    KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
 | 
						|
    KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
 | 
						|
 | 
						|
    find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \
 | 
						|
                     -perm /u+r,g+r | tar cfz $DEST -P -T -
 | 
						|
 | 
						|
    if [ $? -eq 0 ] ; then
 | 
						|
      echo "$DEST successfully created, copy to test system and unpack with:"
 | 
						|
      echo "  tar xfz $DEST -P"
 | 
						|
    else
 | 
						|
      echo "Could not create file $DEST"
 | 
						|
    fi
 | 
						|
 | 
						|
 | 
						|
Appendix B: gather_on_test.sh
 | 
						|
-----------------------------
 | 
						|
 | 
						|
Sample script to gather coverage data files on the test machine
 | 
						|
(see :ref:`Separated build and test machines b. <gcov-build>`):
 | 
						|
 | 
						|
.. code-block:: sh
 | 
						|
 | 
						|
    #!/bin/bash -e
 | 
						|
 | 
						|
    DEST=$1
 | 
						|
    GCDA=/sys/kernel/debug/gcov
 | 
						|
 | 
						|
    if [ -z "$DEST" ] ; then
 | 
						|
      echo "Usage: $0 <output.tar.gz>" >&2
 | 
						|
      exit 1
 | 
						|
    fi
 | 
						|
 | 
						|
    TEMPDIR=$(mktemp -d)
 | 
						|
    echo Collecting data..
 | 
						|
    find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
 | 
						|
    find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
 | 
						|
    find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
 | 
						|
    tar czf $DEST -C $TEMPDIR sys
 | 
						|
    rm -rf $TEMPDIR
 | 
						|
 | 
						|
    echo "$DEST successfully created, copy to build system and unpack with:"
 | 
						|
    echo "  tar xfz $DEST"
 |