]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/gcov.c
gcov.c (total_lines, [...]): New global vars.
[thirdparty/gcc.git] / gcc / gcov.c
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
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>
9
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.
14
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.
19
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/>. */
23
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. */
28
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
31
32 /* Need an option to show individual block counts, and show
33 probabilities of fall through arcs. */
34
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"
42
43 #include <getopt.h>
44
45 #define IN_GCOV 1
46 #include "gcov-io.h"
47 #include "gcov-io.c"
48
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. */
52
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. */
57
58 /* The code validates that the profile information read in corresponds
59 to the code currently being compiled. Rather than checking for
60 identical files, the code below computes a checksum on the CFG
61 (based on the order of basic blocks and the arcs in the CFG). If
62 the CFG checksum in the gcda file match the CFG checksum for the
63 code currently being compiled, the profile data will be used. */
64
65 /* This is the size of the buffer used to read in source file lines. */
66
67 #define STRING_SIZE 200
68
69 struct function_info;
70 struct block_info;
71 struct source_info;
72
73 /* Describes an arc between two basic blocks. */
74
75 typedef struct arc_info
76 {
77 /* source and destination blocks. */
78 struct block_info *src;
79 struct block_info *dst;
80
81 /* transition counts. */
82 gcov_type count;
83 /* used in cycle search, so that we do not clobber original counts. */
84 gcov_type cs_count;
85
86 unsigned int count_valid : 1;
87 unsigned int on_tree : 1;
88 unsigned int fake : 1;
89 unsigned int fall_through : 1;
90
91 /* Arc to a catch handler. */
92 unsigned int is_throw : 1;
93
94 /* Arc is for a function that abnormally returns. */
95 unsigned int is_call_non_return : 1;
96
97 /* Arc is for catch/setjmp. */
98 unsigned int is_nonlocal_return : 1;
99
100 /* Is an unconditional branch. */
101 unsigned int is_unconditional : 1;
102
103 /* Loop making arc. */
104 unsigned int cycle : 1;
105
106 /* Next branch on line. */
107 struct arc_info *line_next;
108
109 /* Links to next arc on src and dst lists. */
110 struct arc_info *succ_next;
111 struct arc_info *pred_next;
112 } arc_t;
113
114 /* Describes a basic block. Contains lists of arcs to successor and
115 predecessor blocks. */
116
117 typedef struct block_info
118 {
119 /* Chain of exit and entry arcs. */
120 arc_t *succ;
121 arc_t *pred;
122
123 /* Number of unprocessed exit and entry arcs. */
124 gcov_type num_succ;
125 gcov_type num_pred;
126
127 /* Block execution count. */
128 gcov_type count;
129 unsigned flags : 12;
130 unsigned count_valid : 1;
131 unsigned valid_chain : 1;
132 unsigned invalid_chain : 1;
133 unsigned exceptional : 1;
134
135 /* Block is a call instrumenting site. */
136 unsigned is_call_site : 1; /* Does the call. */
137 unsigned is_call_return : 1; /* Is the return. */
138
139 /* Block is a landing pad for longjmp or throw. */
140 unsigned is_nonlocal_return : 1;
141
142 union
143 {
144 struct
145 {
146 /* Array of line numbers and source files. source files are
147 introduced by a linenumber of zero, the next 'line number' is
148 the number of the source file. Always starts with a source
149 file. */
150 unsigned *encoding;
151 unsigned num;
152 } line; /* Valid until blocks are linked onto lines */
153 struct
154 {
155 /* Single line graph cycle workspace. Used for all-blocks
156 mode. */
157 arc_t *arc;
158 unsigned ident;
159 } cycle; /* Used in all-blocks mode, after blocks are linked onto
160 lines. */
161 } u;
162
163 /* Temporary chain for solving graph, and for chaining blocks on one
164 line. */
165 struct block_info *chain;
166
167 } block_t;
168
169 /* Describes a single function. Contains an array of basic blocks. */
170
171 typedef struct function_info
172 {
173 /* Name of function. */
174 char *name;
175 unsigned ident;
176 unsigned lineno_checksum;
177 unsigned cfg_checksum;
178
179 /* The graph contains at least one fake incoming edge. */
180 unsigned has_catch : 1;
181
182 /* Array of basic blocks. */
183 block_t *blocks;
184 unsigned num_blocks;
185 unsigned blocks_executed;
186
187 /* Raw arc coverage counts. */
188 gcov_type *counts;
189 unsigned num_counts;
190
191 /* First line number & file. */
192 unsigned line;
193 unsigned src;
194
195 /* Next function in same source file. */
196 struct function_info *line_next;
197
198 /* Next function. */
199 struct function_info *next;
200 } function_t;
201
202 /* Describes coverage of a file or function. */
203
204 typedef struct coverage_info
205 {
206 int lines;
207 int lines_executed;
208
209 int branches;
210 int branches_executed;
211 int branches_taken;
212
213 int calls;
214 int calls_executed;
215
216 char *name;
217 } coverage_t;
218
219 /* Describes a single line of source. Contains a chain of basic blocks
220 with code on it. */
221
222 typedef struct line_info
223 {
224 gcov_type count; /* execution count */
225 union
226 {
227 arc_t *branches; /* branches from blocks that end on this
228 line. Used for branch-counts when not
229 all-blocks mode. */
230 block_t *blocks; /* blocks which start on this line. Used
231 in all-blocks mode. */
232 } u;
233 unsigned exists : 1;
234 unsigned unexceptional : 1;
235 } line_t;
236
237 /* Describes a file mentioned in the block graph. Contains an array
238 of line info. */
239
240 typedef struct source_info
241 {
242 /* Canonical name of source file. */
243 char *name;
244 time_t file_time;
245
246 /* Array of line information. */
247 line_t *lines;
248 unsigned num_lines;
249
250 coverage_t coverage;
251
252 /* Functions in this source file. These are in ascending line
253 number order. */
254 function_t *functions;
255 } source_t;
256
257 typedef struct name_map
258 {
259 char *name; /* Source file name */
260 unsigned src; /* Source file */
261 } name_map_t;
262
263 /* Holds a list of function basic block graphs. */
264
265 static function_t *functions;
266 static function_t **fn_end = &functions;
267
268 static source_t *sources; /* Array of source files */
269 static unsigned n_sources; /* Number of sources */
270 static unsigned a_sources; /* Allocated sources */
271
272 static name_map_t *names; /* Mapping of file names to sources */
273 static unsigned n_names; /* Number of names */
274 static unsigned a_names; /* Allocated names */
275
276 /* This holds data summary information. */
277
278 static unsigned object_runs;
279 static unsigned program_count;
280
281 static unsigned total_lines;
282 static unsigned total_executed;
283
284 /* Modification time of graph file. */
285
286 static time_t bbg_file_time;
287
288 /* Name and file pointer of the input file for the basic block graph. */
289
290 static char *bbg_file_name;
291
292 /* Stamp of the bbg file */
293 static unsigned bbg_stamp;
294
295 /* Name and file pointer of the input file for the arc count data. */
296
297 static char *da_file_name;
298
299 /* Data file is missing. */
300
301 static int no_data_file;
302
303 /* If there is several input files, compute and display results after
304 reading all data files. This way if two or more gcda file refer to
305 the same source file (eg inline subprograms in a .h file), the
306 counts are added. */
307
308 static int multiple_files = 0;
309
310 /* Output branch probabilities. */
311
312 static int flag_branches = 0;
313
314 /* Show unconditional branches too. */
315 static int flag_unconditional = 0;
316
317 /* Output a gcov file if this is true. This is on by default, and can
318 be turned off by the -n option. */
319
320 static int flag_gcov_file = 1;
321
322 /* Output progress indication if this is true. This is off by default
323 and can be turned on by the -d option. */
324
325 static int flag_display_progress = 0;
326
327 /* For included files, make the gcov output file name include the name
328 of the input source file. For example, if x.h is included in a.c,
329 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
330
331 static int flag_long_names = 0;
332
333 /* Output count information for every basic block, not merely those
334 that contain line number information. */
335
336 static int flag_all_blocks = 0;
337
338 /* Output summary info for each function. */
339
340 static int flag_function_summary = 0;
341
342 /* Object directory file prefix. This is the directory/file where the
343 graph and data files are looked for, if nonzero. */
344
345 static char *object_directory = 0;
346
347 /* Source directory prefix. This is removed from source pathnames
348 that match, when generating the output file name. */
349
350 static char *source_prefix = 0;
351 static size_t source_length = 0;
352
353 /* Only show data for sources with relative pathnames. Absolute ones
354 usually indicate a system header file, which although it may
355 contain inline functions, is usually uninteresting. */
356 static int flag_relative_only = 0;
357
358 /* Preserve all pathname components. Needed when object files and
359 source files are in subdirectories. '/' is mangled as '#', '.' is
360 elided and '..' mangled to '^'. */
361
362 static int flag_preserve_paths = 0;
363
364 /* Output the number of times a branch was taken as opposed to the percentage
365 of times it was taken. */
366
367 static int flag_counts = 0;
368
369 /* Forward declarations. */
370 static int process_args (int, char **);
371 static void print_usage (int) ATTRIBUTE_NORETURN;
372 static void print_version (void) ATTRIBUTE_NORETURN;
373 static void process_file (const char *);
374 static void generate_results (const char *);
375 static void create_file_names (const char *);
376 static int name_search (const void *, const void *);
377 static int name_sort (const void *, const void *);
378 static char *canonicalize_name (const char *);
379 static unsigned find_source (const char *);
380 static function_t *read_graph_file (void);
381 static int read_count_file (function_t *);
382 static void solve_flow_graph (function_t *);
383 static void find_exception_blocks (function_t *);
384 static void add_branch_counts (coverage_t *, const arc_t *);
385 static void add_line_counts (coverage_t *, function_t *);
386 static void executed_summary (unsigned, unsigned);
387 static void function_summary (const coverage_t *, const char *);
388 static const char *format_gcov (gcov_type, gcov_type, int);
389 static void accumulate_line_counts (source_t *);
390 static int output_branch_count (FILE *, int, const arc_t *);
391 static void output_lines (FILE *, const source_t *);
392 static char *make_gcov_file_name (const char *, const char *);
393 static char *mangle_name (const char *, char *);
394 static void release_structures (void);
395 static void release_function (function_t *);
396 extern int main (int, char **);
397
398 int
399 main (int argc, char **argv)
400 {
401 int argno;
402 int first_arg;
403 const char *p;
404
405 p = argv[0] + strlen (argv[0]);
406 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
407 --p;
408 progname = p;
409
410 xmalloc_set_program_name (progname);
411
412 /* Unlock the stdio streams. */
413 unlock_std_streams ();
414
415 gcc_init_libintl ();
416
417 diagnostic_initialize (global_dc, 0);
418
419 /* Handle response files. */
420 expandargv (&argc, &argv);
421
422 a_names = 10;
423 names = XNEWVEC (name_map_t, a_names);
424 a_sources = 10;
425 sources = XNEWVEC (source_t, a_sources);
426
427 argno = process_args (argc, argv);
428 if (optind == argc)
429 print_usage (true);
430
431 if (argc - argno > 1)
432 multiple_files = 1;
433
434 first_arg = argno;
435
436 for (; argno != argc; argno++)
437 {
438 if (flag_display_progress)
439 printf("Processing file %d out of %d\n",
440 argno - first_arg + 1, argc - first_arg);
441 process_file (argv[argno]);
442 }
443
444 generate_results (multiple_files ? NULL : argv[argc - 1]);
445
446 release_structures ();
447
448 return 0;
449 }
450 \f
451 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
452 otherwise the output of --help. */
453
454 static void
455 print_usage (int error_p)
456 {
457 FILE *file = error_p ? stderr : stdout;
458 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
459
460 fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
461 fnotice (file, "Print code coverage information.\n\n");
462 fnotice (file, " -h, --help Print this help, then exit\n");
463 fnotice (file, " -v, --version Print version number, then exit\n");
464 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
465 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
466 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
467 rather than percentages\n");
468 fnotice (file, " -n, --no-output Do not create an output file\n");
469 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
470 source files\n");
471 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
472 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
473 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
474 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
475 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
476 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
477 fnotice (file, " -d, --display-progress Display progress information\n");
478 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
479 bug_report_url);
480 exit (status);
481 }
482
483 /* Print version information and exit. */
484
485 static void
486 print_version (void)
487 {
488 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
489 fprintf (stdout, "Copyright %s 2011 Free Software Foundation, Inc.\n",
490 _("(C)"));
491 fnotice (stdout,
492 _("This is free software; see the source for copying conditions.\n"
493 "There is NO warranty; not even for MERCHANTABILITY or \n"
494 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
495 exit (SUCCESS_EXIT_CODE);
496 }
497
498 static const struct option options[] =
499 {
500 { "help", no_argument, NULL, 'h' },
501 { "version", no_argument, NULL, 'v' },
502 { "all-blocks", no_argument, NULL, 'a' },
503 { "branch-probabilities", no_argument, NULL, 'b' },
504 { "branch-counts", no_argument, NULL, 'c' },
505 { "no-output", no_argument, NULL, 'n' },
506 { "long-file-names", no_argument, NULL, 'l' },
507 { "function-summaries", no_argument, NULL, 'f' },
508 { "preserve-paths", no_argument, NULL, 'p' },
509 { "relative-only", no_argument, NULL, 'r' },
510 { "object-directory", required_argument, NULL, 'o' },
511 { "object-file", required_argument, NULL, 'o' },
512 { "source-prefix", required_argument, NULL, 's' },
513 { "unconditional-branches", no_argument, NULL, 'u' },
514 { "display-progress", no_argument, NULL, 'd' },
515 { 0, 0, 0, 0 }
516 };
517
518 /* Process args, return index to first non-arg. */
519
520 static int
521 process_args (int argc, char **argv)
522 {
523 int opt;
524
525 while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
526 {
527 switch (opt)
528 {
529 case 'a':
530 flag_all_blocks = 1;
531 break;
532 case 'b':
533 flag_branches = 1;
534 break;
535 case 'c':
536 flag_counts = 1;
537 break;
538 case 'f':
539 flag_function_summary = 1;
540 break;
541 case 'h':
542 print_usage (false);
543 /* print_usage will exit. */
544 case 'l':
545 flag_long_names = 1;
546 break;
547 case 'n':
548 flag_gcov_file = 0;
549 break;
550 case 'o':
551 object_directory = optarg;
552 break;
553 case 's':
554 source_prefix = optarg;
555 source_length = strlen (source_prefix);
556 break;
557 case 'r':
558 flag_relative_only = 1;
559 break;
560 case 'p':
561 flag_preserve_paths = 1;
562 break;
563 case 'u':
564 flag_unconditional = 1;
565 break;
566 case 'd':
567 flag_display_progress = 1;
568 break;
569 case 'v':
570 print_version ();
571 /* print_version will exit. */
572 default:
573 print_usage (true);
574 /* print_usage will exit. */
575 }
576 }
577
578 return optind;
579 }
580
581 /* Process a single input file. */
582
583 static void
584 process_file (const char *file_name)
585 {
586 function_t *fns;
587
588 create_file_names (file_name);
589 fns = read_graph_file ();
590 if (!fns)
591 return;
592
593 read_count_file (fns);
594 while (fns)
595 {
596 function_t *fn = fns;
597
598 fns = fn->next;
599 fn->next = NULL;
600 if (fn->counts)
601 {
602 unsigned src = fn->src;
603 unsigned line = fn->line;
604 unsigned block_no;
605 function_t *probe, **prev;
606
607 /* Now insert it into the source file's list of
608 functions. Normally functions will be encountered in
609 ascending order, so a simple scan is quick. Note we're
610 building this list in reverse order. */
611 for (prev = &sources[src].functions;
612 (probe = *prev); prev = &probe->line_next)
613 if (probe->line <= line)
614 break;
615 fn->line_next = probe;
616 *prev = fn;
617
618 /* Mark last line in files touched by function. */
619 for (block_no = 0; block_no != fn->num_blocks; block_no++)
620 {
621 unsigned *enc = fn->blocks[block_no].u.line.encoding;
622 unsigned num = fn->blocks[block_no].u.line.num;
623
624 for (; num--; enc++)
625 if (!*enc)
626 {
627 if (enc[1] != src)
628 {
629 if (line >= sources[src].num_lines)
630 sources[src].num_lines = line + 1;
631 line = 0;
632 src = enc[1];
633 }
634 enc++;
635 num--;
636 }
637 else if (*enc > line)
638 line = *enc;
639 }
640 if (line >= sources[src].num_lines)
641 sources[src].num_lines = line + 1;
642
643 solve_flow_graph (fn);
644 if (fn->has_catch)
645 find_exception_blocks (fn);
646 *fn_end = fn;
647 fn_end = &fn->next;
648 }
649 else
650 /* The function was not in the executable -- some other
651 instance must have been selected. */
652 release_function (fn);
653 }
654 }
655
656 static void
657 generate_results (const char *file_name)
658 {
659 unsigned ix;
660 source_t *src;
661 function_t *fn;
662
663 for (ix = n_sources, src = sources; ix--; src++)
664 if (src->num_lines)
665 src->lines = XCNEWVEC (line_t, src->num_lines);
666
667 for (fn = functions; fn; fn = fn->next)
668 {
669 coverage_t coverage;
670
671 memset (&coverage, 0, sizeof (coverage));
672 coverage.name = fn->name;
673 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
674 if (flag_function_summary)
675 {
676 function_summary (&coverage, "Function");
677 fnotice (stdout, "\n");
678 }
679 }
680
681 if (file_name)
682 {
683 name_map_t *name_map = (name_map_t *)bsearch
684 (file_name, names, n_names, sizeof (*names), name_search);
685 if (name_map)
686 file_name = sources[name_map->src].coverage.name;
687 else
688 file_name = canonicalize_name (file_name);
689 }
690
691 for (ix = n_sources, src = sources; ix--; src++)
692 {
693 if (flag_relative_only)
694 {
695 /* Ignore this source, if it is an absolute path (after
696 source prefix removal). */
697 char first = src->coverage.name[0];
698
699 #if HAVE_DOS_BASED_FILE_SYSTEM
700 if (first && src->coverage.name[1] == ':')
701 first = src->coverage.name[2];
702 #endif
703 if (IS_DIR_SEPARATOR (first))
704 continue;
705 }
706
707 accumulate_line_counts (src);
708 function_summary (&src->coverage, "File");
709 total_lines += src->coverage.lines;
710 total_executed += src->coverage.lines_executed;
711 if (flag_gcov_file && src->coverage.lines)
712 {
713 char *gcov_file_name
714 = make_gcov_file_name (file_name, src->coverage.name);
715 FILE *gcov_file = fopen (gcov_file_name, "w");
716
717 if (gcov_file)
718 {
719 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
720 output_lines (gcov_file, src);
721 if (ferror (gcov_file))
722 fnotice (stderr, "Error writing output file '%s'\n",
723 gcov_file_name);
724 fclose (gcov_file);
725 }
726 else
727 fnotice (stderr, "Could not open output file '%s'\n",
728 gcov_file_name);
729 free (gcov_file_name);
730 }
731 fnotice (stdout, "\n");
732 }
733
734 if (!file_name)
735 executed_summary (total_lines, total_executed);
736 }
737
738 /* Release a function structure */
739
740 static void
741 release_function (function_t *fn)
742 {
743 unsigned ix;
744 block_t *block;
745
746 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
747 {
748 arc_t *arc, *arc_n;
749
750 for (arc = block->succ; arc; arc = arc_n)
751 {
752 arc_n = arc->succ_next;
753 free (arc);
754 }
755 }
756 free (fn->blocks);
757 free (fn->counts);
758 }
759
760 /* Release all memory used. */
761
762 static void
763 release_structures (void)
764 {
765 unsigned ix;
766 function_t *fn;
767
768 for (ix = n_sources; ix--;)
769 free (sources[ix].lines);
770 free (sources);
771
772 for (ix = n_names; ix--;)
773 free (names[ix].name);
774 free (names);
775
776 while ((fn = functions))
777 {
778 functions = fn->next;
779 release_function (fn);
780 }
781 }
782
783 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
784 is not specified, these are named from FILE_NAME sans extension. If
785 OBJECT_DIRECTORY is specified and is a directory, the files are in that
786 directory, but named from the basename of the FILE_NAME, sans extension.
787 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
788 and the data files are named from that. */
789
790 static void
791 create_file_names (const char *file_name)
792 {
793 char *cptr;
794 char *name;
795 int length = strlen (file_name);
796 int base;
797
798 /* Free previous file names. */
799 free (bbg_file_name);
800 free (da_file_name);
801 da_file_name = bbg_file_name = NULL;
802 bbg_file_time = 0;
803 bbg_stamp = 0;
804
805 if (object_directory && object_directory[0])
806 {
807 struct stat status;
808
809 length += strlen (object_directory) + 2;
810 name = XNEWVEC (char, length);
811 name[0] = 0;
812
813 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
814 strcat (name, object_directory);
815 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
816 strcat (name, "/");
817 }
818 else
819 {
820 name = XNEWVEC (char, length + 1);
821 strcpy (name, file_name);
822 base = 0;
823 }
824
825 if (base)
826 {
827 /* Append source file name. */
828 const char *cptr = lbasename (file_name);
829 strcat (name, cptr ? cptr : file_name);
830 }
831
832 /* Remove the extension. */
833 cptr = strrchr (name, '.');
834 if (cptr)
835 *cptr = 0;
836
837 length = strlen (name);
838
839 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
840 strcpy (bbg_file_name, name);
841 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
842
843 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
844 strcpy (da_file_name, name);
845 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
846
847 free (name);
848 return;
849 }
850
851 /* A is a string and B is a pointer to name_map_t. Compare for file
852 name orderability. */
853
854 static int
855 name_search (const void *a_, const void *b_)
856 {
857 const char *a = (const char *)a_;
858 const name_map_t *b = (const name_map_t *)b_;
859
860 #if HAVE_DOS_BASED_FILE_SYSTEM
861 return strcasecmp (a, b->name);
862 #else
863 return strcmp (a, b->name);
864 #endif
865 }
866
867 /* A and B are a pointer to name_map_t. Compare for file name
868 orderability. */
869
870 static int
871 name_sort (const void *a_, const void *b_)
872 {
873 const name_map_t *a = (const name_map_t *)a_;
874 return name_search (a->name, b_);
875 }
876
877 /* Find or create a source file structure for FILE_NAME. Copies
878 FILE_NAME on creation */
879
880 static unsigned
881 find_source (const char *file_name)
882 {
883 name_map_t *name_map;
884 char *canon;
885 unsigned idx;
886 struct stat status;
887
888 if (!file_name)
889 file_name = "<unknown>";
890 name_map = (name_map_t *)bsearch
891 (file_name, names, n_names, sizeof (*names), name_search);
892 if (name_map)
893 {
894 idx = name_map->src;
895 goto check_date;
896 }
897
898 if (n_names + 2 > a_names)
899 {
900 /* Extend the name map array -- we'll be inserting one or two
901 entries. */
902 a_names *= 2;
903 name_map = XNEWVEC (name_map_t, a_names);
904 memcpy (name_map, names, n_names * sizeof (*names));
905 free (names);
906 names = name_map;
907 }
908
909 /* Not found, try the canonical name. */
910 canon = canonicalize_name (file_name);
911 name_map = (name_map_t *)bsearch
912 (canon, names, n_names, sizeof (*names), name_search);
913 if (!name_map)
914 {
915 /* Not found with canonical name, create a new source. */
916 source_t *src;
917
918 if (n_sources == a_sources)
919 {
920 a_sources *= 2;
921 src = XNEWVEC (source_t, a_sources);
922 memcpy (src, sources, n_sources * sizeof (*sources));
923 free (sources);
924 sources = src;
925 }
926
927 idx = n_sources;
928
929 name_map = &names[n_names++];
930 name_map->name = canon;
931 name_map->src = idx;
932
933 src = &sources[n_sources++];
934 memset (src, 0, sizeof (*src));
935 src->name = canon;
936 src->coverage.name = src->name;
937 if (source_length
938 #if HAVE_DOS_BASED_FILE_SYSTEM
939 /* You lose if separators don't match exactly in the
940 prefix. */
941 && !strncasecmp (source_prefix, src->coverage.name, source_length)
942 #else
943 && !strncmp (source_prefix, src->coverage.name, source_length)
944 #endif
945 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
946 src->coverage.name += source_length + 1;
947 if (!stat (src->name, &status))
948 src->file_time = status.st_mtime;
949 }
950 else
951 idx = name_map->src;
952
953 if (name_search (file_name, name_map))
954 {
955 /* Append the non-canonical name. */
956 name_map = &names[n_names++];
957 name_map->name = xstrdup (file_name);
958 name_map->src = idx;
959 }
960
961 /* Resort the name map. */
962 qsort (names, n_names, sizeof (*names), name_sort);
963
964 check_date:
965 if (sources[idx].file_time > bbg_file_time)
966 {
967 static int info_emitted;
968
969 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
970 file_name, bbg_file_name);
971 if (!info_emitted)
972 {
973 fnotice (stderr,
974 "(the message is only displayed one per source file)\n");
975 info_emitted = 1;
976 }
977 sources[idx].file_time = 0;
978 }
979
980 return idx;
981 }
982
983 /* Read the graph file. Return list of functions read -- in reverse order. */
984
985 static function_t *
986 read_graph_file (void)
987 {
988 unsigned version;
989 unsigned current_tag = 0;
990 function_t *fn = NULL;
991 function_t *fns = NULL;
992 function_t **fns_end = &fns;
993 unsigned src_idx = 0;
994 unsigned ix;
995 unsigned tag;
996
997 if (!gcov_open (bbg_file_name, 1))
998 {
999 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
1000 return fns;
1001 }
1002 bbg_file_time = gcov_time ();
1003 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1004 {
1005 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
1006 gcov_close ();
1007 return fns;
1008 }
1009
1010 version = gcov_read_unsigned ();
1011 if (version != GCOV_VERSION)
1012 {
1013 char v[4], e[4];
1014
1015 GCOV_UNSIGNED2STRING (v, version);
1016 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1017
1018 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1019 bbg_file_name, v, e);
1020 }
1021 bbg_stamp = gcov_read_unsigned ();
1022
1023 while ((tag = gcov_read_unsigned ()))
1024 {
1025 unsigned length = gcov_read_unsigned ();
1026 gcov_position_t base = gcov_position ();
1027
1028 if (tag == GCOV_TAG_FUNCTION)
1029 {
1030 char *function_name;
1031 unsigned ident, lineno;
1032 unsigned lineno_checksum, cfg_checksum;
1033
1034 ident = gcov_read_unsigned ();
1035 lineno_checksum = gcov_read_unsigned ();
1036 cfg_checksum = gcov_read_unsigned ();
1037 function_name = xstrdup (gcov_read_string ());
1038 src_idx = find_source (gcov_read_string ());
1039 lineno = gcov_read_unsigned ();
1040
1041 fn = XCNEW (function_t);
1042 fn->name = function_name;
1043 fn->ident = ident;
1044 fn->lineno_checksum = lineno_checksum;
1045 fn->cfg_checksum = cfg_checksum;
1046 fn->src = src_idx;
1047 fn->line = lineno;
1048
1049 fn->line_next = NULL;
1050 fn->next = NULL;
1051 *fns_end = fn;
1052 fns_end = &fn->next;
1053 current_tag = tag;
1054 }
1055 else if (fn && tag == GCOV_TAG_BLOCKS)
1056 {
1057 if (fn->blocks)
1058 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1059 bbg_file_name, fn->name);
1060 else
1061 {
1062 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1063 fn->num_blocks = num_blocks;
1064
1065 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
1066 for (ix = 0; ix != num_blocks; ix++)
1067 fn->blocks[ix].flags = gcov_read_unsigned ();
1068 }
1069 }
1070 else if (fn && tag == GCOV_TAG_ARCS)
1071 {
1072 unsigned src = gcov_read_unsigned ();
1073 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1074 block_t *src_blk = &fn->blocks[src];
1075 unsigned mark_catches = 0;
1076 struct arc_info *arc;
1077
1078 if (src >= fn->num_blocks || fn->blocks[src].succ)
1079 goto corrupt;
1080
1081 while (num_dests--)
1082 {
1083 unsigned dest = gcov_read_unsigned ();
1084 unsigned flags = gcov_read_unsigned ();
1085
1086 if (dest >= fn->num_blocks)
1087 goto corrupt;
1088 arc = XCNEW (arc_t);
1089
1090 arc->dst = &fn->blocks[dest];
1091 arc->src = src_blk;
1092
1093 arc->count = 0;
1094 arc->count_valid = 0;
1095 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1096 arc->fake = !!(flags & GCOV_ARC_FAKE);
1097 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1098
1099 arc->succ_next = src_blk->succ;
1100 src_blk->succ = arc;
1101 src_blk->num_succ++;
1102
1103 arc->pred_next = fn->blocks[dest].pred;
1104 fn->blocks[dest].pred = arc;
1105 fn->blocks[dest].num_pred++;
1106
1107 if (arc->fake)
1108 {
1109 if (src)
1110 {
1111 /* Exceptional exit from this function, the
1112 source block must be a call. */
1113 fn->blocks[src].is_call_site = 1;
1114 arc->is_call_non_return = 1;
1115 mark_catches = 1;
1116 }
1117 else
1118 {
1119 /* Non-local return from a callee of this
1120 function. The destination block is a setjmp. */
1121 arc->is_nonlocal_return = 1;
1122 fn->blocks[dest].is_nonlocal_return = 1;
1123 }
1124 }
1125
1126 if (!arc->on_tree)
1127 fn->num_counts++;
1128 }
1129
1130 if (mark_catches)
1131 {
1132 /* We have a fake exit from this block. The other
1133 non-fall through exits must be to catch handlers.
1134 Mark them as catch arcs. */
1135
1136 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1137 if (!arc->fake && !arc->fall_through)
1138 {
1139 arc->is_throw = 1;
1140 fn->has_catch = 1;
1141 }
1142 }
1143 }
1144 else if (fn && tag == GCOV_TAG_LINES)
1145 {
1146 unsigned blockno = gcov_read_unsigned ();
1147 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1148
1149 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1150 goto corrupt;
1151
1152 for (ix = 0; ; )
1153 {
1154 unsigned lineno = gcov_read_unsigned ();
1155
1156 if (lineno)
1157 {
1158 if (!ix)
1159 {
1160 line_nos[ix++] = 0;
1161 line_nos[ix++] = src_idx;
1162 }
1163 line_nos[ix++] = lineno;
1164 }
1165 else
1166 {
1167 const char *file_name = gcov_read_string ();
1168
1169 if (!file_name)
1170 break;
1171 src_idx = find_source (file_name);
1172 line_nos[ix++] = 0;
1173 line_nos[ix++] = src_idx;
1174 }
1175 }
1176
1177 fn->blocks[blockno].u.line.encoding = line_nos;
1178 fn->blocks[blockno].u.line.num = ix;
1179 }
1180 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1181 {
1182 fn = NULL;
1183 current_tag = 0;
1184 }
1185 gcov_sync (base, length);
1186 if (gcov_is_error ())
1187 {
1188 corrupt:;
1189 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1190 break;
1191 }
1192 }
1193 gcov_close ();
1194
1195 if (!fns)
1196 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1197
1198 return fns;
1199 }
1200
1201 /* Reads profiles from the count file and attach to each
1202 function. Return nonzero if fatal error. */
1203
1204 static int
1205 read_count_file (function_t *fns)
1206 {
1207 unsigned ix;
1208 unsigned version;
1209 unsigned tag;
1210 function_t *fn = NULL;
1211 int error = 0;
1212
1213 if (!gcov_open (da_file_name, 1))
1214 {
1215 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1216 da_file_name);
1217 no_data_file = 1;
1218 return 0;
1219 }
1220 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1221 {
1222 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1223 cleanup:;
1224 gcov_close ();
1225 return 1;
1226 }
1227 version = gcov_read_unsigned ();
1228 if (version != GCOV_VERSION)
1229 {
1230 char v[4], e[4];
1231
1232 GCOV_UNSIGNED2STRING (v, version);
1233 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1234
1235 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1236 da_file_name, v, e);
1237 }
1238 tag = gcov_read_unsigned ();
1239 if (tag != bbg_stamp)
1240 {
1241 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1242 goto cleanup;
1243 }
1244
1245 while ((tag = gcov_read_unsigned ()))
1246 {
1247 unsigned length = gcov_read_unsigned ();
1248 unsigned long base = gcov_position ();
1249
1250 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1251 {
1252 struct gcov_summary summary;
1253 gcov_read_summary (&summary);
1254 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1255 program_count++;
1256 }
1257 else if (tag == GCOV_TAG_FUNCTION && !length)
1258 ; /* placeholder */
1259 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1260 {
1261 unsigned ident;
1262 struct function_info *fn_n;
1263
1264 /* Try to find the function in the list. To speed up the
1265 search, first start from the last function found. */
1266 ident = gcov_read_unsigned ();
1267 fn_n = fns;
1268 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1269 {
1270 if (fn)
1271 ;
1272 else if ((fn = fn_n))
1273 fn_n = NULL;
1274 else
1275 {
1276 fnotice (stderr, "%s:unknown function '%u'\n",
1277 da_file_name, ident);
1278 break;
1279 }
1280 if (fn->ident == ident)
1281 break;
1282 }
1283
1284 if (!fn)
1285 ;
1286 else if (gcov_read_unsigned () != fn->lineno_checksum
1287 || gcov_read_unsigned () != fn->cfg_checksum)
1288 {
1289 mismatch:;
1290 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1291 da_file_name, fn->name);
1292 goto cleanup;
1293 }
1294 }
1295 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1296 {
1297 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1298 goto mismatch;
1299
1300 if (!fn->counts)
1301 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1302
1303 for (ix = 0; ix != fn->num_counts; ix++)
1304 fn->counts[ix] += gcov_read_counter ();
1305 }
1306 gcov_sync (base, length);
1307 if ((error = gcov_is_error ()))
1308 {
1309 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1310 da_file_name);
1311 goto cleanup;
1312 }
1313 }
1314
1315 gcov_close ();
1316 return 0;
1317 }
1318
1319 /* Solve the flow graph. Propagate counts from the instrumented arcs
1320 to the blocks and the uninstrumented arcs. */
1321
1322 static void
1323 solve_flow_graph (function_t *fn)
1324 {
1325 unsigned ix;
1326 arc_t *arc;
1327 gcov_type *count_ptr = fn->counts;
1328 block_t *blk;
1329 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1330 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1331
1332 /* The arcs were built in reverse order. Fix that now. */
1333 for (ix = fn->num_blocks; ix--;)
1334 {
1335 arc_t *arc_p, *arc_n;
1336
1337 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1338 arc_p = arc, arc = arc_n)
1339 {
1340 arc_n = arc->succ_next;
1341 arc->succ_next = arc_p;
1342 }
1343 fn->blocks[ix].succ = arc_p;
1344
1345 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1346 arc_p = arc, arc = arc_n)
1347 {
1348 arc_n = arc->pred_next;
1349 arc->pred_next = arc_p;
1350 }
1351 fn->blocks[ix].pred = arc_p;
1352 }
1353
1354 if (fn->num_blocks < 2)
1355 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1356 bbg_file_name, fn->name);
1357 else
1358 {
1359 if (fn->blocks[0].num_pred)
1360 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1361 bbg_file_name, fn->name);
1362 else
1363 /* We can't deduce the entry block counts from the lack of
1364 predecessors. */
1365 fn->blocks[0].num_pred = ~(unsigned)0;
1366
1367 if (fn->blocks[fn->num_blocks - 1].num_succ)
1368 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1369 bbg_file_name, fn->name);
1370 else
1371 /* Likewise, we can't deduce exit block counts from the lack
1372 of its successors. */
1373 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1374 }
1375
1376 /* Propagate the measured counts, this must be done in the same
1377 order as the code in profile.c */
1378 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1379 {
1380 block_t const *prev_dst = NULL;
1381 int out_of_order = 0;
1382 int non_fake_succ = 0;
1383
1384 for (arc = blk->succ; arc; arc = arc->succ_next)
1385 {
1386 if (!arc->fake)
1387 non_fake_succ++;
1388
1389 if (!arc->on_tree)
1390 {
1391 if (count_ptr)
1392 arc->count = *count_ptr++;
1393 arc->count_valid = 1;
1394 blk->num_succ--;
1395 arc->dst->num_pred--;
1396 }
1397 if (prev_dst && prev_dst > arc->dst)
1398 out_of_order = 1;
1399 prev_dst = arc->dst;
1400 }
1401 if (non_fake_succ == 1)
1402 {
1403 /* If there is only one non-fake exit, it is an
1404 unconditional branch. */
1405 for (arc = blk->succ; arc; arc = arc->succ_next)
1406 if (!arc->fake)
1407 {
1408 arc->is_unconditional = 1;
1409 /* If this block is instrumenting a call, it might be
1410 an artificial block. It is not artificial if it has
1411 a non-fallthrough exit, or the destination of this
1412 arc has more than one entry. Mark the destination
1413 block as a return site, if none of those conditions
1414 hold. */
1415 if (blk->is_call_site && arc->fall_through
1416 && arc->dst->pred == arc && !arc->pred_next)
1417 arc->dst->is_call_return = 1;
1418 }
1419 }
1420
1421 /* Sort the successor arcs into ascending dst order. profile.c
1422 normally produces arcs in the right order, but sometimes with
1423 one or two out of order. We're not using a particularly
1424 smart sort. */
1425 if (out_of_order)
1426 {
1427 arc_t *start = blk->succ;
1428 unsigned changes = 1;
1429
1430 while (changes)
1431 {
1432 arc_t *arc, *arc_p, *arc_n;
1433
1434 changes = 0;
1435 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1436 {
1437 if (arc->dst > arc_n->dst)
1438 {
1439 changes = 1;
1440 if (arc_p)
1441 arc_p->succ_next = arc_n;
1442 else
1443 start = arc_n;
1444 arc->succ_next = arc_n->succ_next;
1445 arc_n->succ_next = arc;
1446 arc_p = arc_n;
1447 }
1448 else
1449 {
1450 arc_p = arc;
1451 arc = arc_n;
1452 }
1453 }
1454 }
1455 blk->succ = start;
1456 }
1457
1458 /* Place it on the invalid chain, it will be ignored if that's
1459 wrong. */
1460 blk->invalid_chain = 1;
1461 blk->chain = invalid_blocks;
1462 invalid_blocks = blk;
1463 }
1464
1465 while (invalid_blocks || valid_blocks)
1466 {
1467 while ((blk = invalid_blocks))
1468 {
1469 gcov_type total = 0;
1470 const arc_t *arc;
1471
1472 invalid_blocks = blk->chain;
1473 blk->invalid_chain = 0;
1474 if (!blk->num_succ)
1475 for (arc = blk->succ; arc; arc = arc->succ_next)
1476 total += arc->count;
1477 else if (!blk->num_pred)
1478 for (arc = blk->pred; arc; arc = arc->pred_next)
1479 total += arc->count;
1480 else
1481 continue;
1482
1483 blk->count = total;
1484 blk->count_valid = 1;
1485 blk->chain = valid_blocks;
1486 blk->valid_chain = 1;
1487 valid_blocks = blk;
1488 }
1489 while ((blk = valid_blocks))
1490 {
1491 gcov_type total;
1492 arc_t *arc, *inv_arc;
1493
1494 valid_blocks = blk->chain;
1495 blk->valid_chain = 0;
1496 if (blk->num_succ == 1)
1497 {
1498 block_t *dst;
1499
1500 total = blk->count;
1501 inv_arc = NULL;
1502 for (arc = blk->succ; arc; arc = arc->succ_next)
1503 {
1504 total -= arc->count;
1505 if (!arc->count_valid)
1506 inv_arc = arc;
1507 }
1508 dst = inv_arc->dst;
1509 inv_arc->count_valid = 1;
1510 inv_arc->count = total;
1511 blk->num_succ--;
1512 dst->num_pred--;
1513 if (dst->count_valid)
1514 {
1515 if (dst->num_pred == 1 && !dst->valid_chain)
1516 {
1517 dst->chain = valid_blocks;
1518 dst->valid_chain = 1;
1519 valid_blocks = dst;
1520 }
1521 }
1522 else
1523 {
1524 if (!dst->num_pred && !dst->invalid_chain)
1525 {
1526 dst->chain = invalid_blocks;
1527 dst->invalid_chain = 1;
1528 invalid_blocks = dst;
1529 }
1530 }
1531 }
1532 if (blk->num_pred == 1)
1533 {
1534 block_t *src;
1535
1536 total = blk->count;
1537 inv_arc = NULL;
1538 for (arc = blk->pred; arc; arc = arc->pred_next)
1539 {
1540 total -= arc->count;
1541 if (!arc->count_valid)
1542 inv_arc = arc;
1543 }
1544 src = inv_arc->src;
1545 inv_arc->count_valid = 1;
1546 inv_arc->count = total;
1547 blk->num_pred--;
1548 src->num_succ--;
1549 if (src->count_valid)
1550 {
1551 if (src->num_succ == 1 && !src->valid_chain)
1552 {
1553 src->chain = valid_blocks;
1554 src->valid_chain = 1;
1555 valid_blocks = src;
1556 }
1557 }
1558 else
1559 {
1560 if (!src->num_succ && !src->invalid_chain)
1561 {
1562 src->chain = invalid_blocks;
1563 src->invalid_chain = 1;
1564 invalid_blocks = src;
1565 }
1566 }
1567 }
1568 }
1569 }
1570
1571 /* If the graph has been correctly solved, every block will have a
1572 valid count. */
1573 for (ix = 0; ix < fn->num_blocks; ix++)
1574 if (!fn->blocks[ix].count_valid)
1575 {
1576 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1577 bbg_file_name, fn->name);
1578 break;
1579 }
1580 }
1581
1582 /* Mark all the blocks only reachable via an incoming catch. */
1583
1584 static void
1585 find_exception_blocks (function_t *fn)
1586 {
1587 unsigned ix;
1588 block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1589
1590 /* First mark all blocks as exceptional. */
1591 for (ix = fn->num_blocks; ix--;)
1592 fn->blocks[ix].exceptional = 1;
1593
1594 /* Now mark all the blocks reachable via non-fake edges */
1595 queue[0] = fn->blocks;
1596 queue[0]->exceptional = 0;
1597 for (ix = 1; ix;)
1598 {
1599 block_t *block = queue[--ix];
1600 const arc_t *arc;
1601
1602 for (arc = block->succ; arc; arc = arc->succ_next)
1603 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1604 {
1605 arc->dst->exceptional = 0;
1606 queue[ix++] = arc->dst;
1607 }
1608 }
1609 }
1610 \f
1611
1612 /* Increment totals in COVERAGE according to arc ARC. */
1613
1614 static void
1615 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1616 {
1617 if (arc->is_call_non_return)
1618 {
1619 coverage->calls++;
1620 if (arc->src->count)
1621 coverage->calls_executed++;
1622 }
1623 else if (!arc->is_unconditional)
1624 {
1625 coverage->branches++;
1626 if (arc->src->count)
1627 coverage->branches_executed++;
1628 if (arc->count)
1629 coverage->branches_taken++;
1630 }
1631 }
1632
1633 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1634 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1635 If DP is zero, no decimal point is printed. Only print 100% when
1636 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1637 format TOP. Return pointer to a static string. */
1638
1639 static char const *
1640 format_gcov (gcov_type top, gcov_type bottom, int dp)
1641 {
1642 static char buffer[20];
1643
1644 if (dp >= 0)
1645 {
1646 float ratio = bottom ? (float)top / bottom : 0;
1647 int ix;
1648 unsigned limit = 100;
1649 unsigned percent;
1650
1651 for (ix = dp; ix--; )
1652 limit *= 10;
1653
1654 percent = (unsigned) (ratio * limit + (float)0.5);
1655 if (percent <= 0 && top)
1656 percent = 1;
1657 else if (percent >= limit && top != bottom)
1658 percent = limit - 1;
1659 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1660 if (dp)
1661 {
1662 dp++;
1663 do
1664 {
1665 buffer[ix+1] = buffer[ix];
1666 ix--;
1667 }
1668 while (dp--);
1669 buffer[ix + 1] = '.';
1670 }
1671 }
1672 else
1673 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1674
1675 return buffer;
1676 }
1677
1678 /* Summary of execution */
1679
1680 static void
1681 executed_summary (unsigned lines, unsigned executed)
1682 {
1683 if (lines)
1684 fnotice (stdout, "Lines executed:%s of %d\n",
1685 format_gcov (executed, lines, 2), lines);
1686 else
1687 fnotice (stdout, "No executable lines\n");
1688 }
1689
1690 /* Output summary info for a function or file. */
1691
1692 static void
1693 function_summary (const coverage_t *coverage, const char *title)
1694 {
1695 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1696 executed_summary (coverage->lines, coverage->lines_executed);
1697
1698 if (flag_branches)
1699 {
1700 if (coverage->branches)
1701 {
1702 fnotice (stdout, "Branches executed:%s of %d\n",
1703 format_gcov (coverage->branches_executed,
1704 coverage->branches, 2),
1705 coverage->branches);
1706 fnotice (stdout, "Taken at least once:%s of %d\n",
1707 format_gcov (coverage->branches_taken,
1708 coverage->branches, 2),
1709 coverage->branches);
1710 }
1711 else
1712 fnotice (stdout, "No branches\n");
1713 if (coverage->calls)
1714 fnotice (stdout, "Calls executed:%s of %d\n",
1715 format_gcov (coverage->calls_executed, coverage->calls, 2),
1716 coverage->calls);
1717 else
1718 fnotice (stdout, "No calls\n");
1719 }
1720 }
1721
1722 /* Canonicalize the filename NAME by canonicalizing directory
1723 separators, eliding . components and resolving .. components
1724 appropriately. Always returns a unique string. */
1725
1726 static char *
1727 canonicalize_name (const char *name)
1728 {
1729 /* The canonical name cannot be longer than the incoming name. */
1730 char *result = XNEWVEC (char, strlen (name) + 1);
1731 const char *base = name, *probe;
1732 char *ptr = result;
1733 char *dd_base;
1734 int slash = 0;
1735
1736 #if HAVE_DOS_BASED_FILE_SYSTEM
1737 if (base[0] && base[1] == ':')
1738 {
1739 result[0] = base[0];
1740 result[1] = ':';
1741 base += 2;
1742 ptr += 2;
1743 }
1744 #endif
1745 for (dd_base = ptr; *base; base = probe)
1746 {
1747 size_t len;
1748
1749 for (probe = base; *probe; probe++)
1750 if (IS_DIR_SEPARATOR (*probe))
1751 break;
1752
1753 len = probe - base;
1754 if (len == 1 && base[0] == '.')
1755 /* Elide a '.' directory */
1756 ;
1757 else if (len == 2 && base[0] == '.' && base[1] == '.')
1758 {
1759 /* '..', we can only elide it and the previous directory, if
1760 we're not a symlink. */
1761 struct stat ATTRIBUTE_UNUSED buf;
1762
1763 *ptr = 0;
1764 if (dd_base == ptr
1765 #if defined (S_ISLNK)
1766 /* S_ISLNK is not POSIX.1-1996. */
1767 || stat (result, &buf) || S_ISLNK (buf.st_mode)
1768 #endif
1769 )
1770 {
1771 /* Cannot elide, or unreadable or a symlink. */
1772 dd_base = ptr + 2 + slash;
1773 goto regular;
1774 }
1775 while (ptr != dd_base && *ptr != '/')
1776 ptr--;
1777 slash = ptr != result;
1778 }
1779 else
1780 {
1781 regular:
1782 /* Regular pathname component. */
1783 if (slash)
1784 *ptr++ = '/';
1785 memcpy (ptr, base, len);
1786 ptr += len;
1787 slash = 1;
1788 }
1789
1790 for (; IS_DIR_SEPARATOR (*probe); probe++)
1791 continue;
1792 }
1793 *ptr = 0;
1794
1795 return result;
1796 }
1797
1798 /* Generate an output file name. INPUT_NAME is the canonicalized main
1799 input file and SRC_NAME is the canonicalized file name.
1800 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
1801 long_output_names we prepend the processed name of the input file
1802 to each output name (except when the current source file is the
1803 input file, so you don't get a double concatenation). The two
1804 components are separated by '##'. With preserve_paths we create a
1805 filename from all path components of the source file, replacing '/'
1806 with '#', and .. with '^', without it we simply take the basename
1807 component. (Remember, the canonicalized name will already have
1808 elided '.' components and converted \\ separators.) */
1809
1810 static char *
1811 make_gcov_file_name (const char *input_name, const char *src_name)
1812 {
1813 char *ptr;
1814 char *result;
1815
1816 if (flag_long_names && input_name && strcmp (src_name, input_name))
1817 {
1818 /* Generate the input filename part. */
1819 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1820
1821 ptr = result;
1822 ptr = mangle_name (input_name, ptr);
1823 ptr[0] = ptr[1] = '#';
1824 ptr += 2;
1825 }
1826 else
1827 {
1828 result = XNEWVEC (char, strlen (src_name) + 10);
1829 ptr = result;
1830 }
1831
1832 ptr = mangle_name (src_name, ptr);
1833 strcpy (ptr, ".gcov");
1834
1835 return result;
1836 }
1837
1838 static char *
1839 mangle_name (char const *base, char *ptr)
1840 {
1841 size_t len;
1842
1843 /* Generate the source filename part. */
1844 if (!flag_preserve_paths)
1845 {
1846 base = lbasename (base);
1847 len = strlen (base);
1848 memcpy (ptr, base, len);
1849 ptr += len;
1850 }
1851 else
1852 {
1853 /* Convert '/' to '#', convert '..' to '^',
1854 convert ':' to '~' on DOS based file system. */
1855 const char *probe;
1856
1857 #if HAVE_DOS_BASED_FILE_SYSTEM
1858 if (base[0] && base[1] == ':')
1859 {
1860 ptr[0] = base[0];
1861 ptr[1] = '~';
1862 ptr += 2;
1863 base += 2;
1864 }
1865 #endif
1866 for (; *base; base = probe)
1867 {
1868 size_t len;
1869
1870 for (probe = base; *probe; probe++)
1871 if (*probe == '/')
1872 break;
1873 len = probe - base;
1874 if (len == 2 && base[0] == '.' && base[1] == '.')
1875 *ptr++ = '^';
1876 else
1877 {
1878 memcpy (ptr, base, len);
1879 ptr += len;
1880 }
1881 if (*probe)
1882 {
1883 *ptr++ = '#';
1884 probe++;
1885 }
1886 }
1887 }
1888
1889 return ptr;
1890 }
1891
1892 /* Scan through the bb_data for each line in the block, increment
1893 the line number execution count indicated by the execution count of
1894 the appropriate basic block. */
1895
1896 static void
1897 add_line_counts (coverage_t *coverage, function_t *fn)
1898 {
1899 unsigned ix;
1900 line_t *line = NULL; /* This is propagated from one iteration to the
1901 next. */
1902
1903 /* Scan each basic block. */
1904 for (ix = 0; ix != fn->num_blocks; ix++)
1905 {
1906 block_t *block = &fn->blocks[ix];
1907 unsigned *encoding;
1908 const source_t *src = NULL;
1909 unsigned jx;
1910
1911 if (block->count && ix && ix + 1 != fn->num_blocks)
1912 fn->blocks_executed++;
1913 for (jx = 0, encoding = block->u.line.encoding;
1914 jx != block->u.line.num; jx++, encoding++)
1915 if (!*encoding)
1916 {
1917 src = &sources[*++encoding];
1918 jx++;
1919 }
1920 else
1921 {
1922 line = &src->lines[*encoding];
1923
1924 if (coverage)
1925 {
1926 if (!line->exists)
1927 coverage->lines++;
1928 if (!line->count && block->count)
1929 coverage->lines_executed++;
1930 }
1931 line->exists = 1;
1932 if (!block->exceptional)
1933 line->unexceptional = 1;
1934 line->count += block->count;
1935 }
1936 free (block->u.line.encoding);
1937 block->u.cycle.arc = NULL;
1938 block->u.cycle.ident = ~0U;
1939
1940 if (!ix || ix + 1 == fn->num_blocks)
1941 /* Entry or exit block */;
1942 else if (flag_all_blocks)
1943 {
1944 line_t *block_line = line;
1945
1946 if (!block_line)
1947 block_line = &sources[fn->src].lines[fn->line];
1948
1949 block->chain = block_line->u.blocks;
1950 block_line->u.blocks = block;
1951 }
1952 else if (flag_branches)
1953 {
1954 arc_t *arc;
1955
1956 for (arc = block->succ; arc; arc = arc->succ_next)
1957 {
1958 arc->line_next = line->u.branches;
1959 line->u.branches = arc;
1960 if (coverage && !arc->is_unconditional)
1961 add_branch_counts (coverage, arc);
1962 }
1963 }
1964 }
1965 if (!line)
1966 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1967 }
1968
1969 /* Accumulate the line counts of a file. */
1970
1971 static void
1972 accumulate_line_counts (source_t *src)
1973 {
1974 line_t *line;
1975 function_t *fn, *fn_p, *fn_n;
1976 unsigned ix;
1977
1978 /* Reverse the function order. */
1979 for (fn = src->functions, fn_p = NULL; fn;
1980 fn_p = fn, fn = fn_n)
1981 {
1982 fn_n = fn->line_next;
1983 fn->line_next = fn_p;
1984 }
1985 src->functions = fn_p;
1986
1987 for (ix = src->num_lines, line = src->lines; ix--; line++)
1988 {
1989 if (!flag_all_blocks)
1990 {
1991 arc_t *arc, *arc_p, *arc_n;
1992
1993 /* Total and reverse the branch information. */
1994 for (arc = line->u.branches, arc_p = NULL; arc;
1995 arc_p = arc, arc = arc_n)
1996 {
1997 arc_n = arc->line_next;
1998 arc->line_next = arc_p;
1999
2000 add_branch_counts (&src->coverage, arc);
2001 }
2002 line->u.branches = arc_p;
2003 }
2004 else if (line->u.blocks)
2005 {
2006 /* The user expects the line count to be the number of times
2007 a line has been executed. Simply summing the block count
2008 will give an artificially high number. The Right Thing
2009 is to sum the entry counts to the graph of blocks on this
2010 line, then find the elementary cycles of the local graph
2011 and add the transition counts of those cycles. */
2012 block_t *block, *block_p, *block_n;
2013 gcov_type count = 0;
2014
2015 /* Reverse the block information. */
2016 for (block = line->u.blocks, block_p = NULL; block;
2017 block_p = block, block = block_n)
2018 {
2019 block_n = block->chain;
2020 block->chain = block_p;
2021 block->u.cycle.ident = ix;
2022 }
2023 line->u.blocks = block_p;
2024
2025 /* Sum the entry arcs. */
2026 for (block = line->u.blocks; block; block = block->chain)
2027 {
2028 arc_t *arc;
2029
2030 for (arc = block->pred; arc; arc = arc->pred_next)
2031 {
2032 if (arc->src->u.cycle.ident != ix)
2033 count += arc->count;
2034 if (flag_branches)
2035 add_branch_counts (&src->coverage, arc);
2036 }
2037
2038 /* Initialize the cs_count. */
2039 for (arc = block->succ; arc; arc = arc->succ_next)
2040 arc->cs_count = arc->count;
2041 }
2042
2043 /* Find the loops. This uses the algorithm described in
2044 Tiernan 'An Efficient Search Algorithm to Find the
2045 Elementary Circuits of a Graph', CACM Dec 1970. We hold
2046 the P array by having each block point to the arc that
2047 connects to the previous block. The H array is implicitly
2048 held because of the arc ordering, and the block's
2049 previous arc pointer.
2050
2051 Although the algorithm is O(N^3) for highly connected
2052 graphs, at worst we'll have O(N^2), as most blocks have
2053 only one or two exits. Most graphs will be small.
2054
2055 For each loop we find, locate the arc with the smallest
2056 transition count, and add that to the cumulative
2057 count. Decrease flow over the cycle and remove the arc
2058 from consideration. */
2059 for (block = line->u.blocks; block; block = block->chain)
2060 {
2061 block_t *head = block;
2062 arc_t *arc;
2063
2064 next_vertex:;
2065 arc = head->succ;
2066 current_vertex:;
2067 while (arc)
2068 {
2069 block_t *dst = arc->dst;
2070 if (/* Already used that arc. */
2071 arc->cycle
2072 /* Not to same graph, or before first vertex. */
2073 || dst->u.cycle.ident != ix
2074 /* Already in path. */
2075 || dst->u.cycle.arc)
2076 {
2077 arc = arc->succ_next;
2078 continue;
2079 }
2080
2081 if (dst == block)
2082 {
2083 /* Found a closing arc. */
2084 gcov_type cycle_count = arc->cs_count;
2085 arc_t *cycle_arc = arc;
2086 arc_t *probe_arc;
2087
2088 /* Locate the smallest arc count of the loop. */
2089 for (dst = head; (probe_arc = dst->u.cycle.arc);
2090 dst = probe_arc->src)
2091 if (cycle_count > probe_arc->cs_count)
2092 {
2093 cycle_count = probe_arc->cs_count;
2094 cycle_arc = probe_arc;
2095 }
2096
2097 count += cycle_count;
2098 cycle_arc->cycle = 1;
2099
2100 /* Remove the flow from the cycle. */
2101 arc->cs_count -= cycle_count;
2102 for (dst = head; (probe_arc = dst->u.cycle.arc);
2103 dst = probe_arc->src)
2104 probe_arc->cs_count -= cycle_count;
2105
2106 /* Unwind to the cyclic arc. */
2107 while (head != cycle_arc->src)
2108 {
2109 arc = head->u.cycle.arc;
2110 head->u.cycle.arc = NULL;
2111 head = arc->src;
2112 }
2113 /* Move on. */
2114 arc = arc->succ_next;
2115 continue;
2116 }
2117
2118 /* Add new block to chain. */
2119 dst->u.cycle.arc = arc;
2120 head = dst;
2121 goto next_vertex;
2122 }
2123 /* We could not add another vertex to the path. Remove
2124 the last vertex from the list. */
2125 arc = head->u.cycle.arc;
2126 if (arc)
2127 {
2128 /* It was not the first vertex. Move onto next arc. */
2129 head->u.cycle.arc = NULL;
2130 head = arc->src;
2131 arc = arc->succ_next;
2132 goto current_vertex;
2133 }
2134 /* Mark this block as unusable. */
2135 block->u.cycle.ident = ~0U;
2136 }
2137
2138 line->count = count;
2139 }
2140
2141 if (line->exists)
2142 {
2143 src->coverage.lines++;
2144 if (line->count)
2145 src->coverage.lines_executed++;
2146 }
2147 }
2148 }
2149
2150 /* Output information about ARC number IX. Returns nonzero if
2151 anything is output. */
2152
2153 static int
2154 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2155 {
2156 if (arc->is_call_non_return)
2157 {
2158 if (arc->src->count)
2159 {
2160 fnotice (gcov_file, "call %2d returned %s\n", ix,
2161 format_gcov (arc->src->count - arc->count,
2162 arc->src->count, -flag_counts));
2163 }
2164 else
2165 fnotice (gcov_file, "call %2d never executed\n", ix);
2166 }
2167 else if (!arc->is_unconditional)
2168 {
2169 if (arc->src->count)
2170 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2171 format_gcov (arc->count, arc->src->count, -flag_counts),
2172 arc->fall_through ? " (fallthrough)"
2173 : arc->is_throw ? " (throw)" : "");
2174 else
2175 fnotice (gcov_file, "branch %2d never executed\n", ix);
2176 }
2177 else if (flag_unconditional && !arc->dst->is_call_return)
2178 {
2179 if (arc->src->count)
2180 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2181 format_gcov (arc->count, arc->src->count, -flag_counts));
2182 else
2183 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2184 }
2185 else
2186 return 0;
2187 return 1;
2188
2189 }
2190
2191 /* Read in the source file one line at a time, and output that line to
2192 the gcov file preceded by its execution count and other
2193 information. */
2194
2195 static void
2196 output_lines (FILE *gcov_file, const source_t *src)
2197 {
2198 FILE *source_file;
2199 unsigned line_num; /* current line number. */
2200 const line_t *line; /* current line info ptr. */
2201 char string[STRING_SIZE]; /* line buffer. */
2202 char const *retval = ""; /* status of source file reading. */
2203 function_t *fn = NULL;
2204
2205 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2206 if (!multiple_files)
2207 {
2208 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2209 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2210 no_data_file ? "-" : da_file_name);
2211 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
2212 }
2213 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2214
2215 source_file = fopen (src->name, "r");
2216 if (!source_file)
2217 {
2218 fnotice (stderr, "Cannot open source file %s\n", src->name);
2219 retval = NULL;
2220 }
2221 else if (src->file_time == 0)
2222 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2223
2224 if (flag_branches)
2225 fn = src->functions;
2226
2227 for (line_num = 1, line = &src->lines[line_num];
2228 line_num < src->num_lines; line_num++, line++)
2229 {
2230 for (; fn && fn->line == line_num; fn = fn->line_next)
2231 {
2232 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
2233 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
2234
2235 for (; arc; arc = arc->pred_next)
2236 if (arc->fake)
2237 return_count -= arc->count;
2238
2239 fprintf (gcov_file, "function %s", fn->name);
2240 fprintf (gcov_file, " called %s",
2241 format_gcov (fn->blocks[0].count, 0, -1));
2242 fprintf (gcov_file, " returned %s",
2243 format_gcov (return_count, fn->blocks[0].count, 0));
2244 fprintf (gcov_file, " blocks executed %s",
2245 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2246 fprintf (gcov_file, "\n");
2247 }
2248
2249 /* For lines which don't exist in the .bb file, print '-' before
2250 the source line. For lines which exist but were never
2251 executed, print '#####' before the source line. Otherwise,
2252 print the execution count before the source line. There are
2253 16 spaces of indentation added before the source line so that
2254 tabs won't be messed up. */
2255 fprintf (gcov_file, "%9s:%5u:",
2256 !line->exists ? "-" : line->count
2257 ? format_gcov (line->count, 0, -1)
2258 : line->unexceptional ? "#####" : "=====", line_num);
2259
2260 if (retval)
2261 {
2262 /* Copy source line. */
2263 do
2264 {
2265 retval = fgets (string, STRING_SIZE, source_file);
2266 if (!retval)
2267 break;
2268 fputs (retval, gcov_file);
2269 }
2270 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
2271 }
2272 if (!retval)
2273 fputs ("/*EOF*/\n", gcov_file);
2274
2275 if (flag_all_blocks)
2276 {
2277 block_t *block;
2278 arc_t *arc;
2279 int ix, jx;
2280
2281 for (ix = jx = 0, block = line->u.blocks; block;
2282 block = block->chain)
2283 {
2284 if (!block->is_call_return)
2285 fprintf (gcov_file, "%9s:%5u-block %2d\n",
2286 !line->exists ? "-" : block->count
2287 ? format_gcov (block->count, 0, -1)
2288 : block->exceptional ? "%%%%%" : "$$$$$",
2289 line_num, ix++);
2290 if (flag_branches)
2291 for (arc = block->succ; arc; arc = arc->succ_next)
2292 jx += output_branch_count (gcov_file, jx, arc);
2293 }
2294 }
2295 else if (flag_branches)
2296 {
2297 int ix;
2298 arc_t *arc;
2299
2300 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2301 ix += output_branch_count (gcov_file, ix, arc);
2302 }
2303 }
2304
2305 /* Handle all remaining source lines. There may be lines after the
2306 last line of code. */
2307 if (retval)
2308 {
2309 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
2310 {
2311 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
2312
2313 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
2314 {
2315 retval = fgets (string, STRING_SIZE, source_file);
2316 if (!retval)
2317 break;
2318 fputs (retval, gcov_file);
2319 }
2320 }
2321 }
2322
2323 if (source_file)
2324 fclose (source_file);
2325 }