Back to home page

OSCL-LXR

 
 

    


0001 Using gcov with the Linux kernel
0002 ================================
0003 
0004 gcov profiling kernel support enables the use of GCC's coverage testing
0005 tool gcov_ with the Linux kernel. Coverage data of a running kernel
0006 is exported in gcov-compatible format via the "gcov" debugfs directory.
0007 To get coverage data for a specific file, change to the kernel build
0008 directory and use gcov with the ``-o`` option as follows (requires root)::
0009 
0010     # cd /tmp/linux-out
0011     # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
0012 
0013 This will create source code files annotated with execution counts
0014 in the current directory. In addition, graphical gcov front-ends such
0015 as lcov_ can be used to automate the process of collecting data
0016 for the entire kernel and provide coverage overviews in HTML format.
0017 
0018 Possible uses:
0019 
0020 * debugging (has this line been reached at all?)
0021 * test improvement (how do I change my test to cover these lines?)
0022 * minimizing kernel configurations (do I need this option if the
0023   associated code is never run?)
0024 
0025 .. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
0026 .. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
0027 
0028 
0029 Preparation
0030 -----------
0031 
0032 Configure the kernel with::
0033 
0034         CONFIG_DEBUG_FS=y
0035         CONFIG_GCOV_KERNEL=y
0036 
0037 and to get coverage data for the entire kernel::
0038 
0039         CONFIG_GCOV_PROFILE_ALL=y
0040 
0041 Note that kernels compiled with profiling flags will be significantly
0042 larger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported
0043 on all architectures.
0044 
0045 Profiling data will only become accessible once debugfs has been
0046 mounted::
0047 
0048         mount -t debugfs none /sys/kernel/debug
0049 
0050 
0051 Customization
0052 -------------
0053 
0054 To enable profiling for specific files or directories, add a line
0055 similar to the following to the respective kernel Makefile:
0056 
0057 - For a single file (e.g. main.o)::
0058 
0059         GCOV_PROFILE_main.o := y
0060 
0061 - For all files in one directory::
0062 
0063         GCOV_PROFILE := y
0064 
0065 To exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL
0066 is specified, use::
0067 
0068         GCOV_PROFILE_main.o := n
0069 
0070 and::
0071 
0072         GCOV_PROFILE := n
0073 
0074 Only files which are linked to the main kernel image or are compiled as
0075 kernel modules are supported by this mechanism.
0076 
0077 
0078 Files
0079 -----
0080 
0081 The gcov kernel support creates the following files in debugfs:
0082 
0083 ``/sys/kernel/debug/gcov``
0084         Parent directory for all gcov-related files.
0085 
0086 ``/sys/kernel/debug/gcov/reset``
0087         Global reset file: resets all coverage data to zero when
0088         written to.
0089 
0090 ``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda``
0091         The actual gcov data file as understood by the gcov
0092         tool. Resets file coverage data to zero when written to.
0093 
0094 ``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno``
0095         Symbolic link to a static data file required by the gcov
0096         tool. This file is generated by gcc when compiling with
0097         option ``-ftest-coverage``.
0098 
0099 
0100 Modules
0101 -------
0102 
0103 Kernel modules may contain cleanup code which is only run during
0104 module unload time. The gcov mechanism provides a means to collect
0105 coverage data for such code by keeping a copy of the data associated
0106 with the unloaded module. This data remains available through debugfs.
0107 Once the module is loaded again, the associated coverage counters are
0108 initialized with the data from its previous instantiation.
0109 
0110 This behavior can be deactivated by specifying the gcov_persist kernel
0111 parameter::
0112 
0113         gcov_persist=0
0114 
0115 At run-time, a user can also choose to discard data for an unloaded
0116 module by writing to its data file or the global reset file.
0117 
0118 
0119 Separated build and test machines
0120 ---------------------------------
0121 
0122 The gcov kernel profiling infrastructure is designed to work out-of-the
0123 box for setups where kernels are built and run on the same machine. In
0124 cases where the kernel runs on a separate machine, special preparations
0125 must be made, depending on where the gcov tool is used:
0126 
0127 .. _gcov-test:
0128 
0129 a) gcov is run on the TEST machine
0130 
0131     The gcov tool version on the test machine must be compatible with the
0132     gcc version used for kernel build. Also the following files need to be
0133     copied from build to test machine:
0134 
0135     from the source tree:
0136       - all C source files + headers
0137 
0138     from the build tree:
0139       - all C source files + headers
0140       - all .gcda and .gcno files
0141       - all links to directories
0142 
0143     It is important to note that these files need to be placed into the
0144     exact same file system location on the test machine as on the build
0145     machine. If any of the path components is symbolic link, the actual
0146     directory needs to be used instead (due to make's CURDIR handling).
0147 
0148 .. _gcov-build:
0149 
0150 b) gcov is run on the BUILD machine
0151 
0152     The following files need to be copied after each test case from test
0153     to build machine:
0154 
0155     from the gcov directory in sysfs:
0156       - all .gcda files
0157       - all links to .gcno files
0158 
0159     These files can be copied to any location on the build machine. gcov
0160     must then be called with the -o option pointing to that directory.
0161 
0162     Example directory setup on the build machine::
0163 
0164       /tmp/linux:    kernel source tree
0165       /tmp/out:      kernel build directory as specified by make O=
0166       /tmp/coverage: location of the files copied from the test machine
0167 
0168       [user@build] cd /tmp/out
0169       [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
0170 
0171 
0172 Note on compilers
0173 -----------------
0174 
0175 GCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with
0176 GCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang.
0177 
0178 .. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
0179 .. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html
0180 
0181 Build differences between GCC and Clang gcov are handled by Kconfig. It
0182 automatically selects the appropriate gcov format depending on the detected
0183 toolchain.
0184 
0185 
0186 Troubleshooting
0187 ---------------
0188 
0189 Problem
0190     Compilation aborts during linker step.
0191 
0192 Cause
0193     Profiling flags are specified for source files which are not
0194     linked to the main kernel or which are linked by a custom
0195     linker procedure.
0196 
0197 Solution
0198     Exclude affected source files from profiling by specifying
0199     ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the
0200     corresponding Makefile.
0201 
0202 Problem
0203     Files copied from sysfs appear empty or incomplete.
0204 
0205 Cause
0206     Due to the way seq_file works, some tools such as cp or tar
0207     may not correctly copy files from sysfs.
0208 
0209 Solution
0210     Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links.
0211     Alternatively use the mechanism shown in Appendix B.
0212 
0213 
0214 Appendix A: gather_on_build.sh
0215 ------------------------------
0216 
0217 Sample script to gather coverage meta files on the build machine
0218 (see :ref:`Separated build and test machines a. <gcov-test>`):
0219 
0220 .. code-block:: sh
0221 
0222     #!/bin/bash
0223 
0224     KSRC=$1
0225     KOBJ=$2
0226     DEST=$3
0227 
0228     if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then
0229       echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2
0230       exit 1
0231     fi
0232 
0233     KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
0234     KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
0235 
0236     find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \
0237                      -perm /u+r,g+r | tar cfz $DEST -P -T -
0238 
0239     if [ $? -eq 0 ] ; then
0240       echo "$DEST successfully created, copy to test system and unpack with:"
0241       echo "  tar xfz $DEST -P"
0242     else
0243       echo "Could not create file $DEST"
0244     fi
0245 
0246 
0247 Appendix B: gather_on_test.sh
0248 -----------------------------
0249 
0250 Sample script to gather coverage data files on the test machine
0251 (see :ref:`Separated build and test machines b. <gcov-build>`):
0252 
0253 .. code-block:: sh
0254 
0255     #!/bin/bash -e
0256 
0257     DEST=$1
0258     GCDA=/sys/kernel/debug/gcov
0259 
0260     if [ -z "$DEST" ] ; then
0261       echo "Usage: $0 <output.tar.gz>" >&2
0262       exit 1
0263     fi
0264 
0265     TEMPDIR=$(mktemp -d)
0266     echo Collecting data..
0267     find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
0268     find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
0269     find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
0270     tar czf $DEST -C $TEMPDIR sys
0271     rm -rf $TEMPDIR
0272 
0273     echo "$DEST successfully created, copy to build system and unpack with:"
0274     echo "  tar xfz $DEST"