12584bab2SJonathan CorbetUsing gcov with the Linux kernel 22584bab2SJonathan Corbet================================ 32584bab2SJonathan Corbet 42584bab2SJonathan Corbetgcov profiling kernel support enables the use of GCC's coverage testing 52584bab2SJonathan Corbettool gcov_ with the Linux kernel. Coverage data of a running kernel 62584bab2SJonathan Corbetis exported in gcov-compatible format via the "gcov" debugfs directory. 72584bab2SJonathan CorbetTo get coverage data for a specific file, change to the kernel build 82584bab2SJonathan Corbetdirectory and use gcov with the ``-o`` option as follows (requires root):: 92584bab2SJonathan Corbet 102584bab2SJonathan Corbet # cd /tmp/linux-out 112584bab2SJonathan Corbet # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c 122584bab2SJonathan Corbet 132584bab2SJonathan CorbetThis will create source code files annotated with execution counts 142584bab2SJonathan Corbetin the current directory. In addition, graphical gcov front-ends such 152584bab2SJonathan Corbetas lcov_ can be used to automate the process of collecting data 162584bab2SJonathan Corbetfor the entire kernel and provide coverage overviews in HTML format. 172584bab2SJonathan Corbet 182584bab2SJonathan CorbetPossible uses: 192584bab2SJonathan Corbet 202584bab2SJonathan Corbet* debugging (has this line been reached at all?) 212584bab2SJonathan Corbet* test improvement (how do I change my test to cover these lines?) 222584bab2SJonathan Corbet* minimizing kernel configurations (do I need this option if the 232584bab2SJonathan Corbet associated code is never run?) 242584bab2SJonathan Corbet 254d8c1e05SAlexander A. Klimov.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 262584bab2SJonathan Corbet.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php 272584bab2SJonathan Corbet 282584bab2SJonathan Corbet 292584bab2SJonathan CorbetPreparation 302584bab2SJonathan Corbet----------- 312584bab2SJonathan Corbet 322584bab2SJonathan CorbetConfigure the kernel with:: 332584bab2SJonathan Corbet 342584bab2SJonathan Corbet CONFIG_DEBUG_FS=y 352584bab2SJonathan Corbet CONFIG_GCOV_KERNEL=y 362584bab2SJonathan Corbet 372584bab2SJonathan Corbetand to get coverage data for the entire kernel:: 382584bab2SJonathan Corbet 392584bab2SJonathan Corbet CONFIG_GCOV_PROFILE_ALL=y 402584bab2SJonathan Corbet 412584bab2SJonathan CorbetNote that kernels compiled with profiling flags will be significantly 422584bab2SJonathan Corbetlarger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported 432584bab2SJonathan Corbeton all architectures. 442584bab2SJonathan Corbet 452584bab2SJonathan CorbetProfiling data will only become accessible once debugfs has been 462584bab2SJonathan Corbetmounted:: 472584bab2SJonathan Corbet 482584bab2SJonathan Corbet mount -t debugfs none /sys/kernel/debug 492584bab2SJonathan Corbet 502584bab2SJonathan Corbet 512584bab2SJonathan CorbetCustomization 522584bab2SJonathan Corbet------------- 532584bab2SJonathan Corbet 542584bab2SJonathan CorbetTo enable profiling for specific files or directories, add a line 552584bab2SJonathan Corbetsimilar to the following to the respective kernel Makefile: 562584bab2SJonathan Corbet 572584bab2SJonathan Corbet- For a single file (e.g. main.o):: 582584bab2SJonathan Corbet 592584bab2SJonathan Corbet GCOV_PROFILE_main.o := y 602584bab2SJonathan Corbet 612584bab2SJonathan Corbet- For all files in one directory:: 622584bab2SJonathan Corbet 632584bab2SJonathan Corbet GCOV_PROFILE := y 642584bab2SJonathan Corbet 652584bab2SJonathan CorbetTo exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL 662584bab2SJonathan Corbetis specified, use:: 672584bab2SJonathan Corbet 682584bab2SJonathan Corbet GCOV_PROFILE_main.o := n 692584bab2SJonathan Corbet 702584bab2SJonathan Corbetand:: 712584bab2SJonathan Corbet 722584bab2SJonathan Corbet GCOV_PROFILE := n 732584bab2SJonathan Corbet 742584bab2SJonathan CorbetOnly files which are linked to the main kernel image or are compiled as 752584bab2SJonathan Corbetkernel modules are supported by this mechanism. 762584bab2SJonathan Corbet 772584bab2SJonathan Corbet 782584bab2SJonathan CorbetFiles 792584bab2SJonathan Corbet----- 802584bab2SJonathan Corbet 812584bab2SJonathan CorbetThe gcov kernel support creates the following files in debugfs: 822584bab2SJonathan Corbet 832584bab2SJonathan Corbet``/sys/kernel/debug/gcov`` 842584bab2SJonathan Corbet Parent directory for all gcov-related files. 852584bab2SJonathan Corbet 862584bab2SJonathan Corbet``/sys/kernel/debug/gcov/reset`` 872584bab2SJonathan Corbet Global reset file: resets all coverage data to zero when 882584bab2SJonathan Corbet written to. 892584bab2SJonathan Corbet 902584bab2SJonathan Corbet``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda`` 912584bab2SJonathan Corbet The actual gcov data file as understood by the gcov 922584bab2SJonathan Corbet tool. Resets file coverage data to zero when written to. 932584bab2SJonathan Corbet 942584bab2SJonathan Corbet``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno`` 952584bab2SJonathan Corbet Symbolic link to a static data file required by the gcov 962584bab2SJonathan Corbet tool. This file is generated by gcc when compiling with 972584bab2SJonathan Corbet option ``-ftest-coverage``. 982584bab2SJonathan Corbet 992584bab2SJonathan Corbet 1002584bab2SJonathan CorbetModules 1012584bab2SJonathan Corbet------- 1022584bab2SJonathan Corbet 1032584bab2SJonathan CorbetKernel modules may contain cleanup code which is only run during 1042584bab2SJonathan Corbetmodule unload time. The gcov mechanism provides a means to collect 1052584bab2SJonathan Corbetcoverage data for such code by keeping a copy of the data associated 1062584bab2SJonathan Corbetwith the unloaded module. This data remains available through debugfs. 1072584bab2SJonathan CorbetOnce the module is loaded again, the associated coverage counters are 1082584bab2SJonathan Corbetinitialized with the data from its previous instantiation. 1092584bab2SJonathan Corbet 1102584bab2SJonathan CorbetThis behavior can be deactivated by specifying the gcov_persist kernel 1112584bab2SJonathan Corbetparameter:: 1122584bab2SJonathan Corbet 1132584bab2SJonathan Corbet gcov_persist=0 1142584bab2SJonathan Corbet 1152584bab2SJonathan CorbetAt run-time, a user can also choose to discard data for an unloaded 1162584bab2SJonathan Corbetmodule by writing to its data file or the global reset file. 1172584bab2SJonathan Corbet 1182584bab2SJonathan Corbet 1192584bab2SJonathan CorbetSeparated build and test machines 1202584bab2SJonathan Corbet--------------------------------- 1212584bab2SJonathan Corbet 1222584bab2SJonathan CorbetThe gcov kernel profiling infrastructure is designed to work out-of-the 1232584bab2SJonathan Corbetbox for setups where kernels are built and run on the same machine. In 1242584bab2SJonathan Corbetcases where the kernel runs on a separate machine, special preparations 1252584bab2SJonathan Corbetmust be made, depending on where the gcov tool is used: 1262584bab2SJonathan Corbet 127*1446e322SWu XiangCheng.. _gcov-test: 128*1446e322SWu XiangCheng 1292584bab2SJonathan Corbeta) gcov is run on the TEST machine 1302584bab2SJonathan Corbet 1312584bab2SJonathan Corbet The gcov tool version on the test machine must be compatible with the 1322584bab2SJonathan Corbet gcc version used for kernel build. Also the following files need to be 1332584bab2SJonathan Corbet copied from build to test machine: 1342584bab2SJonathan Corbet 1352584bab2SJonathan Corbet from the source tree: 1362584bab2SJonathan Corbet - all C source files + headers 1372584bab2SJonathan Corbet 1382584bab2SJonathan Corbet from the build tree: 1392584bab2SJonathan Corbet - all C source files + headers 1402584bab2SJonathan Corbet - all .gcda and .gcno files 1412584bab2SJonathan Corbet - all links to directories 1422584bab2SJonathan Corbet 1432584bab2SJonathan Corbet It is important to note that these files need to be placed into the 1442584bab2SJonathan Corbet exact same file system location on the test machine as on the build 1452584bab2SJonathan Corbet machine. If any of the path components is symbolic link, the actual 1462584bab2SJonathan Corbet directory needs to be used instead (due to make's CURDIR handling). 1472584bab2SJonathan Corbet 148*1446e322SWu XiangCheng.. _gcov-build: 149*1446e322SWu XiangCheng 1502584bab2SJonathan Corbetb) gcov is run on the BUILD machine 1512584bab2SJonathan Corbet 1522584bab2SJonathan Corbet The following files need to be copied after each test case from test 1532584bab2SJonathan Corbet to build machine: 1542584bab2SJonathan Corbet 1552584bab2SJonathan Corbet from the gcov directory in sysfs: 1562584bab2SJonathan Corbet - all .gcda files 1572584bab2SJonathan Corbet - all links to .gcno files 1582584bab2SJonathan Corbet 1592584bab2SJonathan Corbet These files can be copied to any location on the build machine. gcov 1602584bab2SJonathan Corbet must then be called with the -o option pointing to that directory. 1612584bab2SJonathan Corbet 1622584bab2SJonathan Corbet Example directory setup on the build machine:: 1632584bab2SJonathan Corbet 1642584bab2SJonathan Corbet /tmp/linux: kernel source tree 1652584bab2SJonathan Corbet /tmp/out: kernel build directory as specified by make O= 1662584bab2SJonathan Corbet /tmp/coverage: location of the files copied from the test machine 1672584bab2SJonathan Corbet 1682584bab2SJonathan Corbet [user@build] cd /tmp/out 1692584bab2SJonathan Corbet [user@build] gcov -o /tmp/coverage/tmp/out/init main.c 1702584bab2SJonathan Corbet 1712584bab2SJonathan Corbet 172aa069a23STri VoNote on compilers 173aa069a23STri Vo----------------- 174aa069a23STri Vo 175aa069a23STri VoGCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with 176aa069a23STri VoGCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang. 177aa069a23STri Vo 1784d8c1e05SAlexander A. Klimov.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 179aa069a23STri Vo.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html 180aa069a23STri Vo 181aa069a23STri VoBuild differences between GCC and Clang gcov are handled by Kconfig. It 182aa069a23STri Voautomatically selects the appropriate gcov format depending on the detected 183aa069a23STri Votoolchain. 184aa069a23STri Vo 185aa069a23STri Vo 1862584bab2SJonathan CorbetTroubleshooting 1872584bab2SJonathan Corbet--------------- 1882584bab2SJonathan Corbet 1892584bab2SJonathan CorbetProblem 1902584bab2SJonathan Corbet Compilation aborts during linker step. 1912584bab2SJonathan Corbet 1922584bab2SJonathan CorbetCause 1932584bab2SJonathan Corbet Profiling flags are specified for source files which are not 1942584bab2SJonathan Corbet linked to the main kernel or which are linked by a custom 1952584bab2SJonathan Corbet linker procedure. 1962584bab2SJonathan Corbet 1972584bab2SJonathan CorbetSolution 1982584bab2SJonathan Corbet Exclude affected source files from profiling by specifying 1992584bab2SJonathan Corbet ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the 2002584bab2SJonathan Corbet corresponding Makefile. 2012584bab2SJonathan Corbet 2022584bab2SJonathan CorbetProblem 2032584bab2SJonathan Corbet Files copied from sysfs appear empty or incomplete. 2042584bab2SJonathan Corbet 2052584bab2SJonathan CorbetCause 2062584bab2SJonathan Corbet Due to the way seq_file works, some tools such as cp or tar 2072584bab2SJonathan Corbet may not correctly copy files from sysfs. 2082584bab2SJonathan Corbet 2092584bab2SJonathan CorbetSolution 2100a464ea4SJonathan Neuschäfer Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links. 2112584bab2SJonathan Corbet Alternatively use the mechanism shown in Appendix B. 2122584bab2SJonathan Corbet 2132584bab2SJonathan Corbet 2142584bab2SJonathan CorbetAppendix A: gather_on_build.sh 2152584bab2SJonathan Corbet------------------------------ 2162584bab2SJonathan Corbet 2172584bab2SJonathan CorbetSample script to gather coverage meta files on the build machine 218*1446e322SWu XiangCheng(see :ref:`Separated build and test machines a. <gcov-test>`): 21957131dd3SJani Nikula 22057131dd3SJani Nikula.. code-block:: sh 2212584bab2SJonathan Corbet 2222584bab2SJonathan Corbet #!/bin/bash 2232584bab2SJonathan Corbet 2242584bab2SJonathan Corbet KSRC=$1 2252584bab2SJonathan Corbet KOBJ=$2 2262584bab2SJonathan Corbet DEST=$3 2272584bab2SJonathan Corbet 2282584bab2SJonathan Corbet if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then 2292584bab2SJonathan Corbet echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2 2302584bab2SJonathan Corbet exit 1 2312584bab2SJonathan Corbet fi 2322584bab2SJonathan Corbet 2332584bab2SJonathan Corbet KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 2342584bab2SJonathan Corbet KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 2352584bab2SJonathan Corbet 2362584bab2SJonathan Corbet find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \ 2372584bab2SJonathan Corbet -perm /u+r,g+r | tar cfz $DEST -P -T - 2382584bab2SJonathan Corbet 2392584bab2SJonathan Corbet if [ $? -eq 0 ] ; then 2402584bab2SJonathan Corbet echo "$DEST successfully created, copy to test system and unpack with:" 2412584bab2SJonathan Corbet echo " tar xfz $DEST -P" 2422584bab2SJonathan Corbet else 2432584bab2SJonathan Corbet echo "Could not create file $DEST" 2442584bab2SJonathan Corbet fi 2452584bab2SJonathan Corbet 2462584bab2SJonathan Corbet 2472584bab2SJonathan CorbetAppendix B: gather_on_test.sh 2482584bab2SJonathan Corbet----------------------------- 2492584bab2SJonathan Corbet 2502584bab2SJonathan CorbetSample script to gather coverage data files on the test machine 251*1446e322SWu XiangCheng(see :ref:`Separated build and test machines b. <gcov-build>`): 25257131dd3SJani Nikula 25357131dd3SJani Nikula.. code-block:: sh 2542584bab2SJonathan Corbet 2552584bab2SJonathan Corbet #!/bin/bash -e 2562584bab2SJonathan Corbet 2572584bab2SJonathan Corbet DEST=$1 2582584bab2SJonathan Corbet GCDA=/sys/kernel/debug/gcov 2592584bab2SJonathan Corbet 2602584bab2SJonathan Corbet if [ -z "$DEST" ] ; then 2612584bab2SJonathan Corbet echo "Usage: $0 <output.tar.gz>" >&2 2622584bab2SJonathan Corbet exit 1 2632584bab2SJonathan Corbet fi 2642584bab2SJonathan Corbet 2652584bab2SJonathan Corbet TEMPDIR=$(mktemp -d) 2662584bab2SJonathan Corbet echo Collecting data.. 2672584bab2SJonathan Corbet find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; 2682584bab2SJonathan Corbet find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; 2692584bab2SJonathan Corbet find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; 2702584bab2SJonathan Corbet tar czf $DEST -C $TEMPDIR sys 2712584bab2SJonathan Corbet rm -rf $TEMPDIR 2722584bab2SJonathan Corbet 2732584bab2SJonathan Corbet echo "$DEST successfully created, copy to build system and unpack with:" 2742584bab2SJonathan Corbet echo " tar xfz $DEST" 275