1 /* Gcov.c: prepend line execution counts and branch probabilities to a
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)
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. */
34 #define INCLUDE_ALGORITHM
35 #define INCLUDE_VECTOR
36 #define INCLUDE_STRING
40 #include "coretypes.h"
43 #include "diagnostic.h"
46 #include "color-macros.h"
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. */
80 /* Describes an arc between two basic blocks. */
84 /* source and destination blocks. */
85 struct block_info
*src
;
86 struct block_info
*dst
;
88 /* transition counts. */
90 /* used in cycle search, so that we do not clobber original counts. */
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
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. */
139 /* Chain of exit and entry arcs. */
143 /* Number of unprocessed exit and entry arcs. */
149 /* Block execution 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
;
167 /* Single line graph cycle workspace. Used for all-blocks
171 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
174 /* Temporary chain for solving graph, and for chaining blocks on one
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
)
188 /* Describes a single line of source. Contains a chain of basic blocks
193 /* Default constructor. */
196 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
197 bool has_block (block_info
*needle
);
199 /* Execution 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
;
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)
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. */
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. */
238 is_artificial (function_info
*fn
)
240 return fn
->artificial
;
243 /* Name of function. */
245 char *demangled_name
;
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
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. */
273 /* First line column. */
274 unsigned start_column
;
276 /* Last line number. */
279 /* Index of source file where the function is defined. */
282 /* Vector of line information. */
283 vector
<line_info
> lines
;
286 struct function_info
*next
;
289 /* Function info comparer that will sort functions according to starting
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. */
311 int branches_executed
;
320 /* Describes a file mentioned in the block graph. Contains an array
325 /* Default constructor. */
328 vector
<function_info
*> get_functions_at_location (unsigned line_num
) const;
330 /* Index of the source_info in sources vector. */
333 /* Canonical name of source file. */
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
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
)
364 std::sort (r
.begin (), r
.end (), function_line_start_cmp ());
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;
385 return strcmp (this->name
, rhs
.name
) == 0;
389 bool operator< (const name_map
&rhs
) const
391 #if HAVE_DOS_BASED_FILE_SYSTEM
392 return strcasecmp (this->name
, rhs
.name
) < 0;
394 return strcmp (this->name
, rhs
.name
) < 0;
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
451 static int multiple_files
= 0;
453 /* Output branch probabilities. */
455 static int flag_branches
= 0;
457 /* Show unconditional branches too. */
458 static int flag_unconditional
= 0;
460 /* Output a gcov file if this is true. This is on by default, and can
461 be turned off by the -n option. */
463 static int flag_gcov_file
= 1;
465 /* Output to stdout instead to a gcov file. */
467 static int flag_use_stdout
= 0;
469 /* Output progress indication if this is true. This is off by default
470 and can be turned on by the -d option. */
472 static int flag_display_progress
= 0;
474 /* Output *.gcov file in intermediate format used by 'lcov'. */
476 static int flag_intermediate_format
= 0;
478 /* Output demangled function names. */
480 static int flag_demangled_names
= 0;
482 /* For included files, make the gcov output file name include the name
483 of the input source file. For example, if x.h is included in a.c,
484 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
486 static int flag_long_names
= 0;
488 /* For situations when a long name can potentially hit filesystem path limit,
489 let's calculate md5sum of the path and append it to a file name. */
491 static int flag_hash_filenames
= 0;
493 /* Print verbose informations. */
495 static int flag_verbose
= 0;
497 /* Print colored output. */
499 static int flag_use_colors
= 0;
501 /* Output count information for every basic block, not merely those
502 that contain line number information. */
504 static int flag_all_blocks
= 0;
506 /* Output human readable numbers. */
508 static int flag_human_readable_numbers
= 0;
510 /* Output summary info for each function. */
512 static int flag_function_summary
= 0;
514 /* Object directory file prefix. This is the directory/file where the
515 graph and data files are looked for, if nonzero. */
517 static char *object_directory
= 0;
519 /* Source directory prefix. This is removed from source pathnames
520 that match, when generating the output file name. */
522 static char *source_prefix
= 0;
523 static size_t source_length
= 0;
525 /* Only show data for sources with relative pathnames. Absolute ones
526 usually indicate a system header file, which although it may
527 contain inline functions, is usually uninteresting. */
528 static int flag_relative_only
= 0;
530 /* Preserve all pathname components. Needed when object files and
531 source files are in subdirectories. '/' is mangled as '#', '.' is
532 elided and '..' mangled to '^'. */
534 static int flag_preserve_paths
= 0;
536 /* Output the number of times a branch was taken as opposed to the percentage
537 of times it was taken. */
539 static int flag_counts
= 0;
541 /* Forward declarations. */
542 static int process_args (int, char **);
543 static void print_usage (int) ATTRIBUTE_NORETURN
;
544 static void print_version (void) ATTRIBUTE_NORETURN
;
545 static void process_file (const char *);
546 static void generate_results (const char *);
547 static void create_file_names (const char *);
548 static char *canonicalize_name (const char *);
549 static unsigned find_source (const char *);
550 static void read_graph_file (void);
551 static int read_count_file (void);
552 static void solve_flow_graph (function_info
*);
553 static void find_exception_blocks (function_info
*);
554 static void add_branch_counts (coverage_info
*, const arc_info
*);
555 static void add_line_counts (coverage_info
*, function_info
*);
556 static void executed_summary (unsigned, unsigned);
557 static void function_summary (const coverage_info
*, const char *);
558 static const char *format_gcov (gcov_type
, gcov_type
, int);
559 static void accumulate_line_counts (source_info
*);
560 static void output_gcov_file (const char *, source_info
*);
561 static int output_branch_count (FILE *, int, const arc_info
*);
562 static void output_lines (FILE *, const source_info
*);
563 static char *make_gcov_file_name (const char *, const char *);
564 static char *mangle_name (const char *, char *);
565 static void release_structures (void);
566 extern int main (int, char **);
568 function_info::function_info (): name (NULL
), demangled_name (NULL
),
569 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
570 artificial (0), is_group (0),
571 blocks (), blocks_executed (0), counts (),
572 start_line (0), start_column (), end_line (0), src (0), lines (), next (NULL
)
576 function_info::~function_info ()
578 for (int i
= blocks
.size () - 1; i
>= 0; i
--)
580 arc_info
*arc
, *arc_n
;
582 for (arc
= blocks
[i
].succ
; arc
; arc
= arc_n
)
584 arc_n
= arc
->succ_next
;
588 if (flag_demangled_names
&& demangled_name
!= name
)
589 free (demangled_name
);
593 bool function_info::group_line_p (unsigned n
, unsigned src_idx
)
595 return is_group
&& src
== src_idx
&& start_line
<= n
&& n
<= end_line
;
599 There are a bajillion algorithms that do this. Boost's function is named
600 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
601 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
602 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
604 The basic algorithm is simple: effectively, we're finding all simple paths
605 in a subgraph (that shrinks every iteration). Duplicates are filtered by
606 "blocking" a path when a node is added to the path (this also prevents non-
607 simple paths)--the node is unblocked only when it participates in a cycle.
610 typedef vector
<arc_info
*> arc_vector_t
;
611 typedef vector
<const block_info
*> block_vector_t
;
613 /* Enum with types of loop in CFG. */
622 /* Loop_type operator that merges two values: A and B. */
624 inline loop_type
& operator |= (loop_type
& a
, loop_type b
)
626 return a
= static_cast<loop_type
> (a
| b
);
629 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
630 and subtract the value from all counts. The subtracted value is added
631 to COUNT. Returns type of loop. */
634 handle_cycle (const arc_vector_t
&edges
, int64_t &count
)
636 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
638 int64_t cycle_count
= INTTYPE_MAXIMUM (int64_t);
639 for (unsigned i
= 0; i
< edges
.size (); i
++)
641 int64_t ecount
= edges
[i
]->cs_count
;
642 if (cycle_count
> ecount
)
643 cycle_count
= ecount
;
645 count
+= cycle_count
;
646 for (unsigned i
= 0; i
< edges
.size (); i
++)
647 edges
[i
]->cs_count
-= cycle_count
;
649 return cycle_count
< 0 ? NEGATIVE_LOOP
: LOOP
;
652 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
653 blocked by U in BLOCK_LISTS. */
656 unblock (const block_info
*u
, block_vector_t
&blocked
,
657 vector
<block_vector_t
> &block_lists
)
659 block_vector_t::iterator it
= find (blocked
.begin (), blocked
.end (), u
);
660 if (it
== blocked
.end ())
663 unsigned index
= it
- blocked
.begin ();
666 block_vector_t
to_unblock (block_lists
[index
]);
668 block_lists
.erase (block_lists
.begin () + index
);
670 for (block_vector_t::iterator it
= to_unblock
.begin ();
671 it
!= to_unblock
.end (); it
++)
672 unblock (*it
, blocked
, block_lists
);
675 /* Find circuit going to block V, PATH is provisional seen cycle.
676 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
677 blocked by a block. COUNT is accumulated count of the current LINE.
678 Returns what type of loop it contains. */
681 circuit (block_info
*v
, arc_vector_t
&path
, block_info
*start
,
682 block_vector_t
&blocked
, vector
<block_vector_t
> &block_lists
,
683 line_info
&linfo
, int64_t &count
)
685 loop_type result
= NO_LOOP
;
687 /* Add v to the block list. */
688 gcc_assert (find (blocked
.begin (), blocked
.end (), v
) == blocked
.end ());
689 blocked
.push_back (v
);
690 block_lists
.push_back (block_vector_t ());
692 for (arc_info
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
694 block_info
*w
= arc
->dst
;
695 if (w
< start
|| !linfo
.has_block (w
))
698 path
.push_back (arc
);
700 /* Cycle has been found. */
701 result
|= handle_cycle (path
, count
);
702 else if (find (blocked
.begin (), blocked
.end (), w
) == blocked
.end ())
703 result
|= circuit (w
, path
, start
, blocked
, block_lists
, linfo
, count
);
708 if (result
!= NO_LOOP
)
709 unblock (v
, blocked
, block_lists
);
711 for (arc_info
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
713 block_info
*w
= arc
->dst
;
714 if (w
< start
|| !linfo
.has_block (w
))
718 = find (blocked
.begin (), blocked
.end (), w
) - blocked
.begin ();
719 gcc_assert (index
< blocked
.size ());
720 block_vector_t
&list
= block_lists
[index
];
721 if (find (list
.begin (), list
.end (), v
) == list
.end ())
728 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
729 contains a negative loop, then perform the same function once again. */
732 get_cycles_count (line_info
&linfo
, bool handle_negative_cycles
= true)
734 /* Note that this algorithm works even if blocks aren't in sorted order.
735 Each iteration of the circuit detection is completely independent
736 (except for reducing counts, but that shouldn't matter anyways).
737 Therefore, operating on a permuted order (i.e., non-sorted) only
738 has the effect of permuting the output cycles. */
740 loop_type result
= NO_LOOP
;
742 for (vector
<block_info
*>::iterator it
= linfo
.blocks
.begin ();
743 it
!= linfo
.blocks
.end (); it
++)
746 block_vector_t blocked
;
747 vector
<block_vector_t
> block_lists
;
748 result
|= circuit (*it
, path
, *it
, blocked
, block_lists
, linfo
,
752 /* If we have a negative cycle, repeat the find_cycles routine. */
753 if (result
== NEGATIVE_LOOP
&& handle_negative_cycles
)
754 count
+= get_cycles_count (linfo
, false);
760 main (int argc
, char **argv
)
766 p
= argv
[0] + strlen (argv
[0]);
767 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
771 xmalloc_set_program_name (progname
);
773 /* Unlock the stdio streams. */
774 unlock_std_streams ();
778 diagnostic_initialize (global_dc
, 0);
780 /* Handle response files. */
781 expandargv (&argc
, &argv
);
783 argno
= process_args (argc
, argv
);
787 if (argc
- argno
> 1)
792 for (; argno
!= argc
; argno
++)
794 if (flag_display_progress
)
795 printf ("Processing file %d out of %d\n", argno
- first_arg
+ 1,
797 process_file (argv
[argno
]);
799 if (flag_intermediate_format
|| argno
== argc
- 1)
801 generate_results (argv
[argno
]);
802 release_structures ();
809 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
810 otherwise the output of --help. */
813 print_usage (int error_p
)
815 FILE *file
= error_p
? stderr
: stdout
;
816 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
818 fnotice (file
, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
819 fnotice (file
, "Print code coverage information.\n\n");
820 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
821 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
822 fnotice (file
, " -c, --branch-counts Output counts of branches taken\n\
823 rather than percentages\n");
824 fnotice (file
, " -d, --display-progress Display progress information\n");
825 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
826 fnotice (file
, " -h, --help Print this help, then exit\n");
827 fnotice (file
, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
828 fnotice (file
, " -j, --human-readable Output human readable numbers\n");
829 fnotice (file
, " -k, --use-colors Emit colored output\n");
830 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
832 fnotice (file
, " -m, --demangled-names Output demangled function names\n");
833 fnotice (file
, " -n, --no-output Do not create an output file\n");
834 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
835 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
836 fnotice (file
, " -r, --relative-only Only show data for relative sources\n");
837 fnotice (file
, " -s, --source-prefix DIR Source prefix to elide\n");
838 fnotice (file
, " -t, --stdout Output to stdout instead of a file\n");
839 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
840 fnotice (file
, " -v, --version Print version number, then exit\n");
841 fnotice (file
, " -w, --verbose Print verbose informations\n");
842 fnotice (file
, " -x, --hash-filenames Hash long pathnames\n");
843 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
848 /* Print version information and exit. */
853 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
854 fprintf (stdout
, "Copyright %s 2018 Free Software Foundation, Inc.\n",
857 _("This is free software; see the source for copying conditions.\n"
858 "There is NO warranty; not even for MERCHANTABILITY or \n"
859 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
860 exit (SUCCESS_EXIT_CODE
);
863 static const struct option options
[] =
865 { "help", no_argument
, NULL
, 'h' },
866 { "version", no_argument
, NULL
, 'v' },
867 { "verbose", no_argument
, NULL
, 'w' },
868 { "all-blocks", no_argument
, NULL
, 'a' },
869 { "branch-probabilities", no_argument
, NULL
, 'b' },
870 { "branch-counts", no_argument
, NULL
, 'c' },
871 { "intermediate-format", no_argument
, NULL
, 'i' },
872 { "human-readable", no_argument
, NULL
, 'j' },
873 { "no-output", no_argument
, NULL
, 'n' },
874 { "long-file-names", no_argument
, NULL
, 'l' },
875 { "function-summaries", no_argument
, NULL
, 'f' },
876 { "demangled-names", no_argument
, NULL
, 'm' },
877 { "preserve-paths", no_argument
, NULL
, 'p' },
878 { "relative-only", no_argument
, NULL
, 'r' },
879 { "object-directory", required_argument
, NULL
, 'o' },
880 { "object-file", required_argument
, NULL
, 'o' },
881 { "source-prefix", required_argument
, NULL
, 's' },
882 { "stdout", no_argument
, NULL
, 't' },
883 { "unconditional-branches", no_argument
, NULL
, 'u' },
884 { "display-progress", no_argument
, NULL
, 'd' },
885 { "hash-filenames", no_argument
, NULL
, 'x' },
886 { "use-colors", no_argument
, NULL
, 'k' },
890 /* Process args, return index to first non-arg. */
893 process_args (int argc
, char **argv
)
897 const char *opts
= "abcdfhijklmno:prs:tuvwx";
898 while ((opt
= getopt_long (argc
, argv
, opts
, options
, NULL
)) != -1)
912 flag_function_summary
= 1;
916 /* print_usage will exit. */
921 flag_human_readable_numbers
= 1;
927 flag_demangled_names
= 1;
933 object_directory
= optarg
;
936 source_prefix
= optarg
;
937 source_length
= strlen (source_prefix
);
940 flag_relative_only
= 1;
943 flag_preserve_paths
= 1;
946 flag_unconditional
= 1;
949 flag_intermediate_format
= 1;
953 flag_display_progress
= 1;
956 flag_hash_filenames
= 1;
966 /* print_version will exit. */
969 /* print_usage will exit. */
976 /* Output intermediate LINE sitting on LINE_NUM to output file F. */
979 output_intermediate_line (FILE *f
, line_info
*line
, unsigned line_num
)
984 fprintf (f
, "lcount:%u,%s,%d\n", line_num
,
985 format_gcov (line
->count
, 0, -1),
986 line
->has_unexecuted_block
);
988 vector
<arc_info
*>::const_iterator it
;
990 for (it
= line
->branches
.begin (); it
!= line
->branches
.end ();
993 if (!(*it
)->is_unconditional
&& !(*it
)->is_call_non_return
)
995 const char *branch_type
;
996 /* branch:<line_num>,<branch_coverage_infoype>
997 branch_coverage_infoype
998 : notexec (Branch not executed)
999 : taken (Branch executed and taken)
1000 : nottaken (Branch executed, but not taken)
1002 if ((*it
)->src
->count
)
1004 = ((*it
)->count
> 0) ? "taken" : "nottaken";
1006 branch_type
= "notexec";
1007 fprintf (f
, "branch:%d,%s\n", line_num
, branch_type
);
1012 /* Get the name of the gcov file. The return value must be free'd.
1014 It appends the '.gcov' extension to the *basename* of the file.
1015 The resulting file name will be in PWD.
1018 input: foo.da, output: foo.da.gcov
1019 input: a/b/foo.cc, output: foo.cc.gcov */
1022 get_gcov_intermediate_filename (const char *file_name
)
1024 const char *gcov
= ".gcov";
1028 /* Find the 'basename'. */
1029 cptr
= lbasename (file_name
);
1031 result
= XNEWVEC (char, strlen (cptr
) + strlen (gcov
) + 1);
1032 sprintf (result
, "%s%s", cptr
, gcov
);
1037 /* Output the result in intermediate format used by 'lcov'.
1039 The intermediate format contains a single file named 'foo.cc.gcov',
1040 with no source code included.
1042 The default gcov outputs multiple files: 'foo.cc.gcov',
1043 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
1044 included. Instead the intermediate format here outputs only a single
1045 file 'foo.cc.gcov' similar to the above example. */
1048 output_intermediate_file (FILE *gcov_file
, source_info
*src
)
1050 fprintf (gcov_file
, "version:%s\n", version_string
);
1051 fprintf (gcov_file
, "file:%s\n", src
->name
); /* source file name */
1052 fprintf (gcov_file
, "cwd:%s\n", bbg_cwd
);
1054 std::sort (src
->functions
.begin (), src
->functions
.end (),
1055 function_line_start_cmp ());
1056 for (vector
<function_info
*>::iterator it
= src
->functions
.begin ();
1057 it
!= src
->functions
.end (); it
++)
1059 /* function:<name>,<line_number>,<execution_count> */
1060 fprintf (gcov_file
, "function:%d,%d,%s,%s\n", (*it
)->start_line
,
1061 (*it
)->end_line
, format_gcov ((*it
)->blocks
[0].count
, 0, -1),
1062 flag_demangled_names
? (*it
)->demangled_name
: (*it
)->name
);
1065 for (unsigned line_num
= 1; line_num
<= src
->lines
.size (); line_num
++)
1067 vector
<function_info
*> fns
= src
->get_functions_at_location (line_num
);
1069 /* Print first group functions that begin on the line. */
1070 for (vector
<function_info
*>::iterator it2
= fns
.begin ();
1071 it2
!= fns
.end (); it2
++)
1073 vector
<line_info
> &lines
= (*it2
)->lines
;
1074 for (unsigned i
= 0; i
< lines
.size (); i
++)
1076 line_info
*line
= &lines
[i
];
1077 output_intermediate_line (gcov_file
, line
, line_num
+ i
);
1081 /* Follow with lines associated with the source file. */
1082 output_intermediate_line (gcov_file
, &src
->lines
[line_num
], line_num
);
1086 /* Function start pair. */
1087 struct function_start
1089 unsigned source_file_idx
;
1090 unsigned start_line
;
1093 /* Traits class for function start hash maps below. */
1095 struct function_start_pair_hash
: typed_noop_remove
<function_start
>
1097 typedef function_start value_type
;
1098 typedef function_start compare_type
;
1101 hash (const function_start
&ref
)
1103 inchash::hash
hstate (0);
1104 hstate
.add_int (ref
.source_file_idx
);
1105 hstate
.add_int (ref
.start_line
);
1106 return hstate
.end ();
1110 equal (const function_start
&ref1
, const function_start
&ref2
)
1112 return (ref1
.source_file_idx
== ref2
.source_file_idx
1113 && ref1
.start_line
== ref2
.start_line
);
1117 mark_deleted (function_start
&ref
)
1119 ref
.start_line
= ~1U;
1123 mark_empty (function_start
&ref
)
1125 ref
.start_line
= ~2U;
1129 is_deleted (const function_start
&ref
)
1131 return ref
.start_line
== ~1U;
1135 is_empty (const function_start
&ref
)
1137 return ref
.start_line
== ~2U;
1141 /* Process a single input file. */
1144 process_file (const char *file_name
)
1146 create_file_names (file_name
);
1148 if (functions
.empty ())
1153 hash_map
<function_start_pair_hash
, function_info
*> fn_map
;
1155 /* Identify group functions. */
1156 for (vector
<function_info
*>::iterator it
= functions
.begin ();
1157 it
!= functions
.end (); it
++)
1158 if (!(*it
)->artificial
)
1160 function_start needle
;
1161 needle
.source_file_idx
= (*it
)->src
;
1162 needle
.start_line
= (*it
)->start_line
;
1164 function_info
**slot
= fn_map
.get (needle
);
1167 (*slot
)->is_group
= 1;
1168 (*it
)->is_group
= 1;
1171 fn_map
.put (needle
, *it
);
1174 /* Remove all artificial function. */
1175 functions
.erase (remove_if (functions
.begin (), functions
.end (),
1176 function_info::is_artificial
), functions
.end ());
1178 for (vector
<function_info
*>::iterator it
= functions
.begin ();
1179 it
!= functions
.end (); it
++)
1181 function_info
*fn
= *it
;
1182 unsigned src
= fn
->src
;
1184 if (!fn
->counts
.empty () || no_data_file
)
1186 source_info
*s
= &sources
[src
];
1187 s
->functions
.push_back (fn
);
1189 /* Mark last line in files touched by function. */
1190 for (unsigned block_no
= 0; block_no
!= fn
->blocks
.size ();
1193 block_info
*block
= &fn
->blocks
[block_no
];
1194 for (unsigned i
= 0; i
< block
->locations
.size (); i
++)
1196 /* Sort lines of locations. */
1197 sort (block
->locations
[i
].lines
.begin (),
1198 block
->locations
[i
].lines
.end ());
1200 if (!block
->locations
[i
].lines
.empty ())
1202 s
= &sources
[block
->locations
[i
].source_file_idx
];
1204 = block
->locations
[i
].lines
.back ();
1206 /* Record new lines for the function. */
1207 if (last_line
>= s
->lines
.size ())
1209 s
= &sources
[block
->locations
[i
].source_file_idx
];
1211 = block
->locations
[i
].lines
.back ();
1213 /* Record new lines for the function. */
1214 if (last_line
>= s
->lines
.size ())
1216 /* Record new lines for a source file. */
1217 s
->lines
.resize (last_line
+ 1);
1224 /* Allocate lines for group function, following start_line
1225 and end_line information of the function. */
1227 fn
->lines
.resize (fn
->end_line
- fn
->start_line
+ 1);
1230 solve_flow_graph (fn
);
1232 find_exception_blocks (fn
);
1236 /* The function was not in the executable -- some other
1237 instance must have been selected. */
1243 output_gcov_file (const char *file_name
, source_info
*src
)
1245 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->coverage
.name
);
1247 if (src
->coverage
.lines
)
1249 FILE *gcov_file
= fopen (gcov_file_name
, "w");
1252 fnotice (stdout
, "Creating '%s'\n", gcov_file_name
);
1253 output_lines (gcov_file
, src
);
1254 if (ferror (gcov_file
))
1255 fnotice (stderr
, "Error writing output file '%s'\n",
1260 fnotice (stderr
, "Could not open output file '%s'\n", gcov_file_name
);
1264 unlink (gcov_file_name
);
1265 fnotice (stdout
, "Removing '%s'\n", gcov_file_name
);
1267 free (gcov_file_name
);
1271 generate_results (const char *file_name
)
1273 FILE *gcov_intermediate_file
= NULL
;
1274 char *gcov_intermediate_filename
= NULL
;
1276 for (vector
<function_info
*>::iterator it
= functions
.begin ();
1277 it
!= functions
.end (); it
++)
1279 function_info
*fn
= *it
;
1280 coverage_info coverage
;
1282 memset (&coverage
, 0, sizeof (coverage
));
1283 coverage
.name
= flag_demangled_names
? fn
->demangled_name
: fn
->name
;
1284 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
1285 if (flag_function_summary
)
1287 function_summary (&coverage
, "Function");
1288 fnotice (stdout
, "\n");
1296 needle
.name
= file_name
;
1297 vector
<name_map
>::iterator it
= std::find (names
.begin (), names
.end (),
1299 if (it
!= names
.end ())
1300 file_name
= sources
[it
->src
].coverage
.name
;
1302 file_name
= canonicalize_name (file_name
);
1305 if (flag_gcov_file
&& flag_intermediate_format
&& !flag_use_stdout
)
1307 /* Open the intermediate file. */
1308 gcov_intermediate_filename
= get_gcov_intermediate_filename (file_name
);
1309 gcov_intermediate_file
= fopen (gcov_intermediate_filename
, "w");
1310 if (!gcov_intermediate_file
)
1312 fnotice (stderr
, "Cannot open intermediate output file %s\n",
1313 gcov_intermediate_filename
);
1318 for (vector
<source_info
>::iterator it
= sources
.begin ();
1319 it
!= sources
.end (); it
++)
1321 source_info
*src
= &(*it
);
1322 if (flag_relative_only
)
1324 /* Ignore this source, if it is an absolute path (after
1325 source prefix removal). */
1326 char first
= src
->coverage
.name
[0];
1328 #if HAVE_DOS_BASED_FILE_SYSTEM
1329 if (first
&& src
->coverage
.name
[1] == ':')
1330 first
= src
->coverage
.name
[2];
1332 if (IS_DIR_SEPARATOR (first
))
1336 accumulate_line_counts (src
);
1338 if (!flag_use_stdout
)
1339 function_summary (&src
->coverage
, "File");
1340 total_lines
+= src
->coverage
.lines
;
1341 total_executed
+= src
->coverage
.lines_executed
;
1344 if (flag_intermediate_format
)
1345 /* Output the intermediate format without requiring source
1346 files. This outputs a section to a *single* file. */
1347 output_intermediate_file ((flag_use_stdout
1348 ? stdout
: gcov_intermediate_file
), src
);
1351 if (flag_use_stdout
)
1353 if (src
->coverage
.lines
)
1354 output_lines (stdout
, src
);
1358 output_gcov_file (file_name
, src
);
1359 fnotice (stdout
, "\n");
1365 if (flag_gcov_file
&& flag_intermediate_format
&& !flag_use_stdout
)
1367 /* Now we've finished writing the intermediate file. */
1368 fclose (gcov_intermediate_file
);
1369 XDELETEVEC (gcov_intermediate_filename
);
1373 executed_summary (total_lines
, total_executed
);
1376 /* Release all memory used. */
1379 release_structures (void)
1381 for (vector
<function_info
*>::iterator it
= functions
.begin ();
1382 it
!= functions
.end (); it
++)
1387 functions
.resize (0);
1390 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1391 is not specified, these are named from FILE_NAME sans extension. If
1392 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1393 directory, but named from the basename of the FILE_NAME, sans extension.
1394 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1395 and the data files are named from that. */
1398 create_file_names (const char *file_name
)
1402 int length
= strlen (file_name
);
1405 /* Free previous file names. */
1406 free (bbg_file_name
);
1407 free (da_file_name
);
1408 da_file_name
= bbg_file_name
= NULL
;
1412 if (object_directory
&& object_directory
[0])
1416 length
+= strlen (object_directory
) + 2;
1417 name
= XNEWVEC (char, length
);
1420 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
1421 strcat (name
, object_directory
);
1422 if (base
&& (!IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
1427 name
= XNEWVEC (char, length
+ 1);
1428 strcpy (name
, file_name
);
1434 /* Append source file name. */
1435 const char *cptr
= lbasename (file_name
);
1436 strcat (name
, cptr
? cptr
: file_name
);
1439 /* Remove the extension. */
1440 cptr
= strrchr (CONST_CAST (char *, lbasename (name
)), '.');
1444 length
= strlen (name
);
1446 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
1447 strcpy (bbg_file_name
, name
);
1448 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
1450 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
1451 strcpy (da_file_name
, name
);
1452 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
1458 /* Find or create a source file structure for FILE_NAME. Copies
1459 FILE_NAME on creation */
1462 find_source (const char *file_name
)
1469 file_name
= "<unknown>";
1472 needle
.name
= file_name
;
1474 vector
<name_map
>::iterator it
= std::find (names
.begin (), names
.end (),
1476 if (it
!= names
.end ())
1482 /* Not found, try the canonical name. */
1483 canon
= canonicalize_name (file_name
);
1484 needle
.name
= canon
;
1485 it
= std::find (names
.begin (), names
.end (), needle
);
1486 if (it
== names
.end ())
1488 /* Not found with canonical name, create a new source. */
1491 idx
= sources
.size ();
1492 needle
= name_map (canon
, idx
);
1493 names
.push_back (needle
);
1495 sources
.push_back (source_info ());
1496 src
= &sources
.back ();
1498 src
->coverage
.name
= src
->name
;
1501 #if HAVE_DOS_BASED_FILE_SYSTEM
1502 /* You lose if separators don't match exactly in the
1504 && !strncasecmp (source_prefix
, src
->coverage
.name
, source_length
)
1506 && !strncmp (source_prefix
, src
->coverage
.name
, source_length
)
1508 && IS_DIR_SEPARATOR (src
->coverage
.name
[source_length
]))
1509 src
->coverage
.name
+= source_length
+ 1;
1510 if (!stat (src
->name
, &status
))
1511 src
->file_time
= status
.st_mtime
;
1516 needle
.name
= file_name
;
1517 if (std::find (names
.begin (), names
.end (), needle
) == names
.end ())
1519 /* Append the non-canonical name. */
1520 names
.push_back (name_map (xstrdup (file_name
), idx
));
1523 /* Resort the name map. */
1524 std::sort (names
.begin (), names
.end ());
1527 if (sources
[idx
].file_time
> bbg_file_time
)
1529 static int info_emitted
;
1531 fnotice (stderr
, "%s:source file is newer than notes file '%s'\n",
1532 file_name
, bbg_file_name
);
1536 "(the message is displayed only once per source file)\n");
1539 sources
[idx
].file_time
= 0;
1545 /* Read the notes file. Save functions to FUNCTIONS global vector. */
1548 read_graph_file (void)
1551 unsigned current_tag
= 0;
1554 if (!gcov_open (bbg_file_name
, 1))
1556 fnotice (stderr
, "%s:cannot open notes file\n", bbg_file_name
);
1559 bbg_file_time
= gcov_time ();
1560 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
1562 fnotice (stderr
, "%s:not a gcov notes file\n", bbg_file_name
);
1567 version
= gcov_read_unsigned ();
1568 if (version
!= GCOV_VERSION
)
1572 GCOV_UNSIGNED2STRING (v
, version
);
1573 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1575 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
1576 bbg_file_name
, v
, e
);
1578 bbg_stamp
= gcov_read_unsigned ();
1579 bbg_cwd
= xstrdup (gcov_read_string ());
1580 bbg_supports_has_unexecuted_blocks
= gcov_read_unsigned ();
1582 function_info
*fn
= NULL
;
1583 while ((tag
= gcov_read_unsigned ()))
1585 unsigned length
= gcov_read_unsigned ();
1586 gcov_position_t base
= gcov_position ();
1588 if (tag
== GCOV_TAG_FUNCTION
)
1590 char *function_name
;
1592 unsigned lineno_checksum
, cfg_checksum
;
1594 ident
= gcov_read_unsigned ();
1595 lineno_checksum
= gcov_read_unsigned ();
1596 cfg_checksum
= gcov_read_unsigned ();
1597 function_name
= xstrdup (gcov_read_string ());
1598 unsigned artificial
= gcov_read_unsigned ();
1599 unsigned src_idx
= find_source (gcov_read_string ());
1600 unsigned start_line
= gcov_read_unsigned ();
1601 unsigned start_column
= gcov_read_unsigned ();
1602 unsigned end_line
= gcov_read_unsigned ();
1604 fn
= new function_info ();
1605 functions
.push_back (fn
);
1606 fn
->name
= function_name
;
1607 if (flag_demangled_names
)
1609 fn
->demangled_name
= cplus_demangle (fn
->name
, DMGL_PARAMS
);
1610 if (!fn
->demangled_name
)
1611 fn
->demangled_name
= fn
->name
;
1614 fn
->lineno_checksum
= lineno_checksum
;
1615 fn
->cfg_checksum
= cfg_checksum
;
1617 fn
->start_line
= start_line
;
1618 fn
->start_column
= start_column
;
1619 fn
->end_line
= end_line
;
1620 fn
->artificial
= artificial
;
1624 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
1626 if (!fn
->blocks
.empty ())
1627 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
1628 bbg_file_name
, fn
->name
);
1630 fn
->blocks
.resize (gcov_read_unsigned ());
1632 else if (fn
&& tag
== GCOV_TAG_ARCS
)
1634 unsigned src
= gcov_read_unsigned ();
1635 fn
->blocks
[src
].id
= src
;
1636 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
1637 block_info
*src_blk
= &fn
->blocks
[src
];
1638 unsigned mark_catches
= 0;
1639 struct arc_info
*arc
;
1641 if (src
>= fn
->blocks
.size () || fn
->blocks
[src
].succ
)
1646 unsigned dest
= gcov_read_unsigned ();
1647 unsigned flags
= gcov_read_unsigned ();
1649 if (dest
>= fn
->blocks
.size ())
1651 arc
= XCNEW (arc_info
);
1653 arc
->dst
= &fn
->blocks
[dest
];
1657 arc
->count_valid
= 0;
1658 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
1659 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
1660 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
1662 arc
->succ_next
= src_blk
->succ
;
1663 src_blk
->succ
= arc
;
1664 src_blk
->num_succ
++;
1666 arc
->pred_next
= fn
->blocks
[dest
].pred
;
1667 fn
->blocks
[dest
].pred
= arc
;
1668 fn
->blocks
[dest
].num_pred
++;
1674 /* Exceptional exit from this function, the
1675 source block must be a call. */
1676 fn
->blocks
[src
].is_call_site
= 1;
1677 arc
->is_call_non_return
= 1;
1682 /* Non-local return from a callee of this
1683 function. The destination block is a setjmp. */
1684 arc
->is_nonlocal_return
= 1;
1685 fn
->blocks
[dest
].is_nonlocal_return
= 1;
1690 fn
->counts
.push_back (0);
1695 /* We have a fake exit from this block. The other
1696 non-fall through exits must be to catch handlers.
1697 Mark them as catch arcs. */
1699 for (arc
= src_blk
->succ
; arc
; arc
= arc
->succ_next
)
1700 if (!arc
->fake
&& !arc
->fall_through
)
1707 else if (fn
&& tag
== GCOV_TAG_LINES
)
1709 unsigned blockno
= gcov_read_unsigned ();
1710 block_info
*block
= &fn
->blocks
[blockno
];
1712 if (blockno
>= fn
->blocks
.size ())
1717 unsigned lineno
= gcov_read_unsigned ();
1720 block
->locations
.back ().lines
.push_back (lineno
);
1723 const char *file_name
= gcov_read_string ();
1727 block
->locations
.push_back (block_location_info
1728 (find_source (file_name
)));
1732 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
1737 gcov_sync (base
, length
);
1738 if (gcov_is_error ())
1741 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
1747 if (functions
.empty ())
1748 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
1751 /* Reads profiles from the count file and attach to each
1752 function. Return nonzero if fatal error. */
1755 read_count_file (void)
1760 function_info
*fn
= NULL
;
1763 if (!gcov_open (da_file_name
, 1))
1765 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1770 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1772 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1777 version
= gcov_read_unsigned ();
1778 if (version
!= GCOV_VERSION
)
1782 GCOV_UNSIGNED2STRING (v
, version
);
1783 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1785 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1786 da_file_name
, v
, e
);
1788 tag
= gcov_read_unsigned ();
1789 if (tag
!= bbg_stamp
)
1791 fnotice (stderr
, "%s:stamp mismatch with notes file\n", da_file_name
);
1795 while ((tag
= gcov_read_unsigned ()))
1797 unsigned length
= gcov_read_unsigned ();
1798 unsigned long base
= gcov_position ();
1800 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1802 struct gcov_summary summary
;
1803 gcov_read_summary (&summary
);
1804 object_runs
+= summary
.runs
;
1807 else if (tag
== GCOV_TAG_FUNCTION
&& !length
)
1809 else if (tag
== GCOV_TAG_FUNCTION
&& length
== GCOV_TAG_FUNCTION_LENGTH
)
1813 /* Try to find the function in the list. To speed up the
1814 search, first start from the last function found. */
1815 ident
= gcov_read_unsigned ();
1818 for (vector
<function_info
*>::reverse_iterator it
1819 = functions
.rbegin (); it
!= functions
.rend (); it
++)
1821 if ((*it
)->ident
== ident
)
1830 else if (gcov_read_unsigned () != fn
->lineno_checksum
1831 || gcov_read_unsigned () != fn
->cfg_checksum
)
1834 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1835 da_file_name
, fn
->name
);
1839 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1841 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->counts
.size ()))
1844 for (ix
= 0; ix
!= fn
->counts
.size (); ix
++)
1845 fn
->counts
[ix
] += gcov_read_counter ();
1847 gcov_sync (base
, length
);
1848 if ((error
= gcov_is_error ()))
1852 ? N_("%s:overflowed\n")
1853 : N_("%s:corrupted\n"),
1863 /* Solve the flow graph. Propagate counts from the instrumented arcs
1864 to the blocks and the uninstrumented arcs. */
1867 solve_flow_graph (function_info
*fn
)
1871 gcov_type
*count_ptr
= &fn
->counts
.front ();
1873 block_info
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1874 block_info
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1876 /* The arcs were built in reverse order. Fix that now. */
1877 for (ix
= fn
->blocks
.size (); ix
--;)
1879 arc_info
*arc_p
, *arc_n
;
1881 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1882 arc_p
= arc
, arc
= arc_n
)
1884 arc_n
= arc
->succ_next
;
1885 arc
->succ_next
= arc_p
;
1887 fn
->blocks
[ix
].succ
= arc_p
;
1889 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1890 arc_p
= arc
, arc
= arc_n
)
1892 arc_n
= arc
->pred_next
;
1893 arc
->pred_next
= arc_p
;
1895 fn
->blocks
[ix
].pred
= arc_p
;
1898 if (fn
->blocks
.size () < 2)
1899 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1900 bbg_file_name
, fn
->name
);
1903 if (fn
->blocks
[ENTRY_BLOCK
].num_pred
)
1904 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1905 bbg_file_name
, fn
->name
);
1907 /* We can't deduce the entry block counts from the lack of
1909 fn
->blocks
[ENTRY_BLOCK
].num_pred
= ~(unsigned)0;
1911 if (fn
->blocks
[EXIT_BLOCK
].num_succ
)
1912 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1913 bbg_file_name
, fn
->name
);
1915 /* Likewise, we can't deduce exit block counts from the lack
1916 of its successors. */
1917 fn
->blocks
[EXIT_BLOCK
].num_succ
= ~(unsigned)0;
1920 /* Propagate the measured counts, this must be done in the same
1921 order as the code in profile.c */
1922 for (unsigned i
= 0; i
< fn
->blocks
.size (); i
++)
1924 blk
= &fn
->blocks
[i
];
1925 block_info
const *prev_dst
= NULL
;
1926 int out_of_order
= 0;
1927 int non_fake_succ
= 0;
1929 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1937 arc
->count
= *count_ptr
++;
1938 arc
->count_valid
= 1;
1940 arc
->dst
->num_pred
--;
1942 if (prev_dst
&& prev_dst
> arc
->dst
)
1944 prev_dst
= arc
->dst
;
1946 if (non_fake_succ
== 1)
1948 /* If there is only one non-fake exit, it is an
1949 unconditional branch. */
1950 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1953 arc
->is_unconditional
= 1;
1954 /* If this block is instrumenting a call, it might be
1955 an artificial block. It is not artificial if it has
1956 a non-fallthrough exit, or the destination of this
1957 arc has more than one entry. Mark the destination
1958 block as a return site, if none of those conditions
1960 if (blk
->is_call_site
&& arc
->fall_through
1961 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1962 arc
->dst
->is_call_return
= 1;
1966 /* Sort the successor arcs into ascending dst order. profile.c
1967 normally produces arcs in the right order, but sometimes with
1968 one or two out of order. We're not using a particularly
1972 arc_info
*start
= blk
->succ
;
1973 unsigned changes
= 1;
1977 arc_info
*arc
, *arc_p
, *arc_n
;
1980 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1982 if (arc
->dst
> arc_n
->dst
)
1986 arc_p
->succ_next
= arc_n
;
1989 arc
->succ_next
= arc_n
->succ_next
;
1990 arc_n
->succ_next
= arc
;
2003 /* Place it on the invalid chain, it will be ignored if that's
2005 blk
->invalid_chain
= 1;
2006 blk
->chain
= invalid_blocks
;
2007 invalid_blocks
= blk
;
2010 while (invalid_blocks
|| valid_blocks
)
2012 while ((blk
= invalid_blocks
))
2014 gcov_type total
= 0;
2015 const arc_info
*arc
;
2017 invalid_blocks
= blk
->chain
;
2018 blk
->invalid_chain
= 0;
2020 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
2021 total
+= arc
->count
;
2022 else if (!blk
->num_pred
)
2023 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
2024 total
+= arc
->count
;
2029 blk
->count_valid
= 1;
2030 blk
->chain
= valid_blocks
;
2031 blk
->valid_chain
= 1;
2034 while ((blk
= valid_blocks
))
2037 arc_info
*arc
, *inv_arc
;
2039 valid_blocks
= blk
->chain
;
2040 blk
->valid_chain
= 0;
2041 if (blk
->num_succ
== 1)
2047 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
2049 total
-= arc
->count
;
2050 if (!arc
->count_valid
)
2054 inv_arc
->count_valid
= 1;
2055 inv_arc
->count
= total
;
2058 if (dst
->count_valid
)
2060 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
2062 dst
->chain
= valid_blocks
;
2063 dst
->valid_chain
= 1;
2069 if (!dst
->num_pred
&& !dst
->invalid_chain
)
2071 dst
->chain
= invalid_blocks
;
2072 dst
->invalid_chain
= 1;
2073 invalid_blocks
= dst
;
2077 if (blk
->num_pred
== 1)
2083 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
2085 total
-= arc
->count
;
2086 if (!arc
->count_valid
)
2090 inv_arc
->count_valid
= 1;
2091 inv_arc
->count
= total
;
2094 if (src
->count_valid
)
2096 if (src
->num_succ
== 1 && !src
->valid_chain
)
2098 src
->chain
= valid_blocks
;
2099 src
->valid_chain
= 1;
2105 if (!src
->num_succ
&& !src
->invalid_chain
)
2107 src
->chain
= invalid_blocks
;
2108 src
->invalid_chain
= 1;
2109 invalid_blocks
= src
;
2116 /* If the graph has been correctly solved, every block will have a
2118 for (unsigned i
= 0; ix
< fn
->blocks
.size (); i
++)
2119 if (!fn
->blocks
[i
].count_valid
)
2121 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
2122 bbg_file_name
, fn
->name
);
2127 /* Mark all the blocks only reachable via an incoming catch. */
2130 find_exception_blocks (function_info
*fn
)
2133 block_info
**queue
= XALLOCAVEC (block_info
*, fn
->blocks
.size ());
2135 /* First mark all blocks as exceptional. */
2136 for (ix
= fn
->blocks
.size (); ix
--;)
2137 fn
->blocks
[ix
].exceptional
= 1;
2139 /* Now mark all the blocks reachable via non-fake edges */
2140 queue
[0] = &fn
->blocks
[0];
2141 queue
[0]->exceptional
= 0;
2144 block_info
*block
= queue
[--ix
];
2145 const arc_info
*arc
;
2147 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2148 if (!arc
->fake
&& !arc
->is_throw
&& arc
->dst
->exceptional
)
2150 arc
->dst
->exceptional
= 0;
2151 queue
[ix
++] = arc
->dst
;
2157 /* Increment totals in COVERAGE according to arc ARC. */
2160 add_branch_counts (coverage_info
*coverage
, const arc_info
*arc
)
2162 if (arc
->is_call_non_return
)
2165 if (arc
->src
->count
)
2166 coverage
->calls_executed
++;
2168 else if (!arc
->is_unconditional
)
2170 coverage
->branches
++;
2171 if (arc
->src
->count
)
2172 coverage
->branches_executed
++;
2174 coverage
->branches_taken
++;
2178 /* Format COUNT, if flag_human_readable_numbers is set, return it human
2182 format_count (gcov_type count
)
2184 static char buffer
[64];
2185 const char *units
= " kMGTPEZY";
2187 if (count
< 1000 || !flag_human_readable_numbers
)
2189 sprintf (buffer
, "%" PRId64
, count
);
2194 gcov_type divisor
= 1;
2195 for (i
= 0; units
[i
+1]; i
++, divisor
*= 1000)
2197 if (count
+ divisor
/ 2 < 1000 * divisor
)
2200 gcov_type r
= (count
+ divisor
/ 2) / divisor
;
2201 sprintf (buffer
, "%" PRId64
"%c", r
, units
[i
]);
2205 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
2206 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
2207 If DP is zero, no decimal point is printed. Only print 100% when
2208 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
2209 format TOP. Return pointer to a static string. */
2212 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
2214 static char buffer
[20];
2216 /* Handle invalid values that would result in a misleading value. */
2217 if (bottom
!= 0 && top
> bottom
&& dp
>= 0)
2219 sprintf (buffer
, "NAN %%");
2225 float ratio
= bottom
? (float)top
/ bottom
: 0;
2227 unsigned limit
= 100;
2230 for (ix
= dp
; ix
--; )
2233 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
2234 if (percent
<= 0 && top
)
2236 else if (percent
>= limit
&& top
!= bottom
)
2237 percent
= limit
- 1;
2238 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
2244 buffer
[ix
+1] = buffer
[ix
];
2248 buffer
[ix
+ 1] = '.';
2252 return format_count (top
);
2257 /* Summary of execution */
2260 executed_summary (unsigned lines
, unsigned executed
)
2263 fnotice (stdout
, "Lines executed:%s of %d\n",
2264 format_gcov (executed
, lines
, 2), lines
);
2266 fnotice (stdout
, "No executable lines\n");
2269 /* Output summary info for a function or file. */
2272 function_summary (const coverage_info
*coverage
, const char *title
)
2274 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
2275 executed_summary (coverage
->lines
, coverage
->lines_executed
);
2279 if (coverage
->branches
)
2281 fnotice (stdout
, "Branches executed:%s of %d\n",
2282 format_gcov (coverage
->branches_executed
,
2283 coverage
->branches
, 2),
2284 coverage
->branches
);
2285 fnotice (stdout
, "Taken at least once:%s of %d\n",
2286 format_gcov (coverage
->branches_taken
,
2287 coverage
->branches
, 2),
2288 coverage
->branches
);
2291 fnotice (stdout
, "No branches\n");
2292 if (coverage
->calls
)
2293 fnotice (stdout
, "Calls executed:%s of %d\n",
2294 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
2297 fnotice (stdout
, "No calls\n");
2301 /* Canonicalize the filename NAME by canonicalizing directory
2302 separators, eliding . components and resolving .. components
2303 appropriately. Always returns a unique string. */
2306 canonicalize_name (const char *name
)
2308 /* The canonical name cannot be longer than the incoming name. */
2309 char *result
= XNEWVEC (char, strlen (name
) + 1);
2310 const char *base
= name
, *probe
;
2315 #if HAVE_DOS_BASED_FILE_SYSTEM
2316 if (base
[0] && base
[1] == ':')
2318 result
[0] = base
[0];
2324 for (dd_base
= ptr
; *base
; base
= probe
)
2328 for (probe
= base
; *probe
; probe
++)
2329 if (IS_DIR_SEPARATOR (*probe
))
2333 if (len
== 1 && base
[0] == '.')
2334 /* Elide a '.' directory */
2336 else if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2338 /* '..', we can only elide it and the previous directory, if
2339 we're not a symlink. */
2340 struct stat ATTRIBUTE_UNUSED buf
;
2344 #if defined (S_ISLNK)
2345 /* S_ISLNK is not POSIX.1-1996. */
2346 || stat (result
, &buf
) || S_ISLNK (buf
.st_mode
)
2350 /* Cannot elide, or unreadable or a symlink. */
2351 dd_base
= ptr
+ 2 + slash
;
2354 while (ptr
!= dd_base
&& *ptr
!= '/')
2356 slash
= ptr
!= result
;
2361 /* Regular pathname component. */
2364 memcpy (ptr
, base
, len
);
2369 for (; IS_DIR_SEPARATOR (*probe
); probe
++)
2377 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2380 md5sum_to_hex (const char *sum
, char *buffer
)
2382 for (unsigned i
= 0; i
< 16; i
++)
2383 sprintf (buffer
+ (2 * i
), "%02x", (unsigned char)sum
[i
]);
2386 /* Generate an output file name. INPUT_NAME is the canonicalized main
2387 input file and SRC_NAME is the canonicalized file name.
2388 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2389 long_output_names we prepend the processed name of the input file
2390 to each output name (except when the current source file is the
2391 input file, so you don't get a double concatenation). The two
2392 components are separated by '##'. With preserve_paths we create a
2393 filename from all path components of the source file, replacing '/'
2394 with '#', and .. with '^', without it we simply take the basename
2395 component. (Remember, the canonicalized name will already have
2396 elided '.' components and converted \\ separators.) */
2399 make_gcov_file_name (const char *input_name
, const char *src_name
)
2404 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
2406 /* Generate the input filename part. */
2407 result
= XNEWVEC (char, strlen (input_name
) + strlen (src_name
) + 10);
2410 ptr
= mangle_name (input_name
, ptr
);
2411 ptr
[0] = ptr
[1] = '#';
2416 result
= XNEWVEC (char, strlen (src_name
) + 10);
2420 ptr
= mangle_name (src_name
, ptr
);
2421 strcpy (ptr
, ".gcov");
2423 /* When hashing filenames, we shorten them by only using the filename
2424 component and appending a hash of the full (mangled) pathname. */
2425 if (flag_hash_filenames
)
2429 char md5sum_hex
[33];
2431 md5_init_ctx (&ctx
);
2432 md5_process_bytes (src_name
, strlen (src_name
), &ctx
);
2433 md5_finish_ctx (&ctx
, md5sum
);
2434 md5sum_to_hex (md5sum
, md5sum_hex
);
2437 result
= XNEWVEC (char, strlen (src_name
) + 50);
2439 ptr
= mangle_name (src_name
, ptr
);
2440 ptr
[0] = ptr
[1] = '#';
2442 memcpy (ptr
, md5sum_hex
, 32);
2444 strcpy (ptr
, ".gcov");
2451 mangle_name (char const *base
, char *ptr
)
2455 /* Generate the source filename part. */
2456 if (!flag_preserve_paths
)
2458 base
= lbasename (base
);
2459 len
= strlen (base
);
2460 memcpy (ptr
, base
, len
);
2465 /* Convert '/' to '#', convert '..' to '^',
2466 convert ':' to '~' on DOS based file system. */
2469 #if HAVE_DOS_BASED_FILE_SYSTEM
2470 if (base
[0] && base
[1] == ':')
2478 for (; *base
; base
= probe
)
2482 for (probe
= base
; *probe
; probe
++)
2486 if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2490 memcpy (ptr
, base
, len
);
2504 /* Scan through the bb_data for each line in the block, increment
2505 the line number execution count indicated by the execution count of
2506 the appropriate basic block. */
2509 add_line_counts (coverage_info
*coverage
, function_info
*fn
)
2511 bool has_any_line
= false;
2512 /* Scan each basic block. */
2513 for (unsigned ix
= 0; ix
!= fn
->blocks
.size (); ix
++)
2515 line_info
*line
= NULL
;
2516 block_info
*block
= &fn
->blocks
[ix
];
2517 if (block
->count
&& ix
&& ix
+ 1 != fn
->blocks
.size ())
2518 fn
->blocks_executed
++;
2519 for (unsigned i
= 0; i
< block
->locations
.size (); i
++)
2521 unsigned src_idx
= block
->locations
[i
].source_file_idx
;
2522 vector
<unsigned> &lines
= block
->locations
[i
].lines
;
2524 block
->cycle
.arc
= NULL
;
2525 block
->cycle
.ident
= ~0U;
2527 for (unsigned j
= 0; j
< lines
.size (); j
++)
2529 unsigned ln
= lines
[j
];
2531 /* Line belongs to a function that is in a group. */
2532 if (fn
->group_line_p (ln
, src_idx
))
2534 gcc_assert (lines
[j
] - fn
->start_line
< fn
->lines
.size ());
2535 line
= &(fn
->lines
[lines
[j
] - fn
->start_line
]);
2537 if (!block
->exceptional
)
2539 line
->unexceptional
= 1;
2540 if (block
->count
== 0)
2541 line
->has_unexecuted_block
= 1;
2543 line
->count
+= block
->count
;
2547 gcc_assert (ln
< sources
[src_idx
].lines
.size ());
2548 line
= &(sources
[src_idx
].lines
[ln
]);
2553 if (!line
->count
&& block
->count
)
2554 coverage
->lines_executed
++;
2557 if (!block
->exceptional
)
2559 line
->unexceptional
= 1;
2560 if (block
->count
== 0)
2561 line
->has_unexecuted_block
= 1;
2563 line
->count
+= block
->count
;
2567 has_any_line
= true;
2569 if (!ix
|| ix
+ 1 == fn
->blocks
.size ())
2570 /* Entry or exit block. */;
2571 else if (line
!= NULL
)
2573 line
->blocks
.push_back (block
);
2579 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2580 line
->branches
.push_back (arc
);
2587 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
2590 /* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE
2591 is set to true, update source file summary. */
2593 static void accumulate_line_info (line_info
*line
, source_info
*src
,
2597 for (vector
<arc_info
*>::iterator it
= line
->branches
.begin ();
2598 it
!= line
->branches
.end (); it
++)
2599 add_branch_counts (&src
->coverage
, *it
);
2601 if (!line
->blocks
.empty ())
2603 /* The user expects the line count to be the number of times
2604 a line has been executed. Simply summing the block count
2605 will give an artificially high number. The Right Thing
2606 is to sum the entry counts to the graph of blocks on this
2607 line, then find the elementary cycles of the local graph
2608 and add the transition counts of those cycles. */
2609 gcov_type count
= 0;
2611 /* Cycle detection. */
2612 for (vector
<block_info
*>::iterator it
= line
->blocks
.begin ();
2613 it
!= line
->blocks
.end (); it
++)
2615 for (arc_info
*arc
= (*it
)->pred
; arc
; arc
= arc
->pred_next
)
2616 if (!line
->has_block (arc
->src
))
2617 count
+= arc
->count
;
2618 for (arc_info
*arc
= (*it
)->succ
; arc
; arc
= arc
->succ_next
)
2619 arc
->cs_count
= arc
->count
;
2622 /* Now, add the count of loops entirely on this line. */
2623 count
+= get_cycles_count (*line
);
2624 line
->count
= count
;
2627 if (line
->exists
&& add_coverage
)
2629 src
->coverage
.lines
++;
2631 src
->coverage
.lines_executed
++;
2635 /* Accumulate the line counts of a file. */
2638 accumulate_line_counts (source_info
*src
)
2640 /* First work on group functions. */
2641 for (vector
<function_info
*>::iterator it
= src
->functions
.begin ();
2642 it
!= src
->functions
.end (); it
++)
2644 function_info
*fn
= *it
;
2646 if (fn
->src
!= src
->index
|| !fn
->is_group
)
2649 for (vector
<line_info
>::iterator it2
= fn
->lines
.begin ();
2650 it2
!= fn
->lines
.end (); it2
++)
2652 line_info
*line
= &(*it2
);
2653 accumulate_line_info (line
, src
, false);
2657 /* Work on global lines that line in source file SRC. */
2658 for (vector
<line_info
>::iterator it
= src
->lines
.begin ();
2659 it
!= src
->lines
.end (); it
++)
2660 accumulate_line_info (&(*it
), src
, true);
2662 /* If not using intermediate mode, sum lines of group functions and
2663 add them to lines that live in a source file. */
2664 if (!flag_intermediate_format
)
2665 for (vector
<function_info
*>::iterator it
= src
->functions
.begin ();
2666 it
!= src
->functions
.end (); it
++)
2668 function_info
*fn
= *it
;
2670 if (fn
->src
!= src
->index
|| !fn
->is_group
)
2673 for (unsigned i
= 0; i
< fn
->lines
.size (); i
++)
2675 line_info
*fn_line
= &fn
->lines
[i
];
2676 if (fn_line
->exists
)
2678 unsigned ln
= fn
->start_line
+ i
;
2679 line_info
*src_line
= &src
->lines
[ln
];
2681 if (!src_line
->exists
)
2682 src
->coverage
.lines
++;
2683 if (!src_line
->count
&& fn_line
->count
)
2684 src
->coverage
.lines_executed
++;
2686 src_line
->count
+= fn_line
->count
;
2687 src_line
->exists
= 1;
2689 if (fn_line
->has_unexecuted_block
)
2690 src_line
->has_unexecuted_block
= 1;
2692 if (fn_line
->unexceptional
)
2693 src_line
->unexceptional
= 1;
2699 /* Output information about ARC number IX. Returns nonzero if
2700 anything is output. */
2703 output_branch_count (FILE *gcov_file
, int ix
, const arc_info
*arc
)
2705 if (arc
->is_call_non_return
)
2707 if (arc
->src
->count
)
2709 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
2710 format_gcov (arc
->src
->count
- arc
->count
,
2711 arc
->src
->count
, -flag_counts
));
2714 fnotice (gcov_file
, "call %2d never executed\n", ix
);
2716 else if (!arc
->is_unconditional
)
2718 if (arc
->src
->count
)
2719 fnotice (gcov_file
, "branch %2d taken %s%s", ix
,
2720 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
2721 arc
->fall_through
? " (fallthrough)"
2722 : arc
->is_throw
? " (throw)" : "");
2724 fnotice (gcov_file
, "branch %2d never executed", ix
);
2727 fnotice (gcov_file
, " (BB %d)", arc
->dst
->id
);
2729 fnotice (gcov_file
, "\n");
2731 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
2733 if (arc
->src
->count
)
2734 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
2735 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
2737 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
2745 read_line (FILE *file
)
2747 static char *string
;
2748 static size_t string_len
;
2755 string
= XNEWVEC (char, string_len
);
2758 while ((ptr
= fgets (string
+ pos
, string_len
- pos
, file
)))
2760 size_t len
= strlen (string
+ pos
);
2762 if (len
&& string
[pos
+ len
- 1] == '\n')
2764 string
[pos
+ len
- 1] = 0;
2768 /* If the file contains NUL characters or an incomplete
2769 last line, which can happen more than once in one run,
2770 we have to avoid doubling the STRING_LEN unnecessarily. */
2771 if (pos
> string_len
/ 2)
2774 string
= XRESIZEVEC (char, string
, string_len
);
2778 return pos
? string
: NULL
;
2781 /* Pad string S with spaces from left to have total width equal to 9. */
2784 pad_count_string (string
&s
)
2787 s
.insert (0, 9 - s
.size (), ' ');
2790 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2791 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2792 an exceptional statement. The output is printed for LINE_NUM of given
2793 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2794 used to indicate non-executed blocks. */
2797 output_line_beginning (FILE *f
, bool exists
, bool unexceptional
,
2798 bool has_unexecuted_block
,
2799 gcov_type count
, unsigned line_num
,
2800 const char *exceptional_string
,
2801 const char *unexceptional_string
)
2808 s
= format_gcov (count
, 0, -1);
2809 if (has_unexecuted_block
2810 && bbg_supports_has_unexecuted_blocks
)
2812 if (flag_use_colors
)
2814 pad_count_string (s
);
2815 s
.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
2816 COLOR_SEPARATOR COLOR_FG_WHITE
));
2822 pad_count_string (s
);
2826 if (flag_use_colors
)
2829 pad_count_string (s
);
2831 s
.insert (0, SGR_SEQ (COLOR_BG_RED
2832 COLOR_SEPARATOR COLOR_FG_WHITE
));
2834 s
.insert (0, SGR_SEQ (COLOR_BG_CYAN
2835 COLOR_SEPARATOR COLOR_FG_WHITE
));
2840 s
= unexceptional
? unexceptional_string
: exceptional_string
;
2841 pad_count_string (s
);
2848 pad_count_string (s
);
2851 fprintf (f
, "%s:%5u", s
.c_str (), line_num
);
2855 print_source_line (FILE *f
, const vector
<const char *> &source_lines
,
2858 gcc_assert (line
>= 1);
2859 gcc_assert (line
<= source_lines
.size ());
2861 fprintf (f
, ":%s\n", source_lines
[line
- 1]);
2864 /* Output line details for LINE and print it to F file. LINE lives on
2868 output_line_details (FILE *f
, const line_info
*line
, unsigned line_num
)
2870 if (flag_all_blocks
)
2876 for (vector
<block_info
*>::const_iterator it
= line
->blocks
.begin ();
2877 it
!= line
->blocks
.end (); it
++)
2879 if (!(*it
)->is_call_return
)
2881 output_line_beginning (f
, line
->exists
,
2882 (*it
)->exceptional
, false,
2883 (*it
)->count
, line_num
,
2885 fprintf (f
, "-block %2d", ix
++);
2887 fprintf (f
, " (BB %u)", (*it
)->id
);
2891 for (arc
= (*it
)->succ
; arc
; arc
= arc
->succ_next
)
2892 jx
+= output_branch_count (f
, jx
, arc
);
2895 else if (flag_branches
)
2900 for (vector
<arc_info
*>::const_iterator it
= line
->branches
.begin ();
2901 it
!= line
->branches
.end (); it
++)
2902 ix
+= output_branch_count (f
, ix
, (*it
));
2906 /* Output detail statistics about function FN to file F. */
2909 output_function_details (FILE *f
, const function_info
*fn
)
2914 arc_info
*arc
= fn
->blocks
[EXIT_BLOCK
].pred
;
2915 gcov_type return_count
= fn
->blocks
[EXIT_BLOCK
].count
;
2916 gcov_type called_count
= fn
->blocks
[ENTRY_BLOCK
].count
;
2918 for (; arc
; arc
= arc
->pred_next
)
2920 return_count
-= arc
->count
;
2922 fprintf (f
, "function %s",
2923 flag_demangled_names
? fn
->demangled_name
: fn
->name
);
2924 fprintf (f
, " called %s",
2925 format_gcov (called_count
, 0, -1));
2926 fprintf (f
, " returned %s",
2927 format_gcov (return_count
, called_count
, 0));
2928 fprintf (f
, " blocks executed %s",
2929 format_gcov (fn
->blocks_executed
, fn
->blocks
.size () - 2,
2934 /* Read in the source file one line at a time, and output that line to
2935 the gcov file preceded by its execution count and other
2939 output_lines (FILE *gcov_file
, const source_info
*src
)
2941 #define DEFAULT_LINE_START " -: 0:"
2942 #define FN_SEPARATOR "------------------\n"
2947 fprintf (gcov_file
, DEFAULT_LINE_START
"Source:%s\n", src
->coverage
.name
);
2948 if (!multiple_files
)
2950 fprintf (gcov_file
, DEFAULT_LINE_START
"Graph:%s\n", bbg_file_name
);
2951 fprintf (gcov_file
, DEFAULT_LINE_START
"Data:%s\n",
2952 no_data_file
? "-" : da_file_name
);
2953 fprintf (gcov_file
, DEFAULT_LINE_START
"Runs:%u\n", object_runs
);
2955 fprintf (gcov_file
, DEFAULT_LINE_START
"Programs:%u\n", program_count
);
2957 source_file
= fopen (src
->name
, "r");
2959 fnotice (stderr
, "Cannot open source file %s\n", src
->name
);
2960 else if (src
->file_time
== 0)
2961 fprintf (gcov_file
, DEFAULT_LINE_START
"Source is newer than graph\n");
2963 vector
<const char *> source_lines
;
2965 while ((retval
= read_line (source_file
)) != NULL
)
2966 source_lines
.push_back (xstrdup (retval
));
2968 unsigned line_start_group
= 0;
2969 vector
<function_info
*> fns
;
2971 for (unsigned line_num
= 1; line_num
<= source_lines
.size (); line_num
++)
2973 if (line_num
>= src
->lines
.size ())
2975 fprintf (gcov_file
, "%9s:%5u", "-", line_num
);
2976 print_source_line (gcov_file
, source_lines
, line_num
);
2980 const line_info
*line
= &src
->lines
[line_num
];
2982 if (line_start_group
== 0)
2984 fns
= src
->get_functions_at_location (line_num
);
2985 if (fns
.size () > 1)
2987 /* It's possible to have functions that partially overlap,
2988 thus take the maximum end_line of functions starting
2990 for (unsigned i
= 0; i
< fns
.size (); i
++)
2991 if (fns
[i
]->end_line
> line_start_group
)
2992 line_start_group
= fns
[i
]->end_line
;
2994 else if (fns
.size () == 1)
2996 function_info
*fn
= fns
[0];
2997 output_function_details (gcov_file
, fn
);
3001 /* For lines which don't exist in the .bb file, print '-' before
3002 the source line. For lines which exist but were never
3003 executed, print '#####' or '=====' before the source line.
3004 Otherwise, print the execution count before the source line.
3005 There are 16 spaces of indentation added before the source
3006 line so that tabs won't be messed up. */
3007 output_line_beginning (gcov_file
, line
->exists
, line
->unexceptional
,
3008 line
->has_unexecuted_block
, line
->count
,
3009 line_num
, "=====", "#####");
3011 print_source_line (gcov_file
, source_lines
, line_num
);
3012 output_line_details (gcov_file
, line
, line_num
);
3014 if (line_start_group
== line_num
)
3016 for (vector
<function_info
*>::iterator it
= fns
.begin ();
3017 it
!= fns
.end (); it
++)
3019 function_info
*fn
= *it
;
3020 vector
<line_info
> &lines
= fn
->lines
;
3022 fprintf (gcov_file
, FN_SEPARATOR
);
3025 = flag_demangled_names
? fn
->demangled_name
: fn
->name
;
3027 if (flag_use_colors
)
3029 fn_name
.insert (0, SGR_SEQ (COLOR_FG_CYAN
));
3030 fn_name
+= SGR_RESET
;
3033 fprintf (gcov_file
, "%s:\n", fn_name
.c_str ());
3035 output_function_details (gcov_file
, fn
);
3037 /* Print all lines covered by the function. */
3038 for (unsigned i
= 0; i
< lines
.size (); i
++)
3040 line_info
*line
= &lines
[i
];
3041 unsigned l
= fn
->start_line
+ i
;
3043 /* For lines which don't exist in the .bb file, print '-'
3044 before the source line. For lines which exist but
3045 were never executed, print '#####' or '=====' before
3046 the source line. Otherwise, print the execution count
3047 before the source line.
3048 There are 16 spaces of indentation added before the source
3049 line so that tabs won't be messed up. */
3050 output_line_beginning (gcov_file
, line
->exists
,
3051 line
->unexceptional
,
3052 line
->has_unexecuted_block
,
3054 l
, "=====", "#####");
3056 print_source_line (gcov_file
, source_lines
, l
);
3057 output_line_details (gcov_file
, line
, l
);
3061 fprintf (gcov_file
, FN_SEPARATOR
);
3062 line_start_group
= 0;
3067 fclose (source_file
);