1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990-2017 Free Software Foundation, Inc.
4 Contributed by James E. Wilson of Cygnus Support.
5 Mangled by Bob Manson of Cygnus Support.
6 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
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
38 #include "coretypes.h"
41 #include "diagnostic.h"
44 #include "color-macros.h"
56 /* The gcno file is generated by -ftest-coverage option. The gcda file is
57 generated by a program compiled with -fprofile-arcs. Their formats
58 are documented in gcov-io.h. */
60 /* The functions in this file for creating and solution program flow graphs
61 are very similar to functions in the gcc source file profile.c. In
62 some places we make use of the knowledge of how profile.c works to
63 select particular algorithms here. */
65 /* The code validates that the profile information read in corresponds
66 to the code currently being compiled. Rather than checking for
67 identical files, the code below compares a checksum on the CFG
68 (based on the order of basic blocks and the arcs in the CFG). If
69 the CFG checksum in the gcda file match the CFG checksum in the
70 gcno file, the profile data will be used. */
72 /* This is the size of the buffer used to read in source file lines. */
78 /* Describes an arc between two basic blocks. */
80 typedef struct arc_info
82 /* source and destination blocks. */
83 struct block_info
*src
;
84 struct block_info
*dst
;
86 /* transition counts. */
88 /* used in cycle search, so that we do not clobber original counts. */
91 unsigned int count_valid
: 1;
92 unsigned int on_tree
: 1;
93 unsigned int fake
: 1;
94 unsigned int fall_through
: 1;
96 /* Arc to a catch handler. */
97 unsigned int is_throw
: 1;
99 /* Arc is for a function that abnormally returns. */
100 unsigned int is_call_non_return
: 1;
102 /* Arc is for catch/setjmp. */
103 unsigned int is_nonlocal_return
: 1;
105 /* Is an unconditional branch. */
106 unsigned int is_unconditional
: 1;
108 /* Loop making arc. */
109 unsigned int cycle
: 1;
111 /* Next branch on line. */
112 struct arc_info
*line_next
;
114 /* Links to next arc on src and dst lists. */
115 struct arc_info
*succ_next
;
116 struct arc_info
*pred_next
;
119 /* Describes which locations (lines and files) are associated with
122 struct block_location_info
124 block_location_info (unsigned _source_file_idx
):
125 source_file_idx (_source_file_idx
)
128 unsigned source_file_idx
;
129 vector
<unsigned> lines
;
132 /* Describes a basic block. Contains lists of arcs to successor and
133 predecessor blocks. */
135 typedef struct block_info
140 /* Chain of exit and entry arcs. */
144 /* Number of unprocessed exit and entry arcs. */
150 /* Block execution count. */
152 unsigned count_valid
: 1;
153 unsigned valid_chain
: 1;
154 unsigned invalid_chain
: 1;
155 unsigned exceptional
: 1;
157 /* Block is a call instrumenting site. */
158 unsigned is_call_site
: 1; /* Does the call. */
159 unsigned is_call_return
: 1; /* Is the return. */
161 /* Block is a landing pad for longjmp or throw. */
162 unsigned is_nonlocal_return
: 1;
164 vector
<block_location_info
> locations
;
168 /* Single line graph cycle workspace. Used for all-blocks
172 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
175 /* Temporary chain for solving graph, and for chaining blocks on one
177 struct block_info
*chain
;
181 block_info::block_info (): succ (NULL
), pred (NULL
), num_succ (0), num_pred (0),
182 id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
183 exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
184 locations (), chain (NULL
)
189 /* Describes a single function. Contains an array of basic blocks. */
191 typedef struct function_info
196 /* Name of function. */
198 char *demangled_name
;
200 unsigned lineno_checksum
;
201 unsigned cfg_checksum
;
203 /* The graph contains at least one fake incoming edge. */
204 unsigned has_catch
: 1;
206 /* Array of basic blocks. Like in GCC, the entry block is
207 at blocks[0] and the exit block is at blocks[1]. */
208 #define ENTRY_BLOCK (0)
209 #define EXIT_BLOCK (1)
210 vector
<block_t
> blocks
;
211 unsigned blocks_executed
;
213 /* Raw arc coverage counts. */
217 /* First line number & file. */
221 /* Next function in same source file. */
222 struct function_info
*next_file_fn
;
225 struct function_info
*next
;
228 /* Describes coverage of a file or function. */
230 typedef struct coverage_info
236 int branches_executed
;
245 /* Describes a single line of source. Contains a chain of basic blocks
248 typedef struct line_info
250 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
251 bool has_block (block_t
*needle
);
253 gcov_type count
; /* execution count */
254 arc_t
*branches
; /* branches from blocks that end on this line. */
255 block_t
*blocks
; /* blocks which start on this line.
256 Used in all-blocks mode. */
258 unsigned unexceptional
: 1;
259 unsigned has_unexecuted_block
: 1;
263 line_t::has_block (block_t
*needle
)
265 for (block_t
*n
= blocks
; n
; n
= n
->chain
)
272 /* Describes a file mentioned in the block graph. Contains an array
275 typedef struct source_info
277 /* Canonical name of source file. */
281 /* Array of line information. */
287 /* Functions in this source file. These are in ascending line
289 function_t
*functions
;
292 typedef struct name_map
294 char *name
; /* Source file name */
295 unsigned src
; /* Source file */
298 /* Holds a list of function basic block graphs. */
300 static function_t
*functions
;
301 static function_t
**fn_end
= &functions
;
303 static source_t
*sources
; /* Array of source files */
304 static unsigned n_sources
; /* Number of sources */
305 static unsigned a_sources
; /* Allocated sources */
307 static name_map_t
*names
; /* Mapping of file names to sources */
308 static unsigned n_names
; /* Number of names */
309 static unsigned a_names
; /* Allocated names */
311 /* This holds data summary information. */
313 static unsigned object_runs
;
314 static unsigned program_count
;
316 static unsigned total_lines
;
317 static unsigned total_executed
;
319 /* Modification time of graph file. */
321 static time_t bbg_file_time
;
323 /* Name of the notes (gcno) output file. The "bbg" prefix is for
324 historical reasons, when the notes file contained only the
325 basic block graph notes. */
327 static char *bbg_file_name
;
329 /* Stamp of the bbg file */
330 static unsigned bbg_stamp
;
332 /* Name and file pointer of the input file for the count data (gcda). */
334 static char *da_file_name
;
336 /* Data file is missing. */
338 static int no_data_file
;
340 /* If there is several input files, compute and display results after
341 reading all data files. This way if two or more gcda file refer to
342 the same source file (eg inline subprograms in a .h file), the
345 static int multiple_files
= 0;
347 /* Output branch probabilities. */
349 static int flag_branches
= 0;
351 /* Show unconditional branches too. */
352 static int flag_unconditional
= 0;
354 /* Output a gcov file if this is true. This is on by default, and can
355 be turned off by the -n option. */
357 static int flag_gcov_file
= 1;
359 /* Output progress indication if this is true. This is off by default
360 and can be turned on by the -d option. */
362 static int flag_display_progress
= 0;
364 /* Output *.gcov file in intermediate format used by 'lcov'. */
366 static int flag_intermediate_format
= 0;
368 /* Output demangled function names. */
370 static int flag_demangled_names
= 0;
372 /* For included files, make the gcov output file name include the name
373 of the input source file. For example, if x.h is included in a.c,
374 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
376 static int flag_long_names
= 0;
378 /* For situations when a long name can potentially hit filesystem path limit,
379 let's calculate md5sum of the path and append it to a file name. */
381 static int flag_hash_filenames
= 0;
383 /* Print verbose informations. */
385 static int flag_verbose
= 0;
387 /* Print colored output. */
389 static int flag_use_colors
= 0;
391 /* Output count information for every basic block, not merely those
392 that contain line number information. */
394 static int flag_all_blocks
= 0;
396 /* Output summary info for each function. */
398 static int flag_function_summary
= 0;
400 /* Object directory file prefix. This is the directory/file where the
401 graph and data files are looked for, if nonzero. */
403 static char *object_directory
= 0;
405 /* Source directory prefix. This is removed from source pathnames
406 that match, when generating the output file name. */
408 static char *source_prefix
= 0;
409 static size_t source_length
= 0;
411 /* Only show data for sources with relative pathnames. Absolute ones
412 usually indicate a system header file, which although it may
413 contain inline functions, is usually uninteresting. */
414 static int flag_relative_only
= 0;
416 /* Preserve all pathname components. Needed when object files and
417 source files are in subdirectories. '/' is mangled as '#', '.' is
418 elided and '..' mangled to '^'. */
420 static int flag_preserve_paths
= 0;
422 /* Output the number of times a branch was taken as opposed to the percentage
423 of times it was taken. */
425 static int flag_counts
= 0;
427 /* Forward declarations. */
428 static int process_args (int, char **);
429 static void print_usage (int) ATTRIBUTE_NORETURN
;
430 static void print_version (void) ATTRIBUTE_NORETURN
;
431 static void process_file (const char *);
432 static void generate_results (const char *);
433 static void create_file_names (const char *);
434 static int name_search (const void *, const void *);
435 static int name_sort (const void *, const void *);
436 static char *canonicalize_name (const char *);
437 static unsigned find_source (const char *);
438 static function_t
*read_graph_file (void);
439 static int read_count_file (function_t
*);
440 static void solve_flow_graph (function_t
*);
441 static void find_exception_blocks (function_t
*);
442 static void add_branch_counts (coverage_t
*, const arc_t
*);
443 static void add_line_counts (coverage_t
*, function_t
*);
444 static void executed_summary (unsigned, unsigned);
445 static void function_summary (const coverage_t
*, const char *);
446 static const char *format_gcov (gcov_type
, gcov_type
, int);
447 static void accumulate_line_counts (source_t
*);
448 static void output_gcov_file (const char *, source_t
*);
449 static int output_branch_count (FILE *, int, const arc_t
*);
450 static void output_lines (FILE *, const source_t
*);
451 static char *make_gcov_file_name (const char *, const char *);
452 static char *mangle_name (const char *, char *);
453 static void release_structures (void);
454 extern int main (int, char **);
456 function_info::function_info (): name (NULL
), demangled_name (NULL
),
457 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
458 blocks (), blocks_executed (0), counts (NULL
), num_counts (0),
459 line (0), src (0), next_file_fn (NULL
), next (NULL
)
463 function_info::~function_info ()
465 for (int i
= blocks
.size () - 1; i
>= 0; i
--)
469 for (arc
= blocks
[i
].succ
; arc
; arc
= arc_n
)
471 arc_n
= arc
->succ_next
;
476 if (flag_demangled_names
&& demangled_name
!= name
)
477 free (demangled_name
);
482 There are a bajillion algorithms that do this. Boost's function is named
483 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
484 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
485 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
487 The basic algorithm is simple: effectively, we're finding all simple paths
488 in a subgraph (that shrinks every iteration). Duplicates are filtered by
489 "blocking" a path when a node is added to the path (this also prevents non-
490 simple paths)--the node is unblocked only when it participates in a cycle.
493 typedef vector
<arc_t
*> arc_vector_t
;
494 typedef vector
<const block_t
*> block_vector_t
;
496 /* Enum with types of loop in CFG. */
505 /* Loop_type operator that merges two values: A and B. */
507 inline loop_type
& operator |= (loop_type
& a
, loop_type b
)
509 return a
= static_cast<loop_type
> (a
| b
);
512 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
513 and subtract the value from all counts. The subtracted value is added
514 to COUNT. Returns type of loop. */
517 handle_cycle (const arc_vector_t
&edges
, int64_t &count
)
519 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
521 int64_t cycle_count
= INTTYPE_MAXIMUM (int64_t);
522 for (unsigned i
= 0; i
< edges
.size (); i
++)
524 int64_t ecount
= edges
[i
]->cs_count
;
525 if (cycle_count
> ecount
)
526 cycle_count
= ecount
;
528 count
+= cycle_count
;
529 for (unsigned i
= 0; i
< edges
.size (); i
++)
530 edges
[i
]->cs_count
-= cycle_count
;
532 return cycle_count
< 0 ? NEGATIVE_LOOP
: LOOP
;
535 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
536 blocked by U in BLOCK_LISTS. */
539 unblock (const block_t
*u
, block_vector_t
&blocked
,
540 vector
<block_vector_t
> &block_lists
)
542 block_vector_t::iterator it
= find (blocked
.begin (), blocked
.end (), u
);
543 if (it
== blocked
.end ())
546 unsigned index
= it
- blocked
.begin ();
549 block_vector_t
to_unblock (block_lists
[index
]);
551 block_lists
.erase (block_lists
.begin () + index
);
553 for (block_vector_t::iterator it
= to_unblock
.begin ();
554 it
!= to_unblock
.end (); it
++)
555 unblock (*it
, blocked
, block_lists
);
558 /* Find circuit going to block V, PATH is provisional seen cycle.
559 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
560 blocked by a block. COUNT is accumulated count of the current LINE.
561 Returns what type of loop it contains. */
564 circuit (block_t
*v
, arc_vector_t
&path
, block_t
*start
,
565 block_vector_t
&blocked
, vector
<block_vector_t
> &block_lists
,
566 line_t
&linfo
, int64_t &count
)
568 loop_type result
= NO_LOOP
;
570 /* Add v to the block list. */
571 gcc_assert (find (blocked
.begin (), blocked
.end (), v
) == blocked
.end ());
572 blocked
.push_back (v
);
573 block_lists
.push_back (block_vector_t ());
575 for (arc_t
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
577 block_t
*w
= arc
->dst
;
578 if (w
< start
|| !linfo
.has_block (w
))
581 path
.push_back (arc
);
583 /* Cycle has been found. */
584 result
|= handle_cycle (path
, count
);
585 else if (find (blocked
.begin (), blocked
.end (), w
) == blocked
.end ())
586 result
|= circuit (w
, path
, start
, blocked
, block_lists
, linfo
, count
);
591 if (result
!= NO_LOOP
)
592 unblock (v
, blocked
, block_lists
);
594 for (arc_t
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
596 block_t
*w
= arc
->dst
;
597 if (w
< start
|| !linfo
.has_block (w
))
601 = find (blocked
.begin (), blocked
.end (), w
) - blocked
.begin ();
602 gcc_assert (index
< blocked
.size ());
603 block_vector_t
&list
= block_lists
[index
];
604 if (find (list
.begin (), list
.end (), v
) == list
.end ())
611 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
612 contains a negative loop, then perform the same function once again. */
615 get_cycles_count (line_t
&linfo
, bool handle_negative_cycles
= true)
617 /* Note that this algorithm works even if blocks aren't in sorted order.
618 Each iteration of the circuit detection is completely independent
619 (except for reducing counts, but that shouldn't matter anyways).
620 Therefore, operating on a permuted order (i.e., non-sorted) only
621 has the effect of permuting the output cycles. */
623 loop_type result
= NO_LOOP
;
625 for (block_t
*block
= linfo
.blocks
; block
; block
= block
->chain
)
628 block_vector_t blocked
;
629 vector
<block_vector_t
> block_lists
;
630 result
|= circuit (block
, path
, block
, blocked
, block_lists
, linfo
,
634 /* If we have a negative cycle, repeat the find_cycles routine. */
635 if (result
== NEGATIVE_LOOP
&& handle_negative_cycles
)
636 count
+= get_cycles_count (linfo
, false);
642 main (int argc
, char **argv
)
648 p
= argv
[0] + strlen (argv
[0]);
649 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
653 xmalloc_set_program_name (progname
);
655 /* Unlock the stdio streams. */
656 unlock_std_streams ();
660 diagnostic_initialize (global_dc
, 0);
662 /* Handle response files. */
663 expandargv (&argc
, &argv
);
666 names
= XNEWVEC (name_map_t
, a_names
);
668 sources
= XNEWVEC (source_t
, a_sources
);
670 argno
= process_args (argc
, argv
);
674 if (argc
- argno
> 1)
679 for (; argno
!= argc
; argno
++)
681 if (flag_display_progress
)
682 printf ("Processing file %d out of %d\n", argno
- first_arg
+ 1,
684 process_file (argv
[argno
]);
687 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
689 release_structures ();
694 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
695 otherwise the output of --help. */
698 print_usage (int error_p
)
700 FILE *file
= error_p
? stderr
: stdout
;
701 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
703 fnotice (file
, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
704 fnotice (file
, "Print code coverage information.\n\n");
705 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
706 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
707 fnotice (file
, " -c, --branch-counts Output counts of branches taken\n\
708 rather than percentages\n");
709 fnotice (file
, " -d, --display-progress Display progress information\n");
710 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
711 fnotice (file
, " -h, --help Print this help, then exit\n");
712 fnotice (file
, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
713 fnotice (file
, " -k, --use-colors Emit colored output\n");
714 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
716 fnotice (file
, " -m, --demangled-names Output demangled function names\n");
717 fnotice (file
, " -n, --no-output Do not create an output file\n");
718 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
719 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
720 fnotice (file
, " -r, --relative-only Only show data for relative sources\n");
721 fnotice (file
, " -s, --source-prefix DIR Source prefix to elide\n");
722 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
723 fnotice (file
, " -v, --version Print version number, then exit\n");
724 fnotice (file
, " -w, --verbose Print verbose informations\n");
725 fnotice (file
, " -x, --hash-filenames Hash long pathnames\n");
726 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
731 /* Print version information and exit. */
736 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
737 fprintf (stdout
, "Copyright %s 2017 Free Software Foundation, Inc.\n",
740 _("This is free software; see the source for copying conditions.\n"
741 "There is NO warranty; not even for MERCHANTABILITY or \n"
742 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
743 exit (SUCCESS_EXIT_CODE
);
746 static const struct option options
[] =
748 { "help", no_argument
, NULL
, 'h' },
749 { "version", no_argument
, NULL
, 'v' },
750 { "verbose", no_argument
, NULL
, 'w' },
751 { "all-blocks", no_argument
, NULL
, 'a' },
752 { "branch-probabilities", no_argument
, NULL
, 'b' },
753 { "branch-counts", no_argument
, NULL
, 'c' },
754 { "intermediate-format", no_argument
, NULL
, 'i' },
755 { "no-output", no_argument
, NULL
, 'n' },
756 { "long-file-names", no_argument
, NULL
, 'l' },
757 { "function-summaries", no_argument
, NULL
, 'f' },
758 { "demangled-names", no_argument
, NULL
, 'm' },
759 { "preserve-paths", no_argument
, NULL
, 'p' },
760 { "relative-only", no_argument
, NULL
, 'r' },
761 { "object-directory", required_argument
, NULL
, 'o' },
762 { "object-file", required_argument
, NULL
, 'o' },
763 { "source-prefix", required_argument
, NULL
, 's' },
764 { "unconditional-branches", no_argument
, NULL
, 'u' },
765 { "display-progress", no_argument
, NULL
, 'd' },
766 { "hash-filenames", no_argument
, NULL
, 'x' },
767 { "use-colors", no_argument
, NULL
, 'k' },
771 /* Process args, return index to first non-arg. */
774 process_args (int argc
, char **argv
)
778 const char *opts
= "abcdfhiklmno:prs:uvwx";
779 while ((opt
= getopt_long (argc
, argv
, opts
, options
, NULL
)) != -1)
793 flag_function_summary
= 1;
797 /* print_usage will exit. */
805 flag_demangled_names
= 1;
811 object_directory
= optarg
;
814 source_prefix
= optarg
;
815 source_length
= strlen (source_prefix
);
818 flag_relative_only
= 1;
821 flag_preserve_paths
= 1;
824 flag_unconditional
= 1;
827 flag_intermediate_format
= 1;
831 flag_display_progress
= 1;
834 flag_hash_filenames
= 1;
841 /* print_version will exit. */
844 /* print_usage will exit. */
851 /* Output the result in intermediate format used by 'lcov'.
853 The intermediate format contains a single file named 'foo.cc.gcov',
854 with no source code included.
856 The default gcov outputs multiple files: 'foo.cc.gcov',
857 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
858 included. Instead the intermediate format here outputs only a single
859 file 'foo.cc.gcov' similar to the above example. */
862 output_intermediate_file (FILE *gcov_file
, source_t
*src
)
864 unsigned line_num
; /* current line number. */
865 const line_t
*line
; /* current line info ptr. */
866 function_t
*fn
; /* current function info ptr. */
868 fprintf (gcov_file
, "file:%s\n", src
->name
); /* source file name */
870 for (fn
= src
->functions
; fn
; fn
= fn
->next_file_fn
)
872 /* function:<name>,<line_number>,<execution_count> */
873 fprintf (gcov_file
, "function:%d,%s,%s\n", fn
->line
,
874 format_gcov (fn
->blocks
[0].count
, 0, -1),
875 flag_demangled_names
? fn
->demangled_name
: fn
->name
);
878 for (line_num
= 1, line
= &src
->lines
[line_num
];
879 line_num
< src
->num_lines
;
884 fprintf (gcov_file
, "lcount:%u,%s,%d\n", line_num
,
885 format_gcov (line
->count
, 0, -1), line
->has_unexecuted_block
);
887 for (arc
= line
->branches
; arc
; arc
= arc
->line_next
)
889 if (!arc
->is_unconditional
&& !arc
->is_call_non_return
)
891 const char *branch_type
;
892 /* branch:<line_num>,<branch_coverage_type>
894 : notexec (Branch not executed)
895 : taken (Branch executed and taken)
896 : nottaken (Branch executed, but not taken)
899 branch_type
= (arc
->count
> 0) ? "taken" : "nottaken";
901 branch_type
= "notexec";
902 fprintf (gcov_file
, "branch:%d,%s\n", line_num
, branch_type
);
908 /* Process a single input file. */
911 process_file (const char *file_name
)
915 create_file_names (file_name
);
916 fns
= read_graph_file ();
920 read_count_file (fns
);
923 function_t
*fn
= fns
;
927 if (fn
->counts
|| no_data_file
)
929 unsigned src
= fn
->src
;
930 unsigned line
= fn
->line
;
932 function_t
*probe
, **prev
;
934 /* Now insert it into the source file's list of
935 functions. Normally functions will be encountered in
936 ascending order, so a simple scan is quick. Note we're
937 building this list in reverse order. */
938 for (prev
= &sources
[src
].functions
;
939 (probe
= *prev
); prev
= &probe
->next_file_fn
)
940 if (probe
->line
<= line
)
942 fn
->next_file_fn
= probe
;
945 /* Mark last line in files touched by function. */
946 for (block_no
= 0; block_no
!= fn
->blocks
.size (); block_no
++)
948 block_t
*block
= &fn
->blocks
[block_no
];
949 for (unsigned i
= 0; i
< block
->locations
.size (); i
++)
951 unsigned s
= block
->locations
[i
].source_file_idx
;
953 /* Sort lines of locations. */
954 sort (block
->locations
[i
].lines
.begin (),
955 block
->locations
[i
].lines
.end ());
957 if (!block
->locations
[i
].lines
.empty ())
960 = block
->locations
[i
].lines
.back () + 1;
961 if (last_line
> sources
[s
].num_lines
)
962 sources
[s
].num_lines
= last_line
;
967 solve_flow_graph (fn
);
969 find_exception_blocks (fn
);
974 /* The function was not in the executable -- some other
975 instance must have been selected. */
981 output_gcov_file (const char *file_name
, source_t
*src
)
983 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->coverage
.name
);
985 if (src
->coverage
.lines
)
987 FILE *gcov_file
= fopen (gcov_file_name
, "w");
990 fnotice (stdout
, "Creating '%s'\n", gcov_file_name
);
992 if (flag_intermediate_format
)
993 output_intermediate_file (gcov_file
, src
);
995 output_lines (gcov_file
, src
);
996 if (ferror (gcov_file
))
997 fnotice (stderr
, "Error writing output file '%s'\n", gcov_file_name
);
1001 fnotice (stderr
, "Could not open output file '%s'\n", gcov_file_name
);
1005 unlink (gcov_file_name
);
1006 fnotice (stdout
, "Removing '%s'\n", gcov_file_name
);
1008 free (gcov_file_name
);
1012 generate_results (const char *file_name
)
1018 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
1020 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
1022 for (fn
= functions
; fn
; fn
= fn
->next
)
1024 coverage_t coverage
;
1026 memset (&coverage
, 0, sizeof (coverage
));
1027 coverage
.name
= flag_demangled_names
? fn
->demangled_name
: fn
->name
;
1028 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
1029 if (flag_function_summary
)
1031 function_summary (&coverage
, "Function");
1032 fnotice (stdout
, "\n");
1038 name_map_t
*name_map
= (name_map_t
*)bsearch
1039 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
1041 file_name
= sources
[name_map
->src
].coverage
.name
;
1043 file_name
= canonicalize_name (file_name
);
1046 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
1048 if (flag_relative_only
)
1050 /* Ignore this source, if it is an absolute path (after
1051 source prefix removal). */
1052 char first
= src
->coverage
.name
[0];
1054 #if HAVE_DOS_BASED_FILE_SYSTEM
1055 if (first
&& src
->coverage
.name
[1] == ':')
1056 first
= src
->coverage
.name
[2];
1058 if (IS_DIR_SEPARATOR (first
))
1062 accumulate_line_counts (src
);
1063 function_summary (&src
->coverage
, "File");
1064 total_lines
+= src
->coverage
.lines
;
1065 total_executed
+= src
->coverage
.lines_executed
;
1068 output_gcov_file (file_name
, src
);
1069 fnotice (stdout
, "\n");
1074 executed_summary (total_lines
, total_executed
);
1077 /* Release all memory used. */
1080 release_structures (void)
1085 for (ix
= n_sources
; ix
--;)
1086 free (sources
[ix
].lines
);
1089 for (ix
= n_names
; ix
--;)
1090 free (names
[ix
].name
);
1093 while ((fn
= functions
))
1095 functions
= fn
->next
;
1100 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1101 is not specified, these are named from FILE_NAME sans extension. If
1102 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1103 directory, but named from the basename of the FILE_NAME, sans extension.
1104 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1105 and the data files are named from that. */
1108 create_file_names (const char *file_name
)
1112 int length
= strlen (file_name
);
1115 /* Free previous file names. */
1116 free (bbg_file_name
);
1117 free (da_file_name
);
1118 da_file_name
= bbg_file_name
= NULL
;
1122 if (object_directory
&& object_directory
[0])
1126 length
+= strlen (object_directory
) + 2;
1127 name
= XNEWVEC (char, length
);
1130 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
1131 strcat (name
, object_directory
);
1132 if (base
&& (!IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
1137 name
= XNEWVEC (char, length
+ 1);
1138 strcpy (name
, file_name
);
1144 /* Append source file name. */
1145 const char *cptr
= lbasename (file_name
);
1146 strcat (name
, cptr
? cptr
: file_name
);
1149 /* Remove the extension. */
1150 cptr
= strrchr (CONST_CAST (char *, lbasename (name
)), '.');
1154 length
= strlen (name
);
1156 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
1157 strcpy (bbg_file_name
, name
);
1158 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
1160 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
1161 strcpy (da_file_name
, name
);
1162 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
1168 /* A is a string and B is a pointer to name_map_t. Compare for file
1169 name orderability. */
1172 name_search (const void *a_
, const void *b_
)
1174 const char *a
= (const char *)a_
;
1175 const name_map_t
*b
= (const name_map_t
*)b_
;
1177 #if HAVE_DOS_BASED_FILE_SYSTEM
1178 return strcasecmp (a
, b
->name
);
1180 return strcmp (a
, b
->name
);
1184 /* A and B are a pointer to name_map_t. Compare for file name
1188 name_sort (const void *a_
, const void *b_
)
1190 const name_map_t
*a
= (const name_map_t
*)a_
;
1191 return name_search (a
->name
, b_
);
1194 /* Find or create a source file structure for FILE_NAME. Copies
1195 FILE_NAME on creation */
1198 find_source (const char *file_name
)
1200 name_map_t
*name_map
;
1206 file_name
= "<unknown>";
1207 name_map
= (name_map_t
*)bsearch
1208 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
1211 idx
= name_map
->src
;
1215 if (n_names
+ 2 > a_names
)
1217 /* Extend the name map array -- we'll be inserting one or two
1220 name_map
= XNEWVEC (name_map_t
, a_names
);
1221 memcpy (name_map
, names
, n_names
* sizeof (*names
));
1226 /* Not found, try the canonical name. */
1227 canon
= canonicalize_name (file_name
);
1228 name_map
= (name_map_t
*) bsearch (canon
, names
, n_names
, sizeof (*names
),
1232 /* Not found with canonical name, create a new source. */
1235 if (n_sources
== a_sources
)
1238 src
= XNEWVEC (source_t
, a_sources
);
1239 memcpy (src
, sources
, n_sources
* sizeof (*sources
));
1246 name_map
= &names
[n_names
++];
1247 name_map
->name
= canon
;
1248 name_map
->src
= idx
;
1250 src
= &sources
[n_sources
++];
1251 memset (src
, 0, sizeof (*src
));
1253 src
->coverage
.name
= src
->name
;
1255 #if HAVE_DOS_BASED_FILE_SYSTEM
1256 /* You lose if separators don't match exactly in the
1258 && !strncasecmp (source_prefix
, src
->coverage
.name
, source_length
)
1260 && !strncmp (source_prefix
, src
->coverage
.name
, source_length
)
1262 && IS_DIR_SEPARATOR (src
->coverage
.name
[source_length
]))
1263 src
->coverage
.name
+= source_length
+ 1;
1264 if (!stat (src
->name
, &status
))
1265 src
->file_time
= status
.st_mtime
;
1268 idx
= name_map
->src
;
1270 if (name_search (file_name
, name_map
))
1272 /* Append the non-canonical name. */
1273 name_map
= &names
[n_names
++];
1274 name_map
->name
= xstrdup (file_name
);
1275 name_map
->src
= idx
;
1278 /* Resort the name map. */
1279 qsort (names
, n_names
, sizeof (*names
), name_sort
);
1282 if (sources
[idx
].file_time
> bbg_file_time
)
1284 static int info_emitted
;
1286 fnotice (stderr
, "%s:source file is newer than notes file '%s'\n",
1287 file_name
, bbg_file_name
);
1291 "(the message is displayed only once per source file)\n");
1294 sources
[idx
].file_time
= 0;
1300 /* Read the notes file. Return list of functions read -- in reverse order. */
1303 read_graph_file (void)
1306 unsigned current_tag
= 0;
1307 function_t
*fn
= NULL
;
1308 function_t
*fns
= NULL
;
1309 function_t
**fns_end
= &fns
;
1312 if (!gcov_open (bbg_file_name
, 1))
1314 fnotice (stderr
, "%s:cannot open notes file\n", bbg_file_name
);
1317 bbg_file_time
= gcov_time ();
1318 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
1320 fnotice (stderr
, "%s:not a gcov notes file\n", bbg_file_name
);
1325 version
= gcov_read_unsigned ();
1326 if (version
!= GCOV_VERSION
)
1330 GCOV_UNSIGNED2STRING (v
, version
);
1331 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1333 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
1334 bbg_file_name
, v
, e
);
1336 bbg_stamp
= gcov_read_unsigned ();
1338 while ((tag
= gcov_read_unsigned ()))
1340 unsigned length
= gcov_read_unsigned ();
1341 gcov_position_t base
= gcov_position ();
1343 if (tag
== GCOV_TAG_FUNCTION
)
1345 char *function_name
;
1346 unsigned ident
, lineno
;
1347 unsigned lineno_checksum
, cfg_checksum
;
1349 ident
= gcov_read_unsigned ();
1350 lineno_checksum
= gcov_read_unsigned ();
1351 cfg_checksum
= gcov_read_unsigned ();
1352 function_name
= xstrdup (gcov_read_string ());
1353 unsigned src_idx
= find_source (gcov_read_string ());
1354 lineno
= gcov_read_unsigned ();
1356 fn
= new function_t
;
1357 fn
->name
= function_name
;
1358 if (flag_demangled_names
)
1360 fn
->demangled_name
= cplus_demangle (fn
->name
, DMGL_PARAMS
);
1361 if (!fn
->demangled_name
)
1362 fn
->demangled_name
= fn
->name
;
1365 fn
->lineno_checksum
= lineno_checksum
;
1366 fn
->cfg_checksum
= cfg_checksum
;
1370 fn
->next_file_fn
= NULL
;
1373 fns_end
= &fn
->next
;
1376 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
1378 if (!fn
->blocks
.empty ())
1379 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
1380 bbg_file_name
, fn
->name
);
1382 fn
->blocks
.resize (gcov_read_unsigned ());
1384 else if (fn
&& tag
== GCOV_TAG_ARCS
)
1386 unsigned src
= gcov_read_unsigned ();
1387 fn
->blocks
[src
].id
= src
;
1388 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
1389 block_t
*src_blk
= &fn
->blocks
[src
];
1390 unsigned mark_catches
= 0;
1391 struct arc_info
*arc
;
1393 if (src
>= fn
->blocks
.size () || fn
->blocks
[src
].succ
)
1398 unsigned dest
= gcov_read_unsigned ();
1399 unsigned flags
= gcov_read_unsigned ();
1401 if (dest
>= fn
->blocks
.size ())
1403 arc
= XCNEW (arc_t
);
1405 arc
->dst
= &fn
->blocks
[dest
];
1409 arc
->count_valid
= 0;
1410 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
1411 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
1412 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
1414 arc
->succ_next
= src_blk
->succ
;
1415 src_blk
->succ
= arc
;
1416 src_blk
->num_succ
++;
1418 arc
->pred_next
= fn
->blocks
[dest
].pred
;
1419 fn
->blocks
[dest
].pred
= arc
;
1420 fn
->blocks
[dest
].num_pred
++;
1426 /* Exceptional exit from this function, the
1427 source block must be a call. */
1428 fn
->blocks
[src
].is_call_site
= 1;
1429 arc
->is_call_non_return
= 1;
1434 /* Non-local return from a callee of this
1435 function. The destination block is a setjmp. */
1436 arc
->is_nonlocal_return
= 1;
1437 fn
->blocks
[dest
].is_nonlocal_return
= 1;
1447 /* We have a fake exit from this block. The other
1448 non-fall through exits must be to catch handlers.
1449 Mark them as catch arcs. */
1451 for (arc
= src_blk
->succ
; arc
; arc
= arc
->succ_next
)
1452 if (!arc
->fake
&& !arc
->fall_through
)
1459 else if (fn
&& tag
== GCOV_TAG_LINES
)
1461 unsigned blockno
= gcov_read_unsigned ();
1462 block_t
*block
= &fn
->blocks
[blockno
];
1464 if (blockno
>= fn
->blocks
.size ())
1469 unsigned lineno
= gcov_read_unsigned ();
1472 block
->locations
.back ().lines
.push_back (lineno
);
1475 const char *file_name
= gcov_read_string ();
1479 block
->locations
.push_back (block_location_info
1480 (find_source (file_name
)));
1484 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
1489 gcov_sync (base
, length
);
1490 if (gcov_is_error ())
1493 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
1500 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
1505 /* Reads profiles from the count file and attach to each
1506 function. Return nonzero if fatal error. */
1509 read_count_file (function_t
*fns
)
1514 function_t
*fn
= NULL
;
1517 if (!gcov_open (da_file_name
, 1))
1519 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1524 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1526 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1531 version
= gcov_read_unsigned ();
1532 if (version
!= GCOV_VERSION
)
1536 GCOV_UNSIGNED2STRING (v
, version
);
1537 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1539 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1540 da_file_name
, v
, e
);
1542 tag
= gcov_read_unsigned ();
1543 if (tag
!= bbg_stamp
)
1545 fnotice (stderr
, "%s:stamp mismatch with notes file\n", da_file_name
);
1549 while ((tag
= gcov_read_unsigned ()))
1551 unsigned length
= gcov_read_unsigned ();
1552 unsigned long base
= gcov_position ();
1554 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1556 struct gcov_summary summary
;
1557 gcov_read_summary (&summary
);
1558 object_runs
+= summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
;
1561 else if (tag
== GCOV_TAG_FUNCTION
&& !length
)
1563 else if (tag
== GCOV_TAG_FUNCTION
&& length
== GCOV_TAG_FUNCTION_LENGTH
)
1566 struct function_info
*fn_n
;
1568 /* Try to find the function in the list. To speed up the
1569 search, first start from the last function found. */
1570 ident
= gcov_read_unsigned ();
1572 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1576 else if ((fn
= fn_n
))
1580 fnotice (stderr
, "%s:unknown function '%u'\n",
1581 da_file_name
, ident
);
1584 if (fn
->ident
== ident
)
1590 else if (gcov_read_unsigned () != fn
->lineno_checksum
1591 || gcov_read_unsigned () != fn
->cfg_checksum
)
1594 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1595 da_file_name
, fn
->name
);
1599 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1601 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1605 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1607 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1608 fn
->counts
[ix
] += gcov_read_counter ();
1610 gcov_sync (base
, length
);
1611 if ((error
= gcov_is_error ()))
1615 ? N_("%s:overflowed\n")
1616 : N_("%s:corrupted\n"),
1626 /* Solve the flow graph. Propagate counts from the instrumented arcs
1627 to the blocks and the uninstrumented arcs. */
1630 solve_flow_graph (function_t
*fn
)
1634 gcov_type
*count_ptr
= fn
->counts
;
1636 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1637 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1639 /* The arcs were built in reverse order. Fix that now. */
1640 for (ix
= fn
->blocks
.size (); ix
--;)
1642 arc_t
*arc_p
, *arc_n
;
1644 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1645 arc_p
= arc
, arc
= arc_n
)
1647 arc_n
= arc
->succ_next
;
1648 arc
->succ_next
= arc_p
;
1650 fn
->blocks
[ix
].succ
= arc_p
;
1652 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1653 arc_p
= arc
, arc
= arc_n
)
1655 arc_n
= arc
->pred_next
;
1656 arc
->pred_next
= arc_p
;
1658 fn
->blocks
[ix
].pred
= arc_p
;
1661 if (fn
->blocks
.size () < 2)
1662 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1663 bbg_file_name
, fn
->name
);
1666 if (fn
->blocks
[ENTRY_BLOCK
].num_pred
)
1667 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1668 bbg_file_name
, fn
->name
);
1670 /* We can't deduce the entry block counts from the lack of
1672 fn
->blocks
[ENTRY_BLOCK
].num_pred
= ~(unsigned)0;
1674 if (fn
->blocks
[EXIT_BLOCK
].num_succ
)
1675 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1676 bbg_file_name
, fn
->name
);
1678 /* Likewise, we can't deduce exit block counts from the lack
1679 of its successors. */
1680 fn
->blocks
[EXIT_BLOCK
].num_succ
= ~(unsigned)0;
1683 /* Propagate the measured counts, this must be done in the same
1684 order as the code in profile.c */
1685 for (unsigned i
= 0; i
< fn
->blocks
.size (); i
++)
1687 blk
= &fn
->blocks
[i
];
1688 block_t
const *prev_dst
= NULL
;
1689 int out_of_order
= 0;
1690 int non_fake_succ
= 0;
1692 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1700 arc
->count
= *count_ptr
++;
1701 arc
->count_valid
= 1;
1703 arc
->dst
->num_pred
--;
1705 if (prev_dst
&& prev_dst
> arc
->dst
)
1707 prev_dst
= arc
->dst
;
1709 if (non_fake_succ
== 1)
1711 /* If there is only one non-fake exit, it is an
1712 unconditional branch. */
1713 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1716 arc
->is_unconditional
= 1;
1717 /* If this block is instrumenting a call, it might be
1718 an artificial block. It is not artificial if it has
1719 a non-fallthrough exit, or the destination of this
1720 arc has more than one entry. Mark the destination
1721 block as a return site, if none of those conditions
1723 if (blk
->is_call_site
&& arc
->fall_through
1724 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1725 arc
->dst
->is_call_return
= 1;
1729 /* Sort the successor arcs into ascending dst order. profile.c
1730 normally produces arcs in the right order, but sometimes with
1731 one or two out of order. We're not using a particularly
1735 arc_t
*start
= blk
->succ
;
1736 unsigned changes
= 1;
1740 arc_t
*arc
, *arc_p
, *arc_n
;
1743 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1745 if (arc
->dst
> arc_n
->dst
)
1749 arc_p
->succ_next
= arc_n
;
1752 arc
->succ_next
= arc_n
->succ_next
;
1753 arc_n
->succ_next
= arc
;
1766 /* Place it on the invalid chain, it will be ignored if that's
1768 blk
->invalid_chain
= 1;
1769 blk
->chain
= invalid_blocks
;
1770 invalid_blocks
= blk
;
1773 while (invalid_blocks
|| valid_blocks
)
1775 while ((blk
= invalid_blocks
))
1777 gcov_type total
= 0;
1780 invalid_blocks
= blk
->chain
;
1781 blk
->invalid_chain
= 0;
1783 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1784 total
+= arc
->count
;
1785 else if (!blk
->num_pred
)
1786 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1787 total
+= arc
->count
;
1792 blk
->count_valid
= 1;
1793 blk
->chain
= valid_blocks
;
1794 blk
->valid_chain
= 1;
1797 while ((blk
= valid_blocks
))
1800 arc_t
*arc
, *inv_arc
;
1802 valid_blocks
= blk
->chain
;
1803 blk
->valid_chain
= 0;
1804 if (blk
->num_succ
== 1)
1810 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1812 total
-= arc
->count
;
1813 if (!arc
->count_valid
)
1817 inv_arc
->count_valid
= 1;
1818 inv_arc
->count
= total
;
1821 if (dst
->count_valid
)
1823 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1825 dst
->chain
= valid_blocks
;
1826 dst
->valid_chain
= 1;
1832 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1834 dst
->chain
= invalid_blocks
;
1835 dst
->invalid_chain
= 1;
1836 invalid_blocks
= dst
;
1840 if (blk
->num_pred
== 1)
1846 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1848 total
-= arc
->count
;
1849 if (!arc
->count_valid
)
1853 inv_arc
->count_valid
= 1;
1854 inv_arc
->count
= total
;
1857 if (src
->count_valid
)
1859 if (src
->num_succ
== 1 && !src
->valid_chain
)
1861 src
->chain
= valid_blocks
;
1862 src
->valid_chain
= 1;
1868 if (!src
->num_succ
&& !src
->invalid_chain
)
1870 src
->chain
= invalid_blocks
;
1871 src
->invalid_chain
= 1;
1872 invalid_blocks
= src
;
1879 /* If the graph has been correctly solved, every block will have a
1881 for (unsigned i
= 0; ix
< fn
->blocks
.size (); i
++)
1882 if (!fn
->blocks
[i
].count_valid
)
1884 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1885 bbg_file_name
, fn
->name
);
1890 /* Mark all the blocks only reachable via an incoming catch. */
1893 find_exception_blocks (function_t
*fn
)
1896 block_t
**queue
= XALLOCAVEC (block_t
*, fn
->blocks
.size ());
1898 /* First mark all blocks as exceptional. */
1899 for (ix
= fn
->blocks
.size (); ix
--;)
1900 fn
->blocks
[ix
].exceptional
= 1;
1902 /* Now mark all the blocks reachable via non-fake edges */
1903 queue
[0] = &fn
->blocks
[0];
1904 queue
[0]->exceptional
= 0;
1907 block_t
*block
= queue
[--ix
];
1910 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1911 if (!arc
->fake
&& !arc
->is_throw
&& arc
->dst
->exceptional
)
1913 arc
->dst
->exceptional
= 0;
1914 queue
[ix
++] = arc
->dst
;
1920 /* Increment totals in COVERAGE according to arc ARC. */
1923 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1925 if (arc
->is_call_non_return
)
1928 if (arc
->src
->count
)
1929 coverage
->calls_executed
++;
1931 else if (!arc
->is_unconditional
)
1933 coverage
->branches
++;
1934 if (arc
->src
->count
)
1935 coverage
->branches_executed
++;
1937 coverage
->branches_taken
++;
1941 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1942 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1943 If DP is zero, no decimal point is printed. Only print 100% when
1944 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1945 format TOP. Return pointer to a static string. */
1948 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1950 static char buffer
[20];
1952 /* Handle invalid values that would result in a misleading value. */
1953 if (bottom
!= 0 && top
> bottom
&& dp
>= 0)
1955 sprintf (buffer
, "NAN %%");
1961 float ratio
= bottom
? (float)top
/ bottom
: 0;
1963 unsigned limit
= 100;
1966 for (ix
= dp
; ix
--; )
1969 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1970 if (percent
<= 0 && top
)
1972 else if (percent
>= limit
&& top
!= bottom
)
1973 percent
= limit
- 1;
1974 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1980 buffer
[ix
+1] = buffer
[ix
];
1984 buffer
[ix
+ 1] = '.';
1988 sprintf (buffer
, "%" PRId64
, (int64_t)top
);
1993 /* Summary of execution */
1996 executed_summary (unsigned lines
, unsigned executed
)
1999 fnotice (stdout
, "Lines executed:%s of %d\n",
2000 format_gcov (executed
, lines
, 2), lines
);
2002 fnotice (stdout
, "No executable lines\n");
2005 /* Output summary info for a function or file. */
2008 function_summary (const coverage_t
*coverage
, const char *title
)
2010 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
2011 executed_summary (coverage
->lines
, coverage
->lines_executed
);
2015 if (coverage
->branches
)
2017 fnotice (stdout
, "Branches executed:%s of %d\n",
2018 format_gcov (coverage
->branches_executed
,
2019 coverage
->branches
, 2),
2020 coverage
->branches
);
2021 fnotice (stdout
, "Taken at least once:%s of %d\n",
2022 format_gcov (coverage
->branches_taken
,
2023 coverage
->branches
, 2),
2024 coverage
->branches
);
2027 fnotice (stdout
, "No branches\n");
2028 if (coverage
->calls
)
2029 fnotice (stdout
, "Calls executed:%s of %d\n",
2030 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
2033 fnotice (stdout
, "No calls\n");
2037 /* Canonicalize the filename NAME by canonicalizing directory
2038 separators, eliding . components and resolving .. components
2039 appropriately. Always returns a unique string. */
2042 canonicalize_name (const char *name
)
2044 /* The canonical name cannot be longer than the incoming name. */
2045 char *result
= XNEWVEC (char, strlen (name
) + 1);
2046 const char *base
= name
, *probe
;
2051 #if HAVE_DOS_BASED_FILE_SYSTEM
2052 if (base
[0] && base
[1] == ':')
2054 result
[0] = base
[0];
2060 for (dd_base
= ptr
; *base
; base
= probe
)
2064 for (probe
= base
; *probe
; probe
++)
2065 if (IS_DIR_SEPARATOR (*probe
))
2069 if (len
== 1 && base
[0] == '.')
2070 /* Elide a '.' directory */
2072 else if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2074 /* '..', we can only elide it and the previous directory, if
2075 we're not a symlink. */
2076 struct stat ATTRIBUTE_UNUSED buf
;
2080 #if defined (S_ISLNK)
2081 /* S_ISLNK is not POSIX.1-1996. */
2082 || stat (result
, &buf
) || S_ISLNK (buf
.st_mode
)
2086 /* Cannot elide, or unreadable or a symlink. */
2087 dd_base
= ptr
+ 2 + slash
;
2090 while (ptr
!= dd_base
&& *ptr
!= '/')
2092 slash
= ptr
!= result
;
2097 /* Regular pathname component. */
2100 memcpy (ptr
, base
, len
);
2105 for (; IS_DIR_SEPARATOR (*probe
); probe
++)
2113 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2116 md5sum_to_hex (const char *sum
, char *buffer
)
2118 for (unsigned i
= 0; i
< 16; i
++)
2119 sprintf (buffer
+ (2 * i
), "%02x", (unsigned char)sum
[i
]);
2122 /* Generate an output file name. INPUT_NAME is the canonicalized main
2123 input file and SRC_NAME is the canonicalized file name.
2124 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2125 long_output_names we prepend the processed name of the input file
2126 to each output name (except when the current source file is the
2127 input file, so you don't get a double concatenation). The two
2128 components are separated by '##'. With preserve_paths we create a
2129 filename from all path components of the source file, replacing '/'
2130 with '#', and .. with '^', without it we simply take the basename
2131 component. (Remember, the canonicalized name will already have
2132 elided '.' components and converted \\ separators.) */
2135 make_gcov_file_name (const char *input_name
, const char *src_name
)
2140 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
2142 /* Generate the input filename part. */
2143 result
= XNEWVEC (char, strlen (input_name
) + strlen (src_name
) + 10);
2146 ptr
= mangle_name (input_name
, ptr
);
2147 ptr
[0] = ptr
[1] = '#';
2152 result
= XNEWVEC (char, strlen (src_name
) + 10);
2156 ptr
= mangle_name (src_name
, ptr
);
2157 strcpy (ptr
, ".gcov");
2159 /* When hashing filenames, we shorten them by only using the filename
2160 component and appending a hash of the full (mangled) pathname. */
2161 if (flag_hash_filenames
)
2165 char md5sum_hex
[33];
2167 md5_init_ctx (&ctx
);
2168 md5_process_bytes (src_name
, strlen (src_name
), &ctx
);
2169 md5_finish_ctx (&ctx
, md5sum
);
2170 md5sum_to_hex (md5sum
, md5sum_hex
);
2173 result
= XNEWVEC (char, strlen (src_name
) + 50);
2175 ptr
= mangle_name (src_name
, ptr
);
2176 ptr
[0] = ptr
[1] = '#';
2178 memcpy (ptr
, md5sum_hex
, 32);
2180 strcpy (ptr
, ".gcov");
2187 mangle_name (char const *base
, char *ptr
)
2191 /* Generate the source filename part. */
2192 if (!flag_preserve_paths
)
2194 base
= lbasename (base
);
2195 len
= strlen (base
);
2196 memcpy (ptr
, base
, len
);
2201 /* Convert '/' to '#', convert '..' to '^',
2202 convert ':' to '~' on DOS based file system. */
2205 #if HAVE_DOS_BASED_FILE_SYSTEM
2206 if (base
[0] && base
[1] == ':')
2214 for (; *base
; base
= probe
)
2218 for (probe
= base
; *probe
; probe
++)
2222 if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2226 memcpy (ptr
, base
, len
);
2240 /* Scan through the bb_data for each line in the block, increment
2241 the line number execution count indicated by the execution count of
2242 the appropriate basic block. */
2245 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
2247 bool has_any_line
= false;
2248 /* Scan each basic block. */
2249 for (unsigned ix
= 0; ix
!= fn
->blocks
.size (); ix
++)
2251 line_t
*line
= NULL
;
2252 block_t
*block
= &fn
->blocks
[ix
];
2253 if (block
->count
&& ix
&& ix
+ 1 != fn
->blocks
.size ())
2254 fn
->blocks_executed
++;
2255 for (unsigned i
= 0; i
< block
->locations
.size (); i
++)
2257 const source_t
*src
= &sources
[block
->locations
[i
].source_file_idx
];
2259 vector
<unsigned> &lines
= block
->locations
[i
].lines
;
2260 for (unsigned j
= 0; j
< lines
.size (); j
++)
2262 line
= &src
->lines
[lines
[j
]];
2267 if (!line
->count
&& block
->count
)
2268 coverage
->lines_executed
++;
2271 if (!block
->exceptional
)
2273 line
->unexceptional
= 1;
2274 if (block
->count
== 0)
2275 line
->has_unexecuted_block
= 1;
2277 line
->count
+= block
->count
;
2280 block
->cycle
.arc
= NULL
;
2281 block
->cycle
.ident
= ~0U;
2282 has_any_line
= true;
2284 if (!ix
|| ix
+ 1 == fn
->blocks
.size ())
2285 /* Entry or exit block */;
2286 else if (line
!= NULL
)
2288 block
->chain
= line
->blocks
;
2289 line
->blocks
= block
;
2295 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2297 arc
->line_next
= line
->branches
;
2298 line
->branches
= arc
;
2299 if (coverage
&& !arc
->is_unconditional
)
2300 add_branch_counts (coverage
, arc
);
2307 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
2310 /* Accumulate the line counts of a file. */
2313 accumulate_line_counts (source_t
*src
)
2316 function_t
*fn
, *fn_p
, *fn_n
;
2319 /* Reverse the function order. */
2320 for (fn
= src
->functions
, fn_p
= NULL
; fn
; fn_p
= fn
, fn
= fn_n
)
2322 fn_n
= fn
->next_file_fn
;
2323 fn
->next_file_fn
= fn_p
;
2325 src
->functions
= fn_p
;
2327 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
2331 /* The user expects the line count to be the number of times
2332 a line has been executed. Simply summing the block count
2333 will give an artificially high number. The Right Thing
2334 is to sum the entry counts to the graph of blocks on this
2335 line, then find the elementary cycles of the local graph
2336 and add the transition counts of those cycles. */
2337 block_t
*block
, *block_p
, *block_n
;
2338 gcov_type count
= 0;
2340 /* Reverse the block information. */
2341 for (block
= line
->blocks
, block_p
= NULL
; block
;
2342 block_p
= block
, block
= block_n
)
2344 block_n
= block
->chain
;
2345 block
->chain
= block_p
;
2346 block
->cycle
.ident
= ix
;
2348 line
->blocks
= block_p
;
2350 /* Sum the entry arcs. */
2351 for (block
= line
->blocks
; block
; block
= block
->chain
)
2355 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2357 add_branch_counts (&src
->coverage
, arc
);
2360 /* Cycle detection. */
2361 for (block
= line
->blocks
; block
; block
= block
->chain
)
2363 for (arc_t
*arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2364 if (!line
->has_block (arc
->src
))
2365 count
+= arc
->count
;
2366 for (arc_t
*arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2367 arc
->cs_count
= arc
->count
;
2370 /* Now, add the count of loops entirely on this line. */
2371 count
+= get_cycles_count (*line
);
2372 line
->count
= count
;
2377 src
->coverage
.lines
++;
2379 src
->coverage
.lines_executed
++;
2384 /* Output information about ARC number IX. Returns nonzero if
2385 anything is output. */
2388 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
2390 if (arc
->is_call_non_return
)
2392 if (arc
->src
->count
)
2394 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
2395 format_gcov (arc
->src
->count
- arc
->count
,
2396 arc
->src
->count
, -flag_counts
));
2399 fnotice (gcov_file
, "call %2d never executed\n", ix
);
2401 else if (!arc
->is_unconditional
)
2403 if (arc
->src
->count
)
2404 fnotice (gcov_file
, "branch %2d taken %s%s", ix
,
2405 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
2406 arc
->fall_through
? " (fallthrough)"
2407 : arc
->is_throw
? " (throw)" : "");
2409 fnotice (gcov_file
, "branch %2d never executed", ix
);
2412 fnotice (gcov_file
, " (BB %d)", arc
->dst
->id
);
2414 fnotice (gcov_file
, "\n");
2416 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
2418 if (arc
->src
->count
)
2419 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
2420 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
2422 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
2430 read_line (FILE *file
)
2432 static char *string
;
2433 static size_t string_len
;
2440 string
= XNEWVEC (char, string_len
);
2443 while ((ptr
= fgets (string
+ pos
, string_len
- pos
, file
)))
2445 size_t len
= strlen (string
+ pos
);
2447 if (len
&& string
[pos
+ len
- 1] == '\n')
2449 string
[pos
+ len
- 1] = 0;
2453 /* If the file contains NUL characters or an incomplete
2454 last line, which can happen more than once in one run,
2455 we have to avoid doubling the STRING_LEN unnecessarily. */
2456 if (pos
> string_len
/ 2)
2459 string
= XRESIZEVEC (char, string
, string_len
);
2463 return pos
? string
: NULL
;
2466 /* Pad string S with spaces from left to have total width equal to 9. */
2469 pad_count_string (string
&s
)
2472 s
.insert (0, 9 - s
.size (), ' ');
2475 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2476 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2477 an exceptional statement. The output is printed for LINE_NUM of given
2478 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2479 used to indicate non-executed blocks. */
2482 output_line_beginning (FILE *f
, bool exists
, bool unexceptional
,
2483 bool has_unexecuted_block
,
2484 gcov_type count
, unsigned line_num
,
2485 const char *exceptional_string
,
2486 const char *unexceptional_string
)
2493 s
= format_gcov (count
, 0, -1);
2494 if (has_unexecuted_block
)
2496 if (flag_use_colors
)
2498 pad_count_string (s
);
2499 s
= SGR_SEQ (COLOR_BG_MAGENTA COLOR_SEPARATOR COLOR_FG_WHITE
);
2505 pad_count_string (s
);
2509 if (flag_use_colors
)
2512 pad_count_string (s
);
2514 s
.insert (0, SGR_SEQ (COLOR_BG_RED
2515 COLOR_SEPARATOR COLOR_FG_WHITE
));
2517 s
.insert (0, SGR_SEQ (COLOR_BG_CYAN
2518 COLOR_SEPARATOR COLOR_FG_WHITE
));
2523 s
= unexceptional
? unexceptional_string
: exceptional_string
;
2524 pad_count_string (s
);
2531 pad_count_string (s
);
2534 fprintf (f
, "%s:%5u", s
.c_str (), line_num
);
2537 /* Read in the source file one line at a time, and output that line to
2538 the gcov file preceded by its execution count and other
2542 output_lines (FILE *gcov_file
, const source_t
*src
)
2544 #define DEFAULT_LINE_START " -: 0:"
2547 unsigned line_num
; /* current line number. */
2548 const line_t
*line
; /* current line info ptr. */
2549 const char *retval
= ""; /* status of source file reading. */
2550 function_t
*fn
= NULL
;
2552 fprintf (gcov_file
, DEFAULT_LINE_START
"Source:%s\n", src
->coverage
.name
);
2553 if (!multiple_files
)
2555 fprintf (gcov_file
, DEFAULT_LINE_START
"Graph:%s\n", bbg_file_name
);
2556 fprintf (gcov_file
, DEFAULT_LINE_START
"Data:%s\n",
2557 no_data_file
? "-" : da_file_name
);
2558 fprintf (gcov_file
, DEFAULT_LINE_START
"Runs:%u\n", object_runs
);
2560 fprintf (gcov_file
, DEFAULT_LINE_START
"Programs:%u\n", program_count
);
2562 source_file
= fopen (src
->name
, "r");
2565 fnotice (stderr
, "Cannot open source file %s\n", src
->name
);
2568 else if (src
->file_time
== 0)
2569 fprintf (gcov_file
, DEFAULT_LINE_START
"Source is newer than graph\n");
2572 fn
= src
->functions
;
2574 for (line_num
= 1, line
= &src
->lines
[line_num
];
2575 line_num
< src
->num_lines
; line_num
++, line
++)
2577 for (; fn
&& fn
->line
== line_num
; fn
= fn
->next_file_fn
)
2579 arc_t
*arc
= fn
->blocks
[EXIT_BLOCK
].pred
;
2580 gcov_type return_count
= fn
->blocks
[EXIT_BLOCK
].count
;
2581 gcov_type called_count
= fn
->blocks
[ENTRY_BLOCK
].count
;
2583 for (; arc
; arc
= arc
->pred_next
)
2585 return_count
-= arc
->count
;
2587 fprintf (gcov_file
, "function %s", flag_demangled_names
?
2588 fn
->demangled_name
: fn
->name
);
2589 fprintf (gcov_file
, " called %s",
2590 format_gcov (called_count
, 0, -1));
2591 fprintf (gcov_file
, " returned %s",
2592 format_gcov (return_count
, called_count
, 0));
2593 fprintf (gcov_file
, " blocks executed %s",
2594 format_gcov (fn
->blocks_executed
, fn
->blocks
.size () - 2,
2596 fprintf (gcov_file
, "\n");
2600 retval
= read_line (source_file
);
2602 /* For lines which don't exist in the .bb file, print '-' before
2603 the source line. For lines which exist but were never
2604 executed, print '#####' or '=====' before the source line.
2605 Otherwise, print the execution count before the source line.
2606 There are 16 spaces of indentation added before the source
2607 line so that tabs won't be messed up. */
2608 output_line_beginning (gcov_file
, line
->exists
, line
->unexceptional
,
2609 line
->has_unexecuted_block
, line
->count
, line_num
,
2611 fprintf (gcov_file
, ":%s\n", retval
? retval
: "/*EOF*/");
2613 if (flag_all_blocks
)
2619 for (ix
= jx
= 0, block
= line
->blocks
; block
;
2620 block
= block
->chain
)
2622 if (!block
->is_call_return
)
2624 output_line_beginning (gcov_file
, line
->exists
,
2625 block
->exceptional
, false,
2626 block
->count
, line_num
,
2628 fprintf (gcov_file
, "-block %2d", ix
++);
2630 fprintf (gcov_file
, " (BB %u)", block
->id
);
2631 fprintf (gcov_file
, "\n");
2634 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2635 jx
+= output_branch_count (gcov_file
, jx
, arc
);
2638 else if (flag_branches
)
2643 for (ix
= 0, arc
= line
->branches
; arc
; arc
= arc
->line_next
)
2644 ix
+= output_branch_count (gcov_file
, ix
, arc
);
2648 /* Handle all remaining source lines. There may be lines after the
2649 last line of code. */
2652 for (; (retval
= read_line (source_file
)); line_num
++)
2653 fprintf (gcov_file
, "%9s:%5u:%s\n", "-", line_num
, retval
);
2657 fclose (source_file
);