xref: /OK3568_Linux_fs/kernel/Documentation/dev-tools/gcov.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunUsing gcov with the Linux kernel
2*4882a593Smuzhiyun================================
3*4882a593Smuzhiyun
4*4882a593Smuzhiyungcov profiling kernel support enables the use of GCC's coverage testing
5*4882a593Smuzhiyuntool gcov_ with the Linux kernel. Coverage data of a running kernel
6*4882a593Smuzhiyunis exported in gcov-compatible format via the "gcov" debugfs directory.
7*4882a593SmuzhiyunTo get coverage data for a specific file, change to the kernel build
8*4882a593Smuzhiyundirectory and use gcov with the ``-o`` option as follows (requires root)::
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun    # cd /tmp/linux-out
11*4882a593Smuzhiyun    # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
12*4882a593Smuzhiyun
13*4882a593SmuzhiyunThis will create source code files annotated with execution counts
14*4882a593Smuzhiyunin the current directory. In addition, graphical gcov front-ends such
15*4882a593Smuzhiyunas lcov_ can be used to automate the process of collecting data
16*4882a593Smuzhiyunfor the entire kernel and provide coverage overviews in HTML format.
17*4882a593Smuzhiyun
18*4882a593SmuzhiyunPossible uses:
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun* debugging (has this line been reached at all?)
21*4882a593Smuzhiyun* test improvement (how do I change my test to cover these lines?)
22*4882a593Smuzhiyun* minimizing kernel configurations (do I need this option if the
23*4882a593Smuzhiyun  associated code is never run?)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
26*4882a593Smuzhiyun.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun
29*4882a593SmuzhiyunPreparation
30*4882a593Smuzhiyun-----------
31*4882a593Smuzhiyun
32*4882a593SmuzhiyunConfigure the kernel with::
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun        CONFIG_DEBUG_FS=y
35*4882a593Smuzhiyun        CONFIG_GCOV_KERNEL=y
36*4882a593Smuzhiyun
37*4882a593Smuzhiyunand to get coverage data for the entire kernel::
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun        CONFIG_GCOV_PROFILE_ALL=y
40*4882a593Smuzhiyun
41*4882a593SmuzhiyunNote that kernels compiled with profiling flags will be significantly
42*4882a593Smuzhiyunlarger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported
43*4882a593Smuzhiyunon all architectures.
44*4882a593Smuzhiyun
45*4882a593SmuzhiyunProfiling data will only become accessible once debugfs has been
46*4882a593Smuzhiyunmounted::
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun        mount -t debugfs none /sys/kernel/debug
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun
51*4882a593SmuzhiyunCustomization
52*4882a593Smuzhiyun-------------
53*4882a593Smuzhiyun
54*4882a593SmuzhiyunTo enable profiling for specific files or directories, add a line
55*4882a593Smuzhiyunsimilar to the following to the respective kernel Makefile:
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun- For a single file (e.g. main.o)::
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun	GCOV_PROFILE_main.o := y
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun- For all files in one directory::
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun	GCOV_PROFILE := y
64*4882a593Smuzhiyun
65*4882a593SmuzhiyunTo exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL
66*4882a593Smuzhiyunis specified, use::
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun	GCOV_PROFILE_main.o := n
69*4882a593Smuzhiyun
70*4882a593Smuzhiyunand::
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun	GCOV_PROFILE := n
73*4882a593Smuzhiyun
74*4882a593SmuzhiyunOnly files which are linked to the main kernel image or are compiled as
75*4882a593Smuzhiyunkernel modules are supported by this mechanism.
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun
78*4882a593SmuzhiyunFiles
79*4882a593Smuzhiyun-----
80*4882a593Smuzhiyun
81*4882a593SmuzhiyunThe gcov kernel support creates the following files in debugfs:
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun``/sys/kernel/debug/gcov``
84*4882a593Smuzhiyun	Parent directory for all gcov-related files.
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun``/sys/kernel/debug/gcov/reset``
87*4882a593Smuzhiyun	Global reset file: resets all coverage data to zero when
88*4882a593Smuzhiyun        written to.
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda``
91*4882a593Smuzhiyun	The actual gcov data file as understood by the gcov
92*4882a593Smuzhiyun        tool. Resets file coverage data to zero when written to.
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno``
95*4882a593Smuzhiyun	Symbolic link to a static data file required by the gcov
96*4882a593Smuzhiyun        tool. This file is generated by gcc when compiling with
97*4882a593Smuzhiyun        option ``-ftest-coverage``.
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun
100*4882a593SmuzhiyunModules
101*4882a593Smuzhiyun-------
102*4882a593Smuzhiyun
103*4882a593SmuzhiyunKernel modules may contain cleanup code which is only run during
104*4882a593Smuzhiyunmodule unload time. The gcov mechanism provides a means to collect
105*4882a593Smuzhiyuncoverage data for such code by keeping a copy of the data associated
106*4882a593Smuzhiyunwith the unloaded module. This data remains available through debugfs.
107*4882a593SmuzhiyunOnce the module is loaded again, the associated coverage counters are
108*4882a593Smuzhiyuninitialized with the data from its previous instantiation.
109*4882a593Smuzhiyun
110*4882a593SmuzhiyunThis behavior can be deactivated by specifying the gcov_persist kernel
111*4882a593Smuzhiyunparameter::
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun        gcov_persist=0
114*4882a593Smuzhiyun
115*4882a593SmuzhiyunAt run-time, a user can also choose to discard data for an unloaded
116*4882a593Smuzhiyunmodule by writing to its data file or the global reset file.
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun
119*4882a593SmuzhiyunSeparated build and test machines
120*4882a593Smuzhiyun---------------------------------
121*4882a593Smuzhiyun
122*4882a593SmuzhiyunThe gcov kernel profiling infrastructure is designed to work out-of-the
123*4882a593Smuzhiyunbox for setups where kernels are built and run on the same machine. In
124*4882a593Smuzhiyuncases where the kernel runs on a separate machine, special preparations
125*4882a593Smuzhiyunmust be made, depending on where the gcov tool is used:
126*4882a593Smuzhiyun
127*4882a593Smuzhiyuna) gcov is run on the TEST machine
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun    The gcov tool version on the test machine must be compatible with the
130*4882a593Smuzhiyun    gcc version used for kernel build. Also the following files need to be
131*4882a593Smuzhiyun    copied from build to test machine:
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun    from the source tree:
134*4882a593Smuzhiyun      - all C source files + headers
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun    from the build tree:
137*4882a593Smuzhiyun      - all C source files + headers
138*4882a593Smuzhiyun      - all .gcda and .gcno files
139*4882a593Smuzhiyun      - all links to directories
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun    It is important to note that these files need to be placed into the
142*4882a593Smuzhiyun    exact same file system location on the test machine as on the build
143*4882a593Smuzhiyun    machine. If any of the path components is symbolic link, the actual
144*4882a593Smuzhiyun    directory needs to be used instead (due to make's CURDIR handling).
145*4882a593Smuzhiyun
146*4882a593Smuzhiyunb) gcov is run on the BUILD machine
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun    The following files need to be copied after each test case from test
149*4882a593Smuzhiyun    to build machine:
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun    from the gcov directory in sysfs:
152*4882a593Smuzhiyun      - all .gcda files
153*4882a593Smuzhiyun      - all links to .gcno files
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun    These files can be copied to any location on the build machine. gcov
156*4882a593Smuzhiyun    must then be called with the -o option pointing to that directory.
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun    Example directory setup on the build machine::
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun      /tmp/linux:    kernel source tree
161*4882a593Smuzhiyun      /tmp/out:      kernel build directory as specified by make O=
162*4882a593Smuzhiyun      /tmp/coverage: location of the files copied from the test machine
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun      [user@build] cd /tmp/out
165*4882a593Smuzhiyun      [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun
168*4882a593SmuzhiyunNote on compilers
169*4882a593Smuzhiyun-----------------
170*4882a593Smuzhiyun
171*4882a593SmuzhiyunGCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with
172*4882a593SmuzhiyunGCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang.
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
175*4882a593Smuzhiyun.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html
176*4882a593Smuzhiyun
177*4882a593SmuzhiyunBuild differences between GCC and Clang gcov are handled by Kconfig. It
178*4882a593Smuzhiyunautomatically selects the appropriate gcov format depending on the detected
179*4882a593Smuzhiyuntoolchain.
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun
182*4882a593SmuzhiyunTroubleshooting
183*4882a593Smuzhiyun---------------
184*4882a593Smuzhiyun
185*4882a593SmuzhiyunProblem
186*4882a593Smuzhiyun    Compilation aborts during linker step.
187*4882a593Smuzhiyun
188*4882a593SmuzhiyunCause
189*4882a593Smuzhiyun    Profiling flags are specified for source files which are not
190*4882a593Smuzhiyun    linked to the main kernel or which are linked by a custom
191*4882a593Smuzhiyun    linker procedure.
192*4882a593Smuzhiyun
193*4882a593SmuzhiyunSolution
194*4882a593Smuzhiyun    Exclude affected source files from profiling by specifying
195*4882a593Smuzhiyun    ``GCOV_PROFILE := n`` or ``GCOV_PROFILE_basename.o := n`` in the
196*4882a593Smuzhiyun    corresponding Makefile.
197*4882a593Smuzhiyun
198*4882a593SmuzhiyunProblem
199*4882a593Smuzhiyun    Files copied from sysfs appear empty or incomplete.
200*4882a593Smuzhiyun
201*4882a593SmuzhiyunCause
202*4882a593Smuzhiyun    Due to the way seq_file works, some tools such as cp or tar
203*4882a593Smuzhiyun    may not correctly copy files from sysfs.
204*4882a593Smuzhiyun
205*4882a593SmuzhiyunSolution
206*4882a593Smuzhiyun    Use ``cat`` to read ``.gcda`` files and ``cp -d`` to copy links.
207*4882a593Smuzhiyun    Alternatively use the mechanism shown in Appendix B.
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun
210*4882a593SmuzhiyunAppendix A: gather_on_build.sh
211*4882a593Smuzhiyun------------------------------
212*4882a593Smuzhiyun
213*4882a593SmuzhiyunSample script to gather coverage meta files on the build machine
214*4882a593Smuzhiyun(see 6a):
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun.. code-block:: sh
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun    #!/bin/bash
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun    KSRC=$1
221*4882a593Smuzhiyun    KOBJ=$2
222*4882a593Smuzhiyun    DEST=$3
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun    if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then
225*4882a593Smuzhiyun      echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2
226*4882a593Smuzhiyun      exit 1
227*4882a593Smuzhiyun    fi
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun    KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
230*4882a593Smuzhiyun    KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun    find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \
233*4882a593Smuzhiyun                     -perm /u+r,g+r | tar cfz $DEST -P -T -
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun    if [ $? -eq 0 ] ; then
236*4882a593Smuzhiyun      echo "$DEST successfully created, copy to test system and unpack with:"
237*4882a593Smuzhiyun      echo "  tar xfz $DEST -P"
238*4882a593Smuzhiyun    else
239*4882a593Smuzhiyun      echo "Could not create file $DEST"
240*4882a593Smuzhiyun    fi
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun
243*4882a593SmuzhiyunAppendix B: gather_on_test.sh
244*4882a593Smuzhiyun-----------------------------
245*4882a593Smuzhiyun
246*4882a593SmuzhiyunSample script to gather coverage data files on the test machine
247*4882a593Smuzhiyun(see 6b):
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun.. code-block:: sh
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun    #!/bin/bash -e
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun    DEST=$1
254*4882a593Smuzhiyun    GCDA=/sys/kernel/debug/gcov
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun    if [ -z "$DEST" ] ; then
257*4882a593Smuzhiyun      echo "Usage: $0 <output.tar.gz>" >&2
258*4882a593Smuzhiyun      exit 1
259*4882a593Smuzhiyun    fi
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun    TEMPDIR=$(mktemp -d)
262*4882a593Smuzhiyun    echo Collecting data..
263*4882a593Smuzhiyun    find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
264*4882a593Smuzhiyun    find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
265*4882a593Smuzhiyun    find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
266*4882a593Smuzhiyun    tar czf $DEST -C $TEMPDIR sys
267*4882a593Smuzhiyun    rm -rf $TEMPDIR
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun    echo "$DEST successfully created, copy to build system and unpack with:"
270*4882a593Smuzhiyun    echo "  tar xfz $DEST"
271