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 78*3ade6ce1SVegard NossumModule specific configs 79*3ade6ce1SVegard Nossum----------------------- 80*3ade6ce1SVegard Nossum 81*3ade6ce1SVegard NossumGcov kernel configs for specific modules are described below: 82*3ade6ce1SVegard Nossum 83*3ade6ce1SVegard NossumCONFIG_GCOV_PROFILE_RDS: 84*3ade6ce1SVegard Nossum Enables GCOV profiling on RDS for checking which functions or 85*3ade6ce1SVegard Nossum lines are executed. This config is used by the rds selftest to 86*3ade6ce1SVegard Nossum generate coverage reports. If left unset the report is omitted. 87*3ade6ce1SVegard Nossum 88*3ade6ce1SVegard Nossum 892584bab2SJonathan CorbetFiles 902584bab2SJonathan Corbet----- 912584bab2SJonathan Corbet 922584bab2SJonathan CorbetThe gcov kernel support creates the following files in debugfs: 932584bab2SJonathan Corbet 942584bab2SJonathan Corbet``/sys/kernel/debug/gcov`` 952584bab2SJonathan Corbet Parent directory for all gcov-related files. 962584bab2SJonathan Corbet 972584bab2SJonathan Corbet``/sys/kernel/debug/gcov/reset`` 982584bab2SJonathan Corbet Global reset file: resets all coverage data to zero when 992584bab2SJonathan Corbet written to. 1002584bab2SJonathan Corbet 1012584bab2SJonathan Corbet``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda`` 1022584bab2SJonathan Corbet The actual gcov data file as understood by the gcov 1032584bab2SJonathan Corbet tool. Resets file coverage data to zero when written to. 1042584bab2SJonathan Corbet 1052584bab2SJonathan Corbet``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno`` 1062584bab2SJonathan Corbet Symbolic link to a static data file required by the gcov 1072584bab2SJonathan Corbet tool. This file is generated by gcc when compiling with 1082584bab2SJonathan Corbet option ``-ftest-coverage``. 1092584bab2SJonathan Corbet 1102584bab2SJonathan Corbet 1112584bab2SJonathan CorbetModules 1122584bab2SJonathan Corbet------- 1132584bab2SJonathan Corbet 1142584bab2SJonathan CorbetKernel modules may contain cleanup code which is only run during 1152584bab2SJonathan Corbetmodule unload time. The gcov mechanism provides a means to collect 1162584bab2SJonathan Corbetcoverage data for such code by keeping a copy of the data associated 1172584bab2SJonathan Corbetwith the unloaded module. This data remains available through debugfs. 1182584bab2SJonathan CorbetOnce the module is loaded again, the associated coverage counters are 1192584bab2SJonathan Corbetinitialized with the data from its previous instantiation. 1202584bab2SJonathan Corbet 1212584bab2SJonathan CorbetThis behavior can be deactivated by specifying the gcov_persist kernel 1222584bab2SJonathan Corbetparameter:: 1232584bab2SJonathan Corbet 1242584bab2SJonathan Corbet gcov_persist=0 1252584bab2SJonathan Corbet 1262584bab2SJonathan CorbetAt run-time, a user can also choose to discard data for an unloaded 1272584bab2SJonathan Corbetmodule by writing to its data file or the global reset file. 1282584bab2SJonathan Corbet 1292584bab2SJonathan Corbet 1302584bab2SJonathan CorbetSeparated build and test machines 1312584bab2SJonathan Corbet--------------------------------- 1322584bab2SJonathan Corbet 1332584bab2SJonathan CorbetThe gcov kernel profiling infrastructure is designed to work out-of-the 1342584bab2SJonathan Corbetbox for setups where kernels are built and run on the same machine. In 1352584bab2SJonathan Corbetcases where the kernel runs on a separate machine, special preparations 1362584bab2SJonathan Corbetmust be made, depending on where the gcov tool is used: 1372584bab2SJonathan Corbet 1381446e322SWu XiangCheng.. _gcov-test: 1391446e322SWu XiangCheng 1402584bab2SJonathan Corbeta) gcov is run on the TEST machine 1412584bab2SJonathan Corbet 1422584bab2SJonathan Corbet The gcov tool version on the test machine must be compatible with the 1432584bab2SJonathan Corbet gcc version used for kernel build. Also the following files need to be 1442584bab2SJonathan Corbet copied from build to test machine: 1452584bab2SJonathan Corbet 1462584bab2SJonathan Corbet from the source tree: 1472584bab2SJonathan Corbet - all C source files + headers 1482584bab2SJonathan Corbet 1492584bab2SJonathan Corbet from the build tree: 1502584bab2SJonathan Corbet - all C source files + headers 1512584bab2SJonathan Corbet - all .gcda and .gcno files 1522584bab2SJonathan Corbet - all links to directories 1532584bab2SJonathan Corbet 1542584bab2SJonathan Corbet It is important to note that these files need to be placed into the 1552584bab2SJonathan Corbet exact same file system location on the test machine as on the build 1562584bab2SJonathan Corbet machine. If any of the path components is symbolic link, the actual 1572584bab2SJonathan Corbet directory needs to be used instead (due to make's CURDIR handling). 1582584bab2SJonathan Corbet 1591446e322SWu XiangCheng.. _gcov-build: 1601446e322SWu XiangCheng 1612584bab2SJonathan Corbetb) gcov is run on the BUILD machine 1622584bab2SJonathan Corbet 1632584bab2SJonathan Corbet The following files need to be copied after each test case from test 1642584bab2SJonathan Corbet to build machine: 1652584bab2SJonathan Corbet 1662584bab2SJonathan Corbet from the gcov directory in sysfs: 1672584bab2SJonathan Corbet - all .gcda files 1682584bab2SJonathan Corbet - all links to .gcno files 1692584bab2SJonathan Corbet 1702584bab2SJonathan Corbet These files can be copied to any location on the build machine. gcov 1712584bab2SJonathan Corbet must then be called with the -o option pointing to that directory. 1722584bab2SJonathan Corbet 1732584bab2SJonathan Corbet Example directory setup on the build machine:: 1742584bab2SJonathan Corbet 1752584bab2SJonathan Corbet /tmp/linux: kernel source tree 1762584bab2SJonathan Corbet /tmp/out: kernel build directory as specified by make O= 1772584bab2SJonathan Corbet /tmp/coverage: location of the files copied from the test machine 1782584bab2SJonathan Corbet 1792584bab2SJonathan Corbet [user@build] cd /tmp/out 1802584bab2SJonathan Corbet [user@build] gcov -o /tmp/coverage/tmp/out/init main.c 1812584bab2SJonathan Corbet 1822584bab2SJonathan Corbet 183aa069a23STri VoNote on compilers 184aa069a23STri Vo----------------- 185aa069a23STri Vo 186aa069a23STri VoGCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with 187aa069a23STri VoGCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang. 188aa069a23STri Vo 1894d8c1e05SAlexander A. Klimov.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 190aa069a23STri Vo.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html 191aa069a23STri Vo 192aa069a23STri VoBuild differences between GCC and Clang gcov are handled by Kconfig. It 193aa069a23STri Voautomatically selects the appropriate gcov format depending on the detected 194aa069a23STri Votoolchain. 195aa069a23STri Vo 196aa069a23STri Vo 1972584bab2SJonathan CorbetTroubleshooting 1982584bab2SJonathan Corbet--------------- 1992584bab2SJonathan Corbet 2002584bab2SJonathan CorbetProblem 2012584bab2SJonathan Corbet Compilation aborts during linker step. 2022584bab2SJonathan Corbet 2032584bab2SJonathan CorbetCause 2042584bab2SJonathan Corbet Profiling flags are specified for source files which are not 2052584bab2SJonathan Corbet linked to the main kernel or which are linked by a custom 2062584bab2SJonathan Corbet linker procedure. 2072584bab2SJonathan Corbet 2082584bab2SJonathan CorbetSolution 2092584bab2SJonathan Corbet Exclude affected source files from profiling by specifying 2102584bab2SJonathan Corbet ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the 2112584bab2SJonathan Corbet corresponding Makefile. 2122584bab2SJonathan Corbet 2132584bab2SJonathan CorbetProblem 2142584bab2SJonathan Corbet Files copied from sysfs appear empty or incomplete. 2152584bab2SJonathan Corbet 2162584bab2SJonathan CorbetCause 2172584bab2SJonathan Corbet Due to the way seq_file works, some tools such as cp or tar 2182584bab2SJonathan Corbet may not correctly copy files from sysfs. 2192584bab2SJonathan Corbet 2202584bab2SJonathan CorbetSolution 2210a464ea4SJonathan Neuschäfer Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links. 2222584bab2SJonathan Corbet Alternatively use the mechanism shown in Appendix B. 2232584bab2SJonathan Corbet 2242584bab2SJonathan Corbet 2252584bab2SJonathan CorbetAppendix A: gather_on_build.sh 2262584bab2SJonathan Corbet------------------------------ 2272584bab2SJonathan Corbet 2282584bab2SJonathan CorbetSample script to gather coverage meta files on the build machine 2291446e322SWu XiangCheng(see :ref:`Separated build and test machines a. <gcov-test>`): 23057131dd3SJani Nikula 23157131dd3SJani Nikula.. code-block:: sh 2322584bab2SJonathan Corbet 2332584bab2SJonathan Corbet #!/bin/bash 2342584bab2SJonathan Corbet 2352584bab2SJonathan Corbet KSRC=$1 2362584bab2SJonathan Corbet KOBJ=$2 2372584bab2SJonathan Corbet DEST=$3 2382584bab2SJonathan Corbet 2392584bab2SJonathan Corbet if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then 2402584bab2SJonathan Corbet echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2 2412584bab2SJonathan Corbet exit 1 2422584bab2SJonathan Corbet fi 2432584bab2SJonathan Corbet 2442584bab2SJonathan Corbet KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 2452584bab2SJonathan Corbet KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 2462584bab2SJonathan Corbet 2472584bab2SJonathan Corbet find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \ 2482584bab2SJonathan Corbet -perm /u+r,g+r | tar cfz $DEST -P -T - 2492584bab2SJonathan Corbet 2502584bab2SJonathan Corbet if [ $? -eq 0 ] ; then 2512584bab2SJonathan Corbet echo "$DEST successfully created, copy to test system and unpack with:" 2522584bab2SJonathan Corbet echo " tar xfz $DEST -P" 2532584bab2SJonathan Corbet else 2542584bab2SJonathan Corbet echo "Could not create file $DEST" 2552584bab2SJonathan Corbet fi 2562584bab2SJonathan Corbet 2572584bab2SJonathan Corbet 2582584bab2SJonathan CorbetAppendix B: gather_on_test.sh 2592584bab2SJonathan Corbet----------------------------- 2602584bab2SJonathan Corbet 2612584bab2SJonathan CorbetSample script to gather coverage data files on the test machine 2621446e322SWu XiangCheng(see :ref:`Separated build and test machines b. <gcov-build>`): 26357131dd3SJani Nikula 26457131dd3SJani Nikula.. code-block:: sh 2652584bab2SJonathan Corbet 2662584bab2SJonathan Corbet #!/bin/bash -e 2672584bab2SJonathan Corbet 2682584bab2SJonathan Corbet DEST=$1 2692584bab2SJonathan Corbet GCDA=/sys/kernel/debug/gcov 2702584bab2SJonathan Corbet 2712584bab2SJonathan Corbet if [ -z "$DEST" ] ; then 2722584bab2SJonathan Corbet echo "Usage: $0 <output.tar.gz>" >&2 2732584bab2SJonathan Corbet exit 1 2742584bab2SJonathan Corbet fi 2752584bab2SJonathan Corbet 2762584bab2SJonathan Corbet TEMPDIR=$(mktemp -d) 2772584bab2SJonathan Corbet echo Collecting data.. 2782584bab2SJonathan Corbet find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; 2792584bab2SJonathan Corbet find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; 2802584bab2SJonathan Corbet find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; 2812584bab2SJonathan Corbet tar czf $DEST -C $TEMPDIR sys 2822584bab2SJonathan Corbet rm -rf $TEMPDIR 2832584bab2SJonathan Corbet 2842584bab2SJonathan Corbet echo "$DEST successfully created, copy to build system and unpack with:" 2852584bab2SJonathan Corbet echo " tar xfz $DEST" 286