18c2ecf20Sopenharmony_ciUsing gcov with the Linux kernel 28c2ecf20Sopenharmony_ci================================ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_cigcov profiling kernel support enables the use of GCC's coverage testing 58c2ecf20Sopenharmony_citool gcov_ with the Linux kernel. Coverage data of a running kernel 68c2ecf20Sopenharmony_ciis exported in gcov-compatible format via the "gcov" debugfs directory. 78c2ecf20Sopenharmony_ciTo get coverage data for a specific file, change to the kernel build 88c2ecf20Sopenharmony_cidirectory and use gcov with the ``-o`` option as follows (requires root):: 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci # cd /tmp/linux-out 118c2ecf20Sopenharmony_ci # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciThis will create source code files annotated with execution counts 148c2ecf20Sopenharmony_ciin the current directory. In addition, graphical gcov front-ends such 158c2ecf20Sopenharmony_cias lcov_ can be used to automate the process of collecting data 168c2ecf20Sopenharmony_cifor the entire kernel and provide coverage overviews in HTML format. 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ciPossible uses: 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci* debugging (has this line been reached at all?) 218c2ecf20Sopenharmony_ci* test improvement (how do I change my test to cover these lines?) 228c2ecf20Sopenharmony_ci* minimizing kernel configurations (do I need this option if the 238c2ecf20Sopenharmony_ci associated code is never run?) 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 268c2ecf20Sopenharmony_ci.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ciPreparation 308c2ecf20Sopenharmony_ci----------- 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciConfigure the kernel with:: 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci CONFIG_DEBUG_FS=y 358c2ecf20Sopenharmony_ci CONFIG_GCOV_KERNEL=y 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciand to get coverage data for the entire kernel:: 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci CONFIG_GCOV_PROFILE_ALL=y 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ciNote that kernels compiled with profiling flags will be significantly 428c2ecf20Sopenharmony_cilarger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported 438c2ecf20Sopenharmony_cion all architectures. 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciProfiling data will only become accessible once debugfs has been 468c2ecf20Sopenharmony_cimounted:: 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci mount -t debugfs none /sys/kernel/debug 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ciCustomization 528c2ecf20Sopenharmony_ci------------- 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ciTo enable profiling for specific files or directories, add a line 558c2ecf20Sopenharmony_cisimilar to the following to the respective kernel Makefile: 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci- For a single file (e.g. main.o):: 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci GCOV_PROFILE_main.o := y 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci- For all files in one directory:: 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci GCOV_PROFILE := y 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ciTo exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL 668c2ecf20Sopenharmony_ciis specified, use:: 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci GCOV_PROFILE_main.o := n 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciand:: 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci GCOV_PROFILE := n 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciOnly files which are linked to the main kernel image or are compiled as 758c2ecf20Sopenharmony_cikernel modules are supported by this mechanism. 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciFiles 798c2ecf20Sopenharmony_ci----- 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciThe gcov kernel support creates the following files in debugfs: 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci``/sys/kernel/debug/gcov`` 848c2ecf20Sopenharmony_ci Parent directory for all gcov-related files. 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci``/sys/kernel/debug/gcov/reset`` 878c2ecf20Sopenharmony_ci Global reset file: resets all coverage data to zero when 888c2ecf20Sopenharmony_ci written to. 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda`` 918c2ecf20Sopenharmony_ci The actual gcov data file as understood by the gcov 928c2ecf20Sopenharmony_ci tool. Resets file coverage data to zero when written to. 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno`` 958c2ecf20Sopenharmony_ci Symbolic link to a static data file required by the gcov 968c2ecf20Sopenharmony_ci tool. This file is generated by gcc when compiling with 978c2ecf20Sopenharmony_ci option ``-ftest-coverage``. 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciModules 1018c2ecf20Sopenharmony_ci------- 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciKernel modules may contain cleanup code which is only run during 1048c2ecf20Sopenharmony_cimodule unload time. The gcov mechanism provides a means to collect 1058c2ecf20Sopenharmony_cicoverage data for such code by keeping a copy of the data associated 1068c2ecf20Sopenharmony_ciwith the unloaded module. This data remains available through debugfs. 1078c2ecf20Sopenharmony_ciOnce the module is loaded again, the associated coverage counters are 1088c2ecf20Sopenharmony_ciinitialized with the data from its previous instantiation. 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ciThis behavior can be deactivated by specifying the gcov_persist kernel 1118c2ecf20Sopenharmony_ciparameter:: 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci gcov_persist=0 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciAt run-time, a user can also choose to discard data for an unloaded 1168c2ecf20Sopenharmony_cimodule by writing to its data file or the global reset file. 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciSeparated build and test machines 1208c2ecf20Sopenharmony_ci--------------------------------- 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ciThe gcov kernel profiling infrastructure is designed to work out-of-the 1238c2ecf20Sopenharmony_cibox for setups where kernels are built and run on the same machine. In 1248c2ecf20Sopenharmony_cicases where the kernel runs on a separate machine, special preparations 1258c2ecf20Sopenharmony_cimust be made, depending on where the gcov tool is used: 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cia) gcov is run on the TEST machine 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci The gcov tool version on the test machine must be compatible with the 1308c2ecf20Sopenharmony_ci gcc version used for kernel build. Also the following files need to be 1318c2ecf20Sopenharmony_ci copied from build to test machine: 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci from the source tree: 1348c2ecf20Sopenharmony_ci - all C source files + headers 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci from the build tree: 1378c2ecf20Sopenharmony_ci - all C source files + headers 1388c2ecf20Sopenharmony_ci - all .gcda and .gcno files 1398c2ecf20Sopenharmony_ci - all links to directories 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci It is important to note that these files need to be placed into the 1428c2ecf20Sopenharmony_ci exact same file system location on the test machine as on the build 1438c2ecf20Sopenharmony_ci machine. If any of the path components is symbolic link, the actual 1448c2ecf20Sopenharmony_ci directory needs to be used instead (due to make's CURDIR handling). 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cib) gcov is run on the BUILD machine 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci The following files need to be copied after each test case from test 1498c2ecf20Sopenharmony_ci to build machine: 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci from the gcov directory in sysfs: 1528c2ecf20Sopenharmony_ci - all .gcda files 1538c2ecf20Sopenharmony_ci - all links to .gcno files 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci These files can be copied to any location on the build machine. gcov 1568c2ecf20Sopenharmony_ci must then be called with the -o option pointing to that directory. 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci Example directory setup on the build machine:: 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /tmp/linux: kernel source tree 1618c2ecf20Sopenharmony_ci /tmp/out: kernel build directory as specified by make O= 1628c2ecf20Sopenharmony_ci /tmp/coverage: location of the files copied from the test machine 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci [user@build] cd /tmp/out 1658c2ecf20Sopenharmony_ci [user@build] gcov -o /tmp/coverage/tmp/out/init main.c 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciNote on compilers 1698c2ecf20Sopenharmony_ci----------------- 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciGCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with 1728c2ecf20Sopenharmony_ciGCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang. 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 1758c2ecf20Sopenharmony_ci.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ciBuild differences between GCC and Clang gcov are handled by Kconfig. It 1788c2ecf20Sopenharmony_ciautomatically selects the appropriate gcov format depending on the detected 1798c2ecf20Sopenharmony_citoolchain. 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciTroubleshooting 1838c2ecf20Sopenharmony_ci--------------- 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciProblem 1868c2ecf20Sopenharmony_ci Compilation aborts during linker step. 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ciCause 1898c2ecf20Sopenharmony_ci Profiling flags are specified for source files which are not 1908c2ecf20Sopenharmony_ci linked to the main kernel or which are linked by a custom 1918c2ecf20Sopenharmony_ci linker procedure. 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciSolution 1948c2ecf20Sopenharmony_ci Exclude affected source files from profiling by specifying 1958c2ecf20Sopenharmony_ci ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the 1968c2ecf20Sopenharmony_ci corresponding Makefile. 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ciProblem 1998c2ecf20Sopenharmony_ci Files copied from sysfs appear empty or incomplete. 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ciCause 2028c2ecf20Sopenharmony_ci Due to the way seq_file works, some tools such as cp or tar 2038c2ecf20Sopenharmony_ci may not correctly copy files from sysfs. 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ciSolution 2068c2ecf20Sopenharmony_ci Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links. 2078c2ecf20Sopenharmony_ci Alternatively use the mechanism shown in Appendix B. 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ciAppendix A: gather_on_build.sh 2118c2ecf20Sopenharmony_ci------------------------------ 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ciSample script to gather coverage meta files on the build machine 2148c2ecf20Sopenharmony_ci(see 6a): 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci.. code-block:: sh 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci #!/bin/bash 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci KSRC=$1 2218c2ecf20Sopenharmony_ci KOBJ=$2 2228c2ecf20Sopenharmony_ci DEST=$3 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then 2258c2ecf20Sopenharmony_ci echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2 2268c2ecf20Sopenharmony_ci exit 1 2278c2ecf20Sopenharmony_ci fi 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 2308c2ecf20Sopenharmony_ci KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \ 2338c2ecf20Sopenharmony_ci -perm /u+r,g+r | tar cfz $DEST -P -T - 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if [ $? -eq 0 ] ; then 2368c2ecf20Sopenharmony_ci echo "$DEST successfully created, copy to test system and unpack with:" 2378c2ecf20Sopenharmony_ci echo " tar xfz $DEST -P" 2388c2ecf20Sopenharmony_ci else 2398c2ecf20Sopenharmony_ci echo "Could not create file $DEST" 2408c2ecf20Sopenharmony_ci fi 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ciAppendix B: gather_on_test.sh 2448c2ecf20Sopenharmony_ci----------------------------- 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ciSample script to gather coverage data files on the test machine 2478c2ecf20Sopenharmony_ci(see 6b): 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci.. code-block:: sh 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci #!/bin/bash -e 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci DEST=$1 2548c2ecf20Sopenharmony_ci GCDA=/sys/kernel/debug/gcov 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if [ -z "$DEST" ] ; then 2578c2ecf20Sopenharmony_ci echo "Usage: $0 <output.tar.gz>" >&2 2588c2ecf20Sopenharmony_ci exit 1 2598c2ecf20Sopenharmony_ci fi 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci TEMPDIR=$(mktemp -d) 2628c2ecf20Sopenharmony_ci echo Collecting data.. 2638c2ecf20Sopenharmony_ci find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; 2648c2ecf20Sopenharmony_ci find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; 2658c2ecf20Sopenharmony_ci find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; 2668c2ecf20Sopenharmony_ci tar czf $DEST -C $TEMPDIR sys 2678c2ecf20Sopenharmony_ci rm -rf $TEMPDIR 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci echo "$DEST successfully created, copy to build system and unpack with:" 2708c2ecf20Sopenharmony_ci echo " tar xfz $DEST" 271