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