GCOV: add support for lines with an unexecuted lines.
[official-gcc.git] / gcc / gcov.c
blobf9334f96eb3b1dd35347814add9b3780ecf0d1c4
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 #define INCLUDE_STRING
37 #include "system.h"
38 #include "coretypes.h"
39 #include "tm.h"
40 #include "intl.h"
41 #include "diagnostic.h"
42 #include "version.h"
43 #include "demangle.h"
44 #include "color-macros.h"
46 #include <getopt.h>
48 #include "md5.h"
50 using namespace std;
52 #define IN_GCOV 1
53 #include "gcov-io.h"
54 #include "gcov-io.c"
56 /* The gcno file is generated by -ftest-coverage option. The gcda file is
57 generated by a program compiled with -fprofile-arcs. Their formats
58 are documented in gcov-io.h. */
60 /* The functions in this file for creating and solution program flow graphs
61 are very similar to functions in the gcc source file profile.c. In
62 some places we make use of the knowledge of how profile.c works to
63 select particular algorithms here. */
65 /* The code validates that the profile information read in corresponds
66 to the code currently being compiled. Rather than checking for
67 identical files, the code below compares a checksum on the CFG
68 (based on the order of basic blocks and the arcs in the CFG). If
69 the CFG checksum in the gcda file match the CFG checksum in the
70 gcno file, the profile data will be used. */
72 /* This is the size of the buffer used to read in source file lines. */
74 struct function_info;
75 struct block_info;
76 struct source_info;
78 /* Describes an arc between two basic blocks. */
80 typedef struct arc_info
82 /* source and destination blocks. */
83 struct block_info *src;
84 struct block_info *dst;
86 /* transition counts. */
87 gcov_type count;
88 /* used in cycle search, so that we do not clobber original counts. */
89 gcov_type cs_count;
91 unsigned int count_valid : 1;
92 unsigned int on_tree : 1;
93 unsigned int fake : 1;
94 unsigned int fall_through : 1;
96 /* Arc to a catch handler. */
97 unsigned int is_throw : 1;
99 /* Arc is for a function that abnormally returns. */
100 unsigned int is_call_non_return : 1;
102 /* Arc is for catch/setjmp. */
103 unsigned int is_nonlocal_return : 1;
105 /* Is an unconditional branch. */
106 unsigned int is_unconditional : 1;
108 /* Loop making arc. */
109 unsigned int cycle : 1;
111 /* Next branch on line. */
112 struct arc_info *line_next;
114 /* Links to next arc on src and dst lists. */
115 struct arc_info *succ_next;
116 struct arc_info *pred_next;
117 } arc_t;
119 /* Describes which locations (lines and files) are associated with
120 a basic block. */
122 struct block_location_info
124 block_location_info (unsigned _source_file_idx):
125 source_file_idx (_source_file_idx)
128 unsigned source_file_idx;
129 vector<unsigned> lines;
132 /* Describes a basic block. Contains lists of arcs to successor and
133 predecessor blocks. */
135 typedef struct block_info
137 /* Constructor. */
138 block_info ();
140 /* Chain of exit and entry arcs. */
141 arc_t *succ;
142 arc_t *pred;
144 /* Number of unprocessed exit and entry arcs. */
145 gcov_type num_succ;
146 gcov_type num_pred;
148 unsigned id;
150 /* Block execution count. */
151 gcov_type count;
152 unsigned count_valid : 1;
153 unsigned valid_chain : 1;
154 unsigned invalid_chain : 1;
155 unsigned exceptional : 1;
157 /* Block is a call instrumenting site. */
158 unsigned is_call_site : 1; /* Does the call. */
159 unsigned is_call_return : 1; /* Is the return. */
161 /* Block is a landing pad for longjmp or throw. */
162 unsigned is_nonlocal_return : 1;
164 vector<block_location_info> locations;
166 struct
168 /* Single line graph cycle workspace. Used for all-blocks
169 mode. */
170 arc_t *arc;
171 unsigned ident;
172 } cycle; /* Used in all-blocks mode, after blocks are linked onto
173 lines. */
175 /* Temporary chain for solving graph, and for chaining blocks on one
176 line. */
177 struct block_info *chain;
179 } block_t;
181 block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
182 id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
183 exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
184 locations (), chain (NULL)
186 cycle.arc = NULL;
189 /* Describes a single function. Contains an array of basic blocks. */
191 typedef struct function_info
193 function_info ();
194 ~function_info ();
196 /* Name of function. */
197 char *name;
198 char *demangled_name;
199 unsigned ident;
200 unsigned lineno_checksum;
201 unsigned cfg_checksum;
203 /* The graph contains at least one fake incoming edge. */
204 unsigned has_catch : 1;
206 /* Array of basic blocks. Like in GCC, the entry block is
207 at blocks[0] and the exit block is at blocks[1]. */
208 #define ENTRY_BLOCK (0)
209 #define EXIT_BLOCK (1)
210 vector<block_t> blocks;
211 unsigned blocks_executed;
213 /* Raw arc coverage counts. */
214 gcov_type *counts;
215 unsigned num_counts;
217 /* First line number & file. */
218 unsigned line;
219 unsigned src;
221 /* Next function in same source file. */
222 struct function_info *next_file_fn;
224 /* Next function. */
225 struct function_info *next;
226 } function_t;
228 /* Describes coverage of a file or function. */
230 typedef struct coverage_info
232 int lines;
233 int lines_executed;
235 int branches;
236 int branches_executed;
237 int branches_taken;
239 int calls;
240 int calls_executed;
242 char *name;
243 } coverage_t;
245 /* Describes a single line of source. Contains a chain of basic blocks
246 with code on it. */
248 typedef struct line_info
250 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
251 bool has_block (block_t *needle);
253 gcov_type count; /* execution count */
254 arc_t *branches; /* branches from blocks that end on this line. */
255 block_t *blocks; /* blocks which start on this line.
256 Used in all-blocks mode. */
257 unsigned exists : 1;
258 unsigned unexceptional : 1;
259 unsigned has_unexecuted_block : 1;
260 } line_t;
262 bool
263 line_t::has_block (block_t *needle)
265 for (block_t *n = blocks; n; n = n->chain)
266 if (n == needle)
267 return true;
269 return false;
272 /* Describes a file mentioned in the block graph. Contains an array
273 of line info. */
275 typedef struct source_info
277 /* Canonical name of source file. */
278 char *name;
279 time_t file_time;
281 /* Array of line information. */
282 line_t *lines;
283 unsigned num_lines;
285 coverage_t coverage;
287 /* Functions in this source file. These are in ascending line
288 number order. */
289 function_t *functions;
290 } source_t;
292 typedef struct name_map
294 char *name; /* Source file name */
295 unsigned src; /* Source file */
296 } name_map_t;
298 /* Holds a list of function basic block graphs. */
300 static function_t *functions;
301 static function_t **fn_end = &functions;
303 static source_t *sources; /* Array of source files */
304 static unsigned n_sources; /* Number of sources */
305 static unsigned a_sources; /* Allocated sources */
307 static name_map_t *names; /* Mapping of file names to sources */
308 static unsigned n_names; /* Number of names */
309 static unsigned a_names; /* Allocated names */
311 /* This holds data summary information. */
313 static unsigned object_runs;
314 static unsigned program_count;
316 static unsigned total_lines;
317 static unsigned total_executed;
319 /* Modification time of graph file. */
321 static time_t bbg_file_time;
323 /* Name of the notes (gcno) output file. The "bbg" prefix is for
324 historical reasons, when the notes file contained only the
325 basic block graph notes. */
327 static char *bbg_file_name;
329 /* Stamp of the bbg file */
330 static unsigned bbg_stamp;
332 /* Name and file pointer of the input file for the count data (gcda). */
334 static char *da_file_name;
336 /* Data file is missing. */
338 static int no_data_file;
340 /* If there is several input files, compute and display results after
341 reading all data files. This way if two or more gcda file refer to
342 the same source file (eg inline subprograms in a .h file), the
343 counts are added. */
345 static int multiple_files = 0;
347 /* Output branch probabilities. */
349 static int flag_branches = 0;
351 /* Show unconditional branches too. */
352 static int flag_unconditional = 0;
354 /* Output a gcov file if this is true. This is on by default, and can
355 be turned off by the -n option. */
357 static int flag_gcov_file = 1;
359 /* Output progress indication if this is true. This is off by default
360 and can be turned on by the -d option. */
362 static int flag_display_progress = 0;
364 /* Output *.gcov file in intermediate format used by 'lcov'. */
366 static int flag_intermediate_format = 0;
368 /* Output demangled function names. */
370 static int flag_demangled_names = 0;
372 /* For included files, make the gcov output file name include the name
373 of the input source file. For example, if x.h is included in a.c,
374 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
376 static int flag_long_names = 0;
378 /* For situations when a long name can potentially hit filesystem path limit,
379 let's calculate md5sum of the path and append it to a file name. */
381 static int flag_hash_filenames = 0;
383 /* Print verbose informations. */
385 static int flag_verbose = 0;
387 /* Print colored output. */
389 static int flag_use_colors = 0;
391 /* Output count information for every basic block, not merely those
392 that contain line number information. */
394 static int flag_all_blocks = 0;
396 /* Output summary info for each function. */
398 static int flag_function_summary = 0;
400 /* Object directory file prefix. This is the directory/file where the
401 graph and data files are looked for, if nonzero. */
403 static char *object_directory = 0;
405 /* Source directory prefix. This is removed from source pathnames
406 that match, when generating the output file name. */
408 static char *source_prefix = 0;
409 static size_t source_length = 0;
411 /* Only show data for sources with relative pathnames. Absolute ones
412 usually indicate a system header file, which although it may
413 contain inline functions, is usually uninteresting. */
414 static int flag_relative_only = 0;
416 /* Preserve all pathname components. Needed when object files and
417 source files are in subdirectories. '/' is mangled as '#', '.' is
418 elided and '..' mangled to '^'. */
420 static int flag_preserve_paths = 0;
422 /* Output the number of times a branch was taken as opposed to the percentage
423 of times it was taken. */
425 static int flag_counts = 0;
427 /* Forward declarations. */
428 static int process_args (int, char **);
429 static void print_usage (int) ATTRIBUTE_NORETURN;
430 static void print_version (void) ATTRIBUTE_NORETURN;
431 static void process_file (const char *);
432 static void generate_results (const char *);
433 static void create_file_names (const char *);
434 static int name_search (const void *, const void *);
435 static int name_sort (const void *, const void *);
436 static char *canonicalize_name (const char *);
437 static unsigned find_source (const char *);
438 static function_t *read_graph_file (void);
439 static int read_count_file (function_t *);
440 static void solve_flow_graph (function_t *);
441 static void find_exception_blocks (function_t *);
442 static void add_branch_counts (coverage_t *, const arc_t *);
443 static void add_line_counts (coverage_t *, function_t *);
444 static void executed_summary (unsigned, unsigned);
445 static void function_summary (const coverage_t *, const char *);
446 static const char *format_gcov (gcov_type, gcov_type, int);
447 static void accumulate_line_counts (source_t *);
448 static void output_gcov_file (const char *, source_t *);
449 static int output_branch_count (FILE *, int, const arc_t *);
450 static void output_lines (FILE *, const source_t *);
451 static char *make_gcov_file_name (const char *, const char *);
452 static char *mangle_name (const char *, char *);
453 static void release_structures (void);
454 extern int main (int, char **);
456 function_info::function_info (): name (NULL), demangled_name (NULL),
457 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
458 blocks (), blocks_executed (0), counts (NULL), num_counts (0),
459 line (0), src (0), next_file_fn (NULL), next (NULL)
463 function_info::~function_info ()
465 for (int i = blocks.size () - 1; i >= 0; i--)
467 arc_t *arc, *arc_n;
469 for (arc = blocks[i].succ; arc; arc = arc_n)
471 arc_n = arc->succ_next;
472 free (arc);
475 free (counts);
476 if (flag_demangled_names && demangled_name != name)
477 free (demangled_name);
478 free (name);
481 /* Cycle detection!
482 There are a bajillion algorithms that do this. Boost's function is named
483 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
484 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
485 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
487 The basic algorithm is simple: effectively, we're finding all simple paths
488 in a subgraph (that shrinks every iteration). Duplicates are filtered by
489 "blocking" a path when a node is added to the path (this also prevents non-
490 simple paths)--the node is unblocked only when it participates in a cycle.
493 typedef vector<arc_t *> arc_vector_t;
494 typedef vector<const block_t *> block_vector_t;
496 /* Enum with types of loop in CFG. */
498 enum loop_type
500 NO_LOOP = 0,
501 LOOP = 1,
502 NEGATIVE_LOOP = 3
505 /* Loop_type operator that merges two values: A and B. */
507 inline loop_type& operator |= (loop_type& a, loop_type b)
509 return a = static_cast<loop_type> (a | b);
512 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
513 and subtract the value from all counts. The subtracted value is added
514 to COUNT. Returns type of loop. */
516 static loop_type
517 handle_cycle (const arc_vector_t &edges, int64_t &count)
519 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
520 that amount. */
521 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
522 for (unsigned i = 0; i < edges.size (); i++)
524 int64_t ecount = edges[i]->cs_count;
525 if (cycle_count > ecount)
526 cycle_count = ecount;
528 count += cycle_count;
529 for (unsigned i = 0; i < edges.size (); i++)
530 edges[i]->cs_count -= cycle_count;
532 return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
535 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
536 blocked by U in BLOCK_LISTS. */
538 static void
539 unblock (const block_t *u, block_vector_t &blocked,
540 vector<block_vector_t > &block_lists)
542 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
543 if (it == blocked.end ())
544 return;
546 unsigned index = it - blocked.begin ();
547 blocked.erase (it);
549 block_vector_t to_unblock (block_lists[index]);
551 block_lists.erase (block_lists.begin () + index);
553 for (block_vector_t::iterator it = to_unblock.begin ();
554 it != to_unblock.end (); it++)
555 unblock (*it, blocked, block_lists);
558 /* Find circuit going to block V, PATH is provisional seen cycle.
559 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
560 blocked by a block. COUNT is accumulated count of the current LINE.
561 Returns what type of loop it contains. */
563 static loop_type
564 circuit (block_t *v, arc_vector_t &path, block_t *start,
565 block_vector_t &blocked, vector<block_vector_t> &block_lists,
566 line_t &linfo, int64_t &count)
568 loop_type result = NO_LOOP;
570 /* Add v to the block list. */
571 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
572 blocked.push_back (v);
573 block_lists.push_back (block_vector_t ());
575 for (arc_t *arc = v->succ; arc; arc = arc->succ_next)
577 block_t *w = arc->dst;
578 if (w < start || !linfo.has_block (w))
579 continue;
581 path.push_back (arc);
582 if (w == start)
583 /* Cycle has been found. */
584 result |= handle_cycle (path, count);
585 else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
586 result |= circuit (w, path, start, blocked, block_lists, linfo, count);
588 path.pop_back ();
591 if (result != NO_LOOP)
592 unblock (v, blocked, block_lists);
593 else
594 for (arc_t *arc = v->succ; arc; arc = arc->succ_next)
596 block_t *w = arc->dst;
597 if (w < start || !linfo.has_block (w))
598 continue;
600 size_t index
601 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
602 gcc_assert (index < blocked.size ());
603 block_vector_t &list = block_lists[index];
604 if (find (list.begin (), list.end (), v) == list.end ())
605 list.push_back (v);
608 return result;
611 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
612 contains a negative loop, then perform the same function once again. */
614 static gcov_type
615 get_cycles_count (line_t &linfo, bool handle_negative_cycles = true)
617 /* Note that this algorithm works even if blocks aren't in sorted order.
618 Each iteration of the circuit detection is completely independent
619 (except for reducing counts, but that shouldn't matter anyways).
620 Therefore, operating on a permuted order (i.e., non-sorted) only
621 has the effect of permuting the output cycles. */
623 loop_type result = NO_LOOP;
624 gcov_type count = 0;
625 for (block_t *block = linfo.blocks; block; block = block->chain)
627 arc_vector_t path;
628 block_vector_t blocked;
629 vector<block_vector_t > block_lists;
630 result |= circuit (block, path, block, blocked, block_lists, linfo,
631 count);
634 /* If we have a negative cycle, repeat the find_cycles routine. */
635 if (result == NEGATIVE_LOOP && handle_negative_cycles)
636 count += get_cycles_count (linfo, false);
638 return count;
642 main (int argc, char **argv)
644 int argno;
645 int first_arg;
646 const char *p;
648 p = argv[0] + strlen (argv[0]);
649 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
650 --p;
651 progname = p;
653 xmalloc_set_program_name (progname);
655 /* Unlock the stdio streams. */
656 unlock_std_streams ();
658 gcc_init_libintl ();
660 diagnostic_initialize (global_dc, 0);
662 /* Handle response files. */
663 expandargv (&argc, &argv);
665 a_names = 10;
666 names = XNEWVEC (name_map_t, a_names);
667 a_sources = 10;
668 sources = XNEWVEC (source_t, a_sources);
670 argno = process_args (argc, argv);
671 if (optind == argc)
672 print_usage (true);
674 if (argc - argno > 1)
675 multiple_files = 1;
677 first_arg = argno;
679 for (; argno != argc; argno++)
681 if (flag_display_progress)
682 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
683 argc - first_arg);
684 process_file (argv[argno]);
687 generate_results (multiple_files ? NULL : argv[argc - 1]);
689 release_structures ();
691 return 0;
694 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
695 otherwise the output of --help. */
697 static void
698 print_usage (int error_p)
700 FILE *file = error_p ? stderr : stdout;
701 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
703 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
704 fnotice (file, "Print code coverage information.\n\n");
705 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
706 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
707 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
708 rather than percentages\n");
709 fnotice (file, " -d, --display-progress Display progress information\n");
710 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
711 fnotice (file, " -h, --help Print this help, then exit\n");
712 fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
713 fnotice (file, " -k, --use-colors Emit colored output\n");
714 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
715 source files\n");
716 fnotice (file, " -m, --demangled-names Output demangled function names\n");
717 fnotice (file, " -n, --no-output Do not create an output file\n");
718 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
719 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
720 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
721 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
722 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
723 fnotice (file, " -v, --version Print version number, then exit\n");
724 fnotice (file, " -w, --verbose Print verbose informations\n");
725 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
726 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
727 bug_report_url);
728 exit (status);
731 /* Print version information and exit. */
733 static void
734 print_version (void)
736 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
737 fprintf (stdout, "Copyright %s 2017 Free Software Foundation, Inc.\n",
738 _("(C)"));
739 fnotice (stdout,
740 _("This is free software; see the source for copying conditions.\n"
741 "There is NO warranty; not even for MERCHANTABILITY or \n"
742 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
743 exit (SUCCESS_EXIT_CODE);
746 static const struct option options[] =
748 { "help", no_argument, NULL, 'h' },
749 { "version", no_argument, NULL, 'v' },
750 { "verbose", no_argument, NULL, 'w' },
751 { "all-blocks", no_argument, NULL, 'a' },
752 { "branch-probabilities", no_argument, NULL, 'b' },
753 { "branch-counts", no_argument, NULL, 'c' },
754 { "intermediate-format", no_argument, NULL, 'i' },
755 { "no-output", no_argument, NULL, 'n' },
756 { "long-file-names", no_argument, NULL, 'l' },
757 { "function-summaries", no_argument, NULL, 'f' },
758 { "demangled-names", no_argument, NULL, 'm' },
759 { "preserve-paths", no_argument, NULL, 'p' },
760 { "relative-only", no_argument, NULL, 'r' },
761 { "object-directory", required_argument, NULL, 'o' },
762 { "object-file", required_argument, NULL, 'o' },
763 { "source-prefix", required_argument, NULL, 's' },
764 { "unconditional-branches", no_argument, NULL, 'u' },
765 { "display-progress", no_argument, NULL, 'd' },
766 { "hash-filenames", no_argument, NULL, 'x' },
767 { "use-colors", no_argument, NULL, 'k' },
768 { 0, 0, 0, 0 }
771 /* Process args, return index to first non-arg. */
773 static int
774 process_args (int argc, char **argv)
776 int opt;
778 const char *opts = "abcdfhiklmno:prs:uvwx";
779 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
781 switch (opt)
783 case 'a':
784 flag_all_blocks = 1;
785 break;
786 case 'b':
787 flag_branches = 1;
788 break;
789 case 'c':
790 flag_counts = 1;
791 break;
792 case 'f':
793 flag_function_summary = 1;
794 break;
795 case 'h':
796 print_usage (false);
797 /* print_usage will exit. */
798 case 'l':
799 flag_long_names = 1;
800 break;
801 case 'k':
802 flag_use_colors = 1;
803 break;
804 case 'm':
805 flag_demangled_names = 1;
806 break;
807 case 'n':
808 flag_gcov_file = 0;
809 break;
810 case 'o':
811 object_directory = optarg;
812 break;
813 case 's':
814 source_prefix = optarg;
815 source_length = strlen (source_prefix);
816 break;
817 case 'r':
818 flag_relative_only = 1;
819 break;
820 case 'p':
821 flag_preserve_paths = 1;
822 break;
823 case 'u':
824 flag_unconditional = 1;
825 break;
826 case 'i':
827 flag_intermediate_format = 1;
828 flag_gcov_file = 1;
829 break;
830 case 'd':
831 flag_display_progress = 1;
832 break;
833 case 'x':
834 flag_hash_filenames = 1;
835 break;
836 case 'w':
837 flag_verbose = 1;
838 break;
839 case 'v':
840 print_version ();
841 /* print_version will exit. */
842 default:
843 print_usage (true);
844 /* print_usage will exit. */
848 return optind;
851 /* Output the result in intermediate format used by 'lcov'.
853 The intermediate format contains a single file named 'foo.cc.gcov',
854 with no source code included.
856 The default gcov outputs multiple files: 'foo.cc.gcov',
857 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
858 included. Instead the intermediate format here outputs only a single
859 file 'foo.cc.gcov' similar to the above example. */
861 static void
862 output_intermediate_file (FILE *gcov_file, source_t *src)
864 unsigned line_num; /* current line number. */
865 const line_t *line; /* current line info ptr. */
866 function_t *fn; /* current function info ptr. */
868 fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
870 for (fn = src->functions; fn; fn = fn->next_file_fn)
872 /* function:<name>,<line_number>,<execution_count> */
873 fprintf (gcov_file, "function:%d,%s,%s\n", fn->line,
874 format_gcov (fn->blocks[0].count, 0, -1),
875 flag_demangled_names ? fn->demangled_name : fn->name);
878 for (line_num = 1, line = &src->lines[line_num];
879 line_num < src->num_lines;
880 line_num++, line++)
882 arc_t *arc;
883 if (line->exists)
884 fprintf (gcov_file, "lcount:%u,%s,%d\n", line_num,
885 format_gcov (line->count, 0, -1), line->has_unexecuted_block);
886 if (flag_branches)
887 for (arc = line->branches; arc; arc = arc->line_next)
889 if (!arc->is_unconditional && !arc->is_call_non_return)
891 const char *branch_type;
892 /* branch:<line_num>,<branch_coverage_type>
893 branch_coverage_type
894 : notexec (Branch not executed)
895 : taken (Branch executed and taken)
896 : nottaken (Branch executed, but not taken)
898 if (arc->src->count)
899 branch_type = (arc->count > 0) ? "taken" : "nottaken";
900 else
901 branch_type = "notexec";
902 fprintf (gcov_file, "branch:%d,%s\n", line_num, branch_type);
908 /* Process a single input file. */
910 static void
911 process_file (const char *file_name)
913 function_t *fns;
915 create_file_names (file_name);
916 fns = read_graph_file ();
917 if (!fns)
918 return;
920 read_count_file (fns);
921 while (fns)
923 function_t *fn = fns;
925 fns = fn->next;
926 fn->next = NULL;
927 if (fn->counts || no_data_file)
929 unsigned src = fn->src;
930 unsigned line = fn->line;
931 unsigned block_no;
932 function_t *probe, **prev;
934 /* Now insert it into the source file's list of
935 functions. Normally functions will be encountered in
936 ascending order, so a simple scan is quick. Note we're
937 building this list in reverse order. */
938 for (prev = &sources[src].functions;
939 (probe = *prev); prev = &probe->next_file_fn)
940 if (probe->line <= line)
941 break;
942 fn->next_file_fn = probe;
943 *prev = fn;
945 /* Mark last line in files touched by function. */
946 for (block_no = 0; block_no != fn->blocks.size (); block_no++)
948 block_t *block = &fn->blocks[block_no];
949 for (unsigned i = 0; i < block->locations.size (); i++)
951 unsigned s = block->locations[i].source_file_idx;
953 /* Sort lines of locations. */
954 sort (block->locations[i].lines.begin (),
955 block->locations[i].lines.end ());
957 if (!block->locations[i].lines.empty ())
959 unsigned last_line
960 = block->locations[i].lines.back () + 1;
961 if (last_line > sources[s].num_lines)
962 sources[s].num_lines = last_line;
967 solve_flow_graph (fn);
968 if (fn->has_catch)
969 find_exception_blocks (fn);
970 *fn_end = fn;
971 fn_end = &fn->next;
973 else
974 /* The function was not in the executable -- some other
975 instance must have been selected. */
976 delete fn;
980 static void
981 output_gcov_file (const char *file_name, source_t *src)
983 char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
985 if (src->coverage.lines)
987 FILE *gcov_file = fopen (gcov_file_name, "w");
988 if (gcov_file)
990 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
992 if (flag_intermediate_format)
993 output_intermediate_file (gcov_file, src);
994 else
995 output_lines (gcov_file, src);
996 if (ferror (gcov_file))
997 fnotice (stderr, "Error writing output file '%s'\n", gcov_file_name);
998 fclose (gcov_file);
1000 else
1001 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1003 else
1005 unlink (gcov_file_name);
1006 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1008 free (gcov_file_name);
1011 static void
1012 generate_results (const char *file_name)
1014 unsigned ix;
1015 source_t *src;
1016 function_t *fn;
1018 for (ix = n_sources, src = sources; ix--; src++)
1019 if (src->num_lines)
1020 src->lines = XCNEWVEC (line_t, src->num_lines);
1022 for (fn = functions; fn; fn = fn->next)
1024 coverage_t coverage;
1026 memset (&coverage, 0, sizeof (coverage));
1027 coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
1028 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1029 if (flag_function_summary)
1031 function_summary (&coverage, "Function");
1032 fnotice (stdout, "\n");
1036 if (file_name)
1038 name_map_t *name_map = (name_map_t *)bsearch
1039 (file_name, names, n_names, sizeof (*names), name_search);
1040 if (name_map)
1041 file_name = sources[name_map->src].coverage.name;
1042 else
1043 file_name = canonicalize_name (file_name);
1046 for (ix = n_sources, src = sources; ix--; src++)
1048 if (flag_relative_only)
1050 /* Ignore this source, if it is an absolute path (after
1051 source prefix removal). */
1052 char first = src->coverage.name[0];
1054 #if HAVE_DOS_BASED_FILE_SYSTEM
1055 if (first && src->coverage.name[1] == ':')
1056 first = src->coverage.name[2];
1057 #endif
1058 if (IS_DIR_SEPARATOR (first))
1059 continue;
1062 accumulate_line_counts (src);
1063 function_summary (&src->coverage, "File");
1064 total_lines += src->coverage.lines;
1065 total_executed += src->coverage.lines_executed;
1066 if (flag_gcov_file)
1068 output_gcov_file (file_name, src);
1069 fnotice (stdout, "\n");
1073 if (!file_name)
1074 executed_summary (total_lines, total_executed);
1077 /* Release all memory used. */
1079 static void
1080 release_structures (void)
1082 unsigned ix;
1083 function_t *fn;
1085 for (ix = n_sources; ix--;)
1086 free (sources[ix].lines);
1087 free (sources);
1089 for (ix = n_names; ix--;)
1090 free (names[ix].name);
1091 free (names);
1093 while ((fn = functions))
1095 functions = fn->next;
1096 delete fn;
1100 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1101 is not specified, these are named from FILE_NAME sans extension. If
1102 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1103 directory, but named from the basename of the FILE_NAME, sans extension.
1104 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1105 and the data files are named from that. */
1107 static void
1108 create_file_names (const char *file_name)
1110 char *cptr;
1111 char *name;
1112 int length = strlen (file_name);
1113 int base;
1115 /* Free previous file names. */
1116 free (bbg_file_name);
1117 free (da_file_name);
1118 da_file_name = bbg_file_name = NULL;
1119 bbg_file_time = 0;
1120 bbg_stamp = 0;
1122 if (object_directory && object_directory[0])
1124 struct stat status;
1126 length += strlen (object_directory) + 2;
1127 name = XNEWVEC (char, length);
1128 name[0] = 0;
1130 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1131 strcat (name, object_directory);
1132 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1133 strcat (name, "/");
1135 else
1137 name = XNEWVEC (char, length + 1);
1138 strcpy (name, file_name);
1139 base = 0;
1142 if (base)
1144 /* Append source file name. */
1145 const char *cptr = lbasename (file_name);
1146 strcat (name, cptr ? cptr : file_name);
1149 /* Remove the extension. */
1150 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1151 if (cptr)
1152 *cptr = 0;
1154 length = strlen (name);
1156 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1157 strcpy (bbg_file_name, name);
1158 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1160 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1161 strcpy (da_file_name, name);
1162 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1164 free (name);
1165 return;
1168 /* A is a string and B is a pointer to name_map_t. Compare for file
1169 name orderability. */
1171 static int
1172 name_search (const void *a_, const void *b_)
1174 const char *a = (const char *)a_;
1175 const name_map_t *b = (const name_map_t *)b_;
1177 #if HAVE_DOS_BASED_FILE_SYSTEM
1178 return strcasecmp (a, b->name);
1179 #else
1180 return strcmp (a, b->name);
1181 #endif
1184 /* A and B are a pointer to name_map_t. Compare for file name
1185 orderability. */
1187 static int
1188 name_sort (const void *a_, const void *b_)
1190 const name_map_t *a = (const name_map_t *)a_;
1191 return name_search (a->name, b_);
1194 /* Find or create a source file structure for FILE_NAME. Copies
1195 FILE_NAME on creation */
1197 static unsigned
1198 find_source (const char *file_name)
1200 name_map_t *name_map;
1201 char *canon;
1202 unsigned idx;
1203 struct stat status;
1205 if (!file_name)
1206 file_name = "<unknown>";
1207 name_map = (name_map_t *)bsearch
1208 (file_name, names, n_names, sizeof (*names), name_search);
1209 if (name_map)
1211 idx = name_map->src;
1212 goto check_date;
1215 if (n_names + 2 > a_names)
1217 /* Extend the name map array -- we'll be inserting one or two
1218 entries. */
1219 a_names *= 2;
1220 name_map = XNEWVEC (name_map_t, a_names);
1221 memcpy (name_map, names, n_names * sizeof (*names));
1222 free (names);
1223 names = name_map;
1226 /* Not found, try the canonical name. */
1227 canon = canonicalize_name (file_name);
1228 name_map = (name_map_t *) bsearch (canon, names, n_names, sizeof (*names),
1229 name_search);
1230 if (!name_map)
1232 /* Not found with canonical name, create a new source. */
1233 source_t *src;
1235 if (n_sources == a_sources)
1237 a_sources *= 2;
1238 src = XNEWVEC (source_t, a_sources);
1239 memcpy (src, sources, n_sources * sizeof (*sources));
1240 free (sources);
1241 sources = src;
1244 idx = n_sources;
1246 name_map = &names[n_names++];
1247 name_map->name = canon;
1248 name_map->src = idx;
1250 src = &sources[n_sources++];
1251 memset (src, 0, sizeof (*src));
1252 src->name = canon;
1253 src->coverage.name = src->name;
1254 if (source_length
1255 #if HAVE_DOS_BASED_FILE_SYSTEM
1256 /* You lose if separators don't match exactly in the
1257 prefix. */
1258 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1259 #else
1260 && !strncmp (source_prefix, src->coverage.name, source_length)
1261 #endif
1262 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1263 src->coverage.name += source_length + 1;
1264 if (!stat (src->name, &status))
1265 src->file_time = status.st_mtime;
1267 else
1268 idx = name_map->src;
1270 if (name_search (file_name, name_map))
1272 /* Append the non-canonical name. */
1273 name_map = &names[n_names++];
1274 name_map->name = xstrdup (file_name);
1275 name_map->src = idx;
1278 /* Resort the name map. */
1279 qsort (names, n_names, sizeof (*names), name_sort);
1281 check_date:
1282 if (sources[idx].file_time > bbg_file_time)
1284 static int info_emitted;
1286 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1287 file_name, bbg_file_name);
1288 if (!info_emitted)
1290 fnotice (stderr,
1291 "(the message is displayed only once per source file)\n");
1292 info_emitted = 1;
1294 sources[idx].file_time = 0;
1297 return idx;
1300 /* Read the notes file. Return list of functions read -- in reverse order. */
1302 static function_t *
1303 read_graph_file (void)
1305 unsigned version;
1306 unsigned current_tag = 0;
1307 function_t *fn = NULL;
1308 function_t *fns = NULL;
1309 function_t **fns_end = &fns;
1310 unsigned tag;
1312 if (!gcov_open (bbg_file_name, 1))
1314 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1315 return fns;
1317 bbg_file_time = gcov_time ();
1318 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1320 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1321 gcov_close ();
1322 return fns;
1325 version = gcov_read_unsigned ();
1326 if (version != GCOV_VERSION)
1328 char v[4], e[4];
1330 GCOV_UNSIGNED2STRING (v, version);
1331 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1333 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1334 bbg_file_name, v, e);
1336 bbg_stamp = gcov_read_unsigned ();
1338 while ((tag = gcov_read_unsigned ()))
1340 unsigned length = gcov_read_unsigned ();
1341 gcov_position_t base = gcov_position ();
1343 if (tag == GCOV_TAG_FUNCTION)
1345 char *function_name;
1346 unsigned ident, lineno;
1347 unsigned lineno_checksum, cfg_checksum;
1349 ident = gcov_read_unsigned ();
1350 lineno_checksum = gcov_read_unsigned ();
1351 cfg_checksum = gcov_read_unsigned ();
1352 function_name = xstrdup (gcov_read_string ());
1353 unsigned src_idx = find_source (gcov_read_string ());
1354 lineno = gcov_read_unsigned ();
1356 fn = new function_t;
1357 fn->name = function_name;
1358 if (flag_demangled_names)
1360 fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1361 if (!fn->demangled_name)
1362 fn->demangled_name = fn->name;
1364 fn->ident = ident;
1365 fn->lineno_checksum = lineno_checksum;
1366 fn->cfg_checksum = cfg_checksum;
1367 fn->src = src_idx;
1368 fn->line = lineno;
1370 fn->next_file_fn = NULL;
1371 fn->next = NULL;
1372 *fns_end = fn;
1373 fns_end = &fn->next;
1374 current_tag = tag;
1376 else if (fn && tag == GCOV_TAG_BLOCKS)
1378 if (!fn->blocks.empty ())
1379 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1380 bbg_file_name, fn->name);
1381 else
1382 fn->blocks.resize (gcov_read_unsigned ());
1384 else if (fn && tag == GCOV_TAG_ARCS)
1386 unsigned src = gcov_read_unsigned ();
1387 fn->blocks[src].id = src;
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->blocks.size () || 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->blocks.size ())
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 block_t *block = &fn->blocks[blockno];
1464 if (blockno >= fn->blocks.size ())
1465 goto corrupt;
1467 while (true)
1469 unsigned lineno = gcov_read_unsigned ();
1471 if (lineno)
1472 block->locations.back ().lines.push_back (lineno);
1473 else
1475 const char *file_name = gcov_read_string ();
1477 if (!file_name)
1478 break;
1479 block->locations.push_back (block_location_info
1480 (find_source (file_name)));
1484 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1486 fn = NULL;
1487 current_tag = 0;
1489 gcov_sync (base, length);
1490 if (gcov_is_error ())
1492 corrupt:;
1493 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1494 break;
1497 gcov_close ();
1499 if (!fns)
1500 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1502 return fns;
1505 /* Reads profiles from the count file and attach to each
1506 function. Return nonzero if fatal error. */
1508 static int
1509 read_count_file (function_t *fns)
1511 unsigned ix;
1512 unsigned version;
1513 unsigned tag;
1514 function_t *fn = NULL;
1515 int error = 0;
1517 if (!gcov_open (da_file_name, 1))
1519 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1520 da_file_name);
1521 no_data_file = 1;
1522 return 0;
1524 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1526 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1527 cleanup:;
1528 gcov_close ();
1529 return 1;
1531 version = gcov_read_unsigned ();
1532 if (version != GCOV_VERSION)
1534 char v[4], e[4];
1536 GCOV_UNSIGNED2STRING (v, version);
1537 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1539 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1540 da_file_name, v, e);
1542 tag = gcov_read_unsigned ();
1543 if (tag != bbg_stamp)
1545 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1546 goto cleanup;
1549 while ((tag = gcov_read_unsigned ()))
1551 unsigned length = gcov_read_unsigned ();
1552 unsigned long base = gcov_position ();
1554 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1556 struct gcov_summary summary;
1557 gcov_read_summary (&summary);
1558 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1559 program_count++;
1561 else if (tag == GCOV_TAG_FUNCTION && !length)
1562 ; /* placeholder */
1563 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1565 unsigned ident;
1566 struct function_info *fn_n;
1568 /* Try to find the function in the list. To speed up the
1569 search, first start from the last function found. */
1570 ident = gcov_read_unsigned ();
1571 fn_n = fns;
1572 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1574 if (fn)
1576 else if ((fn = fn_n))
1577 fn_n = NULL;
1578 else
1580 fnotice (stderr, "%s:unknown function '%u'\n",
1581 da_file_name, ident);
1582 break;
1584 if (fn->ident == ident)
1585 break;
1588 if (!fn)
1590 else if (gcov_read_unsigned () != fn->lineno_checksum
1591 || gcov_read_unsigned () != fn->cfg_checksum)
1593 mismatch:;
1594 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1595 da_file_name, fn->name);
1596 goto cleanup;
1599 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1601 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1602 goto mismatch;
1604 if (!fn->counts)
1605 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1607 for (ix = 0; ix != fn->num_counts; ix++)
1608 fn->counts[ix] += gcov_read_counter ();
1610 gcov_sync (base, length);
1611 if ((error = gcov_is_error ()))
1613 fnotice (stderr,
1614 error < 0
1615 ? N_("%s:overflowed\n")
1616 : N_("%s:corrupted\n"),
1617 da_file_name);
1618 goto cleanup;
1622 gcov_close ();
1623 return 0;
1626 /* Solve the flow graph. Propagate counts from the instrumented arcs
1627 to the blocks and the uninstrumented arcs. */
1629 static void
1630 solve_flow_graph (function_t *fn)
1632 unsigned ix;
1633 arc_t *arc;
1634 gcov_type *count_ptr = fn->counts;
1635 block_t *blk;
1636 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1637 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1639 /* The arcs were built in reverse order. Fix that now. */
1640 for (ix = fn->blocks.size (); ix--;)
1642 arc_t *arc_p, *arc_n;
1644 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1645 arc_p = arc, arc = arc_n)
1647 arc_n = arc->succ_next;
1648 arc->succ_next = arc_p;
1650 fn->blocks[ix].succ = arc_p;
1652 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1653 arc_p = arc, arc = arc_n)
1655 arc_n = arc->pred_next;
1656 arc->pred_next = arc_p;
1658 fn->blocks[ix].pred = arc_p;
1661 if (fn->blocks.size () < 2)
1662 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1663 bbg_file_name, fn->name);
1664 else
1666 if (fn->blocks[ENTRY_BLOCK].num_pred)
1667 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1668 bbg_file_name, fn->name);
1669 else
1670 /* We can't deduce the entry block counts from the lack of
1671 predecessors. */
1672 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1674 if (fn->blocks[EXIT_BLOCK].num_succ)
1675 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1676 bbg_file_name, fn->name);
1677 else
1678 /* Likewise, we can't deduce exit block counts from the lack
1679 of its successors. */
1680 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1683 /* Propagate the measured counts, this must be done in the same
1684 order as the code in profile.c */
1685 for (unsigned i = 0; i < fn->blocks.size (); i++)
1687 blk = &fn->blocks[i];
1688 block_t const *prev_dst = NULL;
1689 int out_of_order = 0;
1690 int non_fake_succ = 0;
1692 for (arc = blk->succ; arc; arc = arc->succ_next)
1694 if (!arc->fake)
1695 non_fake_succ++;
1697 if (!arc->on_tree)
1699 if (count_ptr)
1700 arc->count = *count_ptr++;
1701 arc->count_valid = 1;
1702 blk->num_succ--;
1703 arc->dst->num_pred--;
1705 if (prev_dst && prev_dst > arc->dst)
1706 out_of_order = 1;
1707 prev_dst = arc->dst;
1709 if (non_fake_succ == 1)
1711 /* If there is only one non-fake exit, it is an
1712 unconditional branch. */
1713 for (arc = blk->succ; arc; arc = arc->succ_next)
1714 if (!arc->fake)
1716 arc->is_unconditional = 1;
1717 /* If this block is instrumenting a call, it might be
1718 an artificial block. It is not artificial if it has
1719 a non-fallthrough exit, or the destination of this
1720 arc has more than one entry. Mark the destination
1721 block as a return site, if none of those conditions
1722 hold. */
1723 if (blk->is_call_site && arc->fall_through
1724 && arc->dst->pred == arc && !arc->pred_next)
1725 arc->dst->is_call_return = 1;
1729 /* Sort the successor arcs into ascending dst order. profile.c
1730 normally produces arcs in the right order, but sometimes with
1731 one or two out of order. We're not using a particularly
1732 smart sort. */
1733 if (out_of_order)
1735 arc_t *start = blk->succ;
1736 unsigned changes = 1;
1738 while (changes)
1740 arc_t *arc, *arc_p, *arc_n;
1742 changes = 0;
1743 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1745 if (arc->dst > arc_n->dst)
1747 changes = 1;
1748 if (arc_p)
1749 arc_p->succ_next = arc_n;
1750 else
1751 start = arc_n;
1752 arc->succ_next = arc_n->succ_next;
1753 arc_n->succ_next = arc;
1754 arc_p = arc_n;
1756 else
1758 arc_p = arc;
1759 arc = arc_n;
1763 blk->succ = start;
1766 /* Place it on the invalid chain, it will be ignored if that's
1767 wrong. */
1768 blk->invalid_chain = 1;
1769 blk->chain = invalid_blocks;
1770 invalid_blocks = blk;
1773 while (invalid_blocks || valid_blocks)
1775 while ((blk = invalid_blocks))
1777 gcov_type total = 0;
1778 const arc_t *arc;
1780 invalid_blocks = blk->chain;
1781 blk->invalid_chain = 0;
1782 if (!blk->num_succ)
1783 for (arc = blk->succ; arc; arc = arc->succ_next)
1784 total += arc->count;
1785 else if (!blk->num_pred)
1786 for (arc = blk->pred; arc; arc = arc->pred_next)
1787 total += arc->count;
1788 else
1789 continue;
1791 blk->count = total;
1792 blk->count_valid = 1;
1793 blk->chain = valid_blocks;
1794 blk->valid_chain = 1;
1795 valid_blocks = blk;
1797 while ((blk = valid_blocks))
1799 gcov_type total;
1800 arc_t *arc, *inv_arc;
1802 valid_blocks = blk->chain;
1803 blk->valid_chain = 0;
1804 if (blk->num_succ == 1)
1806 block_t *dst;
1808 total = blk->count;
1809 inv_arc = NULL;
1810 for (arc = blk->succ; arc; arc = arc->succ_next)
1812 total -= arc->count;
1813 if (!arc->count_valid)
1814 inv_arc = arc;
1816 dst = inv_arc->dst;
1817 inv_arc->count_valid = 1;
1818 inv_arc->count = total;
1819 blk->num_succ--;
1820 dst->num_pred--;
1821 if (dst->count_valid)
1823 if (dst->num_pred == 1 && !dst->valid_chain)
1825 dst->chain = valid_blocks;
1826 dst->valid_chain = 1;
1827 valid_blocks = dst;
1830 else
1832 if (!dst->num_pred && !dst->invalid_chain)
1834 dst->chain = invalid_blocks;
1835 dst->invalid_chain = 1;
1836 invalid_blocks = dst;
1840 if (blk->num_pred == 1)
1842 block_t *src;
1844 total = blk->count;
1845 inv_arc = NULL;
1846 for (arc = blk->pred; arc; arc = arc->pred_next)
1848 total -= arc->count;
1849 if (!arc->count_valid)
1850 inv_arc = arc;
1852 src = inv_arc->src;
1853 inv_arc->count_valid = 1;
1854 inv_arc->count = total;
1855 blk->num_pred--;
1856 src->num_succ--;
1857 if (src->count_valid)
1859 if (src->num_succ == 1 && !src->valid_chain)
1861 src->chain = valid_blocks;
1862 src->valid_chain = 1;
1863 valid_blocks = src;
1866 else
1868 if (!src->num_succ && !src->invalid_chain)
1870 src->chain = invalid_blocks;
1871 src->invalid_chain = 1;
1872 invalid_blocks = src;
1879 /* If the graph has been correctly solved, every block will have a
1880 valid count. */
1881 for (unsigned i = 0; ix < fn->blocks.size (); i++)
1882 if (!fn->blocks[i].count_valid)
1884 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1885 bbg_file_name, fn->name);
1886 break;
1890 /* Mark all the blocks only reachable via an incoming catch. */
1892 static void
1893 find_exception_blocks (function_t *fn)
1895 unsigned ix;
1896 block_t **queue = XALLOCAVEC (block_t *, fn->blocks.size ());
1898 /* First mark all blocks as exceptional. */
1899 for (ix = fn->blocks.size (); ix--;)
1900 fn->blocks[ix].exceptional = 1;
1902 /* Now mark all the blocks reachable via non-fake edges */
1903 queue[0] = &fn->blocks[0];
1904 queue[0]->exceptional = 0;
1905 for (ix = 1; ix;)
1907 block_t *block = queue[--ix];
1908 const arc_t *arc;
1910 for (arc = block->succ; arc; arc = arc->succ_next)
1911 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1913 arc->dst->exceptional = 0;
1914 queue[ix++] = arc->dst;
1920 /* Increment totals in COVERAGE according to arc ARC. */
1922 static void
1923 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1925 if (arc->is_call_non_return)
1927 coverage->calls++;
1928 if (arc->src->count)
1929 coverage->calls_executed++;
1931 else if (!arc->is_unconditional)
1933 coverage->branches++;
1934 if (arc->src->count)
1935 coverage->branches_executed++;
1936 if (arc->count)
1937 coverage->branches_taken++;
1941 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1942 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1943 If DP is zero, no decimal point is printed. Only print 100% when
1944 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1945 format TOP. Return pointer to a static string. */
1947 static char const *
1948 format_gcov (gcov_type top, gcov_type bottom, int dp)
1950 static char buffer[20];
1952 /* Handle invalid values that would result in a misleading value. */
1953 if (bottom != 0 && top > bottom && dp >= 0)
1955 sprintf (buffer, "NAN %%");
1956 return buffer;
1959 if (dp >= 0)
1961 float ratio = bottom ? (float)top / bottom : 0;
1962 int ix;
1963 unsigned limit = 100;
1964 unsigned percent;
1966 for (ix = dp; ix--; )
1967 limit *= 10;
1969 percent = (unsigned) (ratio * limit + (float)0.5);
1970 if (percent <= 0 && top)
1971 percent = 1;
1972 else if (percent >= limit && top != bottom)
1973 percent = limit - 1;
1974 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1975 if (dp)
1977 dp++;
1980 buffer[ix+1] = buffer[ix];
1981 ix--;
1983 while (dp--);
1984 buffer[ix + 1] = '.';
1987 else
1988 sprintf (buffer, "%" PRId64, (int64_t)top);
1990 return buffer;
1993 /* Summary of execution */
1995 static void
1996 executed_summary (unsigned lines, unsigned executed)
1998 if (lines)
1999 fnotice (stdout, "Lines executed:%s of %d\n",
2000 format_gcov (executed, lines, 2), lines);
2001 else
2002 fnotice (stdout, "No executable lines\n");
2005 /* Output summary info for a function or file. */
2007 static void
2008 function_summary (const coverage_t *coverage, const char *title)
2010 fnotice (stdout, "%s '%s'\n", title, coverage->name);
2011 executed_summary (coverage->lines, coverage->lines_executed);
2013 if (flag_branches)
2015 if (coverage->branches)
2017 fnotice (stdout, "Branches executed:%s of %d\n",
2018 format_gcov (coverage->branches_executed,
2019 coverage->branches, 2),
2020 coverage->branches);
2021 fnotice (stdout, "Taken at least once:%s of %d\n",
2022 format_gcov (coverage->branches_taken,
2023 coverage->branches, 2),
2024 coverage->branches);
2026 else
2027 fnotice (stdout, "No branches\n");
2028 if (coverage->calls)
2029 fnotice (stdout, "Calls executed:%s of %d\n",
2030 format_gcov (coverage->calls_executed, coverage->calls, 2),
2031 coverage->calls);
2032 else
2033 fnotice (stdout, "No calls\n");
2037 /* Canonicalize the filename NAME by canonicalizing directory
2038 separators, eliding . components and resolving .. components
2039 appropriately. Always returns a unique string. */
2041 static char *
2042 canonicalize_name (const char *name)
2044 /* The canonical name cannot be longer than the incoming name. */
2045 char *result = XNEWVEC (char, strlen (name) + 1);
2046 const char *base = name, *probe;
2047 char *ptr = result;
2048 char *dd_base;
2049 int slash = 0;
2051 #if HAVE_DOS_BASED_FILE_SYSTEM
2052 if (base[0] && base[1] == ':')
2054 result[0] = base[0];
2055 result[1] = ':';
2056 base += 2;
2057 ptr += 2;
2059 #endif
2060 for (dd_base = ptr; *base; base = probe)
2062 size_t len;
2064 for (probe = base; *probe; probe++)
2065 if (IS_DIR_SEPARATOR (*probe))
2066 break;
2068 len = probe - base;
2069 if (len == 1 && base[0] == '.')
2070 /* Elide a '.' directory */
2072 else if (len == 2 && base[0] == '.' && base[1] == '.')
2074 /* '..', we can only elide it and the previous directory, if
2075 we're not a symlink. */
2076 struct stat ATTRIBUTE_UNUSED buf;
2078 *ptr = 0;
2079 if (dd_base == ptr
2080 #if defined (S_ISLNK)
2081 /* S_ISLNK is not POSIX.1-1996. */
2082 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2083 #endif
2086 /* Cannot elide, or unreadable or a symlink. */
2087 dd_base = ptr + 2 + slash;
2088 goto regular;
2090 while (ptr != dd_base && *ptr != '/')
2091 ptr--;
2092 slash = ptr != result;
2094 else
2096 regular:
2097 /* Regular pathname component. */
2098 if (slash)
2099 *ptr++ = '/';
2100 memcpy (ptr, base, len);
2101 ptr += len;
2102 slash = 1;
2105 for (; IS_DIR_SEPARATOR (*probe); probe++)
2106 continue;
2108 *ptr = 0;
2110 return result;
2113 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2115 static void
2116 md5sum_to_hex (const char *sum, char *buffer)
2118 for (unsigned i = 0; i < 16; i++)
2119 sprintf (buffer + (2 * i), "%02x", (unsigned char)sum[i]);
2122 /* Generate an output file name. INPUT_NAME is the canonicalized main
2123 input file and SRC_NAME is the canonicalized file name.
2124 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2125 long_output_names we prepend the processed name of the input file
2126 to each output name (except when the current source file is the
2127 input file, so you don't get a double concatenation). The two
2128 components are separated by '##'. With preserve_paths we create a
2129 filename from all path components of the source file, replacing '/'
2130 with '#', and .. with '^', without it we simply take the basename
2131 component. (Remember, the canonicalized name will already have
2132 elided '.' components and converted \\ separators.) */
2134 static char *
2135 make_gcov_file_name (const char *input_name, const char *src_name)
2137 char *ptr;
2138 char *result;
2140 if (flag_long_names && input_name && strcmp (src_name, input_name))
2142 /* Generate the input filename part. */
2143 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
2145 ptr = result;
2146 ptr = mangle_name (input_name, ptr);
2147 ptr[0] = ptr[1] = '#';
2148 ptr += 2;
2150 else
2152 result = XNEWVEC (char, strlen (src_name) + 10);
2153 ptr = result;
2156 ptr = mangle_name (src_name, ptr);
2157 strcpy (ptr, ".gcov");
2159 /* When hashing filenames, we shorten them by only using the filename
2160 component and appending a hash of the full (mangled) pathname. */
2161 if (flag_hash_filenames)
2163 md5_ctx ctx;
2164 char md5sum[16];
2165 char md5sum_hex[33];
2167 md5_init_ctx (&ctx);
2168 md5_process_bytes (src_name, strlen (src_name), &ctx);
2169 md5_finish_ctx (&ctx, md5sum);
2170 md5sum_to_hex (md5sum, md5sum_hex);
2171 free (result);
2173 result = XNEWVEC (char, strlen (src_name) + 50);
2174 ptr = result;
2175 ptr = mangle_name (src_name, ptr);
2176 ptr[0] = ptr[1] = '#';
2177 ptr += 2;
2178 memcpy (ptr, md5sum_hex, 32);
2179 ptr += 32;
2180 strcpy (ptr, ".gcov");
2183 return result;
2186 static char *
2187 mangle_name (char const *base, char *ptr)
2189 size_t len;
2191 /* Generate the source filename part. */
2192 if (!flag_preserve_paths)
2194 base = lbasename (base);
2195 len = strlen (base);
2196 memcpy (ptr, base, len);
2197 ptr += len;
2199 else
2201 /* Convert '/' to '#', convert '..' to '^',
2202 convert ':' to '~' on DOS based file system. */
2203 const char *probe;
2205 #if HAVE_DOS_BASED_FILE_SYSTEM
2206 if (base[0] && base[1] == ':')
2208 ptr[0] = base[0];
2209 ptr[1] = '~';
2210 ptr += 2;
2211 base += 2;
2213 #endif
2214 for (; *base; base = probe)
2216 size_t len;
2218 for (probe = base; *probe; probe++)
2219 if (*probe == '/')
2220 break;
2221 len = probe - base;
2222 if (len == 2 && base[0] == '.' && base[1] == '.')
2223 *ptr++ = '^';
2224 else
2226 memcpy (ptr, base, len);
2227 ptr += len;
2229 if (*probe)
2231 *ptr++ = '#';
2232 probe++;
2237 return ptr;
2240 /* Scan through the bb_data for each line in the block, increment
2241 the line number execution count indicated by the execution count of
2242 the appropriate basic block. */
2244 static void
2245 add_line_counts (coverage_t *coverage, function_t *fn)
2247 bool has_any_line = false;
2248 /* Scan each basic block. */
2249 for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
2251 line_t *line = NULL;
2252 block_t *block = &fn->blocks[ix];
2253 if (block->count && ix && ix + 1 != fn->blocks.size ())
2254 fn->blocks_executed++;
2255 for (unsigned i = 0; i < block->locations.size (); i++)
2257 const source_t *src = &sources[block->locations[i].source_file_idx];
2259 vector<unsigned> &lines = block->locations[i].lines;
2260 for (unsigned j = 0; j < lines.size (); j++)
2262 line = &src->lines[lines[j]];
2263 if (coverage)
2265 if (!line->exists)
2266 coverage->lines++;
2267 if (!line->count && block->count)
2268 coverage->lines_executed++;
2270 line->exists = 1;
2271 if (!block->exceptional)
2273 line->unexceptional = 1;
2274 if (block->count == 0)
2275 line->has_unexecuted_block = 1;
2277 line->count += block->count;
2280 block->cycle.arc = NULL;
2281 block->cycle.ident = ~0U;
2282 has_any_line = true;
2284 if (!ix || ix + 1 == fn->blocks.size ())
2285 /* Entry or exit block */;
2286 else if (line != NULL)
2288 block->chain = line->blocks;
2289 line->blocks = block;
2291 if (flag_branches)
2293 arc_t *arc;
2295 for (arc = block->succ; arc; arc = arc->succ_next)
2297 arc->line_next = line->branches;
2298 line->branches = arc;
2299 if (coverage && !arc->is_unconditional)
2300 add_branch_counts (coverage, arc);
2306 if (!has_any_line)
2307 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
2310 /* Accumulate the line counts of a file. */
2312 static void
2313 accumulate_line_counts (source_t *src)
2315 line_t *line;
2316 function_t *fn, *fn_p, *fn_n;
2317 unsigned ix;
2319 /* Reverse the function order. */
2320 for (fn = src->functions, fn_p = NULL; fn; fn_p = fn, fn = fn_n)
2322 fn_n = fn->next_file_fn;
2323 fn->next_file_fn = fn_p;
2325 src->functions = fn_p;
2327 for (ix = src->num_lines, line = src->lines; ix--; line++)
2329 if (line->blocks)
2331 /* The user expects the line count to be the number of times
2332 a line has been executed. Simply summing the block count
2333 will give an artificially high number. The Right Thing
2334 is to sum the entry counts to the graph of blocks on this
2335 line, then find the elementary cycles of the local graph
2336 and add the transition counts of those cycles. */
2337 block_t *block, *block_p, *block_n;
2338 gcov_type count = 0;
2340 /* Reverse the block information. */
2341 for (block = line->blocks, block_p = NULL; block;
2342 block_p = block, block = block_n)
2344 block_n = block->chain;
2345 block->chain = block_p;
2346 block->cycle.ident = ix;
2348 line->blocks = block_p;
2350 /* Sum the entry arcs. */
2351 for (block = line->blocks; block; block = block->chain)
2353 arc_t *arc;
2355 for (arc = block->pred; arc; arc = arc->pred_next)
2356 if (flag_branches)
2357 add_branch_counts (&src->coverage, arc);
2360 /* Cycle detection. */
2361 for (block = line->blocks; block; block = block->chain)
2363 for (arc_t *arc = block->pred; arc; arc = arc->pred_next)
2364 if (!line->has_block (arc->src))
2365 count += arc->count;
2366 for (arc_t *arc = block->succ; arc; arc = arc->succ_next)
2367 arc->cs_count = arc->count;
2370 /* Now, add the count of loops entirely on this line. */
2371 count += get_cycles_count (*line);
2372 line->count = count;
2375 if (line->exists)
2377 src->coverage.lines++;
2378 if (line->count)
2379 src->coverage.lines_executed++;
2384 /* Output information about ARC number IX. Returns nonzero if
2385 anything is output. */
2387 static int
2388 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2390 if (arc->is_call_non_return)
2392 if (arc->src->count)
2394 fnotice (gcov_file, "call %2d returned %s\n", ix,
2395 format_gcov (arc->src->count - arc->count,
2396 arc->src->count, -flag_counts));
2398 else
2399 fnotice (gcov_file, "call %2d never executed\n", ix);
2401 else if (!arc->is_unconditional)
2403 if (arc->src->count)
2404 fnotice (gcov_file, "branch %2d taken %s%s", ix,
2405 format_gcov (arc->count, arc->src->count, -flag_counts),
2406 arc->fall_through ? " (fallthrough)"
2407 : arc->is_throw ? " (throw)" : "");
2408 else
2409 fnotice (gcov_file, "branch %2d never executed", ix);
2411 if (flag_verbose)
2412 fnotice (gcov_file, " (BB %d)", arc->dst->id);
2414 fnotice (gcov_file, "\n");
2416 else if (flag_unconditional && !arc->dst->is_call_return)
2418 if (arc->src->count)
2419 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2420 format_gcov (arc->count, arc->src->count, -flag_counts));
2421 else
2422 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2424 else
2425 return 0;
2426 return 1;
2429 static const char *
2430 read_line (FILE *file)
2432 static char *string;
2433 static size_t string_len;
2434 size_t pos = 0;
2435 char *ptr;
2437 if (!string_len)
2439 string_len = 200;
2440 string = XNEWVEC (char, string_len);
2443 while ((ptr = fgets (string + pos, string_len - pos, file)))
2445 size_t len = strlen (string + pos);
2447 if (len && string[pos + len - 1] == '\n')
2449 string[pos + len - 1] = 0;
2450 return string;
2452 pos += len;
2453 /* If the file contains NUL characters or an incomplete
2454 last line, which can happen more than once in one run,
2455 we have to avoid doubling the STRING_LEN unnecessarily. */
2456 if (pos > string_len / 2)
2458 string_len *= 2;
2459 string = XRESIZEVEC (char, string, string_len);
2463 return pos ? string : NULL;
2466 /* Pad string S with spaces from left to have total width equal to 9. */
2468 static void
2469 pad_count_string (string &s)
2471 if (s.size () < 9)
2472 s.insert (0, 9 - s.size (), ' ');
2475 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2476 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2477 an exceptional statement. The output is printed for LINE_NUM of given
2478 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2479 used to indicate non-executed blocks. */
2481 static void
2482 output_line_beginning (FILE *f, bool exists, bool unexceptional,
2483 bool has_unexecuted_block,
2484 gcov_type count, unsigned line_num,
2485 const char *exceptional_string,
2486 const char *unexceptional_string)
2488 string s;
2489 if (exists)
2491 if (count > 0)
2493 s = format_gcov (count, 0, -1);
2494 if (has_unexecuted_block)
2496 if (flag_use_colors)
2498 pad_count_string (s);
2499 s = SGR_SEQ (COLOR_BG_MAGENTA COLOR_SEPARATOR COLOR_FG_WHITE);
2500 s += SGR_RESET;
2502 else
2503 s += "*";
2505 pad_count_string (s);
2507 else
2509 if (flag_use_colors)
2511 s = "0";
2512 pad_count_string (s);
2513 if (unexceptional)
2514 s.insert (0, SGR_SEQ (COLOR_BG_RED
2515 COLOR_SEPARATOR COLOR_FG_WHITE));
2516 else
2517 s.insert (0, SGR_SEQ (COLOR_BG_CYAN
2518 COLOR_SEPARATOR COLOR_FG_WHITE));
2519 s += SGR_RESET;
2521 else
2523 s = unexceptional ? unexceptional_string : exceptional_string;
2524 pad_count_string (s);
2528 else
2530 s = "-";
2531 pad_count_string (s);
2534 fprintf (f, "%s:%5u", s.c_str (), line_num);
2537 /* Read in the source file one line at a time, and output that line to
2538 the gcov file preceded by its execution count and other
2539 information. */
2541 static void
2542 output_lines (FILE *gcov_file, const source_t *src)
2544 #define DEFAULT_LINE_START " -: 0:"
2546 FILE *source_file;
2547 unsigned line_num; /* current line number. */
2548 const line_t *line; /* current line info ptr. */
2549 const char *retval = ""; /* status of source file reading. */
2550 function_t *fn = NULL;
2552 fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
2553 if (!multiple_files)
2555 fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
2556 fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
2557 no_data_file ? "-" : da_file_name);
2558 fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
2560 fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
2562 source_file = fopen (src->name, "r");
2563 if (!source_file)
2565 fnotice (stderr, "Cannot open source file %s\n", src->name);
2566 retval = NULL;
2568 else if (src->file_time == 0)
2569 fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
2571 if (flag_branches)
2572 fn = src->functions;
2574 for (line_num = 1, line = &src->lines[line_num];
2575 line_num < src->num_lines; line_num++, line++)
2577 for (; fn && fn->line == line_num; fn = fn->next_file_fn)
2579 arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
2580 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2581 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2583 for (; arc; arc = arc->pred_next)
2584 if (arc->fake)
2585 return_count -= arc->count;
2587 fprintf (gcov_file, "function %s", flag_demangled_names ?
2588 fn->demangled_name : fn->name);
2589 fprintf (gcov_file, " called %s",
2590 format_gcov (called_count, 0, -1));
2591 fprintf (gcov_file, " returned %s",
2592 format_gcov (return_count, called_count, 0));
2593 fprintf (gcov_file, " blocks executed %s",
2594 format_gcov (fn->blocks_executed, fn->blocks.size () - 2,
2595 0));
2596 fprintf (gcov_file, "\n");
2599 if (retval)
2600 retval = read_line (source_file);
2602 /* For lines which don't exist in the .bb file, print '-' before
2603 the source line. For lines which exist but were never
2604 executed, print '#####' or '=====' before the source line.
2605 Otherwise, print the execution count before the source line.
2606 There are 16 spaces of indentation added before the source
2607 line so that tabs won't be messed up. */
2608 output_line_beginning (gcov_file, line->exists, line->unexceptional,
2609 line->has_unexecuted_block, line->count, line_num,
2610 "=====", "#####");
2611 fprintf (gcov_file, ":%s\n", retval ? retval : "/*EOF*/");
2613 if (flag_all_blocks)
2615 block_t *block;
2616 arc_t *arc;
2617 int ix, jx;
2619 for (ix = jx = 0, block = line->blocks; block;
2620 block = block->chain)
2622 if (!block->is_call_return)
2624 output_line_beginning (gcov_file, line->exists,
2625 block->exceptional, false,
2626 block->count, line_num,
2627 "%%%%%", "$$$$$");
2628 fprintf (gcov_file, "-block %2d", ix++);
2629 if (flag_verbose)
2630 fprintf (gcov_file, " (BB %u)", block->id);
2631 fprintf (gcov_file, "\n");
2633 if (flag_branches)
2634 for (arc = block->succ; arc; arc = arc->succ_next)
2635 jx += output_branch_count (gcov_file, jx, arc);
2638 else if (flag_branches)
2640 int ix;
2641 arc_t *arc;
2643 for (ix = 0, arc = line->branches; arc; arc = arc->line_next)
2644 ix += output_branch_count (gcov_file, ix, arc);
2648 /* Handle all remaining source lines. There may be lines after the
2649 last line of code. */
2650 if (retval)
2652 for (; (retval = read_line (source_file)); line_num++)
2653 fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
2656 if (source_file)
2657 fclose (source_file);