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