162306a36Sopenharmony_ciUsing gcov with the Linux kernel 262306a36Sopenharmony_ci================================ 362306a36Sopenharmony_ci 462306a36Sopenharmony_cigcov profiling kernel support enables the use of GCC's coverage testing 562306a36Sopenharmony_citool gcov_ with the Linux kernel. Coverage data of a running kernel 662306a36Sopenharmony_ciis exported in gcov-compatible format via the "gcov" debugfs directory. 762306a36Sopenharmony_ciTo get coverage data for a specific file, change to the kernel build 862306a36Sopenharmony_cidirectory and use gcov with the ``-o`` option as follows (requires root):: 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci # cd /tmp/linux-out 1162306a36Sopenharmony_ci # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciThis will create source code files annotated with execution counts 1462306a36Sopenharmony_ciin the current directory. In addition, graphical gcov front-ends such 1562306a36Sopenharmony_cias lcov_ can be used to automate the process of collecting data 1662306a36Sopenharmony_cifor the entire kernel and provide coverage overviews in HTML format. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciPossible uses: 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci* debugging (has this line been reached at all?) 2162306a36Sopenharmony_ci* test improvement (how do I change my test to cover these lines?) 2262306a36Sopenharmony_ci* minimizing kernel configurations (do I need this option if the 2362306a36Sopenharmony_ci associated code is never run?) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 2662306a36Sopenharmony_ci.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciPreparation 3062306a36Sopenharmony_ci----------- 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciConfigure the kernel with:: 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci CONFIG_DEBUG_FS=y 3562306a36Sopenharmony_ci CONFIG_GCOV_KERNEL=y 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciand to get coverage data for the entire kernel:: 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci CONFIG_GCOV_PROFILE_ALL=y 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciNote that kernels compiled with profiling flags will be significantly 4262306a36Sopenharmony_cilarger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported 4362306a36Sopenharmony_cion all architectures. 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciProfiling data will only become accessible once debugfs has been 4662306a36Sopenharmony_cimounted:: 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci mount -t debugfs none /sys/kernel/debug 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciCustomization 5262306a36Sopenharmony_ci------------- 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ciTo enable profiling for specific files or directories, add a line 5562306a36Sopenharmony_cisimilar to the following to the respective kernel Makefile: 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci- For a single file (e.g. main.o):: 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci GCOV_PROFILE_main.o := y 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci- For all files in one directory:: 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci GCOV_PROFILE := y 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciTo exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL 6662306a36Sopenharmony_ciis specified, use:: 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci GCOV_PROFILE_main.o := n 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciand:: 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci GCOV_PROFILE := n 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciOnly files which are linked to the main kernel image or are compiled as 7562306a36Sopenharmony_cikernel modules are supported by this mechanism. 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciFiles 7962306a36Sopenharmony_ci----- 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciThe gcov kernel support creates the following files in debugfs: 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci``/sys/kernel/debug/gcov`` 8462306a36Sopenharmony_ci Parent directory for all gcov-related files. 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci``/sys/kernel/debug/gcov/reset`` 8762306a36Sopenharmony_ci Global reset file: resets all coverage data to zero when 8862306a36Sopenharmony_ci written to. 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda`` 9162306a36Sopenharmony_ci The actual gcov data file as understood by the gcov 9262306a36Sopenharmony_ci tool. Resets file coverage data to zero when written to. 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno`` 9562306a36Sopenharmony_ci Symbolic link to a static data file required by the gcov 9662306a36Sopenharmony_ci tool. This file is generated by gcc when compiling with 9762306a36Sopenharmony_ci option ``-ftest-coverage``. 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciModules 10162306a36Sopenharmony_ci------- 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciKernel modules may contain cleanup code which is only run during 10462306a36Sopenharmony_cimodule unload time. The gcov mechanism provides a means to collect 10562306a36Sopenharmony_cicoverage data for such code by keeping a copy of the data associated 10662306a36Sopenharmony_ciwith the unloaded module. This data remains available through debugfs. 10762306a36Sopenharmony_ciOnce the module is loaded again, the associated coverage counters are 10862306a36Sopenharmony_ciinitialized with the data from its previous instantiation. 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciThis behavior can be deactivated by specifying the gcov_persist kernel 11162306a36Sopenharmony_ciparameter:: 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci gcov_persist=0 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciAt run-time, a user can also choose to discard data for an unloaded 11662306a36Sopenharmony_cimodule by writing to its data file or the global reset file. 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciSeparated build and test machines 12062306a36Sopenharmony_ci--------------------------------- 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciThe gcov kernel profiling infrastructure is designed to work out-of-the 12362306a36Sopenharmony_cibox for setups where kernels are built and run on the same machine. In 12462306a36Sopenharmony_cicases where the kernel runs on a separate machine, special preparations 12562306a36Sopenharmony_cimust be made, depending on where the gcov tool is used: 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci.. _gcov-test: 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cia) gcov is run on the TEST machine 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci The gcov tool version on the test machine must be compatible with the 13262306a36Sopenharmony_ci gcc version used for kernel build. Also the following files need to be 13362306a36Sopenharmony_ci copied from build to test machine: 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci from the source tree: 13662306a36Sopenharmony_ci - all C source files + headers 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci from the build tree: 13962306a36Sopenharmony_ci - all C source files + headers 14062306a36Sopenharmony_ci - all .gcda and .gcno files 14162306a36Sopenharmony_ci - all links to directories 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci It is important to note that these files need to be placed into the 14462306a36Sopenharmony_ci exact same file system location on the test machine as on the build 14562306a36Sopenharmony_ci machine. If any of the path components is symbolic link, the actual 14662306a36Sopenharmony_ci directory needs to be used instead (due to make's CURDIR handling). 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci.. _gcov-build: 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cib) gcov is run on the BUILD machine 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci The following files need to be copied after each test case from test 15362306a36Sopenharmony_ci to build machine: 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci from the gcov directory in sysfs: 15662306a36Sopenharmony_ci - all .gcda files 15762306a36Sopenharmony_ci - all links to .gcno files 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci These files can be copied to any location on the build machine. gcov 16062306a36Sopenharmony_ci must then be called with the -o option pointing to that directory. 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci Example directory setup on the build machine:: 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /tmp/linux: kernel source tree 16562306a36Sopenharmony_ci /tmp/out: kernel build directory as specified by make O= 16662306a36Sopenharmony_ci /tmp/coverage: location of the files copied from the test machine 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci [user@build] cd /tmp/out 16962306a36Sopenharmony_ci [user@build] gcov -o /tmp/coverage/tmp/out/init main.c 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciNote on compilers 17362306a36Sopenharmony_ci----------------- 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ciGCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with 17662306a36Sopenharmony_ciGCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang. 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 17962306a36Sopenharmony_ci.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciBuild differences between GCC and Clang gcov are handled by Kconfig. It 18262306a36Sopenharmony_ciautomatically selects the appropriate gcov format depending on the detected 18362306a36Sopenharmony_citoolchain. 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ciTroubleshooting 18762306a36Sopenharmony_ci--------------- 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciProblem 19062306a36Sopenharmony_ci Compilation aborts during linker step. 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciCause 19362306a36Sopenharmony_ci Profiling flags are specified for source files which are not 19462306a36Sopenharmony_ci linked to the main kernel or which are linked by a custom 19562306a36Sopenharmony_ci linker procedure. 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciSolution 19862306a36Sopenharmony_ci Exclude affected source files from profiling by specifying 19962306a36Sopenharmony_ci ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the 20062306a36Sopenharmony_ci corresponding Makefile. 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciProblem 20362306a36Sopenharmony_ci Files copied from sysfs appear empty or incomplete. 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciCause 20662306a36Sopenharmony_ci Due to the way seq_file works, some tools such as cp or tar 20762306a36Sopenharmony_ci may not correctly copy files from sysfs. 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciSolution 21062306a36Sopenharmony_ci Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links. 21162306a36Sopenharmony_ci Alternatively use the mechanism shown in Appendix B. 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciAppendix A: gather_on_build.sh 21562306a36Sopenharmony_ci------------------------------ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ciSample script to gather coverage meta files on the build machine 21862306a36Sopenharmony_ci(see :ref:`Separated build and test machines a. <gcov-test>`): 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci.. code-block:: sh 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci #!/bin/bash 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci KSRC=$1 22562306a36Sopenharmony_ci KOBJ=$2 22662306a36Sopenharmony_ci DEST=$3 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then 22962306a36Sopenharmony_ci echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2 23062306a36Sopenharmony_ci exit 1 23162306a36Sopenharmony_ci fi 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 23462306a36Sopenharmony_ci KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -) 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \ 23762306a36Sopenharmony_ci -perm /u+r,g+r | tar cfz $DEST -P -T - 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if [ $? -eq 0 ] ; then 24062306a36Sopenharmony_ci echo "$DEST successfully created, copy to test system and unpack with:" 24162306a36Sopenharmony_ci echo " tar xfz $DEST -P" 24262306a36Sopenharmony_ci else 24362306a36Sopenharmony_ci echo "Could not create file $DEST" 24462306a36Sopenharmony_ci fi 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciAppendix B: gather_on_test.sh 24862306a36Sopenharmony_ci----------------------------- 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciSample script to gather coverage data files on the test machine 25162306a36Sopenharmony_ci(see :ref:`Separated build and test machines b. <gcov-build>`): 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci.. code-block:: sh 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci #!/bin/bash -e 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci DEST=$1 25862306a36Sopenharmony_ci GCDA=/sys/kernel/debug/gcov 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if [ -z "$DEST" ] ; then 26162306a36Sopenharmony_ci echo "Usage: $0 <output.tar.gz>" >&2 26262306a36Sopenharmony_ci exit 1 26362306a36Sopenharmony_ci fi 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci TEMPDIR=$(mktemp -d) 26662306a36Sopenharmony_ci echo Collecting data.. 26762306a36Sopenharmony_ci find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; 26862306a36Sopenharmony_ci find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; 26962306a36Sopenharmony_ci find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; 27062306a36Sopenharmony_ci tar czf $DEST -C $TEMPDIR sys 27162306a36Sopenharmony_ci rm -rf $TEMPDIR 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci echo "$DEST successfully created, copy to build system and unpack with:" 27462306a36Sopenharmony_ci echo " tar xfz $DEST" 275