1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
4 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
5 Free Software Foundation, Inc.
6 Contributed by James E. Wilson of Cygnus Support.
7 Mangled by Bob Manson of Cygnus Support.
8 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
10 Gcov is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
15 Gcov is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with Gcov; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 /* ??? Print a list of the ten blocks with the highest execution counts,
25 and list the line numbers corresponding to those blocks. Also, perhaps
26 list the line numbers with the highest execution counts, only printing
27 the first if there are several which are all listed in the same block. */
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
32 /* Need an option to show individual block counts, and show
33 probabilities of fall through arcs. */
37 #include "coretypes.h"
40 #include "diagnostic.h"
49 /* The gcno file is generated by -ftest-coverage option. The gcda file is
50 generated by a program compiled with -fprofile-arcs. Their formats
51 are documented in gcov-io.h. */
53 /* The functions in this file for creating and solution program flow graphs
54 are very similar to functions in the gcc source file profile.c. In
55 some places we make use of the knowledge of how profile.c works to
56 select particular algorithms here. */
58 /* The code validates that the profile information read in corresponds
59 to the code currently being compiled. Rather than checking for
60 identical files, the code below computes a checksum on the CFG
61 (based on the order of basic blocks and the arcs in the CFG). If
62 the CFG checksum in the gcda file match the CFG checksum for the
63 code currently being compiled, the profile data will be used. */
65 /* This is the size of the buffer used to read in source file lines. */
67 #define STRING_SIZE 200
73 /* Describes an arc between two basic blocks. */
75 typedef struct arc_info
77 /* source and destination blocks. */
78 struct block_info
*src
;
79 struct block_info
*dst
;
81 /* transition counts. */
83 /* used in cycle search, so that we do not clobber original counts. */
86 unsigned int count_valid
: 1;
87 unsigned int on_tree
: 1;
88 unsigned int fake
: 1;
89 unsigned int fall_through
: 1;
91 /* Arc to a catch handler. */
92 unsigned int is_throw
: 1;
94 /* Arc is for a function that abnormally returns. */
95 unsigned int is_call_non_return
: 1;
97 /* Arc is for catch/setjmp. */
98 unsigned int is_nonlocal_return
: 1;
100 /* Is an unconditional branch. */
101 unsigned int is_unconditional
: 1;
103 /* Loop making arc. */
104 unsigned int cycle
: 1;
106 /* Next branch on line. */
107 struct arc_info
*line_next
;
109 /* Links to next arc on src and dst lists. */
110 struct arc_info
*succ_next
;
111 struct arc_info
*pred_next
;
114 /* Describes a basic block. Contains lists of arcs to successor and
115 predecessor blocks. */
117 typedef struct block_info
119 /* Chain of exit and entry arcs. */
123 /* Number of unprocessed exit and entry arcs. */
127 /* Block execution count. */
130 unsigned count_valid
: 1;
131 unsigned valid_chain
: 1;
132 unsigned invalid_chain
: 1;
133 unsigned exceptional
: 1;
135 /* Block is a call instrumenting site. */
136 unsigned is_call_site
: 1; /* Does the call. */
137 unsigned is_call_return
: 1; /* Is the return. */
139 /* Block is a landing pad for longjmp or throw. */
140 unsigned is_nonlocal_return
: 1;
146 /* Array of line numbers and source files. source files are
147 introduced by a linenumber of zero, the next 'line number' is
148 the number of the source file. Always starts with a source
152 } line
; /* Valid until blocks are linked onto lines */
155 /* Single line graph cycle workspace. Used for all-blocks
159 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
163 /* Temporary chain for solving graph, and for chaining blocks on one
165 struct block_info
*chain
;
169 /* Describes a single function. Contains an array of basic blocks. */
171 typedef struct function_info
173 /* Name of function. */
176 unsigned lineno_checksum
;
177 unsigned cfg_checksum
;
179 /* The graph contains at least one fake incoming edge. */
180 unsigned has_catch
: 1;
182 /* Array of basic blocks. */
185 unsigned blocks_executed
;
187 /* Raw arc coverage counts. */
191 /* First line number & file. */
195 /* Next function in same source file. */
196 struct function_info
*line_next
;
199 struct function_info
*next
;
202 /* Describes coverage of a file or function. */
204 typedef struct coverage_info
210 int branches_executed
;
219 /* Describes a single line of source. Contains a chain of basic blocks
222 typedef struct line_info
224 gcov_type count
; /* execution count */
227 arc_t
*branches
; /* branches from blocks that end on this
228 line. Used for branch-counts when not
230 block_t
*blocks
; /* blocks which start on this line. Used
231 in all-blocks mode. */
234 unsigned unexceptional
: 1;
237 /* Describes a file mentioned in the block graph. Contains an array
240 typedef struct source_info
242 /* Canonical name of source file. */
246 /* Array of line information. */
252 /* Functions in this source file. These are in ascending line
254 function_t
*functions
;
257 typedef struct name_map
259 char *name
; /* Source file name */
260 unsigned src
; /* Source file */
263 /* Holds a list of function basic block graphs. */
265 static function_t
*functions
;
266 static function_t
**fn_end
= &functions
;
268 static source_t
*sources
; /* Array of source files */
269 static unsigned n_sources
; /* Number of sources */
270 static unsigned a_sources
; /* Allocated sources */
272 static name_map_t
*names
; /* Mapping of file names to sources */
273 static unsigned n_names
; /* Number of names */
274 static unsigned a_names
; /* Allocated names */
276 /* This holds data summary information. */
278 static unsigned object_runs
;
279 static unsigned program_count
;
281 /* Modification time of graph file. */
283 static time_t bbg_file_time
;
285 /* Name and file pointer of the input file for the basic block graph. */
287 static char *bbg_file_name
;
289 /* Stamp of the bbg file */
290 static unsigned bbg_stamp
;
292 /* Name and file pointer of the input file for the arc count data. */
294 static char *da_file_name
;
296 /* Data file is missing. */
298 static int no_data_file
;
300 /* If there is several input files, compute and display results after
301 reading all data files. This way if two or more gcda file refer to
302 the same source file (eg inline subprograms in a .h file), the
305 static int multiple_files
= 0;
307 /* Output branch probabilities. */
309 static int flag_branches
= 0;
311 /* Show unconditional branches too. */
312 static int flag_unconditional
= 0;
314 /* Output a gcov file if this is true. This is on by default, and can
315 be turned off by the -n option. */
317 static int flag_gcov_file
= 1;
319 /* Output progress indication if this is true. This is off by default
320 and can be turned on by the -d option. */
322 static int flag_display_progress
= 0;
324 /* For included files, make the gcov output file name include the name
325 of the input source file. For example, if x.h is included in a.c,
326 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
328 static int flag_long_names
= 0;
330 /* Output count information for every basic block, not merely those
331 that contain line number information. */
333 static int flag_all_blocks
= 0;
335 /* Output summary info for each function. */
337 static int flag_function_summary
= 0;
339 /* Object directory file prefix. This is the directory/file where the
340 graph and data files are looked for, if nonzero. */
342 static char *object_directory
= 0;
344 /* Source directory prefix. This is removed from source pathnames
345 that match, when generating the output file name. */
347 static char *source_prefix
= 0;
348 static size_t source_length
= 0;
350 /* Only show data for sources with relative pathnames. Absolute ones
351 usually indicate a system header file, which although it may
352 contain inline functions, is usually uninteresting. */
353 static int flag_relative_only
= 0;
355 /* Preserve all pathname components. Needed when object files and
356 source files are in subdirectories. '/' is mangled as '#', '.' is
357 elided and '..' mangled to '^'. */
359 static int flag_preserve_paths
= 0;
361 /* Output the number of times a branch was taken as opposed to the percentage
362 of times it was taken. */
364 static int flag_counts
= 0;
366 /* Forward declarations. */
367 static int process_args (int, char **);
368 static void print_usage (int) ATTRIBUTE_NORETURN
;
369 static void print_version (void) ATTRIBUTE_NORETURN
;
370 static void process_file (const char *);
371 static void generate_results (const char *);
372 static void create_file_names (const char *);
373 static int name_search (const void *, const void *);
374 static int name_sort (const void *, const void *);
375 static char *canonicalize_name (const char *);
376 static unsigned find_source (const char *);
377 static function_t
*read_graph_file (void);
378 static int read_count_file (function_t
*);
379 static void solve_flow_graph (function_t
*);
380 static void find_exception_blocks (function_t
*);
381 static void add_branch_counts (coverage_t
*, const arc_t
*);
382 static void add_line_counts (coverage_t
*, function_t
*);
383 static void function_summary (const coverage_t
*, const char *);
384 static const char *format_gcov (gcov_type
, gcov_type
, int);
385 static void accumulate_line_counts (source_t
*);
386 static int output_branch_count (FILE *, int, const arc_t
*);
387 static void output_lines (FILE *, const source_t
*);
388 static char *make_gcov_file_name (const char *, const char *);
389 static char *mangle_name (const char *, char *);
390 static void release_structures (void);
391 static void release_function (function_t
*);
392 extern int main (int, char **);
395 main (int argc
, char **argv
)
401 p
= argv
[0] + strlen (argv
[0]);
402 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
406 xmalloc_set_program_name (progname
);
408 /* Unlock the stdio streams. */
409 unlock_std_streams ();
413 diagnostic_initialize (global_dc
, 0);
415 /* Handle response files. */
416 expandargv (&argc
, &argv
);
419 names
= XNEWVEC (name_map_t
, a_names
);
421 sources
= XNEWVEC (source_t
, a_sources
);
423 argno
= process_args (argc
, argv
);
427 if (argc
- argno
> 1)
432 for (; argno
!= argc
; argno
++)
434 if (flag_display_progress
)
435 printf("Processing file %d out of %d\n",
436 argno
- first_arg
+ 1, argc
- first_arg
);
437 process_file (argv
[argno
]);
440 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
442 release_structures ();
447 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
448 otherwise the output of --help. */
451 print_usage (int error_p
)
453 FILE *file
= error_p
? stderr
: stdout
;
454 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
456 fnotice (file
, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
457 fnotice (file
, "Print code coverage information.\n\n");
458 fnotice (file
, " -h, --help Print this help, then exit\n");
459 fnotice (file
, " -v, --version Print version number, then exit\n");
460 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
461 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
462 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
463 rather than percentages\n");
464 fnotice (file
, " -n, --no-output Do not create an output file\n");
465 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
467 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
468 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
469 fnotice (file
, " -s, --source-prefix DIR Source prefix to elide\n");
470 fnotice (file
, " -r, --relative-only Only show data for relative sources\n");
471 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
472 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
473 fnotice (file
, " -d, --display-progress Display progress information\n");
474 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
479 /* Print version information and exit. */
484 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
485 fprintf (stdout
, "Copyright %s 2011 Free Software Foundation, Inc.\n",
488 _("This is free software; see the source for copying conditions.\n"
489 "There is NO warranty; not even for MERCHANTABILITY or \n"
490 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
491 exit (SUCCESS_EXIT_CODE
);
494 static const struct option options
[] =
496 { "help", no_argument
, NULL
, 'h' },
497 { "version", no_argument
, NULL
, 'v' },
498 { "all-blocks", no_argument
, NULL
, 'a' },
499 { "branch-probabilities", no_argument
, NULL
, 'b' },
500 { "branch-counts", no_argument
, NULL
, 'c' },
501 { "no-output", no_argument
, NULL
, 'n' },
502 { "long-file-names", no_argument
, NULL
, 'l' },
503 { "function-summaries", no_argument
, NULL
, 'f' },
504 { "preserve-paths", no_argument
, NULL
, 'p' },
505 { "relative-only", no_argument
, NULL
, 'r' },
506 { "object-directory", required_argument
, NULL
, 'o' },
507 { "object-file", required_argument
, NULL
, 'o' },
508 { "source-prefix", required_argument
, NULL
, 's' },
509 { "unconditional-branches", no_argument
, NULL
, 'u' },
510 { "display-progress", no_argument
, NULL
, 'd' },
514 /* Process args, return index to first non-arg. */
517 process_args (int argc
, char **argv
)
521 while ((opt
= getopt_long (argc
, argv
, "abcdfhlno:s:pruv", options
, NULL
)) != -1)
535 flag_function_summary
= 1;
539 /* print_usage will exit. */
547 object_directory
= optarg
;
550 source_prefix
= optarg
;
551 source_length
= strlen (source_prefix
);
554 flag_relative_only
= 1;
557 flag_preserve_paths
= 1;
560 flag_unconditional
= 1;
563 flag_display_progress
= 1;
567 /* print_version will exit. */
570 /* print_usage will exit. */
577 /* Process a single input file. */
580 process_file (const char *file_name
)
584 create_file_names (file_name
);
585 fns
= read_graph_file ();
589 read_count_file (fns
);
592 function_t
*fn
= fns
;
598 unsigned src
= fn
->src
;
599 unsigned line
= fn
->line
;
601 function_t
*probe
, **prev
;
603 /* Now insert it into the source file's list of
604 functions. Normally functions will be encountered in
605 ascending order, so a simple scan is quick. Note we're
606 building this list in reverse order. */
607 for (prev
= &sources
[src
].functions
;
608 (probe
= *prev
); prev
= &probe
->line_next
)
609 if (probe
->line
<= line
)
611 fn
->line_next
= probe
;
614 /* Mark last line in files touched by function. */
615 for (block_no
= 0; block_no
!= fn
->num_blocks
; block_no
++)
617 unsigned *enc
= fn
->blocks
[block_no
].u
.line
.encoding
;
618 unsigned num
= fn
->blocks
[block_no
].u
.line
.num
;
625 if (line
>= sources
[src
].num_lines
)
626 sources
[src
].num_lines
= line
+ 1;
633 else if (*enc
> line
)
636 if (line
>= sources
[src
].num_lines
)
637 sources
[src
].num_lines
= line
+ 1;
639 solve_flow_graph (fn
);
641 find_exception_blocks (fn
);
646 /* The function was not in the executable -- some other
647 instance must have been selected. */
648 release_function (fn
);
653 generate_results (const char *file_name
)
659 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
661 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
663 for (fn
= functions
; fn
; fn
= fn
->next
)
667 memset (&coverage
, 0, sizeof (coverage
));
668 coverage
.name
= fn
->name
;
669 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
670 if (flag_function_summary
)
672 function_summary (&coverage
, "Function");
673 fnotice (stdout
, "\n");
679 name_map_t
*name_map
= (name_map_t
*)bsearch
680 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
682 file_name
= sources
[name_map
->src
].coverage
.name
;
684 file_name
= canonicalize_name (file_name
);
687 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
689 if (flag_relative_only
)
691 /* Ignore this source, if it is an absolute path (after
692 source prefix removal). */
693 char first
= src
->coverage
.name
[0];
695 #if HAVE_DOS_BASED_FILE_SYSTEM
696 if (first
&& src
->coverage
.name
[1] == ':')
697 first
= src
->coverage
.name
[2];
699 if (IS_DIR_SEPARATOR (first
))
703 accumulate_line_counts (src
);
704 function_summary (&src
->coverage
, "File");
705 if (flag_gcov_file
&& src
->coverage
.lines
)
708 = make_gcov_file_name (file_name
, src
->coverage
.name
);
709 FILE *gcov_file
= fopen (gcov_file_name
, "w");
713 fnotice (stdout
, "Creating '%s'\n", gcov_file_name
);
714 output_lines (gcov_file
, src
);
715 if (ferror (gcov_file
))
716 fnotice (stderr
, "Error writing output file '%s'\n",
721 fnotice (stderr
, "Could not open output file '%s'\n",
723 free (gcov_file_name
);
725 fnotice (stdout
, "\n");
729 /* Release a function structure */
732 release_function (function_t
*fn
)
737 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
741 for (arc
= block
->succ
; arc
; arc
= arc_n
)
743 arc_n
= arc
->succ_next
;
751 /* Release all memory used. */
754 release_structures (void)
759 for (ix
= n_sources
; ix
--;)
760 free (sources
[ix
].lines
);
763 for (ix
= n_names
; ix
--;)
764 free (names
[ix
].name
);
767 while ((fn
= functions
))
769 functions
= fn
->next
;
770 release_function (fn
);
774 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
775 is not specified, these are named from FILE_NAME sans extension. If
776 OBJECT_DIRECTORY is specified and is a directory, the files are in that
777 directory, but named from the basename of the FILE_NAME, sans extension.
778 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
779 and the data files are named from that. */
782 create_file_names (const char *file_name
)
786 int length
= strlen (file_name
);
789 /* Free previous file names. */
790 free (bbg_file_name
);
792 da_file_name
= bbg_file_name
= NULL
;
796 if (object_directory
&& object_directory
[0])
800 length
+= strlen (object_directory
) + 2;
801 name
= XNEWVEC (char, length
);
804 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
805 strcat (name
, object_directory
);
806 if (base
&& (! IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
811 name
= XNEWVEC (char, length
+ 1);
812 strcpy (name
, file_name
);
818 /* Append source file name. */
819 const char *cptr
= lbasename (file_name
);
820 strcat (name
, cptr
? cptr
: file_name
);
823 /* Remove the extension. */
824 cptr
= strrchr (name
, '.');
828 length
= strlen (name
);
830 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
831 strcpy (bbg_file_name
, name
);
832 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
834 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
835 strcpy (da_file_name
, name
);
836 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
842 /* A is a string and B is a pointer to name_map_t. Compare for file
843 name orderability. */
846 name_search (const void *a_
, const void *b_
)
848 const char *a
= (const char *)a_
;
849 const name_map_t
*b
= (const name_map_t
*)b_
;
851 #if HAVE_DOS_BASED_FILE_SYSTEM
852 return strcasecmp (a
, b
->name
);
854 return strcmp (a
, b
->name
);
858 /* A and B are a pointer to name_map_t. Compare for file name
862 name_sort (const void *a_
, const void *b_
)
864 const name_map_t
*a
= (const name_map_t
*)a_
;
865 return name_search (a
->name
, b_
);
868 /* Find or create a source file structure for FILE_NAME. Copies
869 FILE_NAME on creation */
872 find_source (const char *file_name
)
874 name_map_t
*name_map
;
880 file_name
= "<unknown>";
881 name_map
= (name_map_t
*)bsearch
882 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
889 if (n_names
+ 2 > a_names
)
891 /* Extend the name map array -- we'll be inserting one or two
894 name_map
= XNEWVEC (name_map_t
, a_names
);
895 memcpy (name_map
, names
, n_names
* sizeof (*names
));
900 /* Not found, try the canonical name. */
901 canon
= canonicalize_name (file_name
);
902 name_map
= (name_map_t
*)bsearch
903 (canon
, names
, n_names
, sizeof (*names
), name_search
);
906 /* Not found with canonical name, create a new source. */
909 if (n_sources
== a_sources
)
912 src
= XNEWVEC (source_t
, a_sources
);
913 memcpy (src
, sources
, n_sources
* sizeof (*sources
));
920 name_map
= &names
[n_names
++];
921 name_map
->name
= canon
;
924 src
= &sources
[n_sources
++];
925 memset (src
, 0, sizeof (*src
));
927 src
->coverage
.name
= src
->name
;
929 #if HAVE_DOS_BASED_FILE_SYSTEM
930 /* You lose if separators don't match exactly in the
932 && !strncasecmp (source_prefix
, src
->coverage
.name
, source_length
)
934 && !strncmp (source_prefix
, src
->coverage
.name
, source_length
)
936 && IS_DIR_SEPARATOR (src
->coverage
.name
[source_length
]))
937 src
->coverage
.name
+= source_length
+ 1;
938 if (!stat (src
->name
, &status
))
939 src
->file_time
= status
.st_mtime
;
944 if (name_search (file_name
, name_map
))
946 /* Append the non-canonical name. */
947 name_map
= &names
[n_names
++];
948 name_map
->name
= xstrdup (file_name
);
952 /* Resort the name map. */
953 qsort (names
, n_names
, sizeof (*names
), name_sort
);
956 if (sources
[idx
].file_time
> bbg_file_time
)
958 static int info_emitted
;
960 fnotice (stderr
, "%s:source file is newer than graph file '%s'\n",
961 file_name
, bbg_file_name
);
965 "(the message is only displayed one per source file)\n");
968 sources
[idx
].file_time
= 0;
974 /* Read the graph file. Return list of functions read -- in reverse order. */
977 read_graph_file (void)
980 unsigned current_tag
= 0;
981 function_t
*fn
= NULL
;
982 function_t
*fns
= NULL
;
983 function_t
**fns_end
= &fns
;
984 unsigned src_idx
= 0;
988 if (!gcov_open (bbg_file_name
, 1))
990 fnotice (stderr
, "%s:cannot open graph file\n", bbg_file_name
);
993 bbg_file_time
= gcov_time ();
994 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
996 fnotice (stderr
, "%s:not a gcov graph file\n", bbg_file_name
);
1001 version
= gcov_read_unsigned ();
1002 if (version
!= GCOV_VERSION
)
1006 GCOV_UNSIGNED2STRING (v
, version
);
1007 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1009 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
1010 bbg_file_name
, v
, e
);
1012 bbg_stamp
= gcov_read_unsigned ();
1014 while ((tag
= gcov_read_unsigned ()))
1016 unsigned length
= gcov_read_unsigned ();
1017 gcov_position_t base
= gcov_position ();
1019 if (tag
== GCOV_TAG_FUNCTION
)
1021 char *function_name
;
1022 unsigned ident
, lineno
;
1023 unsigned lineno_checksum
, cfg_checksum
;
1025 ident
= gcov_read_unsigned ();
1026 lineno_checksum
= gcov_read_unsigned ();
1027 cfg_checksum
= gcov_read_unsigned ();
1028 function_name
= xstrdup (gcov_read_string ());
1029 src_idx
= find_source (gcov_read_string ());
1030 lineno
= gcov_read_unsigned ();
1032 fn
= XCNEW (function_t
);
1033 fn
->name
= function_name
;
1035 fn
->lineno_checksum
= lineno_checksum
;
1036 fn
->cfg_checksum
= cfg_checksum
;
1040 fn
->line_next
= NULL
;
1043 fns_end
= &fn
->next
;
1046 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
1049 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
1050 bbg_file_name
, fn
->name
);
1053 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
1054 fn
->num_blocks
= num_blocks
;
1056 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
1057 for (ix
= 0; ix
!= num_blocks
; ix
++)
1058 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
1061 else if (fn
&& tag
== GCOV_TAG_ARCS
)
1063 unsigned src
= gcov_read_unsigned ();
1064 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
1065 block_t
*src_blk
= &fn
->blocks
[src
];
1066 unsigned mark_catches
= 0;
1067 struct arc_info
*arc
;
1069 if (src
>= fn
->num_blocks
|| fn
->blocks
[src
].succ
)
1074 unsigned dest
= gcov_read_unsigned ();
1075 unsigned flags
= gcov_read_unsigned ();
1077 if (dest
>= fn
->num_blocks
)
1079 arc
= XCNEW (arc_t
);
1081 arc
->dst
= &fn
->blocks
[dest
];
1085 arc
->count_valid
= 0;
1086 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
1087 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
1088 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
1090 arc
->succ_next
= src_blk
->succ
;
1091 src_blk
->succ
= arc
;
1092 src_blk
->num_succ
++;
1094 arc
->pred_next
= fn
->blocks
[dest
].pred
;
1095 fn
->blocks
[dest
].pred
= arc
;
1096 fn
->blocks
[dest
].num_pred
++;
1102 /* Exceptional exit from this function, the
1103 source block must be a call. */
1104 fn
->blocks
[src
].is_call_site
= 1;
1105 arc
->is_call_non_return
= 1;
1110 /* Non-local return from a callee of this
1111 function. The destination block is a setjmp. */
1112 arc
->is_nonlocal_return
= 1;
1113 fn
->blocks
[dest
].is_nonlocal_return
= 1;
1123 /* We have a fake exit from this block. The other
1124 non-fall through exits must be to catch handlers.
1125 Mark them as catch arcs. */
1127 for (arc
= src_blk
->succ
; arc
; arc
= arc
->succ_next
)
1128 if (!arc
->fake
&& !arc
->fall_through
)
1135 else if (fn
&& tag
== GCOV_TAG_LINES
)
1137 unsigned blockno
= gcov_read_unsigned ();
1138 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
1140 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
1145 unsigned lineno
= gcov_read_unsigned ();
1152 line_nos
[ix
++] = src_idx
;
1154 line_nos
[ix
++] = lineno
;
1158 const char *file_name
= gcov_read_string ();
1162 src_idx
= find_source (file_name
);
1164 line_nos
[ix
++] = src_idx
;
1168 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
1169 fn
->blocks
[blockno
].u
.line
.num
= ix
;
1171 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
1176 gcov_sync (base
, length
);
1177 if (gcov_is_error ())
1180 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
1187 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
1192 /* Reads profiles from the count file and attach to each
1193 function. Return nonzero if fatal error. */
1196 read_count_file (function_t
*fns
)
1201 function_t
*fn
= NULL
;
1204 if (!gcov_open (da_file_name
, 1))
1206 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1211 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1213 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1218 version
= gcov_read_unsigned ();
1219 if (version
!= GCOV_VERSION
)
1223 GCOV_UNSIGNED2STRING (v
, version
);
1224 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1226 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1227 da_file_name
, v
, e
);
1229 tag
= gcov_read_unsigned ();
1230 if (tag
!= bbg_stamp
)
1232 fnotice (stderr
, "%s:stamp mismatch with graph file\n", da_file_name
);
1236 while ((tag
= gcov_read_unsigned ()))
1238 unsigned length
= gcov_read_unsigned ();
1239 unsigned long base
= gcov_position ();
1241 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1243 struct gcov_summary summary
;
1244 gcov_read_summary (&summary
);
1245 object_runs
+= summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
;
1248 else if (tag
== GCOV_TAG_FUNCTION
&& !length
)
1250 else if (tag
== GCOV_TAG_FUNCTION
&& length
== GCOV_TAG_FUNCTION_LENGTH
)
1253 struct function_info
*fn_n
;
1255 /* Try to find the function in the list. To speed up the
1256 search, first start from the last function found. */
1257 ident
= gcov_read_unsigned ();
1259 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1263 else if ((fn
= fn_n
))
1267 fnotice (stderr
, "%s:unknown function '%u'\n",
1268 da_file_name
, ident
);
1271 if (fn
->ident
== ident
)
1277 else if (gcov_read_unsigned () != fn
->lineno_checksum
1278 || gcov_read_unsigned () != fn
->cfg_checksum
)
1281 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1282 da_file_name
, fn
->name
);
1286 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1288 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1292 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1294 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1295 fn
->counts
[ix
] += gcov_read_counter ();
1297 gcov_sync (base
, length
);
1298 if ((error
= gcov_is_error ()))
1300 fnotice (stderr
, error
< 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1310 /* Solve the flow graph. Propagate counts from the instrumented arcs
1311 to the blocks and the uninstrumented arcs. */
1314 solve_flow_graph (function_t
*fn
)
1318 gcov_type
*count_ptr
= fn
->counts
;
1320 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1321 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1323 /* The arcs were built in reverse order. Fix that now. */
1324 for (ix
= fn
->num_blocks
; ix
--;)
1326 arc_t
*arc_p
, *arc_n
;
1328 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1329 arc_p
= arc
, arc
= arc_n
)
1331 arc_n
= arc
->succ_next
;
1332 arc
->succ_next
= arc_p
;
1334 fn
->blocks
[ix
].succ
= arc_p
;
1336 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1337 arc_p
= arc
, arc
= arc_n
)
1339 arc_n
= arc
->pred_next
;
1340 arc
->pred_next
= arc_p
;
1342 fn
->blocks
[ix
].pred
= arc_p
;
1345 if (fn
->num_blocks
< 2)
1346 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1347 bbg_file_name
, fn
->name
);
1350 if (fn
->blocks
[0].num_pred
)
1351 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1352 bbg_file_name
, fn
->name
);
1354 /* We can't deduce the entry block counts from the lack of
1356 fn
->blocks
[0].num_pred
= ~(unsigned)0;
1358 if (fn
->blocks
[fn
->num_blocks
- 1].num_succ
)
1359 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1360 bbg_file_name
, fn
->name
);
1362 /* Likewise, we can't deduce exit block counts from the lack
1363 of its successors. */
1364 fn
->blocks
[fn
->num_blocks
- 1].num_succ
= ~(unsigned)0;
1367 /* Propagate the measured counts, this must be done in the same
1368 order as the code in profile.c */
1369 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1371 block_t
const *prev_dst
= NULL
;
1372 int out_of_order
= 0;
1373 int non_fake_succ
= 0;
1375 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1383 arc
->count
= *count_ptr
++;
1384 arc
->count_valid
= 1;
1386 arc
->dst
->num_pred
--;
1388 if (prev_dst
&& prev_dst
> arc
->dst
)
1390 prev_dst
= arc
->dst
;
1392 if (non_fake_succ
== 1)
1394 /* If there is only one non-fake exit, it is an
1395 unconditional branch. */
1396 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1399 arc
->is_unconditional
= 1;
1400 /* If this block is instrumenting a call, it might be
1401 an artificial block. It is not artificial if it has
1402 a non-fallthrough exit, or the destination of this
1403 arc has more than one entry. Mark the destination
1404 block as a return site, if none of those conditions
1406 if (blk
->is_call_site
&& arc
->fall_through
1407 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1408 arc
->dst
->is_call_return
= 1;
1412 /* Sort the successor arcs into ascending dst order. profile.c
1413 normally produces arcs in the right order, but sometimes with
1414 one or two out of order. We're not using a particularly
1418 arc_t
*start
= blk
->succ
;
1419 unsigned changes
= 1;
1423 arc_t
*arc
, *arc_p
, *arc_n
;
1426 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1428 if (arc
->dst
> arc_n
->dst
)
1432 arc_p
->succ_next
= arc_n
;
1435 arc
->succ_next
= arc_n
->succ_next
;
1436 arc_n
->succ_next
= arc
;
1449 /* Place it on the invalid chain, it will be ignored if that's
1451 blk
->invalid_chain
= 1;
1452 blk
->chain
= invalid_blocks
;
1453 invalid_blocks
= blk
;
1456 while (invalid_blocks
|| valid_blocks
)
1458 while ((blk
= invalid_blocks
))
1460 gcov_type total
= 0;
1463 invalid_blocks
= blk
->chain
;
1464 blk
->invalid_chain
= 0;
1466 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1467 total
+= arc
->count
;
1468 else if (!blk
->num_pred
)
1469 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1470 total
+= arc
->count
;
1475 blk
->count_valid
= 1;
1476 blk
->chain
= valid_blocks
;
1477 blk
->valid_chain
= 1;
1480 while ((blk
= valid_blocks
))
1483 arc_t
*arc
, *inv_arc
;
1485 valid_blocks
= blk
->chain
;
1486 blk
->valid_chain
= 0;
1487 if (blk
->num_succ
== 1)
1493 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1495 total
-= arc
->count
;
1496 if (!arc
->count_valid
)
1500 inv_arc
->count_valid
= 1;
1501 inv_arc
->count
= total
;
1504 if (dst
->count_valid
)
1506 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1508 dst
->chain
= valid_blocks
;
1509 dst
->valid_chain
= 1;
1515 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1517 dst
->chain
= invalid_blocks
;
1518 dst
->invalid_chain
= 1;
1519 invalid_blocks
= dst
;
1523 if (blk
->num_pred
== 1)
1529 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1531 total
-= arc
->count
;
1532 if (!arc
->count_valid
)
1536 inv_arc
->count_valid
= 1;
1537 inv_arc
->count
= total
;
1540 if (src
->count_valid
)
1542 if (src
->num_succ
== 1 && !src
->valid_chain
)
1544 src
->chain
= valid_blocks
;
1545 src
->valid_chain
= 1;
1551 if (!src
->num_succ
&& !src
->invalid_chain
)
1553 src
->chain
= invalid_blocks
;
1554 src
->invalid_chain
= 1;
1555 invalid_blocks
= src
;
1562 /* If the graph has been correctly solved, every block will have a
1564 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1565 if (!fn
->blocks
[ix
].count_valid
)
1567 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1568 bbg_file_name
, fn
->name
);
1573 /* Mark all the blocks only reachable via an incoming catch. */
1576 find_exception_blocks (function_t
*fn
)
1579 block_t
**queue
= XALLOCAVEC (block_t
*, fn
->num_blocks
);
1581 /* First mark all blocks as exceptional. */
1582 for (ix
= fn
->num_blocks
; ix
--;)
1583 fn
->blocks
[ix
].exceptional
= 1;
1585 /* Now mark all the blocks reachable via non-fake edges */
1586 queue
[0] = fn
->blocks
;
1587 queue
[0]->exceptional
= 0;
1590 block_t
*block
= queue
[--ix
];
1593 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1594 if (!arc
->fake
&& !arc
->is_throw
&& arc
->dst
->exceptional
)
1596 arc
->dst
->exceptional
= 0;
1597 queue
[ix
++] = arc
->dst
;
1603 /* Increment totals in COVERAGE according to arc ARC. */
1606 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1608 if (arc
->is_call_non_return
)
1611 if (arc
->src
->count
)
1612 coverage
->calls_executed
++;
1614 else if (!arc
->is_unconditional
)
1616 coverage
->branches
++;
1617 if (arc
->src
->count
)
1618 coverage
->branches_executed
++;
1620 coverage
->branches_taken
++;
1624 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1625 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1626 If DP is zero, no decimal point is printed. Only print 100% when
1627 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1628 format TOP. Return pointer to a static string. */
1631 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1633 static char buffer
[20];
1637 float ratio
= bottom
? (float)top
/ bottom
: 0;
1639 unsigned limit
= 100;
1642 for (ix
= dp
; ix
--; )
1645 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1646 if (percent
<= 0 && top
)
1648 else if (percent
>= limit
&& top
!= bottom
)
1649 percent
= limit
- 1;
1650 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1656 buffer
[ix
+1] = buffer
[ix
];
1660 buffer
[ix
+ 1] = '.';
1664 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)top
);
1670 /* Output summary info for a function. */
1673 function_summary (const coverage_t
*coverage
, const char *title
)
1675 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
1677 if (coverage
->lines
)
1678 fnotice (stdout
, "Lines executed:%s of %d\n",
1679 format_gcov (coverage
->lines_executed
, coverage
->lines
, 2),
1682 fnotice (stdout
, "No executable lines\n");
1686 if (coverage
->branches
)
1688 fnotice (stdout
, "Branches executed:%s of %d\n",
1689 format_gcov (coverage
->branches_executed
,
1690 coverage
->branches
, 2),
1691 coverage
->branches
);
1692 fnotice (stdout
, "Taken at least once:%s of %d\n",
1693 format_gcov (coverage
->branches_taken
,
1694 coverage
->branches
, 2),
1695 coverage
->branches
);
1698 fnotice (stdout
, "No branches\n");
1699 if (coverage
->calls
)
1700 fnotice (stdout
, "Calls executed:%s of %d\n",
1701 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
1704 fnotice (stdout
, "No calls\n");
1708 /* Canonicalize the filename NAME by canonicalizing directory
1709 separators, eliding . components and resolving .. components
1710 appropriately. Always returns a unique string. */
1713 canonicalize_name (const char *name
)
1715 /* The canonical name cannot be longer than the incoming name. */
1716 char *result
= XNEWVEC (char, strlen (name
) + 1);
1717 const char *base
= name
, *probe
;
1722 #if HAVE_DOS_BASED_FILE_SYSTEM
1723 if (base
[0] && base
[1] == ':')
1725 result
[0] = base
[0];
1731 for (dd_base
= ptr
; *base
; base
= probe
)
1735 for (probe
= base
; *probe
; probe
++)
1736 if (IS_DIR_SEPARATOR (*probe
))
1740 if (len
== 1 && base
[0] == '.')
1741 /* Elide a '.' directory */
1743 else if (len
== 2 && base
[0] == '.' && base
[1] == '.')
1745 /* '..', we can only elide it and the previous directory, if
1746 we're not a symlink. */
1747 struct stat ATTRIBUTE_UNUSED buf
;
1751 #if defined (S_ISLNK)
1752 /* S_ISLNK is not POSIX.1-1996. */
1753 || stat (result
, &buf
) || S_ISLNK (buf
.st_mode
)
1757 /* Cannot elide, or unreadable or a symlink. */
1758 dd_base
= ptr
+ 2 + slash
;
1761 while (ptr
!= dd_base
&& *ptr
!= '/')
1763 slash
= ptr
!= result
;
1768 /* Regular pathname component. */
1771 memcpy (ptr
, base
, len
);
1776 for (; IS_DIR_SEPARATOR (*probe
); probe
++)
1784 /* Generate an output file name. INPUT_NAME is the canonicalized main
1785 input file and SRC_NAME is the canonicalized file name.
1786 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
1787 long_output_names we prepend the processed name of the input file
1788 to each output name (except when the current source file is the
1789 input file, so you don't get a double concatenation). The two
1790 components are separated by '##'. With preserve_paths we create a
1791 filename from all path components of the source file, replacing '/'
1792 with '#', and .. with '^', without it we simply take the basename
1793 component. (Remember, the canonicalized name will already have
1794 elided '.' components and converted \\ separators.) */
1797 make_gcov_file_name (const char *input_name
, const char *src_name
)
1802 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
1804 /* Generate the input filename part. */
1805 result
= XNEWVEC (char, strlen (input_name
) + strlen (src_name
) + 10);
1808 ptr
= mangle_name (input_name
, ptr
);
1809 ptr
[0] = ptr
[1] = '#';
1814 result
= XNEWVEC (char, strlen (src_name
) + 10);
1818 ptr
= mangle_name (src_name
, ptr
);
1819 strcpy (ptr
, ".gcov");
1825 mangle_name (char const *base
, char *ptr
)
1829 /* Generate the source filename part. */
1830 if (!flag_preserve_paths
)
1832 base
= lbasename (base
);
1833 len
= strlen (base
);
1834 memcpy (ptr
, base
, len
);
1839 /* Convert '/' to '#', convert '..' to '^',
1840 convert ':' to '~' on DOS based file system. */
1843 #if HAVE_DOS_BASED_FILE_SYSTEM
1844 if (base
[0] && base
[1] == ':')
1852 for (; *base
; base
= probe
)
1856 for (probe
= base
; *probe
; probe
++)
1860 if (len
== 2 && base
[0] == '.' && base
[1] == '.')
1864 memcpy (ptr
, base
, len
);
1878 /* Scan through the bb_data for each line in the block, increment
1879 the line number execution count indicated by the execution count of
1880 the appropriate basic block. */
1883 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
1886 line_t
*line
= NULL
; /* This is propagated from one iteration to the
1889 /* Scan each basic block. */
1890 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
1892 block_t
*block
= &fn
->blocks
[ix
];
1894 const source_t
*src
= NULL
;
1897 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
1898 fn
->blocks_executed
++;
1899 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
1900 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
1903 src
= &sources
[*++encoding
];
1908 line
= &src
->lines
[*encoding
];
1914 if (!line
->count
&& block
->count
)
1915 coverage
->lines_executed
++;
1918 if (!block
->exceptional
)
1919 line
->unexceptional
= 1;
1920 line
->count
+= block
->count
;
1922 free (block
->u
.line
.encoding
);
1923 block
->u
.cycle
.arc
= NULL
;
1924 block
->u
.cycle
.ident
= ~0U;
1926 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
1927 /* Entry or exit block */;
1928 else if (flag_all_blocks
)
1930 line_t
*block_line
= line
;
1933 block_line
= &sources
[fn
->src
].lines
[fn
->line
];
1935 block
->chain
= block_line
->u
.blocks
;
1936 block_line
->u
.blocks
= block
;
1938 else if (flag_branches
)
1942 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1944 arc
->line_next
= line
->u
.branches
;
1945 line
->u
.branches
= arc
;
1946 if (coverage
&& !arc
->is_unconditional
)
1947 add_branch_counts (coverage
, arc
);
1952 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
1955 /* Accumulate the line counts of a file. */
1958 accumulate_line_counts (source_t
*src
)
1961 function_t
*fn
, *fn_p
, *fn_n
;
1964 /* Reverse the function order. */
1965 for (fn
= src
->functions
, fn_p
= NULL
; fn
;
1966 fn_p
= fn
, fn
= fn_n
)
1968 fn_n
= fn
->line_next
;
1969 fn
->line_next
= fn_p
;
1971 src
->functions
= fn_p
;
1973 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
1975 if (!flag_all_blocks
)
1977 arc_t
*arc
, *arc_p
, *arc_n
;
1979 /* Total and reverse the branch information. */
1980 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
1981 arc_p
= arc
, arc
= arc_n
)
1983 arc_n
= arc
->line_next
;
1984 arc
->line_next
= arc_p
;
1986 add_branch_counts (&src
->coverage
, arc
);
1988 line
->u
.branches
= arc_p
;
1990 else if (line
->u
.blocks
)
1992 /* The user expects the line count to be the number of times
1993 a line has been executed. Simply summing the block count
1994 will give an artificially high number. The Right Thing
1995 is to sum the entry counts to the graph of blocks on this
1996 line, then find the elementary cycles of the local graph
1997 and add the transition counts of those cycles. */
1998 block_t
*block
, *block_p
, *block_n
;
1999 gcov_type count
= 0;
2001 /* Reverse the block information. */
2002 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
2003 block_p
= block
, block
= block_n
)
2005 block_n
= block
->chain
;
2006 block
->chain
= block_p
;
2007 block
->u
.cycle
.ident
= ix
;
2009 line
->u
.blocks
= block_p
;
2011 /* Sum the entry arcs. */
2012 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
2016 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2018 if (arc
->src
->u
.cycle
.ident
!= ix
)
2019 count
+= arc
->count
;
2021 add_branch_counts (&src
->coverage
, arc
);
2024 /* Initialize the cs_count. */
2025 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2026 arc
->cs_count
= arc
->count
;
2029 /* Find the loops. This uses the algorithm described in
2030 Tiernan 'An Efficient Search Algorithm to Find the
2031 Elementary Circuits of a Graph', CACM Dec 1970. We hold
2032 the P array by having each block point to the arc that
2033 connects to the previous block. The H array is implicitly
2034 held because of the arc ordering, and the block's
2035 previous arc pointer.
2037 Although the algorithm is O(N^3) for highly connected
2038 graphs, at worst we'll have O(N^2), as most blocks have
2039 only one or two exits. Most graphs will be small.
2041 For each loop we find, locate the arc with the smallest
2042 transition count, and add that to the cumulative
2043 count. Decrease flow over the cycle and remove the arc
2044 from consideration. */
2045 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
2047 block_t
*head
= block
;
2055 block_t
*dst
= arc
->dst
;
2056 if (/* Already used that arc. */
2058 /* Not to same graph, or before first vertex. */
2059 || dst
->u
.cycle
.ident
!= ix
2060 /* Already in path. */
2061 || dst
->u
.cycle
.arc
)
2063 arc
= arc
->succ_next
;
2069 /* Found a closing arc. */
2070 gcov_type cycle_count
= arc
->cs_count
;
2071 arc_t
*cycle_arc
= arc
;
2074 /* Locate the smallest arc count of the loop. */
2075 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
2076 dst
= probe_arc
->src
)
2077 if (cycle_count
> probe_arc
->cs_count
)
2079 cycle_count
= probe_arc
->cs_count
;
2080 cycle_arc
= probe_arc
;
2083 count
+= cycle_count
;
2084 cycle_arc
->cycle
= 1;
2086 /* Remove the flow from the cycle. */
2087 arc
->cs_count
-= cycle_count
;
2088 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
2089 dst
= probe_arc
->src
)
2090 probe_arc
->cs_count
-= cycle_count
;
2092 /* Unwind to the cyclic arc. */
2093 while (head
!= cycle_arc
->src
)
2095 arc
= head
->u
.cycle
.arc
;
2096 head
->u
.cycle
.arc
= NULL
;
2100 arc
= arc
->succ_next
;
2104 /* Add new block to chain. */
2105 dst
->u
.cycle
.arc
= arc
;
2109 /* We could not add another vertex to the path. Remove
2110 the last vertex from the list. */
2111 arc
= head
->u
.cycle
.arc
;
2114 /* It was not the first vertex. Move onto next arc. */
2115 head
->u
.cycle
.arc
= NULL
;
2117 arc
= arc
->succ_next
;
2118 goto current_vertex
;
2120 /* Mark this block as unusable. */
2121 block
->u
.cycle
.ident
= ~0U;
2124 line
->count
= count
;
2129 src
->coverage
.lines
++;
2131 src
->coverage
.lines_executed
++;
2136 /* Output information about ARC number IX. Returns nonzero if
2137 anything is output. */
2140 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
2142 if (arc
->is_call_non_return
)
2144 if (arc
->src
->count
)
2146 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
2147 format_gcov (arc
->src
->count
- arc
->count
,
2148 arc
->src
->count
, -flag_counts
));
2151 fnotice (gcov_file
, "call %2d never executed\n", ix
);
2153 else if (!arc
->is_unconditional
)
2155 if (arc
->src
->count
)
2156 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
2157 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
2158 arc
->fall_through
? " (fallthrough)"
2159 : arc
->is_throw
? " (throw)" : "");
2161 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
2163 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
2165 if (arc
->src
->count
)
2166 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
2167 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
2169 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
2177 /* Read in the source file one line at a time, and output that line to
2178 the gcov file preceded by its execution count and other
2182 output_lines (FILE *gcov_file
, const source_t
*src
)
2185 unsigned line_num
; /* current line number. */
2186 const line_t
*line
; /* current line info ptr. */
2187 char string
[STRING_SIZE
]; /* line buffer. */
2188 char const *retval
= ""; /* status of source file reading. */
2189 function_t
*fn
= NULL
;
2191 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->coverage
.name
);
2192 if (!multiple_files
)
2194 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
2195 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
2196 no_data_file
? "-" : da_file_name
);
2197 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0, object_runs
);
2199 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
2201 source_file
= fopen (src
->name
, "r");
2204 fnotice (stderr
, "Cannot open source file %s\n", src
->name
);
2207 else if (src
->file_time
== 0)
2208 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
2211 fn
= src
->functions
;
2213 for (line_num
= 1, line
= &src
->lines
[line_num
];
2214 line_num
< src
->num_lines
; line_num
++, line
++)
2216 for (; fn
&& fn
->line
== line_num
; fn
= fn
->line_next
)
2218 arc_t
*arc
= fn
->blocks
[fn
->num_blocks
- 1].pred
;
2219 gcov_type return_count
= fn
->blocks
[fn
->num_blocks
- 1].count
;
2221 for (; arc
; arc
= arc
->pred_next
)
2223 return_count
-= arc
->count
;
2225 fprintf (gcov_file
, "function %s", fn
->name
);
2226 fprintf (gcov_file
, " called %s",
2227 format_gcov (fn
->blocks
[0].count
, 0, -1));
2228 fprintf (gcov_file
, " returned %s",
2229 format_gcov (return_count
, fn
->blocks
[0].count
, 0));
2230 fprintf (gcov_file
, " blocks executed %s",
2231 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
2232 fprintf (gcov_file
, "\n");
2235 /* For lines which don't exist in the .bb file, print '-' before
2236 the source line. For lines which exist but were never
2237 executed, print '#####' before the source line. Otherwise,
2238 print the execution count before the source line. There are
2239 16 spaces of indentation added before the source line so that
2240 tabs won't be messed up. */
2241 fprintf (gcov_file
, "%9s:%5u:",
2242 !line
->exists
? "-" : line
->count
2243 ? format_gcov (line
->count
, 0, -1)
2244 : line
->unexceptional
? "#####" : "=====", line_num
);
2248 /* Copy source line. */
2251 retval
= fgets (string
, STRING_SIZE
, source_file
);
2254 fputs (retval
, gcov_file
);
2256 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
2259 fputs ("/*EOF*/\n", gcov_file
);
2261 if (flag_all_blocks
)
2267 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
2268 block
= block
->chain
)
2270 if (!block
->is_call_return
)
2271 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
2272 !line
->exists
? "-" : block
->count
2273 ? format_gcov (block
->count
, 0, -1)
2274 : block
->exceptional
? "%%%%%" : "$$$$$",
2277 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2278 jx
+= output_branch_count (gcov_file
, jx
, arc
);
2281 else if (flag_branches
)
2286 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
2287 ix
+= output_branch_count (gcov_file
, ix
, arc
);
2291 /* Handle all remaining source lines. There may be lines after the
2292 last line of code. */
2295 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
2297 fprintf (gcov_file
, "%9s:%5u:%s", "-", line_num
, retval
);
2299 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
2301 retval
= fgets (string
, STRING_SIZE
, source_file
);
2304 fputs (retval
, gcov_file
);
2310 fclose (source_file
);