1Using gcov with the Linux kernel 2================================ 3 4gcov profiling kernel support enables the use of GCC's coverage testing 5tool gcov_ with the Linux kernel. Coverage data of a running kernel 6is exported in gcov-compatible format via the "gcov" debugfs directory. 7To get coverage data for a specific file, change to the kernel build 8directory and use gcov with the ``-o`` option as follows (requires root):: 9 10 # cd /tmp/linux-out 11 # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c 12 13This will create source code files annotated with execution counts 14in the current directory. In addition, graphical gcov front-ends such 15as lcov_ can be used to automate the process of collecting data 16for the entire kernel and provide coverage overviews in HTML format. 17 18Possible uses: 19 20* debugging (has this line been reached at all?) 21* test improvement (how do I change my test to cover these lines?) 22* minimizing kernel configurations (do I need this option if the 23 associated code is never run?) 24 25.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 26.. _lcov: https://github.com/linux-test-project/lcov 27 28 29Preparation 30----------- 31 32Configure the kernel with:: 33 34 CONFIG_DEBUG_FS=y 35 CONFIG_GCOV_KERNEL=y 36 37and to get coverage data for the entire kernel:: 38 39 CONFIG_GCOV_PROFILE_ALL=y 40 41Note that kernels compiled with profiling flags will be significantly 42larger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported 43on all architectures. 44 45Profiling data will only become accessible once debugfs has been 46mounted:: 47 48 mount -t debugfs none /sys/kernel/debug 49 50 51Customization 52------------- 53 54To enable profiling for specific files or directories, add a line 55similar to the following to the respective kernel Makefile: 56 57- For a single file (e.g. main.o):: 58 59 GCOV_PROFILE_main.o := y 60 61- For all files in one directory:: 62 63 GCOV_PROFILE := y 64 65To exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL 66is specified, use:: 67 68 GCOV_PROFILE_main.o := n 69 70and:: 71 72 GCOV_PROFILE := n 73 74Only files which are linked to the main kernel image or are compiled as 75kernel modules are supported by this mechanism. 76 77 78Module specific configs 79----------------------- 80 81Gcov kernel configs for specific modules are described below: 82 83CONFIG_GCOV_PROFILE_RDS: 84 Enables GCOV profiling on RDS for checking which functions or 85 lines are executed. This config is used by the rds selftest to 86 generate coverage reports. If left unset the report is omitted. 87 88 89Files 90----- 91 92The gcov kernel support creates the following files in debugfs: 93 94``/sys/kernel/debug/gcov`` 95 Parent directory for all gcov-related files. 96 97``/sys/kernel/debug/gcov/reset`` 98 Global reset file: resets all coverage data to zero when 99 written to. 100 101``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda`` 102 The actual gcov data file as understood by the gcov 103 tool. Resets file coverage data to zero when written to. 104 105``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno`` 106 Symbolic link to a static data file required by the gcov 107 tool. This file is generated by gcc when compiling with 108 option ``-ftest-coverage``. 109 110 111Modules 112------- 113 114Kernel modules may contain cleanup code which is only run during 115module unload time. The gcov mechanism provides a means to collect 116coverage data for such code by keeping a copy of the data associated 117with the unloaded module. This data remains available through debugfs. 118Once the module is loaded again, the associated coverage counters are 119initialized with the data from its previous instantiation. 120 121This behavior can be deactivated by specifying the gcov_persist kernel 122parameter:: 123 124 gcov_persist=0 125 126At run-time, a user can also choose to discard data for an unloaded 127module by writing to its data file or the global reset file. 128 129 130Separated build and test machines 131--------------------------------- 132 133The gcov kernel profiling infrastructure is designed to work out-of-the 134box for setups where kernels are built and run on the same machine. In 135cases where the kernel runs on a separate machine, special preparations 136must be made, depending on where the gcov tool is used: 137 138.. _gcov-test: 139 140a) gcov is run on the TEST machine 141 142 The gcov tool version on the test machine must be compatible with the 143 gcc version used for kernel build. Also the following files need to be 144 copied from build to test machine: 145 146 from the source tree: 147 - all C source files + headers 148 149 from the build tree: 150 - all C source files + headers 151 - all .gcda and .gcno files 152 - all links to directories 153 154 It is important to note that these files need to be placed into the 155 exact same file system location on the test machine as on the build 156 machine. If any of the path components is symbolic link, the actual 157 directory needs to be used instead (due to make's CURDIR handling). 158 159.. _gcov-build: 160 161b) gcov is run on the BUILD machine 162 163 The following files need to be copied after each test case from test 164 to build machine: 165 166 from the gcov directory in sysfs: 167 - all .gcda files 168 - all links to .gcno files 169 170 These files can be copied to any location on the build machine. gcov 171 must then be called with the -o option pointing to that directory. 172 173 Example directory setup on the build machine:: 174 175 /tmp/linux: kernel source tree 176 /tmp/out: kernel build directory as specified by make O= 177 /tmp/coverage: location of the files copied from the test machine 178 179 [user@build] cd /tmp/out 180 [user@build] gcov -o /tmp/coverage/tmp/out/init main.c 181 182 183Note on compilers 184----------------- 185 186GCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with 187GCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang. 188 189.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 190.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html 191 192Build differences between GCC and Clang gcov are handled by Kconfig. It 193automatically selects the appropriate gcov format depending on the detected 194toolchain. 195 196 197Troubleshooting 198--------------- 199 200Problem 201 Compilation aborts during linker step. 202 203Cause 204 Profiling flags are specified for source files which are not 205 linked to the main kernel or which are linked by a custom 206 linker procedure. 207 208Solution 209 Exclude affected source files from profiling by specifying 210 ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the 211 corresponding Makefile. 212 213Problem 214 Files copied from sysfs appear empty or incomplete. 215 216Cause 217 Due to the way seq_file works, some tools such as cp or tar 218 may not correctly copy files from sysfs. 219 220Solution 221 Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links. 222 Alternatively use the mechanism shown in Appendix B. 223 224 225Appendix A: gather_on_build.sh 226------------------------------ 227 228Sample script to gather coverage meta files on the build machine 229(see :ref:`Separated build and test machines a. <gcov-test>`): 230 231.. code-block:: sh 232 233 #!/bin/bash 234 235 KSRC=$1 236 KOBJ=$2 237 DEST=$3 238 239 if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then 240 echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2 241 exit 1 242 fi 243 244 KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 245 KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 246 247 find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \ 248 -perm /u+r,g+r | tar cfz $DEST -P -T - 249 250 if [ $? -eq 0 ] ; then 251 echo "$DEST successfully created, copy to test system and unpack with:" 252 echo " tar xfz $DEST -P" 253 else 254 echo "Could not create file $DEST" 255 fi 256 257 258Appendix B: gather_on_test.sh 259----------------------------- 260 261Sample script to gather coverage data files on the test machine 262(see :ref:`Separated build and test machines b. <gcov-build>`): 263 264.. code-block:: sh 265 266 #!/bin/bash -e 267 268 DEST=$1 269 GCDA=/sys/kernel/debug/gcov 270 271 if [ -z "$DEST" ] ; then 272 echo "Usage: $0 <output.tar.gz>" >&2 273 exit 1 274 fi 275 276 TEMPDIR=$(mktemp -d) 277 echo Collecting data.. 278 find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; 279 find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; 280 find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; 281 tar czf $DEST -C $TEMPDIR sys 282 rm -rf $TEMPDIR 283 284 echo "$DEST successfully created, copy to build system and unpack with:" 285 echo " tar xfz $DEST" 286