2012-12-14 Steve Ellcey <sellcey@mips.com>
[official-gcc.git] / gcc / gcov.c
blob09831c2c6d6e49f669e734fafeace29af4b59233
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
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, 2012
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)
13 any later version.
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. */
35 #include "config.h"
36 #include "system.h"
37 #include "coretypes.h"
38 #include "tm.h"
39 #include "intl.h"
40 #include "diagnostic.h"
41 #include "version.h"
43 #include <getopt.h>
45 #define IN_GCOV 1
46 #include "gcov-io.h"
47 #include "gcov-io.c"
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 compares 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 in the
63 gcno file, the profile data will be used. */
65 /* This is the size of the buffer used to read in source file lines. */
67 struct function_info;
68 struct block_info;
69 struct source_info;
71 /* Describes an arc between two basic blocks. */
73 typedef struct arc_info
75 /* source and destination blocks. */
76 struct block_info *src;
77 struct block_info *dst;
79 /* transition counts. */
80 gcov_type count;
81 /* used in cycle search, so that we do not clobber original counts. */
82 gcov_type cs_count;
84 unsigned int count_valid : 1;
85 unsigned int on_tree : 1;
86 unsigned int fake : 1;
87 unsigned int fall_through : 1;
89 /* Arc to a catch handler. */
90 unsigned int is_throw : 1;
92 /* Arc is for a function that abnormally returns. */
93 unsigned int is_call_non_return : 1;
95 /* Arc is for catch/setjmp. */
96 unsigned int is_nonlocal_return : 1;
98 /* Is an unconditional branch. */
99 unsigned int is_unconditional : 1;
101 /* Loop making arc. */
102 unsigned int cycle : 1;
104 /* Next branch on line. */
105 struct arc_info *line_next;
107 /* Links to next arc on src and dst lists. */
108 struct arc_info *succ_next;
109 struct arc_info *pred_next;
110 } arc_t;
112 /* Describes a basic block. Contains lists of arcs to successor and
113 predecessor blocks. */
115 typedef struct block_info
117 /* Chain of exit and entry arcs. */
118 arc_t *succ;
119 arc_t *pred;
121 /* Number of unprocessed exit and entry arcs. */
122 gcov_type num_succ;
123 gcov_type num_pred;
125 /* Block execution count. */
126 gcov_type count;
127 unsigned flags : 12;
128 unsigned count_valid : 1;
129 unsigned valid_chain : 1;
130 unsigned invalid_chain : 1;
131 unsigned exceptional : 1;
133 /* Block is a call instrumenting site. */
134 unsigned is_call_site : 1; /* Does the call. */
135 unsigned is_call_return : 1; /* Is the return. */
137 /* Block is a landing pad for longjmp or throw. */
138 unsigned is_nonlocal_return : 1;
140 union
142 struct
144 /* Array of line numbers and source files. source files are
145 introduced by a linenumber of zero, the next 'line number' is
146 the number of the source file. Always starts with a source
147 file. */
148 unsigned *encoding;
149 unsigned num;
150 } line; /* Valid until blocks are linked onto lines */
151 struct
153 /* Single line graph cycle workspace. Used for all-blocks
154 mode. */
155 arc_t *arc;
156 unsigned ident;
157 } cycle; /* Used in all-blocks mode, after blocks are linked onto
158 lines. */
159 } u;
161 /* Temporary chain for solving graph, and for chaining blocks on one
162 line. */
163 struct block_info *chain;
165 } block_t;
167 /* Describes a single function. Contains an array of basic blocks. */
169 typedef struct function_info
171 /* Name of function. */
172 char *name;
173 unsigned ident;
174 unsigned lineno_checksum;
175 unsigned cfg_checksum;
177 /* The graph contains at least one fake incoming edge. */
178 unsigned has_catch : 1;
180 /* Array of basic blocks. Like in GCC, the entry block is
181 at blocks[0] and the exit block is at blocks[1]. */
182 #define ENTRY_BLOCK (0)
183 #define EXIT_BLOCK (1)
184 block_t *blocks;
185 unsigned num_blocks;
186 unsigned blocks_executed;
188 /* Raw arc coverage counts. */
189 gcov_type *counts;
190 unsigned num_counts;
192 /* First line number & file. */
193 unsigned line;
194 unsigned src;
196 /* Next function in same source file. */
197 struct function_info *line_next;
199 /* Next function. */
200 struct function_info *next;
201 } function_t;
203 /* Describes coverage of a file or function. */
205 typedef struct coverage_info
207 int lines;
208 int lines_executed;
210 int branches;
211 int branches_executed;
212 int branches_taken;
214 int calls;
215 int calls_executed;
217 char *name;
218 } coverage_t;
220 /* Describes a single line of source. Contains a chain of basic blocks
221 with code on it. */
223 typedef struct line_info
225 gcov_type count; /* execution count */
226 union
228 arc_t *branches; /* branches from blocks that end on this
229 line. Used for branch-counts when not
230 all-blocks mode. */
231 block_t *blocks; /* blocks which start on this line. Used
232 in all-blocks mode. */
233 } u;
234 unsigned exists : 1;
235 unsigned unexceptional : 1;
236 } line_t;
238 /* Describes a file mentioned in the block graph. Contains an array
239 of line info. */
241 typedef struct source_info
243 /* Canonical name of source file. */
244 char *name;
245 time_t file_time;
247 /* Array of line information. */
248 line_t *lines;
249 unsigned num_lines;
251 coverage_t coverage;
253 /* Functions in this source file. These are in ascending line
254 number order. */
255 function_t *functions;
256 } source_t;
258 typedef struct name_map
260 char *name; /* Source file name */
261 unsigned src; /* Source file */
262 } name_map_t;
264 /* Holds a list of function basic block graphs. */
266 static function_t *functions;
267 static function_t **fn_end = &functions;
269 static source_t *sources; /* Array of source files */
270 static unsigned n_sources; /* Number of sources */
271 static unsigned a_sources; /* Allocated sources */
273 static name_map_t *names; /* Mapping of file names to sources */
274 static unsigned n_names; /* Number of names */
275 static unsigned a_names; /* Allocated names */
277 /* This holds data summary information. */
279 static unsigned object_runs;
280 static unsigned program_count;
282 static unsigned total_lines;
283 static unsigned total_executed;
285 /* Modification time of graph file. */
287 static time_t bbg_file_time;
289 /* Name of the notes (gcno) output file. The "bbg" prefix is for
290 historical reasons, when the notes file contained only the
291 basic block graph notes. */
293 static char *bbg_file_name;
295 /* Stamp of the bbg file */
296 static unsigned bbg_stamp;
298 /* Name and file pointer of the input file for the count data (gcda). */
300 static char *da_file_name;
302 /* Data file is missing. */
304 static int no_data_file;
306 /* If there is several input files, compute and display results after
307 reading all data files. This way if two or more gcda file refer to
308 the same source file (eg inline subprograms in a .h file), the
309 counts are added. */
311 static int multiple_files = 0;
313 /* Output branch probabilities. */
315 static int flag_branches = 0;
317 /* Show unconditional branches too. */
318 static int flag_unconditional = 0;
320 /* Output a gcov file if this is true. This is on by default, and can
321 be turned off by the -n option. */
323 static int flag_gcov_file = 1;
325 /* Output progress indication if this is true. This is off by default
326 and can be turned on by the -d option. */
328 static int flag_display_progress = 0;
330 /* For included files, make the gcov output file name include the name
331 of the input source file. For example, if x.h is included in a.c,
332 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
334 static int flag_long_names = 0;
336 /* Output count information for every basic block, not merely those
337 that contain line number information. */
339 static int flag_all_blocks = 0;
341 /* Output summary info for each function. */
343 static int flag_function_summary = 0;
345 /* Object directory file prefix. This is the directory/file where the
346 graph and data files are looked for, if nonzero. */
348 static char *object_directory = 0;
350 /* Source directory prefix. This is removed from source pathnames
351 that match, when generating the output file name. */
353 static char *source_prefix = 0;
354 static size_t source_length = 0;
356 /* Only show data for sources with relative pathnames. Absolute ones
357 usually indicate a system header file, which although it may
358 contain inline functions, is usually uninteresting. */
359 static int flag_relative_only = 0;
361 /* Preserve all pathname components. Needed when object files and
362 source files are in subdirectories. '/' is mangled as '#', '.' is
363 elided and '..' mangled to '^'. */
365 static int flag_preserve_paths = 0;
367 /* Output the number of times a branch was taken as opposed to the percentage
368 of times it was taken. */
370 static int flag_counts = 0;
372 /* Forward declarations. */
373 static int process_args (int, char **);
374 static void print_usage (int) ATTRIBUTE_NORETURN;
375 static void print_version (void) ATTRIBUTE_NORETURN;
376 static void process_file (const char *);
377 static void generate_results (const char *);
378 static void create_file_names (const char *);
379 static int name_search (const void *, const void *);
380 static int name_sort (const void *, const void *);
381 static char *canonicalize_name (const char *);
382 static unsigned find_source (const char *);
383 static function_t *read_graph_file (void);
384 static int read_count_file (function_t *);
385 static void solve_flow_graph (function_t *);
386 static void find_exception_blocks (function_t *);
387 static void add_branch_counts (coverage_t *, const arc_t *);
388 static void add_line_counts (coverage_t *, function_t *);
389 static void executed_summary (unsigned, unsigned);
390 static void function_summary (const coverage_t *, const char *);
391 static const char *format_gcov (gcov_type, gcov_type, int);
392 static void accumulate_line_counts (source_t *);
393 static int output_branch_count (FILE *, int, const arc_t *);
394 static void output_lines (FILE *, const source_t *);
395 static char *make_gcov_file_name (const char *, const char *);
396 static char *mangle_name (const char *, char *);
397 static void release_structures (void);
398 static void release_function (function_t *);
399 extern int main (int, char **);
402 main (int argc, char **argv)
404 int argno;
405 int first_arg;
406 const char *p;
408 p = argv[0] + strlen (argv[0]);
409 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
410 --p;
411 progname = p;
413 xmalloc_set_program_name (progname);
415 /* Unlock the stdio streams. */
416 unlock_std_streams ();
418 gcc_init_libintl ();
420 diagnostic_initialize (global_dc, 0);
422 /* Handle response files. */
423 expandargv (&argc, &argv);
425 a_names = 10;
426 names = XNEWVEC (name_map_t, a_names);
427 a_sources = 10;
428 sources = XNEWVEC (source_t, a_sources);
430 argno = process_args (argc, argv);
431 if (optind == argc)
432 print_usage (true);
434 if (argc - argno > 1)
435 multiple_files = 1;
437 first_arg = argno;
439 for (; argno != argc; argno++)
441 if (flag_display_progress)
442 printf("Processing file %d out of %d\n",
443 argno - first_arg + 1, argc - first_arg);
444 process_file (argv[argno]);
447 generate_results (multiple_files ? NULL : argv[argc - 1]);
449 release_structures ();
451 return 0;
454 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
455 otherwise the output of --help. */
457 static void
458 print_usage (int error_p)
460 FILE *file = error_p ? stderr : stdout;
461 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
463 fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
464 fnotice (file, "Print code coverage information.\n\n");
465 fnotice (file, " -h, --help Print this help, then exit\n");
466 fnotice (file, " -v, --version Print version number, then exit\n");
467 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
468 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
469 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
470 rather than percentages\n");
471 fnotice (file, " -n, --no-output Do not create an output file\n");
472 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
473 source files\n");
474 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
475 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
476 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
477 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
478 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
479 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
480 fnotice (file, " -d, --display-progress Display progress information\n");
481 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
482 bug_report_url);
483 exit (status);
486 /* Print version information and exit. */
488 static void
489 print_version (void)
491 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
492 fprintf (stdout, "Copyright %s 2012 Free Software Foundation, Inc.\n",
493 _("(C)"));
494 fnotice (stdout,
495 _("This is free software; see the source for copying conditions.\n"
496 "There is NO warranty; not even for MERCHANTABILITY or \n"
497 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
498 exit (SUCCESS_EXIT_CODE);
501 static const struct option options[] =
503 { "help", no_argument, NULL, 'h' },
504 { "version", no_argument, NULL, 'v' },
505 { "all-blocks", no_argument, NULL, 'a' },
506 { "branch-probabilities", no_argument, NULL, 'b' },
507 { "branch-counts", no_argument, NULL, 'c' },
508 { "no-output", no_argument, NULL, 'n' },
509 { "long-file-names", no_argument, NULL, 'l' },
510 { "function-summaries", no_argument, NULL, 'f' },
511 { "preserve-paths", no_argument, NULL, 'p' },
512 { "relative-only", no_argument, NULL, 'r' },
513 { "object-directory", required_argument, NULL, 'o' },
514 { "object-file", required_argument, NULL, 'o' },
515 { "source-prefix", required_argument, NULL, 's' },
516 { "unconditional-branches", no_argument, NULL, 'u' },
517 { "display-progress", no_argument, NULL, 'd' },
518 { 0, 0, 0, 0 }
521 /* Process args, return index to first non-arg. */
523 static int
524 process_args (int argc, char **argv)
526 int opt;
528 while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
530 switch (opt)
532 case 'a':
533 flag_all_blocks = 1;
534 break;
535 case 'b':
536 flag_branches = 1;
537 break;
538 case 'c':
539 flag_counts = 1;
540 break;
541 case 'f':
542 flag_function_summary = 1;
543 break;
544 case 'h':
545 print_usage (false);
546 /* print_usage will exit. */
547 case 'l':
548 flag_long_names = 1;
549 break;
550 case 'n':
551 flag_gcov_file = 0;
552 break;
553 case 'o':
554 object_directory = optarg;
555 break;
556 case 's':
557 source_prefix = optarg;
558 source_length = strlen (source_prefix);
559 break;
560 case 'r':
561 flag_relative_only = 1;
562 break;
563 case 'p':
564 flag_preserve_paths = 1;
565 break;
566 case 'u':
567 flag_unconditional = 1;
568 break;
569 case 'd':
570 flag_display_progress = 1;
571 break;
572 case 'v':
573 print_version ();
574 /* print_version will exit. */
575 default:
576 print_usage (true);
577 /* print_usage will exit. */
581 return optind;
584 /* Process a single input file. */
586 static void
587 process_file (const char *file_name)
589 function_t *fns;
591 create_file_names (file_name);
592 fns = read_graph_file ();
593 if (!fns)
594 return;
596 read_count_file (fns);
597 while (fns)
599 function_t *fn = fns;
601 fns = fn->next;
602 fn->next = NULL;
603 if (fn->counts)
605 unsigned src = fn->src;
606 unsigned line = fn->line;
607 unsigned block_no;
608 function_t *probe, **prev;
610 /* Now insert it into the source file's list of
611 functions. Normally functions will be encountered in
612 ascending order, so a simple scan is quick. Note we're
613 building this list in reverse order. */
614 for (prev = &sources[src].functions;
615 (probe = *prev); prev = &probe->line_next)
616 if (probe->line <= line)
617 break;
618 fn->line_next = probe;
619 *prev = fn;
621 /* Mark last line in files touched by function. */
622 for (block_no = 0; block_no != fn->num_blocks; block_no++)
624 unsigned *enc = fn->blocks[block_no].u.line.encoding;
625 unsigned num = fn->blocks[block_no].u.line.num;
627 for (; num--; enc++)
628 if (!*enc)
630 if (enc[1] != src)
632 if (line >= sources[src].num_lines)
633 sources[src].num_lines = line + 1;
634 line = 0;
635 src = enc[1];
637 enc++;
638 num--;
640 else if (*enc > line)
641 line = *enc;
643 if (line >= sources[src].num_lines)
644 sources[src].num_lines = line + 1;
646 solve_flow_graph (fn);
647 if (fn->has_catch)
648 find_exception_blocks (fn);
649 *fn_end = fn;
650 fn_end = &fn->next;
652 else
653 /* The function was not in the executable -- some other
654 instance must have been selected. */
655 release_function (fn);
659 static void
660 generate_results (const char *file_name)
662 unsigned ix;
663 source_t *src;
664 function_t *fn;
666 for (ix = n_sources, src = sources; ix--; src++)
667 if (src->num_lines)
668 src->lines = XCNEWVEC (line_t, src->num_lines);
670 for (fn = functions; fn; fn = fn->next)
672 coverage_t coverage;
674 memset (&coverage, 0, sizeof (coverage));
675 coverage.name = fn->name;
676 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
677 if (flag_function_summary)
679 function_summary (&coverage, "Function");
680 fnotice (stdout, "\n");
684 if (file_name)
686 name_map_t *name_map = (name_map_t *)bsearch
687 (file_name, names, n_names, sizeof (*names), name_search);
688 if (name_map)
689 file_name = sources[name_map->src].coverage.name;
690 else
691 file_name = canonicalize_name (file_name);
694 for (ix = n_sources, src = sources; ix--; src++)
696 if (flag_relative_only)
698 /* Ignore this source, if it is an absolute path (after
699 source prefix removal). */
700 char first = src->coverage.name[0];
702 #if HAVE_DOS_BASED_FILE_SYSTEM
703 if (first && src->coverage.name[1] == ':')
704 first = src->coverage.name[2];
705 #endif
706 if (IS_DIR_SEPARATOR (first))
707 continue;
710 accumulate_line_counts (src);
711 function_summary (&src->coverage, "File");
712 total_lines += src->coverage.lines;
713 total_executed += src->coverage.lines_executed;
714 if (flag_gcov_file)
716 char *gcov_file_name
717 = make_gcov_file_name (file_name, src->coverage.name);
719 if (src->coverage.lines)
721 FILE *gcov_file = fopen (gcov_file_name, "w");
723 if (gcov_file)
725 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
726 output_lines (gcov_file, src);
727 if (ferror (gcov_file))
728 fnotice (stderr, "Error writing output file '%s'\n",
729 gcov_file_name);
730 fclose (gcov_file);
732 else
733 fnotice (stderr, "Could not open output file '%s'\n",
734 gcov_file_name);
736 else
738 unlink (gcov_file_name);
739 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
741 free (gcov_file_name);
743 fnotice (stdout, "\n");
746 if (!file_name)
747 executed_summary (total_lines, total_executed);
750 /* Release a function structure */
752 static void
753 release_function (function_t *fn)
755 unsigned ix;
756 block_t *block;
758 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
760 arc_t *arc, *arc_n;
762 for (arc = block->succ; arc; arc = arc_n)
764 arc_n = arc->succ_next;
765 free (arc);
768 free (fn->blocks);
769 free (fn->counts);
772 /* Release all memory used. */
774 static void
775 release_structures (void)
777 unsigned ix;
778 function_t *fn;
780 for (ix = n_sources; ix--;)
781 free (sources[ix].lines);
782 free (sources);
784 for (ix = n_names; ix--;)
785 free (names[ix].name);
786 free (names);
788 while ((fn = functions))
790 functions = fn->next;
791 release_function (fn);
795 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
796 is not specified, these are named from FILE_NAME sans extension. If
797 OBJECT_DIRECTORY is specified and is a directory, the files are in that
798 directory, but named from the basename of the FILE_NAME, sans extension.
799 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
800 and the data files are named from that. */
802 static void
803 create_file_names (const char *file_name)
805 char *cptr;
806 char *name;
807 int length = strlen (file_name);
808 int base;
810 /* Free previous file names. */
811 free (bbg_file_name);
812 free (da_file_name);
813 da_file_name = bbg_file_name = NULL;
814 bbg_file_time = 0;
815 bbg_stamp = 0;
817 if (object_directory && object_directory[0])
819 struct stat status;
821 length += strlen (object_directory) + 2;
822 name = XNEWVEC (char, length);
823 name[0] = 0;
825 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
826 strcat (name, object_directory);
827 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
828 strcat (name, "/");
830 else
832 name = XNEWVEC (char, length + 1);
833 strcpy (name, file_name);
834 base = 0;
837 if (base)
839 /* Append source file name. */
840 const char *cptr = lbasename (file_name);
841 strcat (name, cptr ? cptr : file_name);
844 /* Remove the extension. */
845 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
846 if (cptr)
847 *cptr = 0;
849 length = strlen (name);
851 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
852 strcpy (bbg_file_name, name);
853 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
855 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
856 strcpy (da_file_name, name);
857 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
859 free (name);
860 return;
863 /* A is a string and B is a pointer to name_map_t. Compare for file
864 name orderability. */
866 static int
867 name_search (const void *a_, const void *b_)
869 const char *a = (const char *)a_;
870 const name_map_t *b = (const name_map_t *)b_;
872 #if HAVE_DOS_BASED_FILE_SYSTEM
873 return strcasecmp (a, b->name);
874 #else
875 return strcmp (a, b->name);
876 #endif
879 /* A and B are a pointer to name_map_t. Compare for file name
880 orderability. */
882 static int
883 name_sort (const void *a_, const void *b_)
885 const name_map_t *a = (const name_map_t *)a_;
886 return name_search (a->name, b_);
889 /* Find or create a source file structure for FILE_NAME. Copies
890 FILE_NAME on creation */
892 static unsigned
893 find_source (const char *file_name)
895 name_map_t *name_map;
896 char *canon;
897 unsigned idx;
898 struct stat status;
900 if (!file_name)
901 file_name = "<unknown>";
902 name_map = (name_map_t *)bsearch
903 (file_name, names, n_names, sizeof (*names), name_search);
904 if (name_map)
906 idx = name_map->src;
907 goto check_date;
910 if (n_names + 2 > a_names)
912 /* Extend the name map array -- we'll be inserting one or two
913 entries. */
914 a_names *= 2;
915 name_map = XNEWVEC (name_map_t, a_names);
916 memcpy (name_map, names, n_names * sizeof (*names));
917 free (names);
918 names = name_map;
921 /* Not found, try the canonical name. */
922 canon = canonicalize_name (file_name);
923 name_map = (name_map_t *)bsearch
924 (canon, names, n_names, sizeof (*names), name_search);
925 if (!name_map)
927 /* Not found with canonical name, create a new source. */
928 source_t *src;
930 if (n_sources == a_sources)
932 a_sources *= 2;
933 src = XNEWVEC (source_t, a_sources);
934 memcpy (src, sources, n_sources * sizeof (*sources));
935 free (sources);
936 sources = src;
939 idx = n_sources;
941 name_map = &names[n_names++];
942 name_map->name = canon;
943 name_map->src = idx;
945 src = &sources[n_sources++];
946 memset (src, 0, sizeof (*src));
947 src->name = canon;
948 src->coverage.name = src->name;
949 if (source_length
950 #if HAVE_DOS_BASED_FILE_SYSTEM
951 /* You lose if separators don't match exactly in the
952 prefix. */
953 && !strncasecmp (source_prefix, src->coverage.name, source_length)
954 #else
955 && !strncmp (source_prefix, src->coverage.name, source_length)
956 #endif
957 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
958 src->coverage.name += source_length + 1;
959 if (!stat (src->name, &status))
960 src->file_time = status.st_mtime;
962 else
963 idx = name_map->src;
965 if (name_search (file_name, name_map))
967 /* Append the non-canonical name. */
968 name_map = &names[n_names++];
969 name_map->name = xstrdup (file_name);
970 name_map->src = idx;
973 /* Resort the name map. */
974 qsort (names, n_names, sizeof (*names), name_sort);
976 check_date:
977 if (sources[idx].file_time > bbg_file_time)
979 static int info_emitted;
981 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
982 file_name, bbg_file_name);
983 if (!info_emitted)
985 fnotice (stderr,
986 "(the message is only displayed one per source file)\n");
987 info_emitted = 1;
989 sources[idx].file_time = 0;
992 return idx;
995 /* Read the notes file. Return list of functions read -- in reverse order. */
997 static function_t *
998 read_graph_file (void)
1000 unsigned version;
1001 unsigned current_tag = 0;
1002 function_t *fn = NULL;
1003 function_t *fns = NULL;
1004 function_t **fns_end = &fns;
1005 unsigned src_idx = 0;
1006 unsigned ix;
1007 unsigned tag;
1009 if (!gcov_open (bbg_file_name, 1))
1011 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1012 return fns;
1014 bbg_file_time = gcov_time ();
1015 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1017 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1018 gcov_close ();
1019 return fns;
1022 version = gcov_read_unsigned ();
1023 if (version != GCOV_VERSION)
1025 char v[4], e[4];
1027 GCOV_UNSIGNED2STRING (v, version);
1028 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1030 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1031 bbg_file_name, v, e);
1033 bbg_stamp = gcov_read_unsigned ();
1035 while ((tag = gcov_read_unsigned ()))
1037 unsigned length = gcov_read_unsigned ();
1038 gcov_position_t base = gcov_position ();
1040 if (tag == GCOV_TAG_FUNCTION)
1042 char *function_name;
1043 unsigned ident, lineno;
1044 unsigned lineno_checksum, cfg_checksum;
1046 ident = gcov_read_unsigned ();
1047 lineno_checksum = gcov_read_unsigned ();
1048 cfg_checksum = gcov_read_unsigned ();
1049 function_name = xstrdup (gcov_read_string ());
1050 src_idx = find_source (gcov_read_string ());
1051 lineno = gcov_read_unsigned ();
1053 fn = XCNEW (function_t);
1054 fn->name = function_name;
1055 fn->ident = ident;
1056 fn->lineno_checksum = lineno_checksum;
1057 fn->cfg_checksum = cfg_checksum;
1058 fn->src = src_idx;
1059 fn->line = lineno;
1061 fn->line_next = NULL;
1062 fn->next = NULL;
1063 *fns_end = fn;
1064 fns_end = &fn->next;
1065 current_tag = tag;
1067 else if (fn && tag == GCOV_TAG_BLOCKS)
1069 if (fn->blocks)
1070 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1071 bbg_file_name, fn->name);
1072 else
1074 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1075 fn->num_blocks = num_blocks;
1077 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
1078 for (ix = 0; ix != num_blocks; ix++)
1079 fn->blocks[ix].flags = gcov_read_unsigned ();
1082 else if (fn && tag == GCOV_TAG_ARCS)
1084 unsigned src = gcov_read_unsigned ();
1085 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1086 block_t *src_blk = &fn->blocks[src];
1087 unsigned mark_catches = 0;
1088 struct arc_info *arc;
1090 if (src >= fn->num_blocks || fn->blocks[src].succ)
1091 goto corrupt;
1093 while (num_dests--)
1095 unsigned dest = gcov_read_unsigned ();
1096 unsigned flags = gcov_read_unsigned ();
1098 if (dest >= fn->num_blocks)
1099 goto corrupt;
1100 arc = XCNEW (arc_t);
1102 arc->dst = &fn->blocks[dest];
1103 arc->src = src_blk;
1105 arc->count = 0;
1106 arc->count_valid = 0;
1107 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1108 arc->fake = !!(flags & GCOV_ARC_FAKE);
1109 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1111 arc->succ_next = src_blk->succ;
1112 src_blk->succ = arc;
1113 src_blk->num_succ++;
1115 arc->pred_next = fn->blocks[dest].pred;
1116 fn->blocks[dest].pred = arc;
1117 fn->blocks[dest].num_pred++;
1119 if (arc->fake)
1121 if (src)
1123 /* Exceptional exit from this function, the
1124 source block must be a call. */
1125 fn->blocks[src].is_call_site = 1;
1126 arc->is_call_non_return = 1;
1127 mark_catches = 1;
1129 else
1131 /* Non-local return from a callee of this
1132 function. The destination block is a setjmp. */
1133 arc->is_nonlocal_return = 1;
1134 fn->blocks[dest].is_nonlocal_return = 1;
1138 if (!arc->on_tree)
1139 fn->num_counts++;
1142 if (mark_catches)
1144 /* We have a fake exit from this block. The other
1145 non-fall through exits must be to catch handlers.
1146 Mark them as catch arcs. */
1148 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1149 if (!arc->fake && !arc->fall_through)
1151 arc->is_throw = 1;
1152 fn->has_catch = 1;
1156 else if (fn && tag == GCOV_TAG_LINES)
1158 unsigned blockno = gcov_read_unsigned ();
1159 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1161 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1162 goto corrupt;
1164 for (ix = 0; ; )
1166 unsigned lineno = gcov_read_unsigned ();
1168 if (lineno)
1170 if (!ix)
1172 line_nos[ix++] = 0;
1173 line_nos[ix++] = src_idx;
1175 line_nos[ix++] = lineno;
1177 else
1179 const char *file_name = gcov_read_string ();
1181 if (!file_name)
1182 break;
1183 src_idx = find_source (file_name);
1184 line_nos[ix++] = 0;
1185 line_nos[ix++] = src_idx;
1189 fn->blocks[blockno].u.line.encoding = line_nos;
1190 fn->blocks[blockno].u.line.num = ix;
1192 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1194 fn = NULL;
1195 current_tag = 0;
1197 gcov_sync (base, length);
1198 if (gcov_is_error ())
1200 corrupt:;
1201 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1202 break;
1205 gcov_close ();
1207 if (!fns)
1208 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1210 return fns;
1213 /* Reads profiles from the count file and attach to each
1214 function. Return nonzero if fatal error. */
1216 static int
1217 read_count_file (function_t *fns)
1219 unsigned ix;
1220 unsigned version;
1221 unsigned tag;
1222 function_t *fn = NULL;
1223 int error = 0;
1225 if (!gcov_open (da_file_name, 1))
1227 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1228 da_file_name);
1229 no_data_file = 1;
1230 return 0;
1232 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1234 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1235 cleanup:;
1236 gcov_close ();
1237 return 1;
1239 version = gcov_read_unsigned ();
1240 if (version != GCOV_VERSION)
1242 char v[4], e[4];
1244 GCOV_UNSIGNED2STRING (v, version);
1245 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1247 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1248 da_file_name, v, e);
1250 tag = gcov_read_unsigned ();
1251 if (tag != bbg_stamp)
1253 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1254 goto cleanup;
1257 while ((tag = gcov_read_unsigned ()))
1259 unsigned length = gcov_read_unsigned ();
1260 unsigned long base = gcov_position ();
1262 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1264 struct gcov_summary summary;
1265 gcov_read_summary (&summary);
1266 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1267 program_count++;
1269 else if (tag == GCOV_TAG_FUNCTION && !length)
1270 ; /* placeholder */
1271 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1273 unsigned ident;
1274 struct function_info *fn_n;
1276 /* Try to find the function in the list. To speed up the
1277 search, first start from the last function found. */
1278 ident = gcov_read_unsigned ();
1279 fn_n = fns;
1280 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1282 if (fn)
1284 else if ((fn = fn_n))
1285 fn_n = NULL;
1286 else
1288 fnotice (stderr, "%s:unknown function '%u'\n",
1289 da_file_name, ident);
1290 break;
1292 if (fn->ident == ident)
1293 break;
1296 if (!fn)
1298 else if (gcov_read_unsigned () != fn->lineno_checksum
1299 || gcov_read_unsigned () != fn->cfg_checksum)
1301 mismatch:;
1302 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1303 da_file_name, fn->name);
1304 goto cleanup;
1307 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1309 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1310 goto mismatch;
1312 if (!fn->counts)
1313 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1315 for (ix = 0; ix != fn->num_counts; ix++)
1316 fn->counts[ix] += gcov_read_counter ();
1318 gcov_sync (base, length);
1319 if ((error = gcov_is_error ()))
1321 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1322 da_file_name);
1323 goto cleanup;
1327 gcov_close ();
1328 return 0;
1331 /* Solve the flow graph. Propagate counts from the instrumented arcs
1332 to the blocks and the uninstrumented arcs. */
1334 static void
1335 solve_flow_graph (function_t *fn)
1337 unsigned ix;
1338 arc_t *arc;
1339 gcov_type *count_ptr = fn->counts;
1340 block_t *blk;
1341 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1342 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1344 /* The arcs were built in reverse order. Fix that now. */
1345 for (ix = fn->num_blocks; ix--;)
1347 arc_t *arc_p, *arc_n;
1349 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1350 arc_p = arc, arc = arc_n)
1352 arc_n = arc->succ_next;
1353 arc->succ_next = arc_p;
1355 fn->blocks[ix].succ = arc_p;
1357 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1358 arc_p = arc, arc = arc_n)
1360 arc_n = arc->pred_next;
1361 arc->pred_next = arc_p;
1363 fn->blocks[ix].pred = arc_p;
1366 if (fn->num_blocks < 2)
1367 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1368 bbg_file_name, fn->name);
1369 else
1371 if (fn->blocks[ENTRY_BLOCK].num_pred)
1372 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1373 bbg_file_name, fn->name);
1374 else
1375 /* We can't deduce the entry block counts from the lack of
1376 predecessors. */
1377 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1379 if (fn->blocks[EXIT_BLOCK].num_succ)
1380 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1381 bbg_file_name, fn->name);
1382 else
1383 /* Likewise, we can't deduce exit block counts from the lack
1384 of its successors. */
1385 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1388 /* Propagate the measured counts, this must be done in the same
1389 order as the code in profile.c */
1390 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1392 block_t const *prev_dst = NULL;
1393 int out_of_order = 0;
1394 int non_fake_succ = 0;
1396 for (arc = blk->succ; arc; arc = arc->succ_next)
1398 if (!arc->fake)
1399 non_fake_succ++;
1401 if (!arc->on_tree)
1403 if (count_ptr)
1404 arc->count = *count_ptr++;
1405 arc->count_valid = 1;
1406 blk->num_succ--;
1407 arc->dst->num_pred--;
1409 if (prev_dst && prev_dst > arc->dst)
1410 out_of_order = 1;
1411 prev_dst = arc->dst;
1413 if (non_fake_succ == 1)
1415 /* If there is only one non-fake exit, it is an
1416 unconditional branch. */
1417 for (arc = blk->succ; arc; arc = arc->succ_next)
1418 if (!arc->fake)
1420 arc->is_unconditional = 1;
1421 /* If this block is instrumenting a call, it might be
1422 an artificial block. It is not artificial if it has
1423 a non-fallthrough exit, or the destination of this
1424 arc has more than one entry. Mark the destination
1425 block as a return site, if none of those conditions
1426 hold. */
1427 if (blk->is_call_site && arc->fall_through
1428 && arc->dst->pred == arc && !arc->pred_next)
1429 arc->dst->is_call_return = 1;
1433 /* Sort the successor arcs into ascending dst order. profile.c
1434 normally produces arcs in the right order, but sometimes with
1435 one or two out of order. We're not using a particularly
1436 smart sort. */
1437 if (out_of_order)
1439 arc_t *start = blk->succ;
1440 unsigned changes = 1;
1442 while (changes)
1444 arc_t *arc, *arc_p, *arc_n;
1446 changes = 0;
1447 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1449 if (arc->dst > arc_n->dst)
1451 changes = 1;
1452 if (arc_p)
1453 arc_p->succ_next = arc_n;
1454 else
1455 start = arc_n;
1456 arc->succ_next = arc_n->succ_next;
1457 arc_n->succ_next = arc;
1458 arc_p = arc_n;
1460 else
1462 arc_p = arc;
1463 arc = arc_n;
1467 blk->succ = start;
1470 /* Place it on the invalid chain, it will be ignored if that's
1471 wrong. */
1472 blk->invalid_chain = 1;
1473 blk->chain = invalid_blocks;
1474 invalid_blocks = blk;
1477 while (invalid_blocks || valid_blocks)
1479 while ((blk = invalid_blocks))
1481 gcov_type total = 0;
1482 const arc_t *arc;
1484 invalid_blocks = blk->chain;
1485 blk->invalid_chain = 0;
1486 if (!blk->num_succ)
1487 for (arc = blk->succ; arc; arc = arc->succ_next)
1488 total += arc->count;
1489 else if (!blk->num_pred)
1490 for (arc = blk->pred; arc; arc = arc->pred_next)
1491 total += arc->count;
1492 else
1493 continue;
1495 blk->count = total;
1496 blk->count_valid = 1;
1497 blk->chain = valid_blocks;
1498 blk->valid_chain = 1;
1499 valid_blocks = blk;
1501 while ((blk = valid_blocks))
1503 gcov_type total;
1504 arc_t *arc, *inv_arc;
1506 valid_blocks = blk->chain;
1507 blk->valid_chain = 0;
1508 if (blk->num_succ == 1)
1510 block_t *dst;
1512 total = blk->count;
1513 inv_arc = NULL;
1514 for (arc = blk->succ; arc; arc = arc->succ_next)
1516 total -= arc->count;
1517 if (!arc->count_valid)
1518 inv_arc = arc;
1520 dst = inv_arc->dst;
1521 inv_arc->count_valid = 1;
1522 inv_arc->count = total;
1523 blk->num_succ--;
1524 dst->num_pred--;
1525 if (dst->count_valid)
1527 if (dst->num_pred == 1 && !dst->valid_chain)
1529 dst->chain = valid_blocks;
1530 dst->valid_chain = 1;
1531 valid_blocks = dst;
1534 else
1536 if (!dst->num_pred && !dst->invalid_chain)
1538 dst->chain = invalid_blocks;
1539 dst->invalid_chain = 1;
1540 invalid_blocks = dst;
1544 if (blk->num_pred == 1)
1546 block_t *src;
1548 total = blk->count;
1549 inv_arc = NULL;
1550 for (arc = blk->pred; arc; arc = arc->pred_next)
1552 total -= arc->count;
1553 if (!arc->count_valid)
1554 inv_arc = arc;
1556 src = inv_arc->src;
1557 inv_arc->count_valid = 1;
1558 inv_arc->count = total;
1559 blk->num_pred--;
1560 src->num_succ--;
1561 if (src->count_valid)
1563 if (src->num_succ == 1 && !src->valid_chain)
1565 src->chain = valid_blocks;
1566 src->valid_chain = 1;
1567 valid_blocks = src;
1570 else
1572 if (!src->num_succ && !src->invalid_chain)
1574 src->chain = invalid_blocks;
1575 src->invalid_chain = 1;
1576 invalid_blocks = src;
1583 /* If the graph has been correctly solved, every block will have a
1584 valid count. */
1585 for (ix = 0; ix < fn->num_blocks; ix++)
1586 if (!fn->blocks[ix].count_valid)
1588 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1589 bbg_file_name, fn->name);
1590 break;
1594 /* Mark all the blocks only reachable via an incoming catch. */
1596 static void
1597 find_exception_blocks (function_t *fn)
1599 unsigned ix;
1600 block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1602 /* First mark all blocks as exceptional. */
1603 for (ix = fn->num_blocks; ix--;)
1604 fn->blocks[ix].exceptional = 1;
1606 /* Now mark all the blocks reachable via non-fake edges */
1607 queue[0] = fn->blocks;
1608 queue[0]->exceptional = 0;
1609 for (ix = 1; ix;)
1611 block_t *block = queue[--ix];
1612 const arc_t *arc;
1614 for (arc = block->succ; arc; arc = arc->succ_next)
1615 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1617 arc->dst->exceptional = 0;
1618 queue[ix++] = arc->dst;
1624 /* Increment totals in COVERAGE according to arc ARC. */
1626 static void
1627 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1629 if (arc->is_call_non_return)
1631 coverage->calls++;
1632 if (arc->src->count)
1633 coverage->calls_executed++;
1635 else if (!arc->is_unconditional)
1637 coverage->branches++;
1638 if (arc->src->count)
1639 coverage->branches_executed++;
1640 if (arc->count)
1641 coverage->branches_taken++;
1645 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1646 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1647 If DP is zero, no decimal point is printed. Only print 100% when
1648 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1649 format TOP. Return pointer to a static string. */
1651 static char const *
1652 format_gcov (gcov_type top, gcov_type bottom, int dp)
1654 static char buffer[20];
1656 if (dp >= 0)
1658 float ratio = bottom ? (float)top / bottom : 0;
1659 int ix;
1660 unsigned limit = 100;
1661 unsigned percent;
1663 for (ix = dp; ix--; )
1664 limit *= 10;
1666 percent = (unsigned) (ratio * limit + (float)0.5);
1667 if (percent <= 0 && top)
1668 percent = 1;
1669 else if (percent >= limit && top != bottom)
1670 percent = limit - 1;
1671 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1672 if (dp)
1674 dp++;
1677 buffer[ix+1] = buffer[ix];
1678 ix--;
1680 while (dp--);
1681 buffer[ix + 1] = '.';
1684 else
1685 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1687 return buffer;
1690 /* Summary of execution */
1692 static void
1693 executed_summary (unsigned lines, unsigned executed)
1695 if (lines)
1696 fnotice (stdout, "Lines executed:%s of %d\n",
1697 format_gcov (executed, lines, 2), lines);
1698 else
1699 fnotice (stdout, "No executable lines\n");
1702 /* Output summary info for a function or file. */
1704 static void
1705 function_summary (const coverage_t *coverage, const char *title)
1707 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1708 executed_summary (coverage->lines, coverage->lines_executed);
1710 if (flag_branches)
1712 if (coverage->branches)
1714 fnotice (stdout, "Branches executed:%s of %d\n",
1715 format_gcov (coverage->branches_executed,
1716 coverage->branches, 2),
1717 coverage->branches);
1718 fnotice (stdout, "Taken at least once:%s of %d\n",
1719 format_gcov (coverage->branches_taken,
1720 coverage->branches, 2),
1721 coverage->branches);
1723 else
1724 fnotice (stdout, "No branches\n");
1725 if (coverage->calls)
1726 fnotice (stdout, "Calls executed:%s of %d\n",
1727 format_gcov (coverage->calls_executed, coverage->calls, 2),
1728 coverage->calls);
1729 else
1730 fnotice (stdout, "No calls\n");
1734 /* Canonicalize the filename NAME by canonicalizing directory
1735 separators, eliding . components and resolving .. components
1736 appropriately. Always returns a unique string. */
1738 static char *
1739 canonicalize_name (const char *name)
1741 /* The canonical name cannot be longer than the incoming name. */
1742 char *result = XNEWVEC (char, strlen (name) + 1);
1743 const char *base = name, *probe;
1744 char *ptr = result;
1745 char *dd_base;
1746 int slash = 0;
1748 #if HAVE_DOS_BASED_FILE_SYSTEM
1749 if (base[0] && base[1] == ':')
1751 result[0] = base[0];
1752 result[1] = ':';
1753 base += 2;
1754 ptr += 2;
1756 #endif
1757 for (dd_base = ptr; *base; base = probe)
1759 size_t len;
1761 for (probe = base; *probe; probe++)
1762 if (IS_DIR_SEPARATOR (*probe))
1763 break;
1765 len = probe - base;
1766 if (len == 1 && base[0] == '.')
1767 /* Elide a '.' directory */
1769 else if (len == 2 && base[0] == '.' && base[1] == '.')
1771 /* '..', we can only elide it and the previous directory, if
1772 we're not a symlink. */
1773 struct stat ATTRIBUTE_UNUSED buf;
1775 *ptr = 0;
1776 if (dd_base == ptr
1777 #if defined (S_ISLNK)
1778 /* S_ISLNK is not POSIX.1-1996. */
1779 || stat (result, &buf) || S_ISLNK (buf.st_mode)
1780 #endif
1783 /* Cannot elide, or unreadable or a symlink. */
1784 dd_base = ptr + 2 + slash;
1785 goto regular;
1787 while (ptr != dd_base && *ptr != '/')
1788 ptr--;
1789 slash = ptr != result;
1791 else
1793 regular:
1794 /* Regular pathname component. */
1795 if (slash)
1796 *ptr++ = '/';
1797 memcpy (ptr, base, len);
1798 ptr += len;
1799 slash = 1;
1802 for (; IS_DIR_SEPARATOR (*probe); probe++)
1803 continue;
1805 *ptr = 0;
1807 return result;
1810 /* Generate an output file name. INPUT_NAME is the canonicalized main
1811 input file and SRC_NAME is the canonicalized file name.
1812 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
1813 long_output_names we prepend the processed name of the input file
1814 to each output name (except when the current source file is the
1815 input file, so you don't get a double concatenation). The two
1816 components are separated by '##'. With preserve_paths we create a
1817 filename from all path components of the source file, replacing '/'
1818 with '#', and .. with '^', without it we simply take the basename
1819 component. (Remember, the canonicalized name will already have
1820 elided '.' components and converted \\ separators.) */
1822 static char *
1823 make_gcov_file_name (const char *input_name, const char *src_name)
1825 char *ptr;
1826 char *result;
1828 if (flag_long_names && input_name && strcmp (src_name, input_name))
1830 /* Generate the input filename part. */
1831 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1833 ptr = result;
1834 ptr = mangle_name (input_name, ptr);
1835 ptr[0] = ptr[1] = '#';
1836 ptr += 2;
1838 else
1840 result = XNEWVEC (char, strlen (src_name) + 10);
1841 ptr = result;
1844 ptr = mangle_name (src_name, ptr);
1845 strcpy (ptr, ".gcov");
1847 return result;
1850 static char *
1851 mangle_name (char const *base, char *ptr)
1853 size_t len;
1855 /* Generate the source filename part. */
1856 if (!flag_preserve_paths)
1858 base = lbasename (base);
1859 len = strlen (base);
1860 memcpy (ptr, base, len);
1861 ptr += len;
1863 else
1865 /* Convert '/' to '#', convert '..' to '^',
1866 convert ':' to '~' on DOS based file system. */
1867 const char *probe;
1869 #if HAVE_DOS_BASED_FILE_SYSTEM
1870 if (base[0] && base[1] == ':')
1872 ptr[0] = base[0];
1873 ptr[1] = '~';
1874 ptr += 2;
1875 base += 2;
1877 #endif
1878 for (; *base; base = probe)
1880 size_t len;
1882 for (probe = base; *probe; probe++)
1883 if (*probe == '/')
1884 break;
1885 len = probe - base;
1886 if (len == 2 && base[0] == '.' && base[1] == '.')
1887 *ptr++ = '^';
1888 else
1890 memcpy (ptr, base, len);
1891 ptr += len;
1893 if (*probe)
1895 *ptr++ = '#';
1896 probe++;
1901 return ptr;
1904 /* Scan through the bb_data for each line in the block, increment
1905 the line number execution count indicated by the execution count of
1906 the appropriate basic block. */
1908 static void
1909 add_line_counts (coverage_t *coverage, function_t *fn)
1911 unsigned ix;
1912 line_t *line = NULL; /* This is propagated from one iteration to the
1913 next. */
1915 /* Scan each basic block. */
1916 for (ix = 0; ix != fn->num_blocks; ix++)
1918 block_t *block = &fn->blocks[ix];
1919 unsigned *encoding;
1920 const source_t *src = NULL;
1921 unsigned jx;
1923 if (block->count && ix && ix + 1 != fn->num_blocks)
1924 fn->blocks_executed++;
1925 for (jx = 0, encoding = block->u.line.encoding;
1926 jx != block->u.line.num; jx++, encoding++)
1927 if (!*encoding)
1929 src = &sources[*++encoding];
1930 jx++;
1932 else
1934 line = &src->lines[*encoding];
1936 if (coverage)
1938 if (!line->exists)
1939 coverage->lines++;
1940 if (!line->count && block->count)
1941 coverage->lines_executed++;
1943 line->exists = 1;
1944 if (!block->exceptional)
1945 line->unexceptional = 1;
1946 line->count += block->count;
1948 free (block->u.line.encoding);
1949 block->u.cycle.arc = NULL;
1950 block->u.cycle.ident = ~0U;
1952 if (!ix || ix + 1 == fn->num_blocks)
1953 /* Entry or exit block */;
1954 else if (flag_all_blocks)
1956 line_t *block_line = line;
1958 if (!block_line)
1959 block_line = &sources[fn->src].lines[fn->line];
1961 block->chain = block_line->u.blocks;
1962 block_line->u.blocks = block;
1964 else if (flag_branches)
1966 arc_t *arc;
1968 for (arc = block->succ; arc; arc = arc->succ_next)
1970 arc->line_next = line->u.branches;
1971 line->u.branches = arc;
1972 if (coverage && !arc->is_unconditional)
1973 add_branch_counts (coverage, arc);
1977 if (!line)
1978 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1981 /* Accumulate the line counts of a file. */
1983 static void
1984 accumulate_line_counts (source_t *src)
1986 line_t *line;
1987 function_t *fn, *fn_p, *fn_n;
1988 unsigned ix;
1990 /* Reverse the function order. */
1991 for (fn = src->functions, fn_p = NULL; fn;
1992 fn_p = fn, fn = fn_n)
1994 fn_n = fn->line_next;
1995 fn->line_next = fn_p;
1997 src->functions = fn_p;
1999 for (ix = src->num_lines, line = src->lines; ix--; line++)
2001 if (!flag_all_blocks)
2003 arc_t *arc, *arc_p, *arc_n;
2005 /* Total and reverse the branch information. */
2006 for (arc = line->u.branches, arc_p = NULL; arc;
2007 arc_p = arc, arc = arc_n)
2009 arc_n = arc->line_next;
2010 arc->line_next = arc_p;
2012 add_branch_counts (&src->coverage, arc);
2014 line->u.branches = arc_p;
2016 else if (line->u.blocks)
2018 /* The user expects the line count to be the number of times
2019 a line has been executed. Simply summing the block count
2020 will give an artificially high number. The Right Thing
2021 is to sum the entry counts to the graph of blocks on this
2022 line, then find the elementary cycles of the local graph
2023 and add the transition counts of those cycles. */
2024 block_t *block, *block_p, *block_n;
2025 gcov_type count = 0;
2027 /* Reverse the block information. */
2028 for (block = line->u.blocks, block_p = NULL; block;
2029 block_p = block, block = block_n)
2031 block_n = block->chain;
2032 block->chain = block_p;
2033 block->u.cycle.ident = ix;
2035 line->u.blocks = block_p;
2037 /* Sum the entry arcs. */
2038 for (block = line->u.blocks; block; block = block->chain)
2040 arc_t *arc;
2042 for (arc = block->pred; arc; arc = arc->pred_next)
2044 if (arc->src->u.cycle.ident != ix)
2045 count += arc->count;
2046 if (flag_branches)
2047 add_branch_counts (&src->coverage, arc);
2050 /* Initialize the cs_count. */
2051 for (arc = block->succ; arc; arc = arc->succ_next)
2052 arc->cs_count = arc->count;
2055 /* Find the loops. This uses the algorithm described in
2056 Tiernan 'An Efficient Search Algorithm to Find the
2057 Elementary Circuits of a Graph', CACM Dec 1970. We hold
2058 the P array by having each block point to the arc that
2059 connects to the previous block. The H array is implicitly
2060 held because of the arc ordering, and the block's
2061 previous arc pointer.
2063 Although the algorithm is O(N^3) for highly connected
2064 graphs, at worst we'll have O(N^2), as most blocks have
2065 only one or two exits. Most graphs will be small.
2067 For each loop we find, locate the arc with the smallest
2068 transition count, and add that to the cumulative
2069 count. Decrease flow over the cycle and remove the arc
2070 from consideration. */
2071 for (block = line->u.blocks; block; block = block->chain)
2073 block_t *head = block;
2074 arc_t *arc;
2076 next_vertex:;
2077 arc = head->succ;
2078 current_vertex:;
2079 while (arc)
2081 block_t *dst = arc->dst;
2082 if (/* Already used that arc. */
2083 arc->cycle
2084 /* Not to same graph, or before first vertex. */
2085 || dst->u.cycle.ident != ix
2086 /* Already in path. */
2087 || dst->u.cycle.arc)
2089 arc = arc->succ_next;
2090 continue;
2093 if (dst == block)
2095 /* Found a closing arc. */
2096 gcov_type cycle_count = arc->cs_count;
2097 arc_t *cycle_arc = arc;
2098 arc_t *probe_arc;
2100 /* Locate the smallest arc count of the loop. */
2101 for (dst = head; (probe_arc = dst->u.cycle.arc);
2102 dst = probe_arc->src)
2103 if (cycle_count > probe_arc->cs_count)
2105 cycle_count = probe_arc->cs_count;
2106 cycle_arc = probe_arc;
2109 count += cycle_count;
2110 cycle_arc->cycle = 1;
2112 /* Remove the flow from the cycle. */
2113 arc->cs_count -= cycle_count;
2114 for (dst = head; (probe_arc = dst->u.cycle.arc);
2115 dst = probe_arc->src)
2116 probe_arc->cs_count -= cycle_count;
2118 /* Unwind to the cyclic arc. */
2119 while (head != cycle_arc->src)
2121 arc = head->u.cycle.arc;
2122 head->u.cycle.arc = NULL;
2123 head = arc->src;
2125 /* Move on. */
2126 arc = arc->succ_next;
2127 continue;
2130 /* Add new block to chain. */
2131 dst->u.cycle.arc = arc;
2132 head = dst;
2133 goto next_vertex;
2135 /* We could not add another vertex to the path. Remove
2136 the last vertex from the list. */
2137 arc = head->u.cycle.arc;
2138 if (arc)
2140 /* It was not the first vertex. Move onto next arc. */
2141 head->u.cycle.arc = NULL;
2142 head = arc->src;
2143 arc = arc->succ_next;
2144 goto current_vertex;
2146 /* Mark this block as unusable. */
2147 block->u.cycle.ident = ~0U;
2150 line->count = count;
2153 if (line->exists)
2155 src->coverage.lines++;
2156 if (line->count)
2157 src->coverage.lines_executed++;
2162 /* Output information about ARC number IX. Returns nonzero if
2163 anything is output. */
2165 static int
2166 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2168 if (arc->is_call_non_return)
2170 if (arc->src->count)
2172 fnotice (gcov_file, "call %2d returned %s\n", ix,
2173 format_gcov (arc->src->count - arc->count,
2174 arc->src->count, -flag_counts));
2176 else
2177 fnotice (gcov_file, "call %2d never executed\n", ix);
2179 else if (!arc->is_unconditional)
2181 if (arc->src->count)
2182 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2183 format_gcov (arc->count, arc->src->count, -flag_counts),
2184 arc->fall_through ? " (fallthrough)"
2185 : arc->is_throw ? " (throw)" : "");
2186 else
2187 fnotice (gcov_file, "branch %2d never executed\n", ix);
2189 else if (flag_unconditional && !arc->dst->is_call_return)
2191 if (arc->src->count)
2192 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2193 format_gcov (arc->count, arc->src->count, -flag_counts));
2194 else
2195 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2197 else
2198 return 0;
2199 return 1;
2203 static const char *
2204 read_line (FILE *file)
2206 static char *string;
2207 static size_t string_len;
2208 size_t pos = 0;
2209 char *ptr;
2211 if (!string_len)
2213 string_len = 200;
2214 string = XNEWVEC (char, string_len);
2217 while ((ptr = fgets (string + pos, string_len - pos, file)))
2219 size_t len = strlen (string + pos);
2221 if (string[pos + len - 1] == '\n')
2223 string[pos + len - 1] = 0;
2224 return string;
2226 pos += len;
2227 string = XRESIZEVEC (char, string, string_len * 2);
2228 string_len *= 2;
2231 return pos ? string : NULL;
2234 /* Read in the source file one line at a time, and output that line to
2235 the gcov file preceded by its execution count and other
2236 information. */
2238 static void
2239 output_lines (FILE *gcov_file, const source_t *src)
2241 FILE *source_file;
2242 unsigned line_num; /* current line number. */
2243 const line_t *line; /* current line info ptr. */
2244 const char *retval = ""; /* status of source file reading. */
2245 function_t *fn = NULL;
2247 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2248 if (!multiple_files)
2250 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2251 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2252 no_data_file ? "-" : da_file_name);
2253 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
2255 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2257 source_file = fopen (src->name, "r");
2258 if (!source_file)
2260 fnotice (stderr, "Cannot open source file %s\n", src->name);
2261 retval = NULL;
2263 else if (src->file_time == 0)
2264 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2266 if (flag_branches)
2267 fn = src->functions;
2269 for (line_num = 1, line = &src->lines[line_num];
2270 line_num < src->num_lines; line_num++, line++)
2272 for (; fn && fn->line == line_num; fn = fn->line_next)
2274 arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
2275 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2276 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2278 for (; arc; arc = arc->pred_next)
2279 if (arc->fake)
2280 return_count -= arc->count;
2282 fprintf (gcov_file, "function %s", fn->name);
2283 fprintf (gcov_file, " called %s",
2284 format_gcov (called_count, 0, -1));
2285 fprintf (gcov_file, " returned %s",
2286 format_gcov (return_count, called_count, 0));
2287 fprintf (gcov_file, " blocks executed %s",
2288 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2289 fprintf (gcov_file, "\n");
2292 if (retval)
2293 retval = read_line (source_file);
2295 /* For lines which don't exist in the .bb file, print '-' before
2296 the source line. For lines which exist but were never
2297 executed, print '#####' or '=====' before the source line.
2298 Otherwise, print the execution count before the source line.
2299 There are 16 spaces of indentation added before the source
2300 line so that tabs won't be messed up. */
2301 fprintf (gcov_file, "%9s:%5u:%s\n",
2302 !line->exists ? "-" : line->count
2303 ? format_gcov (line->count, 0, -1)
2304 : line->unexceptional ? "#####" : "=====", line_num,
2305 retval ? retval : "/*EOF*/");
2307 if (flag_all_blocks)
2309 block_t *block;
2310 arc_t *arc;
2311 int ix, jx;
2313 for (ix = jx = 0, block = line->u.blocks; block;
2314 block = block->chain)
2316 if (!block->is_call_return)
2317 fprintf (gcov_file, "%9s:%5u-block %2d\n",
2318 !line->exists ? "-" : block->count
2319 ? format_gcov (block->count, 0, -1)
2320 : block->exceptional ? "%%%%%" : "$$$$$",
2321 line_num, ix++);
2322 if (flag_branches)
2323 for (arc = block->succ; arc; arc = arc->succ_next)
2324 jx += output_branch_count (gcov_file, jx, arc);
2327 else if (flag_branches)
2329 int ix;
2330 arc_t *arc;
2332 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2333 ix += output_branch_count (gcov_file, ix, arc);
2337 /* Handle all remaining source lines. There may be lines after the
2338 last line of code. */
2339 if (retval)
2341 for (; (retval = read_line (source_file)); line_num++)
2342 fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
2345 if (source_file)
2346 fclose (source_file);