Simplify gcov_histogram as it's used only for ARCS counters.
[official-gcc.git] / gcc / gcov.c
blob2114a43d14082171783fa3db00f0d574807004d0
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990-2018 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 #define INCLUDE_MAP
38 #define INCLUDE_SET
39 #include "system.h"
40 #include "coretypes.h"
41 #include "tm.h"
42 #include "intl.h"
43 #include "diagnostic.h"
44 #include "version.h"
45 #include "demangle.h"
46 #include "color-macros.h"
48 #include <getopt.h>
50 #include "md5.h"
52 using namespace std;
54 #define IN_GCOV 1
55 #include "gcov-io.h"
56 #include "gcov-io.c"
58 /* The gcno file is generated by -ftest-coverage option. The gcda file is
59 generated by a program compiled with -fprofile-arcs. Their formats
60 are documented in gcov-io.h. */
62 /* The functions in this file for creating and solution program flow graphs
63 are very similar to functions in the gcc source file profile.c. In
64 some places we make use of the knowledge of how profile.c works to
65 select particular algorithms here. */
67 /* The code validates that the profile information read in corresponds
68 to the code currently being compiled. Rather than checking for
69 identical files, the code below compares a checksum on the CFG
70 (based on the order of basic blocks and the arcs in the CFG). If
71 the CFG checksum in the gcda file match the CFG checksum in the
72 gcno file, the profile data will be used. */
74 /* This is the size of the buffer used to read in source file lines. */
76 struct function_info;
77 struct block_info;
78 struct source_info;
80 /* Describes an arc between two basic blocks. */
82 struct arc_info
84 /* source and destination blocks. */
85 struct block_info *src;
86 struct block_info *dst;
88 /* transition counts. */
89 gcov_type count;
90 /* used in cycle search, so that we do not clobber original counts. */
91 gcov_type cs_count;
93 unsigned int count_valid : 1;
94 unsigned int on_tree : 1;
95 unsigned int fake : 1;
96 unsigned int fall_through : 1;
98 /* Arc to a catch handler. */
99 unsigned int is_throw : 1;
101 /* Arc is for a function that abnormally returns. */
102 unsigned int is_call_non_return : 1;
104 /* Arc is for catch/setjmp. */
105 unsigned int is_nonlocal_return : 1;
107 /* Is an unconditional branch. */
108 unsigned int is_unconditional : 1;
110 /* Loop making arc. */
111 unsigned int cycle : 1;
113 /* Links to next arc on src and dst lists. */
114 struct arc_info *succ_next;
115 struct arc_info *pred_next;
118 /* Describes which locations (lines and files) are associated with
119 a basic block. */
121 struct block_location_info
123 block_location_info (unsigned _source_file_idx):
124 source_file_idx (_source_file_idx)
127 unsigned source_file_idx;
128 vector<unsigned> lines;
131 /* Describes a basic block. Contains lists of arcs to successor and
132 predecessor blocks. */
134 struct block_info
136 /* Constructor. */
137 block_info ();
139 /* Chain of exit and entry arcs. */
140 arc_info *succ;
141 arc_info *pred;
143 /* Number of unprocessed exit and entry arcs. */
144 gcov_type num_succ;
145 gcov_type num_pred;
147 unsigned id;
149 /* Block execution count. */
150 gcov_type count;
151 unsigned count_valid : 1;
152 unsigned valid_chain : 1;
153 unsigned invalid_chain : 1;
154 unsigned exceptional : 1;
156 /* Block is a call instrumenting site. */
157 unsigned is_call_site : 1; /* Does the call. */
158 unsigned is_call_return : 1; /* Is the return. */
160 /* Block is a landing pad for longjmp or throw. */
161 unsigned is_nonlocal_return : 1;
163 vector<block_location_info> locations;
165 struct
167 /* Single line graph cycle workspace. Used for all-blocks
168 mode. */
169 arc_info *arc;
170 unsigned ident;
171 } cycle; /* Used in all-blocks mode, after blocks are linked onto
172 lines. */
174 /* Temporary chain for solving graph, and for chaining blocks on one
175 line. */
176 struct block_info *chain;
180 block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
181 id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
182 exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
183 locations (), chain (NULL)
185 cycle.arc = NULL;
188 /* Describes a single line of source. Contains a chain of basic blocks
189 with code on it. */
191 struct line_info
193 /* Default constructor. */
194 line_info ();
196 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
197 bool has_block (block_info *needle);
199 /* Execution count. */
200 gcov_type count;
202 /* Branches from blocks that end on this line. */
203 vector<arc_info *> branches;
205 /* blocks which start on this line. Used in all-blocks mode. */
206 vector<block_info *> blocks;
208 unsigned exists : 1;
209 unsigned unexceptional : 1;
210 unsigned has_unexecuted_block : 1;
213 line_info::line_info (): count (0), branches (), blocks (), exists (false),
214 unexceptional (0), has_unexecuted_block (0)
218 bool
219 line_info::has_block (block_info *needle)
221 return std::find (blocks.begin (), blocks.end (), needle) != blocks.end ();
224 /* Describes a single function. Contains an array of basic blocks. */
226 struct function_info
228 function_info ();
229 ~function_info ();
231 /* Return true when line N belongs to the function in source file SRC_IDX.
232 The line must be defined in body of the function, can't be inlined. */
233 bool group_line_p (unsigned n, unsigned src_idx);
235 /* Function filter based on function_info::artificial variable. */
237 static inline bool
238 is_artificial (function_info *fn)
240 return fn->artificial;
243 /* Name of function. */
244 char *name;
245 char *demangled_name;
246 unsigned ident;
247 unsigned lineno_checksum;
248 unsigned cfg_checksum;
250 /* The graph contains at least one fake incoming edge. */
251 unsigned has_catch : 1;
253 /* True when the function is artificial and does not exist
254 in a source file. */
255 unsigned artificial : 1;
257 /* True when multiple functions start at a line in a source file. */
258 unsigned is_group : 1;
260 /* Array of basic blocks. Like in GCC, the entry block is
261 at blocks[0] and the exit block is at blocks[1]. */
262 #define ENTRY_BLOCK (0)
263 #define EXIT_BLOCK (1)
264 vector<block_info> blocks;
265 unsigned blocks_executed;
267 /* Raw arc coverage counts. */
268 vector<gcov_type> counts;
270 /* First line number. */
271 unsigned start_line;
273 /* First line column. */
274 unsigned start_column;
276 /* Last line number. */
277 unsigned end_line;
279 /* Index of source file where the function is defined. */
280 unsigned src;
282 /* Vector of line information. */
283 vector<line_info> lines;
285 /* Next function. */
286 struct function_info *next;
289 /* Function info comparer that will sort functions according to starting
290 line. */
292 struct function_line_start_cmp
294 inline bool operator() (const function_info *lhs,
295 const function_info *rhs)
297 return (lhs->start_line == rhs->start_line
298 ? lhs->start_column < rhs->start_column
299 : lhs->start_line < rhs->start_line);
303 /* Describes coverage of a file or function. */
305 struct coverage_info
307 int lines;
308 int lines_executed;
310 int branches;
311 int branches_executed;
312 int branches_taken;
314 int calls;
315 int calls_executed;
317 char *name;
320 /* Describes a file mentioned in the block graph. Contains an array
321 of line info. */
323 struct source_info
325 /* Default constructor. */
326 source_info ();
328 vector<function_info *> get_functions_at_location (unsigned line_num) const;
330 /* Index of the source_info in sources vector. */
331 unsigned index;
333 /* Canonical name of source file. */
334 char *name;
335 time_t file_time;
337 /* Vector of line information. */
338 vector<line_info> lines;
340 coverage_info coverage;
342 /* Functions in this source file. These are in ascending line
343 number order. */
344 vector <function_info *> functions;
347 source_info::source_info (): index (0), name (NULL), file_time (),
348 lines (), coverage (), functions ()
352 vector<function_info *>
353 source_info::get_functions_at_location (unsigned line_num) const
355 vector<function_info *> r;
357 for (vector<function_info *>::const_iterator it = functions.begin ();
358 it != functions.end (); it++)
360 if ((*it)->start_line == line_num && (*it)->src == index)
361 r.push_back (*it);
364 std::sort (r.begin (), r.end (), function_line_start_cmp ());
366 return r;
369 class name_map
371 public:
372 name_map ()
376 name_map (char *_name, unsigned _src): name (_name), src (_src)
380 bool operator== (const name_map &rhs) const
382 #if HAVE_DOS_BASED_FILE_SYSTEM
383 return strcasecmp (this->name, rhs.name) == 0;
384 #else
385 return strcmp (this->name, rhs.name) == 0;
386 #endif
389 bool operator< (const name_map &rhs) const
391 #if HAVE_DOS_BASED_FILE_SYSTEM
392 return strcasecmp (this->name, rhs.name) < 0;
393 #else
394 return strcmp (this->name, rhs.name) < 0;
395 #endif
398 const char *name; /* Source file name */
399 unsigned src; /* Source file */
402 /* Vector of all functions. */
403 static vector<function_info *> functions;
405 /* Vector of source files. */
406 static vector<source_info> sources;
408 /* Mapping of file names to sources */
409 static vector<name_map> names;
411 /* This holds data summary information. */
413 static unsigned object_runs;
414 static unsigned program_count;
416 static unsigned total_lines;
417 static unsigned total_executed;
419 /* Modification time of graph file. */
421 static time_t bbg_file_time;
423 /* Name of the notes (gcno) output file. The "bbg" prefix is for
424 historical reasons, when the notes file contained only the
425 basic block graph notes. */
427 static char *bbg_file_name;
429 /* Stamp of the bbg file */
430 static unsigned bbg_stamp;
432 /* Supports has_unexecuted_blocks functionality. */
433 static unsigned bbg_supports_has_unexecuted_blocks;
435 /* Working directory in which a TU was compiled. */
436 static const char *bbg_cwd;
438 /* Name and file pointer of the input file for the count data (gcda). */
440 static char *da_file_name;
442 /* Data file is missing. */
444 static int no_data_file;
446 /* If there is several input files, compute and display results after
447 reading all data files. This way if two or more gcda file refer to
448 the same source file (eg inline subprograms in a .h file), the
449 counts are added. */
451 static int multiple_files = 0;
453 /* Output branch probabilities. */
455 static int flag_branches = 0;
457 /* Show unconditional branches too. */
458 static int flag_unconditional = 0;
460 /* Output a gcov file if this is true. This is on by default, and can
461 be turned off by the -n option. */
463 static int flag_gcov_file = 1;
465 /* Output to stdout instead to a gcov file. */
467 static int flag_use_stdout = 0;
469 /* Output progress indication if this is true. This is off by default
470 and can be turned on by the -d option. */
472 static int flag_display_progress = 0;
474 /* Output *.gcov file in intermediate format used by 'lcov'. */
476 static int flag_intermediate_format = 0;
478 /* Output demangled function names. */
480 static int flag_demangled_names = 0;
482 /* For included files, make the gcov output file name include the name
483 of the input source file. For example, if x.h is included in a.c,
484 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
486 static int flag_long_names = 0;
488 /* For situations when a long name can potentially hit filesystem path limit,
489 let's calculate md5sum of the path and append it to a file name. */
491 static int flag_hash_filenames = 0;
493 /* Print verbose informations. */
495 static int flag_verbose = 0;
497 /* Print colored output. */
499 static int flag_use_colors = 0;
501 /* Output count information for every basic block, not merely those
502 that contain line number information. */
504 static int flag_all_blocks = 0;
506 /* Output human readable numbers. */
508 static int flag_human_readable_numbers = 0;
510 /* Output summary info for each function. */
512 static int flag_function_summary = 0;
514 /* Object directory file prefix. This is the directory/file where the
515 graph and data files are looked for, if nonzero. */
517 static char *object_directory = 0;
519 /* Source directory prefix. This is removed from source pathnames
520 that match, when generating the output file name. */
522 static char *source_prefix = 0;
523 static size_t source_length = 0;
525 /* Only show data for sources with relative pathnames. Absolute ones
526 usually indicate a system header file, which although it may
527 contain inline functions, is usually uninteresting. */
528 static int flag_relative_only = 0;
530 /* Preserve all pathname components. Needed when object files and
531 source files are in subdirectories. '/' is mangled as '#', '.' is
532 elided and '..' mangled to '^'. */
534 static int flag_preserve_paths = 0;
536 /* Output the number of times a branch was taken as opposed to the percentage
537 of times it was taken. */
539 static int flag_counts = 0;
541 /* Forward declarations. */
542 static int process_args (int, char **);
543 static void print_usage (int) ATTRIBUTE_NORETURN;
544 static void print_version (void) ATTRIBUTE_NORETURN;
545 static void process_file (const char *);
546 static void generate_results (const char *);
547 static void create_file_names (const char *);
548 static char *canonicalize_name (const char *);
549 static unsigned find_source (const char *);
550 static void read_graph_file (void);
551 static int read_count_file (void);
552 static void solve_flow_graph (function_info *);
553 static void find_exception_blocks (function_info *);
554 static void add_branch_counts (coverage_info *, const arc_info *);
555 static void add_line_counts (coverage_info *, function_info *);
556 static void executed_summary (unsigned, unsigned);
557 static void function_summary (const coverage_info *, const char *);
558 static const char *format_gcov (gcov_type, gcov_type, int);
559 static void accumulate_line_counts (source_info *);
560 static void output_gcov_file (const char *, source_info *);
561 static int output_branch_count (FILE *, int, const arc_info *);
562 static void output_lines (FILE *, const source_info *);
563 static char *make_gcov_file_name (const char *, const char *);
564 static char *mangle_name (const char *, char *);
565 static void release_structures (void);
566 extern int main (int, char **);
568 function_info::function_info (): name (NULL), demangled_name (NULL),
569 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
570 artificial (0), is_group (0),
571 blocks (), blocks_executed (0), counts (),
572 start_line (0), start_column (), end_line (0), src (0), lines (), next (NULL)
576 function_info::~function_info ()
578 for (int i = blocks.size () - 1; i >= 0; i--)
580 arc_info *arc, *arc_n;
582 for (arc = blocks[i].succ; arc; arc = arc_n)
584 arc_n = arc->succ_next;
585 free (arc);
588 if (flag_demangled_names && demangled_name != name)
589 free (demangled_name);
590 free (name);
593 bool function_info::group_line_p (unsigned n, unsigned src_idx)
595 return is_group && src == src_idx && start_line <= n && n <= end_line;
598 /* Cycle detection!
599 There are a bajillion algorithms that do this. Boost's function is named
600 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
601 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
602 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
604 The basic algorithm is simple: effectively, we're finding all simple paths
605 in a subgraph (that shrinks every iteration). Duplicates are filtered by
606 "blocking" a path when a node is added to the path (this also prevents non-
607 simple paths)--the node is unblocked only when it participates in a cycle.
610 typedef vector<arc_info *> arc_vector_t;
611 typedef vector<const block_info *> block_vector_t;
613 /* Enum with types of loop in CFG. */
615 enum loop_type
617 NO_LOOP = 0,
618 LOOP = 1,
619 NEGATIVE_LOOP = 3
622 /* Loop_type operator that merges two values: A and B. */
624 inline loop_type& operator |= (loop_type& a, loop_type b)
626 return a = static_cast<loop_type> (a | b);
629 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
630 and subtract the value from all counts. The subtracted value is added
631 to COUNT. Returns type of loop. */
633 static loop_type
634 handle_cycle (const arc_vector_t &edges, int64_t &count)
636 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
637 that amount. */
638 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
639 for (unsigned i = 0; i < edges.size (); i++)
641 int64_t ecount = edges[i]->cs_count;
642 if (cycle_count > ecount)
643 cycle_count = ecount;
645 count += cycle_count;
646 for (unsigned i = 0; i < edges.size (); i++)
647 edges[i]->cs_count -= cycle_count;
649 return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
652 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
653 blocked by U in BLOCK_LISTS. */
655 static void
656 unblock (const block_info *u, block_vector_t &blocked,
657 vector<block_vector_t > &block_lists)
659 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
660 if (it == blocked.end ())
661 return;
663 unsigned index = it - blocked.begin ();
664 blocked.erase (it);
666 block_vector_t to_unblock (block_lists[index]);
668 block_lists.erase (block_lists.begin () + index);
670 for (block_vector_t::iterator it = to_unblock.begin ();
671 it != to_unblock.end (); it++)
672 unblock (*it, blocked, block_lists);
675 /* Find circuit going to block V, PATH is provisional seen cycle.
676 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
677 blocked by a block. COUNT is accumulated count of the current LINE.
678 Returns what type of loop it contains. */
680 static loop_type
681 circuit (block_info *v, arc_vector_t &path, block_info *start,
682 block_vector_t &blocked, vector<block_vector_t> &block_lists,
683 line_info &linfo, int64_t &count)
685 loop_type result = NO_LOOP;
687 /* Add v to the block list. */
688 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
689 blocked.push_back (v);
690 block_lists.push_back (block_vector_t ());
692 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
694 block_info *w = arc->dst;
695 if (w < start || !linfo.has_block (w))
696 continue;
698 path.push_back (arc);
699 if (w == start)
700 /* Cycle has been found. */
701 result |= handle_cycle (path, count);
702 else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
703 result |= circuit (w, path, start, blocked, block_lists, linfo, count);
705 path.pop_back ();
708 if (result != NO_LOOP)
709 unblock (v, blocked, block_lists);
710 else
711 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
713 block_info *w = arc->dst;
714 if (w < start || !linfo.has_block (w))
715 continue;
717 size_t index
718 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
719 gcc_assert (index < blocked.size ());
720 block_vector_t &list = block_lists[index];
721 if (find (list.begin (), list.end (), v) == list.end ())
722 list.push_back (v);
725 return result;
728 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
729 contains a negative loop, then perform the same function once again. */
731 static gcov_type
732 get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
734 /* Note that this algorithm works even if blocks aren't in sorted order.
735 Each iteration of the circuit detection is completely independent
736 (except for reducing counts, but that shouldn't matter anyways).
737 Therefore, operating on a permuted order (i.e., non-sorted) only
738 has the effect of permuting the output cycles. */
740 loop_type result = NO_LOOP;
741 gcov_type count = 0;
742 for (vector<block_info *>::iterator it = linfo.blocks.begin ();
743 it != linfo.blocks.end (); it++)
745 arc_vector_t path;
746 block_vector_t blocked;
747 vector<block_vector_t > block_lists;
748 result |= circuit (*it, path, *it, blocked, block_lists, linfo,
749 count);
752 /* If we have a negative cycle, repeat the find_cycles routine. */
753 if (result == NEGATIVE_LOOP && handle_negative_cycles)
754 count += get_cycles_count (linfo, false);
756 return count;
760 main (int argc, char **argv)
762 int argno;
763 int first_arg;
764 const char *p;
766 p = argv[0] + strlen (argv[0]);
767 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
768 --p;
769 progname = p;
771 xmalloc_set_program_name (progname);
773 /* Unlock the stdio streams. */
774 unlock_std_streams ();
776 gcc_init_libintl ();
778 diagnostic_initialize (global_dc, 0);
780 /* Handle response files. */
781 expandargv (&argc, &argv);
783 argno = process_args (argc, argv);
784 if (optind == argc)
785 print_usage (true);
787 if (argc - argno > 1)
788 multiple_files = 1;
790 first_arg = argno;
792 for (; argno != argc; argno++)
794 if (flag_display_progress)
795 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
796 argc - first_arg);
797 process_file (argv[argno]);
799 if (flag_intermediate_format || argno == argc - 1)
801 generate_results (argv[argno]);
802 release_structures ();
806 return 0;
809 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
810 otherwise the output of --help. */
812 static void
813 print_usage (int error_p)
815 FILE *file = error_p ? stderr : stdout;
816 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
818 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
819 fnotice (file, "Print code coverage information.\n\n");
820 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
821 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
822 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
823 rather than percentages\n");
824 fnotice (file, " -d, --display-progress Display progress information\n");
825 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
826 fnotice (file, " -h, --help Print this help, then exit\n");
827 fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
828 fnotice (file, " -j, --human-readable Output human readable numbers\n");
829 fnotice (file, " -k, --use-colors Emit colored output\n");
830 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
831 source files\n");
832 fnotice (file, " -m, --demangled-names Output demangled function names\n");
833 fnotice (file, " -n, --no-output Do not create an output file\n");
834 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
835 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
836 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
837 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
838 fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
839 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
840 fnotice (file, " -v, --version Print version number, then exit\n");
841 fnotice (file, " -w, --verbose Print verbose informations\n");
842 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
843 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
844 bug_report_url);
845 exit (status);
848 /* Print version information and exit. */
850 static void
851 print_version (void)
853 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
854 fprintf (stdout, "Copyright %s 2018 Free Software Foundation, Inc.\n",
855 _("(C)"));
856 fnotice (stdout,
857 _("This is free software; see the source for copying conditions.\n"
858 "There is NO warranty; not even for MERCHANTABILITY or \n"
859 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
860 exit (SUCCESS_EXIT_CODE);
863 static const struct option options[] =
865 { "help", no_argument, NULL, 'h' },
866 { "version", no_argument, NULL, 'v' },
867 { "verbose", no_argument, NULL, 'w' },
868 { "all-blocks", no_argument, NULL, 'a' },
869 { "branch-probabilities", no_argument, NULL, 'b' },
870 { "branch-counts", no_argument, NULL, 'c' },
871 { "intermediate-format", no_argument, NULL, 'i' },
872 { "human-readable", no_argument, NULL, 'j' },
873 { "no-output", no_argument, NULL, 'n' },
874 { "long-file-names", no_argument, NULL, 'l' },
875 { "function-summaries", no_argument, NULL, 'f' },
876 { "demangled-names", no_argument, NULL, 'm' },
877 { "preserve-paths", no_argument, NULL, 'p' },
878 { "relative-only", no_argument, NULL, 'r' },
879 { "object-directory", required_argument, NULL, 'o' },
880 { "object-file", required_argument, NULL, 'o' },
881 { "source-prefix", required_argument, NULL, 's' },
882 { "stdout", no_argument, NULL, 't' },
883 { "unconditional-branches", no_argument, NULL, 'u' },
884 { "display-progress", no_argument, NULL, 'd' },
885 { "hash-filenames", no_argument, NULL, 'x' },
886 { "use-colors", no_argument, NULL, 'k' },
887 { 0, 0, 0, 0 }
890 /* Process args, return index to first non-arg. */
892 static int
893 process_args (int argc, char **argv)
895 int opt;
897 const char *opts = "abcdfhijklmno:prs:tuvwx";
898 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
900 switch (opt)
902 case 'a':
903 flag_all_blocks = 1;
904 break;
905 case 'b':
906 flag_branches = 1;
907 break;
908 case 'c':
909 flag_counts = 1;
910 break;
911 case 'f':
912 flag_function_summary = 1;
913 break;
914 case 'h':
915 print_usage (false);
916 /* print_usage will exit. */
917 case 'l':
918 flag_long_names = 1;
919 break;
920 case 'j':
921 flag_human_readable_numbers = 1;
922 break;
923 case 'k':
924 flag_use_colors = 1;
925 break;
926 case 'm':
927 flag_demangled_names = 1;
928 break;
929 case 'n':
930 flag_gcov_file = 0;
931 break;
932 case 'o':
933 object_directory = optarg;
934 break;
935 case 's':
936 source_prefix = optarg;
937 source_length = strlen (source_prefix);
938 break;
939 case 'r':
940 flag_relative_only = 1;
941 break;
942 case 'p':
943 flag_preserve_paths = 1;
944 break;
945 case 'u':
946 flag_unconditional = 1;
947 break;
948 case 'i':
949 flag_intermediate_format = 1;
950 flag_gcov_file = 1;
951 break;
952 case 'd':
953 flag_display_progress = 1;
954 break;
955 case 'x':
956 flag_hash_filenames = 1;
957 break;
958 case 'w':
959 flag_verbose = 1;
960 break;
961 case 't':
962 flag_use_stdout = 1;
963 break;
964 case 'v':
965 print_version ();
966 /* print_version will exit. */
967 default:
968 print_usage (true);
969 /* print_usage will exit. */
973 return optind;
976 /* Output intermediate LINE sitting on LINE_NUM to output file F. */
978 static void
979 output_intermediate_line (FILE *f, line_info *line, unsigned line_num)
981 if (!line->exists)
982 return;
984 fprintf (f, "lcount:%u,%s,%d\n", line_num,
985 format_gcov (line->count, 0, -1),
986 line->has_unexecuted_block);
988 vector<arc_info *>::const_iterator it;
989 if (flag_branches)
990 for (it = line->branches.begin (); it != line->branches.end ();
991 it++)
993 if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
995 const char *branch_type;
996 /* branch:<line_num>,<branch_coverage_infoype>
997 branch_coverage_infoype
998 : notexec (Branch not executed)
999 : taken (Branch executed and taken)
1000 : nottaken (Branch executed, but not taken)
1002 if ((*it)->src->count)
1003 branch_type
1004 = ((*it)->count > 0) ? "taken" : "nottaken";
1005 else
1006 branch_type = "notexec";
1007 fprintf (f, "branch:%d,%s\n", line_num, branch_type);
1012 /* Get the name of the gcov file. The return value must be free'd.
1014 It appends the '.gcov' extension to the *basename* of the file.
1015 The resulting file name will be in PWD.
1017 e.g.,
1018 input: foo.da, output: foo.da.gcov
1019 input: a/b/foo.cc, output: foo.cc.gcov */
1021 static char *
1022 get_gcov_intermediate_filename (const char *file_name)
1024 const char *gcov = ".gcov";
1025 char *result;
1026 const char *cptr;
1028 /* Find the 'basename'. */
1029 cptr = lbasename (file_name);
1031 result = XNEWVEC (char, strlen (cptr) + strlen (gcov) + 1);
1032 sprintf (result, "%s%s", cptr, gcov);
1034 return result;
1037 /* Output the result in intermediate format used by 'lcov'.
1039 The intermediate format contains a single file named 'foo.cc.gcov',
1040 with no source code included.
1042 The default gcov outputs multiple files: 'foo.cc.gcov',
1043 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
1044 included. Instead the intermediate format here outputs only a single
1045 file 'foo.cc.gcov' similar to the above example. */
1047 static void
1048 output_intermediate_file (FILE *gcov_file, source_info *src)
1050 fprintf (gcov_file, "version:%s\n", version_string);
1051 fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
1052 fprintf (gcov_file, "cwd:%s\n", bbg_cwd);
1054 std::sort (src->functions.begin (), src->functions.end (),
1055 function_line_start_cmp ());
1056 for (vector<function_info *>::iterator it = src->functions.begin ();
1057 it != src->functions.end (); it++)
1059 /* function:<name>,<line_number>,<execution_count> */
1060 fprintf (gcov_file, "function:%d,%d,%s,%s\n", (*it)->start_line,
1061 (*it)->end_line, format_gcov ((*it)->blocks[0].count, 0, -1),
1062 flag_demangled_names ? (*it)->demangled_name : (*it)->name);
1065 for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
1067 vector<function_info *> fns = src->get_functions_at_location (line_num);
1069 /* Print first group functions that begin on the line. */
1070 for (vector<function_info *>::iterator it2 = fns.begin ();
1071 it2 != fns.end (); it2++)
1073 vector<line_info> &lines = (*it2)->lines;
1074 for (unsigned i = 0; i < lines.size (); i++)
1076 line_info *line = &lines[i];
1077 output_intermediate_line (gcov_file, line, line_num + i);
1081 /* Follow with lines associated with the source file. */
1082 output_intermediate_line (gcov_file, &src->lines[line_num], line_num);
1086 /* Function start pair. */
1087 struct function_start
1089 unsigned source_file_idx;
1090 unsigned start_line;
1093 /* Traits class for function start hash maps below. */
1095 struct function_start_pair_hash : typed_noop_remove <function_start>
1097 typedef function_start value_type;
1098 typedef function_start compare_type;
1100 static hashval_t
1101 hash (const function_start &ref)
1103 inchash::hash hstate (0);
1104 hstate.add_int (ref.source_file_idx);
1105 hstate.add_int (ref.start_line);
1106 return hstate.end ();
1109 static bool
1110 equal (const function_start &ref1, const function_start &ref2)
1112 return (ref1.source_file_idx == ref2.source_file_idx
1113 && ref1.start_line == ref2.start_line);
1116 static void
1117 mark_deleted (function_start &ref)
1119 ref.start_line = ~1U;
1122 static void
1123 mark_empty (function_start &ref)
1125 ref.start_line = ~2U;
1128 static bool
1129 is_deleted (const function_start &ref)
1131 return ref.start_line == ~1U;
1134 static bool
1135 is_empty (const function_start &ref)
1137 return ref.start_line == ~2U;
1141 /* Process a single input file. */
1143 static void
1144 process_file (const char *file_name)
1146 create_file_names (file_name);
1147 read_graph_file ();
1148 if (functions.empty ())
1149 return;
1151 read_count_file ();
1153 hash_map<function_start_pair_hash, function_info *> fn_map;
1155 /* Identify group functions. */
1156 for (vector<function_info *>::iterator it = functions.begin ();
1157 it != functions.end (); it++)
1158 if (!(*it)->artificial)
1160 function_start needle;
1161 needle.source_file_idx = (*it)->src;
1162 needle.start_line = (*it)->start_line;
1164 function_info **slot = fn_map.get (needle);
1165 if (slot)
1167 (*slot)->is_group = 1;
1168 (*it)->is_group = 1;
1170 else
1171 fn_map.put (needle, *it);
1174 /* Remove all artificial function. */
1175 functions.erase (remove_if (functions.begin (), functions.end (),
1176 function_info::is_artificial), functions.end ());
1178 for (vector<function_info *>::iterator it = functions.begin ();
1179 it != functions.end (); it++)
1181 function_info *fn = *it;
1182 unsigned src = fn->src;
1184 if (!fn->counts.empty () || no_data_file)
1186 source_info *s = &sources[src];
1187 s->functions.push_back (fn);
1189 /* Mark last line in files touched by function. */
1190 for (unsigned block_no = 0; block_no != fn->blocks.size ();
1191 block_no++)
1193 block_info *block = &fn->blocks[block_no];
1194 for (unsigned i = 0; i < block->locations.size (); i++)
1196 /* Sort lines of locations. */
1197 sort (block->locations[i].lines.begin (),
1198 block->locations[i].lines.end ());
1200 if (!block->locations[i].lines.empty ())
1202 s = &sources[block->locations[i].source_file_idx];
1203 unsigned last_line
1204 = block->locations[i].lines.back ();
1206 /* Record new lines for the function. */
1207 if (last_line >= s->lines.size ())
1209 s = &sources[block->locations[i].source_file_idx];
1210 unsigned last_line
1211 = block->locations[i].lines.back ();
1213 /* Record new lines for the function. */
1214 if (last_line >= s->lines.size ())
1216 /* Record new lines for a source file. */
1217 s->lines.resize (last_line + 1);
1224 /* Allocate lines for group function, following start_line
1225 and end_line information of the function. */
1226 if (fn->is_group)
1227 fn->lines.resize (fn->end_line - fn->start_line + 1);
1230 solve_flow_graph (fn);
1231 if (fn->has_catch)
1232 find_exception_blocks (fn);
1234 else
1236 /* The function was not in the executable -- some other
1237 instance must have been selected. */
1242 static void
1243 output_gcov_file (const char *file_name, source_info *src)
1245 char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
1247 if (src->coverage.lines)
1249 FILE *gcov_file = fopen (gcov_file_name, "w");
1250 if (gcov_file)
1252 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
1253 output_lines (gcov_file, src);
1254 if (ferror (gcov_file))
1255 fnotice (stderr, "Error writing output file '%s'\n",
1256 gcov_file_name);
1257 fclose (gcov_file);
1259 else
1260 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1262 else
1264 unlink (gcov_file_name);
1265 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1267 free (gcov_file_name);
1270 static void
1271 generate_results (const char *file_name)
1273 FILE *gcov_intermediate_file = NULL;
1274 char *gcov_intermediate_filename = NULL;
1276 for (vector<function_info *>::iterator it = functions.begin ();
1277 it != functions.end (); it++)
1279 function_info *fn = *it;
1280 coverage_info coverage;
1282 memset (&coverage, 0, sizeof (coverage));
1283 coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
1284 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1285 if (flag_function_summary)
1287 function_summary (&coverage, "Function");
1288 fnotice (stdout, "\n");
1292 name_map needle;
1294 if (file_name)
1296 needle.name = file_name;
1297 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1298 needle);
1299 if (it != names.end ())
1300 file_name = sources[it->src].coverage.name;
1301 else
1302 file_name = canonicalize_name (file_name);
1305 if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout)
1307 /* Open the intermediate file. */
1308 gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
1309 gcov_intermediate_file = fopen (gcov_intermediate_filename, "w");
1310 if (!gcov_intermediate_file)
1312 fnotice (stderr, "Cannot open intermediate output file %s\n",
1313 gcov_intermediate_filename);
1314 return;
1318 for (vector<source_info>::iterator it = sources.begin ();
1319 it != sources.end (); it++)
1321 source_info *src = &(*it);
1322 if (flag_relative_only)
1324 /* Ignore this source, if it is an absolute path (after
1325 source prefix removal). */
1326 char first = src->coverage.name[0];
1328 #if HAVE_DOS_BASED_FILE_SYSTEM
1329 if (first && src->coverage.name[1] == ':')
1330 first = src->coverage.name[2];
1331 #endif
1332 if (IS_DIR_SEPARATOR (first))
1333 continue;
1336 accumulate_line_counts (src);
1338 if (!flag_use_stdout)
1339 function_summary (&src->coverage, "File");
1340 total_lines += src->coverage.lines;
1341 total_executed += src->coverage.lines_executed;
1342 if (flag_gcov_file)
1344 if (flag_intermediate_format)
1345 /* Output the intermediate format without requiring source
1346 files. This outputs a section to a *single* file. */
1347 output_intermediate_file ((flag_use_stdout
1348 ? stdout : gcov_intermediate_file), src);
1349 else
1351 if (flag_use_stdout)
1353 if (src->coverage.lines)
1354 output_lines (stdout, src);
1356 else
1358 output_gcov_file (file_name, src);
1359 fnotice (stdout, "\n");
1365 if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout)
1367 /* Now we've finished writing the intermediate file. */
1368 fclose (gcov_intermediate_file);
1369 XDELETEVEC (gcov_intermediate_filename);
1372 if (!file_name)
1373 executed_summary (total_lines, total_executed);
1376 /* Release all memory used. */
1378 static void
1379 release_structures (void)
1381 for (vector<function_info *>::iterator it = functions.begin ();
1382 it != functions.end (); it++)
1383 delete (*it);
1385 sources.resize (0);
1386 names.resize (0);
1387 functions.resize (0);
1390 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1391 is not specified, these are named from FILE_NAME sans extension. If
1392 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1393 directory, but named from the basename of the FILE_NAME, sans extension.
1394 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1395 and the data files are named from that. */
1397 static void
1398 create_file_names (const char *file_name)
1400 char *cptr;
1401 char *name;
1402 int length = strlen (file_name);
1403 int base;
1405 /* Free previous file names. */
1406 free (bbg_file_name);
1407 free (da_file_name);
1408 da_file_name = bbg_file_name = NULL;
1409 bbg_file_time = 0;
1410 bbg_stamp = 0;
1412 if (object_directory && object_directory[0])
1414 struct stat status;
1416 length += strlen (object_directory) + 2;
1417 name = XNEWVEC (char, length);
1418 name[0] = 0;
1420 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1421 strcat (name, object_directory);
1422 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1423 strcat (name, "/");
1425 else
1427 name = XNEWVEC (char, length + 1);
1428 strcpy (name, file_name);
1429 base = 0;
1432 if (base)
1434 /* Append source file name. */
1435 const char *cptr = lbasename (file_name);
1436 strcat (name, cptr ? cptr : file_name);
1439 /* Remove the extension. */
1440 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1441 if (cptr)
1442 *cptr = 0;
1444 length = strlen (name);
1446 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1447 strcpy (bbg_file_name, name);
1448 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1450 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1451 strcpy (da_file_name, name);
1452 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1454 free (name);
1455 return;
1458 /* Find or create a source file structure for FILE_NAME. Copies
1459 FILE_NAME on creation */
1461 static unsigned
1462 find_source (const char *file_name)
1464 char *canon;
1465 unsigned idx;
1466 struct stat status;
1468 if (!file_name)
1469 file_name = "<unknown>";
1471 name_map needle;
1472 needle.name = file_name;
1474 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1475 needle);
1476 if (it != names.end ())
1478 idx = it->src;
1479 goto check_date;
1482 /* Not found, try the canonical name. */
1483 canon = canonicalize_name (file_name);
1484 needle.name = canon;
1485 it = std::find (names.begin (), names.end (), needle);
1486 if (it == names.end ())
1488 /* Not found with canonical name, create a new source. */
1489 source_info *src;
1491 idx = sources.size ();
1492 needle = name_map (canon, idx);
1493 names.push_back (needle);
1495 sources.push_back (source_info ());
1496 src = &sources.back ();
1497 src->name = canon;
1498 src->coverage.name = src->name;
1499 src->index = idx;
1500 if (source_length
1501 #if HAVE_DOS_BASED_FILE_SYSTEM
1502 /* You lose if separators don't match exactly in the
1503 prefix. */
1504 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1505 #else
1506 && !strncmp (source_prefix, src->coverage.name, source_length)
1507 #endif
1508 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1509 src->coverage.name += source_length + 1;
1510 if (!stat (src->name, &status))
1511 src->file_time = status.st_mtime;
1513 else
1514 idx = it->src;
1516 needle.name = file_name;
1517 if (std::find (names.begin (), names.end (), needle) == names.end ())
1519 /* Append the non-canonical name. */
1520 names.push_back (name_map (xstrdup (file_name), idx));
1523 /* Resort the name map. */
1524 std::sort (names.begin (), names.end ());
1526 check_date:
1527 if (sources[idx].file_time > bbg_file_time)
1529 static int info_emitted;
1531 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1532 file_name, bbg_file_name);
1533 if (!info_emitted)
1535 fnotice (stderr,
1536 "(the message is displayed only once per source file)\n");
1537 info_emitted = 1;
1539 sources[idx].file_time = 0;
1542 return idx;
1545 /* Read the notes file. Save functions to FUNCTIONS global vector. */
1547 static void
1548 read_graph_file (void)
1550 unsigned version;
1551 unsigned current_tag = 0;
1552 unsigned tag;
1554 if (!gcov_open (bbg_file_name, 1))
1556 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1557 return;
1559 bbg_file_time = gcov_time ();
1560 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1562 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1563 gcov_close ();
1564 return;
1567 version = gcov_read_unsigned ();
1568 if (version != GCOV_VERSION)
1570 char v[4], e[4];
1572 GCOV_UNSIGNED2STRING (v, version);
1573 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1575 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1576 bbg_file_name, v, e);
1578 bbg_stamp = gcov_read_unsigned ();
1579 bbg_cwd = xstrdup (gcov_read_string ());
1580 bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
1582 function_info *fn = NULL;
1583 while ((tag = gcov_read_unsigned ()))
1585 unsigned length = gcov_read_unsigned ();
1586 gcov_position_t base = gcov_position ();
1588 if (tag == GCOV_TAG_FUNCTION)
1590 char *function_name;
1591 unsigned ident;
1592 unsigned lineno_checksum, cfg_checksum;
1594 ident = gcov_read_unsigned ();
1595 lineno_checksum = gcov_read_unsigned ();
1596 cfg_checksum = gcov_read_unsigned ();
1597 function_name = xstrdup (gcov_read_string ());
1598 unsigned artificial = gcov_read_unsigned ();
1599 unsigned src_idx = find_source (gcov_read_string ());
1600 unsigned start_line = gcov_read_unsigned ();
1601 unsigned start_column = gcov_read_unsigned ();
1602 unsigned end_line = gcov_read_unsigned ();
1604 fn = new function_info ();
1605 functions.push_back (fn);
1606 fn->name = function_name;
1607 if (flag_demangled_names)
1609 fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1610 if (!fn->demangled_name)
1611 fn->demangled_name = fn->name;
1613 fn->ident = ident;
1614 fn->lineno_checksum = lineno_checksum;
1615 fn->cfg_checksum = cfg_checksum;
1616 fn->src = src_idx;
1617 fn->start_line = start_line;
1618 fn->start_column = start_column;
1619 fn->end_line = end_line;
1620 fn->artificial = artificial;
1622 current_tag = tag;
1624 else if (fn && tag == GCOV_TAG_BLOCKS)
1626 if (!fn->blocks.empty ())
1627 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1628 bbg_file_name, fn->name);
1629 else
1630 fn->blocks.resize (gcov_read_unsigned ());
1632 else if (fn && tag == GCOV_TAG_ARCS)
1634 unsigned src = gcov_read_unsigned ();
1635 fn->blocks[src].id = src;
1636 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1637 block_info *src_blk = &fn->blocks[src];
1638 unsigned mark_catches = 0;
1639 struct arc_info *arc;
1641 if (src >= fn->blocks.size () || fn->blocks[src].succ)
1642 goto corrupt;
1644 while (num_dests--)
1646 unsigned dest = gcov_read_unsigned ();
1647 unsigned flags = gcov_read_unsigned ();
1649 if (dest >= fn->blocks.size ())
1650 goto corrupt;
1651 arc = XCNEW (arc_info);
1653 arc->dst = &fn->blocks[dest];
1654 arc->src = src_blk;
1656 arc->count = 0;
1657 arc->count_valid = 0;
1658 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1659 arc->fake = !!(flags & GCOV_ARC_FAKE);
1660 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1662 arc->succ_next = src_blk->succ;
1663 src_blk->succ = arc;
1664 src_blk->num_succ++;
1666 arc->pred_next = fn->blocks[dest].pred;
1667 fn->blocks[dest].pred = arc;
1668 fn->blocks[dest].num_pred++;
1670 if (arc->fake)
1672 if (src)
1674 /* Exceptional exit from this function, the
1675 source block must be a call. */
1676 fn->blocks[src].is_call_site = 1;
1677 arc->is_call_non_return = 1;
1678 mark_catches = 1;
1680 else
1682 /* Non-local return from a callee of this
1683 function. The destination block is a setjmp. */
1684 arc->is_nonlocal_return = 1;
1685 fn->blocks[dest].is_nonlocal_return = 1;
1689 if (!arc->on_tree)
1690 fn->counts.push_back (0);
1693 if (mark_catches)
1695 /* We have a fake exit from this block. The other
1696 non-fall through exits must be to catch handlers.
1697 Mark them as catch arcs. */
1699 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1700 if (!arc->fake && !arc->fall_through)
1702 arc->is_throw = 1;
1703 fn->has_catch = 1;
1707 else if (fn && tag == GCOV_TAG_LINES)
1709 unsigned blockno = gcov_read_unsigned ();
1710 block_info *block = &fn->blocks[blockno];
1712 if (blockno >= fn->blocks.size ())
1713 goto corrupt;
1715 while (true)
1717 unsigned lineno = gcov_read_unsigned ();
1719 if (lineno)
1720 block->locations.back ().lines.push_back (lineno);
1721 else
1723 const char *file_name = gcov_read_string ();
1725 if (!file_name)
1726 break;
1727 block->locations.push_back (block_location_info
1728 (find_source (file_name)));
1732 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1734 fn = NULL;
1735 current_tag = 0;
1737 gcov_sync (base, length);
1738 if (gcov_is_error ())
1740 corrupt:;
1741 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1742 break;
1745 gcov_close ();
1747 if (functions.empty ())
1748 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1751 /* Reads profiles from the count file and attach to each
1752 function. Return nonzero if fatal error. */
1754 static int
1755 read_count_file (void)
1757 unsigned ix;
1758 unsigned version;
1759 unsigned tag;
1760 function_info *fn = NULL;
1761 int error = 0;
1763 if (!gcov_open (da_file_name, 1))
1765 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1766 da_file_name);
1767 no_data_file = 1;
1768 return 0;
1770 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1772 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1773 cleanup:;
1774 gcov_close ();
1775 return 1;
1777 version = gcov_read_unsigned ();
1778 if (version != GCOV_VERSION)
1780 char v[4], e[4];
1782 GCOV_UNSIGNED2STRING (v, version);
1783 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1785 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1786 da_file_name, v, e);
1788 tag = gcov_read_unsigned ();
1789 if (tag != bbg_stamp)
1791 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1792 goto cleanup;
1795 while ((tag = gcov_read_unsigned ()))
1797 unsigned length = gcov_read_unsigned ();
1798 unsigned long base = gcov_position ();
1800 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1802 struct gcov_summary summary;
1803 gcov_read_summary (&summary);
1804 object_runs += summary.runs;
1805 program_count++;
1807 else if (tag == GCOV_TAG_FUNCTION && !length)
1808 ; /* placeholder */
1809 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1811 unsigned ident;
1813 /* Try to find the function in the list. To speed up the
1814 search, first start from the last function found. */
1815 ident = gcov_read_unsigned ();
1817 fn = NULL;
1818 for (vector<function_info *>::reverse_iterator it
1819 = functions.rbegin (); it != functions.rend (); it++)
1821 if ((*it)->ident == ident)
1823 fn = *it;
1824 break;
1828 if (!fn)
1830 else if (gcov_read_unsigned () != fn->lineno_checksum
1831 || gcov_read_unsigned () != fn->cfg_checksum)
1833 mismatch:;
1834 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1835 da_file_name, fn->name);
1836 goto cleanup;
1839 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1841 if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
1842 goto mismatch;
1844 for (ix = 0; ix != fn->counts.size (); ix++)
1845 fn->counts[ix] += gcov_read_counter ();
1847 gcov_sync (base, length);
1848 if ((error = gcov_is_error ()))
1850 fnotice (stderr,
1851 error < 0
1852 ? N_("%s:overflowed\n")
1853 : N_("%s:corrupted\n"),
1854 da_file_name);
1855 goto cleanup;
1859 gcov_close ();
1860 return 0;
1863 /* Solve the flow graph. Propagate counts from the instrumented arcs
1864 to the blocks and the uninstrumented arcs. */
1866 static void
1867 solve_flow_graph (function_info *fn)
1869 unsigned ix;
1870 arc_info *arc;
1871 gcov_type *count_ptr = &fn->counts.front ();
1872 block_info *blk;
1873 block_info *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1874 block_info *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1876 /* The arcs were built in reverse order. Fix that now. */
1877 for (ix = fn->blocks.size (); ix--;)
1879 arc_info *arc_p, *arc_n;
1881 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1882 arc_p = arc, arc = arc_n)
1884 arc_n = arc->succ_next;
1885 arc->succ_next = arc_p;
1887 fn->blocks[ix].succ = arc_p;
1889 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1890 arc_p = arc, arc = arc_n)
1892 arc_n = arc->pred_next;
1893 arc->pred_next = arc_p;
1895 fn->blocks[ix].pred = arc_p;
1898 if (fn->blocks.size () < 2)
1899 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1900 bbg_file_name, fn->name);
1901 else
1903 if (fn->blocks[ENTRY_BLOCK].num_pred)
1904 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1905 bbg_file_name, fn->name);
1906 else
1907 /* We can't deduce the entry block counts from the lack of
1908 predecessors. */
1909 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1911 if (fn->blocks[EXIT_BLOCK].num_succ)
1912 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1913 bbg_file_name, fn->name);
1914 else
1915 /* Likewise, we can't deduce exit block counts from the lack
1916 of its successors. */
1917 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1920 /* Propagate the measured counts, this must be done in the same
1921 order as the code in profile.c */
1922 for (unsigned i = 0; i < fn->blocks.size (); i++)
1924 blk = &fn->blocks[i];
1925 block_info const *prev_dst = NULL;
1926 int out_of_order = 0;
1927 int non_fake_succ = 0;
1929 for (arc = blk->succ; arc; arc = arc->succ_next)
1931 if (!arc->fake)
1932 non_fake_succ++;
1934 if (!arc->on_tree)
1936 if (count_ptr)
1937 arc->count = *count_ptr++;
1938 arc->count_valid = 1;
1939 blk->num_succ--;
1940 arc->dst->num_pred--;
1942 if (prev_dst && prev_dst > arc->dst)
1943 out_of_order = 1;
1944 prev_dst = arc->dst;
1946 if (non_fake_succ == 1)
1948 /* If there is only one non-fake exit, it is an
1949 unconditional branch. */
1950 for (arc = blk->succ; arc; arc = arc->succ_next)
1951 if (!arc->fake)
1953 arc->is_unconditional = 1;
1954 /* If this block is instrumenting a call, it might be
1955 an artificial block. It is not artificial if it has
1956 a non-fallthrough exit, or the destination of this
1957 arc has more than one entry. Mark the destination
1958 block as a return site, if none of those conditions
1959 hold. */
1960 if (blk->is_call_site && arc->fall_through
1961 && arc->dst->pred == arc && !arc->pred_next)
1962 arc->dst->is_call_return = 1;
1966 /* Sort the successor arcs into ascending dst order. profile.c
1967 normally produces arcs in the right order, but sometimes with
1968 one or two out of order. We're not using a particularly
1969 smart sort. */
1970 if (out_of_order)
1972 arc_info *start = blk->succ;
1973 unsigned changes = 1;
1975 while (changes)
1977 arc_info *arc, *arc_p, *arc_n;
1979 changes = 0;
1980 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1982 if (arc->dst > arc_n->dst)
1984 changes = 1;
1985 if (arc_p)
1986 arc_p->succ_next = arc_n;
1987 else
1988 start = arc_n;
1989 arc->succ_next = arc_n->succ_next;
1990 arc_n->succ_next = arc;
1991 arc_p = arc_n;
1993 else
1995 arc_p = arc;
1996 arc = arc_n;
2000 blk->succ = start;
2003 /* Place it on the invalid chain, it will be ignored if that's
2004 wrong. */
2005 blk->invalid_chain = 1;
2006 blk->chain = invalid_blocks;
2007 invalid_blocks = blk;
2010 while (invalid_blocks || valid_blocks)
2012 while ((blk = invalid_blocks))
2014 gcov_type total = 0;
2015 const arc_info *arc;
2017 invalid_blocks = blk->chain;
2018 blk->invalid_chain = 0;
2019 if (!blk->num_succ)
2020 for (arc = blk->succ; arc; arc = arc->succ_next)
2021 total += arc->count;
2022 else if (!blk->num_pred)
2023 for (arc = blk->pred; arc; arc = arc->pred_next)
2024 total += arc->count;
2025 else
2026 continue;
2028 blk->count = total;
2029 blk->count_valid = 1;
2030 blk->chain = valid_blocks;
2031 blk->valid_chain = 1;
2032 valid_blocks = blk;
2034 while ((blk = valid_blocks))
2036 gcov_type total;
2037 arc_info *arc, *inv_arc;
2039 valid_blocks = blk->chain;
2040 blk->valid_chain = 0;
2041 if (blk->num_succ == 1)
2043 block_info *dst;
2045 total = blk->count;
2046 inv_arc = NULL;
2047 for (arc = blk->succ; arc; arc = arc->succ_next)
2049 total -= arc->count;
2050 if (!arc->count_valid)
2051 inv_arc = arc;
2053 dst = inv_arc->dst;
2054 inv_arc->count_valid = 1;
2055 inv_arc->count = total;
2056 blk->num_succ--;
2057 dst->num_pred--;
2058 if (dst->count_valid)
2060 if (dst->num_pred == 1 && !dst->valid_chain)
2062 dst->chain = valid_blocks;
2063 dst->valid_chain = 1;
2064 valid_blocks = dst;
2067 else
2069 if (!dst->num_pred && !dst->invalid_chain)
2071 dst->chain = invalid_blocks;
2072 dst->invalid_chain = 1;
2073 invalid_blocks = dst;
2077 if (blk->num_pred == 1)
2079 block_info *src;
2081 total = blk->count;
2082 inv_arc = NULL;
2083 for (arc = blk->pred; arc; arc = arc->pred_next)
2085 total -= arc->count;
2086 if (!arc->count_valid)
2087 inv_arc = arc;
2089 src = inv_arc->src;
2090 inv_arc->count_valid = 1;
2091 inv_arc->count = total;
2092 blk->num_pred--;
2093 src->num_succ--;
2094 if (src->count_valid)
2096 if (src->num_succ == 1 && !src->valid_chain)
2098 src->chain = valid_blocks;
2099 src->valid_chain = 1;
2100 valid_blocks = src;
2103 else
2105 if (!src->num_succ && !src->invalid_chain)
2107 src->chain = invalid_blocks;
2108 src->invalid_chain = 1;
2109 invalid_blocks = src;
2116 /* If the graph has been correctly solved, every block will have a
2117 valid count. */
2118 for (unsigned i = 0; ix < fn->blocks.size (); i++)
2119 if (!fn->blocks[i].count_valid)
2121 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
2122 bbg_file_name, fn->name);
2123 break;
2127 /* Mark all the blocks only reachable via an incoming catch. */
2129 static void
2130 find_exception_blocks (function_info *fn)
2132 unsigned ix;
2133 block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ());
2135 /* First mark all blocks as exceptional. */
2136 for (ix = fn->blocks.size (); ix--;)
2137 fn->blocks[ix].exceptional = 1;
2139 /* Now mark all the blocks reachable via non-fake edges */
2140 queue[0] = &fn->blocks[0];
2141 queue[0]->exceptional = 0;
2142 for (ix = 1; ix;)
2144 block_info *block = queue[--ix];
2145 const arc_info *arc;
2147 for (arc = block->succ; arc; arc = arc->succ_next)
2148 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
2150 arc->dst->exceptional = 0;
2151 queue[ix++] = arc->dst;
2157 /* Increment totals in COVERAGE according to arc ARC. */
2159 static void
2160 add_branch_counts (coverage_info *coverage, const arc_info *arc)
2162 if (arc->is_call_non_return)
2164 coverage->calls++;
2165 if (arc->src->count)
2166 coverage->calls_executed++;
2168 else if (!arc->is_unconditional)
2170 coverage->branches++;
2171 if (arc->src->count)
2172 coverage->branches_executed++;
2173 if (arc->count)
2174 coverage->branches_taken++;
2178 /* Format COUNT, if flag_human_readable_numbers is set, return it human
2179 readable format. */
2181 static char const *
2182 format_count (gcov_type count)
2184 static char buffer[64];
2185 const char *units = " kMGTPEZY";
2187 if (count < 1000 || !flag_human_readable_numbers)
2189 sprintf (buffer, "%" PRId64, count);
2190 return buffer;
2193 unsigned i;
2194 gcov_type divisor = 1;
2195 for (i = 0; units[i+1]; i++, divisor *= 1000)
2197 if (count + divisor / 2 < 1000 * divisor)
2198 break;
2200 gcov_type r = (count + divisor / 2) / divisor;
2201 sprintf (buffer, "%" PRId64 "%c", r, units[i]);
2202 return buffer;
2205 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
2206 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
2207 If DP is zero, no decimal point is printed. Only print 100% when
2208 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
2209 format TOP. Return pointer to a static string. */
2211 static char const *
2212 format_gcov (gcov_type top, gcov_type bottom, int dp)
2214 static char buffer[20];
2216 /* Handle invalid values that would result in a misleading value. */
2217 if (bottom != 0 && top > bottom && dp >= 0)
2219 sprintf (buffer, "NAN %%");
2220 return buffer;
2223 if (dp >= 0)
2225 float ratio = bottom ? (float)top / bottom : 0;
2226 int ix;
2227 unsigned limit = 100;
2228 unsigned percent;
2230 for (ix = dp; ix--; )
2231 limit *= 10;
2233 percent = (unsigned) (ratio * limit + (float)0.5);
2234 if (percent <= 0 && top)
2235 percent = 1;
2236 else if (percent >= limit && top != bottom)
2237 percent = limit - 1;
2238 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
2239 if (dp)
2241 dp++;
2244 buffer[ix+1] = buffer[ix];
2245 ix--;
2247 while (dp--);
2248 buffer[ix + 1] = '.';
2251 else
2252 return format_count (top);
2254 return buffer;
2257 /* Summary of execution */
2259 static void
2260 executed_summary (unsigned lines, unsigned executed)
2262 if (lines)
2263 fnotice (stdout, "Lines executed:%s of %d\n",
2264 format_gcov (executed, lines, 2), lines);
2265 else
2266 fnotice (stdout, "No executable lines\n");
2269 /* Output summary info for a function or file. */
2271 static void
2272 function_summary (const coverage_info *coverage, const char *title)
2274 fnotice (stdout, "%s '%s'\n", title, coverage->name);
2275 executed_summary (coverage->lines, coverage->lines_executed);
2277 if (flag_branches)
2279 if (coverage->branches)
2281 fnotice (stdout, "Branches executed:%s of %d\n",
2282 format_gcov (coverage->branches_executed,
2283 coverage->branches, 2),
2284 coverage->branches);
2285 fnotice (stdout, "Taken at least once:%s of %d\n",
2286 format_gcov (coverage->branches_taken,
2287 coverage->branches, 2),
2288 coverage->branches);
2290 else
2291 fnotice (stdout, "No branches\n");
2292 if (coverage->calls)
2293 fnotice (stdout, "Calls executed:%s of %d\n",
2294 format_gcov (coverage->calls_executed, coverage->calls, 2),
2295 coverage->calls);
2296 else
2297 fnotice (stdout, "No calls\n");
2301 /* Canonicalize the filename NAME by canonicalizing directory
2302 separators, eliding . components and resolving .. components
2303 appropriately. Always returns a unique string. */
2305 static char *
2306 canonicalize_name (const char *name)
2308 /* The canonical name cannot be longer than the incoming name. */
2309 char *result = XNEWVEC (char, strlen (name) + 1);
2310 const char *base = name, *probe;
2311 char *ptr = result;
2312 char *dd_base;
2313 int slash = 0;
2315 #if HAVE_DOS_BASED_FILE_SYSTEM
2316 if (base[0] && base[1] == ':')
2318 result[0] = base[0];
2319 result[1] = ':';
2320 base += 2;
2321 ptr += 2;
2323 #endif
2324 for (dd_base = ptr; *base; base = probe)
2326 size_t len;
2328 for (probe = base; *probe; probe++)
2329 if (IS_DIR_SEPARATOR (*probe))
2330 break;
2332 len = probe - base;
2333 if (len == 1 && base[0] == '.')
2334 /* Elide a '.' directory */
2336 else if (len == 2 && base[0] == '.' && base[1] == '.')
2338 /* '..', we can only elide it and the previous directory, if
2339 we're not a symlink. */
2340 struct stat ATTRIBUTE_UNUSED buf;
2342 *ptr = 0;
2343 if (dd_base == ptr
2344 #if defined (S_ISLNK)
2345 /* S_ISLNK is not POSIX.1-1996. */
2346 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2347 #endif
2350 /* Cannot elide, or unreadable or a symlink. */
2351 dd_base = ptr + 2 + slash;
2352 goto regular;
2354 while (ptr != dd_base && *ptr != '/')
2355 ptr--;
2356 slash = ptr != result;
2358 else
2360 regular:
2361 /* Regular pathname component. */
2362 if (slash)
2363 *ptr++ = '/';
2364 memcpy (ptr, base, len);
2365 ptr += len;
2366 slash = 1;
2369 for (; IS_DIR_SEPARATOR (*probe); probe++)
2370 continue;
2372 *ptr = 0;
2374 return result;
2377 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2379 static void
2380 md5sum_to_hex (const char *sum, char *buffer)
2382 for (unsigned i = 0; i < 16; i++)
2383 sprintf (buffer + (2 * i), "%02x", (unsigned char)sum[i]);
2386 /* Generate an output file name. INPUT_NAME is the canonicalized main
2387 input file and SRC_NAME is the canonicalized file name.
2388 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2389 long_output_names we prepend the processed name of the input file
2390 to each output name (except when the current source file is the
2391 input file, so you don't get a double concatenation). The two
2392 components are separated by '##'. With preserve_paths we create a
2393 filename from all path components of the source file, replacing '/'
2394 with '#', and .. with '^', without it we simply take the basename
2395 component. (Remember, the canonicalized name will already have
2396 elided '.' components and converted \\ separators.) */
2398 static char *
2399 make_gcov_file_name (const char *input_name, const char *src_name)
2401 char *ptr;
2402 char *result;
2404 if (flag_long_names && input_name && strcmp (src_name, input_name))
2406 /* Generate the input filename part. */
2407 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
2409 ptr = result;
2410 ptr = mangle_name (input_name, ptr);
2411 ptr[0] = ptr[1] = '#';
2412 ptr += 2;
2414 else
2416 result = XNEWVEC (char, strlen (src_name) + 10);
2417 ptr = result;
2420 ptr = mangle_name (src_name, ptr);
2421 strcpy (ptr, ".gcov");
2423 /* When hashing filenames, we shorten them by only using the filename
2424 component and appending a hash of the full (mangled) pathname. */
2425 if (flag_hash_filenames)
2427 md5_ctx ctx;
2428 char md5sum[16];
2429 char md5sum_hex[33];
2431 md5_init_ctx (&ctx);
2432 md5_process_bytes (src_name, strlen (src_name), &ctx);
2433 md5_finish_ctx (&ctx, md5sum);
2434 md5sum_to_hex (md5sum, md5sum_hex);
2435 free (result);
2437 result = XNEWVEC (char, strlen (src_name) + 50);
2438 ptr = result;
2439 ptr = mangle_name (src_name, ptr);
2440 ptr[0] = ptr[1] = '#';
2441 ptr += 2;
2442 memcpy (ptr, md5sum_hex, 32);
2443 ptr += 32;
2444 strcpy (ptr, ".gcov");
2447 return result;
2450 static char *
2451 mangle_name (char const *base, char *ptr)
2453 size_t len;
2455 /* Generate the source filename part. */
2456 if (!flag_preserve_paths)
2458 base = lbasename (base);
2459 len = strlen (base);
2460 memcpy (ptr, base, len);
2461 ptr += len;
2463 else
2465 /* Convert '/' to '#', convert '..' to '^',
2466 convert ':' to '~' on DOS based file system. */
2467 const char *probe;
2469 #if HAVE_DOS_BASED_FILE_SYSTEM
2470 if (base[0] && base[1] == ':')
2472 ptr[0] = base[0];
2473 ptr[1] = '~';
2474 ptr += 2;
2475 base += 2;
2477 #endif
2478 for (; *base; base = probe)
2480 size_t len;
2482 for (probe = base; *probe; probe++)
2483 if (*probe == '/')
2484 break;
2485 len = probe - base;
2486 if (len == 2 && base[0] == '.' && base[1] == '.')
2487 *ptr++ = '^';
2488 else
2490 memcpy (ptr, base, len);
2491 ptr += len;
2493 if (*probe)
2495 *ptr++ = '#';
2496 probe++;
2501 return ptr;
2504 /* Scan through the bb_data for each line in the block, increment
2505 the line number execution count indicated by the execution count of
2506 the appropriate basic block. */
2508 static void
2509 add_line_counts (coverage_info *coverage, function_info *fn)
2511 bool has_any_line = false;
2512 /* Scan each basic block. */
2513 for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
2515 line_info *line = NULL;
2516 block_info *block = &fn->blocks[ix];
2517 if (block->count && ix && ix + 1 != fn->blocks.size ())
2518 fn->blocks_executed++;
2519 for (unsigned i = 0; i < block->locations.size (); i++)
2521 unsigned src_idx = block->locations[i].source_file_idx;
2522 vector<unsigned> &lines = block->locations[i].lines;
2524 block->cycle.arc = NULL;
2525 block->cycle.ident = ~0U;
2527 for (unsigned j = 0; j < lines.size (); j++)
2529 unsigned ln = lines[j];
2531 /* Line belongs to a function that is in a group. */
2532 if (fn->group_line_p (ln, src_idx))
2534 gcc_assert (lines[j] - fn->start_line < fn->lines.size ());
2535 line = &(fn->lines[lines[j] - fn->start_line]);
2536 line->exists = 1;
2537 if (!block->exceptional)
2539 line->unexceptional = 1;
2540 if (block->count == 0)
2541 line->has_unexecuted_block = 1;
2543 line->count += block->count;
2545 else
2547 gcc_assert (ln < sources[src_idx].lines.size ());
2548 line = &(sources[src_idx].lines[ln]);
2549 if (coverage)
2551 if (!line->exists)
2552 coverage->lines++;
2553 if (!line->count && block->count)
2554 coverage->lines_executed++;
2556 line->exists = 1;
2557 if (!block->exceptional)
2559 line->unexceptional = 1;
2560 if (block->count == 0)
2561 line->has_unexecuted_block = 1;
2563 line->count += block->count;
2567 has_any_line = true;
2569 if (!ix || ix + 1 == fn->blocks.size ())
2570 /* Entry or exit block. */;
2571 else if (line != NULL)
2573 line->blocks.push_back (block);
2575 if (flag_branches)
2577 arc_info *arc;
2579 for (arc = block->succ; arc; arc = arc->succ_next)
2580 line->branches.push_back (arc);
2586 if (!has_any_line)
2587 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
2590 /* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE
2591 is set to true, update source file summary. */
2593 static void accumulate_line_info (line_info *line, source_info *src,
2594 bool add_coverage)
2596 if (add_coverage)
2597 for (vector<arc_info *>::iterator it = line->branches.begin ();
2598 it != line->branches.end (); it++)
2599 add_branch_counts (&src->coverage, *it);
2601 if (!line->blocks.empty ())
2603 /* The user expects the line count to be the number of times
2604 a line has been executed. Simply summing the block count
2605 will give an artificially high number. The Right Thing
2606 is to sum the entry counts to the graph of blocks on this
2607 line, then find the elementary cycles of the local graph
2608 and add the transition counts of those cycles. */
2609 gcov_type count = 0;
2611 /* Cycle detection. */
2612 for (vector<block_info *>::iterator it = line->blocks.begin ();
2613 it != line->blocks.end (); it++)
2615 for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next)
2616 if (!line->has_block (arc->src))
2617 count += arc->count;
2618 for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next)
2619 arc->cs_count = arc->count;
2622 /* Now, add the count of loops entirely on this line. */
2623 count += get_cycles_count (*line);
2624 line->count = count;
2627 if (line->exists && add_coverage)
2629 src->coverage.lines++;
2630 if (line->count)
2631 src->coverage.lines_executed++;
2635 /* Accumulate the line counts of a file. */
2637 static void
2638 accumulate_line_counts (source_info *src)
2640 /* First work on group functions. */
2641 for (vector<function_info *>::iterator it = src->functions.begin ();
2642 it != src->functions.end (); it++)
2644 function_info *fn = *it;
2646 if (fn->src != src->index || !fn->is_group)
2647 continue;
2649 for (vector<line_info>::iterator it2 = fn->lines.begin ();
2650 it2 != fn->lines.end (); it2++)
2652 line_info *line = &(*it2);
2653 accumulate_line_info (line, src, false);
2657 /* Work on global lines that line in source file SRC. */
2658 for (vector<line_info>::iterator it = src->lines.begin ();
2659 it != src->lines.end (); it++)
2660 accumulate_line_info (&(*it), src, true);
2662 /* If not using intermediate mode, sum lines of group functions and
2663 add them to lines that live in a source file. */
2664 if (!flag_intermediate_format)
2665 for (vector<function_info *>::iterator it = src->functions.begin ();
2666 it != src->functions.end (); it++)
2668 function_info *fn = *it;
2670 if (fn->src != src->index || !fn->is_group)
2671 continue;
2673 for (unsigned i = 0; i < fn->lines.size (); i++)
2675 line_info *fn_line = &fn->lines[i];
2676 if (fn_line->exists)
2678 unsigned ln = fn->start_line + i;
2679 line_info *src_line = &src->lines[ln];
2681 if (!src_line->exists)
2682 src->coverage.lines++;
2683 if (!src_line->count && fn_line->count)
2684 src->coverage.lines_executed++;
2686 src_line->count += fn_line->count;
2687 src_line->exists = 1;
2689 if (fn_line->has_unexecuted_block)
2690 src_line->has_unexecuted_block = 1;
2692 if (fn_line->unexceptional)
2693 src_line->unexceptional = 1;
2699 /* Output information about ARC number IX. Returns nonzero if
2700 anything is output. */
2702 static int
2703 output_branch_count (FILE *gcov_file, int ix, const arc_info *arc)
2705 if (arc->is_call_non_return)
2707 if (arc->src->count)
2709 fnotice (gcov_file, "call %2d returned %s\n", ix,
2710 format_gcov (arc->src->count - arc->count,
2711 arc->src->count, -flag_counts));
2713 else
2714 fnotice (gcov_file, "call %2d never executed\n", ix);
2716 else if (!arc->is_unconditional)
2718 if (arc->src->count)
2719 fnotice (gcov_file, "branch %2d taken %s%s", ix,
2720 format_gcov (arc->count, arc->src->count, -flag_counts),
2721 arc->fall_through ? " (fallthrough)"
2722 : arc->is_throw ? " (throw)" : "");
2723 else
2724 fnotice (gcov_file, "branch %2d never executed", ix);
2726 if (flag_verbose)
2727 fnotice (gcov_file, " (BB %d)", arc->dst->id);
2729 fnotice (gcov_file, "\n");
2731 else if (flag_unconditional && !arc->dst->is_call_return)
2733 if (arc->src->count)
2734 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2735 format_gcov (arc->count, arc->src->count, -flag_counts));
2736 else
2737 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2739 else
2740 return 0;
2741 return 1;
2744 static const char *
2745 read_line (FILE *file)
2747 static char *string;
2748 static size_t string_len;
2749 size_t pos = 0;
2750 char *ptr;
2752 if (!string_len)
2754 string_len = 200;
2755 string = XNEWVEC (char, string_len);
2758 while ((ptr = fgets (string + pos, string_len - pos, file)))
2760 size_t len = strlen (string + pos);
2762 if (len && string[pos + len - 1] == '\n')
2764 string[pos + len - 1] = 0;
2765 return string;
2767 pos += len;
2768 /* If the file contains NUL characters or an incomplete
2769 last line, which can happen more than once in one run,
2770 we have to avoid doubling the STRING_LEN unnecessarily. */
2771 if (pos > string_len / 2)
2773 string_len *= 2;
2774 string = XRESIZEVEC (char, string, string_len);
2778 return pos ? string : NULL;
2781 /* Pad string S with spaces from left to have total width equal to 9. */
2783 static void
2784 pad_count_string (string &s)
2786 if (s.size () < 9)
2787 s.insert (0, 9 - s.size (), ' ');
2790 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2791 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2792 an exceptional statement. The output is printed for LINE_NUM of given
2793 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2794 used to indicate non-executed blocks. */
2796 static void
2797 output_line_beginning (FILE *f, bool exists, bool unexceptional,
2798 bool has_unexecuted_block,
2799 gcov_type count, unsigned line_num,
2800 const char *exceptional_string,
2801 const char *unexceptional_string)
2803 string s;
2804 if (exists)
2806 if (count > 0)
2808 s = format_gcov (count, 0, -1);
2809 if (has_unexecuted_block
2810 && bbg_supports_has_unexecuted_blocks)
2812 if (flag_use_colors)
2814 pad_count_string (s);
2815 s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
2816 COLOR_SEPARATOR COLOR_FG_WHITE));
2817 s += SGR_RESET;
2819 else
2820 s += "*";
2822 pad_count_string (s);
2824 else
2826 if (flag_use_colors)
2828 s = "0";
2829 pad_count_string (s);
2830 if (unexceptional)
2831 s.insert (0, SGR_SEQ (COLOR_BG_RED
2832 COLOR_SEPARATOR COLOR_FG_WHITE));
2833 else
2834 s.insert (0, SGR_SEQ (COLOR_BG_CYAN
2835 COLOR_SEPARATOR COLOR_FG_WHITE));
2836 s += SGR_RESET;
2838 else
2840 s = unexceptional ? unexceptional_string : exceptional_string;
2841 pad_count_string (s);
2845 else
2847 s = "-";
2848 pad_count_string (s);
2851 fprintf (f, "%s:%5u", s.c_str (), line_num);
2854 static void
2855 print_source_line (FILE *f, const vector<const char *> &source_lines,
2856 unsigned line)
2858 gcc_assert (line >= 1);
2859 gcc_assert (line <= source_lines.size ());
2861 fprintf (f, ":%s\n", source_lines[line - 1]);
2864 /* Output line details for LINE and print it to F file. LINE lives on
2865 LINE_NUM. */
2867 static void
2868 output_line_details (FILE *f, const line_info *line, unsigned line_num)
2870 if (flag_all_blocks)
2872 arc_info *arc;
2873 int ix, jx;
2875 ix = jx = 0;
2876 for (vector<block_info *>::const_iterator it = line->blocks.begin ();
2877 it != line->blocks.end (); it++)
2879 if (!(*it)->is_call_return)
2881 output_line_beginning (f, line->exists,
2882 (*it)->exceptional, false,
2883 (*it)->count, line_num,
2884 "%%%%%", "$$$$$");
2885 fprintf (f, "-block %2d", ix++);
2886 if (flag_verbose)
2887 fprintf (f, " (BB %u)", (*it)->id);
2888 fprintf (f, "\n");
2890 if (flag_branches)
2891 for (arc = (*it)->succ; arc; arc = arc->succ_next)
2892 jx += output_branch_count (f, jx, arc);
2895 else if (flag_branches)
2897 int ix;
2899 ix = 0;
2900 for (vector<arc_info *>::const_iterator it = line->branches.begin ();
2901 it != line->branches.end (); it++)
2902 ix += output_branch_count (f, ix, (*it));
2906 /* Output detail statistics about function FN to file F. */
2908 static void
2909 output_function_details (FILE *f, const function_info *fn)
2911 if (!flag_branches)
2912 return;
2914 arc_info *arc = fn->blocks[EXIT_BLOCK].pred;
2915 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2916 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2918 for (; arc; arc = arc->pred_next)
2919 if (arc->fake)
2920 return_count -= arc->count;
2922 fprintf (f, "function %s",
2923 flag_demangled_names ? fn->demangled_name : fn->name);
2924 fprintf (f, " called %s",
2925 format_gcov (called_count, 0, -1));
2926 fprintf (f, " returned %s",
2927 format_gcov (return_count, called_count, 0));
2928 fprintf (f, " blocks executed %s",
2929 format_gcov (fn->blocks_executed, fn->blocks.size () - 2,
2930 0));
2931 fprintf (f, "\n");
2934 /* Read in the source file one line at a time, and output that line to
2935 the gcov file preceded by its execution count and other
2936 information. */
2938 static void
2939 output_lines (FILE *gcov_file, const source_info *src)
2941 #define DEFAULT_LINE_START " -: 0:"
2942 #define FN_SEPARATOR "------------------\n"
2944 FILE *source_file;
2945 const char *retval;
2947 fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
2948 if (!multiple_files)
2950 fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
2951 fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
2952 no_data_file ? "-" : da_file_name);
2953 fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
2955 fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
2957 source_file = fopen (src->name, "r");
2958 if (!source_file)
2959 fnotice (stderr, "Cannot open source file %s\n", src->name);
2960 else if (src->file_time == 0)
2961 fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
2963 vector<const char *> source_lines;
2964 if (source_file)
2965 while ((retval = read_line (source_file)) != NULL)
2966 source_lines.push_back (xstrdup (retval));
2968 unsigned line_start_group = 0;
2969 vector<function_info *> fns;
2971 for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++)
2973 if (line_num >= src->lines.size ())
2975 fprintf (gcov_file, "%9s:%5u", "-", line_num);
2976 print_source_line (gcov_file, source_lines, line_num);
2977 continue;
2980 const line_info *line = &src->lines[line_num];
2982 if (line_start_group == 0)
2984 fns = src->get_functions_at_location (line_num);
2985 if (fns.size () > 1)
2987 /* It's possible to have functions that partially overlap,
2988 thus take the maximum end_line of functions starting
2989 at LINE_NUM. */
2990 for (unsigned i = 0; i < fns.size (); i++)
2991 if (fns[i]->end_line > line_start_group)
2992 line_start_group = fns[i]->end_line;
2994 else if (fns.size () == 1)
2996 function_info *fn = fns[0];
2997 output_function_details (gcov_file, fn);
3001 /* For lines which don't exist in the .bb file, print '-' before
3002 the source line. For lines which exist but were never
3003 executed, print '#####' or '=====' before the source line.
3004 Otherwise, print the execution count before the source line.
3005 There are 16 spaces of indentation added before the source
3006 line so that tabs won't be messed up. */
3007 output_line_beginning (gcov_file, line->exists, line->unexceptional,
3008 line->has_unexecuted_block, line->count,
3009 line_num, "=====", "#####");
3011 print_source_line (gcov_file, source_lines, line_num);
3012 output_line_details (gcov_file, line, line_num);
3014 if (line_start_group == line_num)
3016 for (vector<function_info *>::iterator it = fns.begin ();
3017 it != fns.end (); it++)
3019 function_info *fn = *it;
3020 vector<line_info> &lines = fn->lines;
3022 fprintf (gcov_file, FN_SEPARATOR);
3024 string fn_name
3025 = flag_demangled_names ? fn->demangled_name : fn->name;
3027 if (flag_use_colors)
3029 fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN));
3030 fn_name += SGR_RESET;
3033 fprintf (gcov_file, "%s:\n", fn_name.c_str ());
3035 output_function_details (gcov_file, fn);
3037 /* Print all lines covered by the function. */
3038 for (unsigned i = 0; i < lines.size (); i++)
3040 line_info *line = &lines[i];
3041 unsigned l = fn->start_line + i;
3043 /* For lines which don't exist in the .bb file, print '-'
3044 before the source line. For lines which exist but
3045 were never executed, print '#####' or '=====' before
3046 the source line. Otherwise, print the execution count
3047 before the source line.
3048 There are 16 spaces of indentation added before the source
3049 line so that tabs won't be messed up. */
3050 output_line_beginning (gcov_file, line->exists,
3051 line->unexceptional,
3052 line->has_unexecuted_block,
3053 line->count,
3054 l, "=====", "#####");
3056 print_source_line (gcov_file, source_lines, l);
3057 output_line_details (gcov_file, line, l);
3061 fprintf (gcov_file, FN_SEPARATOR);
3062 line_start_group = 0;
3066 if (source_file)
3067 fclose (source_file);