This wiki page is based on what was originally in Anton's <minix/gcov.h>.

Introduction

Code coverage testing is offered by gcc through gcov. Special compiler
flags add execution counters to a binary, along with counter increment
operations around each basic block of code. This way, the counters indicate
how many times a line of code has run.

The regular gcov interface uses fopen() and fwrite() directly, which is
impossible from minix system processes and the kernel, of course. Anton
changed libgcc to call gcov_ wrapper functions instead, with are implemented
separately in libc (for normal programs) and libsys (for system processes.)

How to use

Simply set MKCOVERAGE=yes as an environment or make variable. This will cause bsd.gcov.mk (included by bsd.prog.mk) to set the compiler to gcc, and the CFLAGS to extra necessary gcov options. Of course you have to compile everything like this (both for gcov to work and to not mix ack and gcc object files), so do 'make clean' first. e.g.:

# cd /usr/src/servers/vfs
# make MKCOVERAGE=yes clean all

Significantly, this build process also writes gcc .gcno files in this directory, which is line number information. These are needed later by lcov.

The env/make variable means you can do:

# cd /usr/src/tools
# make MKCOVERAGE=yes clean hdboot

in order to generate coverage code and data for all servers and drivers. (Except that that doesn't work literally because the kernel is a special case currently - it won't build with gcov so you have to do make clean, make kernel without gcov, then make hdboot with gcov.)

Reboot with the new gcov-enabled system.

To retrieve the data, run gcov-pull with the pid of the server as an argument (not endpoint/slot number). This pretty much has to happen in the
server's own directory in order for lcov to use the .gcno files:

# cd /usr/src/servers/vfs
# gcov-pull 7

Now you can run lcov to interpret the gcov data and generate a pretty html report. -c means capture, -d . specifies the directory with .gcda files
and implies it has to read from those files as opposed to retrieve the data from the kernel (linux). Install lcov first if it's not installed yet.

That's it; the html report is in that directory. More advanced use combines this coverage data into a single report; from a higher level:

# genhtml -o report ''find . -name 'lcov.*'''

How to implement in new servers

In theory, no peculiar extra work has to be done if your process uses SEF. By default, the standard libsys gcov call handler is invoked
which handles the VFS request properly. If you are unusual, such as if you are the kernel, you need a different mechanism to provide the gcov
buffer.

Implementation

libgcov is linked to each executable. This library writes the
counters to disk (gcda files) whenever the executable exits or forks.
The gcov tool can transform those gcda files, along with gcno files that
are created at compile time, to gcov files. Those gcov files are human
readable, and contain the source code with an execution count at the
beginning of each line. Lcov is a tool made by the Linux test project,
which can transform those gcov files into a nice bundle of html files.

GCOV IN MINIX SERVERS

When making a GCOV call to a server, the gcov library linked into the
server will try to write gcov data to disk. This writing is normally
done with calls to the vfs, using stdio library calls. This is not
correct behavior for servers, especially vfs itself. Therefore, the
server catches those attempts. Instead, the gcov data is stored in a
buffer. When the gcov operation is done, the buffer is copied from the
server to a helping user space process, from where the calls are finally
made to the vfs. GCOV calls to the various servers are all routed trough
vfs.

PARTS OF THE SYSTEM

gcc, gcov, libgcov

In the gcc source package, the header file gcc/gcov-minix-fs-wrapper.h
is added. That file is included in gcc/libgcov.c. The header file add
pointers to file system calls, and redefine all file system function
calls as calls to these pointers. In effect, these pointers are an
extra layer between libgcov and the file system calls. These pointers
can be pointed to functions that do not call the file system, but
transfer the gcov data to the user space buffer. Gcc and gcov are also
used when compiling the servers and converting the gcov data.

sysutil library

In the sysutil library, the functions that replace the standard file
system calls are implemented (in gcov.c). Also, there is one main entry
point that does the function replacement, and calls the libgcov
functionality. This function is called do_gcov_flush_impl.

the minix servers

In the minix servers, the gcov function call is added. It's called
do_gcov_flush. That function call calls the do_gcov_flush_impl in the
sysutil library. Among other arguments, it passes a pointer to the
actual gcov_flush implementation in libgcov, and a function pointer that
replaces the file system function calls with the sysutil versions.
Sysutil does not know about those pointers, because it is not linked to
libgcov.

gcov-tools

There are three tools for using gcov with minix servers. These are
located in /usr/src/commands/gcov-tools. First of all, gcov-pretty adds
extra new lines to the server source code, so that all statements get
their own line. This way, one gets more information on coverage of each
statement. Secondly, gcov-pull creates a buffer, makes a gcov call to
vfs, and then writes to disk all the gcov data that was placed in the
buffer by a server. Thirdly, gcov-lcov is a shell script that combines
a gcov-pull call with an subsequent lcov call. That way, all gcov data
is transformed into html. Also, When previous gcov-data is found, the
two data sets are combined by adding the counters together.

BUGS

Shortcomings of the system are..

If you give a non-server/driver but existing pid to vfs, it will try to sendrec() to that pid anyway, but never receive a reply, hanging the system.

You have to give the pid to gcov-pull, which is a pain to do with many different processes in batches. The problem with name lookups is that they're not unique (mfs specifically).