Analyze niter for until-wrap condition [PR101145]
[official-gcc.git] / gcc / gcov.c
blobcf0a49d8c30562233516d62da571d0ee3a487a47
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990-2021 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"
47 #include "pretty-print.h"
48 #include "json.h"
50 #include <zlib.h>
51 #include <getopt.h>
53 #include "md5.h"
55 using namespace std;
57 #define IN_GCOV 1
58 #include "gcov-io.h"
59 #include "gcov-io.c"
61 /* The gcno file is generated by -ftest-coverage option. The gcda file is
62 generated by a program compiled with -fprofile-arcs. Their formats
63 are documented in gcov-io.h. */
65 /* The functions in this file for creating and solution program flow graphs
66 are very similar to functions in the gcc source file profile.c. In
67 some places we make use of the knowledge of how profile.c works to
68 select particular algorithms here. */
70 /* The code validates that the profile information read in corresponds
71 to the code currently being compiled. Rather than checking for
72 identical files, the code below compares a checksum on the CFG
73 (based on the order of basic blocks and the arcs in the CFG). If
74 the CFG checksum in the gcda file match the CFG checksum in the
75 gcno file, the profile data will be used. */
77 /* This is the size of the buffer used to read in source file lines. */
79 class function_info;
80 class block_info;
81 class source_info;
83 /* Describes an arc between two basic blocks. */
85 struct arc_info
87 /* source and destination blocks. */
88 class block_info *src;
89 class block_info *dst;
91 /* transition counts. */
92 gcov_type count;
93 /* used in cycle search, so that we do not clobber original counts. */
94 gcov_type cs_count;
96 unsigned int count_valid : 1;
97 unsigned int on_tree : 1;
98 unsigned int fake : 1;
99 unsigned int fall_through : 1;
101 /* Arc to a catch handler. */
102 unsigned int is_throw : 1;
104 /* Arc is for a function that abnormally returns. */
105 unsigned int is_call_non_return : 1;
107 /* Arc is for catch/setjmp. */
108 unsigned int is_nonlocal_return : 1;
110 /* Is an unconditional branch. */
111 unsigned int is_unconditional : 1;
113 /* Loop making arc. */
114 unsigned int cycle : 1;
116 /* Links to next arc on src and dst lists. */
117 struct arc_info *succ_next;
118 struct arc_info *pred_next;
121 /* Describes which locations (lines and files) are associated with
122 a basic block. */
124 class block_location_info
126 public:
127 block_location_info (unsigned _source_file_idx):
128 source_file_idx (_source_file_idx)
131 unsigned source_file_idx;
132 vector<unsigned> lines;
135 /* Describes a basic block. Contains lists of arcs to successor and
136 predecessor blocks. */
138 class block_info
140 public:
141 /* Constructor. */
142 block_info ();
144 /* Chain of exit and entry arcs. */
145 arc_info *succ;
146 arc_info *pred;
148 /* Number of unprocessed exit and entry arcs. */
149 gcov_type num_succ;
150 gcov_type num_pred;
152 unsigned id;
154 /* Block execution count. */
155 gcov_type count;
156 unsigned count_valid : 1;
157 unsigned valid_chain : 1;
158 unsigned invalid_chain : 1;
159 unsigned exceptional : 1;
161 /* Block is a call instrumenting site. */
162 unsigned is_call_site : 1; /* Does the call. */
163 unsigned is_call_return : 1; /* Is the return. */
165 /* Block is a landing pad for longjmp or throw. */
166 unsigned is_nonlocal_return : 1;
168 vector<block_location_info> locations;
170 struct
172 /* Single line graph cycle workspace. Used for all-blocks
173 mode. */
174 arc_info *arc;
175 unsigned ident;
176 } cycle; /* Used in all-blocks mode, after blocks are linked onto
177 lines. */
179 /* Temporary chain for solving graph, and for chaining blocks on one
180 line. */
181 class block_info *chain;
185 block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
186 id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
187 exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
188 locations (), chain (NULL)
190 cycle.arc = NULL;
193 /* Describes a single line of source. Contains a chain of basic blocks
194 with code on it. */
196 class line_info
198 public:
199 /* Default constructor. */
200 line_info ();
202 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
203 bool has_block (block_info *needle);
205 /* Execution count. */
206 gcov_type count;
208 /* Branches from blocks that end on this line. */
209 vector<arc_info *> branches;
211 /* blocks which start on this line. Used in all-blocks mode. */
212 vector<block_info *> blocks;
214 unsigned exists : 1;
215 unsigned unexceptional : 1;
216 unsigned has_unexecuted_block : 1;
219 line_info::line_info (): count (0), branches (), blocks (), exists (false),
220 unexceptional (0), has_unexecuted_block (0)
224 bool
225 line_info::has_block (block_info *needle)
227 return std::find (blocks.begin (), blocks.end (), needle) != blocks.end ();
230 /* Output demangled function names. */
232 static int flag_demangled_names = 0;
234 /* Describes a single function. Contains an array of basic blocks. */
236 class function_info
238 public:
239 function_info ();
240 ~function_info ();
242 /* Return true when line N belongs to the function in source file SRC_IDX.
243 The line must be defined in body of the function, can't be inlined. */
244 bool group_line_p (unsigned n, unsigned src_idx);
246 /* Function filter based on function_info::artificial variable. */
248 static inline bool
249 is_artificial (function_info *fn)
251 return fn->artificial;
254 /* Name of function. */
255 char *m_name;
256 char *m_demangled_name;
257 unsigned ident;
258 unsigned lineno_checksum;
259 unsigned cfg_checksum;
261 /* The graph contains at least one fake incoming edge. */
262 unsigned has_catch : 1;
264 /* True when the function is artificial and does not exist
265 in a source file. */
266 unsigned artificial : 1;
268 /* True when multiple functions start at a line in a source file. */
269 unsigned is_group : 1;
271 /* Array of basic blocks. Like in GCC, the entry block is
272 at blocks[0] and the exit block is at blocks[1]. */
273 #define ENTRY_BLOCK (0)
274 #define EXIT_BLOCK (1)
275 vector<block_info> blocks;
276 unsigned blocks_executed;
278 /* Raw arc coverage counts. */
279 vector<gcov_type> counts;
281 /* First line number. */
282 unsigned start_line;
284 /* First line column. */
285 unsigned start_column;
287 /* Last line number. */
288 unsigned end_line;
290 /* Last line column. */
291 unsigned end_column;
293 /* Index of source file where the function is defined. */
294 unsigned src;
296 /* Vector of line information (used only for group functions). */
297 vector<line_info> lines;
299 /* Next function. */
300 class function_info *next;
302 /* Get demangled name of a function. The demangled name
303 is converted when it is used for the first time. */
304 char *get_demangled_name ()
306 if (m_demangled_name == NULL)
308 m_demangled_name = cplus_demangle (m_name, DMGL_PARAMS);
309 if (!m_demangled_name)
310 m_demangled_name = m_name;
313 return m_demangled_name;
316 /* Get name of the function based on flag_demangled_names. */
317 char *get_name ()
319 return flag_demangled_names ? get_demangled_name () : m_name;
322 /* Return number of basic blocks (without entry and exit block). */
323 unsigned get_block_count ()
325 return blocks.size () - 2;
329 /* Function info comparer that will sort functions according to starting
330 line. */
332 struct function_line_start_cmp
334 inline bool operator() (const function_info *lhs,
335 const function_info *rhs)
337 return (lhs->start_line == rhs->start_line
338 ? lhs->start_column < rhs->start_column
339 : lhs->start_line < rhs->start_line);
343 /* Describes coverage of a file or function. */
345 struct coverage_info
347 int lines;
348 int lines_executed;
350 int branches;
351 int branches_executed;
352 int branches_taken;
354 int calls;
355 int calls_executed;
357 char *name;
360 /* Describes a file mentioned in the block graph. Contains an array
361 of line info. */
363 class source_info
365 public:
366 /* Default constructor. */
367 source_info ();
369 vector<function_info *> *get_functions_at_location (unsigned line_num) const;
371 /* Register a new function. */
372 void add_function (function_info *fn);
374 /* Debug the source file. */
375 void debug ();
377 /* Index of the source_info in sources vector. */
378 unsigned index;
380 /* Canonical name of source file. */
381 char *name;
382 time_t file_time;
384 /* Vector of line information. */
385 vector<line_info> lines;
387 coverage_info coverage;
389 /* Maximum line count in the source file. */
390 unsigned int maximum_count;
392 /* Functions in this source file. These are in ascending line
393 number order. */
394 vector<function_info *> functions;
396 /* Line number to functions map. */
397 vector<vector<function_info *> *> line_to_function_map;
400 source_info::source_info (): index (0), name (NULL), file_time (),
401 lines (), coverage (), maximum_count (0), functions ()
405 /* Register a new function. */
406 void
407 source_info::add_function (function_info *fn)
409 functions.push_back (fn);
411 if (fn->start_line >= line_to_function_map.size ())
412 line_to_function_map.resize (fn->start_line + 1);
414 vector<function_info *> **slot = &line_to_function_map[fn->start_line];
415 if (*slot == NULL)
416 *slot = new vector<function_info *> ();
418 (*slot)->push_back (fn);
421 vector<function_info *> *
422 source_info::get_functions_at_location (unsigned line_num) const
424 if (line_num >= line_to_function_map.size ())
425 return NULL;
427 vector<function_info *> *slot = line_to_function_map[line_num];
428 if (slot != NULL)
429 std::sort (slot->begin (), slot->end (), function_line_start_cmp ());
431 return slot;
434 void source_info::debug ()
436 fprintf (stderr, "source_info: %s\n", name);
437 for (vector<function_info *>::iterator it = functions.begin ();
438 it != functions.end (); it++)
440 function_info *fn = *it;
441 fprintf (stderr, " function_info: %s\n", fn->get_name ());
442 for (vector<block_info>::iterator bit = fn->blocks.begin ();
443 bit != fn->blocks.end (); bit++)
445 fprintf (stderr, " block_info id=%d, count=%" PRId64 " \n",
446 bit->id, bit->count);
450 for (unsigned lineno = 1; lineno < lines.size (); ++lineno)
452 line_info &line = lines[lineno];
453 fprintf (stderr, " line_info=%d, count=%" PRId64 "\n", lineno, line.count);
456 fprintf (stderr, "\n");
459 class name_map
461 public:
462 name_map ()
466 name_map (char *_name, unsigned _src): name (_name), src (_src)
470 bool operator== (const name_map &rhs) const
472 #if HAVE_DOS_BASED_FILE_SYSTEM
473 return strcasecmp (this->name, rhs.name) == 0;
474 #else
475 return strcmp (this->name, rhs.name) == 0;
476 #endif
479 bool operator< (const name_map &rhs) const
481 #if HAVE_DOS_BASED_FILE_SYSTEM
482 return strcasecmp (this->name, rhs.name) < 0;
483 #else
484 return strcmp (this->name, rhs.name) < 0;
485 #endif
488 const char *name; /* Source file name */
489 unsigned src; /* Source file */
492 /* Vector of all functions. */
493 static vector<function_info *> functions;
495 /* Function ident to function_info * map. */
496 static map<unsigned, function_info *> ident_to_fn;
498 /* Vector of source files. */
499 static vector<source_info> sources;
501 /* Mapping of file names to sources */
502 static vector<name_map> names;
504 /* Record all processed files in order to warn about
505 a file being read multiple times. */
506 static vector<char *> processed_files;
508 /* This holds data summary information. */
510 static unsigned object_runs;
512 static unsigned total_lines;
513 static unsigned total_executed;
515 /* Modification time of graph file. */
517 static time_t bbg_file_time;
519 /* Name of the notes (gcno) output file. The "bbg" prefix is for
520 historical reasons, when the notes file contained only the
521 basic block graph notes. */
523 static char *bbg_file_name;
525 /* Stamp of the bbg file */
526 static unsigned bbg_stamp;
528 /* Supports has_unexecuted_blocks functionality. */
529 static unsigned bbg_supports_has_unexecuted_blocks;
531 /* Working directory in which a TU was compiled. */
532 static const char *bbg_cwd;
534 /* Name and file pointer of the input file for the count data (gcda). */
536 static char *da_file_name;
538 /* Data file is missing. */
540 static int no_data_file;
542 /* If there is several input files, compute and display results after
543 reading all data files. This way if two or more gcda file refer to
544 the same source file (eg inline subprograms in a .h file), the
545 counts are added. */
547 static int multiple_files = 0;
549 /* Output branch probabilities. */
551 static int flag_branches = 0;
553 /* Show unconditional branches too. */
554 static int flag_unconditional = 0;
556 /* Output a gcov file if this is true. This is on by default, and can
557 be turned off by the -n option. */
559 static int flag_gcov_file = 1;
561 /* Output to stdout instead to a gcov file. */
563 static int flag_use_stdout = 0;
565 /* Output progress indication if this is true. This is off by default
566 and can be turned on by the -d option. */
568 static int flag_display_progress = 0;
570 /* Output *.gcov file in JSON intermediate format used by consumers. */
572 static int flag_json_format = 0;
574 /* For included files, make the gcov output file name include the name
575 of the input source file. For example, if x.h is included in a.c,
576 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
578 static int flag_long_names = 0;
580 /* For situations when a long name can potentially hit filesystem path limit,
581 let's calculate md5sum of the path and append it to a file name. */
583 static int flag_hash_filenames = 0;
585 /* Print verbose informations. */
587 static int flag_verbose = 0;
589 /* Print colored output. */
591 static int flag_use_colors = 0;
593 /* Use perf-like colors to indicate hot lines. */
595 static int flag_use_hotness_colors = 0;
597 /* Output count information for every basic block, not merely those
598 that contain line number information. */
600 static int flag_all_blocks = 0;
602 /* Output human readable numbers. */
604 static int flag_human_readable_numbers = 0;
606 /* Output summary info for each function. */
608 static int flag_function_summary = 0;
610 /* Print debugging dumps. */
612 static int flag_debug = 0;
614 /* Object directory file prefix. This is the directory/file where the
615 graph and data files are looked for, if nonzero. */
617 static char *object_directory = 0;
619 /* Source directory prefix. This is removed from source pathnames
620 that match, when generating the output file name. */
622 static char *source_prefix = 0;
623 static size_t source_length = 0;
625 /* Only show data for sources with relative pathnames. Absolute ones
626 usually indicate a system header file, which although it may
627 contain inline functions, is usually uninteresting. */
628 static int flag_relative_only = 0;
630 /* Preserve all pathname components. Needed when object files and
631 source files are in subdirectories. '/' is mangled as '#', '.' is
632 elided and '..' mangled to '^'. */
634 static int flag_preserve_paths = 0;
636 /* Output the number of times a branch was taken as opposed to the percentage
637 of times it was taken. */
639 static int flag_counts = 0;
641 /* Forward declarations. */
642 static int process_args (int, char **);
643 static void print_usage (int) ATTRIBUTE_NORETURN;
644 static void print_version (void) ATTRIBUTE_NORETURN;
645 static void process_file (const char *);
646 static void process_all_functions (void);
647 static void generate_results (const char *);
648 static void create_file_names (const char *);
649 static char *canonicalize_name (const char *);
650 static unsigned find_source (const char *);
651 static void read_graph_file (void);
652 static int read_count_file (void);
653 static void solve_flow_graph (function_info *);
654 static void find_exception_blocks (function_info *);
655 static void add_branch_counts (coverage_info *, const arc_info *);
656 static void add_line_counts (coverage_info *, function_info *);
657 static void executed_summary (unsigned, unsigned);
658 static void function_summary (const coverage_info *);
659 static void file_summary (const coverage_info *);
660 static const char *format_gcov (gcov_type, gcov_type, int);
661 static void accumulate_line_counts (source_info *);
662 static void output_gcov_file (const char *, source_info *);
663 static int output_branch_count (FILE *, int, const arc_info *);
664 static void output_lines (FILE *, const source_info *);
665 static string make_gcov_file_name (const char *, const char *);
666 static char *mangle_name (const char *);
667 static void release_structures (void);
668 extern int main (int, char **);
670 function_info::function_info (): m_name (NULL), m_demangled_name (NULL),
671 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
672 artificial (0), is_group (0),
673 blocks (), blocks_executed (0), counts (),
674 start_line (0), start_column (0), end_line (0), end_column (0),
675 src (0), lines (), next (NULL)
679 function_info::~function_info ()
681 for (int i = blocks.size () - 1; i >= 0; i--)
683 arc_info *arc, *arc_n;
685 for (arc = blocks[i].succ; arc; arc = arc_n)
687 arc_n = arc->succ_next;
688 free (arc);
691 if (m_demangled_name != m_name)
692 free (m_demangled_name);
693 free (m_name);
696 bool function_info::group_line_p (unsigned n, unsigned src_idx)
698 return is_group && src == src_idx && start_line <= n && n <= end_line;
701 /* Cycle detection!
702 There are a bajillion algorithms that do this. Boost's function is named
703 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
704 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
705 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
707 The basic algorithm is simple: effectively, we're finding all simple paths
708 in a subgraph (that shrinks every iteration). Duplicates are filtered by
709 "blocking" a path when a node is added to the path (this also prevents non-
710 simple paths)--the node is unblocked only when it participates in a cycle.
713 typedef vector<arc_info *> arc_vector_t;
714 typedef vector<const block_info *> block_vector_t;
716 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
717 and subtract the value from all counts. The subtracted value is added
718 to COUNT. Returns type of loop. */
720 static void
721 handle_cycle (const arc_vector_t &edges, int64_t &count)
723 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
724 that amount. */
725 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
726 for (unsigned i = 0; i < edges.size (); i++)
728 int64_t ecount = edges[i]->cs_count;
729 if (cycle_count > ecount)
730 cycle_count = ecount;
732 count += cycle_count;
733 for (unsigned i = 0; i < edges.size (); i++)
734 edges[i]->cs_count -= cycle_count;
736 gcc_assert (cycle_count > 0);
739 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
740 blocked by U in BLOCK_LISTS. */
742 static void
743 unblock (const block_info *u, block_vector_t &blocked,
744 vector<block_vector_t > &block_lists)
746 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
747 if (it == blocked.end ())
748 return;
750 unsigned index = it - blocked.begin ();
751 blocked.erase (it);
753 block_vector_t to_unblock (block_lists[index]);
755 block_lists.erase (block_lists.begin () + index);
757 for (block_vector_t::iterator it = to_unblock.begin ();
758 it != to_unblock.end (); it++)
759 unblock (*it, blocked, block_lists);
762 /* Return true when PATH contains a zero cycle arc count. */
764 static bool
765 path_contains_zero_or_negative_cycle_arc (arc_vector_t &path)
767 for (unsigned i = 0; i < path.size (); i++)
768 if (path[i]->cs_count <= 0)
769 return true;
770 return false;
773 /* Find circuit going to block V, PATH is provisional seen cycle.
774 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
775 blocked by a block. COUNT is accumulated count of the current LINE.
776 Returns what type of loop it contains. */
778 static bool
779 circuit (block_info *v, arc_vector_t &path, block_info *start,
780 block_vector_t &blocked, vector<block_vector_t> &block_lists,
781 line_info &linfo, int64_t &count)
783 bool loop_found = false;
785 /* Add v to the block list. */
786 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
787 blocked.push_back (v);
788 block_lists.push_back (block_vector_t ());
790 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
792 block_info *w = arc->dst;
793 if (w < start
794 || arc->cs_count <= 0
795 || !linfo.has_block (w))
796 continue;
798 path.push_back (arc);
799 if (w == start)
801 /* Cycle has been found. */
802 handle_cycle (path, count);
803 loop_found = true;
805 else if (!path_contains_zero_or_negative_cycle_arc (path)
806 && find (blocked.begin (), blocked.end (), w) == blocked.end ())
807 loop_found |= circuit (w, path, start, blocked, block_lists, linfo,
808 count);
810 path.pop_back ();
813 if (loop_found)
814 unblock (v, blocked, block_lists);
815 else
816 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
818 block_info *w = arc->dst;
819 if (w < start
820 || arc->cs_count <= 0
821 || !linfo.has_block (w))
822 continue;
824 size_t index
825 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
826 gcc_assert (index < blocked.size ());
827 block_vector_t &list = block_lists[index];
828 if (find (list.begin (), list.end (), v) == list.end ())
829 list.push_back (v);
832 return loop_found;
835 /* Find cycles for a LINFO. */
837 static gcov_type
838 get_cycles_count (line_info &linfo)
840 /* Note that this algorithm works even if blocks aren't in sorted order.
841 Each iteration of the circuit detection is completely independent
842 (except for reducing counts, but that shouldn't matter anyways).
843 Therefore, operating on a permuted order (i.e., non-sorted) only
844 has the effect of permuting the output cycles. */
846 bool loop_found = false;
847 gcov_type count = 0;
848 for (vector<block_info *>::iterator it = linfo.blocks.begin ();
849 it != linfo.blocks.end (); it++)
851 arc_vector_t path;
852 block_vector_t blocked;
853 vector<block_vector_t > block_lists;
854 loop_found |= circuit (*it, path, *it, blocked, block_lists, linfo,
855 count);
858 return count;
862 main (int argc, char **argv)
864 int argno;
865 int first_arg;
866 const char *p;
868 p = argv[0] + strlen (argv[0]);
869 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
870 --p;
871 progname = p;
873 xmalloc_set_program_name (progname);
875 /* Unlock the stdio streams. */
876 unlock_std_streams ();
878 gcc_init_libintl ();
880 diagnostic_initialize (global_dc, 0);
882 /* Handle response files. */
883 expandargv (&argc, &argv);
885 argno = process_args (argc, argv);
886 if (optind == argc)
887 print_usage (true);
889 if (argc - argno > 1)
890 multiple_files = 1;
892 first_arg = argno;
894 for (; argno != argc; argno++)
896 if (flag_display_progress)
897 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
898 argc - first_arg);
899 process_file (argv[argno]);
901 if (flag_json_format || argno == argc - 1)
903 process_all_functions ();
904 generate_results (argv[argno]);
905 release_structures ();
909 if (!flag_use_stdout)
910 executed_summary (total_lines, total_executed);
912 return 0;
915 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
916 otherwise the output of --help. */
918 static void
919 print_usage (int error_p)
921 FILE *file = error_p ? stderr : stdout;
922 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
924 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
925 fnotice (file, "Print code coverage information.\n\n");
926 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
927 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
928 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
929 rather than percentages\n");
930 fnotice (file, " -d, --display-progress Display progress information\n");
931 fnotice (file, " -D, --debug Display debugging dumps\n");
932 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
933 fnotice (file, " -h, --help Print this help, then exit\n");
934 fnotice (file, " -j, --json-format Output JSON intermediate format\n\
935 into .gcov.json.gz file\n");
936 fnotice (file, " -H, --human-readable Output human readable numbers\n");
937 fnotice (file, " -k, --use-colors Emit colored output\n");
938 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
939 source files\n");
940 fnotice (file, " -m, --demangled-names Output demangled function names\n");
941 fnotice (file, " -n, --no-output Do not create an output file\n");
942 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
943 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
944 fnotice (file, " -q, --use-hotness-colors Emit perf-like colored output for hot lines\n");
945 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
946 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
947 fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
948 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
949 fnotice (file, " -v, --version Print version number, then exit\n");
950 fnotice (file, " -w, --verbose Print verbose informations\n");
951 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
952 fnotice (file, "\nObsolete options:\n");
953 fnotice (file, " -i, --json-format Replaced with -j, --json-format\n");
954 fnotice (file, " -j, --human-readable Replaced with -H, --human-readable\n");
955 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
956 bug_report_url);
957 exit (status);
960 /* Print version information and exit. */
962 static void
963 print_version (void)
965 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
966 fprintf (stdout, "Copyright %s 2021 Free Software Foundation, Inc.\n",
967 _("(C)"));
968 fnotice (stdout,
969 _("This is free software; see the source for copying conditions. There is NO\n\
970 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
971 exit (SUCCESS_EXIT_CODE);
974 static const struct option options[] =
976 { "help", no_argument, NULL, 'h' },
977 { "version", no_argument, NULL, 'v' },
978 { "verbose", no_argument, NULL, 'w' },
979 { "all-blocks", no_argument, NULL, 'a' },
980 { "branch-probabilities", no_argument, NULL, 'b' },
981 { "branch-counts", no_argument, NULL, 'c' },
982 { "json-format", no_argument, NULL, 'j' },
983 { "human-readable", no_argument, NULL, 'H' },
984 { "no-output", no_argument, NULL, 'n' },
985 { "long-file-names", no_argument, NULL, 'l' },
986 { "function-summaries", no_argument, NULL, 'f' },
987 { "demangled-names", no_argument, NULL, 'm' },
988 { "preserve-paths", no_argument, NULL, 'p' },
989 { "relative-only", no_argument, NULL, 'r' },
990 { "object-directory", required_argument, NULL, 'o' },
991 { "object-file", required_argument, NULL, 'o' },
992 { "source-prefix", required_argument, NULL, 's' },
993 { "stdout", no_argument, NULL, 't' },
994 { "unconditional-branches", no_argument, NULL, 'u' },
995 { "display-progress", no_argument, NULL, 'd' },
996 { "hash-filenames", no_argument, NULL, 'x' },
997 { "use-colors", no_argument, NULL, 'k' },
998 { "use-hotness-colors", no_argument, NULL, 'q' },
999 { "debug", no_argument, NULL, 'D' },
1000 { 0, 0, 0, 0 }
1003 /* Process args, return index to first non-arg. */
1005 static int
1006 process_args (int argc, char **argv)
1008 int opt;
1010 const char *opts = "abcdDfhHijklmno:pqrs:tuvwx";
1011 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
1013 switch (opt)
1015 case 'a':
1016 flag_all_blocks = 1;
1017 break;
1018 case 'b':
1019 flag_branches = 1;
1020 break;
1021 case 'c':
1022 flag_counts = 1;
1023 break;
1024 case 'f':
1025 flag_function_summary = 1;
1026 break;
1027 case 'h':
1028 print_usage (false);
1029 /* print_usage will exit. */
1030 case 'l':
1031 flag_long_names = 1;
1032 break;
1033 case 'H':
1034 flag_human_readable_numbers = 1;
1035 break;
1036 case 'k':
1037 flag_use_colors = 1;
1038 break;
1039 case 'q':
1040 flag_use_hotness_colors = 1;
1041 break;
1042 case 'm':
1043 flag_demangled_names = 1;
1044 break;
1045 case 'n':
1046 flag_gcov_file = 0;
1047 break;
1048 case 'o':
1049 object_directory = optarg;
1050 break;
1051 case 's':
1052 source_prefix = optarg;
1053 source_length = strlen (source_prefix);
1054 break;
1055 case 'r':
1056 flag_relative_only = 1;
1057 break;
1058 case 'p':
1059 flag_preserve_paths = 1;
1060 break;
1061 case 'u':
1062 flag_unconditional = 1;
1063 break;
1064 case 'i':
1065 case 'j':
1066 flag_json_format = 1;
1067 flag_gcov_file = 1;
1068 break;
1069 case 'd':
1070 flag_display_progress = 1;
1071 break;
1072 case 'x':
1073 flag_hash_filenames = 1;
1074 break;
1075 case 'w':
1076 flag_verbose = 1;
1077 break;
1078 case 't':
1079 flag_use_stdout = 1;
1080 break;
1081 case 'D':
1082 flag_debug = 1;
1083 break;
1084 case 'v':
1085 print_version ();
1086 /* print_version will exit. */
1087 default:
1088 print_usage (true);
1089 /* print_usage will exit. */
1093 return optind;
1096 /* Output intermediate LINE sitting on LINE_NUM to JSON OBJECT.
1097 Add FUNCTION_NAME to the LINE. */
1099 static void
1100 output_intermediate_json_line (json::array *object,
1101 line_info *line, unsigned line_num,
1102 const char *function_name)
1104 if (!line->exists)
1105 return;
1107 json::object *lineo = new json::object ();
1108 lineo->set ("line_number", new json::integer_number (line_num));
1109 if (function_name != NULL)
1110 lineo->set ("function_name", new json::string (function_name));
1111 lineo->set ("count", new json::integer_number (line->count));
1112 lineo->set ("unexecuted_block",
1113 new json::literal (line->has_unexecuted_block));
1115 json::array *branches = new json::array ();
1116 lineo->set ("branches", branches);
1118 vector<arc_info *>::const_iterator it;
1119 if (flag_branches)
1120 for (it = line->branches.begin (); it != line->branches.end ();
1121 it++)
1123 if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
1125 json::object *branch = new json::object ();
1126 branch->set ("count", new json::integer_number ((*it)->count));
1127 branch->set ("throw", new json::literal ((*it)->is_throw));
1128 branch->set ("fallthrough",
1129 new json::literal ((*it)->fall_through));
1130 branches->append (branch);
1134 object->append (lineo);
1137 /* Strip filename extension in STR. */
1139 static string
1140 strip_extention (string str)
1142 string::size_type pos = str.rfind ('.');
1143 if (pos != string::npos)
1144 str = str.substr (0, pos);
1146 return str;
1149 /* Calcualte md5sum for INPUT string and return it in hex string format. */
1151 static string
1152 get_md5sum (const char *input)
1154 md5_ctx ctx;
1155 char md5sum[16];
1156 string str;
1158 md5_init_ctx (&ctx);
1159 md5_process_bytes (input, strlen (input), &ctx);
1160 md5_finish_ctx (&ctx, md5sum);
1162 for (unsigned i = 0; i < 16; i++)
1164 char b[3];
1165 sprintf (b, "%02x", (unsigned char)md5sum[i]);
1166 str += b;
1169 return str;
1172 /* Get the name of the gcov file. The return value must be free'd.
1174 It appends the '.gcov' extension to the *basename* of the file.
1175 The resulting file name will be in PWD.
1177 e.g.,
1178 input: foo.da, output: foo.da.gcov
1179 input: a/b/foo.cc, output: foo.cc.gcov */
1181 static string
1182 get_gcov_intermediate_filename (const char *input_file_name)
1184 string base = basename (input_file_name);
1185 string str = strip_extention (base);
1187 if (flag_hash_filenames)
1189 str += "##";
1190 str += get_md5sum (input_file_name);
1192 else if (flag_preserve_paths && base != input_file_name)
1194 str += "##";
1195 str += mangle_path (input_file_name);
1196 str = strip_extention (str);
1199 str += ".gcov.json.gz";
1200 return str.c_str ();
1203 /* Output the result in JSON intermediate format.
1204 Source info SRC is dumped into JSON_FILES which is JSON array. */
1206 static void
1207 output_json_intermediate_file (json::array *json_files, source_info *src)
1209 json::object *root = new json::object ();
1210 json_files->append (root);
1212 root->set ("file", new json::string (src->name));
1214 json::array *functions = new json::array ();
1215 root->set ("functions", functions);
1217 std::sort (src->functions.begin (), src->functions.end (),
1218 function_line_start_cmp ());
1219 for (vector<function_info *>::iterator it = src->functions.begin ();
1220 it != src->functions.end (); it++)
1222 json::object *function = new json::object ();
1223 function->set ("name", new json::string ((*it)->m_name));
1224 function->set ("demangled_name",
1225 new json::string ((*it)->get_demangled_name ()));
1226 function->set ("start_line",
1227 new json::integer_number ((*it)->start_line));
1228 function->set ("start_column",
1229 new json::integer_number ((*it)->start_column));
1230 function->set ("end_line", new json::integer_number ((*it)->end_line));
1231 function->set ("end_column",
1232 new json::integer_number ((*it)->end_column));
1233 function->set ("blocks",
1234 new json::integer_number ((*it)->get_block_count ()));
1235 function->set ("blocks_executed",
1236 new json::integer_number ((*it)->blocks_executed));
1237 function->set ("execution_count",
1238 new json::integer_number ((*it)->blocks[0].count));
1240 functions->append (function);
1243 json::array *lineso = new json::array ();
1244 root->set ("lines", lineso);
1246 vector<function_info *> last_non_group_fns;
1248 for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
1250 vector<function_info *> *fns = src->get_functions_at_location (line_num);
1252 if (fns != NULL)
1253 /* Print info for all group functions that begin on the line. */
1254 for (vector<function_info *>::iterator it2 = fns->begin ();
1255 it2 != fns->end (); it2++)
1257 if (!(*it2)->is_group)
1258 last_non_group_fns.push_back (*it2);
1260 vector<line_info> &lines = (*it2)->lines;
1261 /* The LINES array is allocated only for group functions. */
1262 for (unsigned i = 0; i < lines.size (); i++)
1264 line_info *line = &lines[i];
1265 output_intermediate_json_line (lineso, line, line_num + i,
1266 (*it2)->m_name);
1270 /* Follow with lines associated with the source file. */
1271 if (line_num < src->lines.size ())
1273 unsigned size = last_non_group_fns.size ();
1274 function_info *last_fn = size > 0 ? last_non_group_fns[size - 1] : NULL;
1275 const char *fname = last_fn ? last_fn->m_name : NULL;
1276 output_intermediate_json_line (lineso, &src->lines[line_num], line_num,
1277 fname);
1279 /* Pop ending function from stack. */
1280 if (last_fn != NULL && last_fn->end_line == line_num)
1281 last_non_group_fns.pop_back ();
1286 /* Function start pair. */
1287 struct function_start
1289 unsigned source_file_idx;
1290 unsigned start_line;
1293 /* Traits class for function start hash maps below. */
1295 struct function_start_pair_hash : typed_noop_remove <function_start>
1297 typedef function_start value_type;
1298 typedef function_start compare_type;
1300 static hashval_t
1301 hash (const function_start &ref)
1303 inchash::hash hstate (0);
1304 hstate.add_int (ref.source_file_idx);
1305 hstate.add_int (ref.start_line);
1306 return hstate.end ();
1309 static bool
1310 equal (const function_start &ref1, const function_start &ref2)
1312 return (ref1.source_file_idx == ref2.source_file_idx
1313 && ref1.start_line == ref2.start_line);
1316 static void
1317 mark_deleted (function_start &ref)
1319 ref.start_line = ~1U;
1322 static const bool empty_zero_p = false;
1324 static void
1325 mark_empty (function_start &ref)
1327 ref.start_line = ~2U;
1330 static bool
1331 is_deleted (const function_start &ref)
1333 return ref.start_line == ~1U;
1336 static bool
1337 is_empty (const function_start &ref)
1339 return ref.start_line == ~2U;
1343 /* Process a single input file. */
1345 static void
1346 process_file (const char *file_name)
1348 create_file_names (file_name);
1350 for (unsigned i = 0; i < processed_files.size (); i++)
1351 if (strcmp (da_file_name, processed_files[i]) == 0)
1353 fnotice (stderr, "'%s' file is already processed\n",
1354 file_name);
1355 return;
1358 processed_files.push_back (xstrdup (da_file_name));
1360 read_graph_file ();
1361 read_count_file ();
1364 /* Process all functions in all files. */
1366 static void
1367 process_all_functions (void)
1369 hash_map<function_start_pair_hash, function_info *> fn_map;
1371 /* Identify group functions. */
1372 for (vector<function_info *>::iterator it = functions.begin ();
1373 it != functions.end (); it++)
1374 if (!(*it)->artificial)
1376 function_start needle;
1377 needle.source_file_idx = (*it)->src;
1378 needle.start_line = (*it)->start_line;
1380 function_info **slot = fn_map.get (needle);
1381 if (slot)
1383 (*slot)->is_group = 1;
1384 (*it)->is_group = 1;
1386 else
1387 fn_map.put (needle, *it);
1390 /* Remove all artificial function. */
1391 functions.erase (remove_if (functions.begin (), functions.end (),
1392 function_info::is_artificial), functions.end ());
1394 for (vector<function_info *>::iterator it = functions.begin ();
1395 it != functions.end (); it++)
1397 function_info *fn = *it;
1398 unsigned src = fn->src;
1400 if (!fn->counts.empty () || no_data_file)
1402 source_info *s = &sources[src];
1403 s->add_function (fn);
1405 /* Mark last line in files touched by function. */
1406 for (unsigned block_no = 0; block_no != fn->blocks.size ();
1407 block_no++)
1409 block_info *block = &fn->blocks[block_no];
1410 for (unsigned i = 0; i < block->locations.size (); i++)
1412 /* Sort lines of locations. */
1413 sort (block->locations[i].lines.begin (),
1414 block->locations[i].lines.end ());
1416 if (!block->locations[i].lines.empty ())
1418 s = &sources[block->locations[i].source_file_idx];
1419 unsigned last_line
1420 = block->locations[i].lines.back ();
1422 /* Record new lines for the function. */
1423 if (last_line >= s->lines.size ())
1425 s = &sources[block->locations[i].source_file_idx];
1426 unsigned last_line
1427 = block->locations[i].lines.back ();
1429 /* Record new lines for the function. */
1430 if (last_line >= s->lines.size ())
1432 /* Record new lines for a source file. */
1433 s->lines.resize (last_line + 1);
1440 /* Allocate lines for group function, following start_line
1441 and end_line information of the function. */
1442 if (fn->is_group)
1443 fn->lines.resize (fn->end_line - fn->start_line + 1);
1445 solve_flow_graph (fn);
1446 if (fn->has_catch)
1447 find_exception_blocks (fn);
1449 else
1451 /* The function was not in the executable -- some other
1452 instance must have been selected. */
1457 static void
1458 output_gcov_file (const char *file_name, source_info *src)
1460 string gcov_file_name_str
1461 = make_gcov_file_name (file_name, src->coverage.name);
1462 const char *gcov_file_name = gcov_file_name_str.c_str ();
1464 if (src->coverage.lines)
1466 FILE *gcov_file = fopen (gcov_file_name, "w");
1467 if (gcov_file)
1469 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
1470 output_lines (gcov_file, src);
1471 if (ferror (gcov_file))
1472 fnotice (stderr, "Error writing output file '%s'\n",
1473 gcov_file_name);
1474 fclose (gcov_file);
1476 else
1477 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1479 else
1481 unlink (gcov_file_name);
1482 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1486 static void
1487 generate_results (const char *file_name)
1489 string gcov_intermediate_filename;
1491 for (vector<function_info *>::iterator it = functions.begin ();
1492 it != functions.end (); it++)
1494 function_info *fn = *it;
1495 coverage_info coverage;
1497 memset (&coverage, 0, sizeof (coverage));
1498 coverage.name = fn->get_name ();
1499 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1500 if (flag_function_summary)
1502 function_summary (&coverage);
1503 fnotice (stdout, "\n");
1507 name_map needle;
1508 needle.name = file_name;
1509 vector<name_map>::iterator it
1510 = std::find (names.begin (), names.end (), needle);
1511 if (it != names.end ())
1512 file_name = sources[it->src].coverage.name;
1513 else
1514 file_name = canonicalize_name (file_name);
1516 gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
1518 json::object *root = new json::object ();
1519 root->set ("format_version", new json::string ("1"));
1520 root->set ("gcc_version", new json::string (version_string));
1522 if (bbg_cwd != NULL)
1523 root->set ("current_working_directory", new json::string (bbg_cwd));
1524 root->set ("data_file", new json::string (file_name));
1526 json::array *json_files = new json::array ();
1527 root->set ("files", json_files);
1529 for (vector<source_info>::iterator it = sources.begin ();
1530 it != sources.end (); it++)
1532 source_info *src = &(*it);
1533 if (flag_relative_only)
1535 /* Ignore this source, if it is an absolute path (after
1536 source prefix removal). */
1537 char first = src->coverage.name[0];
1539 #if HAVE_DOS_BASED_FILE_SYSTEM
1540 if (first && src->coverage.name[1] == ':')
1541 first = src->coverage.name[2];
1542 #endif
1543 if (IS_DIR_SEPARATOR (first))
1544 continue;
1547 accumulate_line_counts (src);
1548 if (flag_debug)
1549 src->debug ();
1551 if (!flag_use_stdout)
1552 file_summary (&src->coverage);
1553 total_lines += src->coverage.lines;
1554 total_executed += src->coverage.lines_executed;
1555 if (flag_gcov_file)
1557 if (flag_json_format)
1559 output_json_intermediate_file (json_files, src);
1560 if (!flag_use_stdout)
1561 fnotice (stdout, "\n");
1563 else
1565 if (flag_use_stdout)
1567 if (src->coverage.lines)
1568 output_lines (stdout, src);
1570 else
1572 output_gcov_file (file_name, src);
1573 fnotice (stdout, "\n");
1579 if (flag_gcov_file && flag_json_format)
1581 if (flag_use_stdout)
1583 root->dump (stdout);
1584 printf ("\n");
1586 else
1588 pretty_printer pp;
1589 root->print (&pp);
1590 pp_formatted_text (&pp);
1592 fnotice (stdout, "Creating '%s'\n",
1593 gcov_intermediate_filename.c_str ());
1594 gzFile output = gzopen (gcov_intermediate_filename.c_str (), "w");
1595 if (output == NULL)
1597 fnotice (stderr, "Cannot open JSON output file %s\n",
1598 gcov_intermediate_filename.c_str ());
1599 return;
1602 if (gzputs (output, pp_formatted_text (&pp)) == EOF
1603 || gzclose (output))
1605 fnotice (stderr, "Error writing JSON output file %s\n",
1606 gcov_intermediate_filename.c_str ());
1607 return;
1613 /* Release all memory used. */
1615 static void
1616 release_structures (void)
1618 for (vector<function_info *>::iterator it = functions.begin ();
1619 it != functions.end (); it++)
1620 delete (*it);
1622 sources.resize (0);
1623 names.resize (0);
1624 functions.resize (0);
1625 ident_to_fn.clear ();
1628 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1629 is not specified, these are named from FILE_NAME sans extension. If
1630 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1631 directory, but named from the basename of the FILE_NAME, sans extension.
1632 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1633 and the data files are named from that. */
1635 static void
1636 create_file_names (const char *file_name)
1638 char *cptr;
1639 char *name;
1640 int length = strlen (file_name);
1641 int base;
1643 /* Free previous file names. */
1644 free (bbg_file_name);
1645 free (da_file_name);
1646 da_file_name = bbg_file_name = NULL;
1647 bbg_file_time = 0;
1648 bbg_stamp = 0;
1650 if (object_directory && object_directory[0])
1652 struct stat status;
1654 length += strlen (object_directory) + 2;
1655 name = XNEWVEC (char, length);
1656 name[0] = 0;
1658 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1659 strcat (name, object_directory);
1660 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1661 strcat (name, "/");
1663 else
1665 name = XNEWVEC (char, length + 1);
1666 strcpy (name, file_name);
1667 base = 0;
1670 if (base)
1672 /* Append source file name. */
1673 const char *cptr = lbasename (file_name);
1674 strcat (name, cptr ? cptr : file_name);
1677 /* Remove the extension. */
1678 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1679 if (cptr)
1680 *cptr = 0;
1682 length = strlen (name);
1684 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1685 strcpy (bbg_file_name, name);
1686 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1688 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1689 strcpy (da_file_name, name);
1690 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1692 free (name);
1693 return;
1696 /* Find or create a source file structure for FILE_NAME. Copies
1697 FILE_NAME on creation */
1699 static unsigned
1700 find_source (const char *file_name)
1702 char *canon;
1703 unsigned idx;
1704 struct stat status;
1706 if (!file_name)
1707 file_name = "<unknown>";
1709 name_map needle;
1710 needle.name = file_name;
1712 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1713 needle);
1714 if (it != names.end ())
1716 idx = it->src;
1717 goto check_date;
1720 /* Not found, try the canonical name. */
1721 canon = canonicalize_name (file_name);
1722 needle.name = canon;
1723 it = std::find (names.begin (), names.end (), needle);
1724 if (it == names.end ())
1726 /* Not found with canonical name, create a new source. */
1727 source_info *src;
1729 idx = sources.size ();
1730 needle = name_map (canon, idx);
1731 names.push_back (needle);
1733 sources.push_back (source_info ());
1734 src = &sources.back ();
1735 src->name = canon;
1736 src->coverage.name = src->name;
1737 src->index = idx;
1738 if (source_length
1739 #if HAVE_DOS_BASED_FILE_SYSTEM
1740 /* You lose if separators don't match exactly in the
1741 prefix. */
1742 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1743 #else
1744 && !strncmp (source_prefix, src->coverage.name, source_length)
1745 #endif
1746 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1747 src->coverage.name += source_length + 1;
1748 if (!stat (src->name, &status))
1749 src->file_time = status.st_mtime;
1751 else
1752 idx = it->src;
1754 needle.name = file_name;
1755 if (std::find (names.begin (), names.end (), needle) == names.end ())
1757 /* Append the non-canonical name. */
1758 names.push_back (name_map (xstrdup (file_name), idx));
1761 /* Resort the name map. */
1762 std::sort (names.begin (), names.end ());
1764 check_date:
1765 if (sources[idx].file_time > bbg_file_time)
1767 static int info_emitted;
1769 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1770 file_name, bbg_file_name);
1771 if (!info_emitted)
1773 fnotice (stderr,
1774 "(the message is displayed only once per source file)\n");
1775 info_emitted = 1;
1777 sources[idx].file_time = 0;
1780 return idx;
1783 /* Read the notes file. Save functions to FUNCTIONS global vector. */
1785 static void
1786 read_graph_file (void)
1788 unsigned version;
1789 unsigned current_tag = 0;
1790 unsigned tag;
1792 if (!gcov_open (bbg_file_name, 1))
1794 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1795 return;
1797 bbg_file_time = gcov_time ();
1798 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1800 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1801 gcov_close ();
1802 return;
1805 version = gcov_read_unsigned ();
1806 if (version != GCOV_VERSION)
1808 char v[4], e[4];
1810 GCOV_UNSIGNED2STRING (v, version);
1811 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1813 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1814 bbg_file_name, v, e);
1816 bbg_stamp = gcov_read_unsigned ();
1817 bbg_cwd = xstrdup (gcov_read_string ());
1818 bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
1820 function_info *fn = NULL;
1821 while ((tag = gcov_read_unsigned ()))
1823 unsigned length = gcov_read_unsigned ();
1824 gcov_position_t base = gcov_position ();
1826 if (tag == GCOV_TAG_FUNCTION)
1828 char *function_name;
1829 unsigned ident;
1830 unsigned lineno_checksum, cfg_checksum;
1832 ident = gcov_read_unsigned ();
1833 lineno_checksum = gcov_read_unsigned ();
1834 cfg_checksum = gcov_read_unsigned ();
1835 function_name = xstrdup (gcov_read_string ());
1836 unsigned artificial = gcov_read_unsigned ();
1837 unsigned src_idx = find_source (gcov_read_string ());
1838 unsigned start_line = gcov_read_unsigned ();
1839 unsigned start_column = gcov_read_unsigned ();
1840 unsigned end_line = gcov_read_unsigned ();
1841 unsigned end_column = gcov_read_unsigned ();
1843 fn = new function_info ();
1844 functions.push_back (fn);
1845 ident_to_fn[ident] = fn;
1847 fn->m_name = function_name;
1848 fn->ident = ident;
1849 fn->lineno_checksum = lineno_checksum;
1850 fn->cfg_checksum = cfg_checksum;
1851 fn->src = src_idx;
1852 fn->start_line = start_line;
1853 fn->start_column = start_column;
1854 fn->end_line = end_line;
1855 fn->end_column = end_column;
1856 fn->artificial = artificial;
1858 current_tag = tag;
1860 else if (fn && tag == GCOV_TAG_BLOCKS)
1862 if (!fn->blocks.empty ())
1863 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1864 bbg_file_name, fn->get_name ());
1865 else
1866 fn->blocks.resize (gcov_read_unsigned ());
1868 else if (fn && tag == GCOV_TAG_ARCS)
1870 unsigned src = gcov_read_unsigned ();
1871 fn->blocks[src].id = src;
1872 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1873 block_info *src_blk = &fn->blocks[src];
1874 unsigned mark_catches = 0;
1875 struct arc_info *arc;
1877 if (src >= fn->blocks.size () || fn->blocks[src].succ)
1878 goto corrupt;
1880 while (num_dests--)
1882 unsigned dest = gcov_read_unsigned ();
1883 unsigned flags = gcov_read_unsigned ();
1885 if (dest >= fn->blocks.size ())
1886 goto corrupt;
1887 arc = XCNEW (arc_info);
1889 arc->dst = &fn->blocks[dest];
1890 /* Set id in order to find EXIT_BLOCK. */
1891 arc->dst->id = dest;
1892 arc->src = src_blk;
1894 arc->count = 0;
1895 arc->count_valid = 0;
1896 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1897 arc->fake = !!(flags & GCOV_ARC_FAKE);
1898 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1900 arc->succ_next = src_blk->succ;
1901 src_blk->succ = arc;
1902 src_blk->num_succ++;
1904 arc->pred_next = fn->blocks[dest].pred;
1905 fn->blocks[dest].pred = arc;
1906 fn->blocks[dest].num_pred++;
1908 if (arc->fake)
1910 if (src)
1912 /* Exceptional exit from this function, the
1913 source block must be a call. */
1914 fn->blocks[src].is_call_site = 1;
1915 arc->is_call_non_return = 1;
1916 mark_catches = 1;
1918 else
1920 /* Non-local return from a callee of this
1921 function. The destination block is a setjmp. */
1922 arc->is_nonlocal_return = 1;
1923 fn->blocks[dest].is_nonlocal_return = 1;
1927 if (!arc->on_tree)
1928 fn->counts.push_back (0);
1931 if (mark_catches)
1933 /* We have a fake exit from this block. The other
1934 non-fall through exits must be to catch handlers.
1935 Mark them as catch arcs. */
1937 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1938 if (!arc->fake && !arc->fall_through)
1940 arc->is_throw = 1;
1941 fn->has_catch = 1;
1945 else if (fn && tag == GCOV_TAG_LINES)
1947 unsigned blockno = gcov_read_unsigned ();
1948 block_info *block = &fn->blocks[blockno];
1950 if (blockno >= fn->blocks.size ())
1951 goto corrupt;
1953 while (true)
1955 unsigned lineno = gcov_read_unsigned ();
1957 if (lineno)
1958 block->locations.back ().lines.push_back (lineno);
1959 else
1961 const char *file_name = gcov_read_string ();
1963 if (!file_name)
1964 break;
1965 block->locations.push_back (block_location_info
1966 (find_source (file_name)));
1970 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1972 fn = NULL;
1973 current_tag = 0;
1975 gcov_sync (base, length);
1976 if (gcov_is_error ())
1978 corrupt:;
1979 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1980 break;
1983 gcov_close ();
1985 if (functions.empty ())
1986 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1989 /* Reads profiles from the count file and attach to each
1990 function. Return nonzero if fatal error. */
1992 static int
1993 read_count_file (void)
1995 unsigned ix;
1996 unsigned version;
1997 unsigned tag;
1998 function_info *fn = NULL;
1999 int error = 0;
2000 map<unsigned, function_info *>::iterator it;
2002 if (!gcov_open (da_file_name, 1))
2004 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
2005 da_file_name);
2006 no_data_file = 1;
2007 return 0;
2009 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
2011 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
2012 cleanup:;
2013 gcov_close ();
2014 return 1;
2016 version = gcov_read_unsigned ();
2017 if (version != GCOV_VERSION)
2019 char v[4], e[4];
2021 GCOV_UNSIGNED2STRING (v, version);
2022 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
2024 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
2025 da_file_name, v, e);
2027 tag = gcov_read_unsigned ();
2028 if (tag != bbg_stamp)
2030 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
2031 goto cleanup;
2034 while ((tag = gcov_read_unsigned ()))
2036 unsigned length = gcov_read_unsigned ();
2037 int read_length = (int)length;
2038 unsigned long base = gcov_position ();
2040 if (tag == GCOV_TAG_OBJECT_SUMMARY)
2042 struct gcov_summary summary;
2043 gcov_read_summary (&summary);
2044 object_runs = summary.runs;
2046 else if (tag == GCOV_TAG_FUNCTION && !length)
2047 ; /* placeholder */
2048 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
2050 unsigned ident;
2051 ident = gcov_read_unsigned ();
2052 fn = NULL;
2053 it = ident_to_fn.find (ident);
2054 if (it != ident_to_fn.end ())
2055 fn = it->second;
2057 if (!fn)
2059 else if (gcov_read_unsigned () != fn->lineno_checksum
2060 || gcov_read_unsigned () != fn->cfg_checksum)
2062 mismatch:;
2063 fnotice (stderr, "%s:profile mismatch for '%s'\n",
2064 da_file_name, fn->get_name ());
2065 goto cleanup;
2068 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
2070 length = abs (read_length);
2071 if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
2072 goto mismatch;
2074 if (read_length > 0)
2075 for (ix = 0; ix != fn->counts.size (); ix++)
2076 fn->counts[ix] += gcov_read_counter ();
2078 if (read_length < 0)
2079 read_length = 0;
2080 gcov_sync (base, read_length);
2081 if ((error = gcov_is_error ()))
2083 fnotice (stderr,
2084 error < 0
2085 ? N_("%s:overflowed\n")
2086 : N_("%s:corrupted\n"),
2087 da_file_name);
2088 goto cleanup;
2092 gcov_close ();
2093 return 0;
2096 /* Solve the flow graph. Propagate counts from the instrumented arcs
2097 to the blocks and the uninstrumented arcs. */
2099 static void
2100 solve_flow_graph (function_info *fn)
2102 unsigned ix;
2103 arc_info *arc;
2104 gcov_type *count_ptr = &fn->counts.front ();
2105 block_info *blk;
2106 block_info *valid_blocks = NULL; /* valid, but unpropagated blocks. */
2107 block_info *invalid_blocks = NULL; /* invalid, but inferable blocks. */
2109 /* The arcs were built in reverse order. Fix that now. */
2110 for (ix = fn->blocks.size (); ix--;)
2112 arc_info *arc_p, *arc_n;
2114 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
2115 arc_p = arc, arc = arc_n)
2117 arc_n = arc->succ_next;
2118 arc->succ_next = arc_p;
2120 fn->blocks[ix].succ = arc_p;
2122 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
2123 arc_p = arc, arc = arc_n)
2125 arc_n = arc->pred_next;
2126 arc->pred_next = arc_p;
2128 fn->blocks[ix].pred = arc_p;
2131 if (fn->blocks.size () < 2)
2132 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
2133 bbg_file_name, fn->get_name ());
2134 else
2136 if (fn->blocks[ENTRY_BLOCK].num_pred)
2137 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
2138 bbg_file_name, fn->get_name ());
2139 else
2140 /* We can't deduce the entry block counts from the lack of
2141 predecessors. */
2142 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
2144 if (fn->blocks[EXIT_BLOCK].num_succ)
2145 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
2146 bbg_file_name, fn->get_name ());
2147 else
2148 /* Likewise, we can't deduce exit block counts from the lack
2149 of its successors. */
2150 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
2153 /* Propagate the measured counts, this must be done in the same
2154 order as the code in profile.c */
2155 for (unsigned i = 0; i < fn->blocks.size (); i++)
2157 blk = &fn->blocks[i];
2158 block_info const *prev_dst = NULL;
2159 int out_of_order = 0;
2160 int non_fake_succ = 0;
2162 for (arc = blk->succ; arc; arc = arc->succ_next)
2164 if (!arc->fake)
2165 non_fake_succ++;
2167 if (!arc->on_tree)
2169 if (count_ptr)
2170 arc->count = *count_ptr++;
2171 arc->count_valid = 1;
2172 blk->num_succ--;
2173 arc->dst->num_pred--;
2175 if (prev_dst && prev_dst > arc->dst)
2176 out_of_order = 1;
2177 prev_dst = arc->dst;
2179 if (non_fake_succ == 1)
2181 /* If there is only one non-fake exit, it is an
2182 unconditional branch. */
2183 for (arc = blk->succ; arc; arc = arc->succ_next)
2184 if (!arc->fake)
2186 arc->is_unconditional = 1;
2187 /* If this block is instrumenting a call, it might be
2188 an artificial block. It is not artificial if it has
2189 a non-fallthrough exit, or the destination of this
2190 arc has more than one entry. Mark the destination
2191 block as a return site, if none of those conditions
2192 hold. */
2193 if (blk->is_call_site && arc->fall_through
2194 && arc->dst->pred == arc && !arc->pred_next)
2195 arc->dst->is_call_return = 1;
2199 /* Sort the successor arcs into ascending dst order. profile.c
2200 normally produces arcs in the right order, but sometimes with
2201 one or two out of order. We're not using a particularly
2202 smart sort. */
2203 if (out_of_order)
2205 arc_info *start = blk->succ;
2206 unsigned changes = 1;
2208 while (changes)
2210 arc_info *arc, *arc_p, *arc_n;
2212 changes = 0;
2213 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
2215 if (arc->dst > arc_n->dst)
2217 changes = 1;
2218 if (arc_p)
2219 arc_p->succ_next = arc_n;
2220 else
2221 start = arc_n;
2222 arc->succ_next = arc_n->succ_next;
2223 arc_n->succ_next = arc;
2224 arc_p = arc_n;
2226 else
2228 arc_p = arc;
2229 arc = arc_n;
2233 blk->succ = start;
2236 /* Place it on the invalid chain, it will be ignored if that's
2237 wrong. */
2238 blk->invalid_chain = 1;
2239 blk->chain = invalid_blocks;
2240 invalid_blocks = blk;
2243 while (invalid_blocks || valid_blocks)
2245 while ((blk = invalid_blocks))
2247 gcov_type total = 0;
2248 const arc_info *arc;
2250 invalid_blocks = blk->chain;
2251 blk->invalid_chain = 0;
2252 if (!blk->num_succ)
2253 for (arc = blk->succ; arc; arc = arc->succ_next)
2254 total += arc->count;
2255 else if (!blk->num_pred)
2256 for (arc = blk->pred; arc; arc = arc->pred_next)
2257 total += arc->count;
2258 else
2259 continue;
2261 blk->count = total;
2262 blk->count_valid = 1;
2263 blk->chain = valid_blocks;
2264 blk->valid_chain = 1;
2265 valid_blocks = blk;
2267 while ((blk = valid_blocks))
2269 gcov_type total;
2270 arc_info *arc, *inv_arc;
2272 valid_blocks = blk->chain;
2273 blk->valid_chain = 0;
2274 if (blk->num_succ == 1)
2276 block_info *dst;
2278 total = blk->count;
2279 inv_arc = NULL;
2280 for (arc = blk->succ; arc; arc = arc->succ_next)
2282 total -= arc->count;
2283 if (!arc->count_valid)
2284 inv_arc = arc;
2286 dst = inv_arc->dst;
2287 inv_arc->count_valid = 1;
2288 inv_arc->count = total;
2289 blk->num_succ--;
2290 dst->num_pred--;
2291 if (dst->count_valid)
2293 if (dst->num_pred == 1 && !dst->valid_chain)
2295 dst->chain = valid_blocks;
2296 dst->valid_chain = 1;
2297 valid_blocks = dst;
2300 else
2302 if (!dst->num_pred && !dst->invalid_chain)
2304 dst->chain = invalid_blocks;
2305 dst->invalid_chain = 1;
2306 invalid_blocks = dst;
2310 if (blk->num_pred == 1)
2312 block_info *src;
2314 total = blk->count;
2315 inv_arc = NULL;
2316 for (arc = blk->pred; arc; arc = arc->pred_next)
2318 total -= arc->count;
2319 if (!arc->count_valid)
2320 inv_arc = arc;
2322 src = inv_arc->src;
2323 inv_arc->count_valid = 1;
2324 inv_arc->count = total;
2325 blk->num_pred--;
2326 src->num_succ--;
2327 if (src->count_valid)
2329 if (src->num_succ == 1 && !src->valid_chain)
2331 src->chain = valid_blocks;
2332 src->valid_chain = 1;
2333 valid_blocks = src;
2336 else
2338 if (!src->num_succ && !src->invalid_chain)
2340 src->chain = invalid_blocks;
2341 src->invalid_chain = 1;
2342 invalid_blocks = src;
2349 /* If the graph has been correctly solved, every block will have a
2350 valid count. */
2351 for (unsigned i = 0; ix < fn->blocks.size (); i++)
2352 if (!fn->blocks[i].count_valid)
2354 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
2355 bbg_file_name, fn->get_name ());
2356 break;
2360 /* Mark all the blocks only reachable via an incoming catch. */
2362 static void
2363 find_exception_blocks (function_info *fn)
2365 unsigned ix;
2366 block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ());
2368 /* First mark all blocks as exceptional. */
2369 for (ix = fn->blocks.size (); ix--;)
2370 fn->blocks[ix].exceptional = 1;
2372 /* Now mark all the blocks reachable via non-fake edges */
2373 queue[0] = &fn->blocks[0];
2374 queue[0]->exceptional = 0;
2375 for (ix = 1; ix;)
2377 block_info *block = queue[--ix];
2378 const arc_info *arc;
2380 for (arc = block->succ; arc; arc = arc->succ_next)
2381 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
2383 arc->dst->exceptional = 0;
2384 queue[ix++] = arc->dst;
2390 /* Increment totals in COVERAGE according to arc ARC. */
2392 static void
2393 add_branch_counts (coverage_info *coverage, const arc_info *arc)
2395 if (arc->is_call_non_return)
2397 coverage->calls++;
2398 if (arc->src->count)
2399 coverage->calls_executed++;
2401 else if (!arc->is_unconditional)
2403 coverage->branches++;
2404 if (arc->src->count)
2405 coverage->branches_executed++;
2406 if (arc->count)
2407 coverage->branches_taken++;
2411 /* Format COUNT, if flag_human_readable_numbers is set, return it human
2412 readable format. */
2414 static char const *
2415 format_count (gcov_type count)
2417 static char buffer[64];
2418 const char *units = " kMGTPEZY";
2420 if (count < 1000 || !flag_human_readable_numbers)
2422 sprintf (buffer, "%" PRId64, count);
2423 return buffer;
2426 unsigned i;
2427 gcov_type divisor = 1;
2428 for (i = 0; units[i+1]; i++, divisor *= 1000)
2430 if (count + divisor / 2 < 1000 * divisor)
2431 break;
2433 float r = 1.0f * count / divisor;
2434 sprintf (buffer, "%.1f%c", r, units[i]);
2435 return buffer;
2438 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
2439 count. If DECIMAL_PLACES >= 0, format TOP/BOTTOM * 100 to DECIMAL_PLACES.
2440 If DECIMAL_PLACES is zero, no decimal point is printed. Only print 100% when
2441 TOP==BOTTOM and only print 0% when TOP=0. If DECIMAL_PLACES < 0, then simply
2442 format TOP. Return pointer to a static string. */
2444 static char const *
2445 format_gcov (gcov_type top, gcov_type bottom, int decimal_places)
2447 static char buffer[20];
2449 if (decimal_places >= 0)
2451 float ratio = bottom ? 100.0f * top / bottom: 0;
2453 /* Round up to 1% if there's a small non-zero value. */
2454 if (ratio > 0.0f && ratio < 0.5f && decimal_places == 0)
2455 ratio = 1.0f;
2456 sprintf (buffer, "%.*f%%", decimal_places, ratio);
2458 else
2459 return format_count (top);
2461 return buffer;
2464 /* Summary of execution */
2466 static void
2467 executed_summary (unsigned lines, unsigned executed)
2469 if (lines)
2470 fnotice (stdout, "Lines executed:%s of %d\n",
2471 format_gcov (executed, lines, 2), lines);
2472 else
2473 fnotice (stdout, "No executable lines\n");
2476 /* Output summary info for a function. */
2478 static void
2479 function_summary (const coverage_info *coverage)
2481 fnotice (stdout, "%s '%s'\n", "Function", coverage->name);
2482 executed_summary (coverage->lines, coverage->lines_executed);
2485 /* Output summary info for a file. */
2487 static void
2488 file_summary (const coverage_info *coverage)
2490 fnotice (stdout, "%s '%s'\n", "File", coverage->name);
2491 executed_summary (coverage->lines, coverage->lines_executed);
2493 if (flag_branches)
2495 if (coverage->branches)
2497 fnotice (stdout, "Branches executed:%s of %d\n",
2498 format_gcov (coverage->branches_executed,
2499 coverage->branches, 2),
2500 coverage->branches);
2501 fnotice (stdout, "Taken at least once:%s of %d\n",
2502 format_gcov (coverage->branches_taken,
2503 coverage->branches, 2),
2504 coverage->branches);
2506 else
2507 fnotice (stdout, "No branches\n");
2508 if (coverage->calls)
2509 fnotice (stdout, "Calls executed:%s of %d\n",
2510 format_gcov (coverage->calls_executed, coverage->calls, 2),
2511 coverage->calls);
2512 else
2513 fnotice (stdout, "No calls\n");
2517 /* Canonicalize the filename NAME by canonicalizing directory
2518 separators, eliding . components and resolving .. components
2519 appropriately. Always returns a unique string. */
2521 static char *
2522 canonicalize_name (const char *name)
2524 /* The canonical name cannot be longer than the incoming name. */
2525 char *result = XNEWVEC (char, strlen (name) + 1);
2526 const char *base = name, *probe;
2527 char *ptr = result;
2528 char *dd_base;
2529 int slash = 0;
2531 #if HAVE_DOS_BASED_FILE_SYSTEM
2532 if (base[0] && base[1] == ':')
2534 result[0] = base[0];
2535 result[1] = ':';
2536 base += 2;
2537 ptr += 2;
2539 #endif
2540 for (dd_base = ptr; *base; base = probe)
2542 size_t len;
2544 for (probe = base; *probe; probe++)
2545 if (IS_DIR_SEPARATOR (*probe))
2546 break;
2548 len = probe - base;
2549 if (len == 1 && base[0] == '.')
2550 /* Elide a '.' directory */
2552 else if (len == 2 && base[0] == '.' && base[1] == '.')
2554 /* '..', we can only elide it and the previous directory, if
2555 we're not a symlink. */
2556 struct stat ATTRIBUTE_UNUSED buf;
2558 *ptr = 0;
2559 if (dd_base == ptr
2560 #if defined (S_ISLNK)
2561 /* S_ISLNK is not POSIX.1-1996. */
2562 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2563 #endif
2566 /* Cannot elide, or unreadable or a symlink. */
2567 dd_base = ptr + 2 + slash;
2568 goto regular;
2570 while (ptr != dd_base && *ptr != '/')
2571 ptr--;
2572 slash = ptr != result;
2574 else
2576 regular:
2577 /* Regular pathname component. */
2578 if (slash)
2579 *ptr++ = '/';
2580 memcpy (ptr, base, len);
2581 ptr += len;
2582 slash = 1;
2585 for (; IS_DIR_SEPARATOR (*probe); probe++)
2586 continue;
2588 *ptr = 0;
2590 return result;
2593 /* Generate an output file name. INPUT_NAME is the canonicalized main
2594 input file and SRC_NAME is the canonicalized file name.
2595 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2596 long_output_names we prepend the processed name of the input file
2597 to each output name (except when the current source file is the
2598 input file, so you don't get a double concatenation). The two
2599 components are separated by '##'. With preserve_paths we create a
2600 filename from all path components of the source file, replacing '/'
2601 with '#', and .. with '^', without it we simply take the basename
2602 component. (Remember, the canonicalized name will already have
2603 elided '.' components and converted \\ separators.) */
2605 static string
2606 make_gcov_file_name (const char *input_name, const char *src_name)
2608 string str;
2610 /* When hashing filenames, we shorten them by only using the filename
2611 component and appending a hash of the full (mangled) pathname. */
2612 if (flag_hash_filenames)
2613 str = (string (mangle_name (src_name)) + "##"
2614 + get_md5sum (src_name) + ".gcov");
2615 else
2617 if (flag_long_names && input_name && strcmp (src_name, input_name) != 0)
2619 str += mangle_name (input_name);
2620 str += "##";
2623 str += mangle_name (src_name);
2624 str += ".gcov";
2627 return str;
2630 /* Mangle BASE name, copy it at the beginning of PTR buffer and
2631 return address of the \0 character of the buffer. */
2633 static char *
2634 mangle_name (char const *base)
2636 /* Generate the source filename part. */
2637 if (!flag_preserve_paths)
2638 return xstrdup (lbasename (base));
2639 else
2640 return mangle_path (base);
2643 /* Scan through the bb_data for each line in the block, increment
2644 the line number execution count indicated by the execution count of
2645 the appropriate basic block. */
2647 static void
2648 add_line_counts (coverage_info *coverage, function_info *fn)
2650 bool has_any_line = false;
2651 /* Scan each basic block. */
2652 for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
2654 line_info *line = NULL;
2655 block_info *block = &fn->blocks[ix];
2656 if (block->count && ix && ix + 1 != fn->blocks.size ())
2657 fn->blocks_executed++;
2658 for (unsigned i = 0; i < block->locations.size (); i++)
2660 unsigned src_idx = block->locations[i].source_file_idx;
2661 vector<unsigned> &lines = block->locations[i].lines;
2663 block->cycle.arc = NULL;
2664 block->cycle.ident = ~0U;
2666 for (unsigned j = 0; j < lines.size (); j++)
2668 unsigned ln = lines[j];
2670 /* Line belongs to a function that is in a group. */
2671 if (fn->group_line_p (ln, src_idx))
2673 gcc_assert (lines[j] - fn->start_line < fn->lines.size ());
2674 line = &(fn->lines[lines[j] - fn->start_line]);
2675 line->exists = 1;
2676 if (!block->exceptional)
2678 line->unexceptional = 1;
2679 if (block->count == 0)
2680 line->has_unexecuted_block = 1;
2682 line->count += block->count;
2684 else
2686 gcc_assert (ln < sources[src_idx].lines.size ());
2687 line = &(sources[src_idx].lines[ln]);
2688 if (coverage)
2690 if (!line->exists)
2691 coverage->lines++;
2692 if (!line->count && block->count)
2693 coverage->lines_executed++;
2695 line->exists = 1;
2696 if (!block->exceptional)
2698 line->unexceptional = 1;
2699 if (block->count == 0)
2700 line->has_unexecuted_block = 1;
2702 line->count += block->count;
2706 has_any_line = true;
2708 if (!ix || ix + 1 == fn->blocks.size ())
2709 /* Entry or exit block. */;
2710 else if (line != NULL)
2712 line->blocks.push_back (block);
2714 if (flag_branches)
2716 arc_info *arc;
2718 for (arc = block->succ; arc; arc = arc->succ_next)
2719 line->branches.push_back (arc);
2725 if (!has_any_line)
2726 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name,
2727 fn->get_name ());
2730 /* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE
2731 is set to true, update source file summary. */
2733 static void accumulate_line_info (line_info *line, source_info *src,
2734 bool add_coverage)
2736 if (add_coverage)
2737 for (vector<arc_info *>::iterator it = line->branches.begin ();
2738 it != line->branches.end (); it++)
2739 add_branch_counts (&src->coverage, *it);
2741 if (!line->blocks.empty ())
2743 /* The user expects the line count to be the number of times
2744 a line has been executed. Simply summing the block count
2745 will give an artificially high number. The Right Thing
2746 is to sum the entry counts to the graph of blocks on this
2747 line, then find the elementary cycles of the local graph
2748 and add the transition counts of those cycles. */
2749 gcov_type count = 0;
2751 /* Cycle detection. */
2752 for (vector<block_info *>::iterator it = line->blocks.begin ();
2753 it != line->blocks.end (); it++)
2755 for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next)
2756 if (!line->has_block (arc->src))
2757 count += arc->count;
2758 for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next)
2759 arc->cs_count = arc->count;
2762 /* Now, add the count of loops entirely on this line. */
2763 count += get_cycles_count (*line);
2764 line->count = count;
2766 if (line->count > src->maximum_count)
2767 src->maximum_count = line->count;
2770 if (line->exists && add_coverage)
2772 src->coverage.lines++;
2773 if (line->count)
2774 src->coverage.lines_executed++;
2778 /* Accumulate the line counts of a file. */
2780 static void
2781 accumulate_line_counts (source_info *src)
2783 /* First work on group functions. */
2784 for (vector<function_info *>::iterator it = src->functions.begin ();
2785 it != src->functions.end (); it++)
2787 function_info *fn = *it;
2789 if (fn->src != src->index || !fn->is_group)
2790 continue;
2792 for (vector<line_info>::iterator it2 = fn->lines.begin ();
2793 it2 != fn->lines.end (); it2++)
2795 line_info *line = &(*it2);
2796 accumulate_line_info (line, src, false);
2800 /* Work on global lines that line in source file SRC. */
2801 for (vector<line_info>::iterator it = src->lines.begin ();
2802 it != src->lines.end (); it++)
2803 accumulate_line_info (&(*it), src, true);
2805 /* If not using intermediate mode, sum lines of group functions and
2806 add them to lines that live in a source file. */
2807 if (!flag_json_format)
2808 for (vector<function_info *>::iterator it = src->functions.begin ();
2809 it != src->functions.end (); it++)
2811 function_info *fn = *it;
2813 if (fn->src != src->index || !fn->is_group)
2814 continue;
2816 for (unsigned i = 0; i < fn->lines.size (); i++)
2818 line_info *fn_line = &fn->lines[i];
2819 if (fn_line->exists)
2821 unsigned ln = fn->start_line + i;
2822 line_info *src_line = &src->lines[ln];
2824 if (!src_line->exists)
2825 src->coverage.lines++;
2826 if (!src_line->count && fn_line->count)
2827 src->coverage.lines_executed++;
2829 src_line->count += fn_line->count;
2830 src_line->exists = 1;
2832 if (fn_line->has_unexecuted_block)
2833 src_line->has_unexecuted_block = 1;
2835 if (fn_line->unexceptional)
2836 src_line->unexceptional = 1;
2842 /* Output information about ARC number IX. Returns nonzero if
2843 anything is output. */
2845 static int
2846 output_branch_count (FILE *gcov_file, int ix, const arc_info *arc)
2848 if (arc->is_call_non_return)
2850 if (arc->src->count)
2852 fnotice (gcov_file, "call %2d returned %s\n", ix,
2853 format_gcov (arc->src->count - arc->count,
2854 arc->src->count, -flag_counts));
2856 else
2857 fnotice (gcov_file, "call %2d never executed\n", ix);
2859 else if (!arc->is_unconditional)
2861 if (arc->src->count)
2862 fnotice (gcov_file, "branch %2d taken %s%s", ix,
2863 format_gcov (arc->count, arc->src->count, -flag_counts),
2864 arc->fall_through ? " (fallthrough)"
2865 : arc->is_throw ? " (throw)" : "");
2866 else
2867 fnotice (gcov_file, "branch %2d never executed", ix);
2869 if (flag_verbose)
2870 fnotice (gcov_file, " (BB %d)", arc->dst->id);
2872 fnotice (gcov_file, "\n");
2874 else if (flag_unconditional && !arc->dst->is_call_return)
2876 if (arc->src->count)
2877 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2878 format_gcov (arc->count, arc->src->count, -flag_counts));
2879 else
2880 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2882 else
2883 return 0;
2884 return 1;
2887 static const char *
2888 read_line (FILE *file)
2890 static char *string;
2891 static size_t string_len;
2892 size_t pos = 0;
2893 char *ptr;
2895 if (!string_len)
2897 string_len = 200;
2898 string = XNEWVEC (char, string_len);
2901 while ((ptr = fgets (string + pos, string_len - pos, file)))
2903 size_t len = strlen (string + pos);
2905 if (len && string[pos + len - 1] == '\n')
2907 string[pos + len - 1] = 0;
2908 return string;
2910 pos += len;
2911 /* If the file contains NUL characters or an incomplete
2912 last line, which can happen more than once in one run,
2913 we have to avoid doubling the STRING_LEN unnecessarily. */
2914 if (pos > string_len / 2)
2916 string_len *= 2;
2917 string = XRESIZEVEC (char, string, string_len);
2921 return pos ? string : NULL;
2924 /* Pad string S with spaces from left to have total width equal to 9. */
2926 static void
2927 pad_count_string (string &s)
2929 if (s.size () < 9)
2930 s.insert (0, 9 - s.size (), ' ');
2933 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2934 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2935 an exceptional statement. The output is printed for LINE_NUM of given
2936 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2937 used to indicate non-executed blocks. */
2939 static void
2940 output_line_beginning (FILE *f, bool exists, bool unexceptional,
2941 bool has_unexecuted_block,
2942 gcov_type count, unsigned line_num,
2943 const char *exceptional_string,
2944 const char *unexceptional_string,
2945 unsigned int maximum_count)
2947 string s;
2948 if (exists)
2950 if (count > 0)
2952 s = format_gcov (count, 0, -1);
2953 if (has_unexecuted_block
2954 && bbg_supports_has_unexecuted_blocks)
2956 if (flag_use_colors)
2958 pad_count_string (s);
2959 s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
2960 COLOR_SEPARATOR COLOR_FG_WHITE));
2961 s += SGR_RESET;
2963 else
2964 s += "*";
2966 pad_count_string (s);
2968 else
2970 if (flag_use_colors)
2972 s = "0";
2973 pad_count_string (s);
2974 if (unexceptional)
2975 s.insert (0, SGR_SEQ (COLOR_BG_RED
2976 COLOR_SEPARATOR COLOR_FG_WHITE));
2977 else
2978 s.insert (0, SGR_SEQ (COLOR_BG_CYAN
2979 COLOR_SEPARATOR COLOR_FG_WHITE));
2980 s += SGR_RESET;
2982 else
2984 s = unexceptional ? unexceptional_string : exceptional_string;
2985 pad_count_string (s);
2989 else
2991 s = "-";
2992 pad_count_string (s);
2995 /* Format line number in output. */
2996 char buffer[16];
2997 sprintf (buffer, "%5u", line_num);
2998 string linestr (buffer);
3000 if (flag_use_hotness_colors && maximum_count)
3002 if (count * 2 > maximum_count) /* > 50%. */
3003 linestr.insert (0, SGR_SEQ (COLOR_BG_RED));
3004 else if (count * 5 > maximum_count) /* > 20%. */
3005 linestr.insert (0, SGR_SEQ (COLOR_BG_YELLOW));
3006 else if (count * 10 > maximum_count) /* > 10%. */
3007 linestr.insert (0, SGR_SEQ (COLOR_BG_GREEN));
3008 linestr += SGR_RESET;
3011 fprintf (f, "%s:%s", s.c_str (), linestr.c_str ());
3014 static void
3015 print_source_line (FILE *f, const vector<const char *> &source_lines,
3016 unsigned line)
3018 gcc_assert (line >= 1);
3019 gcc_assert (line <= source_lines.size ());
3021 fprintf (f, ":%s\n", source_lines[line - 1]);
3024 /* Output line details for LINE and print it to F file. LINE lives on
3025 LINE_NUM. */
3027 static void
3028 output_line_details (FILE *f, const line_info *line, unsigned line_num)
3030 if (flag_all_blocks)
3032 arc_info *arc;
3033 int ix, jx;
3035 ix = jx = 0;
3036 for (vector<block_info *>::const_iterator it = line->blocks.begin ();
3037 it != line->blocks.end (); it++)
3039 if (!(*it)->is_call_return)
3041 output_line_beginning (f, line->exists,
3042 (*it)->exceptional, false,
3043 (*it)->count, line_num,
3044 "%%%%%", "$$$$$", 0);
3045 fprintf (f, "-block %2d", ix++);
3046 if (flag_verbose)
3047 fprintf (f, " (BB %u)", (*it)->id);
3048 fprintf (f, "\n");
3050 if (flag_branches)
3051 for (arc = (*it)->succ; arc; arc = arc->succ_next)
3052 jx += output_branch_count (f, jx, arc);
3055 else if (flag_branches)
3057 int ix;
3059 ix = 0;
3060 for (vector<arc_info *>::const_iterator it = line->branches.begin ();
3061 it != line->branches.end (); it++)
3062 ix += output_branch_count (f, ix, (*it));
3066 /* Output detail statistics about function FN to file F. */
3068 static void
3069 output_function_details (FILE *f, function_info *fn)
3071 if (!flag_branches)
3072 return;
3074 arc_info *arc = fn->blocks[EXIT_BLOCK].pred;
3075 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
3076 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
3078 for (; arc; arc = arc->pred_next)
3079 if (arc->fake)
3080 return_count -= arc->count;
3082 fprintf (f, "function %s", fn->get_name ());
3083 fprintf (f, " called %s",
3084 format_gcov (called_count, 0, -1));
3085 fprintf (f, " returned %s",
3086 format_gcov (return_count, called_count, 0));
3087 fprintf (f, " blocks executed %s",
3088 format_gcov (fn->blocks_executed, fn->get_block_count (), 0));
3089 fprintf (f, "\n");
3092 /* Read in the source file one line at a time, and output that line to
3093 the gcov file preceded by its execution count and other
3094 information. */
3096 static void
3097 output_lines (FILE *gcov_file, const source_info *src)
3099 #define DEFAULT_LINE_START " -: 0:"
3100 #define FN_SEPARATOR "------------------\n"
3102 FILE *source_file;
3103 const char *retval;
3105 /* Print colorization legend. */
3106 if (flag_use_colors)
3107 fprintf (gcov_file, "%s",
3108 DEFAULT_LINE_START "Colorization: profile count: " \
3109 SGR_SEQ (COLOR_BG_CYAN) "zero coverage (exceptional)" SGR_RESET \
3110 " " \
3111 SGR_SEQ (COLOR_BG_RED) "zero coverage (unexceptional)" SGR_RESET \
3112 " " \
3113 SGR_SEQ (COLOR_BG_MAGENTA) "unexecuted block" SGR_RESET "\n");
3115 if (flag_use_hotness_colors)
3116 fprintf (gcov_file, "%s",
3117 DEFAULT_LINE_START "Colorization: line numbers: hotness: " \
3118 SGR_SEQ (COLOR_BG_RED) "> 50%" SGR_RESET " " \
3119 SGR_SEQ (COLOR_BG_YELLOW) "> 20%" SGR_RESET " " \
3120 SGR_SEQ (COLOR_BG_GREEN) "> 10%" SGR_RESET "\n");
3122 fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
3123 if (!multiple_files)
3125 fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
3126 fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
3127 no_data_file ? "-" : da_file_name);
3128 fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
3131 source_file = fopen (src->name, "r");
3132 if (!source_file)
3133 fnotice (stderr, "Cannot open source file %s\n", src->name);
3134 else if (src->file_time == 0)
3135 fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
3137 vector<const char *> source_lines;
3138 if (source_file)
3139 while ((retval = read_line (source_file)) != NULL)
3140 source_lines.push_back (xstrdup (retval));
3142 unsigned line_start_group = 0;
3143 vector<function_info *> *fns;
3145 for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++)
3147 if (line_num >= src->lines.size ())
3149 fprintf (gcov_file, "%9s:%5u", "-", line_num);
3150 print_source_line (gcov_file, source_lines, line_num);
3151 continue;
3154 const line_info *line = &src->lines[line_num];
3156 if (line_start_group == 0)
3158 fns = src->get_functions_at_location (line_num);
3159 if (fns != NULL && fns->size () > 1)
3161 /* It's possible to have functions that partially overlap,
3162 thus take the maximum end_line of functions starting
3163 at LINE_NUM. */
3164 for (unsigned i = 0; i < fns->size (); i++)
3165 if ((*fns)[i]->end_line > line_start_group)
3166 line_start_group = (*fns)[i]->end_line;
3168 else if (fns != NULL && fns->size () == 1)
3170 function_info *fn = (*fns)[0];
3171 output_function_details (gcov_file, fn);
3175 /* For lines which don't exist in the .bb file, print '-' before
3176 the source line. For lines which exist but were never
3177 executed, print '#####' or '=====' before the source line.
3178 Otherwise, print the execution count before the source line.
3179 There are 16 spaces of indentation added before the source
3180 line so that tabs won't be messed up. */
3181 output_line_beginning (gcov_file, line->exists, line->unexceptional,
3182 line->has_unexecuted_block, line->count,
3183 line_num, "=====", "#####", src->maximum_count);
3185 print_source_line (gcov_file, source_lines, line_num);
3186 output_line_details (gcov_file, line, line_num);
3188 if (line_start_group == line_num)
3190 for (vector<function_info *>::iterator it = fns->begin ();
3191 it != fns->end (); it++)
3193 function_info *fn = *it;
3194 vector<line_info> &lines = fn->lines;
3196 fprintf (gcov_file, FN_SEPARATOR);
3198 string fn_name = fn->get_name ();
3199 if (flag_use_colors)
3201 fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN));
3202 fn_name += SGR_RESET;
3205 fprintf (gcov_file, "%s:\n", fn_name.c_str ());
3207 output_function_details (gcov_file, fn);
3209 /* Print all lines covered by the function. */
3210 for (unsigned i = 0; i < lines.size (); i++)
3212 line_info *line = &lines[i];
3213 unsigned l = fn->start_line + i;
3215 /* For lines which don't exist in the .bb file, print '-'
3216 before the source line. For lines which exist but
3217 were never executed, print '#####' or '=====' before
3218 the source line. Otherwise, print the execution count
3219 before the source line.
3220 There are 16 spaces of indentation added before the source
3221 line so that tabs won't be messed up. */
3222 output_line_beginning (gcov_file, line->exists,
3223 line->unexceptional,
3224 line->has_unexecuted_block,
3225 line->count,
3226 l, "=====", "#####",
3227 src->maximum_count);
3229 print_source_line (gcov_file, source_lines, l);
3230 output_line_details (gcov_file, line, l);
3234 fprintf (gcov_file, FN_SEPARATOR);
3235 line_start_group = 0;
3239 if (source_file)
3240 fclose (source_file);