GCOV Support for Linux (including dynamic modules)

From: Hubertus Franke (frankeh@watson.ibm.com)
Date: Mon Feb 11 2002 - 13:12:53 EST


Attached is <gcov.tar.bz2> implementing this functionality for
the 2.4.17 and the 2.5.2 kernels.

GCOV kernel support for Linux
=============================

What is GCOV?
-------------
gcov is a test coverage program, which helps discover where your
optimization efforts will best affect your code. Using gcov one can find
out some basic performance statistics on a per source file level such as:
        * how often each line of code executes
        * what lines of code are actually executed
        * how much computing time each section of code uses

What we implemented?
--------------------
gcov is already available for user level applications.
We implemented gcov support for the linux kernel by providing
coverage support infrastructure to the kernel and a dynamic
module (gcov.o) to produce the basic block profile information,
which gives the statistics for the running kernel and modules.

Installing GCOV support on the kernel
-------------------------------------
To provide the coverage support infrastructure to the kernel,
install the gcov patch
(2.5.2-gcov-kernel.patch OR 2.4.17-gcov-kernel.patch) from the root
level of the kernel source path, as

        patch -p1< {path}/2.5.2-gcov-kernel.patch

Configuring the kernel
----------------------

To configure the entire kernel for gcov profiling, run
        make xconfig or menuconfig

There are two options under GCOV coverage profiling. They are
        * enable GCOV kernel
        * GCOV kernel profiler

"enable GCOV kernel" will provide the infrastructure of
coverage support for the kernel.
But this will not compile the kernel with the necessary flags.

To obtain the coverage information for the entire kernel, one should
enable the "GCOV kernel profiler" option.

To get the profiling information for a particular file or directory of
the kernel, provide the following compile options for such targets
itself, like

        CLAGS += ($CFLAGS $GCOV_FLAGS)

where GCOV_FLAGS is "-fprofile-arcs -ftest-coverage"

and compile the kernel.

Accessing GCOV information
--------------------------
In order to produce the profiling information, compile and install the
gcov.o module as follows (ensure that the proper linux include path is
provided in the Makefile)

        make
        insmod gcov.o

and to remove the module, run

        rmmod gcov

The detailed explanation of how gcov provides the statistics
information is described below.

How it works?
-------------

Here is the brief explanation of how gcov works for user level
applications.

The C compiler supports the command line options -fprofile-arcs and
-ftest-coverage. These options cause the compiler to insert additional
code in the object files. These options also generate two files
(a) <sourcefile>.bb and (b) <sourcefile>.bbg, where
        * .bb file contains a list of source files (including headers),
functions within those files and line numbers corresponding to each
basic block in the source file.
        * .bbg file contains a list of the program flow arcs for each
function which in combination with the .bb file enables gcov to
reconstruct the program flow.

Upon executing a gcov enabled user program, it dumps the counter
information into <sourcefile>.da at the time of exit.

Running gcov with the program's source file name as argument, will combine the
information from .bb, .bbg and .da files and produce a listing of the code
along with the frequency of execution of each line.

For further detailed information, refer gcov.readme which is the text
form of gcc/doc/gcov.texi from the GCC source code.

How gcov works for kernel
-------------------------

As the kernel never does exit as a program, this cannot be deployed in such a
fashion. The .da file is made available under /proc/gcov/{kernel source path}.

For example:
Consider a file ./kernel/sched.c. After compiling this file, the
compiler will generate .bb and .bbg file and it will be in the directory
where the source code is located. ie. ./kernel/sched.bb and ./kernel/sched.bbg.

Installing the gcov kernel module will create a file at
/proc/gcov/kernel/sched.da and create symbolic links for the files
 ./kernel/sched.c, ./kernel/sched.bb and ./kernel/sched.bbg to
/proc/gcov. We opted for providing these links in order to allow usage
of an unmodified gcov tool.

Finally there will be 4 files under /proc ie.

/proc/gcov/kernel/sched.c
/proc/gcov/kernel/sched.bb
/proc/gcov/kernel/sched.bbg
/proc/gcov/kernel/sched.da

This is the same for all the files which are built with the gcov
options(-fprofile-arcs and -ftest-coverage).

Now to see the statistics information for the sched.c, run gcov
from any of your local directory as follows:

        gcov -o /proc/gcov/kernel /proc/gcov/kernel/sched.c

This will generate results in the local directory as sched.c.gcov.

Here is a sample output from the signal.c.gcov file

                static void handle_stop_signal(int sig, struct task_struct *t)
                {
        8392 switch (sig) {
           7 case SIGKILL: case SIGCONT:
                                /* Wake up the process if stopped. */
           7 if (t->state == TASK_STOPPED)
      ###### wake_up_process(t);
           7 t->exit_code = 0;
           7 rm_sig_from_queue(SIGSTOP, t);
           7 rm_sig_from_queue(SIGTSTP, t);
           7 rm_sig_from_queue(SIGTTOU, t);
           7 rm_sig_from_queue(SIGTTIN, t);
        8385 break;
 
                        case SIGSTOP: case SIGTSTP:
                        case SIGTTIN: case SIGTTOU:
                                /* If we're stopping again, cancel SIGCONT */
      ###### rm_sig_from_queue(SIGCONT, t);
        8385 break;
        8385 }
                }

where "######" represents no execution.

Here are the various arguments for invoking gcov

     gcov [-b] [-c] [-v] [-n] [-l] [-f] [-o directory] SOURCEFILE
 
-b
     Write branch frequencies to the output file, and write branch
     summary info to the standard output. This option allows you to
     see how often each branch in your program was taken.
 
-c
     Write branch frequencies as the number of branches taken, rather
     than the percentage of branches taken.
 
-v
     Display the `gcov' version number (on the standard error stream).
 
-n
     Do not create the `gcov' output file.
 
-l
     Create long file names for included source files. For example, if
     the header file `x.h' contains code, and was included in the file
     `a.c', then running `gcov' on the file `a.c' will produce an
     output file called `a.c.x.h.gcov' instead of `x.h.gcov'. This can
     be useful if `x.h' is included in multiple source files.
 
-f
     Output summaries for each function in addition to the file level
     summary.
 
-o
     The directory where the object files live. Gcov will search for
     `.bb', `.bbg', and `.da' files in this directory.

How gcov works for dynamic modules
----------------------------------

For dynamic modules, once the module gets installed all these files
(.bb, .bbg, .da) will be created dynamically under
"/proc/gcov/module/{module source path}". Similarly their proc entries
will be eliminated when the module gets removed.

To get the coverage information for dynamic modules, one must install
our 2.4.12-insmod.patch to the insmod code which will be in modutils
package. This modutils source file can be downloaded from

http://www.kernel.org/pub/linux/utils/kernel/modutils/v2.4

This patch should be applied from the modutils source directory as
        patch -p1 < 2.4.12-insmod.patch

and proceed with the instructions in the "INSTALL" file at the
modutils root directory.

Resetting the counters:
----------------------
        One can dynamically reset the counters of the file, by writing "0"
to the required .da file.

For example, if you want to reset the counters in sched.c then executing
the command

        echo "0">/proc/gcov/kernel/sched.da

will reset the counters.

There is a /proc/gcov/vmlinux file which holds the block information
of all the files compiled with gcov options.

cmd> echo "0">/proc/gcov/vmlinux

will reset all the counters in the kernel.

cmd> cat /proc/gcov/vmlinux

dumps the entire block informantion for all files in the following format

filename-len (8bytes)
filename (8bytes aligned)
nounts (8bytes)
counter[0..ncounts-1] (each 8bytes)

We have not written any user level program to utilize the vmlinux file.

Tested Environment
------------------
We have tested this on RedHat 7.0 and 7.2 under gcc versions 2.91.66 and
3.0.3.

Problems
--------
gcc does not provide atomic operations for statistics counters. This needs to
be supported in gcc. As a result counters value MAY be overwritten and hence
produce inaccurate results.

-- Hubertus Franke



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Feb 15 2002 - 21:00:40 EST