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
37 #include "coretypes.h"
40 #include "diagnostic.h"
54 /* The gcno file is generated by -ftest-coverage option. The gcda file is
55 generated by a program compiled with -fprofile-arcs. Their formats
56 are documented in gcov-io.h. */
58 /* The functions in this file for creating and solution program flow graphs
59 are very similar to functions in the gcc source file profile.c. In
60 some places we make use of the knowledge of how profile.c works to
61 select particular algorithms here. */
63 /* The code validates that the profile information read in corresponds
64 to the code currently being compiled. Rather than checking for
65 identical files, the code below compares a checksum on the CFG
66 (based on the order of basic blocks and the arcs in the CFG). If
67 the CFG checksum in the gcda file match the CFG checksum in the
68 gcno file, the profile data will be used. */
70 /* This is the size of the buffer used to read in source file lines. */
76 /* Describes an arc between two basic blocks. */
78 typedef struct arc_info
80 /* source and destination blocks. */
81 struct block_info
*src
;
82 struct block_info
*dst
;
84 /* transition counts. */
86 /* used in cycle search, so that we do not clobber original counts. */
89 unsigned int count_valid
: 1;
90 unsigned int on_tree
: 1;
91 unsigned int fake
: 1;
92 unsigned int fall_through
: 1;
94 /* Arc to a catch handler. */
95 unsigned int is_throw
: 1;
97 /* Arc is for a function that abnormally returns. */
98 unsigned int is_call_non_return
: 1;
100 /* Arc is for catch/setjmp. */
101 unsigned int is_nonlocal_return
: 1;
103 /* Is an unconditional branch. */
104 unsigned int is_unconditional
: 1;
106 /* Loop making arc. */
107 unsigned int cycle
: 1;
109 /* Next branch on line. */
110 struct arc_info
*line_next
;
112 /* Links to next arc on src and dst lists. */
113 struct arc_info
*succ_next
;
114 struct arc_info
*pred_next
;
117 /* Describes a basic block. Contains lists of arcs to successor and
118 predecessor blocks. */
120 typedef struct block_info
122 /* Chain of exit and entry arcs. */
126 /* Number of unprocessed exit and entry arcs. */
130 /* Block execution count. */
133 unsigned count_valid
: 1;
134 unsigned valid_chain
: 1;
135 unsigned invalid_chain
: 1;
136 unsigned exceptional
: 1;
138 /* Block is a call instrumenting site. */
139 unsigned is_call_site
: 1; /* Does the call. */
140 unsigned is_call_return
: 1; /* Is the return. */
142 /* Block is a landing pad for longjmp or throw. */
143 unsigned is_nonlocal_return
: 1;
149 /* Array of line numbers and source files. source files are
150 introduced by a linenumber of zero, the next 'line number' is
151 the number of the source file. Always starts with a source
155 } line
; /* Valid until blocks are linked onto lines */
158 /* Single line graph cycle workspace. Used for all-blocks
162 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
166 /* Temporary chain for solving graph, and for chaining blocks on one
168 struct block_info
*chain
;
172 /* Describes a single function. Contains an array of basic blocks. */
174 typedef struct function_info
176 /* Name of function. */
178 char *demangled_name
;
180 unsigned lineno_checksum
;
181 unsigned cfg_checksum
;
183 /* The graph contains at least one fake incoming edge. */
184 unsigned has_catch
: 1;
186 /* Array of basic blocks. Like in GCC, the entry block is
187 at blocks[0] and the exit block is at blocks[1]. */
188 #define ENTRY_BLOCK (0)
189 #define EXIT_BLOCK (1)
192 unsigned blocks_executed
;
194 /* Raw arc coverage counts. */
198 /* First line number & file. */
202 /* Next function in same source file. */
203 struct function_info
*next_file_fn
;
206 struct function_info
*next
;
209 /* Describes coverage of a file or function. */
211 typedef struct coverage_info
217 int branches_executed
;
226 /* Describes a single line of source. Contains a chain of basic blocks
229 typedef struct line_info
231 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
232 bool has_block (block_t
*needle
);
234 gcov_type count
; /* execution count */
237 arc_t
*branches
; /* branches from blocks that end on this
238 line. Used for branch-counts when not
240 block_t
*blocks
; /* blocks which start on this line. Used
241 in all-blocks mode. */
244 unsigned unexceptional
: 1;
248 line_t::has_block (block_t
*needle
)
250 for (block_t
*n
= u
.blocks
; n
; n
= n
->chain
)
257 /* Describes a file mentioned in the block graph. Contains an array
260 typedef struct source_info
262 /* Canonical name of source file. */
266 /* Array of line information. */
272 /* Functions in this source file. These are in ascending line
274 function_t
*functions
;
277 typedef struct name_map
279 char *name
; /* Source file name */
280 unsigned src
; /* Source file */
283 /* Holds a list of function basic block graphs. */
285 static function_t
*functions
;
286 static function_t
**fn_end
= &functions
;
288 static source_t
*sources
; /* Array of source files */
289 static unsigned n_sources
; /* Number of sources */
290 static unsigned a_sources
; /* Allocated sources */
292 static name_map_t
*names
; /* Mapping of file names to sources */
293 static unsigned n_names
; /* Number of names */
294 static unsigned a_names
; /* Allocated names */
296 /* This holds data summary information. */
298 static unsigned object_runs
;
299 static unsigned program_count
;
301 static unsigned total_lines
;
302 static unsigned total_executed
;
304 /* Modification time of graph file. */
306 static time_t bbg_file_time
;
308 /* Name of the notes (gcno) output file. The "bbg" prefix is for
309 historical reasons, when the notes file contained only the
310 basic block graph notes. */
312 static char *bbg_file_name
;
314 /* Stamp of the bbg file */
315 static unsigned bbg_stamp
;
317 /* Name and file pointer of the input file for the count data (gcda). */
319 static char *da_file_name
;
321 /* Data file is missing. */
323 static int no_data_file
;
325 /* If there is several input files, compute and display results after
326 reading all data files. This way if two or more gcda file refer to
327 the same source file (eg inline subprograms in a .h file), the
330 static int multiple_files
= 0;
332 /* Output branch probabilities. */
334 static int flag_branches
= 0;
336 /* Show unconditional branches too. */
337 static int flag_unconditional
= 0;
339 /* Output a gcov file if this is true. This is on by default, and can
340 be turned off by the -n option. */
342 static int flag_gcov_file
= 1;
344 /* Output progress indication if this is true. This is off by default
345 and can be turned on by the -d option. */
347 static int flag_display_progress
= 0;
349 /* Output *.gcov file in intermediate format used by 'lcov'. */
351 static int flag_intermediate_format
= 0;
353 /* Output demangled function names. */
355 static int flag_demangled_names
= 0;
357 /* For included files, make the gcov output file name include the name
358 of the input source file. For example, if x.h is included in a.c,
359 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
361 static int flag_long_names
= 0;
363 /* For situations when a long name can potentially hit filesystem path limit,
364 let's calculate md5sum of the path and append it to a file name. */
366 static int flag_hash_filenames
= 0;
368 /* Output count information for every basic block, not merely those
369 that contain line number information. */
371 static int flag_all_blocks
= 0;
373 /* Output summary info for each function. */
375 static int flag_function_summary
= 0;
377 /* Object directory file prefix. This is the directory/file where the
378 graph and data files are looked for, if nonzero. */
380 static char *object_directory
= 0;
382 /* Source directory prefix. This is removed from source pathnames
383 that match, when generating the output file name. */
385 static char *source_prefix
= 0;
386 static size_t source_length
= 0;
388 /* Only show data for sources with relative pathnames. Absolute ones
389 usually indicate a system header file, which although it may
390 contain inline functions, is usually uninteresting. */
391 static int flag_relative_only
= 0;
393 /* Preserve all pathname components. Needed when object files and
394 source files are in subdirectories. '/' is mangled as '#', '.' is
395 elided and '..' mangled to '^'. */
397 static int flag_preserve_paths
= 0;
399 /* Output the number of times a branch was taken as opposed to the percentage
400 of times it was taken. */
402 static int flag_counts
= 0;
404 /* Forward declarations. */
405 static int process_args (int, char **);
406 static void print_usage (int) ATTRIBUTE_NORETURN
;
407 static void print_version (void) ATTRIBUTE_NORETURN
;
408 static void process_file (const char *);
409 static void generate_results (const char *);
410 static void create_file_names (const char *);
411 static int name_search (const void *, const void *);
412 static int name_sort (const void *, const void *);
413 static char *canonicalize_name (const char *);
414 static unsigned find_source (const char *);
415 static function_t
*read_graph_file (void);
416 static int read_count_file (function_t
*);
417 static void solve_flow_graph (function_t
*);
418 static void find_exception_blocks (function_t
*);
419 static void add_branch_counts (coverage_t
*, const arc_t
*);
420 static void add_line_counts (coverage_t
*, function_t
*);
421 static void executed_summary (unsigned, unsigned);
422 static void function_summary (const coverage_t
*, const char *);
423 static const char *format_gcov (gcov_type
, gcov_type
, int);
424 static void accumulate_line_counts (source_t
*);
425 static void output_gcov_file (const char *, source_t
*);
426 static int output_branch_count (FILE *, int, const arc_t
*);
427 static void output_lines (FILE *, const source_t
*);
428 static char *make_gcov_file_name (const char *, const char *);
429 static char *mangle_name (const char *, char *);
430 static void release_structures (void);
431 static void release_function (function_t
*);
432 extern int main (int, char **);
435 There are a bajillion algorithms that do this. Boost's function is named
436 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
437 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
438 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
440 The basic algorithm is simple: effectively, we're finding all simple paths
441 in a subgraph (that shrinks every iteration). Duplicates are filtered by
442 "blocking" a path when a node is added to the path (this also prevents non-
443 simple paths)--the node is unblocked only when it participates in a cycle.
446 typedef vector
<arc_t
*> arc_vector_t
;
447 typedef vector
<const block_t
*> block_vector_t
;
449 /* Enum with types of loop in CFG. */
458 /* Loop_type operator that merges two values: A and B. */
460 inline loop_type
& operator |= (loop_type
& a
, loop_type b
)
462 return a
= static_cast<loop_type
> (a
| b
);
465 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
466 and subtract the value from all counts. The subtracted value is added
467 to COUNT. Returns type of loop. */
470 handle_cycle (const arc_vector_t
&edges
, int64_t &count
)
472 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
474 int64_t cycle_count
= INTTYPE_MAXIMUM (int64_t);
475 for (unsigned i
= 0; i
< edges
.size (); i
++)
477 int64_t ecount
= edges
[i
]->cs_count
;
478 if (cycle_count
> ecount
)
479 cycle_count
= ecount
;
481 count
+= cycle_count
;
482 for (unsigned i
= 0; i
< edges
.size (); i
++)
483 edges
[i
]->cs_count
-= cycle_count
;
485 return cycle_count
< 0 ? NEGATIVE_LOOP
: LOOP
;
488 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
489 blocked by U in BLOCK_LISTS. */
492 unblock (const block_t
*u
, block_vector_t
&blocked
,
493 vector
<block_vector_t
> &block_lists
)
495 block_vector_t::iterator it
= find (blocked
.begin (), blocked
.end (), u
);
496 if (it
== blocked
.end ())
499 unsigned index
= it
- blocked
.begin ();
502 for (block_vector_t::iterator it2
= block_lists
[index
].begin ();
503 it2
!= block_lists
[index
].end (); it2
++)
504 unblock (*it2
, blocked
, block_lists
);
505 for (unsigned j
= 0; j
< block_lists
[index
].size (); j
++)
506 unblock (u
, blocked
, block_lists
);
508 block_lists
.erase (block_lists
.begin () + index
);
511 /* Find circuit going to block V, PATH is provisional seen cycle.
512 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
513 blocked by a block. COUNT is accumulated count of the current LINE.
514 Returns what type of loop it contains. */
517 circuit (block_t
*v
, arc_vector_t
&path
, block_t
*start
,
518 block_vector_t
&blocked
, vector
<block_vector_t
> &block_lists
,
519 line_t
&linfo
, int64_t &count
)
521 loop_type result
= NO_LOOP
;
523 /* Add v to the block list. */
524 gcc_assert (find (blocked
.begin (), blocked
.end (), v
) == blocked
.end ());
525 blocked
.push_back (v
);
526 block_lists
.push_back (block_vector_t ());
528 for (arc_t
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
530 block_t
*w
= arc
->dst
;
531 if (w
< start
|| !linfo
.has_block (w
))
534 path
.push_back (arc
);
536 /* Cycle has been found. */
537 result
|= handle_cycle (path
, count
);
538 else if (find (blocked
.begin (), blocked
.end (), w
) == blocked
.end ())
539 result
|= circuit (w
, path
, start
, blocked
, block_lists
, linfo
, count
);
544 if (result
!= NO_LOOP
)
545 unblock (v
, blocked
, block_lists
);
547 for (arc_t
*arc
= v
->succ
; arc
; arc
= arc
->succ_next
)
549 block_t
*w
= arc
->dst
;
550 if (w
< start
|| !linfo
.has_block (w
))
554 = find (blocked
.begin (), blocked
.end (), w
) - blocked
.begin ();
555 gcc_assert (index
< blocked
.size ());
556 block_vector_t
&list
= block_lists
[index
];
557 if (find (list
.begin (), list
.end (), v
) == list
.end ())
564 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
565 contains a negative loop, then perform the same function once again. */
568 get_cycles_count (line_t
&linfo
, bool handle_negative_cycles
= true)
570 /* Note that this algorithm works even if blocks aren't in sorted order.
571 Each iteration of the circuit detection is completely independent
572 (except for reducing counts, but that shouldn't matter anyways).
573 Therefore, operating on a permuted order (i.e., non-sorted) only
574 has the effect of permuting the output cycles. */
576 loop_type result
= NO_LOOP
;
578 for (block_t
*block
= linfo
.u
.blocks
; block
; block
= block
->chain
)
581 block_vector_t blocked
;
582 vector
<block_vector_t
> block_lists
;
583 result
|= circuit (block
, path
, block
, blocked
, block_lists
, linfo
,
587 /* If we have a negative cycle, repeat the find_cycles routine. */
588 if (result
== NEGATIVE_LOOP
&& handle_negative_cycles
)
589 count
+= get_cycles_count (linfo
, false);
595 main (int argc
, char **argv
)
601 p
= argv
[0] + strlen (argv
[0]);
602 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
606 xmalloc_set_program_name (progname
);
608 /* Unlock the stdio streams. */
609 unlock_std_streams ();
613 diagnostic_initialize (global_dc
, 0);
615 /* Handle response files. */
616 expandargv (&argc
, &argv
);
619 names
= XNEWVEC (name_map_t
, a_names
);
621 sources
= XNEWVEC (source_t
, a_sources
);
623 argno
= process_args (argc
, argv
);
627 if (argc
- argno
> 1)
632 for (; argno
!= argc
; argno
++)
634 if (flag_display_progress
)
635 printf ("Processing file %d out of %d\n", argno
- first_arg
+ 1,
637 process_file (argv
[argno
]);
640 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
642 release_structures ();
647 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
648 otherwise the output of --help. */
651 print_usage (int error_p
)
653 FILE *file
= error_p
? stderr
: stdout
;
654 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
656 fnotice (file
, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
657 fnotice (file
, "Print code coverage information.\n\n");
658 fnotice (file
, " -h, --help Print this help, then exit\n");
659 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
660 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
661 fnotice (file
, " -c, --branch-counts Output counts of branches taken\n\
662 rather than percentages\n");
663 fnotice (file
, " -d, --display-progress Display progress information\n");
664 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
665 fnotice (file
, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
666 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
668 fnotice (file
, " -m, --demangled-names Output demangled function names\n");
669 fnotice (file
, " -n, --no-output Do not create an output file\n");
670 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
671 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
672 fnotice (file
, " -r, --relative-only Only show data for relative sources\n");
673 fnotice (file
, " -s, --source-prefix DIR Source prefix to elide\n");
674 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
675 fnotice (file
, " -v, --version Print version number, then exit\n");
676 fnotice (file
, " -x, --hash-filenames Hash long pathnames\n");
677 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
682 /* Print version information and exit. */
687 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
688 fprintf (stdout
, "Copyright %s 2017 Free Software Foundation, Inc.\n",
691 _("This is free software; see the source for copying conditions.\n"
692 "There is NO warranty; not even for MERCHANTABILITY or \n"
693 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
694 exit (SUCCESS_EXIT_CODE
);
697 static const struct option options
[] =
699 { "help", no_argument
, NULL
, 'h' },
700 { "version", no_argument
, NULL
, 'v' },
701 { "all-blocks", no_argument
, NULL
, 'a' },
702 { "branch-probabilities", no_argument
, NULL
, 'b' },
703 { "branch-counts", no_argument
, NULL
, 'c' },
704 { "intermediate-format", no_argument
, NULL
, 'i' },
705 { "no-output", no_argument
, NULL
, 'n' },
706 { "long-file-names", no_argument
, NULL
, 'l' },
707 { "function-summaries", no_argument
, NULL
, 'f' },
708 { "demangled-names", no_argument
, NULL
, 'm' },
709 { "preserve-paths", no_argument
, NULL
, 'p' },
710 { "relative-only", no_argument
, NULL
, 'r' },
711 { "object-directory", required_argument
, NULL
, 'o' },
712 { "object-file", required_argument
, NULL
, 'o' },
713 { "source-prefix", required_argument
, NULL
, 's' },
714 { "unconditional-branches", no_argument
, NULL
, 'u' },
715 { "display-progress", no_argument
, NULL
, 'd' },
716 { "hash-filenames", no_argument
, NULL
, 'x' },
720 /* Process args, return index to first non-arg. */
723 process_args (int argc
, char **argv
)
727 const char *opts
= "abcdfhilmno:prs:uvx";
728 while ((opt
= getopt_long (argc
, argv
, opts
, options
, NULL
)) != -1)
742 flag_function_summary
= 1;
746 /* print_usage will exit. */
751 flag_demangled_names
= 1;
757 object_directory
= optarg
;
760 source_prefix
= optarg
;
761 source_length
= strlen (source_prefix
);
764 flag_relative_only
= 1;
767 flag_preserve_paths
= 1;
770 flag_unconditional
= 1;
773 flag_intermediate_format
= 1;
777 flag_display_progress
= 1;
780 flag_hash_filenames
= 1;
784 /* print_version will exit. */
787 /* print_usage will exit. */
794 /* Output the result in intermediate format used by 'lcov'.
796 The intermediate format contains a single file named 'foo.cc.gcov',
797 with no source code included. A sample output is
802 function:19,1,_GLOBAL__sub_I__Z3foov
803 function:19,1,_Z41__static_initialization_and_destruction_0ii
810 file:/.../basic_ios.h
813 function:157,0,_ZStorSt12_Ios_IostateS_
815 file:/.../char_traits.h
816 function:258,0,_ZNSt11char_traitsIcE6lengthEPKc
820 The default gcov outputs multiple files: 'foo.cc.gcov',
821 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
822 included. Instead the intermediate format here outputs only a single
823 file 'foo.cc.gcov' similar to the above example. */
826 output_intermediate_file (FILE *gcov_file
, source_t
*src
)
828 unsigned line_num
; /* current line number. */
829 const line_t
*line
; /* current line info ptr. */
830 function_t
*fn
; /* current function info ptr. */
832 fprintf (gcov_file
, "file:%s\n", src
->name
); /* source file name */
834 for (fn
= src
->functions
; fn
; fn
= fn
->next_file_fn
)
836 /* function:<name>,<line_number>,<execution_count> */
837 fprintf (gcov_file
, "function:%d,%s,%s\n", fn
->line
,
838 format_gcov (fn
->blocks
[0].count
, 0, -1),
839 flag_demangled_names
? fn
->demangled_name
: fn
->name
);
842 for (line_num
= 1, line
= &src
->lines
[line_num
];
843 line_num
< src
->num_lines
;
848 fprintf (gcov_file
, "lcount:%u,%s\n", line_num
,
849 format_gcov (line
->count
, 0, -1));
851 for (arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
853 if (!arc
->is_unconditional
&& !arc
->is_call_non_return
)
855 const char *branch_type
;
856 /* branch:<line_num>,<branch_coverage_type>
858 : notexec (Branch not executed)
859 : taken (Branch executed and taken)
860 : nottaken (Branch executed, but not taken)
863 branch_type
= (arc
->count
> 0) ? "taken" : "nottaken";
865 branch_type
= "notexec";
866 fprintf (gcov_file
, "branch:%d,%s\n", line_num
, branch_type
);
872 /* Process a single input file. */
875 process_file (const char *file_name
)
879 create_file_names (file_name
);
880 fns
= read_graph_file ();
884 read_count_file (fns
);
887 function_t
*fn
= fns
;
891 if (fn
->counts
|| no_data_file
)
893 unsigned src
= fn
->src
;
894 unsigned line
= fn
->line
;
896 function_t
*probe
, **prev
;
898 /* Now insert it into the source file's list of
899 functions. Normally functions will be encountered in
900 ascending order, so a simple scan is quick. Note we're
901 building this list in reverse order. */
902 for (prev
= &sources
[src
].functions
;
903 (probe
= *prev
); prev
= &probe
->next_file_fn
)
904 if (probe
->line
<= line
)
906 fn
->next_file_fn
= probe
;
909 /* Mark last line in files touched by function. */
910 for (block_no
= 0; block_no
!= fn
->num_blocks
; block_no
++)
912 unsigned *enc
= fn
->blocks
[block_no
].u
.line
.encoding
;
913 unsigned num
= fn
->blocks
[block_no
].u
.line
.num
;
920 if (line
>= sources
[src
].num_lines
)
921 sources
[src
].num_lines
= line
+ 1;
928 else if (*enc
> line
)
931 if (line
>= sources
[src
].num_lines
)
932 sources
[src
].num_lines
= line
+ 1;
934 solve_flow_graph (fn
);
936 find_exception_blocks (fn
);
941 /* The function was not in the executable -- some other
942 instance must have been selected. */
943 release_function (fn
);
948 output_gcov_file (const char *file_name
, source_t
*src
)
950 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->coverage
.name
);
952 if (src
->coverage
.lines
)
954 FILE *gcov_file
= fopen (gcov_file_name
, "w");
957 fnotice (stdout
, "Creating '%s'\n", gcov_file_name
);
959 if (flag_intermediate_format
)
960 output_intermediate_file (gcov_file
, src
);
962 output_lines (gcov_file
, src
);
963 if (ferror (gcov_file
))
964 fnotice (stderr
, "Error writing output file '%s'\n", gcov_file_name
);
968 fnotice (stderr
, "Could not open output file '%s'\n", gcov_file_name
);
972 unlink (gcov_file_name
);
973 fnotice (stdout
, "Removing '%s'\n", gcov_file_name
);
975 free (gcov_file_name
);
979 generate_results (const char *file_name
)
985 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
987 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
989 for (fn
= functions
; fn
; fn
= fn
->next
)
993 memset (&coverage
, 0, sizeof (coverage
));
994 coverage
.name
= flag_demangled_names
? fn
->demangled_name
: fn
->name
;
995 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
996 if (flag_function_summary
)
998 function_summary (&coverage
, "Function");
999 fnotice (stdout
, "\n");
1005 name_map_t
*name_map
= (name_map_t
*)bsearch
1006 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
1008 file_name
= sources
[name_map
->src
].coverage
.name
;
1010 file_name
= canonicalize_name (file_name
);
1013 for (ix
= n_sources
, src
= sources
; ix
--; src
++)
1015 if (flag_relative_only
)
1017 /* Ignore this source, if it is an absolute path (after
1018 source prefix removal). */
1019 char first
= src
->coverage
.name
[0];
1021 #if HAVE_DOS_BASED_FILE_SYSTEM
1022 if (first
&& src
->coverage
.name
[1] == ':')
1023 first
= src
->coverage
.name
[2];
1025 if (IS_DIR_SEPARATOR (first
))
1029 accumulate_line_counts (src
);
1030 function_summary (&src
->coverage
, "File");
1031 total_lines
+= src
->coverage
.lines
;
1032 total_executed
+= src
->coverage
.lines_executed
;
1035 output_gcov_file (file_name
, src
);
1036 fnotice (stdout
, "\n");
1041 executed_summary (total_lines
, total_executed
);
1044 /* Release a function structure */
1047 release_function (function_t
*fn
)
1052 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
1056 for (arc
= block
->succ
; arc
; arc
= arc_n
)
1058 arc_n
= arc
->succ_next
;
1064 if (flag_demangled_names
&& fn
->demangled_name
!= fn
->name
)
1065 free (fn
->demangled_name
);
1069 /* Release all memory used. */
1072 release_structures (void)
1077 for (ix
= n_sources
; ix
--;)
1078 free (sources
[ix
].lines
);
1081 for (ix
= n_names
; ix
--;)
1082 free (names
[ix
].name
);
1085 while ((fn
= functions
))
1087 functions
= fn
->next
;
1088 release_function (fn
);
1092 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1093 is not specified, these are named from FILE_NAME sans extension. If
1094 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1095 directory, but named from the basename of the FILE_NAME, sans extension.
1096 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1097 and the data files are named from that. */
1100 create_file_names (const char *file_name
)
1104 int length
= strlen (file_name
);
1107 /* Free previous file names. */
1108 free (bbg_file_name
);
1109 free (da_file_name
);
1110 da_file_name
= bbg_file_name
= NULL
;
1114 if (object_directory
&& object_directory
[0])
1118 length
+= strlen (object_directory
) + 2;
1119 name
= XNEWVEC (char, length
);
1122 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
1123 strcat (name
, object_directory
);
1124 if (base
&& (!IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
1129 name
= XNEWVEC (char, length
+ 1);
1130 strcpy (name
, file_name
);
1136 /* Append source file name. */
1137 const char *cptr
= lbasename (file_name
);
1138 strcat (name
, cptr
? cptr
: file_name
);
1141 /* Remove the extension. */
1142 cptr
= strrchr (CONST_CAST (char *, lbasename (name
)), '.');
1146 length
= strlen (name
);
1148 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
1149 strcpy (bbg_file_name
, name
);
1150 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
1152 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
1153 strcpy (da_file_name
, name
);
1154 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
1160 /* A is a string and B is a pointer to name_map_t. Compare for file
1161 name orderability. */
1164 name_search (const void *a_
, const void *b_
)
1166 const char *a
= (const char *)a_
;
1167 const name_map_t
*b
= (const name_map_t
*)b_
;
1169 #if HAVE_DOS_BASED_FILE_SYSTEM
1170 return strcasecmp (a
, b
->name
);
1172 return strcmp (a
, b
->name
);
1176 /* A and B are a pointer to name_map_t. Compare for file name
1180 name_sort (const void *a_
, const void *b_
)
1182 const name_map_t
*a
= (const name_map_t
*)a_
;
1183 return name_search (a
->name
, b_
);
1186 /* Find or create a source file structure for FILE_NAME. Copies
1187 FILE_NAME on creation */
1190 find_source (const char *file_name
)
1192 name_map_t
*name_map
;
1198 file_name
= "<unknown>";
1199 name_map
= (name_map_t
*)bsearch
1200 (file_name
, names
, n_names
, sizeof (*names
), name_search
);
1203 idx
= name_map
->src
;
1207 if (n_names
+ 2 > a_names
)
1209 /* Extend the name map array -- we'll be inserting one or two
1212 name_map
= XNEWVEC (name_map_t
, a_names
);
1213 memcpy (name_map
, names
, n_names
* sizeof (*names
));
1218 /* Not found, try the canonical name. */
1219 canon
= canonicalize_name (file_name
);
1220 name_map
= (name_map_t
*) bsearch (canon
, names
, n_names
, sizeof (*names
),
1224 /* Not found with canonical name, create a new source. */
1227 if (n_sources
== a_sources
)
1230 src
= XNEWVEC (source_t
, a_sources
);
1231 memcpy (src
, sources
, n_sources
* sizeof (*sources
));
1238 name_map
= &names
[n_names
++];
1239 name_map
->name
= canon
;
1240 name_map
->src
= idx
;
1242 src
= &sources
[n_sources
++];
1243 memset (src
, 0, sizeof (*src
));
1245 src
->coverage
.name
= src
->name
;
1247 #if HAVE_DOS_BASED_FILE_SYSTEM
1248 /* You lose if separators don't match exactly in the
1250 && !strncasecmp (source_prefix
, src
->coverage
.name
, source_length
)
1252 && !strncmp (source_prefix
, src
->coverage
.name
, source_length
)
1254 && IS_DIR_SEPARATOR (src
->coverage
.name
[source_length
]))
1255 src
->coverage
.name
+= source_length
+ 1;
1256 if (!stat (src
->name
, &status
))
1257 src
->file_time
= status
.st_mtime
;
1260 idx
= name_map
->src
;
1262 if (name_search (file_name
, name_map
))
1264 /* Append the non-canonical name. */
1265 name_map
= &names
[n_names
++];
1266 name_map
->name
= xstrdup (file_name
);
1267 name_map
->src
= idx
;
1270 /* Resort the name map. */
1271 qsort (names
, n_names
, sizeof (*names
), name_sort
);
1274 if (sources
[idx
].file_time
> bbg_file_time
)
1276 static int info_emitted
;
1278 fnotice (stderr
, "%s:source file is newer than notes file '%s'\n",
1279 file_name
, bbg_file_name
);
1283 "(the message is displayed only once per source file)\n");
1286 sources
[idx
].file_time
= 0;
1292 /* Read the notes file. Return list of functions read -- in reverse order. */
1295 read_graph_file (void)
1298 unsigned current_tag
= 0;
1299 function_t
*fn
= NULL
;
1300 function_t
*fns
= NULL
;
1301 function_t
**fns_end
= &fns
;
1302 unsigned src_idx
= 0;
1306 if (!gcov_open (bbg_file_name
, 1))
1308 fnotice (stderr
, "%s:cannot open notes file\n", bbg_file_name
);
1311 bbg_file_time
= gcov_time ();
1312 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
1314 fnotice (stderr
, "%s:not a gcov notes file\n", bbg_file_name
);
1319 version
= gcov_read_unsigned ();
1320 if (version
!= GCOV_VERSION
)
1324 GCOV_UNSIGNED2STRING (v
, version
);
1325 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1327 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
1328 bbg_file_name
, v
, e
);
1330 bbg_stamp
= gcov_read_unsigned ();
1332 while ((tag
= gcov_read_unsigned ()))
1334 unsigned length
= gcov_read_unsigned ();
1335 gcov_position_t base
= gcov_position ();
1337 if (tag
== GCOV_TAG_FUNCTION
)
1339 char *function_name
;
1340 unsigned ident
, lineno
;
1341 unsigned lineno_checksum
, cfg_checksum
;
1343 ident
= gcov_read_unsigned ();
1344 lineno_checksum
= gcov_read_unsigned ();
1345 cfg_checksum
= gcov_read_unsigned ();
1346 function_name
= xstrdup (gcov_read_string ());
1347 src_idx
= find_source (gcov_read_string ());
1348 lineno
= gcov_read_unsigned ();
1350 fn
= XCNEW (function_t
);
1351 fn
->name
= function_name
;
1352 if (flag_demangled_names
)
1354 fn
->demangled_name
= cplus_demangle (fn
->name
, DMGL_PARAMS
);
1355 if (!fn
->demangled_name
)
1356 fn
->demangled_name
= fn
->name
;
1359 fn
->lineno_checksum
= lineno_checksum
;
1360 fn
->cfg_checksum
= cfg_checksum
;
1364 fn
->next_file_fn
= NULL
;
1367 fns_end
= &fn
->next
;
1370 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
1373 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
1374 bbg_file_name
, fn
->name
);
1377 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
1378 fn
->num_blocks
= num_blocks
;
1380 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
1381 for (ix
= 0; ix
!= num_blocks
; ix
++)
1382 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
1385 else if (fn
&& tag
== GCOV_TAG_ARCS
)
1387 unsigned src
= gcov_read_unsigned ();
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
->num_blocks
|| fn
->blocks
[src
].succ
)
1398 unsigned dest
= gcov_read_unsigned ();
1399 unsigned flags
= gcov_read_unsigned ();
1401 if (dest
>= fn
->num_blocks
)
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 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
1464 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
1469 unsigned lineno
= gcov_read_unsigned ();
1476 line_nos
[ix
++] = src_idx
;
1478 line_nos
[ix
++] = lineno
;
1482 const char *file_name
= gcov_read_string ();
1486 src_idx
= find_source (file_name
);
1488 line_nos
[ix
++] = src_idx
;
1492 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
1493 fn
->blocks
[blockno
].u
.line
.num
= ix
;
1495 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
1500 gcov_sync (base
, length
);
1501 if (gcov_is_error ())
1504 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
1511 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
1516 /* Reads profiles from the count file and attach to each
1517 function. Return nonzero if fatal error. */
1520 read_count_file (function_t
*fns
)
1525 function_t
*fn
= NULL
;
1528 if (!gcov_open (da_file_name
, 1))
1530 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1535 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1537 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1542 version
= gcov_read_unsigned ();
1543 if (version
!= GCOV_VERSION
)
1547 GCOV_UNSIGNED2STRING (v
, version
);
1548 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1550 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1551 da_file_name
, v
, e
);
1553 tag
= gcov_read_unsigned ();
1554 if (tag
!= bbg_stamp
)
1556 fnotice (stderr
, "%s:stamp mismatch with notes file\n", da_file_name
);
1560 while ((tag
= gcov_read_unsigned ()))
1562 unsigned length
= gcov_read_unsigned ();
1563 unsigned long base
= gcov_position ();
1565 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1567 struct gcov_summary summary
;
1568 gcov_read_summary (&summary
);
1569 object_runs
+= summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
;
1572 else if (tag
== GCOV_TAG_FUNCTION
&& !length
)
1574 else if (tag
== GCOV_TAG_FUNCTION
&& length
== GCOV_TAG_FUNCTION_LENGTH
)
1577 struct function_info
*fn_n
;
1579 /* Try to find the function in the list. To speed up the
1580 search, first start from the last function found. */
1581 ident
= gcov_read_unsigned ();
1583 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1587 else if ((fn
= fn_n
))
1591 fnotice (stderr
, "%s:unknown function '%u'\n",
1592 da_file_name
, ident
);
1595 if (fn
->ident
== ident
)
1601 else if (gcov_read_unsigned () != fn
->lineno_checksum
1602 || gcov_read_unsigned () != fn
->cfg_checksum
)
1605 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1606 da_file_name
, fn
->name
);
1610 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1612 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1616 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1618 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1619 fn
->counts
[ix
] += gcov_read_counter ();
1621 gcov_sync (base
, length
);
1622 if ((error
= gcov_is_error ()))
1626 ? N_("%s:overflowed\n")
1627 : N_("%s:corrupted\n"),
1637 /* Solve the flow graph. Propagate counts from the instrumented arcs
1638 to the blocks and the uninstrumented arcs. */
1641 solve_flow_graph (function_t
*fn
)
1645 gcov_type
*count_ptr
= fn
->counts
;
1647 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1648 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1650 /* The arcs were built in reverse order. Fix that now. */
1651 for (ix
= fn
->num_blocks
; ix
--;)
1653 arc_t
*arc_p
, *arc_n
;
1655 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1656 arc_p
= arc
, arc
= arc_n
)
1658 arc_n
= arc
->succ_next
;
1659 arc
->succ_next
= arc_p
;
1661 fn
->blocks
[ix
].succ
= arc_p
;
1663 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1664 arc_p
= arc
, arc
= arc_n
)
1666 arc_n
= arc
->pred_next
;
1667 arc
->pred_next
= arc_p
;
1669 fn
->blocks
[ix
].pred
= arc_p
;
1672 if (fn
->num_blocks
< 2)
1673 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1674 bbg_file_name
, fn
->name
);
1677 if (fn
->blocks
[ENTRY_BLOCK
].num_pred
)
1678 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1679 bbg_file_name
, fn
->name
);
1681 /* We can't deduce the entry block counts from the lack of
1683 fn
->blocks
[ENTRY_BLOCK
].num_pred
= ~(unsigned)0;
1685 if (fn
->blocks
[EXIT_BLOCK
].num_succ
)
1686 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1687 bbg_file_name
, fn
->name
);
1689 /* Likewise, we can't deduce exit block counts from the lack
1690 of its successors. */
1691 fn
->blocks
[EXIT_BLOCK
].num_succ
= ~(unsigned)0;
1694 /* Propagate the measured counts, this must be done in the same
1695 order as the code in profile.c */
1696 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1698 block_t
const *prev_dst
= NULL
;
1699 int out_of_order
= 0;
1700 int non_fake_succ
= 0;
1702 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1710 arc
->count
= *count_ptr
++;
1711 arc
->count_valid
= 1;
1713 arc
->dst
->num_pred
--;
1715 if (prev_dst
&& prev_dst
> arc
->dst
)
1717 prev_dst
= arc
->dst
;
1719 if (non_fake_succ
== 1)
1721 /* If there is only one non-fake exit, it is an
1722 unconditional branch. */
1723 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1726 arc
->is_unconditional
= 1;
1727 /* If this block is instrumenting a call, it might be
1728 an artificial block. It is not artificial if it has
1729 a non-fallthrough exit, or the destination of this
1730 arc has more than one entry. Mark the destination
1731 block as a return site, if none of those conditions
1733 if (blk
->is_call_site
&& arc
->fall_through
1734 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1735 arc
->dst
->is_call_return
= 1;
1739 /* Sort the successor arcs into ascending dst order. profile.c
1740 normally produces arcs in the right order, but sometimes with
1741 one or two out of order. We're not using a particularly
1745 arc_t
*start
= blk
->succ
;
1746 unsigned changes
= 1;
1750 arc_t
*arc
, *arc_p
, *arc_n
;
1753 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1755 if (arc
->dst
> arc_n
->dst
)
1759 arc_p
->succ_next
= arc_n
;
1762 arc
->succ_next
= arc_n
->succ_next
;
1763 arc_n
->succ_next
= arc
;
1776 /* Place it on the invalid chain, it will be ignored if that's
1778 blk
->invalid_chain
= 1;
1779 blk
->chain
= invalid_blocks
;
1780 invalid_blocks
= blk
;
1783 while (invalid_blocks
|| valid_blocks
)
1785 while ((blk
= invalid_blocks
))
1787 gcov_type total
= 0;
1790 invalid_blocks
= blk
->chain
;
1791 blk
->invalid_chain
= 0;
1793 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1794 total
+= arc
->count
;
1795 else if (!blk
->num_pred
)
1796 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1797 total
+= arc
->count
;
1802 blk
->count_valid
= 1;
1803 blk
->chain
= valid_blocks
;
1804 blk
->valid_chain
= 1;
1807 while ((blk
= valid_blocks
))
1810 arc_t
*arc
, *inv_arc
;
1812 valid_blocks
= blk
->chain
;
1813 blk
->valid_chain
= 0;
1814 if (blk
->num_succ
== 1)
1820 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1822 total
-= arc
->count
;
1823 if (!arc
->count_valid
)
1827 inv_arc
->count_valid
= 1;
1828 inv_arc
->count
= total
;
1831 if (dst
->count_valid
)
1833 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1835 dst
->chain
= valid_blocks
;
1836 dst
->valid_chain
= 1;
1842 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1844 dst
->chain
= invalid_blocks
;
1845 dst
->invalid_chain
= 1;
1846 invalid_blocks
= dst
;
1850 if (blk
->num_pred
== 1)
1856 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1858 total
-= arc
->count
;
1859 if (!arc
->count_valid
)
1863 inv_arc
->count_valid
= 1;
1864 inv_arc
->count
= total
;
1867 if (src
->count_valid
)
1869 if (src
->num_succ
== 1 && !src
->valid_chain
)
1871 src
->chain
= valid_blocks
;
1872 src
->valid_chain
= 1;
1878 if (!src
->num_succ
&& !src
->invalid_chain
)
1880 src
->chain
= invalid_blocks
;
1881 src
->invalid_chain
= 1;
1882 invalid_blocks
= src
;
1889 /* If the graph has been correctly solved, every block will have a
1891 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1892 if (!fn
->blocks
[ix
].count_valid
)
1894 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1895 bbg_file_name
, fn
->name
);
1900 /* Mark all the blocks only reachable via an incoming catch. */
1903 find_exception_blocks (function_t
*fn
)
1906 block_t
**queue
= XALLOCAVEC (block_t
*, fn
->num_blocks
);
1908 /* First mark all blocks as exceptional. */
1909 for (ix
= fn
->num_blocks
; ix
--;)
1910 fn
->blocks
[ix
].exceptional
= 1;
1912 /* Now mark all the blocks reachable via non-fake edges */
1913 queue
[0] = fn
->blocks
;
1914 queue
[0]->exceptional
= 0;
1917 block_t
*block
= queue
[--ix
];
1920 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1921 if (!arc
->fake
&& !arc
->is_throw
&& arc
->dst
->exceptional
)
1923 arc
->dst
->exceptional
= 0;
1924 queue
[ix
++] = arc
->dst
;
1930 /* Increment totals in COVERAGE according to arc ARC. */
1933 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1935 if (arc
->is_call_non_return
)
1938 if (arc
->src
->count
)
1939 coverage
->calls_executed
++;
1941 else if (!arc
->is_unconditional
)
1943 coverage
->branches
++;
1944 if (arc
->src
->count
)
1945 coverage
->branches_executed
++;
1947 coverage
->branches_taken
++;
1951 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
1952 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1953 If DP is zero, no decimal point is printed. Only print 100% when
1954 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1955 format TOP. Return pointer to a static string. */
1958 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1960 static char buffer
[20];
1964 float ratio
= bottom
? (float)top
/ bottom
: 0;
1966 unsigned limit
= 100;
1969 for (ix
= dp
; ix
--; )
1972 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1973 if (percent
<= 0 && top
)
1975 else if (percent
>= limit
&& top
!= bottom
)
1976 percent
= limit
- 1;
1977 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1983 buffer
[ix
+1] = buffer
[ix
];
1987 buffer
[ix
+ 1] = '.';
1991 sprintf (buffer
, "%" PRId64
, (int64_t)top
);
1996 /* Summary of execution */
1999 executed_summary (unsigned lines
, unsigned executed
)
2002 fnotice (stdout
, "Lines executed:%s of %d\n",
2003 format_gcov (executed
, lines
, 2), lines
);
2005 fnotice (stdout
, "No executable lines\n");
2008 /* Output summary info for a function or file. */
2011 function_summary (const coverage_t
*coverage
, const char *title
)
2013 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
2014 executed_summary (coverage
->lines
, coverage
->lines_executed
);
2018 if (coverage
->branches
)
2020 fnotice (stdout
, "Branches executed:%s of %d\n",
2021 format_gcov (coverage
->branches_executed
,
2022 coverage
->branches
, 2),
2023 coverage
->branches
);
2024 fnotice (stdout
, "Taken at least once:%s of %d\n",
2025 format_gcov (coverage
->branches_taken
,
2026 coverage
->branches
, 2),
2027 coverage
->branches
);
2030 fnotice (stdout
, "No branches\n");
2031 if (coverage
->calls
)
2032 fnotice (stdout
, "Calls executed:%s of %d\n",
2033 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
2036 fnotice (stdout
, "No calls\n");
2040 /* Canonicalize the filename NAME by canonicalizing directory
2041 separators, eliding . components and resolving .. components
2042 appropriately. Always returns a unique string. */
2045 canonicalize_name (const char *name
)
2047 /* The canonical name cannot be longer than the incoming name. */
2048 char *result
= XNEWVEC (char, strlen (name
) + 1);
2049 const char *base
= name
, *probe
;
2054 #if HAVE_DOS_BASED_FILE_SYSTEM
2055 if (base
[0] && base
[1] == ':')
2057 result
[0] = base
[0];
2063 for (dd_base
= ptr
; *base
; base
= probe
)
2067 for (probe
= base
; *probe
; probe
++)
2068 if (IS_DIR_SEPARATOR (*probe
))
2072 if (len
== 1 && base
[0] == '.')
2073 /* Elide a '.' directory */
2075 else if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2077 /* '..', we can only elide it and the previous directory, if
2078 we're not a symlink. */
2079 struct stat ATTRIBUTE_UNUSED buf
;
2083 #if defined (S_ISLNK)
2084 /* S_ISLNK is not POSIX.1-1996. */
2085 || stat (result
, &buf
) || S_ISLNK (buf
.st_mode
)
2089 /* Cannot elide, or unreadable or a symlink. */
2090 dd_base
= ptr
+ 2 + slash
;
2093 while (ptr
!= dd_base
&& *ptr
!= '/')
2095 slash
= ptr
!= result
;
2100 /* Regular pathname component. */
2103 memcpy (ptr
, base
, len
);
2108 for (; IS_DIR_SEPARATOR (*probe
); probe
++)
2116 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2119 md5sum_to_hex (const char *sum
, char *buffer
)
2121 for (unsigned i
= 0; i
< 16; i
++)
2122 sprintf (buffer
+ (2 * i
), "%02x", (unsigned char)sum
[i
]);
2125 /* Generate an output file name. INPUT_NAME is the canonicalized main
2126 input file and SRC_NAME is the canonicalized file name.
2127 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2128 long_output_names we prepend the processed name of the input file
2129 to each output name (except when the current source file is the
2130 input file, so you don't get a double concatenation). The two
2131 components are separated by '##'. With preserve_paths we create a
2132 filename from all path components of the source file, replacing '/'
2133 with '#', and .. with '^', without it we simply take the basename
2134 component. (Remember, the canonicalized name will already have
2135 elided '.' components and converted \\ separators.) */
2138 make_gcov_file_name (const char *input_name
, const char *src_name
)
2143 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
2145 /* Generate the input filename part. */
2146 result
= XNEWVEC (char, strlen (input_name
) + strlen (src_name
) + 10);
2149 ptr
= mangle_name (input_name
, ptr
);
2150 ptr
[0] = ptr
[1] = '#';
2155 result
= XNEWVEC (char, strlen (src_name
) + 10);
2159 ptr
= mangle_name (src_name
, ptr
);
2160 strcpy (ptr
, ".gcov");
2162 /* When hashing filenames, we shorten them by only using the filename
2163 component and appending a hash of the full (mangled) pathname. */
2164 if (flag_hash_filenames
)
2168 char md5sum_hex
[33];
2170 md5_init_ctx (&ctx
);
2171 md5_process_bytes (src_name
, strlen (src_name
), &ctx
);
2172 md5_finish_ctx (&ctx
, md5sum
);
2173 md5sum_to_hex (md5sum
, md5sum_hex
);
2176 result
= XNEWVEC (char, strlen (src_name
) + 50);
2178 ptr
= mangle_name (src_name
, ptr
);
2179 ptr
[0] = ptr
[1] = '#';
2181 memcpy (ptr
, md5sum_hex
, 32);
2183 strcpy (ptr
, ".gcov");
2190 mangle_name (char const *base
, char *ptr
)
2194 /* Generate the source filename part. */
2195 if (!flag_preserve_paths
)
2197 base
= lbasename (base
);
2198 len
= strlen (base
);
2199 memcpy (ptr
, base
, len
);
2204 /* Convert '/' to '#', convert '..' to '^',
2205 convert ':' to '~' on DOS based file system. */
2208 #if HAVE_DOS_BASED_FILE_SYSTEM
2209 if (base
[0] && base
[1] == ':')
2217 for (; *base
; base
= probe
)
2221 for (probe
= base
; *probe
; probe
++)
2225 if (len
== 2 && base
[0] == '.' && base
[1] == '.')
2229 memcpy (ptr
, base
, len
);
2243 /* Scan through the bb_data for each line in the block, increment
2244 the line number execution count indicated by the execution count of
2245 the appropriate basic block. */
2248 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
2251 line_t
*line
= NULL
; /* This is propagated from one iteration to the
2254 /* Scan each basic block. */
2255 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
2257 block_t
*block
= &fn
->blocks
[ix
];
2259 const source_t
*src
= NULL
;
2262 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
2263 fn
->blocks_executed
++;
2264 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
2265 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
2268 src
= &sources
[*++encoding
];
2273 line
= &src
->lines
[*encoding
];
2279 if (!line
->count
&& block
->count
)
2280 coverage
->lines_executed
++;
2283 if (!block
->exceptional
)
2284 line
->unexceptional
= 1;
2285 line
->count
+= block
->count
;
2287 free (block
->u
.line
.encoding
);
2288 block
->u
.cycle
.arc
= NULL
;
2289 block
->u
.cycle
.ident
= ~0U;
2291 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
2292 /* Entry or exit block */;
2293 else if (flag_all_blocks
)
2295 line_t
*block_line
= line
;
2298 block_line
= &sources
[fn
->src
].lines
[fn
->line
];
2300 block
->chain
= block_line
->u
.blocks
;
2301 block_line
->u
.blocks
= block
;
2303 else if (flag_branches
)
2307 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2309 arc
->line_next
= line
->u
.branches
;
2310 line
->u
.branches
= arc
;
2311 if (coverage
&& !arc
->is_unconditional
)
2312 add_branch_counts (coverage
, arc
);
2317 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
2320 /* Accumulate the line counts of a file. */
2323 accumulate_line_counts (source_t
*src
)
2326 function_t
*fn
, *fn_p
, *fn_n
;
2329 /* Reverse the function order. */
2330 for (fn
= src
->functions
, fn_p
= NULL
; fn
; fn_p
= fn
, fn
= fn_n
)
2332 fn_n
= fn
->next_file_fn
;
2333 fn
->next_file_fn
= fn_p
;
2335 src
->functions
= fn_p
;
2337 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
2339 if (!flag_all_blocks
)
2341 arc_t
*arc
, *arc_p
, *arc_n
;
2343 /* Total and reverse the branch information. */
2344 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
2345 arc_p
= arc
, arc
= arc_n
)
2347 arc_n
= arc
->line_next
;
2348 arc
->line_next
= arc_p
;
2350 add_branch_counts (&src
->coverage
, arc
);
2352 line
->u
.branches
= arc_p
;
2354 else if (line
->u
.blocks
)
2356 /* The user expects the line count to be the number of times
2357 a line has been executed. Simply summing the block count
2358 will give an artificially high number. The Right Thing
2359 is to sum the entry counts to the graph of blocks on this
2360 line, then find the elementary cycles of the local graph
2361 and add the transition counts of those cycles. */
2362 block_t
*block
, *block_p
, *block_n
;
2363 gcov_type count
= 0;
2365 /* Reverse the block information. */
2366 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
2367 block_p
= block
, block
= block_n
)
2369 block_n
= block
->chain
;
2370 block
->chain
= block_p
;
2371 block
->u
.cycle
.ident
= ix
;
2373 line
->u
.blocks
= block_p
;
2375 /* Sum the entry arcs. */
2376 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
2380 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2382 add_branch_counts (&src
->coverage
, arc
);
2385 /* Cycle detection. */
2386 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
2388 for (arc_t
*arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
2389 if (!line
->has_block (arc
->src
))
2390 count
+= arc
->count
;
2391 for (arc_t
*arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2392 arc
->cs_count
= arc
->count
;
2395 /* Now, add the count of loops entirely on this line. */
2396 count
+= get_cycles_count (*line
);
2397 line
->count
= count
;
2402 src
->coverage
.lines
++;
2404 src
->coverage
.lines_executed
++;
2409 /* Output information about ARC number IX. Returns nonzero if
2410 anything is output. */
2413 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
2415 if (arc
->is_call_non_return
)
2417 if (arc
->src
->count
)
2419 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
2420 format_gcov (arc
->src
->count
- arc
->count
,
2421 arc
->src
->count
, -flag_counts
));
2424 fnotice (gcov_file
, "call %2d never executed\n", ix
);
2426 else if (!arc
->is_unconditional
)
2428 if (arc
->src
->count
)
2429 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
2430 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
2431 arc
->fall_through
? " (fallthrough)"
2432 : arc
->is_throw
? " (throw)" : "");
2434 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
2436 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
2438 if (arc
->src
->count
)
2439 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
2440 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
2442 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
2450 read_line (FILE *file
)
2452 static char *string
;
2453 static size_t string_len
;
2460 string
= XNEWVEC (char, string_len
);
2463 while ((ptr
= fgets (string
+ pos
, string_len
- pos
, file
)))
2465 size_t len
= strlen (string
+ pos
);
2467 if (len
&& string
[pos
+ len
- 1] == '\n')
2469 string
[pos
+ len
- 1] = 0;
2473 /* If the file contains NUL characters or an incomplete
2474 last line, which can happen more than once in one run,
2475 we have to avoid doubling the STRING_LEN unnecessarily. */
2476 if (pos
> string_len
/ 2)
2479 string
= XRESIZEVEC (char, string
, string_len
);
2483 return pos
? string
: NULL
;
2486 /* Read in the source file one line at a time, and output that line to
2487 the gcov file preceded by its execution count and other
2491 output_lines (FILE *gcov_file
, const source_t
*src
)
2494 unsigned line_num
; /* current line number. */
2495 const line_t
*line
; /* current line info ptr. */
2496 const char *retval
= ""; /* status of source file reading. */
2497 function_t
*fn
= NULL
;
2499 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->coverage
.name
);
2500 if (!multiple_files
)
2502 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
2503 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
2504 no_data_file
? "-" : da_file_name
);
2505 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0, object_runs
);
2507 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
2509 source_file
= fopen (src
->name
, "r");
2512 fnotice (stderr
, "Cannot open source file %s\n", src
->name
);
2515 else if (src
->file_time
== 0)
2516 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
2519 fn
= src
->functions
;
2521 for (line_num
= 1, line
= &src
->lines
[line_num
];
2522 line_num
< src
->num_lines
; line_num
++, line
++)
2524 for (; fn
&& fn
->line
== line_num
; fn
= fn
->next_file_fn
)
2526 arc_t
*arc
= fn
->blocks
[EXIT_BLOCK
].pred
;
2527 gcov_type return_count
= fn
->blocks
[EXIT_BLOCK
].count
;
2528 gcov_type called_count
= fn
->blocks
[ENTRY_BLOCK
].count
;
2530 for (; arc
; arc
= arc
->pred_next
)
2532 return_count
-= arc
->count
;
2534 fprintf (gcov_file
, "function %s", flag_demangled_names
?
2535 fn
->demangled_name
: fn
->name
);
2536 fprintf (gcov_file
, " called %s",
2537 format_gcov (called_count
, 0, -1));
2538 fprintf (gcov_file
, " returned %s",
2539 format_gcov (return_count
, called_count
, 0));
2540 fprintf (gcov_file
, " blocks executed %s",
2541 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
2542 fprintf (gcov_file
, "\n");
2546 retval
= read_line (source_file
);
2548 /* For lines which don't exist in the .bb file, print '-' before
2549 the source line. For lines which exist but were never
2550 executed, print '#####' or '=====' before the source line.
2551 Otherwise, print the execution count before the source line.
2552 There are 16 spaces of indentation added before the source
2553 line so that tabs won't be messed up. */
2554 fprintf (gcov_file
, "%9s:%5u:%s\n",
2555 !line
->exists
? "-" : line
->count
2556 ? format_gcov (line
->count
, 0, -1)
2557 : line
->unexceptional
? "#####" : "=====", line_num
,
2558 retval
? retval
: "/*EOF*/");
2560 if (flag_all_blocks
)
2566 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
2567 block
= block
->chain
)
2569 if (!block
->is_call_return
)
2570 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
2571 !line
->exists
? "-" : block
->count
2572 ? format_gcov (block
->count
, 0, -1)
2573 : block
->exceptional
? "%%%%%" : "$$$$$",
2576 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
2577 jx
+= output_branch_count (gcov_file
, jx
, arc
);
2580 else if (flag_branches
)
2585 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
2586 ix
+= output_branch_count (gcov_file
, ix
, arc
);
2590 /* Handle all remaining source lines. There may be lines after the
2591 last line of code. */
2594 for (; (retval
= read_line (source_file
)); line_num
++)
2595 fprintf (gcov_file
, "%9s:%5u:%s\n", "-", line_num
, retval
);
2599 fclose (source_file
);