GCC Middle and Back End API Reference
gcov.c File Reference

Data Structures

struct  arc_info
struct  block_info
struct  function_info
struct  coverage_info
struct  line_info
struct  source_info
struct  name_map


typedef struct arc_info arc_t
typedef struct block_info block_t
typedef struct function_info function_t
typedef struct coverage_info coverage_t
typedef struct line_info line_t
typedef struct source_info source_t
typedef struct name_map name_map_t


static int process_args (int, char **)
static void print_usage (static int output_branch_count(FILE int)
static void print_usage ()
static void print_version ()
static int process_args ()
static char * get_gcov_intermediate_filename ()
static void output_intermediate_file ()
static void process_file ()
static void output_gcov_file ()
static void generate_results ()
static void release_function ()
static void release_structures ()
static void create_file_names ()
static int name_search ()
static int name_sort ()
static unsigned find_source ()
static function_tread_graph_file ()
static int read_count_file ()
static void solve_flow_graph ()
static void find_exception_blocks ()
static void add_branch_counts ()
static char const * format_gcov ()
static void executed_summary ()
static void function_summary ()
static char * canonicalize_name ()
static char * make_gcov_file_name ()
static char * mangle_name ()
static void add_line_counts ()
static void accumulate_line_counts ()
static int output_branch_count ()
static const char * read_line ()
static void output_lines ()


static function_tfunctions
static function_t ** fn_end = &functions
static source_tsources
static unsigned n_sources
static unsigned a_sources
static name_map_tnames
static unsigned n_names
static unsigned a_names
static unsigned object_runs
static unsigned program_count
static unsigned total_lines
static unsigned total_executed
static time_t bbg_file_time
static char * bbg_file_name
static unsigned bbg_stamp
static char * da_file_name
static int no_data_file
static int multiple_files = 0
static int flag_branches = 0
static int flag_unconditional = 0
static int flag_gcov_file = 1
static int flag_display_progress = 0
static int flag_intermediate_format = 0
static int flag_demangled_names = 0
static int flag_long_names = 0
static int flag_all_blocks = 0
static int flag_function_summary = 0
static char * object_directory = 0
static char * source_prefix = 0
static size_t source_length = 0
static int flag_relative_only = 0
static int flag_preserve_paths = 0
static int flag_counts = 0
static struct option options []

Typedef Documentation

typedef struct arc_info arc_t
   Describes an arc between two basic blocks.  
typedef struct block_info block_t
   Describes a basic block. Contains lists of arcs to successor and
   predecessor blocks.  
typedef struct coverage_info coverage_t
   Describes coverage of a file or function.  
typedef struct function_info function_t
   Describes a single function. Contains an array of basic blocks.  
typedef struct line_info line_t
   Describes a single line of source. Contains a chain of basic blocks
   with code on it.  
typedef struct name_map name_map_t
typedef struct source_info source_t
   Describes a file mentioned in the block graph.  Contains an array
   of line info.  

Function Documentation

static void accumulate_line_counts ( )
   Accumulate the line counts of a file.  
     Reverse the function order.  
             Total and reverse the branch information.  
             The user expects the line count to be the number of times
             a line has been executed. Simply summing the block count
             will give an artificially high number.  The Right Thing
             is to sum the entry counts to the graph of blocks on this
             line, then find the elementary cycles of the local graph
             and add the transition counts of those cycles.  
             Reverse the block information.  
             Sum the entry arcs.  
                 Initialize the cs_count.  
             Find the loops. This uses the algorithm described in
             Tiernan 'An Efficient Search Algorithm to Find the
             Elementary Circuits of a Graph', CACM Dec 1970. We hold
             the P array by having each block point to the arc that
             connects to the previous block. The H array is implicitly
             held because of the arc ordering, and the block's
             previous arc pointer.

             Although the algorithm is O(N^3) for highly connected
             graphs, at worst we'll have O(N^2), as most blocks have
             only one or two exits. Most graphs will be small.

             For each loop we find, locate the arc with the smallest
             transition count, and add that to the cumulative
             count.  Decrease flow over the cycle and remove the arc
             from consideration.  
                         Not to same graph, or before first vertex.  
                         Already in path.  
                         Found a closing arc.  
                         Locate the smallest arc count of the loop.  
                         Remove the flow from the cycle.  
                         Unwind to the cyclic arc.  
                         Move on.  
                     Add new block to chain.  
                 We could not add another vertex to the path. Remove
                 the last vertex from the list.  
                     It was not the first vertex. Move onto next arc.  
                 Mark this block as unusable.  
static void add_branch_counts ( )
   Increment totals in COVERAGE according to arc ARC.  

Referenced by mangle_name().

static void add_line_counts ( )
   Scan through the bb_data for each line in the block, increment
   the line number execution count indicated by the execution count of
   the appropriate basic block.  
     Scan each basic block.  
           Entry or exit block 
static char* canonicalize_name ( )
   Canonicalize the filename NAME by canonicalizing directory
   separators, eliding . components and resolving .. components
   appropriately.  Always returns a unique string.  
     The canonical name cannot be longer than the incoming name.  
           Elide a '.' directory 
             '..', we can only elide it and the previous directory, if
             we're not a symlink.  
                 S_ISLNK is not POSIX.1-1996.  
                 Cannot elide, or unreadable or a symlink.  
             Regular pathname component.  

References len, and memcpy().

Referenced by create_file_names().

static void create_file_names ( )
   Generate the names of the graph and data files.  If OBJECT_DIRECTORY
   is not specified, these are named from FILE_NAME sans extension.  If
   OBJECT_DIRECTORY is specified and is a directory, the files are in that
   directory, but named from the basename of the FILE_NAME, sans extension.
   Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
   and the data files are named from that.  
     Free previous file names.  
         Append source file name.  
     Remove the extension.  

References a_names, a_sources, canonicalize_name(), source_info::coverage, free(), memcpy(), memset(), n_names, n_sources, coverage_info::name, source_info::name, name_map::name, name_search(), source_length, source_prefix, and name_map::src.

static void executed_summary ( )
   Summary of execution 

References flag_long_names.

static void find_exception_blocks ( )
   Mark all the blocks only reachable via an incoming catch.  
     First mark all blocks as exceptional.  
     Now mark all the blocks reachable via non-fake edges 
static unsigned find_source ( )
   Find or create a source file structure for FILE_NAME. Copies
   FILE_NAME on creation 
         Extend the name map array -- we'll be inserting one or two
     Not found, try the canonical name. 
         Not found with canonical name, create a new source.  
             You lose if separators don't match exactly in the
         Append the non-canonical name.  
     Resort the name map.  
static char const* format_gcov ( )
   Format a GCOV_TYPE integer as either a percent ratio, or absolute
   count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
   If DP is zero, no decimal point is printed. Only print 100% when
   TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
   format TOP.  Return pointer to a static string.  
static void function_summary ( )
   Output summary info for a function or file.  

References mangle_name(), and strlen().

static void generate_results ( )
         Open the intermediate file.  
             Ignore this source, if it is an absolute path (after
             source prefix removal).  
               Output the intermediate format without requiring source
               files.  This outputs a section to a *single* file.  
         Now we've finished writing the intermediate file.  
static char* get_gcov_intermediate_filename ( )
   Get the name of the gcov file.  The return value must be free'd.

   It appends the '.gcov' extension to the *basename* of the file.
   The resulting file name will be in PWD.

   input: foo.da,       output: foo.da.gcov
   input: a/b/foo.cc,   output: foo.cc.gcov  
     Find the 'basename'.  

References arc_info::count, block_info::count, and arc_info::src.

static char* make_gcov_file_name ( )
   Generate an output file name. INPUT_NAME is the canonicalized main
   input file and SRC_NAME is the canonicalized file name.
   LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation.  With
   long_output_names we prepend the processed name of the input file
   to each output name (except when the current source file is the
   input file, so you don't get a double concatenation). The two
   components are separated by '##'.  With preserve_paths we create a
   filename from all path components of the source file, replacing '/'
   with '#', and .. with '^', without it we simply take the basename
   component.  (Remember, the canonicalized name will already have
   elided '.' components and converted \\ separators.)  
         Generate the input filename part.  

References line_info::blocks, block_info::chain, function_info::line, source_info::lines, function_info::src, and line_info::u.

static char* mangle_name ( )
static int name_search ( )
   A is a string and B is a pointer to name_map_t.  Compare for file
   name orderability.  

Referenced by create_file_names().

static int name_sort ( )
   A and B are a pointer to name_map_t.  Compare for file name

References bbg_file_name, and fnotice().

static int output_branch_count ( )
   Output information about ARC number IX.  Returns nonzero if
   anything is output.  
static void output_gcov_file ( )
static void output_intermediate_file ( )

Output the result in intermediate format used by 'lcov'.

The intermediate format contains a single file named 'foo.cc.gcov', with no source code included. A sample output is

file:foo.cc function:5,1,Z3foov function:13,1,main function:19,1,_GLOBAL__sub_I__Z3foov function:19,1,_Z41__static_initialization_and_destruction_0ii lcount:5,1 lcount:7,9 lcount:9,8 lcount:11,1 file:/.../iostream lcount:74,1 file:/.../basic_ios.h file:/.../ostream file:/.../ios_base.h function:157,0,_ZStorSt12_Ios_IostateS lcount:157,0 file:/.../char_traits.h function:258,0,_ZNSt11char_traitsIcE6lengthEPKc lcount:258,0 ...

The default gcov outputs multiple files: 'foo.cc.gcov', 'iostream.gcov', 'ios_base.h.gcov', etc. with source code included. Instead the intermediate format here outputs only a single file 'foo.cc.gcov' similar to the above example.

                     : notexec (Branch not executed)
                     : taken (Branch executed and taken)
                     : nottaken (Branch executed, but not taken)

References function_info::blocks, block_info::line, source_info::num_lines, and block_info::u.

static void output_lines ( )
   Read in the source file one line at a time, and output that line to
   the gcov file preceded by its execution count and other
         For lines which don't exist in the .bb file, print '-' before
         the source line.  For lines which exist but were never
         executed, print '#####' or '=====' before the source line.
         Otherwise, print the execution count before the source line.
         There are 16 spaces of indentation added before the source
         line so that tabs won't be messed up.  
     Handle all remaining source lines.  There may be lines after the
     last line of code.  
static void print_usage ( static int output_branch_count (FILE  int)

Unlock the stdio streams.

     Handle response files.  

References flag_display_progress, and process_file().

static void print_usage ( void  )
   Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
   otherwise the output of --help.  

References flag_all_blocks, flag_branches, flag_counts, flag_demangled_names, flag_function_summary, flag_gcov_file, flag_long_names, and print_usage().

static void print_version ( void  )
   Print version information and exit.  
static int process_args ( int  ,
char **   
   Forward declarations.  
static int process_args ( )
   Process args, return index to first non-arg.  
             print_usage will exit.  
             print_version will exit.  
             print_usage will exit.  

References strlen().

static void process_file ( )
   Process a single input file.  
             Now insert it into the source file's list of
             functions. Normally functions will be encountered in
             ascending order, so a simple scan is quick.  Note we're
             building this list in reverse order.  
             Mark last line in files touched by function.  
           The function was not in the executable -- some other
           instance must have been selected.  

Referenced by print_usage().

static int read_count_file ( )
   Reads profiles from the count file and attach to each
   function. Return nonzero if fatal error.  
             Try to find the function in the list.  To speed up the
             search, first start from the last function found.  
static function_t* read_graph_file ( )
   Read the notes file.  Return list of functions read -- in reverse order.  
                         Exceptional exit from this function, the
                         source block must be a call.  
                         Non-local return from a callee of this
                         function. The destination block is a setjmp.  
                 We have a fake exit from this block.  The other
                 non-fall through exits must be to catch handlers.
                 Mark them as catch arcs.  

References function_info::blocks, arc_info::count, arc_info::count_valid, arc_info::dst, arc_info::fake, arc_info::fall_through, gcov_read_unsigned(), arc_info::is_call_non_return, block_info::is_call_site, arc_info::is_nonlocal_return, block_info::is_nonlocal_return, function_info::num_blocks, function_info::num_counts, block_info::num_pred, block_info::num_succ, arc_info::on_tree, block_info::pred, arc_info::pred_next, arc_info::src, block_info::succ, and arc_info::succ_next.

static const char* read_line ( )
static void release_function ( )
   Release a function structure 
static void release_structures ( )
   Release all memory used.  

References name_map::name.

static void solve_flow_graph ( )
   Solve the flow graph. Propagate counts from the instrumented arcs
   to the blocks and the uninstrumented arcs.  
     The arcs were built in reverse order.  Fix that now.  
           We can't deduce the entry block counts from the lack of
           Likewise, we can't deduce exit block counts from the lack
           of its successors.  
     Propagate the measured counts, this must be done in the same
     order as the code in profile.c  
             If there is only one non-fake exit, it is an
             unconditional branch.  
                   If this block is instrumenting a call, it might be
                   an artificial block. It is not artificial if it has
                   a non-fallthrough exit, or the destination of this
                   arc has more than one entry.  Mark the destination
                   block as a return site, if none of those conditions
         Sort the successor arcs into ascending dst order. profile.c
         normally produces arcs in the right order, but sometimes with
         one or two out of order.  We're not using a particularly
         smart sort.  
         Place it on the invalid chain, it will be ignored if that's
     If the graph has been correctly solved, every block will have a
     valid count.  

References arc_info::dst, and arc_info::succ_next.

Variable Documentation

unsigned a_names

Referenced by create_file_names().

unsigned a_sources

Referenced by create_file_names().

char* bbg_file_name
   Name of the notes (gcno) output file.  The "bbg" prefix is for
   historical reasons, when the notes file contained only the
   basic block graph notes.  

Referenced by name_sort().

time_t bbg_file_time
   Modification time of graph file.  
unsigned bbg_stamp
   Stamp of the bbg file 
char* da_file_name
   Name and file pointer of the input file for the count data (gcda).  
int flag_all_blocks = 0
   Output count information for every basic block, not merely those
   that contain line number information.  

Referenced by mangle_name(), and print_usage().

int flag_branches = 0
   Output branch probabilities.  

Referenced by print_usage().

int flag_counts = 0
   Output the number of times a branch was taken as opposed to the percentage
   of times it was taken.  

Referenced by print_usage().

int flag_demangled_names = 0
   Output demangled function names.  

Referenced by print_usage().

int flag_display_progress = 0
   Output progress indication if this is true.  This is off by default
   and can be turned on by the -d option.  

Referenced by print_usage().

int flag_function_summary = 0
   Output summary info for each function.  

Referenced by print_usage().

int flag_gcov_file = 1
   Output a gcov file if this is true.  This is on by default, and can
   be turned off by the -n option.  

Referenced by print_usage().

int flag_intermediate_format = 0
   Output *.gcov file in intermediate format used by 'lcov'.  
int flag_long_names = 0
   For included files, make the gcov output file name include the name
   of the input source file.  For example, if x.h is included in a.c,
   then the output file name is a.c##x.h.gcov instead of x.h.gcov.  

Referenced by executed_summary(), and print_usage().

int flag_preserve_paths = 0
   Preserve all pathname components. Needed when object files and
   source files are in subdirectories. '/' is mangled as '#', '.' is
   elided and '..' mangled to '^'.  
int flag_relative_only = 0
   Only show data for sources with relative pathnames.  Absolute ones
   usually indicate a system header file, which although it may
   contain inline functions, is usually uninteresting.  
int flag_unconditional = 0
   Show unconditional branches too.  
function_t** fn_end = &functions
function_t* functions
   Holds a list of function basic block graphs.  
int multiple_files = 0
   If there is several input files, compute and display results after
   reading all data files.  This way if two or more gcda file refer to
   the same source file (eg inline subprograms in a .h file), the
   counts are added.  
unsigned n_names

Referenced by create_file_names().

unsigned n_sources

Referenced by create_file_names().

name_map_t* names
int no_data_file
   Data file is missing.  
char* object_directory = 0
   Object directory file prefix.  This is the directory/file where the
   graph and data files are looked for, if nonzero.  
unsigned object_runs
   This holds data summary information.  
struct option options[]
Initial value:
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "all-blocks", no_argument, NULL, 'a' },
{ "branch-probabilities", no_argument, NULL, 'b' },
{ "branch-counts", no_argument, NULL, 'c' },
{ "intermediate-format", no_argument, NULL, 'i' },
{ "no-output", no_argument, NULL, 'n' },
{ "long-file-names", no_argument, NULL, 'l' },
{ "function-summaries", no_argument, NULL, 'f' },
{ "demangled-names", no_argument, NULL, 'm' },
{ "preserve-paths", no_argument, NULL, 'p' },
{ "relative-only", no_argument, NULL, 'r' },
{ "object-directory", required_argument, NULL, 'o' },
{ "object-file", required_argument, NULL, 'o' },
{ "source-prefix", required_argument, NULL, 's' },
{ "unconditional-branches", no_argument, NULL, 'u' },
{ "display-progress", no_argument, NULL, 'd' },
{ 0, 0, 0, 0 }
unsigned program_count
size_t source_length = 0

Referenced by create_file_names().

char* source_prefix = 0
   Source directory prefix.  This is removed from source pathnames
   that match, when generating the output file name.  

Referenced by create_file_names().

source_t* sources
unsigned total_executed
unsigned total_lines