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 /* Source directory prefix. This is removed from source pathnames
337 that match, when generating the output file name. */
339 static char *source_prefix = 0;
340 static size_t source_length = 0;
342 /* Only show data for sources with relative pathnames. Absolute ones
343 usually indicate a system header file, which although it may
344 contain inline functions, is usually uninteresting. */
345 static int flag_relative_only = 0;
347 /* Preserve all pathname components. Needed when object files and
348 source files are in subdirectories. '/' is mangled as '#', '.' is
349 elided and '..' mangled to '^'. */
351 static int flag_preserve_paths = 0;
353 /* Output the number of times a branch was taken as opposed to the percentage
354 of times it was taken. */
356 static int flag_counts = 0;
358 /* Forward declarations. */
359 static int process_args (int, char **);
360 static void print_usage (int) ATTRIBUTE_NORETURN;
361 static void print_version (void) ATTRIBUTE_NORETURN;
362 static void process_file (const char *);
363 static void generate_results (const char *);
364 static void create_file_names (const char *);
365 static int name_search (const void *, const void *);
366 static int name_sort (const void *, const void *);
367 static char *canonicalize_name (const char *);
368 static unsigned find_source (const char *);
369 static function_t *read_graph_file (void);
370 static int read_count_file (function_t *);
371 static void solve_flow_graph (function_t *);
372 static void add_branch_counts (coverage_t *, const arc_t *);
373 static void add_line_counts (coverage_t *, function_t *);
374 static void function_summary (const coverage_t *, const char *);
375 static const char *format_gcov (gcov_type, gcov_type, int);
376 static void accumulate_line_counts (source_t *);
377 static int output_branch_count (FILE *, int, const arc_t *);
378 static void output_lines (FILE *, const source_t *);
379 static char *make_gcov_file_name (const char *, const char *);
380 static char *mangle_name (const char *, char *);
381 static void release_structures (void);
382 static void release_function (function_t *);
383 extern int main (int, char **);
386 main (int argc, char **argv)
392 p = argv[0] + strlen (argv[0]);
393 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
397 xmalloc_set_program_name (progname);
399 /* Unlock the stdio streams. */
400 unlock_std_streams ();
404 diagnostic_initialize (global_dc, 0);
406 /* Handle response files. */
407 expandargv (&argc, &argv);
410 names = XNEWVEC (name_map_t, a_names);
412 sources = XNEWVEC (source_t, a_sources);
414 argno = process_args (argc, argv);
418 if (argc - argno > 1)
423 for (; argno != argc; argno++)
425 if (flag_display_progress)
426 printf("Processing file %d out of %d\n",
427 argno - first_arg + 1, argc - first_arg);
428 process_file (argv[argno]);
431 generate_results (multiple_files ? NULL : argv[argc - 1]);
433 release_structures ();
438 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
439 otherwise the output of --help. */
442 print_usage (int error_p)
444 FILE *file = error_p ? stderr : stdout;
445 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
447 fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
448 fnotice (file, "Print code coverage information.\n\n");
449 fnotice (file, " -h, --help Print this help, then exit\n");
450 fnotice (file, " -v, --version Print version number, then exit\n");
451 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
452 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
453 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
454 rather than percentages\n");
455 fnotice (file, " -n, --no-output Do not create an output file\n");
456 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
458 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
459 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
460 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
461 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
462 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
463 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
464 fnotice (file, " -d, --display-progress Display progress information\n");
465 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
470 /* Print version information and exit. */
475 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
476 fprintf (stdout, "Copyright %s 2011 Free Software Foundation, Inc.\n",
479 _("This is free software; see the source for copying conditions.\n"
480 "There is NO warranty; not even for MERCHANTABILITY or \n"
481 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
482 exit (SUCCESS_EXIT_CODE);
485 static const struct option options[] =
487 { "help", no_argument, NULL, 'h' },
488 { "version", no_argument, NULL, 'v' },
489 { "all-blocks", no_argument, NULL, 'a' },
490 { "branch-probabilities", no_argument, NULL, 'b' },
491 { "branch-counts", no_argument, NULL, 'c' },
492 { "no-output", no_argument, NULL, 'n' },
493 { "long-file-names", no_argument, NULL, 'l' },
494 { "function-summaries", no_argument, NULL, 'f' },
495 { "preserve-paths", no_argument, NULL, 'p' },
496 { "relative-only", no_argument, NULL, 'r' },
497 { "object-directory", required_argument, NULL, 'o' },
498 { "object-file", required_argument, NULL, 'o' },
499 { "source-prefix", required_argument, NULL, 's' },
500 { "unconditional-branches", no_argument, NULL, 'u' },
501 { "display-progress", no_argument, NULL, 'd' },
505 /* Process args, return index to first non-arg. */
508 process_args (int argc, char **argv)
512 while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
526 flag_function_summary = 1;
530 /* print_usage will exit. */
538 object_directory = optarg;
541 source_prefix = optarg;
542 source_length = strlen (source_prefix);
545 flag_relative_only = 1;
548 flag_preserve_paths = 1;
551 flag_unconditional = 1;
554 flag_display_progress = 1;
558 /* print_version will exit. */
561 /* print_usage will exit. */
568 /* Process a single input file. */
571 process_file (const char *file_name)
575 create_file_names (file_name);
576 fns = read_graph_file ();
580 read_count_file (fns);
583 function_t *fn = fns;
589 unsigned src = fn->src;
590 unsigned line = fn->line;
592 function_t *probe, **prev;
594 /* Now insert it into the source file's list of
595 functions. Normally functions will be encountered in
596 ascending order, so a simple scan is quick. Note we're
597 building this list in reverse order. */
598 for (prev = &sources[src].functions;
599 (probe = *prev); prev = &probe->line_next)
600 if (probe->line <= line)
602 fn->line_next = probe;
605 /* Mark last line in files touched by function. */
606 for (block_no = 0; block_no != fn->num_blocks; block_no++)
608 unsigned *enc = fn->blocks[block_no].u.line.encoding;
609 unsigned num = fn->blocks[block_no].u.line.num;
616 if (line >= sources[src].num_lines)
617 sources[src].num_lines = line + 1;
624 else if (*enc > line)
627 if (line >= sources[src].num_lines)
628 sources[src].num_lines = line + 1;
630 solve_flow_graph (fn);
635 /* The function was not in the executable -- some other
636 instance must have been selected. */
637 release_function (fn);
642 generate_results (const char *file_name)
648 for (ix = n_sources, src = sources; ix--; src++)
650 src->lines = XCNEWVEC (line_t, src->num_lines);
652 for (fn = functions; fn; fn = fn->next)
656 memset (&coverage, 0, sizeof (coverage));
657 coverage.name = fn->name;
658 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
659 if (flag_function_summary)
661 function_summary (&coverage, "Function");
662 fnotice (stdout, "\n");
668 name_map_t *name_map = (name_map_t *)bsearch
669 (file_name, names, n_names, sizeof (*names), name_search);
671 file_name = sources[name_map->src].coverage.name;
673 file_name = canonicalize_name (file_name);
676 for (ix = n_sources, src = sources; ix--; src++)
678 if (flag_relative_only)
680 /* Ignore this source, if it is an absolute path (after
681 source prefix removal). */
682 char first = src->coverage.name[0];
684 #if HAVE_DOS_BASED_FILE_SYSTEM
685 if (first && src->coverage.name[1] == ':')
686 first = src->coverage.name[2];
688 if (IS_DIR_SEPARATOR (first))
692 accumulate_line_counts (src);
693 function_summary (&src->coverage, "File");
694 if (flag_gcov_file && src->coverage.lines)
697 = make_gcov_file_name (file_name, src->coverage.name);
698 FILE *gcov_file = fopen (gcov_file_name, "w");
702 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
703 output_lines (gcov_file, src);
704 if (ferror (gcov_file))
705 fnotice (stderr, "Error writing output file '%s'\n",
710 fnotice (stderr, "Could not open output file '%s'\n",
712 free (gcov_file_name);
714 fnotice (stdout, "\n");
718 /* Release a function structure */
721 release_function (function_t *fn)
726 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
730 for (arc = block->succ; arc; arc = arc_n)
732 arc_n = arc->succ_next;
740 /* Release all memory used. */
743 release_structures (void)
748 for (ix = n_sources; ix--;)
749 free (sources[ix].lines);
752 for (ix = n_names; ix--;)
753 free (names[ix].name);
756 while ((fn = functions))
758 functions = fn->next;
759 release_function (fn);
763 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
764 is not specified, these are named from FILE_NAME sans extension. If
765 OBJECT_DIRECTORY is specified and is a directory, the files are in that
766 directory, but named from the basename of the FILE_NAME, sans extension.
767 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
768 and the data files are named from that. */
771 create_file_names (const char *file_name)
775 int length = strlen (file_name);
778 /* Free previous file names. */
779 free (bbg_file_name);
781 da_file_name = bbg_file_name = NULL;
785 if (object_directory && object_directory[0])
789 length += strlen (object_directory) + 2;
790 name = XNEWVEC (char, length);
793 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
794 strcat (name, object_directory);
795 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
800 name = XNEWVEC (char, length + 1);
801 strcpy (name, file_name);
807 /* Append source file name. */
808 const char *cptr = lbasename (file_name);
809 strcat (name, cptr ? cptr : file_name);
812 /* Remove the extension. */
813 cptr = strrchr (name, '.');
817 length = strlen (name);
819 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
820 strcpy (bbg_file_name, name);
821 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
823 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
824 strcpy (da_file_name, name);
825 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
831 /* A is a string and B is a pointer to name_map_t. Compare for file
832 name orderability. */
835 name_search (const void *a_, const void *b_)
837 const char *a = (const char *)a_;
838 const name_map_t *b = (const name_map_t *)b_;
840 #if HAVE_DOS_BASED_FILE_SYSTEM
841 return strcasecmp (a, b->name);
843 return strcmp (a, b->name);
847 /* A and B are a pointer to name_map_t. Compare for file name
851 name_sort (const void *a_, const void *b_)
853 const name_map_t *a = (const name_map_t *)a_;
854 return name_search (a->name, b_);
857 /* Find or create a source file structure for FILE_NAME. Copies
858 FILE_NAME on creation */
861 find_source (const char *file_name)
863 name_map_t *name_map;
869 file_name = "<unknown>";
870 name_map = (name_map_t *)bsearch
871 (file_name, names, n_names, sizeof (*names), name_search);
878 if (n_names + 2 > a_names)
880 /* Extend the name map array -- we'll be inserting one or two
883 name_map = XNEWVEC (name_map_t, a_names);
884 memcpy (name_map, names, n_names * sizeof (*names));
889 /* Not found, try the canonical name. */
890 canon = canonicalize_name (file_name);
891 name_map = (name_map_t *)bsearch
892 (canon, names, n_names, sizeof (*names), name_search);
895 /* Not found with canonical name, create a new source. */
898 if (n_sources == a_sources)
901 src = XNEWVEC (source_t, a_sources);
902 memcpy (src, sources, n_sources * sizeof (*sources));
909 name_map = &names[n_names++];
910 name_map->name = canon;
913 src = &sources[n_sources++];
914 memset (src, 0, sizeof (*src));
916 src->coverage.name = src->name;
918 #if HAVE_DOS_BASED_FILE_SYSTEM
919 /* You lose if separators don't match exactly in the
921 && !strncasecmp (source_prefix, src->coverage.name, source_length)
923 && !strncmp (source_prefix, src->coverage.name, source_length)
925 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
926 src->coverage.name += source_length + 1;
927 if (!stat (src->name, &status))
928 src->file_time = status.st_mtime;
933 if (name_search (file_name, name_map))
935 /* Append the non-canonical name. */
936 name_map = &names[n_names++];
937 name_map->name = xstrdup (file_name);
941 /* Resort the name map. */
942 qsort (names, n_names, sizeof (*names), name_sort);
945 if (sources[idx].file_time > bbg_file_time)
947 static int info_emitted;
949 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
950 file_name, bbg_file_name);
954 "(the message is only displayed one per source file)\n");
957 sources[idx].file_time = 0;
963 /* Read the graph file. Return list of functions read -- in reverse order. */
966 read_graph_file (void)
969 unsigned current_tag = 0;
970 function_t *fn = NULL;
971 function_t *fns = NULL;
972 function_t **fns_end = &fns;
973 unsigned src_idx = 0;
977 if (!gcov_open (bbg_file_name, 1))
979 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
982 bbg_file_time = gcov_time ();
983 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
985 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
990 version = gcov_read_unsigned ();
991 if (version != GCOV_VERSION)
995 GCOV_UNSIGNED2STRING (v, version);
996 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
998 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
999 bbg_file_name, v, e);
1001 bbg_stamp = gcov_read_unsigned ();
1003 while ((tag = gcov_read_unsigned ()))
1005 unsigned length = gcov_read_unsigned ();
1006 gcov_position_t base = gcov_position ();
1008 if (tag == GCOV_TAG_FUNCTION)
1010 char *function_name;
1011 unsigned ident, lineno;
1012 unsigned lineno_checksum, cfg_checksum;
1014 ident = gcov_read_unsigned ();
1015 lineno_checksum = gcov_read_unsigned ();
1016 cfg_checksum = gcov_read_unsigned ();
1017 function_name = xstrdup (gcov_read_string ());
1018 src_idx = find_source (gcov_read_string ());
1019 lineno = gcov_read_unsigned ();
1021 fn = XCNEW (function_t);
1022 fn->name = function_name;
1024 fn->lineno_checksum = lineno_checksum;
1025 fn->cfg_checksum = cfg_checksum;
1029 fn->line_next = NULL;
1032 fns_end = &fn->next;
1035 else if (fn && tag == GCOV_TAG_BLOCKS)
1038 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1039 bbg_file_name, fn->name);
1042 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1043 fn->num_blocks = num_blocks;
1045 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
1046 for (ix = 0; ix != num_blocks; ix++)
1047 fn->blocks[ix].flags = gcov_read_unsigned ();
1050 else if (fn && tag == GCOV_TAG_ARCS)
1052 unsigned src = gcov_read_unsigned ();
1053 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1055 if (src >= fn->num_blocks || fn->blocks[src].succ)
1060 struct arc_info *arc;
1061 unsigned dest = gcov_read_unsigned ();
1062 unsigned flags = gcov_read_unsigned ();
1064 if (dest >= fn->num_blocks)
1066 arc = XCNEW (arc_t);
1068 arc->dst = &fn->blocks[dest];
1069 arc->src = &fn->blocks[src];
1072 arc->count_valid = 0;
1073 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1074 arc->fake = !!(flags & GCOV_ARC_FAKE);
1075 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1077 arc->succ_next = fn->blocks[src].succ;
1078 fn->blocks[src].succ = arc;
1079 fn->blocks[src].num_succ++;
1081 arc->pred_next = fn->blocks[dest].pred;
1082 fn->blocks[dest].pred = arc;
1083 fn->blocks[dest].num_pred++;
1089 /* Exceptional exit from this function, the
1090 source block must be a call. */
1091 fn->blocks[src].is_call_site = 1;
1092 arc->is_call_non_return = 1;
1096 /* Non-local return from a callee of this
1097 function. The destination block is a catch or
1099 arc->is_nonlocal_return = 1;
1100 fn->blocks[dest].is_nonlocal_return = 1;
1108 else if (fn && tag == GCOV_TAG_LINES)
1110 unsigned blockno = gcov_read_unsigned ();
1111 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1113 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1118 unsigned lineno = gcov_read_unsigned ();
1125 line_nos[ix++] = src_idx;
1127 line_nos[ix++] = lineno;
1131 const char *file_name = gcov_read_string ();
1135 src_idx = find_source (file_name);
1137 line_nos[ix++] = src_idx;
1141 fn->blocks[blockno].u.line.encoding = line_nos;
1142 fn->blocks[blockno].u.line.num = ix;
1144 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1149 gcov_sync (base, length);
1150 if (gcov_is_error ())
1153 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1160 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1165 /* Reads profiles from the count file and attach to each
1166 function. Return nonzero if fatal error. */
1169 read_count_file (function_t *fns)
1174 function_t *fn = NULL;
1177 if (!gcov_open (da_file_name, 1))
1179 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1184 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1186 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1191 version = gcov_read_unsigned ();
1192 if (version != GCOV_VERSION)
1196 GCOV_UNSIGNED2STRING (v, version);
1197 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1199 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1200 da_file_name, v, e);
1202 tag = gcov_read_unsigned ();
1203 if (tag != bbg_stamp)
1205 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1209 while ((tag = gcov_read_unsigned ()))
1211 unsigned length = gcov_read_unsigned ();
1212 unsigned long base = gcov_position ();
1214 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1216 struct gcov_summary summary;
1217 gcov_read_summary (&summary);
1218 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1221 else if (tag == GCOV_TAG_FUNCTION && !length)
1223 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1226 struct function_info *fn_n;
1228 /* Try to find the function in the list. To speed up the
1229 search, first start from the last function found. */
1230 ident = gcov_read_unsigned ();
1232 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1236 else if ((fn = fn_n))
1240 fnotice (stderr, "%s:unknown function '%u'\n",
1241 da_file_name, ident);
1244 if (fn->ident == ident)
1250 else if (gcov_read_unsigned () != fn->lineno_checksum
1251 || gcov_read_unsigned () != fn->cfg_checksum)
1254 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1255 da_file_name, fn->name);
1259 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1261 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1265 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1267 for (ix = 0; ix != fn->num_counts; ix++)
1268 fn->counts[ix] += gcov_read_counter ();
1270 gcov_sync (base, length);
1271 if ((error = gcov_is_error ()))
1273 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1283 /* Solve the flow graph. Propagate counts from the instrumented arcs
1284 to the blocks and the uninstrumented arcs. */
1287 solve_flow_graph (function_t *fn)
1291 gcov_type *count_ptr = fn->counts;
1293 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1294 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1296 /* The arcs were built in reverse order. Fix that now. */
1297 for (ix = fn->num_blocks; ix--;)
1299 arc_t *arc_p, *arc_n;
1301 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1302 arc_p = arc, arc = arc_n)
1304 arc_n = arc->succ_next;
1305 arc->succ_next = arc_p;
1307 fn->blocks[ix].succ = arc_p;
1309 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1310 arc_p = arc, arc = arc_n)
1312 arc_n = arc->pred_next;
1313 arc->pred_next = arc_p;
1315 fn->blocks[ix].pred = arc_p;
1318 if (fn->num_blocks < 2)
1319 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1320 bbg_file_name, fn->name);
1323 if (fn->blocks[0].num_pred)
1324 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1325 bbg_file_name, fn->name);
1327 /* We can't deduce the entry block counts from the lack of
1329 fn->blocks[0].num_pred = ~(unsigned)0;
1331 if (fn->blocks[fn->num_blocks - 1].num_succ)
1332 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1333 bbg_file_name, fn->name);
1335 /* Likewise, we can't deduce exit block counts from the lack
1336 of its successors. */
1337 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1340 /* Propagate the measured counts, this must be done in the same
1341 order as the code in profile.c */
1342 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1344 block_t const *prev_dst = NULL;
1345 int out_of_order = 0;
1346 int non_fake_succ = 0;
1348 for (arc = blk->succ; arc; arc = arc->succ_next)
1356 arc->count = *count_ptr++;
1357 arc->count_valid = 1;
1359 arc->dst->num_pred--;
1361 if (prev_dst && prev_dst > arc->dst)
1363 prev_dst = arc->dst;
1365 if (non_fake_succ == 1)
1367 /* If there is only one non-fake exit, it is an
1368 unconditional branch. */
1369 for (arc = blk->succ; arc; arc = arc->succ_next)
1372 arc->is_unconditional = 1;
1373 /* If this block is instrumenting a call, it might be
1374 an artificial block. It is not artificial if it has
1375 a non-fallthrough exit, or the destination of this
1376 arc has more than one entry. Mark the destination
1377 block as a return site, if none of those conditions
1379 if (blk->is_call_site && arc->fall_through
1380 && arc->dst->pred == arc && !arc->pred_next)
1381 arc->dst->is_call_return = 1;
1385 /* Sort the successor arcs into ascending dst order. profile.c
1386 normally produces arcs in the right order, but sometimes with
1387 one or two out of order. We're not using a particularly
1391 arc_t *start = blk->succ;
1392 unsigned changes = 1;
1396 arc_t *arc, *arc_p, *arc_n;
1399 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1401 if (arc->dst > arc_n->dst)
1405 arc_p->succ_next = arc_n;
1408 arc->succ_next = arc_n->succ_next;
1409 arc_n->succ_next = arc;
1422 /* Place it on the invalid chain, it will be ignored if that's
1424 blk->invalid_chain = 1;
1425 blk->chain = invalid_blocks;
1426 invalid_blocks = blk;
1429 while (invalid_blocks || valid_blocks)
1431 while ((blk = invalid_blocks))
1433 gcov_type total = 0;
1436 invalid_blocks = blk->chain;
1437 blk->invalid_chain = 0;
1439 for (arc = blk->succ; arc; arc = arc->succ_next)
1440 total += arc->count;
1441 else if (!blk->num_pred)
1442 for (arc = blk->pred; arc; arc = arc->pred_next)
1443 total += arc->count;
1448 blk->count_valid = 1;
1449 blk->chain = valid_blocks;
1450 blk->valid_chain = 1;
1453 while ((blk = valid_blocks))
1456 arc_t *arc, *inv_arc;
1458 valid_blocks = blk->chain;
1459 blk->valid_chain = 0;
1460 if (blk->num_succ == 1)
1466 for (arc = blk->succ; arc; arc = arc->succ_next)
1468 total -= arc->count;
1469 if (!arc->count_valid)
1473 inv_arc->count_valid = 1;
1474 inv_arc->count = total;
1477 if (dst->count_valid)
1479 if (dst->num_pred == 1 && !dst->valid_chain)
1481 dst->chain = valid_blocks;
1482 dst->valid_chain = 1;
1488 if (!dst->num_pred && !dst->invalid_chain)
1490 dst->chain = invalid_blocks;
1491 dst->invalid_chain = 1;
1492 invalid_blocks = dst;
1496 if (blk->num_pred == 1)
1502 for (arc = blk->pred; arc; arc = arc->pred_next)
1504 total -= arc->count;
1505 if (!arc->count_valid)
1509 inv_arc->count_valid = 1;
1510 inv_arc->count = total;
1513 if (src->count_valid)
1515 if (src->num_succ == 1 && !src->valid_chain)
1517 src->chain = valid_blocks;
1518 src->valid_chain = 1;
1524 if (!src->num_succ && !src->invalid_chain)
1526 src->chain = invalid_blocks;
1527 src->invalid_chain = 1;
1528 invalid_blocks = src;
1535 /* If the graph has been correctly solved, every block will have a
1537 for (ix = 0; ix < fn->num_blocks; ix++)
1538 if (!fn->blocks[ix].count_valid)
1540 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1541 bbg_file_name, fn->name);
1548 /* Increment totals in COVERAGE according to arc ARC. */
1551 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1553 if (arc->is_call_non_return)
1556 if (arc->src->count)
1557 coverage->calls_executed++;
1559 else if (!arc->is_unconditional)
1561 coverage->branches++;
1562 if (arc->src->count)
1563 coverage->branches_executed++;
1565 coverage->branches_taken++;
1569 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1570 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1571 If DP is zero, no decimal point is printed. Only print 100% when
1572 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1573 format TOP. Return pointer to a static string. */
1576 format_gcov (gcov_type top, gcov_type bottom, int dp)
1578 static char buffer[20];
1582 float ratio = bottom ? (float)top / bottom : 0;
1584 unsigned limit = 100;
1587 for (ix = dp; ix--; )
1590 percent = (unsigned) (ratio * limit + (float)0.5);
1591 if (percent <= 0 && top)
1593 else if (percent >= limit && top != bottom)
1594 percent = limit - 1;
1595 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1601 buffer[ix+1] = buffer[ix];
1605 buffer[ix + 1] = '.';
1609 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1615 /* Output summary info for a function. */
1618 function_summary (const coverage_t *coverage, const char *title)
1620 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1622 if (coverage->lines)
1623 fnotice (stdout, "Lines executed:%s of %d\n",
1624 format_gcov (coverage->lines_executed, coverage->lines, 2),
1627 fnotice (stdout, "No executable lines\n");
1631 if (coverage->branches)
1633 fnotice (stdout, "Branches executed:%s of %d\n",
1634 format_gcov (coverage->branches_executed,
1635 coverage->branches, 2),
1636 coverage->branches);
1637 fnotice (stdout, "Taken at least once:%s of %d\n",
1638 format_gcov (coverage->branches_taken,
1639 coverage->branches, 2),
1640 coverage->branches);
1643 fnotice (stdout, "No branches\n");
1644 if (coverage->calls)
1645 fnotice (stdout, "Calls executed:%s of %d\n",
1646 format_gcov (coverage->calls_executed, coverage->calls, 2),
1649 fnotice (stdout, "No calls\n");
1653 /* Canonicalize the filename NAME by canonicalizing directory
1654 separators, eliding . components and resolving .. components
1655 appropriately. Always returns a unique string. */
1658 canonicalize_name (const char *name)
1660 /* The canonical name cannot be longer than the incoming name. */
1661 char *result = XNEWVEC (char, strlen (name) + 1);
1662 const char *base = name, *probe;
1667 #if HAVE_DOS_BASED_FILE_SYSTEM
1668 if (base[0] && base[1] == ':')
1670 result[0] = base[0];
1676 for (dd_base = ptr; *base; base = probe)
1680 for (probe = base; *probe; probe++)
1681 if (IS_DIR_SEPARATOR (*probe))
1685 if (len == 1 && base[0] == '.')
1686 /* Elide a '.' directory */
1688 else if (len == 2 && base[0] == '.' && base[1] == '.')
1690 /* '..', we can only elide it and the previous directory, if
1691 we're not a symlink. */
1692 struct stat ATTRIBUTE_UNUSED buf;
1696 #if defined (S_ISLNK)
1697 /* S_ISLNK is not POSIX.1-1996. */
1698 || stat (result, &buf) || S_ISLNK (buf.st_mode)
1702 /* Cannot elide, or unreadable or a symlink. */
1703 dd_base = ptr + 2 + slash;
1706 while (ptr != dd_base && *ptr != '/')
1708 slash = ptr != result;
1713 /* Regular pathname component. */
1716 memcpy (ptr, base, len);
1721 for (; IS_DIR_SEPARATOR (*probe); probe++)
1729 /* Generate an output file name. INPUT_NAME is the canonicalized main
1730 input file and SRC_NAME is the canonicalized file name.
1731 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
1732 long_output_names we prepend the processed name of the input file
1733 to each output name (except when the current source file is the
1734 input file, so you don't get a double concatenation). The two
1735 components are separated by '##'. With preserve_paths we create a
1736 filename from all path components of the source file, replacing '/'
1737 with '#', and .. with '^', without it we simply take the basename
1738 component. (Remember, the canonicalized name will already have
1739 elided '.' components and converted \\ separators.) */
1742 make_gcov_file_name (const char *input_name, const char *src_name)
1747 if (flag_long_names && input_name && strcmp (src_name, input_name))
1749 /* Generate the input filename part. */
1750 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1753 ptr = mangle_name (input_name, ptr);
1754 ptr[0] = ptr[1] = '#';
1759 result = XNEWVEC (char, strlen (src_name) + 10);
1763 ptr = mangle_name (src_name, ptr);
1764 strcpy (ptr, ".gcov");
1770 mangle_name (char const *base, char *ptr)
1774 /* Generate the source filename part. */
1775 if (!flag_preserve_paths)
1777 base = lbasename (base);
1778 len = strlen (base);
1779 memcpy (ptr, base, len);
1784 /* Convert '/' to '#', convert '..' to '^',
1785 convert ':' to '~' on DOS based file system. */
1788 #if HAVE_DOS_BASED_FILE_SYSTEM
1789 if (base[0] && base[1] == ':')
1797 for (; *base; base = probe)
1801 for (probe = base; *probe; probe++)
1805 if (len == 2 && base[0] == '.' && base[1] == '.')
1809 memcpy (ptr, base, len);
1823 /* Scan through the bb_data for each line in the block, increment
1824 the line number execution count indicated by the execution count of
1825 the appropriate basic block. */
1828 add_line_counts (coverage_t *coverage, function_t *fn)
1831 line_t *line = NULL; /* This is propagated from one iteration to the
1834 /* Scan each basic block. */
1835 for (ix = 0; ix != fn->num_blocks; ix++)
1837 block_t *block = &fn->blocks[ix];
1839 const source_t *src = NULL;
1842 if (block->count && ix && ix + 1 != fn->num_blocks)
1843 fn->blocks_executed++;
1844 for (jx = 0, encoding = block->u.line.encoding;
1845 jx != block->u.line.num; jx++, encoding++)
1848 src = &sources[*++encoding];
1853 line = &src->lines[*encoding];
1859 if (!line->count && block->count)
1860 coverage->lines_executed++;
1863 line->count += block->count;
1865 free (block->u.line.encoding);
1866 block->u.cycle.arc = NULL;
1867 block->u.cycle.ident = ~0U;
1869 if (!ix || ix + 1 == fn->num_blocks)
1870 /* Entry or exit block */;
1871 else if (flag_all_blocks)
1873 line_t *block_line = line;
1876 block_line = &sources[fn->src].lines[fn->line];
1878 block->chain = block_line->u.blocks;
1879 block_line->u.blocks = block;
1881 else if (flag_branches)
1885 for (arc = block->succ; arc; arc = arc->succ_next)
1887 arc->line_next = line->u.branches;
1888 line->u.branches = arc;
1889 if (coverage && !arc->is_unconditional)
1890 add_branch_counts (coverage, arc);
1895 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1898 /* Accumulate the line counts of a file. */
1901 accumulate_line_counts (source_t *src)
1904 function_t *fn, *fn_p, *fn_n;
1907 /* Reverse the function order. */
1908 for (fn = src->functions, fn_p = NULL; fn;
1909 fn_p = fn, fn = fn_n)
1911 fn_n = fn->line_next;
1912 fn->line_next = fn_p;
1914 src->functions = fn_p;
1916 for (ix = src->num_lines, line = src->lines; ix--; line++)
1918 if (!flag_all_blocks)
1920 arc_t *arc, *arc_p, *arc_n;
1922 /* Total and reverse the branch information. */
1923 for (arc = line->u.branches, arc_p = NULL; arc;
1924 arc_p = arc, arc = arc_n)
1926 arc_n = arc->line_next;
1927 arc->line_next = arc_p;
1929 add_branch_counts (&src->coverage, arc);
1931 line->u.branches = arc_p;
1933 else if (line->u.blocks)
1935 /* The user expects the line count to be the number of times
1936 a line has been executed. Simply summing the block count
1937 will give an artificially high number. The Right Thing
1938 is to sum the entry counts to the graph of blocks on this
1939 line, then find the elementary cycles of the local graph
1940 and add the transition counts of those cycles. */
1941 block_t *block, *block_p, *block_n;
1942 gcov_type count = 0;
1944 /* Reverse the block information. */
1945 for (block = line->u.blocks, block_p = NULL; block;
1946 block_p = block, block = block_n)
1948 block_n = block->chain;
1949 block->chain = block_p;
1950 block->u.cycle.ident = ix;
1952 line->u.blocks = block_p;
1954 /* Sum the entry arcs. */
1955 for (block = line->u.blocks; block; block = block->chain)
1959 for (arc = block->pred; arc; arc = arc->pred_next)
1961 if (arc->src->u.cycle.ident != ix)
1962 count += arc->count;
1964 add_branch_counts (&src->coverage, arc);
1967 /* Initialize the cs_count. */
1968 for (arc = block->succ; arc; arc = arc->succ_next)
1969 arc->cs_count = arc->count;
1972 /* Find the loops. This uses the algorithm described in
1973 Tiernan 'An Efficient Search Algorithm to Find the
1974 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1975 the P array by having each block point to the arc that
1976 connects to the previous block. The H array is implicitly
1977 held because of the arc ordering, and the block's
1978 previous arc pointer.
1980 Although the algorithm is O(N^3) for highly connected
1981 graphs, at worst we'll have O(N^2), as most blocks have
1982 only one or two exits. Most graphs will be small.
1984 For each loop we find, locate the arc with the smallest
1985 transition count, and add that to the cumulative
1986 count. Decrease flow over the cycle and remove the arc
1987 from consideration. */
1988 for (block = line->u.blocks; block; block = block->chain)
1990 block_t *head = block;
1998 block_t *dst = arc->dst;
1999 if (/* Already used that arc. */
2001 /* Not to same graph, or before first vertex. */
2002 || dst->u.cycle.ident != ix
2003 /* Already in path. */
2004 || dst->u.cycle.arc)
2006 arc = arc->succ_next;
2012 /* Found a closing arc. */
2013 gcov_type cycle_count = arc->cs_count;
2014 arc_t *cycle_arc = arc;
2017 /* Locate the smallest arc count of the loop. */
2018 for (dst = head; (probe_arc = dst->u.cycle.arc);
2019 dst = probe_arc->src)
2020 if (cycle_count > probe_arc->cs_count)
2022 cycle_count = probe_arc->cs_count;
2023 cycle_arc = probe_arc;
2026 count += cycle_count;
2027 cycle_arc->cycle = 1;
2029 /* Remove the flow from the cycle. */
2030 arc->cs_count -= cycle_count;
2031 for (dst = head; (probe_arc = dst->u.cycle.arc);
2032 dst = probe_arc->src)
2033 probe_arc->cs_count -= cycle_count;
2035 /* Unwind to the cyclic arc. */
2036 while (head != cycle_arc->src)
2038 arc = head->u.cycle.arc;
2039 head->u.cycle.arc = NULL;
2043 arc = arc->succ_next;
2047 /* Add new block to chain. */
2048 dst->u.cycle.arc = arc;
2052 /* We could not add another vertex to the path. Remove
2053 the last vertex from the list. */
2054 arc = head->u.cycle.arc;
2057 /* It was not the first vertex. Move onto next arc. */
2058 head->u.cycle.arc = NULL;
2060 arc = arc->succ_next;
2061 goto current_vertex;
2063 /* Mark this block as unusable. */
2064 block->u.cycle.ident = ~0U;
2067 line->count = count;
2072 src->coverage.lines++;
2074 src->coverage.lines_executed++;
2079 /* Output information about ARC number IX. Returns nonzero if
2080 anything is output. */
2083 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2086 if (arc->is_call_non_return)
2088 if (arc->src->count)
2090 fnotice (gcov_file, "call %2d returned %s\n", ix,
2091 format_gcov (arc->src->count - arc->count,
2092 arc->src->count, -flag_counts));
2095 fnotice (gcov_file, "call %2d never executed\n", ix);
2097 else if (!arc->is_unconditional)
2099 if (arc->src->count)
2100 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2101 format_gcov (arc->count, arc->src->count, -flag_counts),
2102 arc->fall_through ? " (fallthrough)" : "");
2104 fnotice (gcov_file, "branch %2d never executed\n", ix);
2106 else if (flag_unconditional && !arc->dst->is_call_return)
2108 if (arc->src->count)
2109 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2110 format_gcov (arc->count, arc->src->count, -flag_counts));
2112 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2120 /* Read in the source file one line at a time, and output that line to
2121 the gcov file preceded by its execution count and other
2125 output_lines (FILE *gcov_file, const source_t *src)
2128 unsigned line_num; /* current line number. */
2129 const line_t *line; /* current line info ptr. */
2130 char string[STRING_SIZE]; /* line buffer. */
2131 char const *retval = ""; /* status of source file reading. */
2132 function_t *fn = NULL;
2134 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2135 if (!multiple_files)
2137 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2138 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2139 no_data_file ? "-" : da_file_name);
2140 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
2142 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2144 source_file = fopen (src->name, "r");
2147 fnotice (stderr, "Cannot open source file %s\n", src->name);
2150 else if (src->file_time == 0)
2151 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2154 fn = src->functions;
2156 for (line_num = 1, line = &src->lines[line_num];
2157 line_num < src->num_lines; line_num++, line++)
2159 for (; fn && fn->line == line_num; fn = fn->line_next)
2161 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
2162 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
2164 for (; arc; arc = arc->pred_next)
2166 return_count -= arc->count;
2168 fprintf (gcov_file, "function %s", fn->name);
2169 fprintf (gcov_file, " called %s",
2170 format_gcov (fn->blocks[0].count, 0, -1));
2171 fprintf (gcov_file, " returned %s",
2172 format_gcov (return_count, fn->blocks[0].count, 0));
2173 fprintf (gcov_file, " blocks executed %s",
2174 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2175 fprintf (gcov_file, "\n");
2178 /* For lines which don't exist in the .bb file, print '-' before
2179 the source line. For lines which exist but were never
2180 executed, print '#####' before the source line. Otherwise,
2181 print the execution count before the source line. There are
2182 16 spaces of indentation added before the source line so that
2183 tabs won't be messed up. */
2184 fprintf (gcov_file, "%9s:%5u:",
2185 !line->exists ? "-" : !line->count ? "#####"
2186 : format_gcov (line->count, 0, -1), line_num);
2190 /* Copy source line. */
2193 retval = fgets (string, STRING_SIZE, source_file);
2196 fputs (retval, gcov_file);
2198 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
2201 fputs ("/*EOF*/\n", gcov_file);
2203 if (flag_all_blocks)
2209 for (ix = jx = 0, block = line->u.blocks; block;
2210 block = block->chain)
2212 if (!block->is_call_return)
2213 fprintf (gcov_file, "%9s:%5u-block %2d\n",
2214 !line->exists ? "-" : !block->count ? "$$$$$"
2215 : format_gcov (block->count, 0, -1),
2218 for (arc = block->succ; arc; arc = arc->succ_next)
2219 jx += output_branch_count (gcov_file, jx, arc);
2222 else if (flag_branches)
2227 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2228 ix += output_branch_count (gcov_file, ix, arc);
2232 /* Handle all remaining source lines. There may be lines after the
2233 last line of code. */
2236 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
2238 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
2240 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
2242 retval = fgets (string, STRING_SIZE, source_file);
2245 fputs (retval, gcov_file);
2251 fclose (source_file);