[AArch64] Fix -mlow-precision-div (PR 86838)
[official-gcc.git] / gcc / gcov.c
blob43dfc9a4b2c90400e88f88272a69b580c16faade
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 process_all_functions (void);
547 static void generate_results (const char *);
548 static void create_file_names (const char *);
549 static char *canonicalize_name (const char *);
550 static unsigned find_source (const char *);
551 static void read_graph_file (void);
552 static int read_count_file (void);
553 static void solve_flow_graph (function_info *);
554 static void find_exception_blocks (function_info *);
555 static void add_branch_counts (coverage_info *, const arc_info *);
556 static void add_line_counts (coverage_info *, function_info *);
557 static void executed_summary (unsigned, unsigned);
558 static void function_summary (const coverage_info *, const char *);
559 static const char *format_gcov (gcov_type, gcov_type, int);
560 static void accumulate_line_counts (source_info *);
561 static void output_gcov_file (const char *, source_info *);
562 static int output_branch_count (FILE *, int, const arc_info *);
563 static void output_lines (FILE *, const source_info *);
564 static char *make_gcov_file_name (const char *, const char *);
565 static char *mangle_name (const char *, char *);
566 static void release_structures (void);
567 extern int main (int, char **);
569 function_info::function_info (): name (NULL), demangled_name (NULL),
570 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
571 artificial (0), is_group (0),
572 blocks (), blocks_executed (0), counts (),
573 start_line (0), start_column (), end_line (0), src (0), lines (), next (NULL)
577 function_info::~function_info ()
579 for (int i = blocks.size () - 1; i >= 0; i--)
581 arc_info *arc, *arc_n;
583 for (arc = blocks[i].succ; arc; arc = arc_n)
585 arc_n = arc->succ_next;
586 free (arc);
589 if (flag_demangled_names && demangled_name != name)
590 free (demangled_name);
591 free (name);
594 bool function_info::group_line_p (unsigned n, unsigned src_idx)
596 return is_group && src == src_idx && start_line <= n && n <= end_line;
599 /* Cycle detection!
600 There are a bajillion algorithms that do this. Boost's function is named
601 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
602 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
603 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
605 The basic algorithm is simple: effectively, we're finding all simple paths
606 in a subgraph (that shrinks every iteration). Duplicates are filtered by
607 "blocking" a path when a node is added to the path (this also prevents non-
608 simple paths)--the node is unblocked only when it participates in a cycle.
611 typedef vector<arc_info *> arc_vector_t;
612 typedef vector<const block_info *> block_vector_t;
614 /* Enum with types of loop in CFG. */
616 enum loop_type
618 NO_LOOP = 0,
619 LOOP = 1,
620 NEGATIVE_LOOP = 3
623 /* Loop_type operator that merges two values: A and B. */
625 inline loop_type& operator |= (loop_type& a, loop_type b)
627 return a = static_cast<loop_type> (a | b);
630 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
631 and subtract the value from all counts. The subtracted value is added
632 to COUNT. Returns type of loop. */
634 static loop_type
635 handle_cycle (const arc_vector_t &edges, int64_t &count)
637 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
638 that amount. */
639 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
640 for (unsigned i = 0; i < edges.size (); i++)
642 int64_t ecount = edges[i]->cs_count;
643 if (cycle_count > ecount)
644 cycle_count = ecount;
646 count += cycle_count;
647 for (unsigned i = 0; i < edges.size (); i++)
648 edges[i]->cs_count -= cycle_count;
650 return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
653 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
654 blocked by U in BLOCK_LISTS. */
656 static void
657 unblock (const block_info *u, block_vector_t &blocked,
658 vector<block_vector_t > &block_lists)
660 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
661 if (it == blocked.end ())
662 return;
664 unsigned index = it - blocked.begin ();
665 blocked.erase (it);
667 block_vector_t to_unblock (block_lists[index]);
669 block_lists.erase (block_lists.begin () + index);
671 for (block_vector_t::iterator it = to_unblock.begin ();
672 it != to_unblock.end (); it++)
673 unblock (*it, blocked, block_lists);
676 /* Find circuit going to block V, PATH is provisional seen cycle.
677 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
678 blocked by a block. COUNT is accumulated count of the current LINE.
679 Returns what type of loop it contains. */
681 static loop_type
682 circuit (block_info *v, arc_vector_t &path, block_info *start,
683 block_vector_t &blocked, vector<block_vector_t> &block_lists,
684 line_info &linfo, int64_t &count)
686 loop_type result = NO_LOOP;
688 /* Add v to the block list. */
689 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
690 blocked.push_back (v);
691 block_lists.push_back (block_vector_t ());
693 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
695 block_info *w = arc->dst;
696 if (w < start || !linfo.has_block (w))
697 continue;
699 path.push_back (arc);
700 if (w == start)
701 /* Cycle has been found. */
702 result |= handle_cycle (path, count);
703 else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
704 result |= circuit (w, path, start, blocked, block_lists, linfo, count);
706 path.pop_back ();
709 if (result != NO_LOOP)
710 unblock (v, blocked, block_lists);
711 else
712 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
714 block_info *w = arc->dst;
715 if (w < start || !linfo.has_block (w))
716 continue;
718 size_t index
719 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
720 gcc_assert (index < blocked.size ());
721 block_vector_t &list = block_lists[index];
722 if (find (list.begin (), list.end (), v) == list.end ())
723 list.push_back (v);
726 return result;
729 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
730 contains a negative loop, then perform the same function once again. */
732 static gcov_type
733 get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
735 /* Note that this algorithm works even if blocks aren't in sorted order.
736 Each iteration of the circuit detection is completely independent
737 (except for reducing counts, but that shouldn't matter anyways).
738 Therefore, operating on a permuted order (i.e., non-sorted) only
739 has the effect of permuting the output cycles. */
741 loop_type result = NO_LOOP;
742 gcov_type count = 0;
743 for (vector<block_info *>::iterator it = linfo.blocks.begin ();
744 it != linfo.blocks.end (); it++)
746 arc_vector_t path;
747 block_vector_t blocked;
748 vector<block_vector_t > block_lists;
749 result |= circuit (*it, path, *it, blocked, block_lists, linfo,
750 count);
753 /* If we have a negative cycle, repeat the find_cycles routine. */
754 if (result == NEGATIVE_LOOP && handle_negative_cycles)
755 count += get_cycles_count (linfo, false);
757 return count;
761 main (int argc, char **argv)
763 int argno;
764 int first_arg;
765 const char *p;
767 p = argv[0] + strlen (argv[0]);
768 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
769 --p;
770 progname = p;
772 xmalloc_set_program_name (progname);
774 /* Unlock the stdio streams. */
775 unlock_std_streams ();
777 gcc_init_libintl ();
779 diagnostic_initialize (global_dc, 0);
781 /* Handle response files. */
782 expandargv (&argc, &argv);
784 argno = process_args (argc, argv);
785 if (optind == argc)
786 print_usage (true);
788 if (argc - argno > 1)
789 multiple_files = 1;
791 first_arg = argno;
793 for (; argno != argc; argno++)
795 if (flag_display_progress)
796 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
797 argc - first_arg);
798 process_file (argv[argno]);
800 if (flag_intermediate_format || argno == argc - 1)
802 process_all_functions ();
803 generate_results (argv[argno]);
804 release_structures ();
808 return 0;
811 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
812 otherwise the output of --help. */
814 static void
815 print_usage (int error_p)
817 FILE *file = error_p ? stderr : stdout;
818 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
820 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
821 fnotice (file, "Print code coverage information.\n\n");
822 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
823 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
824 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
825 rather than percentages\n");
826 fnotice (file, " -d, --display-progress Display progress information\n");
827 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
828 fnotice (file, " -h, --help Print this help, then exit\n");
829 fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
830 fnotice (file, " -j, --human-readable Output human readable numbers\n");
831 fnotice (file, " -k, --use-colors Emit colored output\n");
832 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
833 source files\n");
834 fnotice (file, " -m, --demangled-names Output demangled function names\n");
835 fnotice (file, " -n, --no-output Do not create an output file\n");
836 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
837 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
838 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
839 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
840 fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
841 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
842 fnotice (file, " -v, --version Print version number, then exit\n");
843 fnotice (file, " -w, --verbose Print verbose informations\n");
844 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
845 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
846 bug_report_url);
847 exit (status);
850 /* Print version information and exit. */
852 static void
853 print_version (void)
855 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
856 fprintf (stdout, "Copyright %s 2018 Free Software Foundation, Inc.\n",
857 _("(C)"));
858 fnotice (stdout,
859 _("This is free software; see the source for copying conditions.\n"
860 "There is NO warranty; not even for MERCHANTABILITY or \n"
861 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
862 exit (SUCCESS_EXIT_CODE);
865 static const struct option options[] =
867 { "help", no_argument, NULL, 'h' },
868 { "version", no_argument, NULL, 'v' },
869 { "verbose", no_argument, NULL, 'w' },
870 { "all-blocks", no_argument, NULL, 'a' },
871 { "branch-probabilities", no_argument, NULL, 'b' },
872 { "branch-counts", no_argument, NULL, 'c' },
873 { "intermediate-format", no_argument, NULL, 'i' },
874 { "human-readable", no_argument, NULL, 'j' },
875 { "no-output", no_argument, NULL, 'n' },
876 { "long-file-names", no_argument, NULL, 'l' },
877 { "function-summaries", no_argument, NULL, 'f' },
878 { "demangled-names", no_argument, NULL, 'm' },
879 { "preserve-paths", no_argument, NULL, 'p' },
880 { "relative-only", no_argument, NULL, 'r' },
881 { "object-directory", required_argument, NULL, 'o' },
882 { "object-file", required_argument, NULL, 'o' },
883 { "source-prefix", required_argument, NULL, 's' },
884 { "stdout", no_argument, NULL, 't' },
885 { "unconditional-branches", no_argument, NULL, 'u' },
886 { "display-progress", no_argument, NULL, 'd' },
887 { "hash-filenames", no_argument, NULL, 'x' },
888 { "use-colors", no_argument, NULL, 'k' },
889 { 0, 0, 0, 0 }
892 /* Process args, return index to first non-arg. */
894 static int
895 process_args (int argc, char **argv)
897 int opt;
899 const char *opts = "abcdfhijklmno:prs:tuvwx";
900 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
902 switch (opt)
904 case 'a':
905 flag_all_blocks = 1;
906 break;
907 case 'b':
908 flag_branches = 1;
909 break;
910 case 'c':
911 flag_counts = 1;
912 break;
913 case 'f':
914 flag_function_summary = 1;
915 break;
916 case 'h':
917 print_usage (false);
918 /* print_usage will exit. */
919 case 'l':
920 flag_long_names = 1;
921 break;
922 case 'j':
923 flag_human_readable_numbers = 1;
924 break;
925 case 'k':
926 flag_use_colors = 1;
927 break;
928 case 'm':
929 flag_demangled_names = 1;
930 break;
931 case 'n':
932 flag_gcov_file = 0;
933 break;
934 case 'o':
935 object_directory = optarg;
936 break;
937 case 's':
938 source_prefix = optarg;
939 source_length = strlen (source_prefix);
940 break;
941 case 'r':
942 flag_relative_only = 1;
943 break;
944 case 'p':
945 flag_preserve_paths = 1;
946 break;
947 case 'u':
948 flag_unconditional = 1;
949 break;
950 case 'i':
951 flag_intermediate_format = 1;
952 flag_gcov_file = 1;
953 break;
954 case 'd':
955 flag_display_progress = 1;
956 break;
957 case 'x':
958 flag_hash_filenames = 1;
959 break;
960 case 'w':
961 flag_verbose = 1;
962 break;
963 case 't':
964 flag_use_stdout = 1;
965 break;
966 case 'v':
967 print_version ();
968 /* print_version will exit. */
969 default:
970 print_usage (true);
971 /* print_usage will exit. */
975 return optind;
978 /* Output intermediate LINE sitting on LINE_NUM to output file F. */
980 static void
981 output_intermediate_line (FILE *f, line_info *line, unsigned line_num)
983 if (!line->exists)
984 return;
986 fprintf (f, "lcount:%u,%s,%d\n", line_num,
987 format_gcov (line->count, 0, -1),
988 line->has_unexecuted_block);
990 vector<arc_info *>::const_iterator it;
991 if (flag_branches)
992 for (it = line->branches.begin (); it != line->branches.end ();
993 it++)
995 if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
997 const char *branch_type;
998 /* branch:<line_num>,<branch_coverage_infoype>
999 branch_coverage_infoype
1000 : notexec (Branch not executed)
1001 : taken (Branch executed and taken)
1002 : nottaken (Branch executed, but not taken)
1004 if ((*it)->src->count)
1005 branch_type
1006 = ((*it)->count > 0) ? "taken" : "nottaken";
1007 else
1008 branch_type = "notexec";
1009 fprintf (f, "branch:%d,%s\n", line_num, branch_type);
1014 /* Get the name of the gcov file. The return value must be free'd.
1016 It appends the '.gcov' extension to the *basename* of the file.
1017 The resulting file name will be in PWD.
1019 e.g.,
1020 input: foo.da, output: foo.da.gcov
1021 input: a/b/foo.cc, output: foo.cc.gcov */
1023 static char *
1024 get_gcov_intermediate_filename (const char *file_name)
1026 const char *gcov = ".gcov";
1027 char *result;
1028 const char *cptr;
1030 /* Find the 'basename'. */
1031 cptr = lbasename (file_name);
1033 result = XNEWVEC (char, strlen (cptr) + strlen (gcov) + 1);
1034 sprintf (result, "%s%s", cptr, gcov);
1036 return result;
1039 /* Output the result in intermediate format used by 'lcov'.
1041 The intermediate format contains a single file named 'foo.cc.gcov',
1042 with no source code included.
1044 The default gcov outputs multiple files: 'foo.cc.gcov',
1045 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
1046 included. Instead the intermediate format here outputs only a single
1047 file 'foo.cc.gcov' similar to the above example. */
1049 static void
1050 output_intermediate_file (FILE *gcov_file, source_info *src)
1052 fprintf (gcov_file, "version:%s\n", version_string);
1053 fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
1054 fprintf (gcov_file, "cwd:%s\n", bbg_cwd);
1056 std::sort (src->functions.begin (), src->functions.end (),
1057 function_line_start_cmp ());
1058 for (vector<function_info *>::iterator it = src->functions.begin ();
1059 it != src->functions.end (); it++)
1061 /* function:<name>,<line_number>,<execution_count> */
1062 fprintf (gcov_file, "function:%d,%d,%s,%s\n", (*it)->start_line,
1063 (*it)->end_line, format_gcov ((*it)->blocks[0].count, 0, -1),
1064 flag_demangled_names ? (*it)->demangled_name : (*it)->name);
1067 for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
1069 vector<function_info *> fns = src->get_functions_at_location (line_num);
1071 /* Print first group functions that begin on the line. */
1072 for (vector<function_info *>::iterator it2 = fns.begin ();
1073 it2 != fns.end (); it2++)
1075 vector<line_info> &lines = (*it2)->lines;
1076 for (unsigned i = 0; i < lines.size (); i++)
1078 line_info *line = &lines[i];
1079 output_intermediate_line (gcov_file, line, line_num + i);
1083 /* Follow with lines associated with the source file. */
1084 output_intermediate_line (gcov_file, &src->lines[line_num], line_num);
1088 /* Function start pair. */
1089 struct function_start
1091 unsigned source_file_idx;
1092 unsigned start_line;
1095 /* Traits class for function start hash maps below. */
1097 struct function_start_pair_hash : typed_noop_remove <function_start>
1099 typedef function_start value_type;
1100 typedef function_start compare_type;
1102 static hashval_t
1103 hash (const function_start &ref)
1105 inchash::hash hstate (0);
1106 hstate.add_int (ref.source_file_idx);
1107 hstate.add_int (ref.start_line);
1108 return hstate.end ();
1111 static bool
1112 equal (const function_start &ref1, const function_start &ref2)
1114 return (ref1.source_file_idx == ref2.source_file_idx
1115 && ref1.start_line == ref2.start_line);
1118 static void
1119 mark_deleted (function_start &ref)
1121 ref.start_line = ~1U;
1124 static void
1125 mark_empty (function_start &ref)
1127 ref.start_line = ~2U;
1130 static bool
1131 is_deleted (const function_start &ref)
1133 return ref.start_line == ~1U;
1136 static bool
1137 is_empty (const function_start &ref)
1139 return ref.start_line == ~2U;
1143 /* Process a single input file. */
1145 static void
1146 process_file (const char *file_name)
1148 create_file_names (file_name);
1149 read_graph_file ();
1150 read_count_file ();
1153 /* Process all functions in all files. */
1155 static void
1156 process_all_functions (void)
1158 hash_map<function_start_pair_hash, function_info *> fn_map;
1160 /* Identify group functions. */
1161 for (vector<function_info *>::iterator it = functions.begin ();
1162 it != functions.end (); it++)
1163 if (!(*it)->artificial)
1165 function_start needle;
1166 needle.source_file_idx = (*it)->src;
1167 needle.start_line = (*it)->start_line;
1169 function_info **slot = fn_map.get (needle);
1170 if (slot)
1172 (*slot)->is_group = 1;
1173 (*it)->is_group = 1;
1175 else
1176 fn_map.put (needle, *it);
1179 /* Remove all artificial function. */
1180 functions.erase (remove_if (functions.begin (), functions.end (),
1181 function_info::is_artificial), functions.end ());
1183 for (vector<function_info *>::iterator it = functions.begin ();
1184 it != functions.end (); it++)
1186 function_info *fn = *it;
1187 unsigned src = fn->src;
1189 if (!fn->counts.empty () || no_data_file)
1191 source_info *s = &sources[src];
1192 s->functions.push_back (fn);
1194 /* Mark last line in files touched by function. */
1195 for (unsigned block_no = 0; block_no != fn->blocks.size ();
1196 block_no++)
1198 block_info *block = &fn->blocks[block_no];
1199 for (unsigned i = 0; i < block->locations.size (); i++)
1201 /* Sort lines of locations. */
1202 sort (block->locations[i].lines.begin (),
1203 block->locations[i].lines.end ());
1205 if (!block->locations[i].lines.empty ())
1207 s = &sources[block->locations[i].source_file_idx];
1208 unsigned last_line
1209 = block->locations[i].lines.back ();
1211 /* Record new lines for the function. */
1212 if (last_line >= s->lines.size ())
1214 s = &sources[block->locations[i].source_file_idx];
1215 unsigned last_line
1216 = block->locations[i].lines.back ();
1218 /* Record new lines for the function. */
1219 if (last_line >= s->lines.size ())
1221 /* Record new lines for a source file. */
1222 s->lines.resize (last_line + 1);
1229 /* Allocate lines for group function, following start_line
1230 and end_line information of the function. */
1231 if (fn->is_group)
1232 fn->lines.resize (fn->end_line - fn->start_line + 1);
1234 solve_flow_graph (fn);
1235 if (fn->has_catch)
1236 find_exception_blocks (fn);
1238 else
1240 /* The function was not in the executable -- some other
1241 instance must have been selected. */
1246 static void
1247 output_gcov_file (const char *file_name, source_info *src)
1249 char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
1251 if (src->coverage.lines)
1253 FILE *gcov_file = fopen (gcov_file_name, "w");
1254 if (gcov_file)
1256 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
1257 output_lines (gcov_file, src);
1258 if (ferror (gcov_file))
1259 fnotice (stderr, "Error writing output file '%s'\n",
1260 gcov_file_name);
1261 fclose (gcov_file);
1263 else
1264 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1266 else
1268 unlink (gcov_file_name);
1269 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1271 free (gcov_file_name);
1274 static void
1275 generate_results (const char *file_name)
1277 FILE *gcov_intermediate_file = NULL;
1278 char *gcov_intermediate_filename = NULL;
1280 for (vector<function_info *>::iterator it = functions.begin ();
1281 it != functions.end (); it++)
1283 function_info *fn = *it;
1284 coverage_info coverage;
1286 memset (&coverage, 0, sizeof (coverage));
1287 coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
1288 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1289 if (flag_function_summary)
1291 function_summary (&coverage, "Function");
1292 fnotice (stdout, "\n");
1296 name_map needle;
1298 if (file_name)
1300 needle.name = file_name;
1301 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1302 needle);
1303 if (it != names.end ())
1304 file_name = sources[it->src].coverage.name;
1305 else
1306 file_name = canonicalize_name (file_name);
1309 if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout)
1311 /* Open the intermediate file. */
1312 gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
1313 gcov_intermediate_file = fopen (gcov_intermediate_filename, "w");
1314 if (!gcov_intermediate_file)
1316 fnotice (stderr, "Cannot open intermediate output file %s\n",
1317 gcov_intermediate_filename);
1318 return;
1322 for (vector<source_info>::iterator it = sources.begin ();
1323 it != sources.end (); it++)
1325 source_info *src = &(*it);
1326 if (flag_relative_only)
1328 /* Ignore this source, if it is an absolute path (after
1329 source prefix removal). */
1330 char first = src->coverage.name[0];
1332 #if HAVE_DOS_BASED_FILE_SYSTEM
1333 if (first && src->coverage.name[1] == ':')
1334 first = src->coverage.name[2];
1335 #endif
1336 if (IS_DIR_SEPARATOR (first))
1337 continue;
1340 accumulate_line_counts (src);
1342 if (!flag_use_stdout)
1343 function_summary (&src->coverage, "File");
1344 total_lines += src->coverage.lines;
1345 total_executed += src->coverage.lines_executed;
1346 if (flag_gcov_file)
1348 if (flag_intermediate_format)
1349 /* Output the intermediate format without requiring source
1350 files. This outputs a section to a *single* file. */
1351 output_intermediate_file ((flag_use_stdout
1352 ? stdout : gcov_intermediate_file), src);
1353 else
1355 if (flag_use_stdout)
1357 if (src->coverage.lines)
1358 output_lines (stdout, src);
1360 else
1362 output_gcov_file (file_name, src);
1363 fnotice (stdout, "\n");
1369 if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout)
1371 /* Now we've finished writing the intermediate file. */
1372 fclose (gcov_intermediate_file);
1373 XDELETEVEC (gcov_intermediate_filename);
1376 if (!file_name)
1377 executed_summary (total_lines, total_executed);
1380 /* Release all memory used. */
1382 static void
1383 release_structures (void)
1385 for (vector<function_info *>::iterator it = functions.begin ();
1386 it != functions.end (); it++)
1387 delete (*it);
1389 sources.resize (0);
1390 names.resize (0);
1391 functions.resize (0);
1394 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1395 is not specified, these are named from FILE_NAME sans extension. If
1396 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1397 directory, but named from the basename of the FILE_NAME, sans extension.
1398 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1399 and the data files are named from that. */
1401 static void
1402 create_file_names (const char *file_name)
1404 char *cptr;
1405 char *name;
1406 int length = strlen (file_name);
1407 int base;
1409 /* Free previous file names. */
1410 free (bbg_file_name);
1411 free (da_file_name);
1412 da_file_name = bbg_file_name = NULL;
1413 bbg_file_time = 0;
1414 bbg_stamp = 0;
1416 if (object_directory && object_directory[0])
1418 struct stat status;
1420 length += strlen (object_directory) + 2;
1421 name = XNEWVEC (char, length);
1422 name[0] = 0;
1424 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1425 strcat (name, object_directory);
1426 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1427 strcat (name, "/");
1429 else
1431 name = XNEWVEC (char, length + 1);
1432 strcpy (name, file_name);
1433 base = 0;
1436 if (base)
1438 /* Append source file name. */
1439 const char *cptr = lbasename (file_name);
1440 strcat (name, cptr ? cptr : file_name);
1443 /* Remove the extension. */
1444 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1445 if (cptr)
1446 *cptr = 0;
1448 length = strlen (name);
1450 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1451 strcpy (bbg_file_name, name);
1452 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1454 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1455 strcpy (da_file_name, name);
1456 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1458 free (name);
1459 return;
1462 /* Find or create a source file structure for FILE_NAME. Copies
1463 FILE_NAME on creation */
1465 static unsigned
1466 find_source (const char *file_name)
1468 char *canon;
1469 unsigned idx;
1470 struct stat status;
1472 if (!file_name)
1473 file_name = "<unknown>";
1475 name_map needle;
1476 needle.name = file_name;
1478 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1479 needle);
1480 if (it != names.end ())
1482 idx = it->src;
1483 goto check_date;
1486 /* Not found, try the canonical name. */
1487 canon = canonicalize_name (file_name);
1488 needle.name = canon;
1489 it = std::find (names.begin (), names.end (), needle);
1490 if (it == names.end ())
1492 /* Not found with canonical name, create a new source. */
1493 source_info *src;
1495 idx = sources.size ();
1496 needle = name_map (canon, idx);
1497 names.push_back (needle);
1499 sources.push_back (source_info ());
1500 src = &sources.back ();
1501 src->name = canon;
1502 src->coverage.name = src->name;
1503 src->index = idx;
1504 if (source_length
1505 #if HAVE_DOS_BASED_FILE_SYSTEM
1506 /* You lose if separators don't match exactly in the
1507 prefix. */
1508 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1509 #else
1510 && !strncmp (source_prefix, src->coverage.name, source_length)
1511 #endif
1512 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1513 src->coverage.name += source_length + 1;
1514 if (!stat (src->name, &status))
1515 src->file_time = status.st_mtime;
1517 else
1518 idx = it->src;
1520 needle.name = file_name;
1521 if (std::find (names.begin (), names.end (), needle) == names.end ())
1523 /* Append the non-canonical name. */
1524 names.push_back (name_map (xstrdup (file_name), idx));
1527 /* Resort the name map. */
1528 std::sort (names.begin (), names.end ());
1530 check_date:
1531 if (sources[idx].file_time > bbg_file_time)
1533 static int info_emitted;
1535 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1536 file_name, bbg_file_name);
1537 if (!info_emitted)
1539 fnotice (stderr,
1540 "(the message is displayed only once per source file)\n");
1541 info_emitted = 1;
1543 sources[idx].file_time = 0;
1546 return idx;
1549 /* Read the notes file. Save functions to FUNCTIONS global vector. */
1551 static void
1552 read_graph_file (void)
1554 unsigned version;
1555 unsigned current_tag = 0;
1556 unsigned tag;
1558 if (!gcov_open (bbg_file_name, 1))
1560 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1561 return;
1563 bbg_file_time = gcov_time ();
1564 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1566 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1567 gcov_close ();
1568 return;
1571 version = gcov_read_unsigned ();
1572 if (version != GCOV_VERSION)
1574 char v[4], e[4];
1576 GCOV_UNSIGNED2STRING (v, version);
1577 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1579 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1580 bbg_file_name, v, e);
1582 bbg_stamp = gcov_read_unsigned ();
1583 bbg_cwd = xstrdup (gcov_read_string ());
1584 bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
1586 function_info *fn = NULL;
1587 while ((tag = gcov_read_unsigned ()))
1589 unsigned length = gcov_read_unsigned ();
1590 gcov_position_t base = gcov_position ();
1592 if (tag == GCOV_TAG_FUNCTION)
1594 char *function_name;
1595 unsigned ident;
1596 unsigned lineno_checksum, cfg_checksum;
1598 ident = gcov_read_unsigned ();
1599 lineno_checksum = gcov_read_unsigned ();
1600 cfg_checksum = gcov_read_unsigned ();
1601 function_name = xstrdup (gcov_read_string ());
1602 unsigned artificial = gcov_read_unsigned ();
1603 unsigned src_idx = find_source (gcov_read_string ());
1604 unsigned start_line = gcov_read_unsigned ();
1605 unsigned start_column = gcov_read_unsigned ();
1606 unsigned end_line = gcov_read_unsigned ();
1608 fn = new function_info ();
1609 functions.push_back (fn);
1610 fn->name = function_name;
1611 if (flag_demangled_names)
1613 fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1614 if (!fn->demangled_name)
1615 fn->demangled_name = fn->name;
1617 fn->ident = ident;
1618 fn->lineno_checksum = lineno_checksum;
1619 fn->cfg_checksum = cfg_checksum;
1620 fn->src = src_idx;
1621 fn->start_line = start_line;
1622 fn->start_column = start_column;
1623 fn->end_line = end_line;
1624 fn->artificial = artificial;
1626 current_tag = tag;
1628 else if (fn && tag == GCOV_TAG_BLOCKS)
1630 if (!fn->blocks.empty ())
1631 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1632 bbg_file_name, fn->name);
1633 else
1634 fn->blocks.resize (gcov_read_unsigned ());
1636 else if (fn && tag == GCOV_TAG_ARCS)
1638 unsigned src = gcov_read_unsigned ();
1639 fn->blocks[src].id = src;
1640 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1641 block_info *src_blk = &fn->blocks[src];
1642 unsigned mark_catches = 0;
1643 struct arc_info *arc;
1645 if (src >= fn->blocks.size () || fn->blocks[src].succ)
1646 goto corrupt;
1648 while (num_dests--)
1650 unsigned dest = gcov_read_unsigned ();
1651 unsigned flags = gcov_read_unsigned ();
1653 if (dest >= fn->blocks.size ())
1654 goto corrupt;
1655 arc = XCNEW (arc_info);
1657 arc->dst = &fn->blocks[dest];
1658 arc->src = src_blk;
1660 arc->count = 0;
1661 arc->count_valid = 0;
1662 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1663 arc->fake = !!(flags & GCOV_ARC_FAKE);
1664 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1666 arc->succ_next = src_blk->succ;
1667 src_blk->succ = arc;
1668 src_blk->num_succ++;
1670 arc->pred_next = fn->blocks[dest].pred;
1671 fn->blocks[dest].pred = arc;
1672 fn->blocks[dest].num_pred++;
1674 if (arc->fake)
1676 if (src)
1678 /* Exceptional exit from this function, the
1679 source block must be a call. */
1680 fn->blocks[src].is_call_site = 1;
1681 arc->is_call_non_return = 1;
1682 mark_catches = 1;
1684 else
1686 /* Non-local return from a callee of this
1687 function. The destination block is a setjmp. */
1688 arc->is_nonlocal_return = 1;
1689 fn->blocks[dest].is_nonlocal_return = 1;
1693 if (!arc->on_tree)
1694 fn->counts.push_back (0);
1697 if (mark_catches)
1699 /* We have a fake exit from this block. The other
1700 non-fall through exits must be to catch handlers.
1701 Mark them as catch arcs. */
1703 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1704 if (!arc->fake && !arc->fall_through)
1706 arc->is_throw = 1;
1707 fn->has_catch = 1;
1711 else if (fn && tag == GCOV_TAG_LINES)
1713 unsigned blockno = gcov_read_unsigned ();
1714 block_info *block = &fn->blocks[blockno];
1716 if (blockno >= fn->blocks.size ())
1717 goto corrupt;
1719 while (true)
1721 unsigned lineno = gcov_read_unsigned ();
1723 if (lineno)
1724 block->locations.back ().lines.push_back (lineno);
1725 else
1727 const char *file_name = gcov_read_string ();
1729 if (!file_name)
1730 break;
1731 block->locations.push_back (block_location_info
1732 (find_source (file_name)));
1736 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1738 fn = NULL;
1739 current_tag = 0;
1741 gcov_sync (base, length);
1742 if (gcov_is_error ())
1744 corrupt:;
1745 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1746 break;
1749 gcov_close ();
1751 if (functions.empty ())
1752 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1755 /* Reads profiles from the count file and attach to each
1756 function. Return nonzero if fatal error. */
1758 static int
1759 read_count_file (void)
1761 unsigned ix;
1762 unsigned version;
1763 unsigned tag;
1764 function_info *fn = NULL;
1765 int error = 0;
1767 if (!gcov_open (da_file_name, 1))
1769 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1770 da_file_name);
1771 no_data_file = 1;
1772 return 0;
1774 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1776 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1777 cleanup:;
1778 gcov_close ();
1779 return 1;
1781 version = gcov_read_unsigned ();
1782 if (version != GCOV_VERSION)
1784 char v[4], e[4];
1786 GCOV_UNSIGNED2STRING (v, version);
1787 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1789 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1790 da_file_name, v, e);
1792 tag = gcov_read_unsigned ();
1793 if (tag != bbg_stamp)
1795 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1796 goto cleanup;
1799 while ((tag = gcov_read_unsigned ()))
1801 unsigned length = gcov_read_unsigned ();
1802 unsigned long base = gcov_position ();
1804 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1806 struct gcov_summary summary;
1807 gcov_read_summary (&summary);
1808 object_runs += summary.runs;
1809 program_count++;
1811 else if (tag == GCOV_TAG_FUNCTION && !length)
1812 ; /* placeholder */
1813 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1815 unsigned ident;
1817 /* Try to find the function in the list. To speed up the
1818 search, first start from the last function found. */
1819 ident = gcov_read_unsigned ();
1821 fn = NULL;
1822 for (vector<function_info *>::reverse_iterator it
1823 = functions.rbegin (); it != functions.rend (); it++)
1825 if ((*it)->ident == ident)
1827 fn = *it;
1828 break;
1832 if (!fn)
1834 else if (gcov_read_unsigned () != fn->lineno_checksum
1835 || gcov_read_unsigned () != fn->cfg_checksum)
1837 mismatch:;
1838 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1839 da_file_name, fn->name);
1840 goto cleanup;
1843 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1845 if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
1846 goto mismatch;
1848 for (ix = 0; ix != fn->counts.size (); ix++)
1849 fn->counts[ix] += gcov_read_counter ();
1851 gcov_sync (base, length);
1852 if ((error = gcov_is_error ()))
1854 fnotice (stderr,
1855 error < 0
1856 ? N_("%s:overflowed\n")
1857 : N_("%s:corrupted\n"),
1858 da_file_name);
1859 goto cleanup;
1863 gcov_close ();
1864 return 0;
1867 /* Solve the flow graph. Propagate counts from the instrumented arcs
1868 to the blocks and the uninstrumented arcs. */
1870 static void
1871 solve_flow_graph (function_info *fn)
1873 unsigned ix;
1874 arc_info *arc;
1875 gcov_type *count_ptr = &fn->counts.front ();
1876 block_info *blk;
1877 block_info *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1878 block_info *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1880 /* The arcs were built in reverse order. Fix that now. */
1881 for (ix = fn->blocks.size (); ix--;)
1883 arc_info *arc_p, *arc_n;
1885 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1886 arc_p = arc, arc = arc_n)
1888 arc_n = arc->succ_next;
1889 arc->succ_next = arc_p;
1891 fn->blocks[ix].succ = arc_p;
1893 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1894 arc_p = arc, arc = arc_n)
1896 arc_n = arc->pred_next;
1897 arc->pred_next = arc_p;
1899 fn->blocks[ix].pred = arc_p;
1902 if (fn->blocks.size () < 2)
1903 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1904 bbg_file_name, fn->name);
1905 else
1907 if (fn->blocks[ENTRY_BLOCK].num_pred)
1908 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1909 bbg_file_name, fn->name);
1910 else
1911 /* We can't deduce the entry block counts from the lack of
1912 predecessors. */
1913 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1915 if (fn->blocks[EXIT_BLOCK].num_succ)
1916 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1917 bbg_file_name, fn->name);
1918 else
1919 /* Likewise, we can't deduce exit block counts from the lack
1920 of its successors. */
1921 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1924 /* Propagate the measured counts, this must be done in the same
1925 order as the code in profile.c */
1926 for (unsigned i = 0; i < fn->blocks.size (); i++)
1928 blk = &fn->blocks[i];
1929 block_info const *prev_dst = NULL;
1930 int out_of_order = 0;
1931 int non_fake_succ = 0;
1933 for (arc = blk->succ; arc; arc = arc->succ_next)
1935 if (!arc->fake)
1936 non_fake_succ++;
1938 if (!arc->on_tree)
1940 if (count_ptr)
1941 arc->count = *count_ptr++;
1942 arc->count_valid = 1;
1943 blk->num_succ--;
1944 arc->dst->num_pred--;
1946 if (prev_dst && prev_dst > arc->dst)
1947 out_of_order = 1;
1948 prev_dst = arc->dst;
1950 if (non_fake_succ == 1)
1952 /* If there is only one non-fake exit, it is an
1953 unconditional branch. */
1954 for (arc = blk->succ; arc; arc = arc->succ_next)
1955 if (!arc->fake)
1957 arc->is_unconditional = 1;
1958 /* If this block is instrumenting a call, it might be
1959 an artificial block. It is not artificial if it has
1960 a non-fallthrough exit, or the destination of this
1961 arc has more than one entry. Mark the destination
1962 block as a return site, if none of those conditions
1963 hold. */
1964 if (blk->is_call_site && arc->fall_through
1965 && arc->dst->pred == arc && !arc->pred_next)
1966 arc->dst->is_call_return = 1;
1970 /* Sort the successor arcs into ascending dst order. profile.c
1971 normally produces arcs in the right order, but sometimes with
1972 one or two out of order. We're not using a particularly
1973 smart sort. */
1974 if (out_of_order)
1976 arc_info *start = blk->succ;
1977 unsigned changes = 1;
1979 while (changes)
1981 arc_info *arc, *arc_p, *arc_n;
1983 changes = 0;
1984 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1986 if (arc->dst > arc_n->dst)
1988 changes = 1;
1989 if (arc_p)
1990 arc_p->succ_next = arc_n;
1991 else
1992 start = arc_n;
1993 arc->succ_next = arc_n->succ_next;
1994 arc_n->succ_next = arc;
1995 arc_p = arc_n;
1997 else
1999 arc_p = arc;
2000 arc = arc_n;
2004 blk->succ = start;
2007 /* Place it on the invalid chain, it will be ignored if that's
2008 wrong. */
2009 blk->invalid_chain = 1;
2010 blk->chain = invalid_blocks;
2011 invalid_blocks = blk;
2014 while (invalid_blocks || valid_blocks)
2016 while ((blk = invalid_blocks))
2018 gcov_type total = 0;
2019 const arc_info *arc;
2021 invalid_blocks = blk->chain;
2022 blk->invalid_chain = 0;
2023 if (!blk->num_succ)
2024 for (arc = blk->succ; arc; arc = arc->succ_next)
2025 total += arc->count;
2026 else if (!blk->num_pred)
2027 for (arc = blk->pred; arc; arc = arc->pred_next)
2028 total += arc->count;
2029 else
2030 continue;
2032 blk->count = total;
2033 blk->count_valid = 1;
2034 blk->chain = valid_blocks;
2035 blk->valid_chain = 1;
2036 valid_blocks = blk;
2038 while ((blk = valid_blocks))
2040 gcov_type total;
2041 arc_info *arc, *inv_arc;
2043 valid_blocks = blk->chain;
2044 blk->valid_chain = 0;
2045 if (blk->num_succ == 1)
2047 block_info *dst;
2049 total = blk->count;
2050 inv_arc = NULL;
2051 for (arc = blk->succ; arc; arc = arc->succ_next)
2053 total -= arc->count;
2054 if (!arc->count_valid)
2055 inv_arc = arc;
2057 dst = inv_arc->dst;
2058 inv_arc->count_valid = 1;
2059 inv_arc->count = total;
2060 blk->num_succ--;
2061 dst->num_pred--;
2062 if (dst->count_valid)
2064 if (dst->num_pred == 1 && !dst->valid_chain)
2066 dst->chain = valid_blocks;
2067 dst->valid_chain = 1;
2068 valid_blocks = dst;
2071 else
2073 if (!dst->num_pred && !dst->invalid_chain)
2075 dst->chain = invalid_blocks;
2076 dst->invalid_chain = 1;
2077 invalid_blocks = dst;
2081 if (blk->num_pred == 1)
2083 block_info *src;
2085 total = blk->count;
2086 inv_arc = NULL;
2087 for (arc = blk->pred; arc; arc = arc->pred_next)
2089 total -= arc->count;
2090 if (!arc->count_valid)
2091 inv_arc = arc;
2093 src = inv_arc->src;
2094 inv_arc->count_valid = 1;
2095 inv_arc->count = total;
2096 blk->num_pred--;
2097 src->num_succ--;
2098 if (src->count_valid)
2100 if (src->num_succ == 1 && !src->valid_chain)
2102 src->chain = valid_blocks;
2103 src->valid_chain = 1;
2104 valid_blocks = src;
2107 else
2109 if (!src->num_succ && !src->invalid_chain)
2111 src->chain = invalid_blocks;
2112 src->invalid_chain = 1;
2113 invalid_blocks = src;
2120 /* If the graph has been correctly solved, every block will have a
2121 valid count. */
2122 for (unsigned i = 0; ix < fn->blocks.size (); i++)
2123 if (!fn->blocks[i].count_valid)
2125 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
2126 bbg_file_name, fn->name);
2127 break;
2131 /* Mark all the blocks only reachable via an incoming catch. */
2133 static void
2134 find_exception_blocks (function_info *fn)
2136 unsigned ix;
2137 block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ());
2139 /* First mark all blocks as exceptional. */
2140 for (ix = fn->blocks.size (); ix--;)
2141 fn->blocks[ix].exceptional = 1;
2143 /* Now mark all the blocks reachable via non-fake edges */
2144 queue[0] = &fn->blocks[0];
2145 queue[0]->exceptional = 0;
2146 for (ix = 1; ix;)
2148 block_info *block = queue[--ix];
2149 const arc_info *arc;
2151 for (arc = block->succ; arc; arc = arc->succ_next)
2152 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
2154 arc->dst->exceptional = 0;
2155 queue[ix++] = arc->dst;
2161 /* Increment totals in COVERAGE according to arc ARC. */
2163 static void
2164 add_branch_counts (coverage_info *coverage, const arc_info *arc)
2166 if (arc->is_call_non_return)
2168 coverage->calls++;
2169 if (arc->src->count)
2170 coverage->calls_executed++;
2172 else if (!arc->is_unconditional)
2174 coverage->branches++;
2175 if (arc->src->count)
2176 coverage->branches_executed++;
2177 if (arc->count)
2178 coverage->branches_taken++;
2182 /* Format COUNT, if flag_human_readable_numbers is set, return it human
2183 readable format. */
2185 static char const *
2186 format_count (gcov_type count)
2188 static char buffer[64];
2189 const char *units = " kMGTPEZY";
2191 if (count < 1000 || !flag_human_readable_numbers)
2193 sprintf (buffer, "%" PRId64, count);
2194 return buffer;
2197 unsigned i;
2198 gcov_type divisor = 1;
2199 for (i = 0; units[i+1]; i++, divisor *= 1000)
2201 if (count + divisor / 2 < 1000 * divisor)
2202 break;
2204 gcov_type r = (count + divisor / 2) / divisor;
2205 sprintf (buffer, "%" PRId64 "%c", r, units[i]);
2206 return buffer;
2209 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
2210 count. If DECIMAL_PLACES >= 0, format TOP/BOTTOM * 100 to DECIMAL_PLACES.
2211 If DECIMAL_PLACES is zero, no decimal point is printed. Only print 100% when
2212 TOP==BOTTOM and only print 0% when TOP=0. If DECIMAL_PLACES < 0, then simply
2213 format TOP. Return pointer to a static string. */
2215 static char const *
2216 format_gcov (gcov_type top, gcov_type bottom, int decimal_places)
2218 static char buffer[20];
2220 if (decimal_places >= 0)
2222 float ratio = bottom ? 100.0f * top / bottom: 0;
2224 /* Round up to 1% if there's a small non-zero value. */
2225 if (ratio > 0.0f && ratio < 0.5f && decimal_places == 0)
2226 ratio = 1.0f;
2227 sprintf (buffer, "%.*f%%", decimal_places, ratio);
2229 else
2230 return format_count (top);
2232 return buffer;
2235 /* Summary of execution */
2237 static void
2238 executed_summary (unsigned lines, unsigned executed)
2240 if (lines)
2241 fnotice (stdout, "Lines executed:%s of %d\n",
2242 format_gcov (executed, lines, 2), lines);
2243 else
2244 fnotice (stdout, "No executable lines\n");
2247 /* Output summary info for a function or file. */
2249 static void
2250 function_summary (const coverage_info *coverage, const char *title)
2252 fnotice (stdout, "%s '%s'\n", title, coverage->name);
2253 executed_summary (coverage->lines, coverage->lines_executed);
2255 if (flag_branches)
2257 if (coverage->branches)
2259 fnotice (stdout, "Branches executed:%s of %d\n",
2260 format_gcov (coverage->branches_executed,
2261 coverage->branches, 2),
2262 coverage->branches);
2263 fnotice (stdout, "Taken at least once:%s of %d\n",
2264 format_gcov (coverage->branches_taken,
2265 coverage->branches, 2),
2266 coverage->branches);
2268 else
2269 fnotice (stdout, "No branches\n");
2270 if (coverage->calls)
2271 fnotice (stdout, "Calls executed:%s of %d\n",
2272 format_gcov (coverage->calls_executed, coverage->calls, 2),
2273 coverage->calls);
2274 else
2275 fnotice (stdout, "No calls\n");
2279 /* Canonicalize the filename NAME by canonicalizing directory
2280 separators, eliding . components and resolving .. components
2281 appropriately. Always returns a unique string. */
2283 static char *
2284 canonicalize_name (const char *name)
2286 /* The canonical name cannot be longer than the incoming name. */
2287 char *result = XNEWVEC (char, strlen (name) + 1);
2288 const char *base = name, *probe;
2289 char *ptr = result;
2290 char *dd_base;
2291 int slash = 0;
2293 #if HAVE_DOS_BASED_FILE_SYSTEM
2294 if (base[0] && base[1] == ':')
2296 result[0] = base[0];
2297 result[1] = ':';
2298 base += 2;
2299 ptr += 2;
2301 #endif
2302 for (dd_base = ptr; *base; base = probe)
2304 size_t len;
2306 for (probe = base; *probe; probe++)
2307 if (IS_DIR_SEPARATOR (*probe))
2308 break;
2310 len = probe - base;
2311 if (len == 1 && base[0] == '.')
2312 /* Elide a '.' directory */
2314 else if (len == 2 && base[0] == '.' && base[1] == '.')
2316 /* '..', we can only elide it and the previous directory, if
2317 we're not a symlink. */
2318 struct stat ATTRIBUTE_UNUSED buf;
2320 *ptr = 0;
2321 if (dd_base == ptr
2322 #if defined (S_ISLNK)
2323 /* S_ISLNK is not POSIX.1-1996. */
2324 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2325 #endif
2328 /* Cannot elide, or unreadable or a symlink. */
2329 dd_base = ptr + 2 + slash;
2330 goto regular;
2332 while (ptr != dd_base && *ptr != '/')
2333 ptr--;
2334 slash = ptr != result;
2336 else
2338 regular:
2339 /* Regular pathname component. */
2340 if (slash)
2341 *ptr++ = '/';
2342 memcpy (ptr, base, len);
2343 ptr += len;
2344 slash = 1;
2347 for (; IS_DIR_SEPARATOR (*probe); probe++)
2348 continue;
2350 *ptr = 0;
2352 return result;
2355 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2357 static void
2358 md5sum_to_hex (const char *sum, char *buffer)
2360 for (unsigned i = 0; i < 16; i++)
2361 sprintf (buffer + (2 * i), "%02x", (unsigned char)sum[i]);
2364 /* Generate an output file name. INPUT_NAME is the canonicalized main
2365 input file and SRC_NAME is the canonicalized file name.
2366 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2367 long_output_names we prepend the processed name of the input file
2368 to each output name (except when the current source file is the
2369 input file, so you don't get a double concatenation). The two
2370 components are separated by '##'. With preserve_paths we create a
2371 filename from all path components of the source file, replacing '/'
2372 with '#', and .. with '^', without it we simply take the basename
2373 component. (Remember, the canonicalized name will already have
2374 elided '.' components and converted \\ separators.) */
2376 static char *
2377 make_gcov_file_name (const char *input_name, const char *src_name)
2379 char *ptr;
2380 char *result;
2382 if (flag_long_names && input_name && strcmp (src_name, input_name))
2384 /* Generate the input filename part. */
2385 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
2387 ptr = result;
2388 ptr = mangle_name (input_name, ptr);
2389 ptr[0] = ptr[1] = '#';
2390 ptr += 2;
2392 else
2394 result = XNEWVEC (char, strlen (src_name) + 10);
2395 ptr = result;
2398 ptr = mangle_name (src_name, ptr);
2399 strcpy (ptr, ".gcov");
2401 /* When hashing filenames, we shorten them by only using the filename
2402 component and appending a hash of the full (mangled) pathname. */
2403 if (flag_hash_filenames)
2405 md5_ctx ctx;
2406 char md5sum[16];
2407 char md5sum_hex[33];
2409 md5_init_ctx (&ctx);
2410 md5_process_bytes (src_name, strlen (src_name), &ctx);
2411 md5_finish_ctx (&ctx, md5sum);
2412 md5sum_to_hex (md5sum, md5sum_hex);
2413 free (result);
2415 result = XNEWVEC (char, strlen (src_name) + 50);
2416 ptr = result;
2417 ptr = mangle_name (src_name, ptr);
2418 ptr[0] = ptr[1] = '#';
2419 ptr += 2;
2420 memcpy (ptr, md5sum_hex, 32);
2421 ptr += 32;
2422 strcpy (ptr, ".gcov");
2425 return result;
2428 static char *
2429 mangle_name (char const *base, char *ptr)
2431 size_t len;
2433 /* Generate the source filename part. */
2434 if (!flag_preserve_paths)
2436 base = lbasename (base);
2437 len = strlen (base);
2438 memcpy (ptr, base, len);
2439 ptr += len;
2441 else
2442 ptr = mangle_path (base);
2444 return ptr;
2447 /* Scan through the bb_data for each line in the block, increment
2448 the line number execution count indicated by the execution count of
2449 the appropriate basic block. */
2451 static void
2452 add_line_counts (coverage_info *coverage, function_info *fn)
2454 bool has_any_line = false;
2455 /* Scan each basic block. */
2456 for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
2458 line_info *line = NULL;
2459 block_info *block = &fn->blocks[ix];
2460 if (block->count && ix && ix + 1 != fn->blocks.size ())
2461 fn->blocks_executed++;
2462 for (unsigned i = 0; i < block->locations.size (); i++)
2464 unsigned src_idx = block->locations[i].source_file_idx;
2465 vector<unsigned> &lines = block->locations[i].lines;
2467 block->cycle.arc = NULL;
2468 block->cycle.ident = ~0U;
2470 for (unsigned j = 0; j < lines.size (); j++)
2472 unsigned ln = lines[j];
2474 /* Line belongs to a function that is in a group. */
2475 if (fn->group_line_p (ln, src_idx))
2477 gcc_assert (lines[j] - fn->start_line < fn->lines.size ());
2478 line = &(fn->lines[lines[j] - fn->start_line]);
2479 line->exists = 1;
2480 if (!block->exceptional)
2482 line->unexceptional = 1;
2483 if (block->count == 0)
2484 line->has_unexecuted_block = 1;
2486 line->count += block->count;
2488 else
2490 gcc_assert (ln < sources[src_idx].lines.size ());
2491 line = &(sources[src_idx].lines[ln]);
2492 if (coverage)
2494 if (!line->exists)
2495 coverage->lines++;
2496 if (!line->count && block->count)
2497 coverage->lines_executed++;
2499 line->exists = 1;
2500 if (!block->exceptional)
2502 line->unexceptional = 1;
2503 if (block->count == 0)
2504 line->has_unexecuted_block = 1;
2506 line->count += block->count;
2510 has_any_line = true;
2512 if (!ix || ix + 1 == fn->blocks.size ())
2513 /* Entry or exit block. */;
2514 else if (line != NULL)
2516 line->blocks.push_back (block);
2518 if (flag_branches)
2520 arc_info *arc;
2522 for (arc = block->succ; arc; arc = arc->succ_next)
2523 line->branches.push_back (arc);
2529 if (!has_any_line)
2530 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
2533 /* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE
2534 is set to true, update source file summary. */
2536 static void accumulate_line_info (line_info *line, source_info *src,
2537 bool add_coverage)
2539 if (add_coverage)
2540 for (vector<arc_info *>::iterator it = line->branches.begin ();
2541 it != line->branches.end (); it++)
2542 add_branch_counts (&src->coverage, *it);
2544 if (!line->blocks.empty ())
2546 /* The user expects the line count to be the number of times
2547 a line has been executed. Simply summing the block count
2548 will give an artificially high number. The Right Thing
2549 is to sum the entry counts to the graph of blocks on this
2550 line, then find the elementary cycles of the local graph
2551 and add the transition counts of those cycles. */
2552 gcov_type count = 0;
2554 /* Cycle detection. */
2555 for (vector<block_info *>::iterator it = line->blocks.begin ();
2556 it != line->blocks.end (); it++)
2558 for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next)
2559 if (!line->has_block (arc->src))
2560 count += arc->count;
2561 for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next)
2562 arc->cs_count = arc->count;
2565 /* Now, add the count of loops entirely on this line. */
2566 count += get_cycles_count (*line);
2567 line->count = count;
2570 if (line->exists && add_coverage)
2572 src->coverage.lines++;
2573 if (line->count)
2574 src->coverage.lines_executed++;
2578 /* Accumulate the line counts of a file. */
2580 static void
2581 accumulate_line_counts (source_info *src)
2583 /* First work on group functions. */
2584 for (vector<function_info *>::iterator it = src->functions.begin ();
2585 it != src->functions.end (); it++)
2587 function_info *fn = *it;
2589 if (fn->src != src->index || !fn->is_group)
2590 continue;
2592 for (vector<line_info>::iterator it2 = fn->lines.begin ();
2593 it2 != fn->lines.end (); it2++)
2595 line_info *line = &(*it2);
2596 accumulate_line_info (line, src, false);
2600 /* Work on global lines that line in source file SRC. */
2601 for (vector<line_info>::iterator it = src->lines.begin ();
2602 it != src->lines.end (); it++)
2603 accumulate_line_info (&(*it), src, true);
2605 /* If not using intermediate mode, sum lines of group functions and
2606 add them to lines that live in a source file. */
2607 if (!flag_intermediate_format)
2608 for (vector<function_info *>::iterator it = src->functions.begin ();
2609 it != src->functions.end (); it++)
2611 function_info *fn = *it;
2613 if (fn->src != src->index || !fn->is_group)
2614 continue;
2616 for (unsigned i = 0; i < fn->lines.size (); i++)
2618 line_info *fn_line = &fn->lines[i];
2619 if (fn_line->exists)
2621 unsigned ln = fn->start_line + i;
2622 line_info *src_line = &src->lines[ln];
2624 if (!src_line->exists)
2625 src->coverage.lines++;
2626 if (!src_line->count && fn_line->count)
2627 src->coverage.lines_executed++;
2629 src_line->count += fn_line->count;
2630 src_line->exists = 1;
2632 if (fn_line->has_unexecuted_block)
2633 src_line->has_unexecuted_block = 1;
2635 if (fn_line->unexceptional)
2636 src_line->unexceptional = 1;
2642 /* Output information about ARC number IX. Returns nonzero if
2643 anything is output. */
2645 static int
2646 output_branch_count (FILE *gcov_file, int ix, const arc_info *arc)
2648 if (arc->is_call_non_return)
2650 if (arc->src->count)
2652 fnotice (gcov_file, "call %2d returned %s\n", ix,
2653 format_gcov (arc->src->count - arc->count,
2654 arc->src->count, -flag_counts));
2656 else
2657 fnotice (gcov_file, "call %2d never executed\n", ix);
2659 else if (!arc->is_unconditional)
2661 if (arc->src->count)
2662 fnotice (gcov_file, "branch %2d taken %s%s", ix,
2663 format_gcov (arc->count, arc->src->count, -flag_counts),
2664 arc->fall_through ? " (fallthrough)"
2665 : arc->is_throw ? " (throw)" : "");
2666 else
2667 fnotice (gcov_file, "branch %2d never executed", ix);
2669 if (flag_verbose)
2670 fnotice (gcov_file, " (BB %d)", arc->dst->id);
2672 fnotice (gcov_file, "\n");
2674 else if (flag_unconditional && !arc->dst->is_call_return)
2676 if (arc->src->count)
2677 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2678 format_gcov (arc->count, arc->src->count, -flag_counts));
2679 else
2680 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2682 else
2683 return 0;
2684 return 1;
2687 static const char *
2688 read_line (FILE *file)
2690 static char *string;
2691 static size_t string_len;
2692 size_t pos = 0;
2693 char *ptr;
2695 if (!string_len)
2697 string_len = 200;
2698 string = XNEWVEC (char, string_len);
2701 while ((ptr = fgets (string + pos, string_len - pos, file)))
2703 size_t len = strlen (string + pos);
2705 if (len && string[pos + len - 1] == '\n')
2707 string[pos + len - 1] = 0;
2708 return string;
2710 pos += len;
2711 /* If the file contains NUL characters or an incomplete
2712 last line, which can happen more than once in one run,
2713 we have to avoid doubling the STRING_LEN unnecessarily. */
2714 if (pos > string_len / 2)
2716 string_len *= 2;
2717 string = XRESIZEVEC (char, string, string_len);
2721 return pos ? string : NULL;
2724 /* Pad string S with spaces from left to have total width equal to 9. */
2726 static void
2727 pad_count_string (string &s)
2729 if (s.size () < 9)
2730 s.insert (0, 9 - s.size (), ' ');
2733 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2734 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2735 an exceptional statement. The output is printed for LINE_NUM of given
2736 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2737 used to indicate non-executed blocks. */
2739 static void
2740 output_line_beginning (FILE *f, bool exists, bool unexceptional,
2741 bool has_unexecuted_block,
2742 gcov_type count, unsigned line_num,
2743 const char *exceptional_string,
2744 const char *unexceptional_string)
2746 string s;
2747 if (exists)
2749 if (count > 0)
2751 s = format_gcov (count, 0, -1);
2752 if (has_unexecuted_block
2753 && bbg_supports_has_unexecuted_blocks)
2755 if (flag_use_colors)
2757 pad_count_string (s);
2758 s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
2759 COLOR_SEPARATOR COLOR_FG_WHITE));
2760 s += SGR_RESET;
2762 else
2763 s += "*";
2765 pad_count_string (s);
2767 else
2769 if (flag_use_colors)
2771 s = "0";
2772 pad_count_string (s);
2773 if (unexceptional)
2774 s.insert (0, SGR_SEQ (COLOR_BG_RED
2775 COLOR_SEPARATOR COLOR_FG_WHITE));
2776 else
2777 s.insert (0, SGR_SEQ (COLOR_BG_CYAN
2778 COLOR_SEPARATOR COLOR_FG_WHITE));
2779 s += SGR_RESET;
2781 else
2783 s = unexceptional ? unexceptional_string : exceptional_string;
2784 pad_count_string (s);
2788 else
2790 s = "-";
2791 pad_count_string (s);
2794 fprintf (f, "%s:%5u", s.c_str (), line_num);
2797 static void
2798 print_source_line (FILE *f, const vector<const char *> &source_lines,
2799 unsigned line)
2801 gcc_assert (line >= 1);
2802 gcc_assert (line <= source_lines.size ());
2804 fprintf (f, ":%s\n", source_lines[line - 1]);
2807 /* Output line details for LINE and print it to F file. LINE lives on
2808 LINE_NUM. */
2810 static void
2811 output_line_details (FILE *f, const line_info *line, unsigned line_num)
2813 if (flag_all_blocks)
2815 arc_info *arc;
2816 int ix, jx;
2818 ix = jx = 0;
2819 for (vector<block_info *>::const_iterator it = line->blocks.begin ();
2820 it != line->blocks.end (); it++)
2822 if (!(*it)->is_call_return)
2824 output_line_beginning (f, line->exists,
2825 (*it)->exceptional, false,
2826 (*it)->count, line_num,
2827 "%%%%%", "$$$$$");
2828 fprintf (f, "-block %2d", ix++);
2829 if (flag_verbose)
2830 fprintf (f, " (BB %u)", (*it)->id);
2831 fprintf (f, "\n");
2833 if (flag_branches)
2834 for (arc = (*it)->succ; arc; arc = arc->succ_next)
2835 jx += output_branch_count (f, jx, arc);
2838 else if (flag_branches)
2840 int ix;
2842 ix = 0;
2843 for (vector<arc_info *>::const_iterator it = line->branches.begin ();
2844 it != line->branches.end (); it++)
2845 ix += output_branch_count (f, ix, (*it));
2849 /* Output detail statistics about function FN to file F. */
2851 static void
2852 output_function_details (FILE *f, const function_info *fn)
2854 if (!flag_branches)
2855 return;
2857 arc_info *arc = fn->blocks[EXIT_BLOCK].pred;
2858 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2859 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2861 for (; arc; arc = arc->pred_next)
2862 if (arc->fake)
2863 return_count -= arc->count;
2865 fprintf (f, "function %s",
2866 flag_demangled_names ? fn->demangled_name : fn->name);
2867 fprintf (f, " called %s",
2868 format_gcov (called_count, 0, -1));
2869 fprintf (f, " returned %s",
2870 format_gcov (return_count, called_count, 0));
2871 fprintf (f, " blocks executed %s",
2872 format_gcov (fn->blocks_executed, fn->blocks.size () - 2,
2873 0));
2874 fprintf (f, "\n");
2877 /* Read in the source file one line at a time, and output that line to
2878 the gcov file preceded by its execution count and other
2879 information. */
2881 static void
2882 output_lines (FILE *gcov_file, const source_info *src)
2884 #define DEFAULT_LINE_START " -: 0:"
2885 #define FN_SEPARATOR "------------------\n"
2887 FILE *source_file;
2888 const char *retval;
2890 fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
2891 if (!multiple_files)
2893 fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
2894 fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
2895 no_data_file ? "-" : da_file_name);
2896 fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
2898 fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
2900 source_file = fopen (src->name, "r");
2901 if (!source_file)
2902 fnotice (stderr, "Cannot open source file %s\n", src->name);
2903 else if (src->file_time == 0)
2904 fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
2906 vector<const char *> source_lines;
2907 if (source_file)
2908 while ((retval = read_line (source_file)) != NULL)
2909 source_lines.push_back (xstrdup (retval));
2911 unsigned line_start_group = 0;
2912 vector<function_info *> fns;
2914 for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++)
2916 if (line_num >= src->lines.size ())
2918 fprintf (gcov_file, "%9s:%5u", "-", line_num);
2919 print_source_line (gcov_file, source_lines, line_num);
2920 continue;
2923 const line_info *line = &src->lines[line_num];
2925 if (line_start_group == 0)
2927 fns = src->get_functions_at_location (line_num);
2928 if (fns.size () > 1)
2930 /* It's possible to have functions that partially overlap,
2931 thus take the maximum end_line of functions starting
2932 at LINE_NUM. */
2933 for (unsigned i = 0; i < fns.size (); i++)
2934 if (fns[i]->end_line > line_start_group)
2935 line_start_group = fns[i]->end_line;
2937 else if (fns.size () == 1)
2939 function_info *fn = fns[0];
2940 output_function_details (gcov_file, fn);
2944 /* For lines which don't exist in the .bb file, print '-' before
2945 the source line. For lines which exist but were never
2946 executed, print '#####' or '=====' before the source line.
2947 Otherwise, print the execution count before the source line.
2948 There are 16 spaces of indentation added before the source
2949 line so that tabs won't be messed up. */
2950 output_line_beginning (gcov_file, line->exists, line->unexceptional,
2951 line->has_unexecuted_block, line->count,
2952 line_num, "=====", "#####");
2954 print_source_line (gcov_file, source_lines, line_num);
2955 output_line_details (gcov_file, line, line_num);
2957 if (line_start_group == line_num)
2959 for (vector<function_info *>::iterator it = fns.begin ();
2960 it != fns.end (); it++)
2962 function_info *fn = *it;
2963 vector<line_info> &lines = fn->lines;
2965 fprintf (gcov_file, FN_SEPARATOR);
2967 string fn_name
2968 = flag_demangled_names ? fn->demangled_name : fn->name;
2970 if (flag_use_colors)
2972 fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN));
2973 fn_name += SGR_RESET;
2976 fprintf (gcov_file, "%s:\n", fn_name.c_str ());
2978 output_function_details (gcov_file, fn);
2980 /* Print all lines covered by the function. */
2981 for (unsigned i = 0; i < lines.size (); i++)
2983 line_info *line = &lines[i];
2984 unsigned l = fn->start_line + i;
2986 /* For lines which don't exist in the .bb file, print '-'
2987 before the source line. For lines which exist but
2988 were never executed, print '#####' or '=====' before
2989 the source line. Otherwise, print the execution count
2990 before the source line.
2991 There are 16 spaces of indentation added before the source
2992 line so that tabs won't be messed up. */
2993 output_line_beginning (gcov_file, line->exists,
2994 line->unexceptional,
2995 line->has_unexecuted_block,
2996 line->count,
2997 l, "=====", "#####");
2999 print_source_line (gcov_file, source_lines, l);
3000 output_line_details (gcov_file, line, l);
3004 fprintf (gcov_file, FN_SEPARATOR);
3005 line_start_group = 0;
3009 if (source_file)
3010 fclose (source_file);