This is a list of common questions regarding the GCOV patch
===========================================================
1. Is there a way to get a graphical output of coverage data?
2. What are possible reasons if a module doesn't show up in /proc/gcov?
3. How do I profile cleanup code of a module?
4. What about the /proc/gcov/module directory?
5. Will unloading the gcov-proc module reset the coverage data?
6. What about the /proc/gcov/vmlinux file?
7. Why does GCOV create result files for some include files?
8. Does this kernel patch work with other compilers?
9. Where do I obtain the GCOV tool?
10. Why are there negative counts in a GCOV result file? Why does GCOV report
some lines as covered even though they weren't?
1. Is there a way to get a graphical output of coverage data?
-------------------------------------------------------------
There is a tool called LCOV which builds on GCOV to provide graphical output
of coverage data. Quote from the LCOV readme file:
LCOV is an extension of GCOV. The extension consists of a set of PERL scripts
which build on the textual GCOV output to implement the following enhanced
functionality:
* HTML based output: coverage rates are additionally indicated using bar
graphs and specific colors.
* Support for large projects: overview pages allow quick browsing of
coverage data by providing three levels of detail: directory view,
file view and source code view.
LCOV was initially designed to support Linux kernel coverage measurements,
but works as well for coverage measurements on standard user space
applications.
The LCOV package is available from:
http://ltp.sourceforge.net/coverage/lcov.php
2. What are possible reasons if a module doesn't show up in /proc/gcov?
-----------------------------------------------------------------------
- Make sure that the module is loaded. Unless the 'gcov_persist' option is
used, entries for dynamic modules in /proc/gcov are deleted once the
module is unloaded.
- Make sure the module was compiled using two additional gcc flags:
-fprofile-arcs -ftest-coverage
- GCOV files for modules which were not compiled in the original kernel
source tree show up in /proc/gcov/module
3. How do I profile cleanup code of a module?
---------------------------------------------
Use the 'gcov_persist' option of the gcov-proc module (see README file).
This way module data will remain in /proc/gcov even after a module was
unloaded.
4. What about the /proc/gcov/module directory?
----------------------------------------------
GCOV files for modules which were not compiled in the original kernel
source tree show up in /proc/gcov/module.
5. Will unloading the gcov-proc module reset the coverage data?
---------------------------------------------------------------
Coverage data for all kernel objects and loaded kernel modules is not
affected when the gcov-proc module is either loaded or unloaded. This does
not apply to entries in /proc/gcov which relate to unloaded modules when
using the gcov_persist option. Such data will be removed when unloading
gcov-proc.
6. What about the /proc/gcov/vmlinux file?
------------------------------------------
The 'vmlinux' file has several functions:
- writing to this file will clear the execution counts of the entire kernel
and all modules. It will also remove data for unloaded modules (see
gcov_persist option in README file)
- reading from this file will provide a concatenation of all GCOV data files
present in /proc/gcov. The format of one entry is defined as follows:
Length of .da filename: (8 bytes)
.da filename: : (8 bytes aligned)
Contents of .da file : (dependent on data)
These entries repeat for each .da file. There is currently no tool
available to further handle this file type.
7. Why does GCOV create result files for some include files?
------------------------------------------------------------
GCOV creates data files for each included file which contributed executable
code to the object file. In cases when two such files have the same name, GCOV
will overwrite the first file. Use the '--long-file-names' option of GCOV to
prevent this.
8. Does this kernel patch work with other compilers?
----------------------------------------------------
No. This kernel patch is based on the profiling code produced by GCC.
9. Where do I obtain the GCOV tool?
-----------------------------------
GCOV is part of GCC and should therefore be present on most linux systems.
10. Why are there negative counts in a GCOV result file? Why does GCOV report
some lines as covered even though they weren't?
-----------------------------------------------------------------------------
There are some characteristics of GCC and the way that this patch accesses
GCOV data that may lead to inaccurate results in a few cases:
Reasons for negative counts:
- concurrent execution of a piece of code on SMP systems: as the update
code for execution counts is not atomic, resulting inconsistent count
values may result in negative counts.
- 'live coverage', i.e. access to coverage data of a file which is
currently in mid-execution: the GCC profiling code is designed so that
an analysis of the count data is performed only after the code has
finished execution. Because this is not the case when using this patch,
inconsistent count values may result in negative counts.
Other sources for inaccuracies:
- GCOV sometimes indicates that the first line of an inline function is
executed exactly twice the times it should have been.
- Because GCOV works on line numbers, putting different branches of
execution in a single line may result in inaccurate data, e.g. consider:
if (a < b) printf("quot;1\n"quot;); else printf("quot;2\n"quot;);
In this case, GCOV will report 100% of the code as being covered, even
though only part of it was actually executed. The same is true for
multi-line macros.
- When using the optimization option of GCC, the compiler will eliminate
code which can never be reached. In some cases such code is incorrectly
associated with other lines which were executed, e.g. consider the
following code which was compiled using the '-O2' option of GCC:
1: 5: if (1 < 2) {
1: 6: printf("quot;true\n"quot;);
-: 7: }
-: 8: else {
1: 9: printf("quot;false\n"quot;);
-: 10: }