SourceForge Logo

Theory of Operations

Introduction

The COVTOOL instrumentor is a C++ program that copies stdin to stdout. It presumes that the source text is a C++ program that has been passed through the C++ preprocessor. The instrumentor modifies that text as it is copied. The modifications are as follows:

The recording function is implemented in a module called "covtoolhelper.c" which must be compiled and linked into the program. The cov++ script normally does this for you.

Instrumentor design

The instrumentor is much less sophisticated that one might imagine. It does not in fact parse the whole of the C++ language and it does not store any kind of "abstract syntax tree" for the program it is working on. Instead, it detects only the most large scale features of the program:

The general idea is that the each statement is prefixed by a function call that logs the fact that a statement is being executed. Consider the following instrumented version of a return statement:

CvT_record_line___(fileRef,LineNumber); return 42;

Note that is a most trivial intrusion into the program. It adds no variable declarations and has no scope affects. The worse case scenario is when you have a program conditional structure. Suppose you mean to instrument the following code:

if(expression)
  return 19;

In a case like this, you can not just inject the line recording function call. Instead, you have to go the extra mile and add {} around the return statement as well as sticking in the line recording directives:

CvT_record_line___(fileRef,LineNumber);if(expression)
  {CvT_record_line___(fileRef,LineNumber);return 19;}

Even this worst case intrusion is relatively simple to implement -- if you can recognize program statements.

As it runs, the instrumentor keeps track of lines in various files parsed. It looks for the compiler supplied hints. They typically take on of the following forms:

  #line number "filename"
or
  #number "filename"

the filename part is easily understood, but the '#number' or '#line number' part must be explained: it is the line number within 'filename' of the next line after '#' line. That is, the compiler puts in # directives to let you know where it is in the file. A preprocessed C++ file might look something like this:

#1 "somefile.c"

#1 "included_file"

  ...

#2 "somefile.c"
line 2 of somefile.c

the key is understand that the compiler gives you directions about which file is currently being processed. The instrumentor makes no attempt to instrument lines in absence of the # directives. so, you can't instrument a file unless it has at least one line looking something like this:

# 1 "filename"

In absence of this syntax, it will simply copy stdin to stdout without adding instrumentation.

Instrumentor options

At this time, there are only two options to the instrumentor:

The -instrument option lets you instruct the covtool.exe program to actually include instrumentation. Without instrumentation, the program adds commentary about its internal state. This is mainly a debugging tool.

The -skip option(s) let you instruct the instrumentor to ignore directoroies. For example, you rarely want to instrument the C++ runtime header files. So you will almost always specify the -skip /usr option to ignore the /usr/ directgory and all subdirectories thereof.

Using cov++

More often than not, you are going to be using the cov++ script rather than the covtool.exe instrumentor directly. This is because the cov++ script was intended as the public interface. It uses script language commands to handle the myriad of minor string substituions needed to pull off an easy to use public interface.