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"