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 is for a function that abnormally returns. */
92 unsigned int is_call_non_return
: 1;
94 /* Arc is for catch/setjmp. */
95 unsigned int is_nonlocal_return
: 1;
97 /* Is an unconditional branch. */
98 unsigned int is_unconditional
: 1;
100 /* Loop making arc. */
101 unsigned int cycle
: 1;
103 /* Next branch on line. */
104 struct arc_info
*line_next
;
106 /* Links to next arc on src and dst lists. */
107 struct arc_info
*succ_next
;
108 struct arc_info
*pred_next
;
111 /* Describes a basic block. Contains lists of arcs to successor and
112 predecessor blocks. */
114 typedef struct block_info
116 /* Chain of exit and entry arcs. */
120 /* Number of unprocessed exit and entry arcs. */
124 /* Block execution count. */
127 unsigned count_valid
: 1;
128 unsigned valid_chain
: 1;
129 unsigned invalid_chain
: 1;
131 /* Block is a call instrumenting site. */
132 unsigned is_call_site
: 1; /* Does the call. */
133 unsigned is_call_return
: 1; /* Is the return. */
135 /* Block is a landing pad for longjmp or throw. */
136 unsigned is_nonlocal_return
: 1;
142 /* Array of line numbers and source files. source files are
143 introduced by a linenumber of zero, the next 'line number' is
144 the number of the source file. Always starts with a source
148 } line
; /* Valid until blocks are linked onto lines */
151 /* Single line graph cycle workspace. Used for all-blocks
155 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
159 /* Temporary chain for solving graph, and for chaining blocks on one
161 struct block_info
*chain
;
165 /* Describes a single function. Contains an array of basic blocks. */
167 typedef struct function_info
169 /* Name of function. */
172 unsigned lineno_checksum
;
173 unsigned cfg_checksum
;
175 /* Array of basic blocks. */
178 unsigned blocks_executed
;
180 /* Raw arc coverage counts. */
184 /* First line number & file. */
188 /* Next function in same source file. */
189 struct function_info
*line_next
;
192 struct function_info
*next
;
195 /* Describes coverage of a file or function. */
197 typedef struct coverage_info
203 int branches_executed
;
212 /* Describes a single line of source. Contains a chain of basic blocks
215 typedef struct line_info
217 gcov_type count
; /* execution count */
220 arc_t
*branches
; /* branches from blocks that end on this
221 line. Used for branch-counts when not
223 block_t
*blocks
; /* blocks which start on this line. Used
224 in all-blocks mode. */
229 /* Describes a file mentioned in the block graph. Contains an array
232 typedef struct source_info
234 /* Canonical name of source file. */
238 /* Array of line information. */
244 /* Functions in this source file. These are in ascending line
246 function_t
*functions
;
249 typedef struct name_map
251 char *name
; /* Source file name */
252 unsigned src
; /* Source file */
255 /* Holds a list of function basic block graphs. */
257 static function_t
*functions
;
258 static function_t
**fn_end
= &functions
;
260 static source_t
*sources
; /* Array of source files */
261 static unsigned n_sources
; /* Number of sources */
262 static unsigned a_sources
; /* Allocated sources */
264 static name_map_t
*names
; /* Mapping of file names to sources */
265 static unsigned n_names
; /* Number of names */
266 static unsigned a_names
; /* Allocated names */
268 /* This holds data summary information. */
270 static unsigned object_runs
;
271 static unsigned program_count
;
273 /* Modification time of graph file. */
275 static time_t bbg_file_time
;
277 /* Name and file pointer of the input file for the basic block graph. */
279 static char *bbg_file_name
;
281 /* Stamp of the bbg file */
282 static unsigned bbg_stamp
;
284 /* Name and file pointer of the input file for the arc count data. */
286 static char *da_file_name
;
288 /* Data file is missing. */
290 static int no_data_file
;
292 /* If there is several input files, compute and display results after
293 reading all data files. This way if two or more gcda file refer to
294 the same source file (eg inline subprograms in a .h file), the
297 static int multiple_files
= 0;
299 /* Output branch probabilities. */
301 static int flag_branches
= 0;
303 /* Show unconditional branches too. */
304 static int flag_unconditional
= 0;
306 /* Output a gcov file if this is true. This is on by default, and can
307 be turned off by the -n option. */
309 static int flag_gcov_file
= 1;
311 /* Output progress indication if this is true. This is off by default
312 and can be turned on by the -d option. */
314 static int flag_display_progress
= 0;
316 /* For included files, make the gcov output file name include the name
317 of the input source file. For example, if x.h is included in a.c,
318 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
320 static int flag_long_names
= 0;
322 /* Output count information for every basic block, not merely those
323 that contain line number information. */
325 static int flag_all_blocks
= 0;
327 /* Output summary info for each function. */
329 static int flag_function_summary
= 0;
331 /* Object directory file prefix. This is the directory/file where the
332 graph and data files are looked for, if nonzero. */
334 static char *object_directory
= 0;
336 /* Preserve all pathname components. Needed when object files and
337 source files are in subdirectories. '/' is mangled as '#', '.' is
338 elided and '..' mangled to '^'. */
340 static int flag_preserve_paths
= 0;
342 /* Output the number of times a branch was taken as opposed to the percentage
343 of times it was taken. */
345 static int flag_counts
= 0;
347 /* Forward declarations. */
348 static int process_args (int, char **);
349 static void print_usage (int) ATTRIBUTE_NORETURN
;
350 static void print_version (void) ATTRIBUTE_NORETURN
;
351 static void process_file (const char *);
352 static void generate_results (const char *);
353 static void create_file_names (const char *);
354 static int name_search (const void *, const void *);
355 static int name_sort (const void *, const void *);
356 static char *canonicalize_name (const char *);
357 static unsigned find_source (const char *);
358 static function_t
*read_graph_file (void);
359 static int read_count_file (function_t
*);
360 static void solve_flow_graph (function_t
*);
361 static void add_branch_counts (coverage_t
*, const arc_t
*);
362 static void add_line_counts (coverage_t
*, function_t
*);
363 static void function_summary (const coverage_t
*, const char *);
364 static const char *format_gcov (gcov_type
, gcov_type
, int);
365 static void accumulate_line_counts (source_t
*);
366 static int output_branch_count (FILE *, int, const arc_t
*);
367 static void output_lines (FILE *, const source_t
*);
368 static char *make_gcov_file_name (const char *, const char *);
369 static char *mangle_name (const char *, char *);
370 static void release_structures (void);
371 static void release_function (function_t
*);
372 extern int main (int, char **);
375 main (int argc
, char **argv
)
381 p
= argv
[0] + strlen (argv
[0]);
382 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
386 xmalloc_set_program_name (progname
);
388 /* Unlock the stdio streams. */
389 unlock_std_streams ();
393 diagnostic_initialize (global_dc
, 0);
395 /* Handle response files. */
396 expandargv (&argc
, &argv
);
398 argno
= process_args (argc
, argv
);
402 if (argc
- argno
> 1)
407 for (; argno
!= argc
; argno
++)
409 if (flag_display_progress
)
410 printf("Processing file %d out of %d\n",
411 argno
- first_arg
+ 1, argc
- first_arg
);
412 process_file (argv
[argno
]);
415 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
417 release_structures ();
422 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
423 otherwise the output of --help. */
426 print_usage (int error_p
)
428 FILE *file
= error_p
? stderr
: stdout
;
429 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
431 fnotice (file
, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
432 fnotice (file
, "Print code coverage information.\n\n");
433 fnotice (file
, " -h, --help Print this help, then exit\n");
434 fnotice (file
, " -v, --version Print version number, then exit\n");
435 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
436 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
437 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
438 rather than percentages\n");
439 fnotice (file
, " -n, --no-output Do not create an output file\n");
440 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
442 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
443 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
444 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
445 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
446 fnotice (file
, " -d, --display-progress Display progress information\n");
447 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
452 /* Print version information and exit. */
457 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
458 fprintf (stdout
, "Copyright %s 2011 Free Software Foundation, Inc.\n",
461 _("This is free software; see the source for copying conditions.\n"
462 "There is NO warranty; not even for MERCHANTABILITY or \n"
463 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
464 exit (SUCCESS_EXIT_CODE
);
467 static const struct option options
[] =
469 { "help", no_argument
, NULL
, 'h' },
470 { "version", no_argument
, NULL
, 'v' },
471 { "all-blocks", no_argument
, NULL
, 'a' },
472 { "branch-probabilities", no_argument
, NULL
, 'b' },
473 { "branch-counts", no_argument
, NULL
, 'c' },
474 { "no-output", no_argument
, NULL
, 'n' },
475 { "long-file-names", no_argument
, NULL
, 'l' },
476 { "function-summaries", no_argument
, NULL
, 'f' },
477 { "preserve-paths", no_argument
, NULL
, 'p' },
478 { "object-directory", required_argument
, NULL
, 'o' },
479 { "object-file", required_argument
, NULL
, 'o' },
480 { "unconditional-branches", no_argument
, NULL
, 'u' },
481 { "display-progress", no_argument
, NULL
, 'd' },
485 /* Process args, return index to first non-arg. */
488 process_args (int argc
, char **argv
)
492 while ((opt
= getopt_long (argc
, argv
, "abcdfhlno:puv", options
, NULL
)) != -1)
506 flag_function_summary
= 1;
510 /* print_usage will exit. */
518 object_directory
= optarg
;
521 flag_preserve_paths
= 1;
524 flag_unconditional
= 1;
527 flag_display_progress
= 1;
531 /* print_version will exit. */
534 /* print_usage will exit. */
541 /* Process a single input file. */
544 process_file (const char *file_name
)
548 create_file_names (file_name
);
549 fns
= read_graph_file ();
553 read_count_file (fns
);
556 function_t
*fn
= fns
;
562 unsigned src
= fn
->src
;
563 unsigned line
= fn
->line
;
565 function_t
*probe
, **prev
;
567 /* Now insert it into the source file's list of
568 functions. Normally functions will be encountered in
569 ascending order, so a simple scan is quick. Note we're
570 building this list in reverse order. */
571 for (prev
= &sources
[src
].functions
;
572 (probe
= *prev
); prev
= &probe
->line_next
)
573 if (probe
->line
<= line
)
575 fn
->line_next
= probe
;
578 /* Mark last line in files touched by function. */
579 for (block_no
= 0; block_no
!= fn
->num_blocks
; block_no
++)
581 unsigned *enc
= fn
->blocks
[block_no
].u
.line
.encoding
;
582 unsigned num
= fn
->blocks
[block_no
].u
.line
.num
;
589 if (line
>= sources
[src
].num_lines
)
590 sources
[src
].num_lines
= line
+ 1;
597 else if (*enc
> line
)
600 if (line
>= sources
[src
].num_lines
)
601 sources
[src
].num_lines
= line
+ 1;
603 solve_flow_graph (fn
);
608 /* The function was not in the executable -- some other
609 instance must have been selected. */
610 release_function (fn
);
615 generate_results (const char *file_name
)
621 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
623 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
625 for (fn
= functions
; fn
; fn
= fn
->next
)
629 memset (&coverage
, 0, sizeof (coverage
));
630 coverage
.name
= fn
->name
;
631 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
632 if (flag_function_summary
)
634 function_summary (&coverage
, "Function");
635 fnotice (stdout
, "\n");
641 name_map_t
*name_map
= (name_map_t
*)bsearch
642 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
644 file_name
= sources
[name_map
->src
].name
;
646 file_name
= canonicalize_name (file_name
);
649 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
651 accumulate_line_counts (src
);
652 function_summary (&src
->coverage
, "File");
653 if (flag_gcov_file
&& src
->coverage
.lines
)
655 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->name
);
656 FILE *gcov_file
= fopen (gcov_file_name
, "w");
660 fnotice (stdout
, "%s:creating '%s'\n",
661 src
->name
, gcov_file_name
);
662 output_lines (gcov_file
, src
);
663 if (ferror (gcov_file
))
664 fnotice (stderr
, "%s:error writing output file '%s'\n",
665 src
->name
, gcov_file_name
);
669 fnotice (stderr
, "%s:could not open output file '%s'\n",
670 src
->name
, gcov_file_name
);
671 free (gcov_file_name
);
673 fnotice (stdout
, "\n");
677 /* Release a function structure */
680 release_function (function_t
*fn
)
685 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
689 for (arc
= block
->succ
; arc
; arc
= arc_n
)
691 arc_n
= arc
->succ_next
;
699 /* Release all memory used. */
702 release_structures (void)
707 for (ix
= n_sources
; ix
--;)
708 free (sources
[ix
].lines
);
711 for (ix
= n_names
; ix
--;)
712 free (names
[ix
].name
);
715 while ((fn
= functions
))
717 functions
= fn
->next
;
718 release_function (fn
);
722 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
723 is not specified, these are named from FILE_NAME sans extension. If
724 OBJECT_DIRECTORY is specified and is a directory, the files are in that
725 directory, but named from the basename of the FILE_NAME, sans extension.
726 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
727 and the data files are named from that. */
730 create_file_names (const char *file_name
)
734 int length
= strlen (file_name
);
737 /* Free previous file names. */
738 free (bbg_file_name
);
740 da_file_name
= bbg_file_name
= NULL
;
744 if (object_directory
&& object_directory
[0])
748 length
+= strlen (object_directory
) + 2;
749 name
= XNEWVEC (char, length
);
752 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
753 strcat (name
, object_directory
);
754 if (base
&& (! IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
759 name
= XNEWVEC (char, length
+ 1);
760 strcpy (name
, file_name
);
766 /* Append source file name. */
767 const char *cptr
= lbasename (file_name
);
768 strcat (name
, cptr
? cptr
: file_name
);
771 /* Remove the extension. */
772 cptr
= strrchr (name
, '.');
776 length
= strlen (name
);
778 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
779 strcpy (bbg_file_name
, name
);
780 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
782 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
783 strcpy (da_file_name
, name
);
784 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
790 /* A is a string and B is a pointer to name_map_t. Compare for file
791 name orderability. */
794 name_search (const void *a_
, const void *b_
)
796 const char *a
= (const char *)a_
;
797 const name_map_t
*b
= (const name_map_t
*)b_
;
799 #if HAVE_DOS_BASED_FILE_SYSTEM
800 return strcasecmp (a
, b
->name
);
802 return strcmp (a
, b
->name
);
806 /* A and B are a pointer to name_map_t. Compare for file name
810 name_sort (const void *a_
, const void *b_
)
812 const name_map_t
*a
= (const name_map_t
*)a_
;
813 return name_search (a
->name
, b_
);
816 /* Find or create a source file structure for FILE_NAME. Copies
817 FILE_NAME on creation */
820 find_source (const char *file_name
)
822 name_map_t
*name_map
;
828 file_name
= "<unknown>";
829 name_map
= (name_map_t
*)bsearch
830 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
837 if (n_names
+ 2 > a_names
)
839 /* Extend the name map array -- we'll be inserting one or two
844 name_map
= XNEWVEC (name_map_t
, a_names
);
845 memcpy (name_map
, names
, n_names
* sizeof (*names
));
850 /* Not found, try the canonical name. */
851 canon
= canonicalize_name (file_name
);
852 name_map
= (name_map_t
*)bsearch
853 (canon
, names
, n_names
, sizeof (*names
), name_search
);
856 /* Not found with canonical name, create a new source. */
859 if (n_sources
== a_sources
)
864 src
= XNEWVEC (source_t
, a_sources
);
865 memcpy (src
, sources
, n_sources
* sizeof (*sources
));
872 name_map
= &names
[n_names
++];
873 name_map
->name
= canon
;
876 src
= &sources
[n_sources
++];
877 memset (src
, 0, sizeof (*src
));
879 src
->coverage
.name
= src
->name
;
880 if (!stat (src
->name
, &status
))
881 src
->file_time
= status
.st_mtime
;
886 if (name_search (file_name
, name_map
))
888 /* Append the non-canonical name. */
889 name_map
= &names
[n_names
++];
890 name_map
->name
= xstrdup (file_name
);
894 /* Resort the name map. */
895 qsort (names
, n_names
, sizeof (*names
), name_sort
);
898 if (sources
[idx
].file_time
> bbg_file_time
)
900 static int info_emitted
;
902 fnotice (stderr
, "%s:source file is newer than graph file '%s'\n",
903 file_name
, bbg_file_name
);
907 "(the message is only displayed one per source file)\n");
910 sources
[idx
].file_time
= 0;
916 /* Read the graph file. Return list of functions read -- in reverse order. */
919 read_graph_file (void)
922 unsigned current_tag
= 0;
923 function_t
*fn
= NULL
;
924 function_t
*fns
= NULL
;
925 function_t
**fns_end
= &fns
;
926 unsigned src_idx
= 0;
930 if (!gcov_open (bbg_file_name
, 1))
932 fnotice (stderr
, "%s:cannot open graph file\n", bbg_file_name
);
935 bbg_file_time
= gcov_time ();
936 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
938 fnotice (stderr
, "%s:not a gcov graph file\n", bbg_file_name
);
943 version
= gcov_read_unsigned ();
944 if (version
!= GCOV_VERSION
)
948 GCOV_UNSIGNED2STRING (v
, version
);
949 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
951 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
952 bbg_file_name
, v
, e
);
954 bbg_stamp
= gcov_read_unsigned ();
956 while ((tag
= gcov_read_unsigned ()))
958 unsigned length
= gcov_read_unsigned ();
959 gcov_position_t base
= gcov_position ();
961 if (tag
== GCOV_TAG_FUNCTION
)
964 unsigned ident
, lineno
;
965 unsigned lineno_checksum
, cfg_checksum
;
967 ident
= gcov_read_unsigned ();
968 lineno_checksum
= gcov_read_unsigned ();
969 cfg_checksum
= gcov_read_unsigned ();
970 function_name
= xstrdup (gcov_read_string ());
971 src_idx
= find_source (gcov_read_string ());
972 lineno
= gcov_read_unsigned ();
974 fn
= XCNEW (function_t
);
975 fn
->name
= function_name
;
977 fn
->lineno_checksum
= lineno_checksum
;
978 fn
->cfg_checksum
= cfg_checksum
;
982 fn
->line_next
= NULL
;
988 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
991 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
992 bbg_file_name
, fn
->name
);
995 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
996 fn
->num_blocks
= num_blocks
;
998 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
999 for (ix
= 0; ix
!= num_blocks
; ix
++)
1000 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
1003 else if (fn
&& tag
== GCOV_TAG_ARCS
)
1005 unsigned src
= gcov_read_unsigned ();
1006 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
1008 if (src
>= fn
->num_blocks
|| fn
->blocks
[src
].succ
)
1013 struct arc_info
*arc
;
1014 unsigned dest
= gcov_read_unsigned ();
1015 unsigned flags
= gcov_read_unsigned ();
1017 if (dest
>= fn
->num_blocks
)
1019 arc
= XCNEW (arc_t
);
1021 arc
->dst
= &fn
->blocks
[dest
];
1022 arc
->src
= &fn
->blocks
[src
];
1025 arc
->count_valid
= 0;
1026 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
1027 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
1028 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
1030 arc
->succ_next
= fn
->blocks
[src
].succ
;
1031 fn
->blocks
[src
].succ
= arc
;
1032 fn
->blocks
[src
].num_succ
++;
1034 arc
->pred_next
= fn
->blocks
[dest
].pred
;
1035 fn
->blocks
[dest
].pred
= arc
;
1036 fn
->blocks
[dest
].num_pred
++;
1042 /* Exceptional exit from this function, the
1043 source block must be a call. */
1044 fn
->blocks
[src
].is_call_site
= 1;
1045 arc
->is_call_non_return
= 1;
1049 /* Non-local return from a callee of this
1050 function. The destination block is a catch or
1052 arc
->is_nonlocal_return
= 1;
1053 fn
->blocks
[dest
].is_nonlocal_return
= 1;
1061 else if (fn
&& tag
== GCOV_TAG_LINES
)
1063 unsigned blockno
= gcov_read_unsigned ();
1064 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
1066 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
1071 unsigned lineno
= gcov_read_unsigned ();
1078 line_nos
[ix
++] = src_idx
;
1080 line_nos
[ix
++] = lineno
;
1084 const char *file_name
= gcov_read_string ();
1088 src_idx
= find_source (file_name
);
1090 line_nos
[ix
++] = src_idx
;
1094 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
1095 fn
->blocks
[blockno
].u
.line
.num
= ix
;
1097 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
1102 gcov_sync (base
, length
);
1103 if (gcov_is_error ())
1106 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
1113 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
1118 /* Reads profiles from the count file and attach to each
1119 function. Return nonzero if fatal error. */
1122 read_count_file (function_t
*fns
)
1127 function_t
*fn
= NULL
;
1130 if (!gcov_open (da_file_name
, 1))
1132 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1137 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1139 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1144 version
= gcov_read_unsigned ();
1145 if (version
!= GCOV_VERSION
)
1149 GCOV_UNSIGNED2STRING (v
, version
);
1150 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1152 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1153 da_file_name
, v
, e
);
1155 tag
= gcov_read_unsigned ();
1156 if (tag
!= bbg_stamp
)
1158 fnotice (stderr
, "%s:stamp mismatch with graph file\n", da_file_name
);
1162 while ((tag
= gcov_read_unsigned ()))
1164 unsigned length
= gcov_read_unsigned ();
1165 unsigned long base
= gcov_position ();
1167 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1169 struct gcov_summary summary
;
1170 gcov_read_summary (&summary
);
1171 object_runs
+= summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
;
1174 else if (tag
== GCOV_TAG_FUNCTION
&& !length
)
1176 else if (tag
== GCOV_TAG_FUNCTION
&& length
== GCOV_TAG_FUNCTION_LENGTH
)
1179 struct function_info
*fn_n
;
1181 /* Try to find the function in the list. To speed up the
1182 search, first start from the last function found. */
1183 ident
= gcov_read_unsigned ();
1185 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1189 else if ((fn
= fn_n
))
1193 fnotice (stderr
, "%s:unknown function '%u'\n",
1194 da_file_name
, ident
);
1197 if (fn
->ident
== ident
)
1203 else if (gcov_read_unsigned () != fn
->lineno_checksum
1204 || gcov_read_unsigned () != fn
->cfg_checksum
)
1207 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1208 da_file_name
, fn
->name
);
1212 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1214 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1218 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1220 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1221 fn
->counts
[ix
] += gcov_read_counter ();
1223 gcov_sync (base
, length
);
1224 if ((error
= gcov_is_error ()))
1226 fnotice (stderr
, error
< 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1236 /* Solve the flow graph. Propagate counts from the instrumented arcs
1237 to the blocks and the uninstrumented arcs. */
1240 solve_flow_graph (function_t
*fn
)
1244 gcov_type
*count_ptr
= fn
->counts
;
1246 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1247 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1249 /* The arcs were built in reverse order. Fix that now. */
1250 for (ix
= fn
->num_blocks
; ix
--;)
1252 arc_t
*arc_p
, *arc_n
;
1254 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1255 arc_p
= arc
, arc
= arc_n
)
1257 arc_n
= arc
->succ_next
;
1258 arc
->succ_next
= arc_p
;
1260 fn
->blocks
[ix
].succ
= arc_p
;
1262 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1263 arc_p
= arc
, arc
= arc_n
)
1265 arc_n
= arc
->pred_next
;
1266 arc
->pred_next
= arc_p
;
1268 fn
->blocks
[ix
].pred
= arc_p
;
1271 if (fn
->num_blocks
< 2)
1272 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1273 bbg_file_name
, fn
->name
);
1276 if (fn
->blocks
[0].num_pred
)
1277 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1278 bbg_file_name
, fn
->name
);
1280 /* We can't deduce the entry block counts from the lack of
1282 fn
->blocks
[0].num_pred
= ~(unsigned)0;
1284 if (fn
->blocks
[fn
->num_blocks
- 1].num_succ
)
1285 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1286 bbg_file_name
, fn
->name
);
1288 /* Likewise, we can't deduce exit block counts from the lack
1289 of its successors. */
1290 fn
->blocks
[fn
->num_blocks
- 1].num_succ
= ~(unsigned)0;
1293 /* Propagate the measured counts, this must be done in the same
1294 order as the code in profile.c */
1295 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1297 block_t
const *prev_dst
= NULL
;
1298 int out_of_order
= 0;
1299 int non_fake_succ
= 0;
1301 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1309 arc
->count
= *count_ptr
++;
1310 arc
->count_valid
= 1;
1312 arc
->dst
->num_pred
--;
1314 if (prev_dst
&& prev_dst
> arc
->dst
)
1316 prev_dst
= arc
->dst
;
1318 if (non_fake_succ
== 1)
1320 /* If there is only one non-fake exit, it is an
1321 unconditional branch. */
1322 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1325 arc
->is_unconditional
= 1;
1326 /* If this block is instrumenting a call, it might be
1327 an artificial block. It is not artificial if it has
1328 a non-fallthrough exit, or the destination of this
1329 arc has more than one entry. Mark the destination
1330 block as a return site, if none of those conditions
1332 if (blk
->is_call_site
&& arc
->fall_through
1333 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1334 arc
->dst
->is_call_return
= 1;
1338 /* Sort the successor arcs into ascending dst order. profile.c
1339 normally produces arcs in the right order, but sometimes with
1340 one or two out of order. We're not using a particularly
1344 arc_t
*start
= blk
->succ
;
1345 unsigned changes
= 1;
1349 arc_t
*arc
, *arc_p
, *arc_n
;
1352 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1354 if (arc
->dst
> arc_n
->dst
)
1358 arc_p
->succ_next
= arc_n
;
1361 arc
->succ_next
= arc_n
->succ_next
;
1362 arc_n
->succ_next
= arc
;
1375 /* Place it on the invalid chain, it will be ignored if that's
1377 blk
->invalid_chain
= 1;
1378 blk
->chain
= invalid_blocks
;
1379 invalid_blocks
= blk
;
1382 while (invalid_blocks
|| valid_blocks
)
1384 while ((blk
= invalid_blocks
))
1386 gcov_type total
= 0;
1389 invalid_blocks
= blk
->chain
;
1390 blk
->invalid_chain
= 0;
1392 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1393 total
+= arc
->count
;
1394 else if (!blk
->num_pred
)
1395 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1396 total
+= arc
->count
;
1401 blk
->count_valid
= 1;
1402 blk
->chain
= valid_blocks
;
1403 blk
->valid_chain
= 1;
1406 while ((blk
= valid_blocks
))
1409 arc_t
*arc
, *inv_arc
;
1411 valid_blocks
= blk
->chain
;
1412 blk
->valid_chain
= 0;
1413 if (blk
->num_succ
== 1)
1419 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1421 total
-= arc
->count
;
1422 if (!arc
->count_valid
)
1426 inv_arc
->count_valid
= 1;
1427 inv_arc
->count
= total
;
1430 if (dst
->count_valid
)
1432 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1434 dst
->chain
= valid_blocks
;
1435 dst
->valid_chain
= 1;
1441 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1443 dst
->chain
= invalid_blocks
;
1444 dst
->invalid_chain
= 1;
1445 invalid_blocks
= dst
;
1449 if (blk
->num_pred
== 1)
1455 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1457 total
-= arc
->count
;
1458 if (!arc
->count_valid
)
1462 inv_arc
->count_valid
= 1;
1463 inv_arc
->count
= total
;
1466 if (src
->count_valid
)
1468 if (src
->num_succ
== 1 && !src
->valid_chain
)
1470 src
->chain
= valid_blocks
;
1471 src
->valid_chain
= 1;
1477 if (!src
->num_succ
&& !src
->invalid_chain
)
1479 src
->chain
= invalid_blocks
;
1480 src
->invalid_chain
= 1;
1481 invalid_blocks
= src
;
1488 /* If the graph has been correctly solved, every block will have a
1490 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1491 if (!fn
->blocks
[ix
].count_valid
)
1493 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1494 bbg_file_name
, fn
->name
);
1501 /* Increment totals in COVERAGE according to arc ARC. */
1504 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1506 if (arc
->is_call_non_return
)
1509 if (arc
->src
->count
)
1510 coverage
->calls_executed
++;
1512 else if (!arc
->is_unconditional
)
1514 coverage
->branches
++;
1515 if (arc
->src
->count
)
1516 coverage
->branches_executed
++;
1518 coverage
->branches_taken
++;
1522 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1523 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1524 If DP is zero, no decimal point is printed. Only print 100% when
1525 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1526 format TOP. Return pointer to a static string. */
1529 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1531 static char buffer
[20];
1535 float ratio
= bottom
? (float)top
/ bottom
: 0;
1537 unsigned limit
= 100;
1540 for (ix
= dp
; ix
--; )
1543 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1544 if (percent
<= 0 && top
)
1546 else if (percent
>= limit
&& top
!= bottom
)
1547 percent
= limit
- 1;
1548 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1554 buffer
[ix
+1] = buffer
[ix
];
1558 buffer
[ix
+ 1] = '.';
1562 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)top
);
1568 /* Output summary info for a function. */
1571 function_summary (const coverage_t
*coverage
, const char *title
)
1573 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
1575 if (coverage
->lines
)
1576 fnotice (stdout
, "Lines executed:%s of %d\n",
1577 format_gcov (coverage
->lines_executed
, coverage
->lines
, 2),
1580 fnotice (stdout
, "No executable lines\n");
1584 if (coverage
->branches
)
1586 fnotice (stdout
, "Branches executed:%s of %d\n",
1587 format_gcov (coverage
->branches_executed
,
1588 coverage
->branches
, 2),
1589 coverage
->branches
);
1590 fnotice (stdout
, "Taken at least once:%s of %d\n",
1591 format_gcov (coverage
->branches_taken
,
1592 coverage
->branches
, 2),
1593 coverage
->branches
);
1596 fnotice (stdout
, "No branches\n");
1597 if (coverage
->calls
)
1598 fnotice (stdout
, "Calls executed:%s of %d\n",
1599 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
1602 fnotice (stdout
, "No calls\n");
1606 /* Canonicalize the filename NAME by canonicalizing directory
1607 separators, eliding . components and resolving .. components
1608 appropriately. Always returns a unique string. */
1611 canonicalize_name (const char *name
)
1613 /* The canonical name cannot be longer than the incoming name. */
1614 char *result
= XNEWVEC (char, strlen (name
) + 1);
1615 const char *base
= name
, *probe
;
1620 #if HAVE_DOS_BASED_FILE_SYSTEM
1621 if (base
[0] && base
[1] == ':')
1623 result
[0] = base
[0];
1629 for (dd_base
= ptr
; *base
; base
= probe
)
1633 for (probe
= base
; *probe
; probe
++)
1634 if (IS_DIR_SEPARATOR (*probe
))
1638 if (len
== 1 && base
[0] == '.')
1639 /* Elide a '.' directory */
1641 else if (len
== 2 && base
[0] == '.' && base
[1] == '.')
1643 /* '..', we can only elide it and the previous directory, if
1644 we're not a symlink. */
1648 if (dd_base
== ptr
|| stat (result
, &buf
) || S_ISLNK (buf
.st_mode
))
1650 /* Cannot elide, or unreadable or a symlink. */
1651 dd_base
= ptr
+ 2 + slash
;
1654 while (ptr
!= dd_base
&& *ptr
!= '/')
1656 slash
= ptr
!= result
;
1661 /* Regular pathname component. */
1664 memcpy (ptr
, base
, len
);
1669 for (; IS_DIR_SEPARATOR (*probe
); probe
++)
1677 /* Generate an output file name. INPUT_NAME is the canonicalized main
1678 input file and SRC_NAME is the canonicalized file name.
1679 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
1680 long_output_names we prepend the processed name of the input file
1681 to each output name (except when the current source file is the
1682 input file, so you don't get a double concatenation). The two
1683 components are separated by '##'. With preserve_paths we create a
1684 filename from all path components of the source file, replacing '/'
1685 with '#', and .. with '^', without it we simply take the basename
1686 component. (Remember, the canonicalized name will already have
1687 elided '.' components and converted \\ separators.) */
1690 make_gcov_file_name (const char *input_name
, const char *src_name
)
1695 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
1697 /* Generate the input filename part. */
1698 result
= XNEWVEC (char, strlen (input_name
) + strlen (src_name
) + 10);
1701 ptr
= mangle_name (input_name
, ptr
);
1702 ptr
[0] = ptr
[1] = '#';
1707 result
= XNEWVEC (char, strlen (src_name
) + 10);
1711 ptr
= mangle_name (src_name
, ptr
);
1712 strcpy (ptr
, ".gcov");
1718 mangle_name (char const *base
, char *ptr
)
1722 /* Generate the source filename part. */
1723 if (!flag_preserve_paths
)
1725 base
= lbasename (base
);
1726 len
= strlen (base
);
1727 memcpy (ptr
, base
, len
);
1732 /* Convert '/' to '#', convert '..' to '^',
1733 convert ':' to '~' on DOS based file system. */
1736 #if HAVE_DOS_BASED_FILE_SYSTEM
1737 if (base
[0] && base
[1] == ':')
1745 for (; *base
; base
= probe
)
1749 for (probe
= base
; *probe
; probe
++)
1753 if (len
== 2 && base
[0] == '.' && base
[1] == '.')
1757 memcpy (ptr
, base
, len
);
1771 /* Scan through the bb_data for each line in the block, increment
1772 the line number execution count indicated by the execution count of
1773 the appropriate basic block. */
1776 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
1779 line_t
*line
= NULL
; /* This is propagated from one iteration to the
1782 /* Scan each basic block. */
1783 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
1785 block_t
*block
= &fn
->blocks
[ix
];
1787 const source_t
*src
= NULL
;
1790 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
1791 fn
->blocks_executed
++;
1792 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
1793 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
1796 src
= &sources
[*++encoding
];
1801 line
= &src
->lines
[*encoding
];
1807 if (!line
->count
&& block
->count
)
1808 coverage
->lines_executed
++;
1811 line
->count
+= block
->count
;
1813 free (block
->u
.line
.encoding
);
1814 block
->u
.cycle
.arc
= NULL
;
1815 block
->u
.cycle
.ident
= ~0U;
1817 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
1818 /* Entry or exit block */;
1819 else if (flag_all_blocks
)
1821 line_t
*block_line
= line
;
1824 block_line
= &sources
[fn
->src
].lines
[fn
->line
];
1826 block
->chain
= block_line
->u
.blocks
;
1827 block_line
->u
.blocks
= block
;
1829 else if (flag_branches
)
1833 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1835 arc
->line_next
= line
->u
.branches
;
1836 line
->u
.branches
= arc
;
1837 if (coverage
&& !arc
->is_unconditional
)
1838 add_branch_counts (coverage
, arc
);
1843 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
1846 /* Accumulate the line counts of a file. */
1849 accumulate_line_counts (source_t
*src
)
1852 function_t
*fn
, *fn_p
, *fn_n
;
1855 /* Reverse the function order. */
1856 for (fn
= src
->functions
, fn_p
= NULL
; fn
;
1857 fn_p
= fn
, fn
= fn_n
)
1859 fn_n
= fn
->line_next
;
1860 fn
->line_next
= fn_p
;
1862 src
->functions
= fn_p
;
1864 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
1866 if (!flag_all_blocks
)
1868 arc_t
*arc
, *arc_p
, *arc_n
;
1870 /* Total and reverse the branch information. */
1871 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
1872 arc_p
= arc
, arc
= arc_n
)
1874 arc_n
= arc
->line_next
;
1875 arc
->line_next
= arc_p
;
1877 add_branch_counts (&src
->coverage
, arc
);
1879 line
->u
.branches
= arc_p
;
1881 else if (line
->u
.blocks
)
1883 /* The user expects the line count to be the number of times
1884 a line has been executed. Simply summing the block count
1885 will give an artificially high number. The Right Thing
1886 is to sum the entry counts to the graph of blocks on this
1887 line, then find the elementary cycles of the local graph
1888 and add the transition counts of those cycles. */
1889 block_t
*block
, *block_p
, *block_n
;
1890 gcov_type count
= 0;
1892 /* Reverse the block information. */
1893 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
1894 block_p
= block
, block
= block_n
)
1896 block_n
= block
->chain
;
1897 block
->chain
= block_p
;
1898 block
->u
.cycle
.ident
= ix
;
1900 line
->u
.blocks
= block_p
;
1902 /* Sum the entry arcs. */
1903 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1907 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
1909 if (arc
->src
->u
.cycle
.ident
!= ix
)
1910 count
+= arc
->count
;
1912 add_branch_counts (&src
->coverage
, arc
);
1915 /* Initialize the cs_count. */
1916 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1917 arc
->cs_count
= arc
->count
;
1920 /* Find the loops. This uses the algorithm described in
1921 Tiernan 'An Efficient Search Algorithm to Find the
1922 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1923 the P array by having each block point to the arc that
1924 connects to the previous block. The H array is implicitly
1925 held because of the arc ordering, and the block's
1926 previous arc pointer.
1928 Although the algorithm is O(N^3) for highly connected
1929 graphs, at worst we'll have O(N^2), as most blocks have
1930 only one or two exits. Most graphs will be small.
1932 For each loop we find, locate the arc with the smallest
1933 transition count, and add that to the cumulative
1934 count. Decrease flow over the cycle and remove the arc
1935 from consideration. */
1936 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1938 block_t
*head
= block
;
1946 block_t
*dst
= arc
->dst
;
1947 if (/* Already used that arc. */
1949 /* Not to same graph, or before first vertex. */
1950 || dst
->u
.cycle
.ident
!= ix
1951 /* Already in path. */
1952 || dst
->u
.cycle
.arc
)
1954 arc
= arc
->succ_next
;
1960 /* Found a closing arc. */
1961 gcov_type cycle_count
= arc
->cs_count
;
1962 arc_t
*cycle_arc
= arc
;
1965 /* Locate the smallest arc count of the loop. */
1966 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1967 dst
= probe_arc
->src
)
1968 if (cycle_count
> probe_arc
->cs_count
)
1970 cycle_count
= probe_arc
->cs_count
;
1971 cycle_arc
= probe_arc
;
1974 count
+= cycle_count
;
1975 cycle_arc
->cycle
= 1;
1977 /* Remove the flow from the cycle. */
1978 arc
->cs_count
-= cycle_count
;
1979 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1980 dst
= probe_arc
->src
)
1981 probe_arc
->cs_count
-= cycle_count
;
1983 /* Unwind to the cyclic arc. */
1984 while (head
!= cycle_arc
->src
)
1986 arc
= head
->u
.cycle
.arc
;
1987 head
->u
.cycle
.arc
= NULL
;
1991 arc
= arc
->succ_next
;
1995 /* Add new block to chain. */
1996 dst
->u
.cycle
.arc
= arc
;
2000 /* We could not add another vertex to the path. Remove
2001 the last vertex from the list. */
2002 arc
= head
->u
.cycle
.arc
;
2005 /* It was not the first vertex. Move onto next arc. */
2006 head
->u
.cycle
.arc
= NULL
;
2008 arc
= arc
->succ_next
;
2009 goto current_vertex
;
2011 /* Mark this block as unusable. */
2012 block
->u
.cycle
.ident
= ~0U;
2015 line
->count
= count
;
2020 src
->coverage
.lines
++;
2022 src
->coverage
.lines_executed
++;
2027 /* Output information about ARC number IX. Returns nonzero if
2028 anything is output. */
2031 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
2034 if (arc
->is_call_non_return
)
2036 if (arc
->src
->count
)
2038 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
2039 format_gcov (arc
->src
->count
- arc
->count
,
2040 arc
->src
->count
, -flag_counts
));
2043 fnotice (gcov_file
, "call %2d never executed\n", ix
);
2045 else if (!arc
->is_unconditional
)
2047 if (arc
->src
->count
)
2048 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
2049 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
2050 arc
->fall_through
? " (fallthrough)" : "");
2052 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
2054 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
2056 if (arc
->src
->count
)
2057 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
2058 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
2060 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
2068 /* Read in the source file one line at a time, and output that line to
2069 the gcov file preceded by its execution count and other
2073 output_lines (FILE *gcov_file
, const source_t
*src
)
2076 unsigned line_num
; /* current line number. */
2077 const line_t
*line
; /* current line info ptr. */
2078 char string
[STRING_SIZE
]; /* line buffer. */
2079 char const *retval
= ""; /* status of source file reading. */
2080 function_t
*fn
= NULL
;
2082 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->name
);
2083 if (!multiple_files
)
2085 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
2086 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
2087 no_data_file
? "-" : da_file_name
);
2088 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0, object_runs
);
2090 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
2092 source_file
= fopen (src
->name
, "r");
2095 fnotice (stderr
, "%s:cannot open source file\n", src
->name
);
2098 else if (src
->file_time
== 0)
2099 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
2102 fn
= src
->functions
;
2104 for (line_num
= 1, line
= &src
->lines
[line_num
];
2105 line_num
< src
->num_lines
; line_num
++, line
++)
2107 for (; fn
&& fn
->line
== line_num
; fn
= fn
->line_next
)
2109 arc_t
*arc
= fn
->blocks
[fn
->num_blocks
- 1].pred
;
2110 gcov_type return_count
= fn
->blocks
[fn
->num_blocks
- 1].count
;
2112 for (; arc
; arc
= arc
->pred_next
)
2114 return_count
-= arc
->count
;
2116 fprintf (gcov_file
, "function %s", fn
->name
);
2117 fprintf (gcov_file
, " called %s",
2118 format_gcov (fn
->blocks
[0].count
, 0, -1));
2119 fprintf (gcov_file
, " returned %s",
2120 format_gcov (return_count
, fn
->blocks
[0].count
, 0));
2121 fprintf (gcov_file
, " blocks executed %s",
2122 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
2123 fprintf (gcov_file
, "\n");
2126 /* For lines which don't exist in the .bb file, print '-' before
2127 the source line. For lines which exist but were never
2128 executed, print '#####' before the source line. Otherwise,
2129 print the execution count before the source line. There are
2130 16 spaces of indentation added before the source line so that
2131 tabs won't be messed up. */
2132 fprintf (gcov_file
, "%9s:%5u:",
2133 !line
->exists
? "-" : !line
->count
? "#####"
2134 : format_gcov (line
->count
, 0, -1), line_num
);
2138 /* Copy source line. */
2141 retval
= fgets (string
, STRING_SIZE
, source_file
);
2144 fputs (retval
, gcov_file
);
2146 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
2149 fputs ("/*EOF*/\n", gcov_file
);
2151 if (flag_all_blocks
)
2157 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
2158 block
= block
->chain
)
2160 if (!block
->is_call_return
)
2161 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
2162 !line
->exists
? "-" : !block
->count
? "$$$$$"
2163 : format_gcov (block
->count
, 0, -1),
2166 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2167 jx
+= output_branch_count (gcov_file
, jx
, arc
);
2170 else if (flag_branches
)
2175 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
2176 ix
+= output_branch_count (gcov_file
, ix
, arc
);
2180 /* Handle all remaining source lines. There may be lines after the
2181 last line of code. */
2184 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
2186 fprintf (gcov_file
, "%9s:%5u:%s", "-", line_num
, retval
);
2188 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
2190 retval
= fgets (string
, STRING_SIZE
, source_file
);
2193 fputs (retval
, gcov_file
);
2199 fclose (source_file
);