PR c++/80176
[official-gcc.git] / gcc / gcov.c
blobbb26a1a9787f266f5efa59a979185d88df40203e
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990-2017 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>
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.
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.
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/>. */
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. */
27 /* ??? Should have an option to print the number of basic blocks, and the
28 percent of them that are covered. */
30 /* Need an option to show individual block counts, and show
31 probabilities of fall through arcs. */
33 #include "config.h"
34 #define INCLUDE_ALGORITHM
35 #define INCLUDE_VECTOR
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 #include "demangle.h"
44 #include <getopt.h>
46 #include "md5.h"
48 using namespace std;
50 #define IN_GCOV 1
51 #include "gcov-io.h"
52 #include "gcov-io.c"
54 /* The gcno file is generated by -ftest-coverage option. The gcda file is
55 generated by a program compiled with -fprofile-arcs. Their formats
56 are documented in gcov-io.h. */
58 /* The functions in this file for creating and solution program flow graphs
59 are very similar to functions in the gcc source file profile.c. In
60 some places we make use of the knowledge of how profile.c works to
61 select particular algorithms here. */
63 /* The code validates that the profile information read in corresponds
64 to the code currently being compiled. Rather than checking for
65 identical files, the code below compares a checksum on the CFG
66 (based on the order of basic blocks and the arcs in the CFG). If
67 the CFG checksum in the gcda file match the CFG checksum in the
68 gcno file, the profile data will be used. */
70 /* This is the size of the buffer used to read in source file lines. */
72 struct function_info;
73 struct block_info;
74 struct source_info;
76 /* Describes an arc between two basic blocks. */
78 typedef struct arc_info
80 /* source and destination blocks. */
81 struct block_info *src;
82 struct block_info *dst;
84 /* transition counts. */
85 gcov_type count;
86 /* used in cycle search, so that we do not clobber original counts. */
87 gcov_type cs_count;
89 unsigned int count_valid : 1;
90 unsigned int on_tree : 1;
91 unsigned int fake : 1;
92 unsigned int fall_through : 1;
94 /* Arc to a catch handler. */
95 unsigned int is_throw : 1;
97 /* Arc is for a function that abnormally returns. */
98 unsigned int is_call_non_return : 1;
100 /* Arc is for catch/setjmp. */
101 unsigned int is_nonlocal_return : 1;
103 /* Is an unconditional branch. */
104 unsigned int is_unconditional : 1;
106 /* Loop making arc. */
107 unsigned int cycle : 1;
109 /* Next branch on line. */
110 struct arc_info *line_next;
112 /* Links to next arc on src and dst lists. */
113 struct arc_info *succ_next;
114 struct arc_info *pred_next;
115 } arc_t;
117 /* Describes a basic block. Contains lists of arcs to successor and
118 predecessor blocks. */
120 typedef struct block_info
122 /* Chain of exit and entry arcs. */
123 arc_t *succ;
124 arc_t *pred;
126 /* Number of unprocessed exit and entry arcs. */
127 gcov_type num_succ;
128 gcov_type num_pred;
130 /* Block execution count. */
131 gcov_type count;
132 unsigned flags : 12;
133 unsigned count_valid : 1;
134 unsigned valid_chain : 1;
135 unsigned invalid_chain : 1;
136 unsigned exceptional : 1;
138 /* Block is a call instrumenting site. */
139 unsigned is_call_site : 1; /* Does the call. */
140 unsigned is_call_return : 1; /* Is the return. */
142 /* Block is a landing pad for longjmp or throw. */
143 unsigned is_nonlocal_return : 1;
145 union
147 struct
149 /* Array of line numbers and source files. source files are
150 introduced by a linenumber of zero, the next 'line number' is
151 the number of the source file. Always starts with a source
152 file. */
153 unsigned *encoding;
154 unsigned num;
155 } line; /* Valid until blocks are linked onto lines */
156 struct
158 /* Single line graph cycle workspace. Used for all-blocks
159 mode. */
160 arc_t *arc;
161 unsigned ident;
162 } cycle; /* Used in all-blocks mode, after blocks are linked onto
163 lines. */
164 } u;
166 /* Temporary chain for solving graph, and for chaining blocks on one
167 line. */
168 struct block_info *chain;
170 } block_t;
172 /* Describes a single function. Contains an array of basic blocks. */
174 typedef struct function_info
176 /* Name of function. */
177 char *name;
178 char *demangled_name;
179 unsigned ident;
180 unsigned lineno_checksum;
181 unsigned cfg_checksum;
183 /* The graph contains at least one fake incoming edge. */
184 unsigned has_catch : 1;
186 /* Array of basic blocks. Like in GCC, the entry block is
187 at blocks[0] and the exit block is at blocks[1]. */
188 #define ENTRY_BLOCK (0)
189 #define EXIT_BLOCK (1)
190 block_t *blocks;
191 unsigned num_blocks;
192 unsigned blocks_executed;
194 /* Raw arc coverage counts. */
195 gcov_type *counts;
196 unsigned num_counts;
198 /* First line number & file. */
199 unsigned line;
200 unsigned src;
202 /* Next function in same source file. */
203 struct function_info *next_file_fn;
205 /* Next function. */
206 struct function_info *next;
207 } function_t;
209 /* Describes coverage of a file or function. */
211 typedef struct coverage_info
213 int lines;
214 int lines_executed;
216 int branches;
217 int branches_executed;
218 int branches_taken;
220 int calls;
221 int calls_executed;
223 char *name;
224 } coverage_t;
226 /* Describes a single line of source. Contains a chain of basic blocks
227 with code on it. */
229 typedef struct line_info
231 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
232 bool has_block (block_t *needle);
234 gcov_type count; /* execution count */
235 union
237 arc_t *branches; /* branches from blocks that end on this
238 line. Used for branch-counts when not
239 all-blocks mode. */
240 block_t *blocks; /* blocks which start on this line. Used
241 in all-blocks mode. */
242 } u;
243 unsigned exists : 1;
244 unsigned unexceptional : 1;
245 } line_t;
247 bool
248 line_t::has_block (block_t *needle)
250 for (block_t *n = u.blocks; n; n = n->chain)
251 if (n == needle)
252 return true;
254 return false;
257 /* Describes a file mentioned in the block graph. Contains an array
258 of line info. */
260 typedef struct source_info
262 /* Canonical name of source file. */
263 char *name;
264 time_t file_time;
266 /* Array of line information. */
267 line_t *lines;
268 unsigned num_lines;
270 coverage_t coverage;
272 /* Functions in this source file. These are in ascending line
273 number order. */
274 function_t *functions;
275 } source_t;
277 typedef struct name_map
279 char *name; /* Source file name */
280 unsigned src; /* Source file */
281 } name_map_t;
283 /* Holds a list of function basic block graphs. */
285 static function_t *functions;
286 static function_t **fn_end = &functions;
288 static source_t *sources; /* Array of source files */
289 static unsigned n_sources; /* Number of sources */
290 static unsigned a_sources; /* Allocated sources */
292 static name_map_t *names; /* Mapping of file names to sources */
293 static unsigned n_names; /* Number of names */
294 static unsigned a_names; /* Allocated names */
296 /* This holds data summary information. */
298 static unsigned object_runs;
299 static unsigned program_count;
301 static unsigned total_lines;
302 static unsigned total_executed;
304 /* Modification time of graph file. */
306 static time_t bbg_file_time;
308 /* Name of the notes (gcno) output file. The "bbg" prefix is for
309 historical reasons, when the notes file contained only the
310 basic block graph notes. */
312 static char *bbg_file_name;
314 /* Stamp of the bbg file */
315 static unsigned bbg_stamp;
317 /* Name and file pointer of the input file for the count data (gcda). */
319 static char *da_file_name;
321 /* Data file is missing. */
323 static int no_data_file;
325 /* If there is several input files, compute and display results after
326 reading all data files. This way if two or more gcda file refer to
327 the same source file (eg inline subprograms in a .h file), the
328 counts are added. */
330 static int multiple_files = 0;
332 /* Output branch probabilities. */
334 static int flag_branches = 0;
336 /* Show unconditional branches too. */
337 static int flag_unconditional = 0;
339 /* Output a gcov file if this is true. This is on by default, and can
340 be turned off by the -n option. */
342 static int flag_gcov_file = 1;
344 /* Output progress indication if this is true. This is off by default
345 and can be turned on by the -d option. */
347 static int flag_display_progress = 0;
349 /* Output *.gcov file in intermediate format used by 'lcov'. */
351 static int flag_intermediate_format = 0;
353 /* Output demangled function names. */
355 static int flag_demangled_names = 0;
357 /* For included files, make the gcov output file name include the name
358 of the input source file. For example, if x.h is included in a.c,
359 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
361 static int flag_long_names = 0;
363 /* For situations when a long name can potentially hit filesystem path limit,
364 let's calculate md5sum of the path and append it to a file name. */
366 static int flag_hash_filenames = 0;
368 /* Output count information for every basic block, not merely those
369 that contain line number information. */
371 static int flag_all_blocks = 0;
373 /* Output summary info for each function. */
375 static int flag_function_summary = 0;
377 /* Object directory file prefix. This is the directory/file where the
378 graph and data files are looked for, if nonzero. */
380 static char *object_directory = 0;
382 /* Source directory prefix. This is removed from source pathnames
383 that match, when generating the output file name. */
385 static char *source_prefix = 0;
386 static size_t source_length = 0;
388 /* Only show data for sources with relative pathnames. Absolute ones
389 usually indicate a system header file, which although it may
390 contain inline functions, is usually uninteresting. */
391 static int flag_relative_only = 0;
393 /* Preserve all pathname components. Needed when object files and
394 source files are in subdirectories. '/' is mangled as '#', '.' is
395 elided and '..' mangled to '^'. */
397 static int flag_preserve_paths = 0;
399 /* Output the number of times a branch was taken as opposed to the percentage
400 of times it was taken. */
402 static int flag_counts = 0;
404 /* Forward declarations. */
405 static int process_args (int, char **);
406 static void print_usage (int) ATTRIBUTE_NORETURN;
407 static void print_version (void) ATTRIBUTE_NORETURN;
408 static void process_file (const char *);
409 static void generate_results (const char *);
410 static void create_file_names (const char *);
411 static int name_search (const void *, const void *);
412 static int name_sort (const void *, const void *);
413 static char *canonicalize_name (const char *);
414 static unsigned find_source (const char *);
415 static function_t *read_graph_file (void);
416 static int read_count_file (function_t *);
417 static void solve_flow_graph (function_t *);
418 static void find_exception_blocks (function_t *);
419 static void add_branch_counts (coverage_t *, const arc_t *);
420 static void add_line_counts (coverage_t *, function_t *);
421 static void executed_summary (unsigned, unsigned);
422 static void function_summary (const coverage_t *, const char *);
423 static const char *format_gcov (gcov_type, gcov_type, int);
424 static void accumulate_line_counts (source_t *);
425 static void output_gcov_file (const char *, source_t *);
426 static int output_branch_count (FILE *, int, const arc_t *);
427 static void output_lines (FILE *, const source_t *);
428 static char *make_gcov_file_name (const char *, const char *);
429 static char *mangle_name (const char *, char *);
430 static void release_structures (void);
431 static void release_function (function_t *);
432 extern int main (int, char **);
434 /* Cycle detection!
435 There are a bajillion algorithms that do this. Boost's function is named
436 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
437 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
438 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
440 The basic algorithm is simple: effectively, we're finding all simple paths
441 in a subgraph (that shrinks every iteration). Duplicates are filtered by
442 "blocking" a path when a node is added to the path (this also prevents non-
443 simple paths)--the node is unblocked only when it participates in a cycle.
446 typedef vector<arc_t *> arc_vector_t;
447 typedef vector<const block_t *> block_vector_t;
449 /* Enum with types of loop in CFG. */
451 enum loop_type
453 NO_LOOP = 0,
454 LOOP = 1,
455 NEGATIVE_LOOP = 3
458 /* Loop_type operator that merges two values: A and B. */
460 inline loop_type& operator |= (loop_type& a, loop_type b)
462 return a = static_cast<loop_type> (a | b);
465 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
466 and subtract the value from all counts. The subtracted value is added
467 to COUNT. Returns type of loop. */
469 static loop_type
470 handle_cycle (const arc_vector_t &edges, int64_t &count)
472 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
473 that amount. */
474 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
475 for (unsigned i = 0; i < edges.size (); i++)
477 int64_t ecount = edges[i]->cs_count;
478 if (cycle_count > ecount)
479 cycle_count = ecount;
481 count += cycle_count;
482 for (unsigned i = 0; i < edges.size (); i++)
483 edges[i]->cs_count -= cycle_count;
485 return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
488 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
489 blocked by U in BLOCK_LISTS. */
491 static void
492 unblock (const block_t *u, block_vector_t &blocked,
493 vector<block_vector_t > &block_lists)
495 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
496 if (it == blocked.end ())
497 return;
499 unsigned index = it - blocked.begin ();
500 blocked.erase (it);
502 for (block_vector_t::iterator it2 = block_lists[index].begin ();
503 it2 != block_lists[index].end (); it2++)
504 unblock (*it2, blocked, block_lists);
505 for (unsigned j = 0; j < block_lists[index].size (); j++)
506 unblock (u, blocked, block_lists);
508 block_lists.erase (block_lists.begin () + index);
511 /* Find circuit going to block V, PATH is provisional seen cycle.
512 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
513 blocked by a block. COUNT is accumulated count of the current LINE.
514 Returns what type of loop it contains. */
516 static loop_type
517 circuit (block_t *v, arc_vector_t &path, block_t *start,
518 block_vector_t &blocked, vector<block_vector_t> &block_lists,
519 line_t &linfo, int64_t &count)
521 loop_type result = NO_LOOP;
523 /* Add v to the block list. */
524 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
525 blocked.push_back (v);
526 block_lists.push_back (block_vector_t ());
528 for (arc_t *arc = v->succ; arc; arc = arc->succ_next)
530 block_t *w = arc->dst;
531 if (w < start || !linfo.has_block (w))
532 continue;
534 path.push_back (arc);
535 if (w == start)
536 /* Cycle has been found. */
537 result |= handle_cycle (path, count);
538 else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
539 result |= circuit (w, path, start, blocked, block_lists, linfo, count);
541 path.pop_back ();
544 if (result != NO_LOOP)
545 unblock (v, blocked, block_lists);
546 else
547 for (arc_t *arc = v->succ; arc; arc = arc->succ_next)
549 block_t *w = arc->dst;
550 if (w < start || !linfo.has_block (w))
551 continue;
553 size_t index
554 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
555 gcc_assert (index < blocked.size ());
556 block_vector_t &list = block_lists[index];
557 if (find (list.begin (), list.end (), v) == list.end ())
558 list.push_back (v);
561 return result;
564 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
565 contains a negative loop, then perform the same function once again. */
567 static gcov_type
568 get_cycles_count (line_t &linfo, bool handle_negative_cycles = true)
570 /* Note that this algorithm works even if blocks aren't in sorted order.
571 Each iteration of the circuit detection is completely independent
572 (except for reducing counts, but that shouldn't matter anyways).
573 Therefore, operating on a permuted order (i.e., non-sorted) only
574 has the effect of permuting the output cycles. */
576 loop_type result = NO_LOOP;
577 gcov_type count = 0;
578 for (block_t *block = linfo.u.blocks; block; block = block->chain)
580 arc_vector_t path;
581 block_vector_t blocked;
582 vector<block_vector_t > block_lists;
583 result |= circuit (block, path, block, blocked, block_lists, linfo,
584 count);
587 /* If we have a negative cycle, repeat the find_cycles routine. */
588 if (result == NEGATIVE_LOOP && handle_negative_cycles)
589 count += get_cycles_count (linfo, false);
591 return count;
595 main (int argc, char **argv)
597 int argno;
598 int first_arg;
599 const char *p;
601 p = argv[0] + strlen (argv[0]);
602 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
603 --p;
604 progname = p;
606 xmalloc_set_program_name (progname);
608 /* Unlock the stdio streams. */
609 unlock_std_streams ();
611 gcc_init_libintl ();
613 diagnostic_initialize (global_dc, 0);
615 /* Handle response files. */
616 expandargv (&argc, &argv);
618 a_names = 10;
619 names = XNEWVEC (name_map_t, a_names);
620 a_sources = 10;
621 sources = XNEWVEC (source_t, a_sources);
623 argno = process_args (argc, argv);
624 if (optind == argc)
625 print_usage (true);
627 if (argc - argno > 1)
628 multiple_files = 1;
630 first_arg = argno;
632 for (; argno != argc; argno++)
634 if (flag_display_progress)
635 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
636 argc - first_arg);
637 process_file (argv[argno]);
640 generate_results (multiple_files ? NULL : argv[argc - 1]);
642 release_structures ();
644 return 0;
647 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
648 otherwise the output of --help. */
650 static void
651 print_usage (int error_p)
653 FILE *file = error_p ? stderr : stdout;
654 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
656 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
657 fnotice (file, "Print code coverage information.\n\n");
658 fnotice (file, " -h, --help Print this help, then exit\n");
659 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
660 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
661 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
662 rather than percentages\n");
663 fnotice (file, " -d, --display-progress Display progress information\n");
664 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
665 fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
666 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
667 source files\n");
668 fnotice (file, " -m, --demangled-names Output demangled function names\n");
669 fnotice (file, " -n, --no-output Do not create an output file\n");
670 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
671 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
672 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
673 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
674 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
675 fnotice (file, " -v, --version Print version number, then exit\n");
676 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
677 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
678 bug_report_url);
679 exit (status);
682 /* Print version information and exit. */
684 static void
685 print_version (void)
687 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
688 fprintf (stdout, "Copyright %s 2017 Free Software Foundation, Inc.\n",
689 _("(C)"));
690 fnotice (stdout,
691 _("This is free software; see the source for copying conditions.\n"
692 "There is NO warranty; not even for MERCHANTABILITY or \n"
693 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
694 exit (SUCCESS_EXIT_CODE);
697 static const struct option options[] =
699 { "help", no_argument, NULL, 'h' },
700 { "version", no_argument, NULL, 'v' },
701 { "all-blocks", no_argument, NULL, 'a' },
702 { "branch-probabilities", no_argument, NULL, 'b' },
703 { "branch-counts", no_argument, NULL, 'c' },
704 { "intermediate-format", no_argument, NULL, 'i' },
705 { "no-output", no_argument, NULL, 'n' },
706 { "long-file-names", no_argument, NULL, 'l' },
707 { "function-summaries", no_argument, NULL, 'f' },
708 { "demangled-names", no_argument, NULL, 'm' },
709 { "preserve-paths", no_argument, NULL, 'p' },
710 { "relative-only", no_argument, NULL, 'r' },
711 { "object-directory", required_argument, NULL, 'o' },
712 { "object-file", required_argument, NULL, 'o' },
713 { "source-prefix", required_argument, NULL, 's' },
714 { "unconditional-branches", no_argument, NULL, 'u' },
715 { "display-progress", no_argument, NULL, 'd' },
716 { "hash-filenames", no_argument, NULL, 'x' },
717 { 0, 0, 0, 0 }
720 /* Process args, return index to first non-arg. */
722 static int
723 process_args (int argc, char **argv)
725 int opt;
727 const char *opts = "abcdfhilmno:prs:uvx";
728 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
730 switch (opt)
732 case 'a':
733 flag_all_blocks = 1;
734 break;
735 case 'b':
736 flag_branches = 1;
737 break;
738 case 'c':
739 flag_counts = 1;
740 break;
741 case 'f':
742 flag_function_summary = 1;
743 break;
744 case 'h':
745 print_usage (false);
746 /* print_usage will exit. */
747 case 'l':
748 flag_long_names = 1;
749 break;
750 case 'm':
751 flag_demangled_names = 1;
752 break;
753 case 'n':
754 flag_gcov_file = 0;
755 break;
756 case 'o':
757 object_directory = optarg;
758 break;
759 case 's':
760 source_prefix = optarg;
761 source_length = strlen (source_prefix);
762 break;
763 case 'r':
764 flag_relative_only = 1;
765 break;
766 case 'p':
767 flag_preserve_paths = 1;
768 break;
769 case 'u':
770 flag_unconditional = 1;
771 break;
772 case 'i':
773 flag_intermediate_format = 1;
774 flag_gcov_file = 1;
775 break;
776 case 'd':
777 flag_display_progress = 1;
778 break;
779 case 'x':
780 flag_hash_filenames = 1;
781 break;
782 case 'v':
783 print_version ();
784 /* print_version will exit. */
785 default:
786 print_usage (true);
787 /* print_usage will exit. */
791 return optind;
794 /* Output the result in intermediate format used by 'lcov'.
796 The intermediate format contains a single file named 'foo.cc.gcov',
797 with no source code included. A sample output is
799 file:foo.cc
800 function:5,1,_Z3foov
801 function:13,1,main
802 function:19,1,_GLOBAL__sub_I__Z3foov
803 function:19,1,_Z41__static_initialization_and_destruction_0ii
804 lcount:5,1
805 lcount:7,9
806 lcount:9,8
807 lcount:11,1
808 file:/.../iostream
809 lcount:74,1
810 file:/.../basic_ios.h
811 file:/.../ostream
812 file:/.../ios_base.h
813 function:157,0,_ZStorSt12_Ios_IostateS_
814 lcount:157,0
815 file:/.../char_traits.h
816 function:258,0,_ZNSt11char_traitsIcE6lengthEPKc
817 lcount:258,0
820 The default gcov outputs multiple files: 'foo.cc.gcov',
821 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
822 included. Instead the intermediate format here outputs only a single
823 file 'foo.cc.gcov' similar to the above example. */
825 static void
826 output_intermediate_file (FILE *gcov_file, source_t *src)
828 unsigned line_num; /* current line number. */
829 const line_t *line; /* current line info ptr. */
830 function_t *fn; /* current function info ptr. */
832 fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
834 for (fn = src->functions; fn; fn = fn->next_file_fn)
836 /* function:<name>,<line_number>,<execution_count> */
837 fprintf (gcov_file, "function:%d,%s,%s\n", fn->line,
838 format_gcov (fn->blocks[0].count, 0, -1),
839 flag_demangled_names ? fn->demangled_name : fn->name);
842 for (line_num = 1, line = &src->lines[line_num];
843 line_num < src->num_lines;
844 line_num++, line++)
846 arc_t *arc;
847 if (line->exists)
848 fprintf (gcov_file, "lcount:%u,%s\n", line_num,
849 format_gcov (line->count, 0, -1));
850 if (flag_branches)
851 for (arc = line->u.branches; arc; arc = arc->line_next)
853 if (!arc->is_unconditional && !arc->is_call_non_return)
855 const char *branch_type;
856 /* branch:<line_num>,<branch_coverage_type>
857 branch_coverage_type
858 : notexec (Branch not executed)
859 : taken (Branch executed and taken)
860 : nottaken (Branch executed, but not taken)
862 if (arc->src->count)
863 branch_type = (arc->count > 0) ? "taken" : "nottaken";
864 else
865 branch_type = "notexec";
866 fprintf (gcov_file, "branch:%d,%s\n", line_num, branch_type);
872 /* Process a single input file. */
874 static void
875 process_file (const char *file_name)
877 function_t *fns;
879 create_file_names (file_name);
880 fns = read_graph_file ();
881 if (!fns)
882 return;
884 read_count_file (fns);
885 while (fns)
887 function_t *fn = fns;
889 fns = fn->next;
890 fn->next = NULL;
891 if (fn->counts || no_data_file)
893 unsigned src = fn->src;
894 unsigned line = fn->line;
895 unsigned block_no;
896 function_t *probe, **prev;
898 /* Now insert it into the source file's list of
899 functions. Normally functions will be encountered in
900 ascending order, so a simple scan is quick. Note we're
901 building this list in reverse order. */
902 for (prev = &sources[src].functions;
903 (probe = *prev); prev = &probe->next_file_fn)
904 if (probe->line <= line)
905 break;
906 fn->next_file_fn = probe;
907 *prev = fn;
909 /* Mark last line in files touched by function. */
910 for (block_no = 0; block_no != fn->num_blocks; block_no++)
912 unsigned *enc = fn->blocks[block_no].u.line.encoding;
913 unsigned num = fn->blocks[block_no].u.line.num;
915 for (; num--; enc++)
916 if (!*enc)
918 if (enc[1] != src)
920 if (line >= sources[src].num_lines)
921 sources[src].num_lines = line + 1;
922 line = 0;
923 src = enc[1];
925 enc++;
926 num--;
928 else if (*enc > line)
929 line = *enc;
931 if (line >= sources[src].num_lines)
932 sources[src].num_lines = line + 1;
934 solve_flow_graph (fn);
935 if (fn->has_catch)
936 find_exception_blocks (fn);
937 *fn_end = fn;
938 fn_end = &fn->next;
940 else
941 /* The function was not in the executable -- some other
942 instance must have been selected. */
943 release_function (fn);
947 static void
948 output_gcov_file (const char *file_name, source_t *src)
950 char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
952 if (src->coverage.lines)
954 FILE *gcov_file = fopen (gcov_file_name, "w");
955 if (gcov_file)
957 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
959 if (flag_intermediate_format)
960 output_intermediate_file (gcov_file, src);
961 else
962 output_lines (gcov_file, src);
963 if (ferror (gcov_file))
964 fnotice (stderr, "Error writing output file '%s'\n", gcov_file_name);
965 fclose (gcov_file);
967 else
968 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
970 else
972 unlink (gcov_file_name);
973 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
975 free (gcov_file_name);
978 static void
979 generate_results (const char *file_name)
981 unsigned ix;
982 source_t *src;
983 function_t *fn;
985 for (ix = n_sources, src = sources; ix--; src++)
986 if (src->num_lines)
987 src->lines = XCNEWVEC (line_t, src->num_lines);
989 for (fn = functions; fn; fn = fn->next)
991 coverage_t coverage;
993 memset (&coverage, 0, sizeof (coverage));
994 coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
995 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
996 if (flag_function_summary)
998 function_summary (&coverage, "Function");
999 fnotice (stdout, "\n");
1003 if (file_name)
1005 name_map_t *name_map = (name_map_t *)bsearch
1006 (file_name, names, n_names, sizeof (*names), name_search);
1007 if (name_map)
1008 file_name = sources[name_map->src].coverage.name;
1009 else
1010 file_name = canonicalize_name (file_name);
1013 for (ix = n_sources, src = sources; ix--; src++)
1015 if (flag_relative_only)
1017 /* Ignore this source, if it is an absolute path (after
1018 source prefix removal). */
1019 char first = src->coverage.name[0];
1021 #if HAVE_DOS_BASED_FILE_SYSTEM
1022 if (first && src->coverage.name[1] == ':')
1023 first = src->coverage.name[2];
1024 #endif
1025 if (IS_DIR_SEPARATOR (first))
1026 continue;
1029 accumulate_line_counts (src);
1030 function_summary (&src->coverage, "File");
1031 total_lines += src->coverage.lines;
1032 total_executed += src->coverage.lines_executed;
1033 if (flag_gcov_file)
1035 output_gcov_file (file_name, src);
1036 fnotice (stdout, "\n");
1040 if (!file_name)
1041 executed_summary (total_lines, total_executed);
1044 /* Release a function structure */
1046 static void
1047 release_function (function_t *fn)
1049 unsigned ix;
1050 block_t *block;
1052 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
1054 arc_t *arc, *arc_n;
1056 for (arc = block->succ; arc; arc = arc_n)
1058 arc_n = arc->succ_next;
1059 free (arc);
1062 free (fn->blocks);
1063 free (fn->counts);
1064 if (flag_demangled_names && fn->demangled_name != fn->name)
1065 free (fn->demangled_name);
1066 free (fn->name);
1069 /* Release all memory used. */
1071 static void
1072 release_structures (void)
1074 unsigned ix;
1075 function_t *fn;
1077 for (ix = n_sources; ix--;)
1078 free (sources[ix].lines);
1079 free (sources);
1081 for (ix = n_names; ix--;)
1082 free (names[ix].name);
1083 free (names);
1085 while ((fn = functions))
1087 functions = fn->next;
1088 release_function (fn);
1092 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1093 is not specified, these are named from FILE_NAME sans extension. If
1094 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1095 directory, but named from the basename of the FILE_NAME, sans extension.
1096 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1097 and the data files are named from that. */
1099 static void
1100 create_file_names (const char *file_name)
1102 char *cptr;
1103 char *name;
1104 int length = strlen (file_name);
1105 int base;
1107 /* Free previous file names. */
1108 free (bbg_file_name);
1109 free (da_file_name);
1110 da_file_name = bbg_file_name = NULL;
1111 bbg_file_time = 0;
1112 bbg_stamp = 0;
1114 if (object_directory && object_directory[0])
1116 struct stat status;
1118 length += strlen (object_directory) + 2;
1119 name = XNEWVEC (char, length);
1120 name[0] = 0;
1122 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1123 strcat (name, object_directory);
1124 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1125 strcat (name, "/");
1127 else
1129 name = XNEWVEC (char, length + 1);
1130 strcpy (name, file_name);
1131 base = 0;
1134 if (base)
1136 /* Append source file name. */
1137 const char *cptr = lbasename (file_name);
1138 strcat (name, cptr ? cptr : file_name);
1141 /* Remove the extension. */
1142 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1143 if (cptr)
1144 *cptr = 0;
1146 length = strlen (name);
1148 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1149 strcpy (bbg_file_name, name);
1150 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1152 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1153 strcpy (da_file_name, name);
1154 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1156 free (name);
1157 return;
1160 /* A is a string and B is a pointer to name_map_t. Compare for file
1161 name orderability. */
1163 static int
1164 name_search (const void *a_, const void *b_)
1166 const char *a = (const char *)a_;
1167 const name_map_t *b = (const name_map_t *)b_;
1169 #if HAVE_DOS_BASED_FILE_SYSTEM
1170 return strcasecmp (a, b->name);
1171 #else
1172 return strcmp (a, b->name);
1173 #endif
1176 /* A and B are a pointer to name_map_t. Compare for file name
1177 orderability. */
1179 static int
1180 name_sort (const void *a_, const void *b_)
1182 const name_map_t *a = (const name_map_t *)a_;
1183 return name_search (a->name, b_);
1186 /* Find or create a source file structure for FILE_NAME. Copies
1187 FILE_NAME on creation */
1189 static unsigned
1190 find_source (const char *file_name)
1192 name_map_t *name_map;
1193 char *canon;
1194 unsigned idx;
1195 struct stat status;
1197 if (!file_name)
1198 file_name = "<unknown>";
1199 name_map = (name_map_t *)bsearch
1200 (file_name, names, n_names, sizeof (*names), name_search);
1201 if (name_map)
1203 idx = name_map->src;
1204 goto check_date;
1207 if (n_names + 2 > a_names)
1209 /* Extend the name map array -- we'll be inserting one or two
1210 entries. */
1211 a_names *= 2;
1212 name_map = XNEWVEC (name_map_t, a_names);
1213 memcpy (name_map, names, n_names * sizeof (*names));
1214 free (names);
1215 names = name_map;
1218 /* Not found, try the canonical name. */
1219 canon = canonicalize_name (file_name);
1220 name_map = (name_map_t *) bsearch (canon, names, n_names, sizeof (*names),
1221 name_search);
1222 if (!name_map)
1224 /* Not found with canonical name, create a new source. */
1225 source_t *src;
1227 if (n_sources == a_sources)
1229 a_sources *= 2;
1230 src = XNEWVEC (source_t, a_sources);
1231 memcpy (src, sources, n_sources * sizeof (*sources));
1232 free (sources);
1233 sources = src;
1236 idx = n_sources;
1238 name_map = &names[n_names++];
1239 name_map->name = canon;
1240 name_map->src = idx;
1242 src = &sources[n_sources++];
1243 memset (src, 0, sizeof (*src));
1244 src->name = canon;
1245 src->coverage.name = src->name;
1246 if (source_length
1247 #if HAVE_DOS_BASED_FILE_SYSTEM
1248 /* You lose if separators don't match exactly in the
1249 prefix. */
1250 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1251 #else
1252 && !strncmp (source_prefix, src->coverage.name, source_length)
1253 #endif
1254 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1255 src->coverage.name += source_length + 1;
1256 if (!stat (src->name, &status))
1257 src->file_time = status.st_mtime;
1259 else
1260 idx = name_map->src;
1262 if (name_search (file_name, name_map))
1264 /* Append the non-canonical name. */
1265 name_map = &names[n_names++];
1266 name_map->name = xstrdup (file_name);
1267 name_map->src = idx;
1270 /* Resort the name map. */
1271 qsort (names, n_names, sizeof (*names), name_sort);
1273 check_date:
1274 if (sources[idx].file_time > bbg_file_time)
1276 static int info_emitted;
1278 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1279 file_name, bbg_file_name);
1280 if (!info_emitted)
1282 fnotice (stderr,
1283 "(the message is displayed only once per source file)\n");
1284 info_emitted = 1;
1286 sources[idx].file_time = 0;
1289 return idx;
1292 /* Read the notes file. Return list of functions read -- in reverse order. */
1294 static function_t *
1295 read_graph_file (void)
1297 unsigned version;
1298 unsigned current_tag = 0;
1299 function_t *fn = NULL;
1300 function_t *fns = NULL;
1301 function_t **fns_end = &fns;
1302 unsigned src_idx = 0;
1303 unsigned ix;
1304 unsigned tag;
1306 if (!gcov_open (bbg_file_name, 1))
1308 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1309 return fns;
1311 bbg_file_time = gcov_time ();
1312 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1314 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1315 gcov_close ();
1316 return fns;
1319 version = gcov_read_unsigned ();
1320 if (version != GCOV_VERSION)
1322 char v[4], e[4];
1324 GCOV_UNSIGNED2STRING (v, version);
1325 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1327 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1328 bbg_file_name, v, e);
1330 bbg_stamp = gcov_read_unsigned ();
1332 while ((tag = gcov_read_unsigned ()))
1334 unsigned length = gcov_read_unsigned ();
1335 gcov_position_t base = gcov_position ();
1337 if (tag == GCOV_TAG_FUNCTION)
1339 char *function_name;
1340 unsigned ident, lineno;
1341 unsigned lineno_checksum, cfg_checksum;
1343 ident = gcov_read_unsigned ();
1344 lineno_checksum = gcov_read_unsigned ();
1345 cfg_checksum = gcov_read_unsigned ();
1346 function_name = xstrdup (gcov_read_string ());
1347 src_idx = find_source (gcov_read_string ());
1348 lineno = gcov_read_unsigned ();
1350 fn = XCNEW (function_t);
1351 fn->name = function_name;
1352 if (flag_demangled_names)
1354 fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1355 if (!fn->demangled_name)
1356 fn->demangled_name = fn->name;
1358 fn->ident = ident;
1359 fn->lineno_checksum = lineno_checksum;
1360 fn->cfg_checksum = cfg_checksum;
1361 fn->src = src_idx;
1362 fn->line = lineno;
1364 fn->next_file_fn = NULL;
1365 fn->next = NULL;
1366 *fns_end = fn;
1367 fns_end = &fn->next;
1368 current_tag = tag;
1370 else if (fn && tag == GCOV_TAG_BLOCKS)
1372 if (fn->blocks)
1373 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1374 bbg_file_name, fn->name);
1375 else
1377 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1378 fn->num_blocks = num_blocks;
1380 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
1381 for (ix = 0; ix != num_blocks; ix++)
1382 fn->blocks[ix].flags = gcov_read_unsigned ();
1385 else if (fn && tag == GCOV_TAG_ARCS)
1387 unsigned src = gcov_read_unsigned ();
1388 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1389 block_t *src_blk = &fn->blocks[src];
1390 unsigned mark_catches = 0;
1391 struct arc_info *arc;
1393 if (src >= fn->num_blocks || fn->blocks[src].succ)
1394 goto corrupt;
1396 while (num_dests--)
1398 unsigned dest = gcov_read_unsigned ();
1399 unsigned flags = gcov_read_unsigned ();
1401 if (dest >= fn->num_blocks)
1402 goto corrupt;
1403 arc = XCNEW (arc_t);
1405 arc->dst = &fn->blocks[dest];
1406 arc->src = src_blk;
1408 arc->count = 0;
1409 arc->count_valid = 0;
1410 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1411 arc->fake = !!(flags & GCOV_ARC_FAKE);
1412 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1414 arc->succ_next = src_blk->succ;
1415 src_blk->succ = arc;
1416 src_blk->num_succ++;
1418 arc->pred_next = fn->blocks[dest].pred;
1419 fn->blocks[dest].pred = arc;
1420 fn->blocks[dest].num_pred++;
1422 if (arc->fake)
1424 if (src)
1426 /* Exceptional exit from this function, the
1427 source block must be a call. */
1428 fn->blocks[src].is_call_site = 1;
1429 arc->is_call_non_return = 1;
1430 mark_catches = 1;
1432 else
1434 /* Non-local return from a callee of this
1435 function. The destination block is a setjmp. */
1436 arc->is_nonlocal_return = 1;
1437 fn->blocks[dest].is_nonlocal_return = 1;
1441 if (!arc->on_tree)
1442 fn->num_counts++;
1445 if (mark_catches)
1447 /* We have a fake exit from this block. The other
1448 non-fall through exits must be to catch handlers.
1449 Mark them as catch arcs. */
1451 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1452 if (!arc->fake && !arc->fall_through)
1454 arc->is_throw = 1;
1455 fn->has_catch = 1;
1459 else if (fn && tag == GCOV_TAG_LINES)
1461 unsigned blockno = gcov_read_unsigned ();
1462 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1464 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1465 goto corrupt;
1467 for (ix = 0; ; )
1469 unsigned lineno = gcov_read_unsigned ();
1471 if (lineno)
1473 if (!ix)
1475 line_nos[ix++] = 0;
1476 line_nos[ix++] = src_idx;
1478 line_nos[ix++] = lineno;
1480 else
1482 const char *file_name = gcov_read_string ();
1484 if (!file_name)
1485 break;
1486 src_idx = find_source (file_name);
1487 line_nos[ix++] = 0;
1488 line_nos[ix++] = src_idx;
1492 fn->blocks[blockno].u.line.encoding = line_nos;
1493 fn->blocks[blockno].u.line.num = ix;
1495 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1497 fn = NULL;
1498 current_tag = 0;
1500 gcov_sync (base, length);
1501 if (gcov_is_error ())
1503 corrupt:;
1504 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1505 break;
1508 gcov_close ();
1510 if (!fns)
1511 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1513 return fns;
1516 /* Reads profiles from the count file and attach to each
1517 function. Return nonzero if fatal error. */
1519 static int
1520 read_count_file (function_t *fns)
1522 unsigned ix;
1523 unsigned version;
1524 unsigned tag;
1525 function_t *fn = NULL;
1526 int error = 0;
1528 if (!gcov_open (da_file_name, 1))
1530 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1531 da_file_name);
1532 no_data_file = 1;
1533 return 0;
1535 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1537 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1538 cleanup:;
1539 gcov_close ();
1540 return 1;
1542 version = gcov_read_unsigned ();
1543 if (version != GCOV_VERSION)
1545 char v[4], e[4];
1547 GCOV_UNSIGNED2STRING (v, version);
1548 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1550 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1551 da_file_name, v, e);
1553 tag = gcov_read_unsigned ();
1554 if (tag != bbg_stamp)
1556 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1557 goto cleanup;
1560 while ((tag = gcov_read_unsigned ()))
1562 unsigned length = gcov_read_unsigned ();
1563 unsigned long base = gcov_position ();
1565 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1567 struct gcov_summary summary;
1568 gcov_read_summary (&summary);
1569 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1570 program_count++;
1572 else if (tag == GCOV_TAG_FUNCTION && !length)
1573 ; /* placeholder */
1574 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1576 unsigned ident;
1577 struct function_info *fn_n;
1579 /* Try to find the function in the list. To speed up the
1580 search, first start from the last function found. */
1581 ident = gcov_read_unsigned ();
1582 fn_n = fns;
1583 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1585 if (fn)
1587 else if ((fn = fn_n))
1588 fn_n = NULL;
1589 else
1591 fnotice (stderr, "%s:unknown function '%u'\n",
1592 da_file_name, ident);
1593 break;
1595 if (fn->ident == ident)
1596 break;
1599 if (!fn)
1601 else if (gcov_read_unsigned () != fn->lineno_checksum
1602 || gcov_read_unsigned () != fn->cfg_checksum)
1604 mismatch:;
1605 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1606 da_file_name, fn->name);
1607 goto cleanup;
1610 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1612 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1613 goto mismatch;
1615 if (!fn->counts)
1616 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1618 for (ix = 0; ix != fn->num_counts; ix++)
1619 fn->counts[ix] += gcov_read_counter ();
1621 gcov_sync (base, length);
1622 if ((error = gcov_is_error ()))
1624 fnotice (stderr,
1625 error < 0
1626 ? N_("%s:overflowed\n")
1627 : N_("%s:corrupted\n"),
1628 da_file_name);
1629 goto cleanup;
1633 gcov_close ();
1634 return 0;
1637 /* Solve the flow graph. Propagate counts from the instrumented arcs
1638 to the blocks and the uninstrumented arcs. */
1640 static void
1641 solve_flow_graph (function_t *fn)
1643 unsigned ix;
1644 arc_t *arc;
1645 gcov_type *count_ptr = fn->counts;
1646 block_t *blk;
1647 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1648 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1650 /* The arcs were built in reverse order. Fix that now. */
1651 for (ix = fn->num_blocks; ix--;)
1653 arc_t *arc_p, *arc_n;
1655 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1656 arc_p = arc, arc = arc_n)
1658 arc_n = arc->succ_next;
1659 arc->succ_next = arc_p;
1661 fn->blocks[ix].succ = arc_p;
1663 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1664 arc_p = arc, arc = arc_n)
1666 arc_n = arc->pred_next;
1667 arc->pred_next = arc_p;
1669 fn->blocks[ix].pred = arc_p;
1672 if (fn->num_blocks < 2)
1673 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1674 bbg_file_name, fn->name);
1675 else
1677 if (fn->blocks[ENTRY_BLOCK].num_pred)
1678 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1679 bbg_file_name, fn->name);
1680 else
1681 /* We can't deduce the entry block counts from the lack of
1682 predecessors. */
1683 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1685 if (fn->blocks[EXIT_BLOCK].num_succ)
1686 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1687 bbg_file_name, fn->name);
1688 else
1689 /* Likewise, we can't deduce exit block counts from the lack
1690 of its successors. */
1691 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1694 /* Propagate the measured counts, this must be done in the same
1695 order as the code in profile.c */
1696 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1698 block_t const *prev_dst = NULL;
1699 int out_of_order = 0;
1700 int non_fake_succ = 0;
1702 for (arc = blk->succ; arc; arc = arc->succ_next)
1704 if (!arc->fake)
1705 non_fake_succ++;
1707 if (!arc->on_tree)
1709 if (count_ptr)
1710 arc->count = *count_ptr++;
1711 arc->count_valid = 1;
1712 blk->num_succ--;
1713 arc->dst->num_pred--;
1715 if (prev_dst && prev_dst > arc->dst)
1716 out_of_order = 1;
1717 prev_dst = arc->dst;
1719 if (non_fake_succ == 1)
1721 /* If there is only one non-fake exit, it is an
1722 unconditional branch. */
1723 for (arc = blk->succ; arc; arc = arc->succ_next)
1724 if (!arc->fake)
1726 arc->is_unconditional = 1;
1727 /* If this block is instrumenting a call, it might be
1728 an artificial block. It is not artificial if it has
1729 a non-fallthrough exit, or the destination of this
1730 arc has more than one entry. Mark the destination
1731 block as a return site, if none of those conditions
1732 hold. */
1733 if (blk->is_call_site && arc->fall_through
1734 && arc->dst->pred == arc && !arc->pred_next)
1735 arc->dst->is_call_return = 1;
1739 /* Sort the successor arcs into ascending dst order. profile.c
1740 normally produces arcs in the right order, but sometimes with
1741 one or two out of order. We're not using a particularly
1742 smart sort. */
1743 if (out_of_order)
1745 arc_t *start = blk->succ;
1746 unsigned changes = 1;
1748 while (changes)
1750 arc_t *arc, *arc_p, *arc_n;
1752 changes = 0;
1753 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1755 if (arc->dst > arc_n->dst)
1757 changes = 1;
1758 if (arc_p)
1759 arc_p->succ_next = arc_n;
1760 else
1761 start = arc_n;
1762 arc->succ_next = arc_n->succ_next;
1763 arc_n->succ_next = arc;
1764 arc_p = arc_n;
1766 else
1768 arc_p = arc;
1769 arc = arc_n;
1773 blk->succ = start;
1776 /* Place it on the invalid chain, it will be ignored if that's
1777 wrong. */
1778 blk->invalid_chain = 1;
1779 blk->chain = invalid_blocks;
1780 invalid_blocks = blk;
1783 while (invalid_blocks || valid_blocks)
1785 while ((blk = invalid_blocks))
1787 gcov_type total = 0;
1788 const arc_t *arc;
1790 invalid_blocks = blk->chain;
1791 blk->invalid_chain = 0;
1792 if (!blk->num_succ)
1793 for (arc = blk->succ; arc; arc = arc->succ_next)
1794 total += arc->count;
1795 else if (!blk->num_pred)
1796 for (arc = blk->pred; arc; arc = arc->pred_next)
1797 total += arc->count;
1798 else
1799 continue;
1801 blk->count = total;
1802 blk->count_valid = 1;
1803 blk->chain = valid_blocks;
1804 blk->valid_chain = 1;
1805 valid_blocks = blk;
1807 while ((blk = valid_blocks))
1809 gcov_type total;
1810 arc_t *arc, *inv_arc;
1812 valid_blocks = blk->chain;
1813 blk->valid_chain = 0;
1814 if (blk->num_succ == 1)
1816 block_t *dst;
1818 total = blk->count;
1819 inv_arc = NULL;
1820 for (arc = blk->succ; arc; arc = arc->succ_next)
1822 total -= arc->count;
1823 if (!arc->count_valid)
1824 inv_arc = arc;
1826 dst = inv_arc->dst;
1827 inv_arc->count_valid = 1;
1828 inv_arc->count = total;
1829 blk->num_succ--;
1830 dst->num_pred--;
1831 if (dst->count_valid)
1833 if (dst->num_pred == 1 && !dst->valid_chain)
1835 dst->chain = valid_blocks;
1836 dst->valid_chain = 1;
1837 valid_blocks = dst;
1840 else
1842 if (!dst->num_pred && !dst->invalid_chain)
1844 dst->chain = invalid_blocks;
1845 dst->invalid_chain = 1;
1846 invalid_blocks = dst;
1850 if (blk->num_pred == 1)
1852 block_t *src;
1854 total = blk->count;
1855 inv_arc = NULL;
1856 for (arc = blk->pred; arc; arc = arc->pred_next)
1858 total -= arc->count;
1859 if (!arc->count_valid)
1860 inv_arc = arc;
1862 src = inv_arc->src;
1863 inv_arc->count_valid = 1;
1864 inv_arc->count = total;
1865 blk->num_pred--;
1866 src->num_succ--;
1867 if (src->count_valid)
1869 if (src->num_succ == 1 && !src->valid_chain)
1871 src->chain = valid_blocks;
1872 src->valid_chain = 1;
1873 valid_blocks = src;
1876 else
1878 if (!src->num_succ && !src->invalid_chain)
1880 src->chain = invalid_blocks;
1881 src->invalid_chain = 1;
1882 invalid_blocks = src;
1889 /* If the graph has been correctly solved, every block will have a
1890 valid count. */
1891 for (ix = 0; ix < fn->num_blocks; ix++)
1892 if (!fn->blocks[ix].count_valid)
1894 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1895 bbg_file_name, fn->name);
1896 break;
1900 /* Mark all the blocks only reachable via an incoming catch. */
1902 static void
1903 find_exception_blocks (function_t *fn)
1905 unsigned ix;
1906 block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1908 /* First mark all blocks as exceptional. */
1909 for (ix = fn->num_blocks; ix--;)
1910 fn->blocks[ix].exceptional = 1;
1912 /* Now mark all the blocks reachable via non-fake edges */
1913 queue[0] = fn->blocks;
1914 queue[0]->exceptional = 0;
1915 for (ix = 1; ix;)
1917 block_t *block = queue[--ix];
1918 const arc_t *arc;
1920 for (arc = block->succ; arc; arc = arc->succ_next)
1921 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1923 arc->dst->exceptional = 0;
1924 queue[ix++] = arc->dst;
1930 /* Increment totals in COVERAGE according to arc ARC. */
1932 static void
1933 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1935 if (arc->is_call_non_return)
1937 coverage->calls++;
1938 if (arc->src->count)
1939 coverage->calls_executed++;
1941 else if (!arc->is_unconditional)
1943 coverage->branches++;
1944 if (arc->src->count)
1945 coverage->branches_executed++;
1946 if (arc->count)
1947 coverage->branches_taken++;
1951 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1952 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1953 If DP is zero, no decimal point is printed. Only print 100% when
1954 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1955 format TOP. Return pointer to a static string. */
1957 static char const *
1958 format_gcov (gcov_type top, gcov_type bottom, int dp)
1960 static char buffer[20];
1962 if (dp >= 0)
1964 float ratio = bottom ? (float)top / bottom : 0;
1965 int ix;
1966 unsigned limit = 100;
1967 unsigned percent;
1969 for (ix = dp; ix--; )
1970 limit *= 10;
1972 percent = (unsigned) (ratio * limit + (float)0.5);
1973 if (percent <= 0 && top)
1974 percent = 1;
1975 else if (percent >= limit && top != bottom)
1976 percent = limit - 1;
1977 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1978 if (dp)
1980 dp++;
1983 buffer[ix+1] = buffer[ix];
1984 ix--;
1986 while (dp--);
1987 buffer[ix + 1] = '.';
1990 else
1991 sprintf (buffer, "%" PRId64, (int64_t)top);
1993 return buffer;
1996 /* Summary of execution */
1998 static void
1999 executed_summary (unsigned lines, unsigned executed)
2001 if (lines)
2002 fnotice (stdout, "Lines executed:%s of %d\n",
2003 format_gcov (executed, lines, 2), lines);
2004 else
2005 fnotice (stdout, "No executable lines\n");
2008 /* Output summary info for a function or file. */
2010 static void
2011 function_summary (const coverage_t *coverage, const char *title)
2013 fnotice (stdout, "%s '%s'\n", title, coverage->name);
2014 executed_summary (coverage->lines, coverage->lines_executed);
2016 if (flag_branches)
2018 if (coverage->branches)
2020 fnotice (stdout, "Branches executed:%s of %d\n",
2021 format_gcov (coverage->branches_executed,
2022 coverage->branches, 2),
2023 coverage->branches);
2024 fnotice (stdout, "Taken at least once:%s of %d\n",
2025 format_gcov (coverage->branches_taken,
2026 coverage->branches, 2),
2027 coverage->branches);
2029 else
2030 fnotice (stdout, "No branches\n");
2031 if (coverage->calls)
2032 fnotice (stdout, "Calls executed:%s of %d\n",
2033 format_gcov (coverage->calls_executed, coverage->calls, 2),
2034 coverage->calls);
2035 else
2036 fnotice (stdout, "No calls\n");
2040 /* Canonicalize the filename NAME by canonicalizing directory
2041 separators, eliding . components and resolving .. components
2042 appropriately. Always returns a unique string. */
2044 static char *
2045 canonicalize_name (const char *name)
2047 /* The canonical name cannot be longer than the incoming name. */
2048 char *result = XNEWVEC (char, strlen (name) + 1);
2049 const char *base = name, *probe;
2050 char *ptr = result;
2051 char *dd_base;
2052 int slash = 0;
2054 #if HAVE_DOS_BASED_FILE_SYSTEM
2055 if (base[0] && base[1] == ':')
2057 result[0] = base[0];
2058 result[1] = ':';
2059 base += 2;
2060 ptr += 2;
2062 #endif
2063 for (dd_base = ptr; *base; base = probe)
2065 size_t len;
2067 for (probe = base; *probe; probe++)
2068 if (IS_DIR_SEPARATOR (*probe))
2069 break;
2071 len = probe - base;
2072 if (len == 1 && base[0] == '.')
2073 /* Elide a '.' directory */
2075 else if (len == 2 && base[0] == '.' && base[1] == '.')
2077 /* '..', we can only elide it and the previous directory, if
2078 we're not a symlink. */
2079 struct stat ATTRIBUTE_UNUSED buf;
2081 *ptr = 0;
2082 if (dd_base == ptr
2083 #if defined (S_ISLNK)
2084 /* S_ISLNK is not POSIX.1-1996. */
2085 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2086 #endif
2089 /* Cannot elide, or unreadable or a symlink. */
2090 dd_base = ptr + 2 + slash;
2091 goto regular;
2093 while (ptr != dd_base && *ptr != '/')
2094 ptr--;
2095 slash = ptr != result;
2097 else
2099 regular:
2100 /* Regular pathname component. */
2101 if (slash)
2102 *ptr++ = '/';
2103 memcpy (ptr, base, len);
2104 ptr += len;
2105 slash = 1;
2108 for (; IS_DIR_SEPARATOR (*probe); probe++)
2109 continue;
2111 *ptr = 0;
2113 return result;
2116 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2118 static void
2119 md5sum_to_hex (const char *sum, char *buffer)
2121 for (unsigned i = 0; i < 16; i++)
2122 sprintf (buffer + (2 * i), "%02x", (unsigned char)sum[i]);
2125 /* Generate an output file name. INPUT_NAME is the canonicalized main
2126 input file and SRC_NAME is the canonicalized file name.
2127 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2128 long_output_names we prepend the processed name of the input file
2129 to each output name (except when the current source file is the
2130 input file, so you don't get a double concatenation). The two
2131 components are separated by '##'. With preserve_paths we create a
2132 filename from all path components of the source file, replacing '/'
2133 with '#', and .. with '^', without it we simply take the basename
2134 component. (Remember, the canonicalized name will already have
2135 elided '.' components and converted \\ separators.) */
2137 static char *
2138 make_gcov_file_name (const char *input_name, const char *src_name)
2140 char *ptr;
2141 char *result;
2143 if (flag_long_names && input_name && strcmp (src_name, input_name))
2145 /* Generate the input filename part. */
2146 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
2148 ptr = result;
2149 ptr = mangle_name (input_name, ptr);
2150 ptr[0] = ptr[1] = '#';
2151 ptr += 2;
2153 else
2155 result = XNEWVEC (char, strlen (src_name) + 10);
2156 ptr = result;
2159 ptr = mangle_name (src_name, ptr);
2160 strcpy (ptr, ".gcov");
2162 /* When hashing filenames, we shorten them by only using the filename
2163 component and appending a hash of the full (mangled) pathname. */
2164 if (flag_hash_filenames)
2166 md5_ctx ctx;
2167 char md5sum[16];
2168 char md5sum_hex[33];
2170 md5_init_ctx (&ctx);
2171 md5_process_bytes (src_name, strlen (src_name), &ctx);
2172 md5_finish_ctx (&ctx, md5sum);
2173 md5sum_to_hex (md5sum, md5sum_hex);
2174 free (result);
2176 result = XNEWVEC (char, strlen (src_name) + 50);
2177 ptr = result;
2178 ptr = mangle_name (src_name, ptr);
2179 ptr[0] = ptr[1] = '#';
2180 ptr += 2;
2181 memcpy (ptr, md5sum_hex, 32);
2182 ptr += 32;
2183 strcpy (ptr, ".gcov");
2186 return result;
2189 static char *
2190 mangle_name (char const *base, char *ptr)
2192 size_t len;
2194 /* Generate the source filename part. */
2195 if (!flag_preserve_paths)
2197 base = lbasename (base);
2198 len = strlen (base);
2199 memcpy (ptr, base, len);
2200 ptr += len;
2202 else
2204 /* Convert '/' to '#', convert '..' to '^',
2205 convert ':' to '~' on DOS based file system. */
2206 const char *probe;
2208 #if HAVE_DOS_BASED_FILE_SYSTEM
2209 if (base[0] && base[1] == ':')
2211 ptr[0] = base[0];
2212 ptr[1] = '~';
2213 ptr += 2;
2214 base += 2;
2216 #endif
2217 for (; *base; base = probe)
2219 size_t len;
2221 for (probe = base; *probe; probe++)
2222 if (*probe == '/')
2223 break;
2224 len = probe - base;
2225 if (len == 2 && base[0] == '.' && base[1] == '.')
2226 *ptr++ = '^';
2227 else
2229 memcpy (ptr, base, len);
2230 ptr += len;
2232 if (*probe)
2234 *ptr++ = '#';
2235 probe++;
2240 return ptr;
2243 /* Scan through the bb_data for each line in the block, increment
2244 the line number execution count indicated by the execution count of
2245 the appropriate basic block. */
2247 static void
2248 add_line_counts (coverage_t *coverage, function_t *fn)
2250 unsigned ix;
2251 line_t *line = NULL; /* This is propagated from one iteration to the
2252 next. */
2254 /* Scan each basic block. */
2255 for (ix = 0; ix != fn->num_blocks; ix++)
2257 block_t *block = &fn->blocks[ix];
2258 unsigned *encoding;
2259 const source_t *src = NULL;
2260 unsigned jx;
2262 if (block->count && ix && ix + 1 != fn->num_blocks)
2263 fn->blocks_executed++;
2264 for (jx = 0, encoding = block->u.line.encoding;
2265 jx != block->u.line.num; jx++, encoding++)
2266 if (!*encoding)
2268 src = &sources[*++encoding];
2269 jx++;
2271 else
2273 line = &src->lines[*encoding];
2275 if (coverage)
2277 if (!line->exists)
2278 coverage->lines++;
2279 if (!line->count && block->count)
2280 coverage->lines_executed++;
2282 line->exists = 1;
2283 if (!block->exceptional)
2284 line->unexceptional = 1;
2285 line->count += block->count;
2287 free (block->u.line.encoding);
2288 block->u.cycle.arc = NULL;
2289 block->u.cycle.ident = ~0U;
2291 if (!ix || ix + 1 == fn->num_blocks)
2292 /* Entry or exit block */;
2293 else if (flag_all_blocks)
2295 line_t *block_line = line;
2297 if (!block_line)
2298 block_line = &sources[fn->src].lines[fn->line];
2300 block->chain = block_line->u.blocks;
2301 block_line->u.blocks = block;
2303 else if (flag_branches)
2305 arc_t *arc;
2307 for (arc = block->succ; arc; arc = arc->succ_next)
2309 arc->line_next = line->u.branches;
2310 line->u.branches = arc;
2311 if (coverage && !arc->is_unconditional)
2312 add_branch_counts (coverage, arc);
2316 if (!line)
2317 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
2320 /* Accumulate the line counts of a file. */
2322 static void
2323 accumulate_line_counts (source_t *src)
2325 line_t *line;
2326 function_t *fn, *fn_p, *fn_n;
2327 unsigned ix;
2329 /* Reverse the function order. */
2330 for (fn = src->functions, fn_p = NULL; fn; fn_p = fn, fn = fn_n)
2332 fn_n = fn->next_file_fn;
2333 fn->next_file_fn = fn_p;
2335 src->functions = fn_p;
2337 for (ix = src->num_lines, line = src->lines; ix--; line++)
2339 if (!flag_all_blocks)
2341 arc_t *arc, *arc_p, *arc_n;
2343 /* Total and reverse the branch information. */
2344 for (arc = line->u.branches, arc_p = NULL; arc;
2345 arc_p = arc, arc = arc_n)
2347 arc_n = arc->line_next;
2348 arc->line_next = arc_p;
2350 add_branch_counts (&src->coverage, arc);
2352 line->u.branches = arc_p;
2354 else if (line->u.blocks)
2356 /* The user expects the line count to be the number of times
2357 a line has been executed. Simply summing the block count
2358 will give an artificially high number. The Right Thing
2359 is to sum the entry counts to the graph of blocks on this
2360 line, then find the elementary cycles of the local graph
2361 and add the transition counts of those cycles. */
2362 block_t *block, *block_p, *block_n;
2363 gcov_type count = 0;
2365 /* Reverse the block information. */
2366 for (block = line->u.blocks, block_p = NULL; block;
2367 block_p = block, block = block_n)
2369 block_n = block->chain;
2370 block->chain = block_p;
2371 block->u.cycle.ident = ix;
2373 line->u.blocks = block_p;
2375 /* Sum the entry arcs. */
2376 for (block = line->u.blocks; block; block = block->chain)
2378 arc_t *arc;
2380 for (arc = block->pred; arc; arc = arc->pred_next)
2381 if (flag_branches)
2382 add_branch_counts (&src->coverage, arc);
2385 /* Cycle detection. */
2386 for (block = line->u.blocks; block; block = block->chain)
2388 for (arc_t *arc = block->pred; arc; arc = arc->pred_next)
2389 if (!line->has_block (arc->src))
2390 count += arc->count;
2391 for (arc_t *arc = block->succ; arc; arc = arc->succ_next)
2392 arc->cs_count = arc->count;
2395 /* Now, add the count of loops entirely on this line. */
2396 count += get_cycles_count (*line);
2397 line->count = count;
2400 if (line->exists)
2402 src->coverage.lines++;
2403 if (line->count)
2404 src->coverage.lines_executed++;
2409 /* Output information about ARC number IX. Returns nonzero if
2410 anything is output. */
2412 static int
2413 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2415 if (arc->is_call_non_return)
2417 if (arc->src->count)
2419 fnotice (gcov_file, "call %2d returned %s\n", ix,
2420 format_gcov (arc->src->count - arc->count,
2421 arc->src->count, -flag_counts));
2423 else
2424 fnotice (gcov_file, "call %2d never executed\n", ix);
2426 else if (!arc->is_unconditional)
2428 if (arc->src->count)
2429 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2430 format_gcov (arc->count, arc->src->count, -flag_counts),
2431 arc->fall_through ? " (fallthrough)"
2432 : arc->is_throw ? " (throw)" : "");
2433 else
2434 fnotice (gcov_file, "branch %2d never executed\n", ix);
2436 else if (flag_unconditional && !arc->dst->is_call_return)
2438 if (arc->src->count)
2439 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2440 format_gcov (arc->count, arc->src->count, -flag_counts));
2441 else
2442 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2444 else
2445 return 0;
2446 return 1;
2449 static const char *
2450 read_line (FILE *file)
2452 static char *string;
2453 static size_t string_len;
2454 size_t pos = 0;
2455 char *ptr;
2457 if (!string_len)
2459 string_len = 200;
2460 string = XNEWVEC (char, string_len);
2463 while ((ptr = fgets (string + pos, string_len - pos, file)))
2465 size_t len = strlen (string + pos);
2467 if (len && string[pos + len - 1] == '\n')
2469 string[pos + len - 1] = 0;
2470 return string;
2472 pos += len;
2473 /* If the file contains NUL characters or an incomplete
2474 last line, which can happen more than once in one run,
2475 we have to avoid doubling the STRING_LEN unnecessarily. */
2476 if (pos > string_len / 2)
2478 string_len *= 2;
2479 string = XRESIZEVEC (char, string, string_len);
2483 return pos ? string : NULL;
2486 /* Read in the source file one line at a time, and output that line to
2487 the gcov file preceded by its execution count and other
2488 information. */
2490 static void
2491 output_lines (FILE *gcov_file, const source_t *src)
2493 FILE *source_file;
2494 unsigned line_num; /* current line number. */
2495 const line_t *line; /* current line info ptr. */
2496 const char *retval = ""; /* status of source file reading. */
2497 function_t *fn = NULL;
2499 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2500 if (!multiple_files)
2502 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2503 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2504 no_data_file ? "-" : da_file_name);
2505 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
2507 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2509 source_file = fopen (src->name, "r");
2510 if (!source_file)
2512 fnotice (stderr, "Cannot open source file %s\n", src->name);
2513 retval = NULL;
2515 else if (src->file_time == 0)
2516 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2518 if (flag_branches)
2519 fn = src->functions;
2521 for (line_num = 1, line = &src->lines[line_num];
2522 line_num < src->num_lines; line_num++, line++)
2524 for (; fn && fn->line == line_num; fn = fn->next_file_fn)
2526 arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
2527 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2528 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2530 for (; arc; arc = arc->pred_next)
2531 if (arc->fake)
2532 return_count -= arc->count;
2534 fprintf (gcov_file, "function %s", flag_demangled_names ?
2535 fn->demangled_name : fn->name);
2536 fprintf (gcov_file, " called %s",
2537 format_gcov (called_count, 0, -1));
2538 fprintf (gcov_file, " returned %s",
2539 format_gcov (return_count, called_count, 0));
2540 fprintf (gcov_file, " blocks executed %s",
2541 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2542 fprintf (gcov_file, "\n");
2545 if (retval)
2546 retval = read_line (source_file);
2548 /* For lines which don't exist in the .bb file, print '-' before
2549 the source line. For lines which exist but were never
2550 executed, print '#####' or '=====' before the source line.
2551 Otherwise, print the execution count before the source line.
2552 There are 16 spaces of indentation added before the source
2553 line so that tabs won't be messed up. */
2554 fprintf (gcov_file, "%9s:%5u:%s\n",
2555 !line->exists ? "-" : line->count
2556 ? format_gcov (line->count, 0, -1)
2557 : line->unexceptional ? "#####" : "=====", line_num,
2558 retval ? retval : "/*EOF*/");
2560 if (flag_all_blocks)
2562 block_t *block;
2563 arc_t *arc;
2564 int ix, jx;
2566 for (ix = jx = 0, block = line->u.blocks; block;
2567 block = block->chain)
2569 if (!block->is_call_return)
2570 fprintf (gcov_file, "%9s:%5u-block %2d\n",
2571 !line->exists ? "-" : block->count
2572 ? format_gcov (block->count, 0, -1)
2573 : block->exceptional ? "%%%%%" : "$$$$$",
2574 line_num, ix++);
2575 if (flag_branches)
2576 for (arc = block->succ; arc; arc = arc->succ_next)
2577 jx += output_branch_count (gcov_file, jx, arc);
2580 else if (flag_branches)
2582 int ix;
2583 arc_t *arc;
2585 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2586 ix += output_branch_count (gcov_file, ix, arc);
2590 /* Handle all remaining source lines. There may be lines after the
2591 last line of code. */
2592 if (retval)
2594 for (; (retval = read_line (source_file)); line_num++)
2595 fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
2598 if (source_file)
2599 fclose (source_file);