re PR tree-optimization/55253 (Revision 193298 miscompiles sqlite with -Os)
[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, 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>
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 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. */
64
65 /* This is the size of the buffer used to read in source file lines. */
66
67 struct function_info;
68 struct block_info;
69 struct source_info;
70
71 /* Describes an arc between two basic blocks. */
72
73 typedef struct arc_info
74 {
75 /* source and destination blocks. */
76 struct block_info *src;
77 struct block_info *dst;
78
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;
83
84 unsigned int count_valid : 1;
85 unsigned int on_tree : 1;
86 unsigned int fake : 1;
87 unsigned int fall_through : 1;
88
89 /* Arc to a catch handler. */
90 unsigned int is_throw : 1;
91
92 /* Arc is for a function that abnormally returns. */
93 unsigned int is_call_non_return : 1;
94
95 /* Arc is for catch/setjmp. */
96 unsigned int is_nonlocal_return : 1;
97
98 /* Is an unconditional branch. */
99 unsigned int is_unconditional : 1;
100
101 /* Loop making arc. */
102 unsigned int cycle : 1;
103
104 /* Next branch on line. */
105 struct arc_info *line_next;
106
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;
111
112 /* Describes a basic block. Contains lists of arcs to successor and
113 predecessor blocks. */
114
115 typedef struct block_info
116 {
117 /* Chain of exit and entry arcs. */
118 arc_t *succ;
119 arc_t *pred;
120
121 /* Number of unprocessed exit and entry arcs. */
122 gcov_type num_succ;
123 gcov_type num_pred;
124
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;
132
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. */
136
137 /* Block is a landing pad for longjmp or throw. */
138 unsigned is_nonlocal_return : 1;
139
140 union
141 {
142 struct
143 {
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
152 {
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;
160
161 /* Temporary chain for solving graph, and for chaining blocks on one
162 line. */
163 struct block_info *chain;
164
165 } block_t;
166
167 /* Describes a single function. Contains an array of basic blocks. */
168
169 typedef struct function_info
170 {
171 /* Name of function. */
172 char *name;
173 unsigned ident;
174 unsigned lineno_checksum;
175 unsigned cfg_checksum;
176
177 /* The graph contains at least one fake incoming edge. */
178 unsigned has_catch : 1;
179
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;
187
188 /* Raw arc coverage counts. */
189 gcov_type *counts;
190 unsigned num_counts;
191
192 /* First line number & file. */
193 unsigned line;
194 unsigned src;
195
196 /* Next function in same source file. */
197 struct function_info *line_next;
198
199 /* Next function. */
200 struct function_info *next;
201 } function_t;
202
203 /* Describes coverage of a file or function. */
204
205 typedef struct coverage_info
206 {
207 int lines;
208 int lines_executed;
209
210 int branches;
211 int branches_executed;
212 int branches_taken;
213
214 int calls;
215 int calls_executed;
216
217 char *name;
218 } coverage_t;
219
220 /* Describes a single line of source. Contains a chain of basic blocks
221 with code on it. */
222
223 typedef struct line_info
224 {
225 gcov_type count; /* execution count */
226 union
227 {
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;
237
238 /* Describes a file mentioned in the block graph. Contains an array
239 of line info. */
240
241 typedef struct source_info
242 {
243 /* Canonical name of source file. */
244 char *name;
245 time_t file_time;
246
247 /* Array of line information. */
248 line_t *lines;
249 unsigned num_lines;
250
251 coverage_t coverage;
252
253 /* Functions in this source file. These are in ascending line
254 number order. */
255 function_t *functions;
256 } source_t;
257
258 typedef struct name_map
259 {
260 char *name; /* Source file name */
261 unsigned src; /* Source file */
262 } name_map_t;
263
264 /* Holds a list of function basic block graphs. */
265
266 static function_t *functions;
267 static function_t **fn_end = &functions;
268
269 static source_t *sources; /* Array of source files */
270 static unsigned n_sources; /* Number of sources */
271 static unsigned a_sources; /* Allocated sources */
272
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 */
276
277 /* This holds data summary information. */
278
279 static unsigned object_runs;
280 static unsigned program_count;
281
282 static unsigned total_lines;
283 static unsigned total_executed;
284
285 /* Modification time of graph file. */
286
287 static time_t bbg_file_time;
288
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. */
292
293 static char *bbg_file_name;
294
295 /* Stamp of the bbg file */
296 static unsigned bbg_stamp;
297
298 /* Name and file pointer of the input file for the count data (gcda). */
299
300 static char *da_file_name;
301
302 /* Data file is missing. */
303
304 static int no_data_file;
305
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. */
310
311 static int multiple_files = 0;
312
313 /* Output branch probabilities. */
314
315 static int flag_branches = 0;
316
317 /* Show unconditional branches too. */
318 static int flag_unconditional = 0;
319
320 /* Output a gcov file if this is true. This is on by default, and can
321 be turned off by the -n option. */
322
323 static int flag_gcov_file = 1;
324
325 /* Output progress indication if this is true. This is off by default
326 and can be turned on by the -d option. */
327
328 static int flag_display_progress = 0;
329
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. */
333
334 static int flag_long_names = 0;
335
336 /* Output count information for every basic block, not merely those
337 that contain line number information. */
338
339 static int flag_all_blocks = 0;
340
341 /* Output summary info for each function. */
342
343 static int flag_function_summary = 0;
344
345 /* Object directory file prefix. This is the directory/file where the
346 graph and data files are looked for, if nonzero. */
347
348 static char *object_directory = 0;
349
350 /* Source directory prefix. This is removed from source pathnames
351 that match, when generating the output file name. */
352
353 static char *source_prefix = 0;
354 static size_t source_length = 0;
355
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;
360
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 '^'. */
364
365 static int flag_preserve_paths = 0;
366
367 /* Output the number of times a branch was taken as opposed to the percentage
368 of times it was taken. */
369
370 static int flag_counts = 0;
371
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 **);
400
401 int
402 main (int argc, char **argv)
403 {
404 int argno;
405 int first_arg;
406 const char *p;
407
408 p = argv[0] + strlen (argv[0]);
409 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
410 --p;
411 progname = p;
412
413 xmalloc_set_program_name (progname);
414
415 /* Unlock the stdio streams. */
416 unlock_std_streams ();
417
418 gcc_init_libintl ();
419
420 diagnostic_initialize (global_dc, 0);
421
422 /* Handle response files. */
423 expandargv (&argc, &argv);
424
425 a_names = 10;
426 names = XNEWVEC (name_map_t, a_names);
427 a_sources = 10;
428 sources = XNEWVEC (source_t, a_sources);
429
430 argno = process_args (argc, argv);
431 if (optind == argc)
432 print_usage (true);
433
434 if (argc - argno > 1)
435 multiple_files = 1;
436
437 first_arg = argno;
438
439 for (; argno != argc; argno++)
440 {
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]);
445 }
446
447 generate_results (multiple_files ? NULL : argv[argc - 1]);
448
449 release_structures ();
450
451 return 0;
452 }
453 \f
454 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
455 otherwise the output of --help. */
456
457 static void
458 print_usage (int error_p)
459 {
460 FILE *file = error_p ? stderr : stdout;
461 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
462
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);
484 }
485
486 /* Print version information and exit. */
487
488 static void
489 print_version (void)
490 {
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);
499 }
500
501 static const struct option options[] =
502 {
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 }
519 };
520
521 /* Process args, return index to first non-arg. */
522
523 static int
524 process_args (int argc, char **argv)
525 {
526 int opt;
527
528 while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
529 {
530 switch (opt)
531 {
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. */
578 }
579 }
580
581 return optind;
582 }
583
584 /* Process a single input file. */
585
586 static void
587 process_file (const char *file_name)
588 {
589 function_t *fns;
590
591 create_file_names (file_name);
592 fns = read_graph_file ();
593 if (!fns)
594 return;
595
596 read_count_file (fns);
597 while (fns)
598 {
599 function_t *fn = fns;
600
601 fns = fn->next;
602 fn->next = NULL;
603 if (fn->counts)
604 {
605 unsigned src = fn->src;
606 unsigned line = fn->line;
607 unsigned block_no;
608 function_t *probe, **prev;
609
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;
620
621 /* Mark last line in files touched by function. */
622 for (block_no = 0; block_no != fn->num_blocks; block_no++)
623 {
624 unsigned *enc = fn->blocks[block_no].u.line.encoding;
625 unsigned num = fn->blocks[block_no].u.line.num;
626
627 for (; num--; enc++)
628 if (!*enc)
629 {
630 if (enc[1] != src)
631 {
632 if (line >= sources[src].num_lines)
633 sources[src].num_lines = line + 1;
634 line = 0;
635 src = enc[1];
636 }
637 enc++;
638 num--;
639 }
640 else if (*enc > line)
641 line = *enc;
642 }
643 if (line >= sources[src].num_lines)
644 sources[src].num_lines = line + 1;
645
646 solve_flow_graph (fn);
647 if (fn->has_catch)
648 find_exception_blocks (fn);
649 *fn_end = fn;
650 fn_end = &fn->next;
651 }
652 else
653 /* The function was not in the executable -- some other
654 instance must have been selected. */
655 release_function (fn);
656 }
657 }
658
659 static void
660 generate_results (const char *file_name)
661 {
662 unsigned ix;
663 source_t *src;
664 function_t *fn;
665
666 for (ix = n_sources, src = sources; ix--; src++)
667 if (src->num_lines)
668 src->lines = XCNEWVEC (line_t, src->num_lines);
669
670 for (fn = functions; fn; fn = fn->next)
671 {
672 coverage_t coverage;
673
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)
678 {
679 function_summary (&coverage, "Function");
680 fnotice (stdout, "\n");
681 }
682 }
683
684 if (file_name)
685 {
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);
692 }
693
694 for (ix = n_sources, src = sources; ix--; src++)
695 {
696 if (flag_relative_only)
697 {
698 /* Ignore this source, if it is an absolute path (after
699 source prefix removal). */
700 char first = src->coverage.name[0];
701
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;
708 }
709
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)
715 {
716 char *gcov_file_name
717 = make_gcov_file_name (file_name, src->coverage.name);
718
719 if (src->coverage.lines)
720 {
721 FILE *gcov_file = fopen (gcov_file_name, "w");
722
723 if (gcov_file)
724 {
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);
731 }
732 else
733 fnotice (stderr, "Could not open output file '%s'\n",
734 gcov_file_name);
735 }
736 else
737 {
738 unlink (gcov_file_name);
739 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
740 }
741 free (gcov_file_name);
742 }
743 fnotice (stdout, "\n");
744 }
745
746 if (!file_name)
747 executed_summary (total_lines, total_executed);
748 }
749
750 /* Release a function structure */
751
752 static void
753 release_function (function_t *fn)
754 {
755 unsigned ix;
756 block_t *block;
757
758 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
759 {
760 arc_t *arc, *arc_n;
761
762 for (arc = block->succ; arc; arc = arc_n)
763 {
764 arc_n = arc->succ_next;
765 free (arc);
766 }
767 }
768 free (fn->blocks);
769 free (fn->counts);
770 }
771
772 /* Release all memory used. */
773
774 static void
775 release_structures (void)
776 {
777 unsigned ix;
778 function_t *fn;
779
780 for (ix = n_sources; ix--;)
781 free (sources[ix].lines);
782 free (sources);
783
784 for (ix = n_names; ix--;)
785 free (names[ix].name);
786 free (names);
787
788 while ((fn = functions))
789 {
790 functions = fn->next;
791 release_function (fn);
792 }
793 }
794
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. */
801
802 static void
803 create_file_names (const char *file_name)
804 {
805 char *cptr;
806 char *name;
807 int length = strlen (file_name);
808 int base;
809
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;
816
817 if (object_directory && object_directory[0])
818 {
819 struct stat status;
820
821 length += strlen (object_directory) + 2;
822 name = XNEWVEC (char, length);
823 name[0] = 0;
824
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, "/");
829 }
830 else
831 {
832 name = XNEWVEC (char, length + 1);
833 strcpy (name, file_name);
834 base = 0;
835 }
836
837 if (base)
838 {
839 /* Append source file name. */
840 const char *cptr = lbasename (file_name);
841 strcat (name, cptr ? cptr : file_name);
842 }
843
844 /* Remove the extension. */
845 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
846 if (cptr)
847 *cptr = 0;
848
849 length = strlen (name);
850
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);
854
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);
858
859 free (name);
860 return;
861 }
862
863 /* A is a string and B is a pointer to name_map_t. Compare for file
864 name orderability. */
865
866 static int
867 name_search (const void *a_, const void *b_)
868 {
869 const char *a = (const char *)a_;
870 const name_map_t *b = (const name_map_t *)b_;
871
872 #if HAVE_DOS_BASED_FILE_SYSTEM
873 return strcasecmp (a, b->name);
874 #else
875 return strcmp (a, b->name);
876 #endif
877 }
878
879 /* A and B are a pointer to name_map_t. Compare for file name
880 orderability. */
881
882 static int
883 name_sort (const void *a_, const void *b_)
884 {
885 const name_map_t *a = (const name_map_t *)a_;
886 return name_search (a->name, b_);
887 }
888
889 /* Find or create a source file structure for FILE_NAME. Copies
890 FILE_NAME on creation */
891
892 static unsigned
893 find_source (const char *file_name)
894 {
895 name_map_t *name_map;
896 char *canon;
897 unsigned idx;
898 struct stat status;
899
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)
905 {
906 idx = name_map->src;
907 goto check_date;
908 }
909
910 if (n_names + 2 > a_names)
911 {
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;
919 }
920
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)
926 {
927 /* Not found with canonical name, create a new source. */
928 source_t *src;
929
930 if (n_sources == a_sources)
931 {
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;
937 }
938
939 idx = n_sources;
940
941 name_map = &names[n_names++];
942 name_map->name = canon;
943 name_map->src = idx;
944
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;
961 }
962 else
963 idx = name_map->src;
964
965 if (name_search (file_name, name_map))
966 {
967 /* Append the non-canonical name. */
968 name_map = &names[n_names++];
969 name_map->name = xstrdup (file_name);
970 name_map->src = idx;
971 }
972
973 /* Resort the name map. */
974 qsort (names, n_names, sizeof (*names), name_sort);
975
976 check_date:
977 if (sources[idx].file_time > bbg_file_time)
978 {
979 static int info_emitted;
980
981 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
982 file_name, bbg_file_name);
983 if (!info_emitted)
984 {
985 fnotice (stderr,
986 "(the message is only displayed one per source file)\n");
987 info_emitted = 1;
988 }
989 sources[idx].file_time = 0;
990 }
991
992 return idx;
993 }
994
995 /* Read the notes file. Return list of functions read -- in reverse order. */
996
997 static function_t *
998 read_graph_file (void)
999 {
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;
1008
1009 if (!gcov_open (bbg_file_name, 1))
1010 {
1011 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1012 return fns;
1013 }
1014 bbg_file_time = gcov_time ();
1015 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1016 {
1017 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1018 gcov_close ();
1019 return fns;
1020 }
1021
1022 version = gcov_read_unsigned ();
1023 if (version != GCOV_VERSION)
1024 {
1025 char v[4], e[4];
1026
1027 GCOV_UNSIGNED2STRING (v, version);
1028 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1029
1030 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1031 bbg_file_name, v, e);
1032 }
1033 bbg_stamp = gcov_read_unsigned ();
1034
1035 while ((tag = gcov_read_unsigned ()))
1036 {
1037 unsigned length = gcov_read_unsigned ();
1038 gcov_position_t base = gcov_position ();
1039
1040 if (tag == GCOV_TAG_FUNCTION)
1041 {
1042 char *function_name;
1043 unsigned ident, lineno;
1044 unsigned lineno_checksum, cfg_checksum;
1045
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 ();
1052
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;
1060
1061 fn->line_next = NULL;
1062 fn->next = NULL;
1063 *fns_end = fn;
1064 fns_end = &fn->next;
1065 current_tag = tag;
1066 }
1067 else if (fn && tag == GCOV_TAG_BLOCKS)
1068 {
1069 if (fn->blocks)
1070 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1071 bbg_file_name, fn->name);
1072 else
1073 {
1074 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1075 fn->num_blocks = num_blocks;
1076
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 ();
1080 }
1081 }
1082 else if (fn && tag == GCOV_TAG_ARCS)
1083 {
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;
1089
1090 if (src >= fn->num_blocks || fn->blocks[src].succ)
1091 goto corrupt;
1092
1093 while (num_dests--)
1094 {
1095 unsigned dest = gcov_read_unsigned ();
1096 unsigned flags = gcov_read_unsigned ();
1097
1098 if (dest >= fn->num_blocks)
1099 goto corrupt;
1100 arc = XCNEW (arc_t);
1101
1102 arc->dst = &fn->blocks[dest];
1103 arc->src = src_blk;
1104
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);
1110
1111 arc->succ_next = src_blk->succ;
1112 src_blk->succ = arc;
1113 src_blk->num_succ++;
1114
1115 arc->pred_next = fn->blocks[dest].pred;
1116 fn->blocks[dest].pred = arc;
1117 fn->blocks[dest].num_pred++;
1118
1119 if (arc->fake)
1120 {
1121 if (src)
1122 {
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;
1128 }
1129 else
1130 {
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;
1135 }
1136 }
1137
1138 if (!arc->on_tree)
1139 fn->num_counts++;
1140 }
1141
1142 if (mark_catches)
1143 {
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. */
1147
1148 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1149 if (!arc->fake && !arc->fall_through)
1150 {
1151 arc->is_throw = 1;
1152 fn->has_catch = 1;
1153 }
1154 }
1155 }
1156 else if (fn && tag == GCOV_TAG_LINES)
1157 {
1158 unsigned blockno = gcov_read_unsigned ();
1159 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1160
1161 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1162 goto corrupt;
1163
1164 for (ix = 0; ; )
1165 {
1166 unsigned lineno = gcov_read_unsigned ();
1167
1168 if (lineno)
1169 {
1170 if (!ix)
1171 {
1172 line_nos[ix++] = 0;
1173 line_nos[ix++] = src_idx;
1174 }
1175 line_nos[ix++] = lineno;
1176 }
1177 else
1178 {
1179 const char *file_name = gcov_read_string ();
1180
1181 if (!file_name)
1182 break;
1183 src_idx = find_source (file_name);
1184 line_nos[ix++] = 0;
1185 line_nos[ix++] = src_idx;
1186 }
1187 }
1188
1189 fn->blocks[blockno].u.line.encoding = line_nos;
1190 fn->blocks[blockno].u.line.num = ix;
1191 }
1192 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1193 {
1194 fn = NULL;
1195 current_tag = 0;
1196 }
1197 gcov_sync (base, length);
1198 if (gcov_is_error ())
1199 {
1200 corrupt:;
1201 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1202 break;
1203 }
1204 }
1205 gcov_close ();
1206
1207 if (!fns)
1208 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1209
1210 return fns;
1211 }
1212
1213 /* Reads profiles from the count file and attach to each
1214 function. Return nonzero if fatal error. */
1215
1216 static int
1217 read_count_file (function_t *fns)
1218 {
1219 unsigned ix;
1220 unsigned version;
1221 unsigned tag;
1222 function_t *fn = NULL;
1223 int error = 0;
1224
1225 if (!gcov_open (da_file_name, 1))
1226 {
1227 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1228 da_file_name);
1229 no_data_file = 1;
1230 return 0;
1231 }
1232 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1233 {
1234 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1235 cleanup:;
1236 gcov_close ();
1237 return 1;
1238 }
1239 version = gcov_read_unsigned ();
1240 if (version != GCOV_VERSION)
1241 {
1242 char v[4], e[4];
1243
1244 GCOV_UNSIGNED2STRING (v, version);
1245 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1246
1247 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1248 da_file_name, v, e);
1249 }
1250 tag = gcov_read_unsigned ();
1251 if (tag != bbg_stamp)
1252 {
1253 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1254 goto cleanup;
1255 }
1256
1257 while ((tag = gcov_read_unsigned ()))
1258 {
1259 unsigned length = gcov_read_unsigned ();
1260 unsigned long base = gcov_position ();
1261
1262 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1263 {
1264 struct gcov_summary summary;
1265 gcov_read_summary (&summary);
1266 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1267 program_count++;
1268 }
1269 else if (tag == GCOV_TAG_FUNCTION && !length)
1270 ; /* placeholder */
1271 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1272 {
1273 unsigned ident;
1274 struct function_info *fn_n;
1275
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)
1281 {
1282 if (fn)
1283 ;
1284 else if ((fn = fn_n))
1285 fn_n = NULL;
1286 else
1287 {
1288 fnotice (stderr, "%s:unknown function '%u'\n",
1289 da_file_name, ident);
1290 break;
1291 }
1292 if (fn->ident == ident)
1293 break;
1294 }
1295
1296 if (!fn)
1297 ;
1298 else if (gcov_read_unsigned () != fn->lineno_checksum
1299 || gcov_read_unsigned () != fn->cfg_checksum)
1300 {
1301 mismatch:;
1302 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1303 da_file_name, fn->name);
1304 goto cleanup;
1305 }
1306 }
1307 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1308 {
1309 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1310 goto mismatch;
1311
1312 if (!fn->counts)
1313 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1314
1315 for (ix = 0; ix != fn->num_counts; ix++)
1316 fn->counts[ix] += gcov_read_counter ();
1317 }
1318 gcov_sync (base, length);
1319 if ((error = gcov_is_error ()))
1320 {
1321 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1322 da_file_name);
1323 goto cleanup;
1324 }
1325 }
1326
1327 gcov_close ();
1328 return 0;
1329 }
1330
1331 /* Solve the flow graph. Propagate counts from the instrumented arcs
1332 to the blocks and the uninstrumented arcs. */
1333
1334 static void
1335 solve_flow_graph (function_t *fn)
1336 {
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. */
1343
1344 /* The arcs were built in reverse order. Fix that now. */
1345 for (ix = fn->num_blocks; ix--;)
1346 {
1347 arc_t *arc_p, *arc_n;
1348
1349 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1350 arc_p = arc, arc = arc_n)
1351 {
1352 arc_n = arc->succ_next;
1353 arc->succ_next = arc_p;
1354 }
1355 fn->blocks[ix].succ = arc_p;
1356
1357 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1358 arc_p = arc, arc = arc_n)
1359 {
1360 arc_n = arc->pred_next;
1361 arc->pred_next = arc_p;
1362 }
1363 fn->blocks[ix].pred = arc_p;
1364 }
1365
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
1370 {
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;
1378
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;
1386 }
1387
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++)
1391 {
1392 block_t const *prev_dst = NULL;
1393 int out_of_order = 0;
1394 int non_fake_succ = 0;
1395
1396 for (arc = blk->succ; arc; arc = arc->succ_next)
1397 {
1398 if (!arc->fake)
1399 non_fake_succ++;
1400
1401 if (!arc->on_tree)
1402 {
1403 if (count_ptr)
1404 arc->count = *count_ptr++;
1405 arc->count_valid = 1;
1406 blk->num_succ--;
1407 arc->dst->num_pred--;
1408 }
1409 if (prev_dst && prev_dst > arc->dst)
1410 out_of_order = 1;
1411 prev_dst = arc->dst;
1412 }
1413 if (non_fake_succ == 1)
1414 {
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)
1419 {
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;
1430 }
1431 }
1432
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)
1438 {
1439 arc_t *start = blk->succ;
1440 unsigned changes = 1;
1441
1442 while (changes)
1443 {
1444 arc_t *arc, *arc_p, *arc_n;
1445
1446 changes = 0;
1447 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1448 {
1449 if (arc->dst > arc_n->dst)
1450 {
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;
1459 }
1460 else
1461 {
1462 arc_p = arc;
1463 arc = arc_n;
1464 }
1465 }
1466 }
1467 blk->succ = start;
1468 }
1469
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;
1475 }
1476
1477 while (invalid_blocks || valid_blocks)
1478 {
1479 while ((blk = invalid_blocks))
1480 {
1481 gcov_type total = 0;
1482 const arc_t *arc;
1483
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;
1494
1495 blk->count = total;
1496 blk->count_valid = 1;
1497 blk->chain = valid_blocks;
1498 blk->valid_chain = 1;
1499 valid_blocks = blk;
1500 }
1501 while ((blk = valid_blocks))
1502 {
1503 gcov_type total;
1504 arc_t *arc, *inv_arc;
1505
1506 valid_blocks = blk->chain;
1507 blk->valid_chain = 0;
1508 if (blk->num_succ == 1)
1509 {
1510 block_t *dst;
1511
1512 total = blk->count;
1513 inv_arc = NULL;
1514 for (arc = blk->succ; arc; arc = arc->succ_next)
1515 {
1516 total -= arc->count;
1517 if (!arc->count_valid)
1518 inv_arc = arc;
1519 }
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)
1526 {
1527 if (dst->num_pred == 1 && !dst->valid_chain)
1528 {
1529 dst->chain = valid_blocks;
1530 dst->valid_chain = 1;
1531 valid_blocks = dst;
1532 }
1533 }
1534 else
1535 {
1536 if (!dst->num_pred && !dst->invalid_chain)
1537 {
1538 dst->chain = invalid_blocks;
1539 dst->invalid_chain = 1;
1540 invalid_blocks = dst;
1541 }
1542 }
1543 }
1544 if (blk->num_pred == 1)
1545 {
1546 block_t *src;
1547
1548 total = blk->count;
1549 inv_arc = NULL;
1550 for (arc = blk->pred; arc; arc = arc->pred_next)
1551 {
1552 total -= arc->count;
1553 if (!arc->count_valid)
1554 inv_arc = arc;
1555 }
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)
1562 {
1563 if (src->num_succ == 1 && !src->valid_chain)
1564 {
1565 src->chain = valid_blocks;
1566 src->valid_chain = 1;
1567 valid_blocks = src;
1568 }
1569 }
1570 else
1571 {
1572 if (!src->num_succ && !src->invalid_chain)
1573 {
1574 src->chain = invalid_blocks;
1575 src->invalid_chain = 1;
1576 invalid_blocks = src;
1577 }
1578 }
1579 }
1580 }
1581 }
1582
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)
1587 {
1588 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1589 bbg_file_name, fn->name);
1590 break;
1591 }
1592 }
1593
1594 /* Mark all the blocks only reachable via an incoming catch. */
1595
1596 static void
1597 find_exception_blocks (function_t *fn)
1598 {
1599 unsigned ix;
1600 block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1601
1602 /* First mark all blocks as exceptional. */
1603 for (ix = fn->num_blocks; ix--;)
1604 fn->blocks[ix].exceptional = 1;
1605
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;)
1610 {
1611 block_t *block = queue[--ix];
1612 const arc_t *arc;
1613
1614 for (arc = block->succ; arc; arc = arc->succ_next)
1615 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1616 {
1617 arc->dst->exceptional = 0;
1618 queue[ix++] = arc->dst;
1619 }
1620 }
1621 }
1622 \f
1623
1624 /* Increment totals in COVERAGE according to arc ARC. */
1625
1626 static void
1627 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1628 {
1629 if (arc->is_call_non_return)
1630 {
1631 coverage->calls++;
1632 if (arc->src->count)
1633 coverage->calls_executed++;
1634 }
1635 else if (!arc->is_unconditional)
1636 {
1637 coverage->branches++;
1638 if (arc->src->count)
1639 coverage->branches_executed++;
1640 if (arc->count)
1641 coverage->branches_taken++;
1642 }
1643 }
1644
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. */
1650
1651 static char const *
1652 format_gcov (gcov_type top, gcov_type bottom, int dp)
1653 {
1654 static char buffer[20];
1655
1656 if (dp >= 0)
1657 {
1658 float ratio = bottom ? (float)top / bottom : 0;
1659 int ix;
1660 unsigned limit = 100;
1661 unsigned percent;
1662
1663 for (ix = dp; ix--; )
1664 limit *= 10;
1665
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)
1673 {
1674 dp++;
1675 do
1676 {
1677 buffer[ix+1] = buffer[ix];
1678 ix--;
1679 }
1680 while (dp--);
1681 buffer[ix + 1] = '.';
1682 }
1683 }
1684 else
1685 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1686
1687 return buffer;
1688 }
1689
1690 /* Summary of execution */
1691
1692 static void
1693 executed_summary (unsigned lines, unsigned executed)
1694 {
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");
1700 }
1701
1702 /* Output summary info for a function or file. */
1703
1704 static void
1705 function_summary (const coverage_t *coverage, const char *title)
1706 {
1707 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1708 executed_summary (coverage->lines, coverage->lines_executed);
1709
1710 if (flag_branches)
1711 {
1712 if (coverage->branches)
1713 {
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);
1722 }
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");
1731 }
1732 }
1733
1734 /* Canonicalize the filename NAME by canonicalizing directory
1735 separators, eliding . components and resolving .. components
1736 appropriately. Always returns a unique string. */
1737
1738 static char *
1739 canonicalize_name (const char *name)
1740 {
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;
1747
1748 #if HAVE_DOS_BASED_FILE_SYSTEM
1749 if (base[0] && base[1] == ':')
1750 {
1751 result[0] = base[0];
1752 result[1] = ':';
1753 base += 2;
1754 ptr += 2;
1755 }
1756 #endif
1757 for (dd_base = ptr; *base; base = probe)
1758 {
1759 size_t len;
1760
1761 for (probe = base; *probe; probe++)
1762 if (IS_DIR_SEPARATOR (*probe))
1763 break;
1764
1765 len = probe - base;
1766 if (len == 1 && base[0] == '.')
1767 /* Elide a '.' directory */
1768 ;
1769 else if (len == 2 && base[0] == '.' && base[1] == '.')
1770 {
1771 /* '..', we can only elide it and the previous directory, if
1772 we're not a symlink. */
1773 struct stat ATTRIBUTE_UNUSED buf;
1774
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
1781 )
1782 {
1783 /* Cannot elide, or unreadable or a symlink. */
1784 dd_base = ptr + 2 + slash;
1785 goto regular;
1786 }
1787 while (ptr != dd_base && *ptr != '/')
1788 ptr--;
1789 slash = ptr != result;
1790 }
1791 else
1792 {
1793 regular:
1794 /* Regular pathname component. */
1795 if (slash)
1796 *ptr++ = '/';
1797 memcpy (ptr, base, len);
1798 ptr += len;
1799 slash = 1;
1800 }
1801
1802 for (; IS_DIR_SEPARATOR (*probe); probe++)
1803 continue;
1804 }
1805 *ptr = 0;
1806
1807 return result;
1808 }
1809
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.) */
1821
1822 static char *
1823 make_gcov_file_name (const char *input_name, const char *src_name)
1824 {
1825 char *ptr;
1826 char *result;
1827
1828 if (flag_long_names && input_name && strcmp (src_name, input_name))
1829 {
1830 /* Generate the input filename part. */
1831 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1832
1833 ptr = result;
1834 ptr = mangle_name (input_name, ptr);
1835 ptr[0] = ptr[1] = '#';
1836 ptr += 2;
1837 }
1838 else
1839 {
1840 result = XNEWVEC (char, strlen (src_name) + 10);
1841 ptr = result;
1842 }
1843
1844 ptr = mangle_name (src_name, ptr);
1845 strcpy (ptr, ".gcov");
1846
1847 return result;
1848 }
1849
1850 static char *
1851 mangle_name (char const *base, char *ptr)
1852 {
1853 size_t len;
1854
1855 /* Generate the source filename part. */
1856 if (!flag_preserve_paths)
1857 {
1858 base = lbasename (base);
1859 len = strlen (base);
1860 memcpy (ptr, base, len);
1861 ptr += len;
1862 }
1863 else
1864 {
1865 /* Convert '/' to '#', convert '..' to '^',
1866 convert ':' to '~' on DOS based file system. */
1867 const char *probe;
1868
1869 #if HAVE_DOS_BASED_FILE_SYSTEM
1870 if (base[0] && base[1] == ':')
1871 {
1872 ptr[0] = base[0];
1873 ptr[1] = '~';
1874 ptr += 2;
1875 base += 2;
1876 }
1877 #endif
1878 for (; *base; base = probe)
1879 {
1880 size_t len;
1881
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
1889 {
1890 memcpy (ptr, base, len);
1891 ptr += len;
1892 }
1893 if (*probe)
1894 {
1895 *ptr++ = '#';
1896 probe++;
1897 }
1898 }
1899 }
1900
1901 return ptr;
1902 }
1903
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. */
1907
1908 static void
1909 add_line_counts (coverage_t *coverage, function_t *fn)
1910 {
1911 unsigned ix;
1912 line_t *line = NULL; /* This is propagated from one iteration to the
1913 next. */
1914
1915 /* Scan each basic block. */
1916 for (ix = 0; ix != fn->num_blocks; ix++)
1917 {
1918 block_t *block = &fn->blocks[ix];
1919 unsigned *encoding;
1920 const source_t *src = NULL;
1921 unsigned jx;
1922
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)
1928 {
1929 src = &sources[*++encoding];
1930 jx++;
1931 }
1932 else
1933 {
1934 line = &src->lines[*encoding];
1935
1936 if (coverage)
1937 {
1938 if (!line->exists)
1939 coverage->lines++;
1940 if (!line->count && block->count)
1941 coverage->lines_executed++;
1942 }
1943 line->exists = 1;
1944 if (!block->exceptional)
1945 line->unexceptional = 1;
1946 line->count += block->count;
1947 }
1948 free (block->u.line.encoding);
1949 block->u.cycle.arc = NULL;
1950 block->u.cycle.ident = ~0U;
1951
1952 if (!ix || ix + 1 == fn->num_blocks)
1953 /* Entry or exit block */;
1954 else if (flag_all_blocks)
1955 {
1956 line_t *block_line = line;
1957
1958 if (!block_line)
1959 block_line = &sources[fn->src].lines[fn->line];
1960
1961 block->chain = block_line->u.blocks;
1962 block_line->u.blocks = block;
1963 }
1964 else if (flag_branches)
1965 {
1966 arc_t *arc;
1967
1968 for (arc = block->succ; arc; arc = arc->succ_next)
1969 {
1970 arc->line_next = line->u.branches;
1971 line->u.branches = arc;
1972 if (coverage && !arc->is_unconditional)
1973 add_branch_counts (coverage, arc);
1974 }
1975 }
1976 }
1977 if (!line)
1978 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1979 }
1980
1981 /* Accumulate the line counts of a file. */
1982
1983 static void
1984 accumulate_line_counts (source_t *src)
1985 {
1986 line_t *line;
1987 function_t *fn, *fn_p, *fn_n;
1988 unsigned ix;
1989
1990 /* Reverse the function order. */
1991 for (fn = src->functions, fn_p = NULL; fn;
1992 fn_p = fn, fn = fn_n)
1993 {
1994 fn_n = fn->line_next;
1995 fn->line_next = fn_p;
1996 }
1997 src->functions = fn_p;
1998
1999 for (ix = src->num_lines, line = src->lines; ix--; line++)
2000 {
2001 if (!flag_all_blocks)
2002 {
2003 arc_t *arc, *arc_p, *arc_n;
2004
2005 /* Total and reverse the branch information. */
2006 for (arc = line->u.branches, arc_p = NULL; arc;
2007 arc_p = arc, arc = arc_n)
2008 {
2009 arc_n = arc->line_next;
2010 arc->line_next = arc_p;
2011
2012 add_branch_counts (&src->coverage, arc);
2013 }
2014 line->u.branches = arc_p;
2015 }
2016 else if (line->u.blocks)
2017 {
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;
2026
2027 /* Reverse the block information. */
2028 for (block = line->u.blocks, block_p = NULL; block;
2029 block_p = block, block = block_n)
2030 {
2031 block_n = block->chain;
2032 block->chain = block_p;
2033 block->u.cycle.ident = ix;
2034 }
2035 line->u.blocks = block_p;
2036
2037 /* Sum the entry arcs. */
2038 for (block = line->u.blocks; block; block = block->chain)
2039 {
2040 arc_t *arc;
2041
2042 for (arc = block->pred; arc; arc = arc->pred_next)
2043 {
2044 if (arc->src->u.cycle.ident != ix)
2045 count += arc->count;
2046 if (flag_branches)
2047 add_branch_counts (&src->coverage, arc);
2048 }
2049
2050 /* Initialize the cs_count. */
2051 for (arc = block->succ; arc; arc = arc->succ_next)
2052 arc->cs_count = arc->count;
2053 }
2054
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.
2062
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.
2066
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)
2072 {
2073 block_t *head = block;
2074 arc_t *arc;
2075
2076 next_vertex:;
2077 arc = head->succ;
2078 current_vertex:;
2079 while (arc)
2080 {
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)
2088 {
2089 arc = arc->succ_next;
2090 continue;
2091 }
2092
2093 if (dst == block)
2094 {
2095 /* Found a closing arc. */
2096 gcov_type cycle_count = arc->cs_count;
2097 arc_t *cycle_arc = arc;
2098 arc_t *probe_arc;
2099
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)
2104 {
2105 cycle_count = probe_arc->cs_count;
2106 cycle_arc = probe_arc;
2107 }
2108
2109 count += cycle_count;
2110 cycle_arc->cycle = 1;
2111
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;
2117
2118 /* Unwind to the cyclic arc. */
2119 while (head != cycle_arc->src)
2120 {
2121 arc = head->u.cycle.arc;
2122 head->u.cycle.arc = NULL;
2123 head = arc->src;
2124 }
2125 /* Move on. */
2126 arc = arc->succ_next;
2127 continue;
2128 }
2129
2130 /* Add new block to chain. */
2131 dst->u.cycle.arc = arc;
2132 head = dst;
2133 goto next_vertex;
2134 }
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)
2139 {
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;
2145 }
2146 /* Mark this block as unusable. */
2147 block->u.cycle.ident = ~0U;
2148 }
2149
2150 line->count = count;
2151 }
2152
2153 if (line->exists)
2154 {
2155 src->coverage.lines++;
2156 if (line->count)
2157 src->coverage.lines_executed++;
2158 }
2159 }
2160 }
2161
2162 /* Output information about ARC number IX. Returns nonzero if
2163 anything is output. */
2164
2165 static int
2166 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2167 {
2168 if (arc->is_call_non_return)
2169 {
2170 if (arc->src->count)
2171 {
2172 fnotice (gcov_file, "call %2d returned %s\n", ix,
2173 format_gcov (arc->src->count - arc->count,
2174 arc->src->count, -flag_counts));
2175 }
2176 else
2177 fnotice (gcov_file, "call %2d never executed\n", ix);
2178 }
2179 else if (!arc->is_unconditional)
2180 {
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);
2188 }
2189 else if (flag_unconditional && !arc->dst->is_call_return)
2190 {
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);
2196 }
2197 else
2198 return 0;
2199 return 1;
2200
2201 }
2202
2203 static const char *
2204 read_line (FILE *file)
2205 {
2206 static char *string;
2207 static size_t string_len;
2208 size_t pos = 0;
2209 char *ptr;
2210
2211 if (!string_len)
2212 {
2213 string_len = 200;
2214 string = XNEWVEC (char, string_len);
2215 }
2216
2217 while ((ptr = fgets (string + pos, string_len - pos, file)))
2218 {
2219 size_t len = strlen (string + pos);
2220
2221 if (string[pos + len - 1] == '\n')
2222 {
2223 string[pos + len - 1] = 0;
2224 return string;
2225 }
2226 pos += len;
2227 string = XRESIZEVEC (char, string, string_len * 2);
2228 string_len *= 2;
2229 }
2230
2231 return pos ? string : NULL;
2232 }
2233
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. */
2237
2238 static void
2239 output_lines (FILE *gcov_file, const source_t *src)
2240 {
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;
2246
2247 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2248 if (!multiple_files)
2249 {
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);
2254 }
2255 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2256
2257 source_file = fopen (src->name, "r");
2258 if (!source_file)
2259 {
2260 fnotice (stderr, "Cannot open source file %s\n", src->name);
2261 retval = NULL;
2262 }
2263 else if (src->file_time == 0)
2264 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2265
2266 if (flag_branches)
2267 fn = src->functions;
2268
2269 for (line_num = 1, line = &src->lines[line_num];
2270 line_num < src->num_lines; line_num++, line++)
2271 {
2272 for (; fn && fn->line == line_num; fn = fn->line_next)
2273 {
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;
2277
2278 for (; arc; arc = arc->pred_next)
2279 if (arc->fake)
2280 return_count -= arc->count;
2281
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");
2290 }
2291
2292 if (retval)
2293 retval = read_line (source_file);
2294
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*/");
2306
2307 if (flag_all_blocks)
2308 {
2309 block_t *block;
2310 arc_t *arc;
2311 int ix, jx;
2312
2313 for (ix = jx = 0, block = line->u.blocks; block;
2314 block = block->chain)
2315 {
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);
2325 }
2326 }
2327 else if (flag_branches)
2328 {
2329 int ix;
2330 arc_t *arc;
2331
2332 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2333 ix += output_branch_count (gcov_file, ix, arc);
2334 }
2335 }
2336
2337 /* Handle all remaining source lines. There may be lines after the
2338 last line of code. */
2339 if (retval)
2340 {
2341 for (; (retval = read_line (source_file)); line_num++)
2342 fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
2343 }
2344
2345 if (source_file)
2346 fclose (source_file);
2347 }