Mark ChangeLog
[official-gcc.git] / gcc / gcov.c
blob7084bd05fcbf7266709b49e02c7e46eef5279fd8
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990-2013 Free Software Foundation, Inc.
4 Contributed by James E. Wilson of Cygnus Support.
5 Mangled by Bob Manson of Cygnus Support.
6 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 Gcov is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Gcov; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* ??? Print a list of the ten blocks with the highest execution counts,
23 and list the line numbers corresponding to those blocks. Also, perhaps
24 list the line numbers with the highest execution counts, only printing
25 the first if there are several which are all listed in the same block. */
27 /* ??? Should have an option to print the number of basic blocks, and the
28 percent of them that are covered. */
30 /* Need an option to show individual block counts, and show
31 probabilities of fall through arcs. */
33 #include "config.h"
34 #include "system.h"
35 #include "coretypes.h"
36 #include "tm.h"
37 #include "intl.h"
38 #include "diagnostic.h"
39 #include "version.h"
41 #include <getopt.h>
43 #define IN_GCOV 1
44 #include "gcov-io.h"
45 #include "gcov-io.c"
47 /* The gcno file is generated by -ftest-coverage option. The gcda file is
48 generated by a program compiled with -fprofile-arcs. Their formats
49 are documented in gcov-io.h. */
51 /* The functions in this file for creating and solution program flow graphs
52 are very similar to functions in the gcc source file profile.c. In
53 some places we make use of the knowledge of how profile.c works to
54 select particular algorithms here. */
56 /* The code validates that the profile information read in corresponds
57 to the code currently being compiled. Rather than checking for
58 identical files, the code below compares a checksum on the CFG
59 (based on the order of basic blocks and the arcs in the CFG). If
60 the CFG checksum in the gcda file match the CFG checksum in the
61 gcno file, the profile data will be used. */
63 /* This is the size of the buffer used to read in source file lines. */
65 struct function_info;
66 struct block_info;
67 struct source_info;
69 /* Describes an arc between two basic blocks. */
71 typedef struct arc_info
73 /* source and destination blocks. */
74 struct block_info *src;
75 struct block_info *dst;
77 /* transition counts. */
78 gcov_type count;
79 /* used in cycle search, so that we do not clobber original counts. */
80 gcov_type cs_count;
82 unsigned int count_valid : 1;
83 unsigned int on_tree : 1;
84 unsigned int fake : 1;
85 unsigned int fall_through : 1;
87 /* Arc to a catch handler. */
88 unsigned int is_throw : 1;
90 /* Arc is for a function that abnormally returns. */
91 unsigned int is_call_non_return : 1;
93 /* Arc is for catch/setjmp. */
94 unsigned int is_nonlocal_return : 1;
96 /* Is an unconditional branch. */
97 unsigned int is_unconditional : 1;
99 /* Loop making arc. */
100 unsigned int cycle : 1;
102 /* Next branch on line. */
103 struct arc_info *line_next;
105 /* Links to next arc on src and dst lists. */
106 struct arc_info *succ_next;
107 struct arc_info *pred_next;
108 } arc_t;
110 /* Describes a basic block. Contains lists of arcs to successor and
111 predecessor blocks. */
113 typedef struct block_info
115 /* Chain of exit and entry arcs. */
116 arc_t *succ;
117 arc_t *pred;
119 /* Number of unprocessed exit and entry arcs. */
120 gcov_type num_succ;
121 gcov_type num_pred;
123 /* Block execution count. */
124 gcov_type count;
125 unsigned flags : 12;
126 unsigned count_valid : 1;
127 unsigned valid_chain : 1;
128 unsigned invalid_chain : 1;
129 unsigned exceptional : 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;
138 union
140 struct
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
145 file. */
146 unsigned *encoding;
147 unsigned num;
148 } line; /* Valid until blocks are linked onto lines */
149 struct
151 /* Single line graph cycle workspace. Used for all-blocks
152 mode. */
153 arc_t *arc;
154 unsigned ident;
155 } cycle; /* Used in all-blocks mode, after blocks are linked onto
156 lines. */
157 } u;
159 /* Temporary chain for solving graph, and for chaining blocks on one
160 line. */
161 struct block_info *chain;
163 } block_t;
165 /* Describes a single function. Contains an array of basic blocks. */
167 typedef struct function_info
169 /* Name of function. */
170 char *name;
171 unsigned ident;
172 unsigned lineno_checksum;
173 unsigned cfg_checksum;
175 /* The graph contains at least one fake incoming edge. */
176 unsigned has_catch : 1;
178 /* Array of basic blocks. Like in GCC, the entry block is
179 at blocks[0] and the exit block is at blocks[1]. */
180 #define ENTRY_BLOCK (0)
181 #define EXIT_BLOCK (1)
182 block_t *blocks;
183 unsigned num_blocks;
184 unsigned blocks_executed;
186 /* Raw arc coverage counts. */
187 gcov_type *counts;
188 unsigned num_counts;
190 /* First line number & file. */
191 unsigned line;
192 unsigned src;
194 /* Next function in same source file. */
195 struct function_info *line_next;
197 /* Next function. */
198 struct function_info *next;
199 } function_t;
201 /* Describes coverage of a file or function. */
203 typedef struct coverage_info
205 int lines;
206 int lines_executed;
208 int branches;
209 int branches_executed;
210 int branches_taken;
212 int calls;
213 int calls_executed;
215 char *name;
216 } coverage_t;
218 /* Describes a single line of source. Contains a chain of basic blocks
219 with code on it. */
221 typedef struct line_info
223 gcov_type count; /* execution count */
224 union
226 arc_t *branches; /* branches from blocks that end on this
227 line. Used for branch-counts when not
228 all-blocks mode. */
229 block_t *blocks; /* blocks which start on this line. Used
230 in all-blocks mode. */
231 } u;
232 unsigned exists : 1;
233 unsigned unexceptional : 1;
234 } line_t;
236 /* Describes a file mentioned in the block graph. Contains an array
237 of line info. */
239 typedef struct source_info
241 /* Canonical name of source file. */
242 char *name;
243 time_t file_time;
245 /* Array of line information. */
246 line_t *lines;
247 unsigned num_lines;
249 coverage_t coverage;
251 /* Functions in this source file. These are in ascending line
252 number order. */
253 function_t *functions;
254 } source_t;
256 typedef struct name_map
258 char *name; /* Source file name */
259 unsigned src; /* Source file */
260 } name_map_t;
262 /* Holds a list of function basic block graphs. */
264 static function_t *functions;
265 static function_t **fn_end = &functions;
267 static source_t *sources; /* Array of source files */
268 static unsigned n_sources; /* Number of sources */
269 static unsigned a_sources; /* Allocated sources */
271 static name_map_t *names; /* Mapping of file names to sources */
272 static unsigned n_names; /* Number of names */
273 static unsigned a_names; /* Allocated names */
275 /* This holds data summary information. */
277 static unsigned object_runs;
278 static unsigned program_count;
280 static unsigned total_lines;
281 static unsigned total_executed;
283 /* Modification time of graph file. */
285 static time_t bbg_file_time;
287 /* Name of the notes (gcno) output file. The "bbg" prefix is for
288 historical reasons, when the notes file contained only the
289 basic block graph notes. */
291 static char *bbg_file_name;
293 /* Stamp of the bbg file */
294 static unsigned bbg_stamp;
296 /* Name and file pointer of the input file for the count data (gcda). */
298 static char *da_file_name;
300 /* Data file is missing. */
302 static int no_data_file;
304 /* If there is several input files, compute and display results after
305 reading all data files. This way if two or more gcda file refer to
306 the same source file (eg inline subprograms in a .h file), the
307 counts are added. */
309 static int multiple_files = 0;
311 /* Output branch probabilities. */
313 static int flag_branches = 0;
315 /* Show unconditional branches too. */
316 static int flag_unconditional = 0;
318 /* Output a gcov file if this is true. This is on by default, and can
319 be turned off by the -n option. */
321 static int flag_gcov_file = 1;
323 /* Output progress indication if this is true. This is off by default
324 and can be turned on by the -d option. */
326 static int flag_display_progress = 0;
328 /* For included files, make the gcov output file name include the name
329 of the input source file. For example, if x.h is included in a.c,
330 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
332 static int flag_long_names = 0;
334 /* Output count information for every basic block, not merely those
335 that contain line number information. */
337 static int flag_all_blocks = 0;
339 /* Output summary info for each function. */
341 static int flag_function_summary = 0;
343 /* Object directory file prefix. This is the directory/file where the
344 graph and data files are looked for, if nonzero. */
346 static char *object_directory = 0;
348 /* Source directory prefix. This is removed from source pathnames
349 that match, when generating the output file name. */
351 static char *source_prefix = 0;
352 static size_t source_length = 0;
354 /* Only show data for sources with relative pathnames. Absolute ones
355 usually indicate a system header file, which although it may
356 contain inline functions, is usually uninteresting. */
357 static int flag_relative_only = 0;
359 /* Preserve all pathname components. Needed when object files and
360 source files are in subdirectories. '/' is mangled as '#', '.' is
361 elided and '..' mangled to '^'. */
363 static int flag_preserve_paths = 0;
365 /* Output the number of times a branch was taken as opposed to the percentage
366 of times it was taken. */
368 static int flag_counts = 0;
370 /* Forward declarations. */
371 static int process_args (int, char **);
372 static void print_usage (int) ATTRIBUTE_NORETURN;
373 static void print_version (void) ATTRIBUTE_NORETURN;
374 static void process_file (const char *);
375 static void generate_results (const char *);
376 static void create_file_names (const char *);
377 static int name_search (const void *, const void *);
378 static int name_sort (const void *, const void *);
379 static char *canonicalize_name (const char *);
380 static unsigned find_source (const char *);
381 static function_t *read_graph_file (void);
382 static int read_count_file (function_t *);
383 static void solve_flow_graph (function_t *);
384 static void find_exception_blocks (function_t *);
385 static void add_branch_counts (coverage_t *, const arc_t *);
386 static void add_line_counts (coverage_t *, function_t *);
387 static void executed_summary (unsigned, unsigned);
388 static void function_summary (const coverage_t *, const char *);
389 static const char *format_gcov (gcov_type, gcov_type, int);
390 static void accumulate_line_counts (source_t *);
391 static int output_branch_count (FILE *, int, const arc_t *);
392 static void output_lines (FILE *, const source_t *);
393 static char *make_gcov_file_name (const char *, const char *);
394 static char *mangle_name (const char *, char *);
395 static void release_structures (void);
396 static void release_function (function_t *);
397 extern int main (int, char **);
400 main (int argc, char **argv)
402 int argno;
403 int first_arg;
404 const char *p;
406 p = argv[0] + strlen (argv[0]);
407 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
408 --p;
409 progname = p;
411 xmalloc_set_program_name (progname);
413 /* Unlock the stdio streams. */
414 unlock_std_streams ();
416 gcc_init_libintl ();
418 diagnostic_initialize (global_dc, 0);
420 /* Handle response files. */
421 expandargv (&argc, &argv);
423 a_names = 10;
424 names = XNEWVEC (name_map_t, a_names);
425 a_sources = 10;
426 sources = XNEWVEC (source_t, a_sources);
428 argno = process_args (argc, argv);
429 if (optind == argc)
430 print_usage (true);
432 if (argc - argno > 1)
433 multiple_files = 1;
435 first_arg = argno;
437 for (; argno != argc; argno++)
439 if (flag_display_progress)
440 printf("Processing file %d out of %d\n",
441 argno - first_arg + 1, argc - first_arg);
442 process_file (argv[argno]);
445 generate_results (multiple_files ? NULL : argv[argc - 1]);
447 release_structures ();
449 return 0;
452 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
453 otherwise the output of --help. */
455 static void
456 print_usage (int error_p)
458 FILE *file = error_p ? stderr : stdout;
459 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
461 fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
462 fnotice (file, "Print code coverage information.\n\n");
463 fnotice (file, " -h, --help Print this help, then exit\n");
464 fnotice (file, " -v, --version Print version number, then exit\n");
465 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
466 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
467 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
468 rather than percentages\n");
469 fnotice (file, " -n, --no-output Do not create an output file\n");
470 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
471 source files\n");
472 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
473 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
474 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
475 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
476 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
477 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
478 fnotice (file, " -d, --display-progress Display progress information\n");
479 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
480 bug_report_url);
481 exit (status);
484 /* Print version information and exit. */
486 static void
487 print_version (void)
489 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
490 fprintf (stdout, "Copyright %s 2013 Free Software Foundation, Inc.\n",
491 _("(C)"));
492 fnotice (stdout,
493 _("This is free software; see the source for copying conditions.\n"
494 "There is NO warranty; not even for MERCHANTABILITY or \n"
495 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
496 exit (SUCCESS_EXIT_CODE);
499 static const struct option options[] =
501 { "help", no_argument, NULL, 'h' },
502 { "version", no_argument, NULL, 'v' },
503 { "all-blocks", no_argument, NULL, 'a' },
504 { "branch-probabilities", no_argument, NULL, 'b' },
505 { "branch-counts", no_argument, NULL, 'c' },
506 { "no-output", no_argument, NULL, 'n' },
507 { "long-file-names", no_argument, NULL, 'l' },
508 { "function-summaries", no_argument, NULL, 'f' },
509 { "preserve-paths", no_argument, NULL, 'p' },
510 { "relative-only", no_argument, NULL, 'r' },
511 { "object-directory", required_argument, NULL, 'o' },
512 { "object-file", required_argument, NULL, 'o' },
513 { "source-prefix", required_argument, NULL, 's' },
514 { "unconditional-branches", no_argument, NULL, 'u' },
515 { "display-progress", no_argument, NULL, 'd' },
516 { 0, 0, 0, 0 }
519 /* Process args, return index to first non-arg. */
521 static int
522 process_args (int argc, char **argv)
524 int opt;
526 while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
528 switch (opt)
530 case 'a':
531 flag_all_blocks = 1;
532 break;
533 case 'b':
534 flag_branches = 1;
535 break;
536 case 'c':
537 flag_counts = 1;
538 break;
539 case 'f':
540 flag_function_summary = 1;
541 break;
542 case 'h':
543 print_usage (false);
544 /* print_usage will exit. */
545 case 'l':
546 flag_long_names = 1;
547 break;
548 case 'n':
549 flag_gcov_file = 0;
550 break;
551 case 'o':
552 object_directory = optarg;
553 break;
554 case 's':
555 source_prefix = optarg;
556 source_length = strlen (source_prefix);
557 break;
558 case 'r':
559 flag_relative_only = 1;
560 break;
561 case 'p':
562 flag_preserve_paths = 1;
563 break;
564 case 'u':
565 flag_unconditional = 1;
566 break;
567 case 'd':
568 flag_display_progress = 1;
569 break;
570 case 'v':
571 print_version ();
572 /* print_version will exit. */
573 default:
574 print_usage (true);
575 /* print_usage will exit. */
579 return optind;
582 /* Process a single input file. */
584 static void
585 process_file (const char *file_name)
587 function_t *fns;
589 create_file_names (file_name);
590 fns = read_graph_file ();
591 if (!fns)
592 return;
594 read_count_file (fns);
595 while (fns)
597 function_t *fn = fns;
599 fns = fn->next;
600 fn->next = NULL;
601 if (fn->counts)
603 unsigned src = fn->src;
604 unsigned line = fn->line;
605 unsigned block_no;
606 function_t *probe, **prev;
608 /* Now insert it into the source file's list of
609 functions. Normally functions will be encountered in
610 ascending order, so a simple scan is quick. Note we're
611 building this list in reverse order. */
612 for (prev = &sources[src].functions;
613 (probe = *prev); prev = &probe->line_next)
614 if (probe->line <= line)
615 break;
616 fn->line_next = probe;
617 *prev = fn;
619 /* Mark last line in files touched by function. */
620 for (block_no = 0; block_no != fn->num_blocks; block_no++)
622 unsigned *enc = fn->blocks[block_no].u.line.encoding;
623 unsigned num = fn->blocks[block_no].u.line.num;
625 for (; num--; enc++)
626 if (!*enc)
628 if (enc[1] != src)
630 if (line >= sources[src].num_lines)
631 sources[src].num_lines = line + 1;
632 line = 0;
633 src = enc[1];
635 enc++;
636 num--;
638 else if (*enc > line)
639 line = *enc;
641 if (line >= sources[src].num_lines)
642 sources[src].num_lines = line + 1;
644 solve_flow_graph (fn);
645 if (fn->has_catch)
646 find_exception_blocks (fn);
647 *fn_end = fn;
648 fn_end = &fn->next;
650 else
651 /* The function was not in the executable -- some other
652 instance must have been selected. */
653 release_function (fn);
657 static void
658 generate_results (const char *file_name)
660 unsigned ix;
661 source_t *src;
662 function_t *fn;
664 for (ix = n_sources, src = sources; ix--; src++)
665 if (src->num_lines)
666 src->lines = XCNEWVEC (line_t, src->num_lines);
668 for (fn = functions; fn; fn = fn->next)
670 coverage_t coverage;
672 memset (&coverage, 0, sizeof (coverage));
673 coverage.name = fn->name;
674 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
675 if (flag_function_summary)
677 function_summary (&coverage, "Function");
678 fnotice (stdout, "\n");
682 if (file_name)
684 name_map_t *name_map = (name_map_t *)bsearch
685 (file_name, names, n_names, sizeof (*names), name_search);
686 if (name_map)
687 file_name = sources[name_map->src].coverage.name;
688 else
689 file_name = canonicalize_name (file_name);
692 for (ix = n_sources, src = sources; ix--; src++)
694 if (flag_relative_only)
696 /* Ignore this source, if it is an absolute path (after
697 source prefix removal). */
698 char first = src->coverage.name[0];
700 #if HAVE_DOS_BASED_FILE_SYSTEM
701 if (first && src->coverage.name[1] == ':')
702 first = src->coverage.name[2];
703 #endif
704 if (IS_DIR_SEPARATOR (first))
705 continue;
708 accumulate_line_counts (src);
709 function_summary (&src->coverage, "File");
710 total_lines += src->coverage.lines;
711 total_executed += src->coverage.lines_executed;
712 if (flag_gcov_file)
714 char *gcov_file_name
715 = make_gcov_file_name (file_name, src->coverage.name);
717 if (src->coverage.lines)
719 FILE *gcov_file = fopen (gcov_file_name, "w");
721 if (gcov_file)
723 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
724 output_lines (gcov_file, src);
725 if (ferror (gcov_file))
726 fnotice (stderr, "Error writing output file '%s'\n",
727 gcov_file_name);
728 fclose (gcov_file);
730 else
731 fnotice (stderr, "Could not open output file '%s'\n",
732 gcov_file_name);
734 else
736 unlink (gcov_file_name);
737 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
739 free (gcov_file_name);
741 fnotice (stdout, "\n");
744 if (!file_name)
745 executed_summary (total_lines, total_executed);
748 /* Release a function structure */
750 static void
751 release_function (function_t *fn)
753 unsigned ix;
754 block_t *block;
756 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
758 arc_t *arc, *arc_n;
760 for (arc = block->succ; arc; arc = arc_n)
762 arc_n = arc->succ_next;
763 free (arc);
766 free (fn->blocks);
767 free (fn->counts);
770 /* Release all memory used. */
772 static void
773 release_structures (void)
775 unsigned ix;
776 function_t *fn;
778 for (ix = n_sources; ix--;)
779 free (sources[ix].lines);
780 free (sources);
782 for (ix = n_names; ix--;)
783 free (names[ix].name);
784 free (names);
786 while ((fn = functions))
788 functions = fn->next;
789 release_function (fn);
793 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
794 is not specified, these are named from FILE_NAME sans extension. If
795 OBJECT_DIRECTORY is specified and is a directory, the files are in that
796 directory, but named from the basename of the FILE_NAME, sans extension.
797 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
798 and the data files are named from that. */
800 static void
801 create_file_names (const char *file_name)
803 char *cptr;
804 char *name;
805 int length = strlen (file_name);
806 int base;
808 /* Free previous file names. */
809 free (bbg_file_name);
810 free (da_file_name);
811 da_file_name = bbg_file_name = NULL;
812 bbg_file_time = 0;
813 bbg_stamp = 0;
815 if (object_directory && object_directory[0])
817 struct stat status;
819 length += strlen (object_directory) + 2;
820 name = XNEWVEC (char, length);
821 name[0] = 0;
823 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
824 strcat (name, object_directory);
825 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
826 strcat (name, "/");
828 else
830 name = XNEWVEC (char, length + 1);
831 strcpy (name, file_name);
832 base = 0;
835 if (base)
837 /* Append source file name. */
838 const char *cptr = lbasename (file_name);
839 strcat (name, cptr ? cptr : file_name);
842 /* Remove the extension. */
843 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
844 if (cptr)
845 *cptr = 0;
847 length = strlen (name);
849 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
850 strcpy (bbg_file_name, name);
851 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
853 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
854 strcpy (da_file_name, name);
855 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
857 free (name);
858 return;
861 /* A is a string and B is a pointer to name_map_t. Compare for file
862 name orderability. */
864 static int
865 name_search (const void *a_, const void *b_)
867 const char *a = (const char *)a_;
868 const name_map_t *b = (const name_map_t *)b_;
870 #if HAVE_DOS_BASED_FILE_SYSTEM
871 return strcasecmp (a, b->name);
872 #else
873 return strcmp (a, b->name);
874 #endif
877 /* A and B are a pointer to name_map_t. Compare for file name
878 orderability. */
880 static int
881 name_sort (const void *a_, const void *b_)
883 const name_map_t *a = (const name_map_t *)a_;
884 return name_search (a->name, b_);
887 /* Find or create a source file structure for FILE_NAME. Copies
888 FILE_NAME on creation */
890 static unsigned
891 find_source (const char *file_name)
893 name_map_t *name_map;
894 char *canon;
895 unsigned idx;
896 struct stat status;
898 if (!file_name)
899 file_name = "<unknown>";
900 name_map = (name_map_t *)bsearch
901 (file_name, names, n_names, sizeof (*names), name_search);
902 if (name_map)
904 idx = name_map->src;
905 goto check_date;
908 if (n_names + 2 > a_names)
910 /* Extend the name map array -- we'll be inserting one or two
911 entries. */
912 a_names *= 2;
913 name_map = XNEWVEC (name_map_t, a_names);
914 memcpy (name_map, names, n_names * sizeof (*names));
915 free (names);
916 names = name_map;
919 /* Not found, try the canonical name. */
920 canon = canonicalize_name (file_name);
921 name_map = (name_map_t *)bsearch
922 (canon, names, n_names, sizeof (*names), name_search);
923 if (!name_map)
925 /* Not found with canonical name, create a new source. */
926 source_t *src;
928 if (n_sources == a_sources)
930 a_sources *= 2;
931 src = XNEWVEC (source_t, a_sources);
932 memcpy (src, sources, n_sources * sizeof (*sources));
933 free (sources);
934 sources = src;
937 idx = n_sources;
939 name_map = &names[n_names++];
940 name_map->name = canon;
941 name_map->src = idx;
943 src = &sources[n_sources++];
944 memset (src, 0, sizeof (*src));
945 src->name = canon;
946 src->coverage.name = src->name;
947 if (source_length
948 #if HAVE_DOS_BASED_FILE_SYSTEM
949 /* You lose if separators don't match exactly in the
950 prefix. */
951 && !strncasecmp (source_prefix, src->coverage.name, source_length)
952 #else
953 && !strncmp (source_prefix, src->coverage.name, source_length)
954 #endif
955 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
956 src->coverage.name += source_length + 1;
957 if (!stat (src->name, &status))
958 src->file_time = status.st_mtime;
960 else
961 idx = name_map->src;
963 if (name_search (file_name, name_map))
965 /* Append the non-canonical name. */
966 name_map = &names[n_names++];
967 name_map->name = xstrdup (file_name);
968 name_map->src = idx;
971 /* Resort the name map. */
972 qsort (names, n_names, sizeof (*names), name_sort);
974 check_date:
975 if (sources[idx].file_time > bbg_file_time)
977 static int info_emitted;
979 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
980 file_name, bbg_file_name);
981 if (!info_emitted)
983 fnotice (stderr,
984 "(the message is only displayed one per source file)\n");
985 info_emitted = 1;
987 sources[idx].file_time = 0;
990 return idx;
993 /* Read the notes file. Return list of functions read -- in reverse order. */
995 static function_t *
996 read_graph_file (void)
998 unsigned version;
999 unsigned current_tag = 0;
1000 function_t *fn = NULL;
1001 function_t *fns = NULL;
1002 function_t **fns_end = &fns;
1003 unsigned src_idx = 0;
1004 unsigned ix;
1005 unsigned tag;
1007 if (!gcov_open (bbg_file_name, 1))
1009 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1010 return fns;
1012 bbg_file_time = gcov_time ();
1013 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1015 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1016 gcov_close ();
1017 return fns;
1020 version = gcov_read_unsigned ();
1021 if (version != GCOV_VERSION)
1023 char v[4], e[4];
1025 GCOV_UNSIGNED2STRING (v, version);
1026 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1028 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1029 bbg_file_name, v, e);
1031 bbg_stamp = gcov_read_unsigned ();
1033 while ((tag = gcov_read_unsigned ()))
1035 unsigned length = gcov_read_unsigned ();
1036 gcov_position_t base = gcov_position ();
1038 if (tag == GCOV_TAG_FUNCTION)
1040 char *function_name;
1041 unsigned ident, lineno;
1042 unsigned lineno_checksum, cfg_checksum;
1044 ident = gcov_read_unsigned ();
1045 lineno_checksum = gcov_read_unsigned ();
1046 cfg_checksum = gcov_read_unsigned ();
1047 function_name = xstrdup (gcov_read_string ());
1048 src_idx = find_source (gcov_read_string ());
1049 lineno = gcov_read_unsigned ();
1051 fn = XCNEW (function_t);
1052 fn->name = function_name;
1053 fn->ident = ident;
1054 fn->lineno_checksum = lineno_checksum;
1055 fn->cfg_checksum = cfg_checksum;
1056 fn->src = src_idx;
1057 fn->line = lineno;
1059 fn->line_next = NULL;
1060 fn->next = NULL;
1061 *fns_end = fn;
1062 fns_end = &fn->next;
1063 current_tag = tag;
1065 else if (fn && tag == GCOV_TAG_BLOCKS)
1067 if (fn->blocks)
1068 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1069 bbg_file_name, fn->name);
1070 else
1072 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1073 fn->num_blocks = num_blocks;
1075 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
1076 for (ix = 0; ix != num_blocks; ix++)
1077 fn->blocks[ix].flags = gcov_read_unsigned ();
1080 else if (fn && tag == GCOV_TAG_ARCS)
1082 unsigned src = gcov_read_unsigned ();
1083 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1084 block_t *src_blk = &fn->blocks[src];
1085 unsigned mark_catches = 0;
1086 struct arc_info *arc;
1088 if (src >= fn->num_blocks || fn->blocks[src].succ)
1089 goto corrupt;
1091 while (num_dests--)
1093 unsigned dest = gcov_read_unsigned ();
1094 unsigned flags = gcov_read_unsigned ();
1096 if (dest >= fn->num_blocks)
1097 goto corrupt;
1098 arc = XCNEW (arc_t);
1100 arc->dst = &fn->blocks[dest];
1101 arc->src = src_blk;
1103 arc->count = 0;
1104 arc->count_valid = 0;
1105 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1106 arc->fake = !!(flags & GCOV_ARC_FAKE);
1107 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1109 arc->succ_next = src_blk->succ;
1110 src_blk->succ = arc;
1111 src_blk->num_succ++;
1113 arc->pred_next = fn->blocks[dest].pred;
1114 fn->blocks[dest].pred = arc;
1115 fn->blocks[dest].num_pred++;
1117 if (arc->fake)
1119 if (src)
1121 /* Exceptional exit from this function, the
1122 source block must be a call. */
1123 fn->blocks[src].is_call_site = 1;
1124 arc->is_call_non_return = 1;
1125 mark_catches = 1;
1127 else
1129 /* Non-local return from a callee of this
1130 function. The destination block is a setjmp. */
1131 arc->is_nonlocal_return = 1;
1132 fn->blocks[dest].is_nonlocal_return = 1;
1136 if (!arc->on_tree)
1137 fn->num_counts++;
1140 if (mark_catches)
1142 /* We have a fake exit from this block. The other
1143 non-fall through exits must be to catch handlers.
1144 Mark them as catch arcs. */
1146 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1147 if (!arc->fake && !arc->fall_through)
1149 arc->is_throw = 1;
1150 fn->has_catch = 1;
1154 else if (fn && tag == GCOV_TAG_LINES)
1156 unsigned blockno = gcov_read_unsigned ();
1157 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1159 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1160 goto corrupt;
1162 for (ix = 0; ; )
1164 unsigned lineno = gcov_read_unsigned ();
1166 if (lineno)
1168 if (!ix)
1170 line_nos[ix++] = 0;
1171 line_nos[ix++] = src_idx;
1173 line_nos[ix++] = lineno;
1175 else
1177 const char *file_name = gcov_read_string ();
1179 if (!file_name)
1180 break;
1181 src_idx = find_source (file_name);
1182 line_nos[ix++] = 0;
1183 line_nos[ix++] = src_idx;
1187 fn->blocks[blockno].u.line.encoding = line_nos;
1188 fn->blocks[blockno].u.line.num = ix;
1190 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1192 fn = NULL;
1193 current_tag = 0;
1195 gcov_sync (base, length);
1196 if (gcov_is_error ())
1198 corrupt:;
1199 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1200 break;
1203 gcov_close ();
1205 if (!fns)
1206 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1208 return fns;
1211 /* Reads profiles from the count file and attach to each
1212 function. Return nonzero if fatal error. */
1214 static int
1215 read_count_file (function_t *fns)
1217 unsigned ix;
1218 unsigned version;
1219 unsigned tag;
1220 function_t *fn = NULL;
1221 int error = 0;
1223 if (!gcov_open (da_file_name, 1))
1225 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1226 da_file_name);
1227 no_data_file = 1;
1228 return 0;
1230 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1232 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1233 cleanup:;
1234 gcov_close ();
1235 return 1;
1237 version = gcov_read_unsigned ();
1238 if (version != GCOV_VERSION)
1240 char v[4], e[4];
1242 GCOV_UNSIGNED2STRING (v, version);
1243 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1245 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1246 da_file_name, v, e);
1248 tag = gcov_read_unsigned ();
1249 if (tag != bbg_stamp)
1251 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1252 goto cleanup;
1255 while ((tag = gcov_read_unsigned ()))
1257 unsigned length = gcov_read_unsigned ();
1258 unsigned long base = gcov_position ();
1260 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1262 struct gcov_summary summary;
1263 gcov_read_summary (&summary);
1264 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1265 program_count++;
1267 else if (tag == GCOV_TAG_FUNCTION && !length)
1268 ; /* placeholder */
1269 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1271 unsigned ident;
1272 struct function_info *fn_n;
1274 /* Try to find the function in the list. To speed up the
1275 search, first start from the last function found. */
1276 ident = gcov_read_unsigned ();
1277 fn_n = fns;
1278 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1280 if (fn)
1282 else if ((fn = fn_n))
1283 fn_n = NULL;
1284 else
1286 fnotice (stderr, "%s:unknown function '%u'\n",
1287 da_file_name, ident);
1288 break;
1290 if (fn->ident == ident)
1291 break;
1294 if (!fn)
1296 else if (gcov_read_unsigned () != fn->lineno_checksum
1297 || gcov_read_unsigned () != fn->cfg_checksum)
1299 mismatch:;
1300 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1301 da_file_name, fn->name);
1302 goto cleanup;
1305 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1307 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1308 goto mismatch;
1310 if (!fn->counts)
1311 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1313 for (ix = 0; ix != fn->num_counts; ix++)
1314 fn->counts[ix] += gcov_read_counter ();
1316 gcov_sync (base, length);
1317 if ((error = gcov_is_error ()))
1319 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1320 da_file_name);
1321 goto cleanup;
1325 gcov_close ();
1326 return 0;
1329 /* Solve the flow graph. Propagate counts from the instrumented arcs
1330 to the blocks and the uninstrumented arcs. */
1332 static void
1333 solve_flow_graph (function_t *fn)
1335 unsigned ix;
1336 arc_t *arc;
1337 gcov_type *count_ptr = fn->counts;
1338 block_t *blk;
1339 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1340 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1342 /* The arcs were built in reverse order. Fix that now. */
1343 for (ix = fn->num_blocks; ix--;)
1345 arc_t *arc_p, *arc_n;
1347 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1348 arc_p = arc, arc = arc_n)
1350 arc_n = arc->succ_next;
1351 arc->succ_next = arc_p;
1353 fn->blocks[ix].succ = arc_p;
1355 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1356 arc_p = arc, arc = arc_n)
1358 arc_n = arc->pred_next;
1359 arc->pred_next = arc_p;
1361 fn->blocks[ix].pred = arc_p;
1364 if (fn->num_blocks < 2)
1365 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1366 bbg_file_name, fn->name);
1367 else
1369 if (fn->blocks[ENTRY_BLOCK].num_pred)
1370 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1371 bbg_file_name, fn->name);
1372 else
1373 /* We can't deduce the entry block counts from the lack of
1374 predecessors. */
1375 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1377 if (fn->blocks[EXIT_BLOCK].num_succ)
1378 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1379 bbg_file_name, fn->name);
1380 else
1381 /* Likewise, we can't deduce exit block counts from the lack
1382 of its successors. */
1383 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1386 /* Propagate the measured counts, this must be done in the same
1387 order as the code in profile.c */
1388 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1390 block_t const *prev_dst = NULL;
1391 int out_of_order = 0;
1392 int non_fake_succ = 0;
1394 for (arc = blk->succ; arc; arc = arc->succ_next)
1396 if (!arc->fake)
1397 non_fake_succ++;
1399 if (!arc->on_tree)
1401 if (count_ptr)
1402 arc->count = *count_ptr++;
1403 arc->count_valid = 1;
1404 blk->num_succ--;
1405 arc->dst->num_pred--;
1407 if (prev_dst && prev_dst > arc->dst)
1408 out_of_order = 1;
1409 prev_dst = arc->dst;
1411 if (non_fake_succ == 1)
1413 /* If there is only one non-fake exit, it is an
1414 unconditional branch. */
1415 for (arc = blk->succ; arc; arc = arc->succ_next)
1416 if (!arc->fake)
1418 arc->is_unconditional = 1;
1419 /* If this block is instrumenting a call, it might be
1420 an artificial block. It is not artificial if it has
1421 a non-fallthrough exit, or the destination of this
1422 arc has more than one entry. Mark the destination
1423 block as a return site, if none of those conditions
1424 hold. */
1425 if (blk->is_call_site && arc->fall_through
1426 && arc->dst->pred == arc && !arc->pred_next)
1427 arc->dst->is_call_return = 1;
1431 /* Sort the successor arcs into ascending dst order. profile.c
1432 normally produces arcs in the right order, but sometimes with
1433 one or two out of order. We're not using a particularly
1434 smart sort. */
1435 if (out_of_order)
1437 arc_t *start = blk->succ;
1438 unsigned changes = 1;
1440 while (changes)
1442 arc_t *arc, *arc_p, *arc_n;
1444 changes = 0;
1445 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1447 if (arc->dst > arc_n->dst)
1449 changes = 1;
1450 if (arc_p)
1451 arc_p->succ_next = arc_n;
1452 else
1453 start = arc_n;
1454 arc->succ_next = arc_n->succ_next;
1455 arc_n->succ_next = arc;
1456 arc_p = arc_n;
1458 else
1460 arc_p = arc;
1461 arc = arc_n;
1465 blk->succ = start;
1468 /* Place it on the invalid chain, it will be ignored if that's
1469 wrong. */
1470 blk->invalid_chain = 1;
1471 blk->chain = invalid_blocks;
1472 invalid_blocks = blk;
1475 while (invalid_blocks || valid_blocks)
1477 while ((blk = invalid_blocks))
1479 gcov_type total = 0;
1480 const arc_t *arc;
1482 invalid_blocks = blk->chain;
1483 blk->invalid_chain = 0;
1484 if (!blk->num_succ)
1485 for (arc = blk->succ; arc; arc = arc->succ_next)
1486 total += arc->count;
1487 else if (!blk->num_pred)
1488 for (arc = blk->pred; arc; arc = arc->pred_next)
1489 total += arc->count;
1490 else
1491 continue;
1493 blk->count = total;
1494 blk->count_valid = 1;
1495 blk->chain = valid_blocks;
1496 blk->valid_chain = 1;
1497 valid_blocks = blk;
1499 while ((blk = valid_blocks))
1501 gcov_type total;
1502 arc_t *arc, *inv_arc;
1504 valid_blocks = blk->chain;
1505 blk->valid_chain = 0;
1506 if (blk->num_succ == 1)
1508 block_t *dst;
1510 total = blk->count;
1511 inv_arc = NULL;
1512 for (arc = blk->succ; arc; arc = arc->succ_next)
1514 total -= arc->count;
1515 if (!arc->count_valid)
1516 inv_arc = arc;
1518 dst = inv_arc->dst;
1519 inv_arc->count_valid = 1;
1520 inv_arc->count = total;
1521 blk->num_succ--;
1522 dst->num_pred--;
1523 if (dst->count_valid)
1525 if (dst->num_pred == 1 && !dst->valid_chain)
1527 dst->chain = valid_blocks;
1528 dst->valid_chain = 1;
1529 valid_blocks = dst;
1532 else
1534 if (!dst->num_pred && !dst->invalid_chain)
1536 dst->chain = invalid_blocks;
1537 dst->invalid_chain = 1;
1538 invalid_blocks = dst;
1542 if (blk->num_pred == 1)
1544 block_t *src;
1546 total = blk->count;
1547 inv_arc = NULL;
1548 for (arc = blk->pred; arc; arc = arc->pred_next)
1550 total -= arc->count;
1551 if (!arc->count_valid)
1552 inv_arc = arc;
1554 src = inv_arc->src;
1555 inv_arc->count_valid = 1;
1556 inv_arc->count = total;
1557 blk->num_pred--;
1558 src->num_succ--;
1559 if (src->count_valid)
1561 if (src->num_succ == 1 && !src->valid_chain)
1563 src->chain = valid_blocks;
1564 src->valid_chain = 1;
1565 valid_blocks = src;
1568 else
1570 if (!src->num_succ && !src->invalid_chain)
1572 src->chain = invalid_blocks;
1573 src->invalid_chain = 1;
1574 invalid_blocks = src;
1581 /* If the graph has been correctly solved, every block will have a
1582 valid count. */
1583 for (ix = 0; ix < fn->num_blocks; ix++)
1584 if (!fn->blocks[ix].count_valid)
1586 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1587 bbg_file_name, fn->name);
1588 break;
1592 /* Mark all the blocks only reachable via an incoming catch. */
1594 static void
1595 find_exception_blocks (function_t *fn)
1597 unsigned ix;
1598 block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1600 /* First mark all blocks as exceptional. */
1601 for (ix = fn->num_blocks; ix--;)
1602 fn->blocks[ix].exceptional = 1;
1604 /* Now mark all the blocks reachable via non-fake edges */
1605 queue[0] = fn->blocks;
1606 queue[0]->exceptional = 0;
1607 for (ix = 1; ix;)
1609 block_t *block = queue[--ix];
1610 const arc_t *arc;
1612 for (arc = block->succ; arc; arc = arc->succ_next)
1613 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1615 arc->dst->exceptional = 0;
1616 queue[ix++] = arc->dst;
1622 /* Increment totals in COVERAGE according to arc ARC. */
1624 static void
1625 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1627 if (arc->is_call_non_return)
1629 coverage->calls++;
1630 if (arc->src->count)
1631 coverage->calls_executed++;
1633 else if (!arc->is_unconditional)
1635 coverage->branches++;
1636 if (arc->src->count)
1637 coverage->branches_executed++;
1638 if (arc->count)
1639 coverage->branches_taken++;
1643 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1644 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1645 If DP is zero, no decimal point is printed. Only print 100% when
1646 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1647 format TOP. Return pointer to a static string. */
1649 static char const *
1650 format_gcov (gcov_type top, gcov_type bottom, int dp)
1652 static char buffer[20];
1654 if (dp >= 0)
1656 float ratio = bottom ? (float)top / bottom : 0;
1657 int ix;
1658 unsigned limit = 100;
1659 unsigned percent;
1661 for (ix = dp; ix--; )
1662 limit *= 10;
1664 percent = (unsigned) (ratio * limit + (float)0.5);
1665 if (percent <= 0 && top)
1666 percent = 1;
1667 else if (percent >= limit && top != bottom)
1668 percent = limit - 1;
1669 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1670 if (dp)
1672 dp++;
1675 buffer[ix+1] = buffer[ix];
1676 ix--;
1678 while (dp--);
1679 buffer[ix + 1] = '.';
1682 else
1683 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1685 return buffer;
1688 /* Summary of execution */
1690 static void
1691 executed_summary (unsigned lines, unsigned executed)
1693 if (lines)
1694 fnotice (stdout, "Lines executed:%s of %d\n",
1695 format_gcov (executed, lines, 2), lines);
1696 else
1697 fnotice (stdout, "No executable lines\n");
1700 /* Output summary info for a function or file. */
1702 static void
1703 function_summary (const coverage_t *coverage, const char *title)
1705 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1706 executed_summary (coverage->lines, coverage->lines_executed);
1708 if (flag_branches)
1710 if (coverage->branches)
1712 fnotice (stdout, "Branches executed:%s of %d\n",
1713 format_gcov (coverage->branches_executed,
1714 coverage->branches, 2),
1715 coverage->branches);
1716 fnotice (stdout, "Taken at least once:%s of %d\n",
1717 format_gcov (coverage->branches_taken,
1718 coverage->branches, 2),
1719 coverage->branches);
1721 else
1722 fnotice (stdout, "No branches\n");
1723 if (coverage->calls)
1724 fnotice (stdout, "Calls executed:%s of %d\n",
1725 format_gcov (coverage->calls_executed, coverage->calls, 2),
1726 coverage->calls);
1727 else
1728 fnotice (stdout, "No calls\n");
1732 /* Canonicalize the filename NAME by canonicalizing directory
1733 separators, eliding . components and resolving .. components
1734 appropriately. Always returns a unique string. */
1736 static char *
1737 canonicalize_name (const char *name)
1739 /* The canonical name cannot be longer than the incoming name. */
1740 char *result = XNEWVEC (char, strlen (name) + 1);
1741 const char *base = name, *probe;
1742 char *ptr = result;
1743 char *dd_base;
1744 int slash = 0;
1746 #if HAVE_DOS_BASED_FILE_SYSTEM
1747 if (base[0] && base[1] == ':')
1749 result[0] = base[0];
1750 result[1] = ':';
1751 base += 2;
1752 ptr += 2;
1754 #endif
1755 for (dd_base = ptr; *base; base = probe)
1757 size_t len;
1759 for (probe = base; *probe; probe++)
1760 if (IS_DIR_SEPARATOR (*probe))
1761 break;
1763 len = probe - base;
1764 if (len == 1 && base[0] == '.')
1765 /* Elide a '.' directory */
1767 else if (len == 2 && base[0] == '.' && base[1] == '.')
1769 /* '..', we can only elide it and the previous directory, if
1770 we're not a symlink. */
1771 struct stat ATTRIBUTE_UNUSED buf;
1773 *ptr = 0;
1774 if (dd_base == ptr
1775 #if defined (S_ISLNK)
1776 /* S_ISLNK is not POSIX.1-1996. */
1777 || stat (result, &buf) || S_ISLNK (buf.st_mode)
1778 #endif
1781 /* Cannot elide, or unreadable or a symlink. */
1782 dd_base = ptr + 2 + slash;
1783 goto regular;
1785 while (ptr != dd_base && *ptr != '/')
1786 ptr--;
1787 slash = ptr != result;
1789 else
1791 regular:
1792 /* Regular pathname component. */
1793 if (slash)
1794 *ptr++ = '/';
1795 memcpy (ptr, base, len);
1796 ptr += len;
1797 slash = 1;
1800 for (; IS_DIR_SEPARATOR (*probe); probe++)
1801 continue;
1803 *ptr = 0;
1805 return result;
1808 /* Generate an output file name. INPUT_NAME is the canonicalized main
1809 input file and SRC_NAME is the canonicalized file name.
1810 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
1811 long_output_names we prepend the processed name of the input file
1812 to each output name (except when the current source file is the
1813 input file, so you don't get a double concatenation). The two
1814 components are separated by '##'. With preserve_paths we create a
1815 filename from all path components of the source file, replacing '/'
1816 with '#', and .. with '^', without it we simply take the basename
1817 component. (Remember, the canonicalized name will already have
1818 elided '.' components and converted \\ separators.) */
1820 static char *
1821 make_gcov_file_name (const char *input_name, const char *src_name)
1823 char *ptr;
1824 char *result;
1826 if (flag_long_names && input_name && strcmp (src_name, input_name))
1828 /* Generate the input filename part. */
1829 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1831 ptr = result;
1832 ptr = mangle_name (input_name, ptr);
1833 ptr[0] = ptr[1] = '#';
1834 ptr += 2;
1836 else
1838 result = XNEWVEC (char, strlen (src_name) + 10);
1839 ptr = result;
1842 ptr = mangle_name (src_name, ptr);
1843 strcpy (ptr, ".gcov");
1845 return result;
1848 static char *
1849 mangle_name (char const *base, char *ptr)
1851 size_t len;
1853 /* Generate the source filename part. */
1854 if (!flag_preserve_paths)
1856 base = lbasename (base);
1857 len = strlen (base);
1858 memcpy (ptr, base, len);
1859 ptr += len;
1861 else
1863 /* Convert '/' to '#', convert '..' to '^',
1864 convert ':' to '~' on DOS based file system. */
1865 const char *probe;
1867 #if HAVE_DOS_BASED_FILE_SYSTEM
1868 if (base[0] && base[1] == ':')
1870 ptr[0] = base[0];
1871 ptr[1] = '~';
1872 ptr += 2;
1873 base += 2;
1875 #endif
1876 for (; *base; base = probe)
1878 size_t len;
1880 for (probe = base; *probe; probe++)
1881 if (*probe == '/')
1882 break;
1883 len = probe - base;
1884 if (len == 2 && base[0] == '.' && base[1] == '.')
1885 *ptr++ = '^';
1886 else
1888 memcpy (ptr, base, len);
1889 ptr += len;
1891 if (*probe)
1893 *ptr++ = '#';
1894 probe++;
1899 return ptr;
1902 /* Scan through the bb_data for each line in the block, increment
1903 the line number execution count indicated by the execution count of
1904 the appropriate basic block. */
1906 static void
1907 add_line_counts (coverage_t *coverage, function_t *fn)
1909 unsigned ix;
1910 line_t *line = NULL; /* This is propagated from one iteration to the
1911 next. */
1913 /* Scan each basic block. */
1914 for (ix = 0; ix != fn->num_blocks; ix++)
1916 block_t *block = &fn->blocks[ix];
1917 unsigned *encoding;
1918 const source_t *src = NULL;
1919 unsigned jx;
1921 if (block->count && ix && ix + 1 != fn->num_blocks)
1922 fn->blocks_executed++;
1923 for (jx = 0, encoding = block->u.line.encoding;
1924 jx != block->u.line.num; jx++, encoding++)
1925 if (!*encoding)
1927 src = &sources[*++encoding];
1928 jx++;
1930 else
1932 line = &src->lines[*encoding];
1934 if (coverage)
1936 if (!line->exists)
1937 coverage->lines++;
1938 if (!line->count && block->count)
1939 coverage->lines_executed++;
1941 line->exists = 1;
1942 if (!block->exceptional)
1943 line->unexceptional = 1;
1944 line->count += block->count;
1946 free (block->u.line.encoding);
1947 block->u.cycle.arc = NULL;
1948 block->u.cycle.ident = ~0U;
1950 if (!ix || ix + 1 == fn->num_blocks)
1951 /* Entry or exit block */;
1952 else if (flag_all_blocks)
1954 line_t *block_line = line;
1956 if (!block_line)
1957 block_line = &sources[fn->src].lines[fn->line];
1959 block->chain = block_line->u.blocks;
1960 block_line->u.blocks = block;
1962 else if (flag_branches)
1964 arc_t *arc;
1966 for (arc = block->succ; arc; arc = arc->succ_next)
1968 arc->line_next = line->u.branches;
1969 line->u.branches = arc;
1970 if (coverage && !arc->is_unconditional)
1971 add_branch_counts (coverage, arc);
1975 if (!line)
1976 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1979 /* Accumulate the line counts of a file. */
1981 static void
1982 accumulate_line_counts (source_t *src)
1984 line_t *line;
1985 function_t *fn, *fn_p, *fn_n;
1986 unsigned ix;
1988 /* Reverse the function order. */
1989 for (fn = src->functions, fn_p = NULL; fn;
1990 fn_p = fn, fn = fn_n)
1992 fn_n = fn->line_next;
1993 fn->line_next = fn_p;
1995 src->functions = fn_p;
1997 for (ix = src->num_lines, line = src->lines; ix--; line++)
1999 if (!flag_all_blocks)
2001 arc_t *arc, *arc_p, *arc_n;
2003 /* Total and reverse the branch information. */
2004 for (arc = line->u.branches, arc_p = NULL; arc;
2005 arc_p = arc, arc = arc_n)
2007 arc_n = arc->line_next;
2008 arc->line_next = arc_p;
2010 add_branch_counts (&src->coverage, arc);
2012 line->u.branches = arc_p;
2014 else if (line->u.blocks)
2016 /* The user expects the line count to be the number of times
2017 a line has been executed. Simply summing the block count
2018 will give an artificially high number. The Right Thing
2019 is to sum the entry counts to the graph of blocks on this
2020 line, then find the elementary cycles of the local graph
2021 and add the transition counts of those cycles. */
2022 block_t *block, *block_p, *block_n;
2023 gcov_type count = 0;
2025 /* Reverse the block information. */
2026 for (block = line->u.blocks, block_p = NULL; block;
2027 block_p = block, block = block_n)
2029 block_n = block->chain;
2030 block->chain = block_p;
2031 block->u.cycle.ident = ix;
2033 line->u.blocks = block_p;
2035 /* Sum the entry arcs. */
2036 for (block = line->u.blocks; block; block = block->chain)
2038 arc_t *arc;
2040 for (arc = block->pred; arc; arc = arc->pred_next)
2042 if (arc->src->u.cycle.ident != ix)
2043 count += arc->count;
2044 if (flag_branches)
2045 add_branch_counts (&src->coverage, arc);
2048 /* Initialize the cs_count. */
2049 for (arc = block->succ; arc; arc = arc->succ_next)
2050 arc->cs_count = arc->count;
2053 /* Find the loops. This uses the algorithm described in
2054 Tiernan 'An Efficient Search Algorithm to Find the
2055 Elementary Circuits of a Graph', CACM Dec 1970. We hold
2056 the P array by having each block point to the arc that
2057 connects to the previous block. The H array is implicitly
2058 held because of the arc ordering, and the block's
2059 previous arc pointer.
2061 Although the algorithm is O(N^3) for highly connected
2062 graphs, at worst we'll have O(N^2), as most blocks have
2063 only one or two exits. Most graphs will be small.
2065 For each loop we find, locate the arc with the smallest
2066 transition count, and add that to the cumulative
2067 count. Decrease flow over the cycle and remove the arc
2068 from consideration. */
2069 for (block = line->u.blocks; block; block = block->chain)
2071 block_t *head = block;
2072 arc_t *arc;
2074 next_vertex:;
2075 arc = head->succ;
2076 current_vertex:;
2077 while (arc)
2079 block_t *dst = arc->dst;
2080 if (/* Already used that arc. */
2081 arc->cycle
2082 /* Not to same graph, or before first vertex. */
2083 || dst->u.cycle.ident != ix
2084 /* Already in path. */
2085 || dst->u.cycle.arc)
2087 arc = arc->succ_next;
2088 continue;
2091 if (dst == block)
2093 /* Found a closing arc. */
2094 gcov_type cycle_count = arc->cs_count;
2095 arc_t *cycle_arc = arc;
2096 arc_t *probe_arc;
2098 /* Locate the smallest arc count of the loop. */
2099 for (dst = head; (probe_arc = dst->u.cycle.arc);
2100 dst = probe_arc->src)
2101 if (cycle_count > probe_arc->cs_count)
2103 cycle_count = probe_arc->cs_count;
2104 cycle_arc = probe_arc;
2107 count += cycle_count;
2108 cycle_arc->cycle = 1;
2110 /* Remove the flow from the cycle. */
2111 arc->cs_count -= cycle_count;
2112 for (dst = head; (probe_arc = dst->u.cycle.arc);
2113 dst = probe_arc->src)
2114 probe_arc->cs_count -= cycle_count;
2116 /* Unwind to the cyclic arc. */
2117 while (head != cycle_arc->src)
2119 arc = head->u.cycle.arc;
2120 head->u.cycle.arc = NULL;
2121 head = arc->src;
2123 /* Move on. */
2124 arc = arc->succ_next;
2125 continue;
2128 /* Add new block to chain. */
2129 dst->u.cycle.arc = arc;
2130 head = dst;
2131 goto next_vertex;
2133 /* We could not add another vertex to the path. Remove
2134 the last vertex from the list. */
2135 arc = head->u.cycle.arc;
2136 if (arc)
2138 /* It was not the first vertex. Move onto next arc. */
2139 head->u.cycle.arc = NULL;
2140 head = arc->src;
2141 arc = arc->succ_next;
2142 goto current_vertex;
2144 /* Mark this block as unusable. */
2145 block->u.cycle.ident = ~0U;
2148 line->count = count;
2151 if (line->exists)
2153 src->coverage.lines++;
2154 if (line->count)
2155 src->coverage.lines_executed++;
2160 /* Output information about ARC number IX. Returns nonzero if
2161 anything is output. */
2163 static int
2164 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2166 if (arc->is_call_non_return)
2168 if (arc->src->count)
2170 fnotice (gcov_file, "call %2d returned %s\n", ix,
2171 format_gcov (arc->src->count - arc->count,
2172 arc->src->count, -flag_counts));
2174 else
2175 fnotice (gcov_file, "call %2d never executed\n", ix);
2177 else if (!arc->is_unconditional)
2179 if (arc->src->count)
2180 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2181 format_gcov (arc->count, arc->src->count, -flag_counts),
2182 arc->fall_through ? " (fallthrough)"
2183 : arc->is_throw ? " (throw)" : "");
2184 else
2185 fnotice (gcov_file, "branch %2d never executed\n", ix);
2187 else if (flag_unconditional && !arc->dst->is_call_return)
2189 if (arc->src->count)
2190 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2191 format_gcov (arc->count, arc->src->count, -flag_counts));
2192 else
2193 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2195 else
2196 return 0;
2197 return 1;
2201 static const char *
2202 read_line (FILE *file)
2204 static char *string;
2205 static size_t string_len;
2206 size_t pos = 0;
2207 char *ptr;
2209 if (!string_len)
2211 string_len = 200;
2212 string = XNEWVEC (char, string_len);
2215 while ((ptr = fgets (string + pos, string_len - pos, file)))
2217 size_t len = strlen (string + pos);
2219 if (string[pos + len - 1] == '\n')
2221 string[pos + len - 1] = 0;
2222 return string;
2224 pos += len;
2225 string = XRESIZEVEC (char, string, string_len * 2);
2226 string_len *= 2;
2229 return pos ? string : NULL;
2232 /* Read in the source file one line at a time, and output that line to
2233 the gcov file preceded by its execution count and other
2234 information. */
2236 static void
2237 output_lines (FILE *gcov_file, const source_t *src)
2239 FILE *source_file;
2240 unsigned line_num; /* current line number. */
2241 const line_t *line; /* current line info ptr. */
2242 const char *retval = ""; /* status of source file reading. */
2243 function_t *fn = NULL;
2245 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2246 if (!multiple_files)
2248 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2249 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2250 no_data_file ? "-" : da_file_name);
2251 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
2253 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2255 source_file = fopen (src->name, "r");
2256 if (!source_file)
2258 fnotice (stderr, "Cannot open source file %s\n", src->name);
2259 retval = NULL;
2261 else if (src->file_time == 0)
2262 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2264 if (flag_branches)
2265 fn = src->functions;
2267 for (line_num = 1, line = &src->lines[line_num];
2268 line_num < src->num_lines; line_num++, line++)
2270 for (; fn && fn->line == line_num; fn = fn->line_next)
2272 arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
2273 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2274 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2276 for (; arc; arc = arc->pred_next)
2277 if (arc->fake)
2278 return_count -= arc->count;
2280 fprintf (gcov_file, "function %s", fn->name);
2281 fprintf (gcov_file, " called %s",
2282 format_gcov (called_count, 0, -1));
2283 fprintf (gcov_file, " returned %s",
2284 format_gcov (return_count, called_count, 0));
2285 fprintf (gcov_file, " blocks executed %s",
2286 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2287 fprintf (gcov_file, "\n");
2290 if (retval)
2291 retval = read_line (source_file);
2293 /* For lines which don't exist in the .bb file, print '-' before
2294 the source line. For lines which exist but were never
2295 executed, print '#####' or '=====' before the source line.
2296 Otherwise, print the execution count before the source line.
2297 There are 16 spaces of indentation added before the source
2298 line so that tabs won't be messed up. */
2299 fprintf (gcov_file, "%9s:%5u:%s\n",
2300 !line->exists ? "-" : line->count
2301 ? format_gcov (line->count, 0, -1)
2302 : line->unexceptional ? "#####" : "=====", line_num,
2303 retval ? retval : "/*EOF*/");
2305 if (flag_all_blocks)
2307 block_t *block;
2308 arc_t *arc;
2309 int ix, jx;
2311 for (ix = jx = 0, block = line->u.blocks; block;
2312 block = block->chain)
2314 if (!block->is_call_return)
2315 fprintf (gcov_file, "%9s:%5u-block %2d\n",
2316 !line->exists ? "-" : block->count
2317 ? format_gcov (block->count, 0, -1)
2318 : block->exceptional ? "%%%%%" : "$$$$$",
2319 line_num, ix++);
2320 if (flag_branches)
2321 for (arc = block->succ; arc; arc = arc->succ_next)
2322 jx += output_branch_count (gcov_file, jx, arc);
2325 else if (flag_branches)
2327 int ix;
2328 arc_t *arc;
2330 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2331 ix += output_branch_count (gcov_file, ix, arc);
2335 /* Handle all remaining source lines. There may be lines after the
2336 last line of code. */
2337 if (retval)
2339 for (; (retval = read_line (source_file)); line_num++)
2340 fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
2343 if (source_file)
2344 fclose (source_file);