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;
262 line_t::has_block (block_t
*needle
)
264 for (block_t
*n
= blocks
; n
; n
= n
->chain
)
271 /* Describes a file mentioned in the block graph. Contains an array
274 typedef struct source_info
276 /* Canonical name of source file. */
280 /* Array of line information. */
286 /* Functions in this source file. These are in ascending line
288 function_t
*functions
;
291 typedef struct name_map
293 char *name
; /* Source file name */
294 unsigned src
; /* Source file */
297 /* Holds a list of function basic block graphs. */
299 static function_t
*functions
;
300 static function_t
**fn_end
= &functions
;
302 static source_t
*sources
; /* Array of source files */
303 static unsigned n_sources
; /* Number of sources */
304 static unsigned a_sources
; /* Allocated sources */
306 static name_map_t
*names
; /* Mapping of file names to sources */
307 static unsigned n_names
; /* Number of names */
308 static unsigned a_names
; /* Allocated names */
310 /* This holds data summary information. */
312 static unsigned object_runs
;
313 static unsigned program_count
;
315 static unsigned total_lines
;
316 static unsigned total_executed
;
318 /* Modification time of graph file. */
320 static time_t bbg_file_time
;
322 /* Name of the notes (gcno) output file. The "bbg" prefix is for
323 historical reasons, when the notes file contained only the
324 basic block graph notes. */
326 static char *bbg_file_name
;
328 /* Stamp of the bbg file */
329 static unsigned bbg_stamp
;
331 /* Name and file pointer of the input file for the count data (gcda). */
333 static char *da_file_name
;
335 /* Data file is missing. */
337 static int no_data_file
;
339 /* If there is several input files, compute and display results after
340 reading all data files. This way if two or more gcda file refer to
341 the same source file (eg inline subprograms in a .h file), the
344 static int multiple_files
= 0;
346 /* Output branch probabilities. */
348 static int flag_branches
= 0;
350 /* Show unconditional branches too. */
351 static int flag_unconditional
= 0;
353 /* Output a gcov file if this is true. This is on by default, and can
354 be turned off by the -n option. */
356 static int flag_gcov_file
= 1;
358 /* Output progress indication if this is true. This is off by default
359 and can be turned on by the -d option. */
361 static int flag_display_progress
= 0;
363 /* Output *.gcov file in intermediate format used by 'lcov'. */
365 static int flag_intermediate_format
= 0;
367 /* Output demangled function names. */
369 static int flag_demangled_names
= 0;
371 /* For included files, make the gcov output file name include the name
372 of the input source file. For example, if x.h is included in a.c,
373 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
375 static int flag_long_names
= 0;
377 /* For situations when a long name can potentially hit filesystem path limit,
378 let's calculate md5sum of the path and append it to a file name. */
380 static int flag_hash_filenames
= 0;
382 /* Print verbose informations. */
384 static int flag_verbose
= 0;
386 /* Print colored output. */
388 static int flag_use_colors
= 0;
390 /* Output count information for every basic block, not merely those
391 that contain line number information. */
393 static int flag_all_blocks
= 0;
395 /* Output summary info for each function. */
397 static int flag_function_summary
= 0;
399 /* Object directory file prefix. This is the directory/file where the
400 graph and data files are looked for, if nonzero. */
402 static char *object_directory
= 0;
404 /* Source directory prefix. This is removed from source pathnames
405 that match, when generating the output file name. */
407 static char *source_prefix
= 0;
408 static size_t source_length
= 0;
410 /* Only show data for sources with relative pathnames. Absolute ones
411 usually indicate a system header file, which although it may
412 contain inline functions, is usually uninteresting. */
413 static int flag_relative_only
= 0;
415 /* Preserve all pathname components. Needed when object files and
416 source files are in subdirectories. '/' is mangled as '#', '.' is
417 elided and '..' mangled to '^'. */
419 static int flag_preserve_paths
= 0;
421 /* Output the number of times a branch was taken as opposed to the percentage
422 of times it was taken. */
424 static int flag_counts
= 0;
426 /* Forward declarations. */
427 static int process_args (int, char **);
428 static void print_usage (int) ATTRIBUTE_NORETURN
;
429 static void print_version (void) ATTRIBUTE_NORETURN
;
430 static void process_file (const char *);
431 static void generate_results (const char *);
432 static void create_file_names (const char *);
433 static int name_search (const void *, const void *);
434 static int name_sort (const void *, const void *);
435 static char *canonicalize_name (const char *);
436 static unsigned find_source (const char *);
437 static function_t
*read_graph_file (void);
438 static int read_count_file (function_t
*);
439 static void solve_flow_graph (function_t
*);
440 static void find_exception_blocks (function_t
*);
441 static void add_branch_counts (coverage_t
*, const arc_t
*);
442 static void add_line_counts (coverage_t
*, function_t
*);
443 static void executed_summary (unsigned, unsigned);
444 static void function_summary (const coverage_t
*, const char *);
445 static const char *format_gcov (gcov_type
, gcov_type
, int);
446 static void accumulate_line_counts (source_t
*);
447 static void output_gcov_file (const char *, source_t
*);
448 static int output_branch_count (FILE *, int, const arc_t
*);
449 static void output_lines (FILE *, const source_t
*);
450 static char *make_gcov_file_name (const char *, const char *);
451 static char *mangle_name (const char *, char *);
452 static void release_structures (void);
453 extern int main (int, char **);
455 function_info::function_info (): name (NULL
), demangled_name (NULL
),
456 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
457 blocks (), blocks_executed (0), counts (NULL
), num_counts (0),
458 line (0), src (0), next_file_fn (NULL
), next (NULL
)
462 function_info::~function_info ()
464 for (int i
= blocks
.size () - 1; i
>= 0; i
--)
468 for (arc
= blocks
[i
].succ
; arc
; arc
= arc_n
)
470 arc_n
= arc
->succ_next
;
475 if (flag_demangled_names
&& demangled_name
!= name
)
476 free (demangled_name
);
481 There are a bajillion algorithms that do this. Boost's function is named
482 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
483 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
484 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
486 The basic algorithm is simple: effectively, we're finding all simple paths
487 in a subgraph (that shrinks every iteration). Duplicates are filtered by
488 "blocking" a path when a node is added to the path (this also prevents non-
489 simple paths)--the node is unblocked only when it participates in a cycle.
492 typedef vector
<arc_t
*> arc_vector_t
;
493 typedef vector
<const block_t
*> block_vector_t
;
495 /* Enum with types of loop in CFG. */
504 /* Loop_type operator that merges two values: A and B. */
506 inline loop_type
& operator |= (loop_type
& a
, loop_type b
)
508 return a
= static_cast<loop_type
> (a
| b
);
511 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
512 and subtract the value from all counts. The subtracted value is added
513 to COUNT. Returns type of loop. */
516 handle_cycle (const arc_vector_t
&edges
, int64_t &count
)
518 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
520 int64_t cycle_count
= INTTYPE_MAXIMUM (int64_t);
521 for (unsigned i
= 0; i
< edges
.size (); i
++)
523 int64_t ecount
= edges
[i
]->cs_count
;
524 if (cycle_count
> ecount
)
525 cycle_count
= ecount
;
527 count
+= cycle_count
;
528 for (unsigned i
= 0; i
< edges
.size (); i
++)
529 edges
[i
]->cs_count
-= cycle_count
;
531 return cycle_count
< 0 ? NEGATIVE_LOOP
: LOOP
;
534 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
535 blocked by U in BLOCK_LISTS. */
538 unblock (const block_t
*u
, block_vector_t
&blocked
,
539 vector
<block_vector_t
> &block_lists
)
541 block_vector_t::iterator it
= find (blocked
.begin (), blocked
.end (), u
);
542 if (it
== blocked
.end ())
545 unsigned index
= it
- blocked
.begin ();
548 block_vector_t
to_unblock (block_lists
[index
]);
550 block_lists
.erase (block_lists
.begin () + index
);
552 for (block_vector_t::iterator it
= to_unblock
.begin ();
553 it
!= to_unblock
.end (); it
++)
554 unblock (*it
, blocked
, block_lists
);
557 /* Find circuit going to block V, PATH is provisional seen cycle.
558 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
559 blocked by a block. COUNT is accumulated count of the current LINE.
560 Returns what type of loop it contains. */
563 circuit (block_t
*v
, arc_vector_t
&path
, block_t
*start
,
564 block_vector_t
&blocked
, vector
<block_vector_t
> &block_lists
,
565 line_t
&linfo
, int64_t &count
)
567 loop_type result
= NO_LOOP
;
569 /* Add v to the block list. */
570 gcc_assert (find (blocked
.begin (), blocked
.end (), v
) == blocked
.end ());
571 blocked
.push_back (v
);
572 block_lists
.push_back (block_vector_t ());
574 for (arc_t
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
576 block_t
*w
= arc
->dst
;
577 if (w
< start
|| !linfo
.has_block (w
))
580 path
.push_back (arc
);
582 /* Cycle has been found. */
583 result
|= handle_cycle (path
, count
);
584 else if (find (blocked
.begin (), blocked
.end (), w
) == blocked
.end ())
585 result
|= circuit (w
, path
, start
, blocked
, block_lists
, linfo
, count
);
590 if (result
!= NO_LOOP
)
591 unblock (v
, blocked
, block_lists
);
593 for (arc_t
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
595 block_t
*w
= arc
->dst
;
596 if (w
< start
|| !linfo
.has_block (w
))
600 = find (blocked
.begin (), blocked
.end (), w
) - blocked
.begin ();
601 gcc_assert (index
< blocked
.size ());
602 block_vector_t
&list
= block_lists
[index
];
603 if (find (list
.begin (), list
.end (), v
) == list
.end ())
610 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
611 contains a negative loop, then perform the same function once again. */
614 get_cycles_count (line_t
&linfo
, bool handle_negative_cycles
= true)
616 /* Note that this algorithm works even if blocks aren't in sorted order.
617 Each iteration of the circuit detection is completely independent
618 (except for reducing counts, but that shouldn't matter anyways).
619 Therefore, operating on a permuted order (i.e., non-sorted) only
620 has the effect of permuting the output cycles. */
622 loop_type result
= NO_LOOP
;
624 for (block_t
*block
= linfo
.blocks
; block
; block
= block
->chain
)
627 block_vector_t blocked
;
628 vector
<block_vector_t
> block_lists
;
629 result
|= circuit (block
, path
, block
, blocked
, block_lists
, linfo
,
633 /* If we have a negative cycle, repeat the find_cycles routine. */
634 if (result
== NEGATIVE_LOOP
&& handle_negative_cycles
)
635 count
+= get_cycles_count (linfo
, false);
641 main (int argc
, char **argv
)
647 p
= argv
[0] + strlen (argv
[0]);
648 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
652 xmalloc_set_program_name (progname
);
654 /* Unlock the stdio streams. */
655 unlock_std_streams ();
659 diagnostic_initialize (global_dc
, 0);
661 /* Handle response files. */
662 expandargv (&argc
, &argv
);
665 names
= XNEWVEC (name_map_t
, a_names
);
667 sources
= XNEWVEC (source_t
, a_sources
);
669 argno
= process_args (argc
, argv
);
673 if (argc
- argno
> 1)
678 for (; argno
!= argc
; argno
++)
680 if (flag_display_progress
)
681 printf ("Processing file %d out of %d\n", argno
- first_arg
+ 1,
683 process_file (argv
[argno
]);
686 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
688 release_structures ();
693 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
694 otherwise the output of --help. */
697 print_usage (int error_p
)
699 FILE *file
= error_p
? stderr
: stdout
;
700 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
702 fnotice (file
, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
703 fnotice (file
, "Print code coverage information.\n\n");
704 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
705 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
706 fnotice (file
, " -c, --branch-counts Output counts of branches taken\n\
707 rather than percentages\n");
708 fnotice (file
, " -d, --display-progress Display progress information\n");
709 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
710 fnotice (file
, " -h, --help Print this help, then exit\n");
711 fnotice (file
, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
712 fnotice (file
, " -k, --use-colors Emit colored output\n");
713 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
715 fnotice (file
, " -m, --demangled-names Output demangled function names\n");
716 fnotice (file
, " -n, --no-output Do not create an output file\n");
717 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
718 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
719 fnotice (file
, " -r, --relative-only Only show data for relative sources\n");
720 fnotice (file
, " -s, --source-prefix DIR Source prefix to elide\n");
721 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
722 fnotice (file
, " -v, --version Print version number, then exit\n");
723 fnotice (file
, " -w, --verbose Print verbose informations\n");
724 fnotice (file
, " -x, --hash-filenames Hash long pathnames\n");
725 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
730 /* Print version information and exit. */
735 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
736 fprintf (stdout
, "Copyright %s 2017 Free Software Foundation, Inc.\n",
739 _("This is free software; see the source for copying conditions.\n"
740 "There is NO warranty; not even for MERCHANTABILITY or \n"
741 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
742 exit (SUCCESS_EXIT_CODE
);
745 static const struct option options
[] =
747 { "help", no_argument
, NULL
, 'h' },
748 { "version", no_argument
, NULL
, 'v' },
749 { "verbose", no_argument
, NULL
, 'w' },
750 { "all-blocks", no_argument
, NULL
, 'a' },
751 { "branch-probabilities", no_argument
, NULL
, 'b' },
752 { "branch-counts", no_argument
, NULL
, 'c' },
753 { "intermediate-format", no_argument
, NULL
, 'i' },
754 { "no-output", no_argument
, NULL
, 'n' },
755 { "long-file-names", no_argument
, NULL
, 'l' },
756 { "function-summaries", no_argument
, NULL
, 'f' },
757 { "demangled-names", no_argument
, NULL
, 'm' },
758 { "preserve-paths", no_argument
, NULL
, 'p' },
759 { "relative-only", no_argument
, NULL
, 'r' },
760 { "object-directory", required_argument
, NULL
, 'o' },
761 { "object-file", required_argument
, NULL
, 'o' },
762 { "source-prefix", required_argument
, NULL
, 's' },
763 { "unconditional-branches", no_argument
, NULL
, 'u' },
764 { "display-progress", no_argument
, NULL
, 'd' },
765 { "hash-filenames", no_argument
, NULL
, 'x' },
766 { "use-colors", no_argument
, NULL
, 'k' },
770 /* Process args, return index to first non-arg. */
773 process_args (int argc
, char **argv
)
777 const char *opts
= "abcdfhiklmno:prs:uvwx";
778 while ((opt
= getopt_long (argc
, argv
, opts
, options
, NULL
)) != -1)
792 flag_function_summary
= 1;
796 /* print_usage will exit. */
804 flag_demangled_names
= 1;
810 object_directory
= optarg
;
813 source_prefix
= optarg
;
814 source_length
= strlen (source_prefix
);
817 flag_relative_only
= 1;
820 flag_preserve_paths
= 1;
823 flag_unconditional
= 1;
826 flag_intermediate_format
= 1;
830 flag_display_progress
= 1;
833 flag_hash_filenames
= 1;
840 /* print_version will exit. */
843 /* print_usage will exit. */
850 /* Output the result in intermediate format used by 'lcov'.
852 The intermediate format contains a single file named 'foo.cc.gcov',
853 with no source code included. A sample output is
858 function:19,1,_GLOBAL__sub_I__Z3foov
859 function:19,1,_Z41__static_initialization_and_destruction_0ii
866 file:/.../basic_ios.h
869 function:157,0,_ZStorSt12_Ios_IostateS_
871 file:/.../char_traits.h
872 function:258,0,_ZNSt11char_traitsIcE6lengthEPKc
876 The default gcov outputs multiple files: 'foo.cc.gcov',
877 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
878 included. Instead the intermediate format here outputs only a single
879 file 'foo.cc.gcov' similar to the above example. */
882 output_intermediate_file (FILE *gcov_file
, source_t
*src
)
884 unsigned line_num
; /* current line number. */
885 const line_t
*line
; /* current line info ptr. */
886 function_t
*fn
; /* current function info ptr. */
888 fprintf (gcov_file
, "file:%s\n", src
->name
); /* source file name */
890 for (fn
= src
->functions
; fn
; fn
= fn
->next_file_fn
)
892 /* function:<name>,<line_number>,<execution_count> */
893 fprintf (gcov_file
, "function:%d,%s,%s\n", fn
->line
,
894 format_gcov (fn
->blocks
[0].count
, 0, -1),
895 flag_demangled_names
? fn
->demangled_name
: fn
->name
);
898 for (line_num
= 1, line
= &src
->lines
[line_num
];
899 line_num
< src
->num_lines
;
904 fprintf (gcov_file
, "lcount:%u,%s\n", line_num
,
905 format_gcov (line
->count
, 0, -1));
907 for (arc
= line
->branches
; arc
; arc
= arc
->line_next
)
909 if (!arc
->is_unconditional
&& !arc
->is_call_non_return
)
911 const char *branch_type
;
912 /* branch:<line_num>,<branch_coverage_type>
914 : notexec (Branch not executed)
915 : taken (Branch executed and taken)
916 : nottaken (Branch executed, but not taken)
919 branch_type
= (arc
->count
> 0) ? "taken" : "nottaken";
921 branch_type
= "notexec";
922 fprintf (gcov_file
, "branch:%d,%s\n", line_num
, branch_type
);
928 /* Process a single input file. */
931 process_file (const char *file_name
)
935 create_file_names (file_name
);
936 fns
= read_graph_file ();
940 read_count_file (fns
);
943 function_t
*fn
= fns
;
947 if (fn
->counts
|| no_data_file
)
949 unsigned src
= fn
->src
;
950 unsigned line
= fn
->line
;
952 function_t
*probe
, **prev
;
954 /* Now insert it into the source file's list of
955 functions. Normally functions will be encountered in
956 ascending order, so a simple scan is quick. Note we're
957 building this list in reverse order. */
958 for (prev
= &sources
[src
].functions
;
959 (probe
= *prev
); prev
= &probe
->next_file_fn
)
960 if (probe
->line
<= line
)
962 fn
->next_file_fn
= probe
;
965 /* Mark last line in files touched by function. */
966 for (block_no
= 0; block_no
!= fn
->blocks
.size (); block_no
++)
968 block_t
*block
= &fn
->blocks
[block_no
];
969 for (unsigned i
= 0; i
< block
->locations
.size (); i
++)
971 unsigned s
= block
->locations
[i
].source_file_idx
;
973 /* Sort lines of locations. */
974 sort (block
->locations
[i
].lines
.begin (),
975 block
->locations
[i
].lines
.end ());
977 if (!block
->locations
[i
].lines
.empty ())
980 = block
->locations
[i
].lines
.back () + 1;
981 if (last_line
> sources
[s
].num_lines
)
982 sources
[s
].num_lines
= last_line
;
987 solve_flow_graph (fn
);
989 find_exception_blocks (fn
);
994 /* The function was not in the executable -- some other
995 instance must have been selected. */
1001 output_gcov_file (const char *file_name
, source_t
*src
)
1003 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->coverage
.name
);
1005 if (src
->coverage
.lines
)
1007 FILE *gcov_file
= fopen (gcov_file_name
, "w");
1010 fnotice (stdout
, "Creating '%s'\n", gcov_file_name
);
1012 if (flag_intermediate_format
)
1013 output_intermediate_file (gcov_file
, src
);
1015 output_lines (gcov_file
, src
);
1016 if (ferror (gcov_file
))
1017 fnotice (stderr
, "Error writing output file '%s'\n", gcov_file_name
);
1021 fnotice (stderr
, "Could not open output file '%s'\n", gcov_file_name
);
1025 unlink (gcov_file_name
);
1026 fnotice (stdout
, "Removing '%s'\n", gcov_file_name
);
1028 free (gcov_file_name
);
1032 generate_results (const char *file_name
)
1038 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
1040 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
1042 for (fn
= functions
; fn
; fn
= fn
->next
)
1044 coverage_t coverage
;
1046 memset (&coverage
, 0, sizeof (coverage
));
1047 coverage
.name
= flag_demangled_names
? fn
->demangled_name
: fn
->name
;
1048 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
1049 if (flag_function_summary
)
1051 function_summary (&coverage
, "Function");
1052 fnotice (stdout
, "\n");
1058 name_map_t
*name_map
= (name_map_t
*)bsearch
1059 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
1061 file_name
= sources
[name_map
->src
].coverage
.name
;
1063 file_name
= canonicalize_name (file_name
);
1066 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
1068 if (flag_relative_only
)
1070 /* Ignore this source, if it is an absolute path (after
1071 source prefix removal). */
1072 char first
= src
->coverage
.name
[0];
1074 #if HAVE_DOS_BASED_FILE_SYSTEM
1075 if (first
&& src
->coverage
.name
[1] == ':')
1076 first
= src
->coverage
.name
[2];
1078 if (IS_DIR_SEPARATOR (first
))
1082 accumulate_line_counts (src
);
1083 function_summary (&src
->coverage
, "File");
1084 total_lines
+= src
->coverage
.lines
;
1085 total_executed
+= src
->coverage
.lines_executed
;
1088 output_gcov_file (file_name
, src
);
1089 fnotice (stdout
, "\n");
1094 executed_summary (total_lines
, total_executed
);
1097 /* Release all memory used. */
1100 release_structures (void)
1105 for (ix
= n_sources
; ix
--;)
1106 free (sources
[ix
].lines
);
1109 for (ix
= n_names
; ix
--;)
1110 free (names
[ix
].name
);
1113 while ((fn
= functions
))
1115 functions
= fn
->next
;
1120 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1121 is not specified, these are named from FILE_NAME sans extension. If
1122 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1123 directory, but named from the basename of the FILE_NAME, sans extension.
1124 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1125 and the data files are named from that. */
1128 create_file_names (const char *file_name
)
1132 int length
= strlen (file_name
);
1135 /* Free previous file names. */
1136 free (bbg_file_name
);
1137 free (da_file_name
);
1138 da_file_name
= bbg_file_name
= NULL
;
1142 if (object_directory
&& object_directory
[0])
1146 length
+= strlen (object_directory
) + 2;
1147 name
= XNEWVEC (char, length
);
1150 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
1151 strcat (name
, object_directory
);
1152 if (base
&& (!IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
1157 name
= XNEWVEC (char, length
+ 1);
1158 strcpy (name
, file_name
);
1164 /* Append source file name. */
1165 const char *cptr
= lbasename (file_name
);
1166 strcat (name
, cptr
? cptr
: file_name
);
1169 /* Remove the extension. */
1170 cptr
= strrchr (CONST_CAST (char *, lbasename (name
)), '.');
1174 length
= strlen (name
);
1176 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
1177 strcpy (bbg_file_name
, name
);
1178 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
1180 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
1181 strcpy (da_file_name
, name
);
1182 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
1188 /* A is a string and B is a pointer to name_map_t. Compare for file
1189 name orderability. */
1192 name_search (const void *a_
, const void *b_
)
1194 const char *a
= (const char *)a_
;
1195 const name_map_t
*b
= (const name_map_t
*)b_
;
1197 #if HAVE_DOS_BASED_FILE_SYSTEM
1198 return strcasecmp (a
, b
->name
);
1200 return strcmp (a
, b
->name
);
1204 /* A and B are a pointer to name_map_t. Compare for file name
1208 name_sort (const void *a_
, const void *b_
)
1210 const name_map_t
*a
= (const name_map_t
*)a_
;
1211 return name_search (a
->name
, b_
);
1214 /* Find or create a source file structure for FILE_NAME. Copies
1215 FILE_NAME on creation */
1218 find_source (const char *file_name
)
1220 name_map_t
*name_map
;
1226 file_name
= "<unknown>";
1227 name_map
= (name_map_t
*)bsearch
1228 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
1231 idx
= name_map
->src
;
1235 if (n_names
+ 2 > a_names
)
1237 /* Extend the name map array -- we'll be inserting one or two
1240 name_map
= XNEWVEC (name_map_t
, a_names
);
1241 memcpy (name_map
, names
, n_names
* sizeof (*names
));
1246 /* Not found, try the canonical name. */
1247 canon
= canonicalize_name (file_name
);
1248 name_map
= (name_map_t
*) bsearch (canon
, names
, n_names
, sizeof (*names
),
1252 /* Not found with canonical name, create a new source. */
1255 if (n_sources
== a_sources
)
1258 src
= XNEWVEC (source_t
, a_sources
);
1259 memcpy (src
, sources
, n_sources
* sizeof (*sources
));
1266 name_map
= &names
[n_names
++];
1267 name_map
->name
= canon
;
1268 name_map
->src
= idx
;
1270 src
= &sources
[n_sources
++];
1271 memset (src
, 0, sizeof (*src
));
1273 src
->coverage
.name
= src
->name
;
1275 #if HAVE_DOS_BASED_FILE_SYSTEM
1276 /* You lose if separators don't match exactly in the
1278 && !strncasecmp (source_prefix
, src
->coverage
.name
, source_length
)
1280 && !strncmp (source_prefix
, src
->coverage
.name
, source_length
)
1282 && IS_DIR_SEPARATOR (src
->coverage
.name
[source_length
]))
1283 src
->coverage
.name
+= source_length
+ 1;
1284 if (!stat (src
->name
, &status
))
1285 src
->file_time
= status
.st_mtime
;
1288 idx
= name_map
->src
;
1290 if (name_search (file_name
, name_map
))
1292 /* Append the non-canonical name. */
1293 name_map
= &names
[n_names
++];
1294 name_map
->name
= xstrdup (file_name
);
1295 name_map
->src
= idx
;
1298 /* Resort the name map. */
1299 qsort (names
, n_names
, sizeof (*names
), name_sort
);
1302 if (sources
[idx
].file_time
> bbg_file_time
)
1304 static int info_emitted
;
1306 fnotice (stderr
, "%s:source file is newer than notes file '%s'\n",
1307 file_name
, bbg_file_name
);
1311 "(the message is displayed only once per source file)\n");
1314 sources
[idx
].file_time
= 0;
1320 /* Read the notes file. Return list of functions read -- in reverse order. */
1323 read_graph_file (void)
1326 unsigned current_tag
= 0;
1327 function_t
*fn
= NULL
;
1328 function_t
*fns
= NULL
;
1329 function_t
**fns_end
= &fns
;
1332 if (!gcov_open (bbg_file_name
, 1))
1334 fnotice (stderr
, "%s:cannot open notes file\n", bbg_file_name
);
1337 bbg_file_time
= gcov_time ();
1338 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
1340 fnotice (stderr
, "%s:not a gcov notes file\n", bbg_file_name
);
1345 version
= gcov_read_unsigned ();
1346 if (version
!= GCOV_VERSION
)
1350 GCOV_UNSIGNED2STRING (v
, version
);
1351 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1353 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
1354 bbg_file_name
, v
, e
);
1356 bbg_stamp
= gcov_read_unsigned ();
1358 while ((tag
= gcov_read_unsigned ()))
1360 unsigned length
= gcov_read_unsigned ();
1361 gcov_position_t base
= gcov_position ();
1363 if (tag
== GCOV_TAG_FUNCTION
)
1365 char *function_name
;
1366 unsigned ident
, lineno
;
1367 unsigned lineno_checksum
, cfg_checksum
;
1369 ident
= gcov_read_unsigned ();
1370 lineno_checksum
= gcov_read_unsigned ();
1371 cfg_checksum
= gcov_read_unsigned ();
1372 function_name
= xstrdup (gcov_read_string ());
1373 unsigned src_idx
= find_source (gcov_read_string ());
1374 lineno
= gcov_read_unsigned ();
1376 fn
= new function_t
;
1377 fn
->name
= function_name
;
1378 if (flag_demangled_names
)
1380 fn
->demangled_name
= cplus_demangle (fn
->name
, DMGL_PARAMS
);
1381 if (!fn
->demangled_name
)
1382 fn
->demangled_name
= fn
->name
;
1385 fn
->lineno_checksum
= lineno_checksum
;
1386 fn
->cfg_checksum
= cfg_checksum
;
1390 fn
->next_file_fn
= NULL
;
1393 fns_end
= &fn
->next
;
1396 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
1398 if (!fn
->blocks
.empty ())
1399 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
1400 bbg_file_name
, fn
->name
);
1402 fn
->blocks
.resize (gcov_read_unsigned ());
1404 else if (fn
&& tag
== GCOV_TAG_ARCS
)
1406 unsigned src
= gcov_read_unsigned ();
1407 fn
->blocks
[src
].id
= src
;
1408 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
1409 block_t
*src_blk
= &fn
->blocks
[src
];
1410 unsigned mark_catches
= 0;
1411 struct arc_info
*arc
;
1413 if (src
>= fn
->blocks
.size () || fn
->blocks
[src
].succ
)
1418 unsigned dest
= gcov_read_unsigned ();
1419 unsigned flags
= gcov_read_unsigned ();
1421 if (dest
>= fn
->blocks
.size ())
1423 arc
= XCNEW (arc_t
);
1425 arc
->dst
= &fn
->blocks
[dest
];
1429 arc
->count_valid
= 0;
1430 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
1431 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
1432 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
1434 arc
->succ_next
= src_blk
->succ
;
1435 src_blk
->succ
= arc
;
1436 src_blk
->num_succ
++;
1438 arc
->pred_next
= fn
->blocks
[dest
].pred
;
1439 fn
->blocks
[dest
].pred
= arc
;
1440 fn
->blocks
[dest
].num_pred
++;
1446 /* Exceptional exit from this function, the
1447 source block must be a call. */
1448 fn
->blocks
[src
].is_call_site
= 1;
1449 arc
->is_call_non_return
= 1;
1454 /* Non-local return from a callee of this
1455 function. The destination block is a setjmp. */
1456 arc
->is_nonlocal_return
= 1;
1457 fn
->blocks
[dest
].is_nonlocal_return
= 1;
1467 /* We have a fake exit from this block. The other
1468 non-fall through exits must be to catch handlers.
1469 Mark them as catch arcs. */
1471 for (arc
= src_blk
->succ
; arc
; arc
= arc
->succ_next
)
1472 if (!arc
->fake
&& !arc
->fall_through
)
1479 else if (fn
&& tag
== GCOV_TAG_LINES
)
1481 unsigned blockno
= gcov_read_unsigned ();
1482 block_t
*block
= &fn
->blocks
[blockno
];
1484 if (blockno
>= fn
->blocks
.size ())
1489 unsigned lineno
= gcov_read_unsigned ();
1492 block
->locations
.back ().lines
.push_back (lineno
);
1495 const char *file_name
= gcov_read_string ();
1499 block
->locations
.push_back (block_location_info
1500 (find_source (file_name
)));
1504 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
1509 gcov_sync (base
, length
);
1510 if (gcov_is_error ())
1513 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
1520 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
1525 /* Reads profiles from the count file and attach to each
1526 function. Return nonzero if fatal error. */
1529 read_count_file (function_t
*fns
)
1534 function_t
*fn
= NULL
;
1537 if (!gcov_open (da_file_name
, 1))
1539 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1544 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1546 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1551 version
= gcov_read_unsigned ();
1552 if (version
!= GCOV_VERSION
)
1556 GCOV_UNSIGNED2STRING (v
, version
);
1557 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1559 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1560 da_file_name
, v
, e
);
1562 tag
= gcov_read_unsigned ();
1563 if (tag
!= bbg_stamp
)
1565 fnotice (stderr
, "%s:stamp mismatch with notes file\n", da_file_name
);
1569 while ((tag
= gcov_read_unsigned ()))
1571 unsigned length
= gcov_read_unsigned ();
1572 unsigned long base
= gcov_position ();
1574 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1576 struct gcov_summary summary
;
1577 gcov_read_summary (&summary
);
1578 object_runs
+= summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
;
1581 else if (tag
== GCOV_TAG_FUNCTION
&& !length
)
1583 else if (tag
== GCOV_TAG_FUNCTION
&& length
== GCOV_TAG_FUNCTION_LENGTH
)
1586 struct function_info
*fn_n
;
1588 /* Try to find the function in the list. To speed up the
1589 search, first start from the last function found. */
1590 ident
= gcov_read_unsigned ();
1592 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1596 else if ((fn
= fn_n
))
1600 fnotice (stderr
, "%s:unknown function '%u'\n",
1601 da_file_name
, ident
);
1604 if (fn
->ident
== ident
)
1610 else if (gcov_read_unsigned () != fn
->lineno_checksum
1611 || gcov_read_unsigned () != fn
->cfg_checksum
)
1614 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1615 da_file_name
, fn
->name
);
1619 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1621 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1625 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1627 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1628 fn
->counts
[ix
] += gcov_read_counter ();
1630 gcov_sync (base
, length
);
1631 if ((error
= gcov_is_error ()))
1635 ? N_("%s:overflowed\n")
1636 : N_("%s:corrupted\n"),
1646 /* Solve the flow graph. Propagate counts from the instrumented arcs
1647 to the blocks and the uninstrumented arcs. */
1650 solve_flow_graph (function_t
*fn
)
1654 gcov_type
*count_ptr
= fn
->counts
;
1656 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1657 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1659 /* The arcs were built in reverse order. Fix that now. */
1660 for (ix
= fn
->blocks
.size (); ix
--;)
1662 arc_t
*arc_p
, *arc_n
;
1664 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1665 arc_p
= arc
, arc
= arc_n
)
1667 arc_n
= arc
->succ_next
;
1668 arc
->succ_next
= arc_p
;
1670 fn
->blocks
[ix
].succ
= arc_p
;
1672 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1673 arc_p
= arc
, arc
= arc_n
)
1675 arc_n
= arc
->pred_next
;
1676 arc
->pred_next
= arc_p
;
1678 fn
->blocks
[ix
].pred
= arc_p
;
1681 if (fn
->blocks
.size () < 2)
1682 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1683 bbg_file_name
, fn
->name
);
1686 if (fn
->blocks
[ENTRY_BLOCK
].num_pred
)
1687 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1688 bbg_file_name
, fn
->name
);
1690 /* We can't deduce the entry block counts from the lack of
1692 fn
->blocks
[ENTRY_BLOCK
].num_pred
= ~(unsigned)0;
1694 if (fn
->blocks
[EXIT_BLOCK
].num_succ
)
1695 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1696 bbg_file_name
, fn
->name
);
1698 /* Likewise, we can't deduce exit block counts from the lack
1699 of its successors. */
1700 fn
->blocks
[EXIT_BLOCK
].num_succ
= ~(unsigned)0;
1703 /* Propagate the measured counts, this must be done in the same
1704 order as the code in profile.c */
1705 for (unsigned i
= 0; i
< fn
->blocks
.size (); i
++)
1707 blk
= &fn
->blocks
[i
];
1708 block_t
const *prev_dst
= NULL
;
1709 int out_of_order
= 0;
1710 int non_fake_succ
= 0;
1712 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1720 arc
->count
= *count_ptr
++;
1721 arc
->count_valid
= 1;
1723 arc
->dst
->num_pred
--;
1725 if (prev_dst
&& prev_dst
> arc
->dst
)
1727 prev_dst
= arc
->dst
;
1729 if (non_fake_succ
== 1)
1731 /* If there is only one non-fake exit, it is an
1732 unconditional branch. */
1733 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1736 arc
->is_unconditional
= 1;
1737 /* If this block is instrumenting a call, it might be
1738 an artificial block. It is not artificial if it has
1739 a non-fallthrough exit, or the destination of this
1740 arc has more than one entry. Mark the destination
1741 block as a return site, if none of those conditions
1743 if (blk
->is_call_site
&& arc
->fall_through
1744 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1745 arc
->dst
->is_call_return
= 1;
1749 /* Sort the successor arcs into ascending dst order. profile.c
1750 normally produces arcs in the right order, but sometimes with
1751 one or two out of order. We're not using a particularly
1755 arc_t
*start
= blk
->succ
;
1756 unsigned changes
= 1;
1760 arc_t
*arc
, *arc_p
, *arc_n
;
1763 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1765 if (arc
->dst
> arc_n
->dst
)
1769 arc_p
->succ_next
= arc_n
;
1772 arc
->succ_next
= arc_n
->succ_next
;
1773 arc_n
->succ_next
= arc
;
1786 /* Place it on the invalid chain, it will be ignored if that's
1788 blk
->invalid_chain
= 1;
1789 blk
->chain
= invalid_blocks
;
1790 invalid_blocks
= blk
;
1793 while (invalid_blocks
|| valid_blocks
)
1795 while ((blk
= invalid_blocks
))
1797 gcov_type total
= 0;
1800 invalid_blocks
= blk
->chain
;
1801 blk
->invalid_chain
= 0;
1803 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1804 total
+= arc
->count
;
1805 else if (!blk
->num_pred
)
1806 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1807 total
+= arc
->count
;
1812 blk
->count_valid
= 1;
1813 blk
->chain
= valid_blocks
;
1814 blk
->valid_chain
= 1;
1817 while ((blk
= valid_blocks
))
1820 arc_t
*arc
, *inv_arc
;
1822 valid_blocks
= blk
->chain
;
1823 blk
->valid_chain
= 0;
1824 if (blk
->num_succ
== 1)
1830 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1832 total
-= arc
->count
;
1833 if (!arc
->count_valid
)
1837 inv_arc
->count_valid
= 1;
1838 inv_arc
->count
= total
;
1841 if (dst
->count_valid
)
1843 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1845 dst
->chain
= valid_blocks
;
1846 dst
->valid_chain
= 1;
1852 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1854 dst
->chain
= invalid_blocks
;
1855 dst
->invalid_chain
= 1;
1856 invalid_blocks
= dst
;
1860 if (blk
->num_pred
== 1)
1866 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1868 total
-= arc
->count
;
1869 if (!arc
->count_valid
)
1873 inv_arc
->count_valid
= 1;
1874 inv_arc
->count
= total
;
1877 if (src
->count_valid
)
1879 if (src
->num_succ
== 1 && !src
->valid_chain
)
1881 src
->chain
= valid_blocks
;
1882 src
->valid_chain
= 1;
1888 if (!src
->num_succ
&& !src
->invalid_chain
)
1890 src
->chain
= invalid_blocks
;
1891 src
->invalid_chain
= 1;
1892 invalid_blocks
= src
;
1899 /* If the graph has been correctly solved, every block will have a
1901 for (unsigned i
= 0; ix
< fn
->blocks
.size (); i
++)
1902 if (!fn
->blocks
[i
].count_valid
)
1904 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1905 bbg_file_name
, fn
->name
);
1910 /* Mark all the blocks only reachable via an incoming catch. */
1913 find_exception_blocks (function_t
*fn
)
1916 block_t
**queue
= XALLOCAVEC (block_t
*, fn
->blocks
.size ());
1918 /* First mark all blocks as exceptional. */
1919 for (ix
= fn
->blocks
.size (); ix
--;)
1920 fn
->blocks
[ix
].exceptional
= 1;
1922 /* Now mark all the blocks reachable via non-fake edges */
1923 queue
[0] = &fn
->blocks
[0];
1924 queue
[0]->exceptional
= 0;
1927 block_t
*block
= queue
[--ix
];
1930 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1931 if (!arc
->fake
&& !arc
->is_throw
&& arc
->dst
->exceptional
)
1933 arc
->dst
->exceptional
= 0;
1934 queue
[ix
++] = arc
->dst
;
1940 /* Increment totals in COVERAGE according to arc ARC. */
1943 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1945 if (arc
->is_call_non_return
)
1948 if (arc
->src
->count
)
1949 coverage
->calls_executed
++;
1951 else if (!arc
->is_unconditional
)
1953 coverage
->branches
++;
1954 if (arc
->src
->count
)
1955 coverage
->branches_executed
++;
1957 coverage
->branches_taken
++;
1961 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1962 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1963 If DP is zero, no decimal point is printed. Only print 100% when
1964 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1965 format TOP. Return pointer to a static string. */
1968 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1970 static char buffer
[20];
1972 /* Handle invalid values that would result in a misleading value. */
1973 if (bottom
!= 0 && top
> bottom
&& dp
>= 0)
1975 sprintf (buffer
, "NAN %%");
1981 float ratio
= bottom
? (float)top
/ bottom
: 0;
1983 unsigned limit
= 100;
1986 for (ix
= dp
; ix
--; )
1989 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1990 if (percent
<= 0 && top
)
1992 else if (percent
>= limit
&& top
!= bottom
)
1993 percent
= limit
- 1;
1994 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
2000 buffer
[ix
+1] = buffer
[ix
];
2004 buffer
[ix
+ 1] = '.';
2008 sprintf (buffer
, "%" PRId64
, (int64_t)top
);
2013 /* Summary of execution */
2016 executed_summary (unsigned lines
, unsigned executed
)
2019 fnotice (stdout
, "Lines executed:%s of %d\n",
2020 format_gcov (executed
, lines
, 2), lines
);
2022 fnotice (stdout
, "No executable lines\n");
2025 /* Output summary info for a function or file. */
2028 function_summary (const coverage_t
*coverage
, const char *title
)
2030 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
2031 executed_summary (coverage
->lines
, coverage
->lines_executed
);
2035 if (coverage
->branches
)
2037 fnotice (stdout
, "Branches executed:%s of %d\n",
2038 format_gcov (coverage
->branches_executed
,
2039 coverage
->branches
, 2),
2040 coverage
->branches
);
2041 fnotice (stdout
, "Taken at least once:%s of %d\n",
2042 format_gcov (coverage
->branches_taken
,
2043 coverage
->branches
, 2),
2044 coverage
->branches
);
2047 fnotice (stdout
, "No branches\n");
2048 if (coverage
->calls
)
2049 fnotice (stdout
, "Calls executed:%s of %d\n",
2050 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
2053 fnotice (stdout
, "No calls\n");
2057 /* Canonicalize the filename NAME by canonicalizing directory
2058 separators, eliding . components and resolving .. components
2059 appropriately. Always returns a unique string. */
2062 canonicalize_name (const char *name
)
2064 /* The canonical name cannot be longer than the incoming name. */
2065 char *result
= XNEWVEC (char, strlen (name
) + 1);
2066 const char *base
= name
, *probe
;
2071 #if HAVE_DOS_BASED_FILE_SYSTEM
2072 if (base
[0] && base
[1] == ':')
2074 result
[0] = base
[0];
2080 for (dd_base
= ptr
; *base
; base
= probe
)
2084 for (probe
= base
; *probe
; probe
++)
2085 if (IS_DIR_SEPARATOR (*probe
))
2089 if (len
== 1 && base
[0] == '.')
2090 /* Elide a '.' directory */
2092 else if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2094 /* '..', we can only elide it and the previous directory, if
2095 we're not a symlink. */
2096 struct stat ATTRIBUTE_UNUSED buf
;
2100 #if defined (S_ISLNK)
2101 /* S_ISLNK is not POSIX.1-1996. */
2102 || stat (result
, &buf
) || S_ISLNK (buf
.st_mode
)
2106 /* Cannot elide, or unreadable or a symlink. */
2107 dd_base
= ptr
+ 2 + slash
;
2110 while (ptr
!= dd_base
&& *ptr
!= '/')
2112 slash
= ptr
!= result
;
2117 /* Regular pathname component. */
2120 memcpy (ptr
, base
, len
);
2125 for (; IS_DIR_SEPARATOR (*probe
); probe
++)
2133 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2136 md5sum_to_hex (const char *sum
, char *buffer
)
2138 for (unsigned i
= 0; i
< 16; i
++)
2139 sprintf (buffer
+ (2 * i
), "%02x", (unsigned char)sum
[i
]);
2142 /* Generate an output file name. INPUT_NAME is the canonicalized main
2143 input file and SRC_NAME is the canonicalized file name.
2144 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2145 long_output_names we prepend the processed name of the input file
2146 to each output name (except when the current source file is the
2147 input file, so you don't get a double concatenation). The two
2148 components are separated by '##'. With preserve_paths we create a
2149 filename from all path components of the source file, replacing '/'
2150 with '#', and .. with '^', without it we simply take the basename
2151 component. (Remember, the canonicalized name will already have
2152 elided '.' components and converted \\ separators.) */
2155 make_gcov_file_name (const char *input_name
, const char *src_name
)
2160 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
2162 /* Generate the input filename part. */
2163 result
= XNEWVEC (char, strlen (input_name
) + strlen (src_name
) + 10);
2166 ptr
= mangle_name (input_name
, ptr
);
2167 ptr
[0] = ptr
[1] = '#';
2172 result
= XNEWVEC (char, strlen (src_name
) + 10);
2176 ptr
= mangle_name (src_name
, ptr
);
2177 strcpy (ptr
, ".gcov");
2179 /* When hashing filenames, we shorten them by only using the filename
2180 component and appending a hash of the full (mangled) pathname. */
2181 if (flag_hash_filenames
)
2185 char md5sum_hex
[33];
2187 md5_init_ctx (&ctx
);
2188 md5_process_bytes (src_name
, strlen (src_name
), &ctx
);
2189 md5_finish_ctx (&ctx
, md5sum
);
2190 md5sum_to_hex (md5sum
, md5sum_hex
);
2193 result
= XNEWVEC (char, strlen (src_name
) + 50);
2195 ptr
= mangle_name (src_name
, ptr
);
2196 ptr
[0] = ptr
[1] = '#';
2198 memcpy (ptr
, md5sum_hex
, 32);
2200 strcpy (ptr
, ".gcov");
2207 mangle_name (char const *base
, char *ptr
)
2211 /* Generate the source filename part. */
2212 if (!flag_preserve_paths
)
2214 base
= lbasename (base
);
2215 len
= strlen (base
);
2216 memcpy (ptr
, base
, len
);
2221 /* Convert '/' to '#', convert '..' to '^',
2222 convert ':' to '~' on DOS based file system. */
2225 #if HAVE_DOS_BASED_FILE_SYSTEM
2226 if (base
[0] && base
[1] == ':')
2234 for (; *base
; base
= probe
)
2238 for (probe
= base
; *probe
; probe
++)
2242 if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2246 memcpy (ptr
, base
, len
);
2260 /* Scan through the bb_data for each line in the block, increment
2261 the line number execution count indicated by the execution count of
2262 the appropriate basic block. */
2265 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
2267 bool has_any_line
= false;
2268 /* Scan each basic block. */
2269 for (unsigned ix
= 0; ix
!= fn
->blocks
.size (); ix
++)
2271 line_t
*line
= NULL
;
2272 block_t
*block
= &fn
->blocks
[ix
];
2273 if (block
->count
&& ix
&& ix
+ 1 != fn
->blocks
.size ())
2274 fn
->blocks_executed
++;
2275 for (unsigned i
= 0; i
< block
->locations
.size (); i
++)
2277 const source_t
*src
= &sources
[block
->locations
[i
].source_file_idx
];
2279 vector
<unsigned> &lines
= block
->locations
[i
].lines
;
2280 for (unsigned j
= 0; j
< lines
.size (); j
++)
2282 line
= &src
->lines
[lines
[j
]];
2287 if (!line
->count
&& block
->count
)
2288 coverage
->lines_executed
++;
2291 if (!block
->exceptional
)
2292 line
->unexceptional
= 1;
2293 line
->count
+= block
->count
;
2296 block
->cycle
.arc
= NULL
;
2297 block
->cycle
.ident
= ~0U;
2298 has_any_line
= true;
2300 if (!ix
|| ix
+ 1 == fn
->blocks
.size ())
2301 /* Entry or exit block */;
2302 else if (line
!= NULL
)
2304 block
->chain
= line
->blocks
;
2305 line
->blocks
= block
;
2311 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2313 arc
->line_next
= line
->branches
;
2314 line
->branches
= arc
;
2315 if (coverage
&& !arc
->is_unconditional
)
2316 add_branch_counts (coverage
, arc
);
2323 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
2326 /* Accumulate the line counts of a file. */
2329 accumulate_line_counts (source_t
*src
)
2332 function_t
*fn
, *fn_p
, *fn_n
;
2335 /* Reverse the function order. */
2336 for (fn
= src
->functions
, fn_p
= NULL
; fn
; fn_p
= fn
, fn
= fn_n
)
2338 fn_n
= fn
->next_file_fn
;
2339 fn
->next_file_fn
= fn_p
;
2341 src
->functions
= fn_p
;
2343 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
2347 /* The user expects the line count to be the number of times
2348 a line has been executed. Simply summing the block count
2349 will give an artificially high number. The Right Thing
2350 is to sum the entry counts to the graph of blocks on this
2351 line, then find the elementary cycles of the local graph
2352 and add the transition counts of those cycles. */
2353 block_t
*block
, *block_p
, *block_n
;
2354 gcov_type count
= 0;
2356 /* Reverse the block information. */
2357 for (block
= line
->blocks
, block_p
= NULL
; block
;
2358 block_p
= block
, block
= block_n
)
2360 block_n
= block
->chain
;
2361 block
->chain
= block_p
;
2362 block
->cycle
.ident
= ix
;
2364 line
->blocks
= block_p
;
2366 /* Sum the entry arcs. */
2367 for (block
= line
->blocks
; block
; block
= block
->chain
)
2371 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2373 add_branch_counts (&src
->coverage
, arc
);
2376 /* Cycle detection. */
2377 for (block
= line
->blocks
; block
; block
= block
->chain
)
2379 for (arc_t
*arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2380 if (!line
->has_block (arc
->src
))
2381 count
+= arc
->count
;
2382 for (arc_t
*arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2383 arc
->cs_count
= arc
->count
;
2386 /* Now, add the count of loops entirely on this line. */
2387 count
+= get_cycles_count (*line
);
2388 line
->count
= count
;
2393 src
->coverage
.lines
++;
2395 src
->coverage
.lines_executed
++;
2400 /* Output information about ARC number IX. Returns nonzero if
2401 anything is output. */
2404 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
2406 if (arc
->is_call_non_return
)
2408 if (arc
->src
->count
)
2410 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
2411 format_gcov (arc
->src
->count
- arc
->count
,
2412 arc
->src
->count
, -flag_counts
));
2415 fnotice (gcov_file
, "call %2d never executed\n", ix
);
2417 else if (!arc
->is_unconditional
)
2419 if (arc
->src
->count
)
2420 fnotice (gcov_file
, "branch %2d taken %s%s", ix
,
2421 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
2422 arc
->fall_through
? " (fallthrough)"
2423 : arc
->is_throw
? " (throw)" : "");
2425 fnotice (gcov_file
, "branch %2d never executed", ix
);
2428 fnotice (gcov_file
, " (BB %d)", arc
->dst
->id
);
2430 fnotice (gcov_file
, "\n");
2432 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
2434 if (arc
->src
->count
)
2435 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
2436 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
2438 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
2446 read_line (FILE *file
)
2448 static char *string
;
2449 static size_t string_len
;
2456 string
= XNEWVEC (char, string_len
);
2459 while ((ptr
= fgets (string
+ pos
, string_len
- pos
, file
)))
2461 size_t len
= strlen (string
+ pos
);
2463 if (len
&& string
[pos
+ len
- 1] == '\n')
2465 string
[pos
+ len
- 1] = 0;
2469 /* If the file contains NUL characters or an incomplete
2470 last line, which can happen more than once in one run,
2471 we have to avoid doubling the STRING_LEN unnecessarily. */
2472 if (pos
> string_len
/ 2)
2475 string
= XRESIZEVEC (char, string
, string_len
);
2479 return pos
? string
: NULL
;
2482 /* Pad string S with spaces from left to have total width equal to 9. */
2485 pad_count_string (string
&s
)
2488 s
.insert (0, 9 - s
.size (), ' ');
2491 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2492 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2493 an exceptional statement. The output is printed for LINE_NUM of given
2494 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2495 used to indicate non-executed blocks. */
2498 output_line_beginning (FILE *f
, bool exists
, bool unexceptional
,
2499 gcov_type count
, unsigned line_num
,
2500 const char *exceptional_string
,
2501 const char *unexceptional_string
)
2508 s
= format_gcov (count
, 0, -1);
2509 pad_count_string (s
);
2513 if (flag_use_colors
)
2516 pad_count_string (s
);
2518 s
.insert (0, SGR_SEQ (COLOR_BG_RED
2519 COLOR_SEPARATOR COLOR_FG_WHITE
));
2521 s
.insert (0, SGR_SEQ (COLOR_BG_CYAN
2522 COLOR_SEPARATOR COLOR_FG_WHITE
));
2527 s
= unexceptional
? unexceptional_string
: exceptional_string
;
2528 pad_count_string (s
);
2535 pad_count_string (s
);
2538 fprintf (f
, "%s:%5u", s
.c_str (), line_num
);
2541 /* Read in the source file one line at a time, and output that line to
2542 the gcov file preceded by its execution count and other
2546 output_lines (FILE *gcov_file
, const source_t
*src
)
2548 #define DEFAULT_LINE_START " -: 0:"
2551 unsigned line_num
; /* current line number. */
2552 const line_t
*line
; /* current line info ptr. */
2553 const char *retval
= ""; /* status of source file reading. */
2554 function_t
*fn
= NULL
;
2556 fprintf (gcov_file
, DEFAULT_LINE_START
"Source:%s\n", src
->coverage
.name
);
2557 if (!multiple_files
)
2559 fprintf (gcov_file
, DEFAULT_LINE_START
"Graph:%s\n", bbg_file_name
);
2560 fprintf (gcov_file
, DEFAULT_LINE_START
"Data:%s\n",
2561 no_data_file
? "-" : da_file_name
);
2562 fprintf (gcov_file
, DEFAULT_LINE_START
"Runs:%u\n", object_runs
);
2564 fprintf (gcov_file
, DEFAULT_LINE_START
"Programs:%u\n", program_count
);
2566 source_file
= fopen (src
->name
, "r");
2569 fnotice (stderr
, "Cannot open source file %s\n", src
->name
);
2572 else if (src
->file_time
== 0)
2573 fprintf (gcov_file
, DEFAULT_LINE_START
"Source is newer than graph\n");
2576 fn
= src
->functions
;
2578 for (line_num
= 1, line
= &src
->lines
[line_num
];
2579 line_num
< src
->num_lines
; line_num
++, line
++)
2581 for (; fn
&& fn
->line
== line_num
; fn
= fn
->next_file_fn
)
2583 arc_t
*arc
= fn
->blocks
[EXIT_BLOCK
].pred
;
2584 gcov_type return_count
= fn
->blocks
[EXIT_BLOCK
].count
;
2585 gcov_type called_count
= fn
->blocks
[ENTRY_BLOCK
].count
;
2587 for (; arc
; arc
= arc
->pred_next
)
2589 return_count
-= arc
->count
;
2591 fprintf (gcov_file
, "function %s", flag_demangled_names
?
2592 fn
->demangled_name
: fn
->name
);
2593 fprintf (gcov_file
, " called %s",
2594 format_gcov (called_count
, 0, -1));
2595 fprintf (gcov_file
, " returned %s",
2596 format_gcov (return_count
, called_count
, 0));
2597 fprintf (gcov_file
, " blocks executed %s",
2598 format_gcov (fn
->blocks_executed
, fn
->blocks
.size () - 2,
2600 fprintf (gcov_file
, "\n");
2604 retval
= read_line (source_file
);
2606 /* For lines which don't exist in the .bb file, print '-' before
2607 the source line. For lines which exist but were never
2608 executed, print '#####' or '=====' before the source line.
2609 Otherwise, print the execution count before the source line.
2610 There are 16 spaces of indentation added before the source
2611 line so that tabs won't be messed up. */
2612 output_line_beginning (gcov_file
, line
->exists
, line
->unexceptional
,
2613 line
->count
, line_num
,
2615 fprintf (gcov_file
, ":%s\n", retval
? retval
: "/*EOF*/");
2617 if (flag_all_blocks
)
2623 for (ix
= jx
= 0, block
= line
->blocks
; block
;
2624 block
= block
->chain
)
2626 if (!block
->is_call_return
)
2628 output_line_beginning (gcov_file
, line
->exists
,
2630 block
->count
, line_num
,
2632 fprintf (gcov_file
, "-block %2d", ix
++);
2634 fprintf (gcov_file
, " (BB %u)", block
->id
);
2635 fprintf (gcov_file
, "\n");
2638 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2639 jx
+= output_branch_count (gcov_file
, jx
, arc
);
2642 else if (flag_branches
)
2647 for (ix
= 0, arc
= line
->branches
; arc
; arc
= arc
->line_next
)
2648 ix
+= output_branch_count (gcov_file
, ix
, arc
);
2652 /* Handle all remaining source lines. There may be lines after the
2653 last line of code. */
2656 for (; (retval
= read_line (source_file
)); line_num
++)
2657 fprintf (gcov_file
, "%9s:%5u:%s\n", "-", line_num
, retval
);
2661 fclose (source_file
);