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: http://ltp.sourceforge.net/coverage/lcov.php 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 78Files 79----- 80 81The gcov kernel support creates the following files in debugfs: 82 83``/sys/kernel/debug/gcov`` 84 Parent directory for all gcov-related files. 85 86``/sys/kernel/debug/gcov/reset`` 87 Global reset file: resets all coverage data to zero when 88 written to. 89 90``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda`` 91 The actual gcov data file as understood by the gcov 92 tool. Resets file coverage data to zero when written to. 93 94``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno`` 95 Symbolic link to a static data file required by the gcov 96 tool. This file is generated by gcc when compiling with 97 option ``-ftest-coverage``. 98 99 100Modules 101------- 102 103Kernel modules may contain cleanup code which is only run during 104module unload time. The gcov mechanism provides a means to collect 105coverage data for such code by keeping a copy of the data associated 106with the unloaded module. This data remains available through debugfs. 107Once the module is loaded again, the associated coverage counters are 108initialized with the data from its previous instantiation. 109 110This behavior can be deactivated by specifying the gcov_persist kernel 111parameter:: 112 113 gcov_persist=0 114 115At run-time, a user can also choose to discard data for an unloaded 116module by writing to its data file or the global reset file. 117 118 119Separated build and test machines 120--------------------------------- 121 122The gcov kernel profiling infrastructure is designed to work out-of-the 123box for setups where kernels are built and run on the same machine. In 124cases where the kernel runs on a separate machine, special preparations 125must be made, depending on where the gcov tool is used: 126 127a) gcov is run on the TEST machine 128 129 The gcov tool version on the test machine must be compatible with the 130 gcc version used for kernel build. Also the following files need to be 131 copied from build to test machine: 132 133 from the source tree: 134 - all C source files + headers 135 136 from the build tree: 137 - all C source files + headers 138 - all .gcda and .gcno files 139 - all links to directories 140 141 It is important to note that these files need to be placed into the 142 exact same file system location on the test machine as on the build 143 machine. If any of the path components is symbolic link, the actual 144 directory needs to be used instead (due to make's CURDIR handling). 145 146b) gcov is run on the BUILD machine 147 148 The following files need to be copied after each test case from test 149 to build machine: 150 151 from the gcov directory in sysfs: 152 - all .gcda files 153 - all links to .gcno files 154 155 These files can be copied to any location on the build machine. gcov 156 must then be called with the -o option pointing to that directory. 157 158 Example directory setup on the build machine:: 159 160 /tmp/linux: kernel source tree 161 /tmp/out: kernel build directory as specified by make O= 162 /tmp/coverage: location of the files copied from the test machine 163 164 [user@build] cd /tmp/out 165 [user@build] gcov -o /tmp/coverage/tmp/out/init main.c 166 167 168Note on compilers 169----------------- 170 171GCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with 172GCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang. 173 174.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 175.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html 176 177Build differences between GCC and Clang gcov are handled by Kconfig. It 178automatically selects the appropriate gcov format depending on the detected 179toolchain. 180 181 182Troubleshooting 183--------------- 184 185Problem 186 Compilation aborts during linker step. 187 188Cause 189 Profiling flags are specified for source files which are not 190 linked to the main kernel or which are linked by a custom 191 linker procedure. 192 193Solution 194 Exclude affected source files from profiling by specifying 195 ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the 196 corresponding Makefile. 197 198Problem 199 Files copied from sysfs appear empty or incomplete. 200 201Cause 202 Due to the way seq_file works, some tools such as cp or tar 203 may not correctly copy files from sysfs. 204 205Solution 206 Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links. 207 Alternatively use the mechanism shown in Appendix B. 208 209 210Appendix A: gather_on_build.sh 211------------------------------ 212 213Sample script to gather coverage meta files on the build machine 214(see 6a): 215 216.. code-block:: sh 217 218 #!/bin/bash 219 220 KSRC=$1 221 KOBJ=$2 222 DEST=$3 223 224 if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then 225 echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2 226 exit 1 227 fi 228 229 KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 230 KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 231 232 find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \ 233 -perm /u+r,g+r | tar cfz $DEST -P -T - 234 235 if [ $? -eq 0 ] ; then 236 echo "$DEST successfully created, copy to test system and unpack with:" 237 echo " tar xfz $DEST -P" 238 else 239 echo "Could not create file $DEST" 240 fi 241 242 243Appendix B: gather_on_test.sh 244----------------------------- 245 246Sample script to gather coverage data files on the test machine 247(see 6b): 248 249.. code-block:: sh 250 251 #!/bin/bash -e 252 253 DEST=$1 254 GCDA=/sys/kernel/debug/gcov 255 256 if [ -z "$DEST" ] ; then 257 echo "Usage: $0 <output.tar.gz>" >&2 258 exit 1 259 fi 260 261 TEMPDIR=$(mktemp -d) 262 echo Collecting data.. 263 find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; 264 find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; 265 find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; 266 tar czf $DEST -C $TEMPDIR sys 267 rm -rf $TEMPDIR 268 269 echo "$DEST successfully created, copy to build system and unpack with:" 270 echo " tar xfz $DEST" 271