]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/gcov.c
Fix gcov misleading error (PR gcov-profile/86817).
[thirdparty/gcc.git] / gcc / gcov.c
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990-2018 Free Software Foundation, Inc.
4 Contributed by James E. Wilson of Cygnus Support.
5 Mangled by Bob Manson of Cygnus Support.
6 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
7
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
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.
17
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/>. */
21
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. */
26
27 /* ??? Should have an option to print the number of basic blocks, and the
28 percent of them that are covered. */
29
30 /* Need an option to show individual block counts, and show
31 probabilities of fall through arcs. */
32
33 #include "config.h"
34 #define INCLUDE_ALGORITHM
35 #define INCLUDE_VECTOR
36 #define INCLUDE_STRING
37 #define INCLUDE_MAP
38 #define INCLUDE_SET
39 #include "system.h"
40 #include "coretypes.h"
41 #include "tm.h"
42 #include "intl.h"
43 #include "diagnostic.h"
44 #include "version.h"
45 #include "demangle.h"
46 #include "color-macros.h"
47
48 #include <getopt.h>
49
50 #include "md5.h"
51
52 using namespace std;
53
54 #define IN_GCOV 1
55 #include "gcov-io.h"
56 #include "gcov-io.c"
57
58 /* The gcno file is generated by -ftest-coverage option. The gcda file is
59 generated by a program compiled with -fprofile-arcs. Their formats
60 are documented in gcov-io.h. */
61
62 /* The functions in this file for creating and solution program flow graphs
63 are very similar to functions in the gcc source file profile.c. In
64 some places we make use of the knowledge of how profile.c works to
65 select particular algorithms here. */
66
67 /* The code validates that the profile information read in corresponds
68 to the code currently being compiled. Rather than checking for
69 identical files, the code below compares a checksum on the CFG
70 (based on the order of basic blocks and the arcs in the CFG). If
71 the CFG checksum in the gcda file match the CFG checksum in the
72 gcno file, the profile data will be used. */
73
74 /* This is the size of the buffer used to read in source file lines. */
75
76 struct function_info;
77 struct block_info;
78 struct source_info;
79
80 /* Describes an arc between two basic blocks. */
81
82 struct arc_info
83 {
84 /* source and destination blocks. */
85 struct block_info *src;
86 struct block_info *dst;
87
88 /* transition counts. */
89 gcov_type count;
90 /* used in cycle search, so that we do not clobber original counts. */
91 gcov_type cs_count;
92
93 unsigned int count_valid : 1;
94 unsigned int on_tree : 1;
95 unsigned int fake : 1;
96 unsigned int fall_through : 1;
97
98 /* Arc to a catch handler. */
99 unsigned int is_throw : 1;
100
101 /* Arc is for a function that abnormally returns. */
102 unsigned int is_call_non_return : 1;
103
104 /* Arc is for catch/setjmp. */
105 unsigned int is_nonlocal_return : 1;
106
107 /* Is an unconditional branch. */
108 unsigned int is_unconditional : 1;
109
110 /* Loop making arc. */
111 unsigned int cycle : 1;
112
113 /* Links to next arc on src and dst lists. */
114 struct arc_info *succ_next;
115 struct arc_info *pred_next;
116 };
117
118 /* Describes which locations (lines and files) are associated with
119 a basic block. */
120
121 struct block_location_info
122 {
123 block_location_info (unsigned _source_file_idx):
124 source_file_idx (_source_file_idx)
125 {}
126
127 unsigned source_file_idx;
128 vector<unsigned> lines;
129 };
130
131 /* Describes a basic block. Contains lists of arcs to successor and
132 predecessor blocks. */
133
134 struct block_info
135 {
136 /* Constructor. */
137 block_info ();
138
139 /* Chain of exit and entry arcs. */
140 arc_info *succ;
141 arc_info *pred;
142
143 /* Number of unprocessed exit and entry arcs. */
144 gcov_type num_succ;
145 gcov_type num_pred;
146
147 unsigned id;
148
149 /* Block execution count. */
150 gcov_type count;
151 unsigned count_valid : 1;
152 unsigned valid_chain : 1;
153 unsigned invalid_chain : 1;
154 unsigned exceptional : 1;
155
156 /* Block is a call instrumenting site. */
157 unsigned is_call_site : 1; /* Does the call. */
158 unsigned is_call_return : 1; /* Is the return. */
159
160 /* Block is a landing pad for longjmp or throw. */
161 unsigned is_nonlocal_return : 1;
162
163 vector<block_location_info> locations;
164
165 struct
166 {
167 /* Single line graph cycle workspace. Used for all-blocks
168 mode. */
169 arc_info *arc;
170 unsigned ident;
171 } cycle; /* Used in all-blocks mode, after blocks are linked onto
172 lines. */
173
174 /* Temporary chain for solving graph, and for chaining blocks on one
175 line. */
176 struct block_info *chain;
177
178 };
179
180 block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
181 id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
182 exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
183 locations (), chain (NULL)
184 {
185 cycle.arc = NULL;
186 }
187
188 /* Describes a single line of source. Contains a chain of basic blocks
189 with code on it. */
190
191 struct line_info
192 {
193 /* Default constructor. */
194 line_info ();
195
196 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
197 bool has_block (block_info *needle);
198
199 /* Execution count. */
200 gcov_type count;
201
202 /* Branches from blocks that end on this line. */
203 vector<arc_info *> branches;
204
205 /* blocks which start on this line. Used in all-blocks mode. */
206 vector<block_info *> blocks;
207
208 unsigned exists : 1;
209 unsigned unexceptional : 1;
210 unsigned has_unexecuted_block : 1;
211 };
212
213 line_info::line_info (): count (0), branches (), blocks (), exists (false),
214 unexceptional (0), has_unexecuted_block (0)
215 {
216 }
217
218 bool
219 line_info::has_block (block_info *needle)
220 {
221 return std::find (blocks.begin (), blocks.end (), needle) != blocks.end ();
222 }
223
224 /* Describes a single function. Contains an array of basic blocks. */
225
226 struct function_info
227 {
228 function_info ();
229 ~function_info ();
230
231 /* Return true when line N belongs to the function in source file SRC_IDX.
232 The line must be defined in body of the function, can't be inlined. */
233 bool group_line_p (unsigned n, unsigned src_idx);
234
235 /* Function filter based on function_info::artificial variable. */
236
237 static inline bool
238 is_artificial (function_info *fn)
239 {
240 return fn->artificial;
241 }
242
243 /* Name of function. */
244 char *name;
245 char *demangled_name;
246 unsigned ident;
247 unsigned lineno_checksum;
248 unsigned cfg_checksum;
249
250 /* The graph contains at least one fake incoming edge. */
251 unsigned has_catch : 1;
252
253 /* True when the function is artificial and does not exist
254 in a source file. */
255 unsigned artificial : 1;
256
257 /* True when multiple functions start at a line in a source file. */
258 unsigned is_group : 1;
259
260 /* Array of basic blocks. Like in GCC, the entry block is
261 at blocks[0] and the exit block is at blocks[1]. */
262 #define ENTRY_BLOCK (0)
263 #define EXIT_BLOCK (1)
264 vector<block_info> blocks;
265 unsigned blocks_executed;
266
267 /* Raw arc coverage counts. */
268 vector<gcov_type> counts;
269
270 /* First line number. */
271 unsigned start_line;
272
273 /* First line column. */
274 unsigned start_column;
275
276 /* Last line number. */
277 unsigned end_line;
278
279 /* Index of source file where the function is defined. */
280 unsigned src;
281
282 /* Vector of line information. */
283 vector<line_info> lines;
284
285 /* Next function. */
286 struct function_info *next;
287 };
288
289 /* Function info comparer that will sort functions according to starting
290 line. */
291
292 struct function_line_start_cmp
293 {
294 inline bool operator() (const function_info *lhs,
295 const function_info *rhs)
296 {
297 return (lhs->start_line == rhs->start_line
298 ? lhs->start_column < rhs->start_column
299 : lhs->start_line < rhs->start_line);
300 }
301 };
302
303 /* Describes coverage of a file or function. */
304
305 struct coverage_info
306 {
307 int lines;
308 int lines_executed;
309
310 int branches;
311 int branches_executed;
312 int branches_taken;
313
314 int calls;
315 int calls_executed;
316
317 char *name;
318 };
319
320 /* Describes a file mentioned in the block graph. Contains an array
321 of line info. */
322
323 struct source_info
324 {
325 /* Default constructor. */
326 source_info ();
327
328 vector<function_info *> get_functions_at_location (unsigned line_num) const;
329
330 /* Index of the source_info in sources vector. */
331 unsigned index;
332
333 /* Canonical name of source file. */
334 char *name;
335 time_t file_time;
336
337 /* Vector of line information. */
338 vector<line_info> lines;
339
340 coverage_info coverage;
341
342 /* Functions in this source file. These are in ascending line
343 number order. */
344 vector <function_info *> functions;
345 };
346
347 source_info::source_info (): index (0), name (NULL), file_time (),
348 lines (), coverage (), functions ()
349 {
350 }
351
352 vector<function_info *>
353 source_info::get_functions_at_location (unsigned line_num) const
354 {
355 vector<function_info *> r;
356
357 for (vector<function_info *>::const_iterator it = functions.begin ();
358 it != functions.end (); it++)
359 {
360 if ((*it)->start_line == line_num && (*it)->src == index)
361 r.push_back (*it);
362 }
363
364 std::sort (r.begin (), r.end (), function_line_start_cmp ());
365
366 return r;
367 }
368
369 class name_map
370 {
371 public:
372 name_map ()
373 {
374 }
375
376 name_map (char *_name, unsigned _src): name (_name), src (_src)
377 {
378 }
379
380 bool operator== (const name_map &rhs) const
381 {
382 #if HAVE_DOS_BASED_FILE_SYSTEM
383 return strcasecmp (this->name, rhs.name) == 0;
384 #else
385 return strcmp (this->name, rhs.name) == 0;
386 #endif
387 }
388
389 bool operator< (const name_map &rhs) const
390 {
391 #if HAVE_DOS_BASED_FILE_SYSTEM
392 return strcasecmp (this->name, rhs.name) < 0;
393 #else
394 return strcmp (this->name, rhs.name) < 0;
395 #endif
396 }
397
398 const char *name; /* Source file name */
399 unsigned src; /* Source file */
400 };
401
402 /* Vector of all functions. */
403 static vector<function_info *> functions;
404
405 /* Vector of source files. */
406 static vector<source_info> sources;
407
408 /* Mapping of file names to sources */
409 static vector<name_map> names;
410
411 /* This holds data summary information. */
412
413 static unsigned object_runs;
414 static unsigned program_count;
415
416 static unsigned total_lines;
417 static unsigned total_executed;
418
419 /* Modification time of graph file. */
420
421 static time_t bbg_file_time;
422
423 /* Name of the notes (gcno) output file. The "bbg" prefix is for
424 historical reasons, when the notes file contained only the
425 basic block graph notes. */
426
427 static char *bbg_file_name;
428
429 /* Stamp of the bbg file */
430 static unsigned bbg_stamp;
431
432 /* Supports has_unexecuted_blocks functionality. */
433 static unsigned bbg_supports_has_unexecuted_blocks;
434
435 /* Working directory in which a TU was compiled. */
436 static const char *bbg_cwd;
437
438 /* Name and file pointer of the input file for the count data (gcda). */
439
440 static char *da_file_name;
441
442 /* Data file is missing. */
443
444 static int no_data_file;
445
446 /* If there is several input files, compute and display results after
447 reading all data files. This way if two or more gcda file refer to
448 the same source file (eg inline subprograms in a .h file), the
449 counts are added. */
450
451 static int multiple_files = 0;
452
453 /* Output branch probabilities. */
454
455 static int flag_branches = 0;
456
457 /* Show unconditional branches too. */
458 static int flag_unconditional = 0;
459
460 /* Output a gcov file if this is true. This is on by default, and can
461 be turned off by the -n option. */
462
463 static int flag_gcov_file = 1;
464
465 /* Output to stdout instead to a gcov file. */
466
467 static int flag_use_stdout = 0;
468
469 /* Output progress indication if this is true. This is off by default
470 and can be turned on by the -d option. */
471
472 static int flag_display_progress = 0;
473
474 /* Output *.gcov file in intermediate format used by 'lcov'. */
475
476 static int flag_intermediate_format = 0;
477
478 /* Output demangled function names. */
479
480 static int flag_demangled_names = 0;
481
482 /* For included files, make the gcov output file name include the name
483 of the input source file. For example, if x.h is included in a.c,
484 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
485
486 static int flag_long_names = 0;
487
488 /* For situations when a long name can potentially hit filesystem path limit,
489 let's calculate md5sum of the path and append it to a file name. */
490
491 static int flag_hash_filenames = 0;
492
493 /* Print verbose informations. */
494
495 static int flag_verbose = 0;
496
497 /* Print colored output. */
498
499 static int flag_use_colors = 0;
500
501 /* Output count information for every basic block, not merely those
502 that contain line number information. */
503
504 static int flag_all_blocks = 0;
505
506 /* Output human readable numbers. */
507
508 static int flag_human_readable_numbers = 0;
509
510 /* Output summary info for each function. */
511
512 static int flag_function_summary = 0;
513
514 /* Object directory file prefix. This is the directory/file where the
515 graph and data files are looked for, if nonzero. */
516
517 static char *object_directory = 0;
518
519 /* Source directory prefix. This is removed from source pathnames
520 that match, when generating the output file name. */
521
522 static char *source_prefix = 0;
523 static size_t source_length = 0;
524
525 /* Only show data for sources with relative pathnames. Absolute ones
526 usually indicate a system header file, which although it may
527 contain inline functions, is usually uninteresting. */
528 static int flag_relative_only = 0;
529
530 /* Preserve all pathname components. Needed when object files and
531 source files are in subdirectories. '/' is mangled as '#', '.' is
532 elided and '..' mangled to '^'. */
533
534 static int flag_preserve_paths = 0;
535
536 /* Output the number of times a branch was taken as opposed to the percentage
537 of times it was taken. */
538
539 static int flag_counts = 0;
540
541 /* Forward declarations. */
542 static int process_args (int, char **);
543 static void print_usage (int) ATTRIBUTE_NORETURN;
544 static void print_version (void) ATTRIBUTE_NORETURN;
545 static void process_file (const char *);
546 static void process_all_functions (void);
547 static void generate_results (const char *);
548 static void create_file_names (const char *);
549 static char *canonicalize_name (const char *);
550 static unsigned find_source (const char *);
551 static void read_graph_file (void);
552 static int read_count_file (void);
553 static void solve_flow_graph (function_info *);
554 static void find_exception_blocks (function_info *);
555 static void add_branch_counts (coverage_info *, const arc_info *);
556 static void add_line_counts (coverage_info *, function_info *);
557 static void executed_summary (unsigned, unsigned);
558 static void function_summary (const coverage_info *, const char *);
559 static const char *format_gcov (gcov_type, gcov_type, int);
560 static void accumulate_line_counts (source_info *);
561 static void output_gcov_file (const char *, source_info *);
562 static int output_branch_count (FILE *, int, const arc_info *);
563 static void output_lines (FILE *, const source_info *);
564 static char *make_gcov_file_name (const char *, const char *);
565 static char *mangle_name (const char *, char *);
566 static void release_structures (void);
567 extern int main (int, char **);
568
569 function_info::function_info (): name (NULL), demangled_name (NULL),
570 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
571 artificial (0), is_group (0),
572 blocks (), blocks_executed (0), counts (),
573 start_line (0), start_column (), end_line (0), src (0), lines (), next (NULL)
574 {
575 }
576
577 function_info::~function_info ()
578 {
579 for (int i = blocks.size () - 1; i >= 0; i--)
580 {
581 arc_info *arc, *arc_n;
582
583 for (arc = blocks[i].succ; arc; arc = arc_n)
584 {
585 arc_n = arc->succ_next;
586 free (arc);
587 }
588 }
589 if (flag_demangled_names && demangled_name != name)
590 free (demangled_name);
591 free (name);
592 }
593
594 bool function_info::group_line_p (unsigned n, unsigned src_idx)
595 {
596 return is_group && src == src_idx && start_line <= n && n <= end_line;
597 }
598
599 /* Cycle detection!
600 There are a bajillion algorithms that do this. Boost's function is named
601 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
602 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
603 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
604
605 The basic algorithm is simple: effectively, we're finding all simple paths
606 in a subgraph (that shrinks every iteration). Duplicates are filtered by
607 "blocking" a path when a node is added to the path (this also prevents non-
608 simple paths)--the node is unblocked only when it participates in a cycle.
609 */
610
611 typedef vector<arc_info *> arc_vector_t;
612 typedef vector<const block_info *> block_vector_t;
613
614 /* Enum with types of loop in CFG. */
615
616 enum loop_type
617 {
618 NO_LOOP = 0,
619 LOOP = 1,
620 NEGATIVE_LOOP = 3
621 };
622
623 /* Loop_type operator that merges two values: A and B. */
624
625 inline loop_type& operator |= (loop_type& a, loop_type b)
626 {
627 return a = static_cast<loop_type> (a | b);
628 }
629
630 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
631 and subtract the value from all counts. The subtracted value is added
632 to COUNT. Returns type of loop. */
633
634 static loop_type
635 handle_cycle (const arc_vector_t &edges, int64_t &count)
636 {
637 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
638 that amount. */
639 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
640 for (unsigned i = 0; i < edges.size (); i++)
641 {
642 int64_t ecount = edges[i]->cs_count;
643 if (cycle_count > ecount)
644 cycle_count = ecount;
645 }
646 count += cycle_count;
647 for (unsigned i = 0; i < edges.size (); i++)
648 edges[i]->cs_count -= cycle_count;
649
650 return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
651 }
652
653 /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
654 blocked by U in BLOCK_LISTS. */
655
656 static void
657 unblock (const block_info *u, block_vector_t &blocked,
658 vector<block_vector_t > &block_lists)
659 {
660 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
661 if (it == blocked.end ())
662 return;
663
664 unsigned index = it - blocked.begin ();
665 blocked.erase (it);
666
667 block_vector_t to_unblock (block_lists[index]);
668
669 block_lists.erase (block_lists.begin () + index);
670
671 for (block_vector_t::iterator it = to_unblock.begin ();
672 it != to_unblock.end (); it++)
673 unblock (*it, blocked, block_lists);
674 }
675
676 /* Find circuit going to block V, PATH is provisional seen cycle.
677 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
678 blocked by a block. COUNT is accumulated count of the current LINE.
679 Returns what type of loop it contains. */
680
681 static loop_type
682 circuit (block_info *v, arc_vector_t &path, block_info *start,
683 block_vector_t &blocked, vector<block_vector_t> &block_lists,
684 line_info &linfo, int64_t &count)
685 {
686 loop_type result = NO_LOOP;
687
688 /* Add v to the block list. */
689 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
690 blocked.push_back (v);
691 block_lists.push_back (block_vector_t ());
692
693 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
694 {
695 block_info *w = arc->dst;
696 if (w < start || !linfo.has_block (w))
697 continue;
698
699 path.push_back (arc);
700 if (w == start)
701 /* Cycle has been found. */
702 result |= handle_cycle (path, count);
703 else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
704 result |= circuit (w, path, start, blocked, block_lists, linfo, count);
705
706 path.pop_back ();
707 }
708
709 if (result != NO_LOOP)
710 unblock (v, blocked, block_lists);
711 else
712 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
713 {
714 block_info *w = arc->dst;
715 if (w < start || !linfo.has_block (w))
716 continue;
717
718 size_t index
719 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
720 gcc_assert (index < blocked.size ());
721 block_vector_t &list = block_lists[index];
722 if (find (list.begin (), list.end (), v) == list.end ())
723 list.push_back (v);
724 }
725
726 return result;
727 }
728
729 /* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
730 contains a negative loop, then perform the same function once again. */
731
732 static gcov_type
733 get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
734 {
735 /* Note that this algorithm works even if blocks aren't in sorted order.
736 Each iteration of the circuit detection is completely independent
737 (except for reducing counts, but that shouldn't matter anyways).
738 Therefore, operating on a permuted order (i.e., non-sorted) only
739 has the effect of permuting the output cycles. */
740
741 loop_type result = NO_LOOP;
742 gcov_type count = 0;
743 for (vector<block_info *>::iterator it = linfo.blocks.begin ();
744 it != linfo.blocks.end (); it++)
745 {
746 arc_vector_t path;
747 block_vector_t blocked;
748 vector<block_vector_t > block_lists;
749 result |= circuit (*it, path, *it, blocked, block_lists, linfo,
750 count);
751 }
752
753 /* If we have a negative cycle, repeat the find_cycles routine. */
754 if (result == NEGATIVE_LOOP && handle_negative_cycles)
755 count += get_cycles_count (linfo, false);
756
757 return count;
758 }
759
760 int
761 main (int argc, char **argv)
762 {
763 int argno;
764 int first_arg;
765 const char *p;
766
767 p = argv[0] + strlen (argv[0]);
768 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
769 --p;
770 progname = p;
771
772 xmalloc_set_program_name (progname);
773
774 /* Unlock the stdio streams. */
775 unlock_std_streams ();
776
777 gcc_init_libintl ();
778
779 diagnostic_initialize (global_dc, 0);
780
781 /* Handle response files. */
782 expandargv (&argc, &argv);
783
784 argno = process_args (argc, argv);
785 if (optind == argc)
786 print_usage (true);
787
788 if (argc - argno > 1)
789 multiple_files = 1;
790
791 first_arg = argno;
792
793 for (; argno != argc; argno++)
794 {
795 if (flag_display_progress)
796 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
797 argc - first_arg);
798 process_file (argv[argno]);
799
800 if (flag_intermediate_format || argno == argc - 1)
801 {
802 process_all_functions ();
803 generate_results (argv[argno]);
804 release_structures ();
805 }
806 }
807
808 return 0;
809 }
810 \f
811 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
812 otherwise the output of --help. */
813
814 static void
815 print_usage (int error_p)
816 {
817 FILE *file = error_p ? stderr : stdout;
818 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
819
820 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
821 fnotice (file, "Print code coverage information.\n\n");
822 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
823 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
824 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
825 rather than percentages\n");
826 fnotice (file, " -d, --display-progress Display progress information\n");
827 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
828 fnotice (file, " -h, --help Print this help, then exit\n");
829 fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
830 fnotice (file, " -j, --human-readable Output human readable numbers\n");
831 fnotice (file, " -k, --use-colors Emit colored output\n");
832 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
833 source files\n");
834 fnotice (file, " -m, --demangled-names Output demangled function names\n");
835 fnotice (file, " -n, --no-output Do not create an output file\n");
836 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
837 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
838 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
839 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
840 fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
841 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
842 fnotice (file, " -v, --version Print version number, then exit\n");
843 fnotice (file, " -w, --verbose Print verbose informations\n");
844 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
845 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
846 bug_report_url);
847 exit (status);
848 }
849
850 /* Print version information and exit. */
851
852 static void
853 print_version (void)
854 {
855 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
856 fprintf (stdout, "Copyright %s 2018 Free Software Foundation, Inc.\n",
857 _("(C)"));
858 fnotice (stdout,
859 _("This is free software; see the source for copying conditions.\n"
860 "There is NO warranty; not even for MERCHANTABILITY or \n"
861 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
862 exit (SUCCESS_EXIT_CODE);
863 }
864
865 static const struct option options[] =
866 {
867 { "help", no_argument, NULL, 'h' },
868 { "version", no_argument, NULL, 'v' },
869 { "verbose", no_argument, NULL, 'w' },
870 { "all-blocks", no_argument, NULL, 'a' },
871 { "branch-probabilities", no_argument, NULL, 'b' },
872 { "branch-counts", no_argument, NULL, 'c' },
873 { "intermediate-format", no_argument, NULL, 'i' },
874 { "human-readable", no_argument, NULL, 'j' },
875 { "no-output", no_argument, NULL, 'n' },
876 { "long-file-names", no_argument, NULL, 'l' },
877 { "function-summaries", no_argument, NULL, 'f' },
878 { "demangled-names", no_argument, NULL, 'm' },
879 { "preserve-paths", no_argument, NULL, 'p' },
880 { "relative-only", no_argument, NULL, 'r' },
881 { "object-directory", required_argument, NULL, 'o' },
882 { "object-file", required_argument, NULL, 'o' },
883 { "source-prefix", required_argument, NULL, 's' },
884 { "stdout", no_argument, NULL, 't' },
885 { "unconditional-branches", no_argument, NULL, 'u' },
886 { "display-progress", no_argument, NULL, 'd' },
887 { "hash-filenames", no_argument, NULL, 'x' },
888 { "use-colors", no_argument, NULL, 'k' },
889 { 0, 0, 0, 0 }
890 };
891
892 /* Process args, return index to first non-arg. */
893
894 static int
895 process_args (int argc, char **argv)
896 {
897 int opt;
898
899 const char *opts = "abcdfhijklmno:prs:tuvwx";
900 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
901 {
902 switch (opt)
903 {
904 case 'a':
905 flag_all_blocks = 1;
906 break;
907 case 'b':
908 flag_branches = 1;
909 break;
910 case 'c':
911 flag_counts = 1;
912 break;
913 case 'f':
914 flag_function_summary = 1;
915 break;
916 case 'h':
917 print_usage (false);
918 /* print_usage will exit. */
919 case 'l':
920 flag_long_names = 1;
921 break;
922 case 'j':
923 flag_human_readable_numbers = 1;
924 break;
925 case 'k':
926 flag_use_colors = 1;
927 break;
928 case 'm':
929 flag_demangled_names = 1;
930 break;
931 case 'n':
932 flag_gcov_file = 0;
933 break;
934 case 'o':
935 object_directory = optarg;
936 break;
937 case 's':
938 source_prefix = optarg;
939 source_length = strlen (source_prefix);
940 break;
941 case 'r':
942 flag_relative_only = 1;
943 break;
944 case 'p':
945 flag_preserve_paths = 1;
946 break;
947 case 'u':
948 flag_unconditional = 1;
949 break;
950 case 'i':
951 flag_intermediate_format = 1;
952 flag_gcov_file = 1;
953 break;
954 case 'd':
955 flag_display_progress = 1;
956 break;
957 case 'x':
958 flag_hash_filenames = 1;
959 break;
960 case 'w':
961 flag_verbose = 1;
962 break;
963 case 't':
964 flag_use_stdout = 1;
965 break;
966 case 'v':
967 print_version ();
968 /* print_version will exit. */
969 default:
970 print_usage (true);
971 /* print_usage will exit. */
972 }
973 }
974
975 return optind;
976 }
977
978 /* Output intermediate LINE sitting on LINE_NUM to output file F. */
979
980 static void
981 output_intermediate_line (FILE *f, line_info *line, unsigned line_num)
982 {
983 if (!line->exists)
984 return;
985
986 fprintf (f, "lcount:%u,%s,%d\n", line_num,
987 format_gcov (line->count, 0, -1),
988 line->has_unexecuted_block);
989
990 vector<arc_info *>::const_iterator it;
991 if (flag_branches)
992 for (it = line->branches.begin (); it != line->branches.end ();
993 it++)
994 {
995 if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
996 {
997 const char *branch_type;
998 /* branch:<line_num>,<branch_coverage_infoype>
999 branch_coverage_infoype
1000 : notexec (Branch not executed)
1001 : taken (Branch executed and taken)
1002 : nottaken (Branch executed, but not taken)
1003 */
1004 if ((*it)->src->count)
1005 branch_type
1006 = ((*it)->count > 0) ? "taken" : "nottaken";
1007 else
1008 branch_type = "notexec";
1009 fprintf (f, "branch:%d,%s\n", line_num, branch_type);
1010 }
1011 }
1012 }
1013
1014 /* Get the name of the gcov file. The return value must be free'd.
1015
1016 It appends the '.gcov' extension to the *basename* of the file.
1017 The resulting file name will be in PWD.
1018
1019 e.g.,
1020 input: foo.da, output: foo.da.gcov
1021 input: a/b/foo.cc, output: foo.cc.gcov */
1022
1023 static char *
1024 get_gcov_intermediate_filename (const char *file_name)
1025 {
1026 const char *gcov = ".gcov";
1027 char *result;
1028 const char *cptr;
1029
1030 /* Find the 'basename'. */
1031 cptr = lbasename (file_name);
1032
1033 result = XNEWVEC (char, strlen (cptr) + strlen (gcov) + 1);
1034 sprintf (result, "%s%s", cptr, gcov);
1035
1036 return result;
1037 }
1038
1039 /* Output the result in intermediate format used by 'lcov'.
1040
1041 The intermediate format contains a single file named 'foo.cc.gcov',
1042 with no source code included.
1043
1044 The default gcov outputs multiple files: 'foo.cc.gcov',
1045 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
1046 included. Instead the intermediate format here outputs only a single
1047 file 'foo.cc.gcov' similar to the above example. */
1048
1049 static void
1050 output_intermediate_file (FILE *gcov_file, source_info *src)
1051 {
1052 fprintf (gcov_file, "version:%s\n", version_string);
1053 fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
1054 fprintf (gcov_file, "cwd:%s\n", bbg_cwd);
1055
1056 std::sort (src->functions.begin (), src->functions.end (),
1057 function_line_start_cmp ());
1058 for (vector<function_info *>::iterator it = src->functions.begin ();
1059 it != src->functions.end (); it++)
1060 {
1061 /* function:<name>,<line_number>,<execution_count> */
1062 fprintf (gcov_file, "function:%d,%d,%s,%s\n", (*it)->start_line,
1063 (*it)->end_line, format_gcov ((*it)->blocks[0].count, 0, -1),
1064 flag_demangled_names ? (*it)->demangled_name : (*it)->name);
1065 }
1066
1067 for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
1068 {
1069 vector<function_info *> fns = src->get_functions_at_location (line_num);
1070
1071 /* Print first group functions that begin on the line. */
1072 for (vector<function_info *>::iterator it2 = fns.begin ();
1073 it2 != fns.end (); it2++)
1074 {
1075 vector<line_info> &lines = (*it2)->lines;
1076 for (unsigned i = 0; i < lines.size (); i++)
1077 {
1078 line_info *line = &lines[i];
1079 output_intermediate_line (gcov_file, line, line_num + i);
1080 }
1081 }
1082
1083 /* Follow with lines associated with the source file. */
1084 output_intermediate_line (gcov_file, &src->lines[line_num], line_num);
1085 }
1086 }
1087
1088 /* Function start pair. */
1089 struct function_start
1090 {
1091 unsigned source_file_idx;
1092 unsigned start_line;
1093 };
1094
1095 /* Traits class for function start hash maps below. */
1096
1097 struct function_start_pair_hash : typed_noop_remove <function_start>
1098 {
1099 typedef function_start value_type;
1100 typedef function_start compare_type;
1101
1102 static hashval_t
1103 hash (const function_start &ref)
1104 {
1105 inchash::hash hstate (0);
1106 hstate.add_int (ref.source_file_idx);
1107 hstate.add_int (ref.start_line);
1108 return hstate.end ();
1109 }
1110
1111 static bool
1112 equal (const function_start &ref1, const function_start &ref2)
1113 {
1114 return (ref1.source_file_idx == ref2.source_file_idx
1115 && ref1.start_line == ref2.start_line);
1116 }
1117
1118 static void
1119 mark_deleted (function_start &ref)
1120 {
1121 ref.start_line = ~1U;
1122 }
1123
1124 static void
1125 mark_empty (function_start &ref)
1126 {
1127 ref.start_line = ~2U;
1128 }
1129
1130 static bool
1131 is_deleted (const function_start &ref)
1132 {
1133 return ref.start_line == ~1U;
1134 }
1135
1136 static bool
1137 is_empty (const function_start &ref)
1138 {
1139 return ref.start_line == ~2U;
1140 }
1141 };
1142
1143 /* Process a single input file. */
1144
1145 static void
1146 process_file (const char *file_name)
1147 {
1148 create_file_names (file_name);
1149 read_graph_file ();
1150 read_count_file ();
1151 }
1152
1153 /* Process all functions in all files. */
1154
1155 static void
1156 process_all_functions (void)
1157 {
1158 hash_map<function_start_pair_hash, function_info *> fn_map;
1159
1160 /* Identify group functions. */
1161 for (vector<function_info *>::iterator it = functions.begin ();
1162 it != functions.end (); it++)
1163 if (!(*it)->artificial)
1164 {
1165 function_start needle;
1166 needle.source_file_idx = (*it)->src;
1167 needle.start_line = (*it)->start_line;
1168
1169 function_info **slot = fn_map.get (needle);
1170 if (slot)
1171 {
1172 (*slot)->is_group = 1;
1173 (*it)->is_group = 1;
1174 }
1175 else
1176 fn_map.put (needle, *it);
1177 }
1178
1179 /* Remove all artificial function. */
1180 functions.erase (remove_if (functions.begin (), functions.end (),
1181 function_info::is_artificial), functions.end ());
1182
1183 for (vector<function_info *>::iterator it = functions.begin ();
1184 it != functions.end (); it++)
1185 {
1186 function_info *fn = *it;
1187 unsigned src = fn->src;
1188
1189 if (!fn->counts.empty () || no_data_file)
1190 {
1191 source_info *s = &sources[src];
1192 s->functions.push_back (fn);
1193
1194 /* Mark last line in files touched by function. */
1195 for (unsigned block_no = 0; block_no != fn->blocks.size ();
1196 block_no++)
1197 {
1198 block_info *block = &fn->blocks[block_no];
1199 for (unsigned i = 0; i < block->locations.size (); i++)
1200 {
1201 /* Sort lines of locations. */
1202 sort (block->locations[i].lines.begin (),
1203 block->locations[i].lines.end ());
1204
1205 if (!block->locations[i].lines.empty ())
1206 {
1207 s = &sources[block->locations[i].source_file_idx];
1208 unsigned last_line
1209 = block->locations[i].lines.back ();
1210
1211 /* Record new lines for the function. */
1212 if (last_line >= s->lines.size ())
1213 {
1214 s = &sources[block->locations[i].source_file_idx];
1215 unsigned last_line
1216 = block->locations[i].lines.back ();
1217
1218 /* Record new lines for the function. */
1219 if (last_line >= s->lines.size ())
1220 {
1221 /* Record new lines for a source file. */
1222 s->lines.resize (last_line + 1);
1223 }
1224 }
1225 }
1226 }
1227 }
1228
1229 /* Allocate lines for group function, following start_line
1230 and end_line information of the function. */
1231 if (fn->is_group)
1232 fn->lines.resize (fn->end_line - fn->start_line + 1);
1233
1234 solve_flow_graph (fn);
1235 if (fn->has_catch)
1236 find_exception_blocks (fn);
1237 }
1238 else
1239 {
1240 /* The function was not in the executable -- some other
1241 instance must have been selected. */
1242 }
1243 }
1244 }
1245
1246 static void
1247 output_gcov_file (const char *file_name, source_info *src)
1248 {
1249 char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
1250
1251 if (src->coverage.lines)
1252 {
1253 FILE *gcov_file = fopen (gcov_file_name, "w");
1254 if (gcov_file)
1255 {
1256 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
1257 output_lines (gcov_file, src);
1258 if (ferror (gcov_file))
1259 fnotice (stderr, "Error writing output file '%s'\n",
1260 gcov_file_name);
1261 fclose (gcov_file);
1262 }
1263 else
1264 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1265 }
1266 else
1267 {
1268 unlink (gcov_file_name);
1269 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1270 }
1271 free (gcov_file_name);
1272 }
1273
1274 static void
1275 generate_results (const char *file_name)
1276 {
1277 FILE *gcov_intermediate_file = NULL;
1278 char *gcov_intermediate_filename = NULL;
1279
1280 for (vector<function_info *>::iterator it = functions.begin ();
1281 it != functions.end (); it++)
1282 {
1283 function_info *fn = *it;
1284 coverage_info coverage;
1285
1286 memset (&coverage, 0, sizeof (coverage));
1287 coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
1288 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1289 if (flag_function_summary)
1290 {
1291 function_summary (&coverage, "Function");
1292 fnotice (stdout, "\n");
1293 }
1294 }
1295
1296 name_map needle;
1297
1298 if (file_name)
1299 {
1300 needle.name = file_name;
1301 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1302 needle);
1303 if (it != names.end ())
1304 file_name = sources[it->src].coverage.name;
1305 else
1306 file_name = canonicalize_name (file_name);
1307 }
1308
1309 if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout)
1310 {
1311 /* Open the intermediate file. */
1312 gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
1313 gcov_intermediate_file = fopen (gcov_intermediate_filename, "w");
1314 if (!gcov_intermediate_file)
1315 {
1316 fnotice (stderr, "Cannot open intermediate output file %s\n",
1317 gcov_intermediate_filename);
1318 return;
1319 }
1320 }
1321
1322 for (vector<source_info>::iterator it = sources.begin ();
1323 it != sources.end (); it++)
1324 {
1325 source_info *src = &(*it);
1326 if (flag_relative_only)
1327 {
1328 /* Ignore this source, if it is an absolute path (after
1329 source prefix removal). */
1330 char first = src->coverage.name[0];
1331
1332 #if HAVE_DOS_BASED_FILE_SYSTEM
1333 if (first && src->coverage.name[1] == ':')
1334 first = src->coverage.name[2];
1335 #endif
1336 if (IS_DIR_SEPARATOR (first))
1337 continue;
1338 }
1339
1340 accumulate_line_counts (src);
1341
1342 if (!flag_use_stdout)
1343 function_summary (&src->coverage, "File");
1344 total_lines += src->coverage.lines;
1345 total_executed += src->coverage.lines_executed;
1346 if (flag_gcov_file)
1347 {
1348 if (flag_intermediate_format)
1349 /* Output the intermediate format without requiring source
1350 files. This outputs a section to a *single* file. */
1351 output_intermediate_file ((flag_use_stdout
1352 ? stdout : gcov_intermediate_file), src);
1353 else
1354 {
1355 if (flag_use_stdout)
1356 {
1357 if (src->coverage.lines)
1358 output_lines (stdout, src);
1359 }
1360 else
1361 {
1362 output_gcov_file (file_name, src);
1363 fnotice (stdout, "\n");
1364 }
1365 }
1366 }
1367 }
1368
1369 if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout)
1370 {
1371 /* Now we've finished writing the intermediate file. */
1372 fclose (gcov_intermediate_file);
1373 XDELETEVEC (gcov_intermediate_filename);
1374 }
1375
1376 if (!file_name)
1377 executed_summary (total_lines, total_executed);
1378 }
1379
1380 /* Release all memory used. */
1381
1382 static void
1383 release_structures (void)
1384 {
1385 for (vector<function_info *>::iterator it = functions.begin ();
1386 it != functions.end (); it++)
1387 delete (*it);
1388
1389 sources.resize (0);
1390 names.resize (0);
1391 functions.resize (0);
1392 }
1393
1394 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1395 is not specified, these are named from FILE_NAME sans extension. If
1396 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1397 directory, but named from the basename of the FILE_NAME, sans extension.
1398 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1399 and the data files are named from that. */
1400
1401 static void
1402 create_file_names (const char *file_name)
1403 {
1404 char *cptr;
1405 char *name;
1406 int length = strlen (file_name);
1407 int base;
1408
1409 /* Free previous file names. */
1410 free (bbg_file_name);
1411 free (da_file_name);
1412 da_file_name = bbg_file_name = NULL;
1413 bbg_file_time = 0;
1414 bbg_stamp = 0;
1415
1416 if (object_directory && object_directory[0])
1417 {
1418 struct stat status;
1419
1420 length += strlen (object_directory) + 2;
1421 name = XNEWVEC (char, length);
1422 name[0] = 0;
1423
1424 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1425 strcat (name, object_directory);
1426 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1427 strcat (name, "/");
1428 }
1429 else
1430 {
1431 name = XNEWVEC (char, length + 1);
1432 strcpy (name, file_name);
1433 base = 0;
1434 }
1435
1436 if (base)
1437 {
1438 /* Append source file name. */
1439 const char *cptr = lbasename (file_name);
1440 strcat (name, cptr ? cptr : file_name);
1441 }
1442
1443 /* Remove the extension. */
1444 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1445 if (cptr)
1446 *cptr = 0;
1447
1448 length = strlen (name);
1449
1450 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1451 strcpy (bbg_file_name, name);
1452 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1453
1454 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1455 strcpy (da_file_name, name);
1456 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1457
1458 free (name);
1459 return;
1460 }
1461
1462 /* Find or create a source file structure for FILE_NAME. Copies
1463 FILE_NAME on creation */
1464
1465 static unsigned
1466 find_source (const char *file_name)
1467 {
1468 char *canon;
1469 unsigned idx;
1470 struct stat status;
1471
1472 if (!file_name)
1473 file_name = "<unknown>";
1474
1475 name_map needle;
1476 needle.name = file_name;
1477
1478 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1479 needle);
1480 if (it != names.end ())
1481 {
1482 idx = it->src;
1483 goto check_date;
1484 }
1485
1486 /* Not found, try the canonical name. */
1487 canon = canonicalize_name (file_name);
1488 needle.name = canon;
1489 it = std::find (names.begin (), names.end (), needle);
1490 if (it == names.end ())
1491 {
1492 /* Not found with canonical name, create a new source. */
1493 source_info *src;
1494
1495 idx = sources.size ();
1496 needle = name_map (canon, idx);
1497 names.push_back (needle);
1498
1499 sources.push_back (source_info ());
1500 src = &sources.back ();
1501 src->name = canon;
1502 src->coverage.name = src->name;
1503 src->index = idx;
1504 if (source_length
1505 #if HAVE_DOS_BASED_FILE_SYSTEM
1506 /* You lose if separators don't match exactly in the
1507 prefix. */
1508 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1509 #else
1510 && !strncmp (source_prefix, src->coverage.name, source_length)
1511 #endif
1512 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1513 src->coverage.name += source_length + 1;
1514 if (!stat (src->name, &status))
1515 src->file_time = status.st_mtime;
1516 }
1517 else
1518 idx = it->src;
1519
1520 needle.name = file_name;
1521 if (std::find (names.begin (), names.end (), needle) == names.end ())
1522 {
1523 /* Append the non-canonical name. */
1524 names.push_back (name_map (xstrdup (file_name), idx));
1525 }
1526
1527 /* Resort the name map. */
1528 std::sort (names.begin (), names.end ());
1529
1530 check_date:
1531 if (sources[idx].file_time > bbg_file_time)
1532 {
1533 static int info_emitted;
1534
1535 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1536 file_name, bbg_file_name);
1537 if (!info_emitted)
1538 {
1539 fnotice (stderr,
1540 "(the message is displayed only once per source file)\n");
1541 info_emitted = 1;
1542 }
1543 sources[idx].file_time = 0;
1544 }
1545
1546 return idx;
1547 }
1548
1549 /* Read the notes file. Save functions to FUNCTIONS global vector. */
1550
1551 static void
1552 read_graph_file (void)
1553 {
1554 unsigned version;
1555 unsigned current_tag = 0;
1556 unsigned tag;
1557
1558 if (!gcov_open (bbg_file_name, 1))
1559 {
1560 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1561 return;
1562 }
1563 bbg_file_time = gcov_time ();
1564 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1565 {
1566 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1567 gcov_close ();
1568 return;
1569 }
1570
1571 version = gcov_read_unsigned ();
1572 if (version != GCOV_VERSION)
1573 {
1574 char v[4], e[4];
1575
1576 GCOV_UNSIGNED2STRING (v, version);
1577 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1578
1579 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1580 bbg_file_name, v, e);
1581 }
1582 bbg_stamp = gcov_read_unsigned ();
1583 bbg_cwd = xstrdup (gcov_read_string ());
1584 bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
1585
1586 function_info *fn = NULL;
1587 while ((tag = gcov_read_unsigned ()))
1588 {
1589 unsigned length = gcov_read_unsigned ();
1590 gcov_position_t base = gcov_position ();
1591
1592 if (tag == GCOV_TAG_FUNCTION)
1593 {
1594 char *function_name;
1595 unsigned ident;
1596 unsigned lineno_checksum, cfg_checksum;
1597
1598 ident = gcov_read_unsigned ();
1599 lineno_checksum = gcov_read_unsigned ();
1600 cfg_checksum = gcov_read_unsigned ();
1601 function_name = xstrdup (gcov_read_string ());
1602 unsigned artificial = gcov_read_unsigned ();
1603 unsigned src_idx = find_source (gcov_read_string ());
1604 unsigned start_line = gcov_read_unsigned ();
1605 unsigned start_column = gcov_read_unsigned ();
1606 unsigned end_line = gcov_read_unsigned ();
1607
1608 fn = new function_info ();
1609 functions.push_back (fn);
1610 fn->name = function_name;
1611 if (flag_demangled_names)
1612 {
1613 fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1614 if (!fn->demangled_name)
1615 fn->demangled_name = fn->name;
1616 }
1617 fn->ident = ident;
1618 fn->lineno_checksum = lineno_checksum;
1619 fn->cfg_checksum = cfg_checksum;
1620 fn->src = src_idx;
1621 fn->start_line = start_line;
1622 fn->start_column = start_column;
1623 fn->end_line = end_line;
1624 fn->artificial = artificial;
1625
1626 current_tag = tag;
1627 }
1628 else if (fn && tag == GCOV_TAG_BLOCKS)
1629 {
1630 if (!fn->blocks.empty ())
1631 fnotice (stderr, "%s:already seen blocks for '%s'\n",
1632 bbg_file_name, fn->name);
1633 else
1634 fn->blocks.resize (gcov_read_unsigned ());
1635 }
1636 else if (fn && tag == GCOV_TAG_ARCS)
1637 {
1638 unsigned src = gcov_read_unsigned ();
1639 fn->blocks[src].id = src;
1640 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1641 block_info *src_blk = &fn->blocks[src];
1642 unsigned mark_catches = 0;
1643 struct arc_info *arc;
1644
1645 if (src >= fn->blocks.size () || fn->blocks[src].succ)
1646 goto corrupt;
1647
1648 while (num_dests--)
1649 {
1650 unsigned dest = gcov_read_unsigned ();
1651 unsigned flags = gcov_read_unsigned ();
1652
1653 if (dest >= fn->blocks.size ())
1654 goto corrupt;
1655 arc = XCNEW (arc_info);
1656
1657 arc->dst = &fn->blocks[dest];
1658 arc->src = src_blk;
1659
1660 arc->count = 0;
1661 arc->count_valid = 0;
1662 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1663 arc->fake = !!(flags & GCOV_ARC_FAKE);
1664 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1665
1666 arc->succ_next = src_blk->succ;
1667 src_blk->succ = arc;
1668 src_blk->num_succ++;
1669
1670 arc->pred_next = fn->blocks[dest].pred;
1671 fn->blocks[dest].pred = arc;
1672 fn->blocks[dest].num_pred++;
1673
1674 if (arc->fake)
1675 {
1676 if (src)
1677 {
1678 /* Exceptional exit from this function, the
1679 source block must be a call. */
1680 fn->blocks[src].is_call_site = 1;
1681 arc->is_call_non_return = 1;
1682 mark_catches = 1;
1683 }
1684 else
1685 {
1686 /* Non-local return from a callee of this
1687 function. The destination block is a setjmp. */
1688 arc->is_nonlocal_return = 1;
1689 fn->blocks[dest].is_nonlocal_return = 1;
1690 }
1691 }
1692
1693 if (!arc->on_tree)
1694 fn->counts.push_back (0);
1695 }
1696
1697 if (mark_catches)
1698 {
1699 /* We have a fake exit from this block. The other
1700 non-fall through exits must be to catch handlers.
1701 Mark them as catch arcs. */
1702
1703 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1704 if (!arc->fake && !arc->fall_through)
1705 {
1706 arc->is_throw = 1;
1707 fn->has_catch = 1;
1708 }
1709 }
1710 }
1711 else if (fn && tag == GCOV_TAG_LINES)
1712 {
1713 unsigned blockno = gcov_read_unsigned ();
1714 block_info *block = &fn->blocks[blockno];
1715
1716 if (blockno >= fn->blocks.size ())
1717 goto corrupt;
1718
1719 while (true)
1720 {
1721 unsigned lineno = gcov_read_unsigned ();
1722
1723 if (lineno)
1724 block->locations.back ().lines.push_back (lineno);
1725 else
1726 {
1727 const char *file_name = gcov_read_string ();
1728
1729 if (!file_name)
1730 break;
1731 block->locations.push_back (block_location_info
1732 (find_source (file_name)));
1733 }
1734 }
1735 }
1736 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1737 {
1738 fn = NULL;
1739 current_tag = 0;
1740 }
1741 gcov_sync (base, length);
1742 if (gcov_is_error ())
1743 {
1744 corrupt:;
1745 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1746 break;
1747 }
1748 }
1749 gcov_close ();
1750
1751 if (functions.empty ())
1752 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1753 }
1754
1755 /* Reads profiles from the count file and attach to each
1756 function. Return nonzero if fatal error. */
1757
1758 static int
1759 read_count_file (void)
1760 {
1761 unsigned ix;
1762 unsigned version;
1763 unsigned tag;
1764 function_info *fn = NULL;
1765 int error = 0;
1766
1767 if (!gcov_open (da_file_name, 1))
1768 {
1769 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1770 da_file_name);
1771 no_data_file = 1;
1772 return 0;
1773 }
1774 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1775 {
1776 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1777 cleanup:;
1778 gcov_close ();
1779 return 1;
1780 }
1781 version = gcov_read_unsigned ();
1782 if (version != GCOV_VERSION)
1783 {
1784 char v[4], e[4];
1785
1786 GCOV_UNSIGNED2STRING (v, version);
1787 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1788
1789 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1790 da_file_name, v, e);
1791 }
1792 tag = gcov_read_unsigned ();
1793 if (tag != bbg_stamp)
1794 {
1795 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1796 goto cleanup;
1797 }
1798
1799 while ((tag = gcov_read_unsigned ()))
1800 {
1801 unsigned length = gcov_read_unsigned ();
1802 unsigned long base = gcov_position ();
1803
1804 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1805 {
1806 struct gcov_summary summary;
1807 gcov_read_summary (&summary);
1808 object_runs += summary.runs;
1809 program_count++;
1810 }
1811 else if (tag == GCOV_TAG_FUNCTION && !length)
1812 ; /* placeholder */
1813 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1814 {
1815 unsigned ident;
1816
1817 /* Try to find the function in the list. To speed up the
1818 search, first start from the last function found. */
1819 ident = gcov_read_unsigned ();
1820
1821 fn = NULL;
1822 for (vector<function_info *>::reverse_iterator it
1823 = functions.rbegin (); it != functions.rend (); it++)
1824 {
1825 if ((*it)->ident == ident)
1826 {
1827 fn = *it;
1828 break;
1829 }
1830 }
1831
1832 if (!fn)
1833 ;
1834 else if (gcov_read_unsigned () != fn->lineno_checksum
1835 || gcov_read_unsigned () != fn->cfg_checksum)
1836 {
1837 mismatch:;
1838 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1839 da_file_name, fn->name);
1840 goto cleanup;
1841 }
1842 }
1843 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1844 {
1845 if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
1846 goto mismatch;
1847
1848 for (ix = 0; ix != fn->counts.size (); ix++)
1849 fn->counts[ix] += gcov_read_counter ();
1850 }
1851 gcov_sync (base, length);
1852 if ((error = gcov_is_error ()))
1853 {
1854 fnotice (stderr,
1855 error < 0
1856 ? N_("%s:overflowed\n")
1857 : N_("%s:corrupted\n"),
1858 da_file_name);
1859 goto cleanup;
1860 }
1861 }
1862
1863 gcov_close ();
1864 return 0;
1865 }
1866
1867 /* Solve the flow graph. Propagate counts from the instrumented arcs
1868 to the blocks and the uninstrumented arcs. */
1869
1870 static void
1871 solve_flow_graph (function_info *fn)
1872 {
1873 unsigned ix;
1874 arc_info *arc;
1875 gcov_type *count_ptr = &fn->counts.front ();
1876 block_info *blk;
1877 block_info *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1878 block_info *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1879
1880 /* The arcs were built in reverse order. Fix that now. */
1881 for (ix = fn->blocks.size (); ix--;)
1882 {
1883 arc_info *arc_p, *arc_n;
1884
1885 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1886 arc_p = arc, arc = arc_n)
1887 {
1888 arc_n = arc->succ_next;
1889 arc->succ_next = arc_p;
1890 }
1891 fn->blocks[ix].succ = arc_p;
1892
1893 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1894 arc_p = arc, arc = arc_n)
1895 {
1896 arc_n = arc->pred_next;
1897 arc->pred_next = arc_p;
1898 }
1899 fn->blocks[ix].pred = arc_p;
1900 }
1901
1902 if (fn->blocks.size () < 2)
1903 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1904 bbg_file_name, fn->name);
1905 else
1906 {
1907 if (fn->blocks[ENTRY_BLOCK].num_pred)
1908 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1909 bbg_file_name, fn->name);
1910 else
1911 /* We can't deduce the entry block counts from the lack of
1912 predecessors. */
1913 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1914
1915 if (fn->blocks[EXIT_BLOCK].num_succ)
1916 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1917 bbg_file_name, fn->name);
1918 else
1919 /* Likewise, we can't deduce exit block counts from the lack
1920 of its successors. */
1921 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1922 }
1923
1924 /* Propagate the measured counts, this must be done in the same
1925 order as the code in profile.c */
1926 for (unsigned i = 0; i < fn->blocks.size (); i++)
1927 {
1928 blk = &fn->blocks[i];
1929 block_info const *prev_dst = NULL;
1930 int out_of_order = 0;
1931 int non_fake_succ = 0;
1932
1933 for (arc = blk->succ; arc; arc = arc->succ_next)
1934 {
1935 if (!arc->fake)
1936 non_fake_succ++;
1937
1938 if (!arc->on_tree)
1939 {
1940 if (count_ptr)
1941 arc->count = *count_ptr++;
1942 arc->count_valid = 1;
1943 blk->num_succ--;
1944 arc->dst->num_pred--;
1945 }
1946 if (prev_dst && prev_dst > arc->dst)
1947 out_of_order = 1;
1948 prev_dst = arc->dst;
1949 }
1950 if (non_fake_succ == 1)
1951 {
1952 /* If there is only one non-fake exit, it is an
1953 unconditional branch. */
1954 for (arc = blk->succ; arc; arc = arc->succ_next)
1955 if (!arc->fake)
1956 {
1957 arc->is_unconditional = 1;
1958 /* If this block is instrumenting a call, it might be
1959 an artificial block. It is not artificial if it has
1960 a non-fallthrough exit, or the destination of this
1961 arc has more than one entry. Mark the destination
1962 block as a return site, if none of those conditions
1963 hold. */
1964 if (blk->is_call_site && arc->fall_through
1965 && arc->dst->pred == arc && !arc->pred_next)
1966 arc->dst->is_call_return = 1;
1967 }
1968 }
1969
1970 /* Sort the successor arcs into ascending dst order. profile.c
1971 normally produces arcs in the right order, but sometimes with
1972 one or two out of order. We're not using a particularly
1973 smart sort. */
1974 if (out_of_order)
1975 {
1976 arc_info *start = blk->succ;
1977 unsigned changes = 1;
1978
1979 while (changes)
1980 {
1981 arc_info *arc, *arc_p, *arc_n;
1982
1983 changes = 0;
1984 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1985 {
1986 if (arc->dst > arc_n->dst)
1987 {
1988 changes = 1;
1989 if (arc_p)
1990 arc_p->succ_next = arc_n;
1991 else
1992 start = arc_n;
1993 arc->succ_next = arc_n->succ_next;
1994 arc_n->succ_next = arc;
1995 arc_p = arc_n;
1996 }
1997 else
1998 {
1999 arc_p = arc;
2000 arc = arc_n;
2001 }
2002 }
2003 }
2004 blk->succ = start;
2005 }
2006
2007 /* Place it on the invalid chain, it will be ignored if that's
2008 wrong. */
2009 blk->invalid_chain = 1;
2010 blk->chain = invalid_blocks;
2011 invalid_blocks = blk;
2012 }
2013
2014 while (invalid_blocks || valid_blocks)
2015 {
2016 while ((blk = invalid_blocks))
2017 {
2018 gcov_type total = 0;
2019 const arc_info *arc;
2020
2021 invalid_blocks = blk->chain;
2022 blk->invalid_chain = 0;
2023 if (!blk->num_succ)
2024 for (arc = blk->succ; arc; arc = arc->succ_next)
2025 total += arc->count;
2026 else if (!blk->num_pred)
2027 for (arc = blk->pred; arc; arc = arc->pred_next)
2028 total += arc->count;
2029 else
2030 continue;
2031
2032 blk->count = total;
2033 blk->count_valid = 1;
2034 blk->chain = valid_blocks;
2035 blk->valid_chain = 1;
2036 valid_blocks = blk;
2037 }
2038 while ((blk = valid_blocks))
2039 {
2040 gcov_type total;
2041 arc_info *arc, *inv_arc;
2042
2043 valid_blocks = blk->chain;
2044 blk->valid_chain = 0;
2045 if (blk->num_succ == 1)
2046 {
2047 block_info *dst;
2048
2049 total = blk->count;
2050 inv_arc = NULL;
2051 for (arc = blk->succ; arc; arc = arc->succ_next)
2052 {
2053 total -= arc->count;
2054 if (!arc->count_valid)
2055 inv_arc = arc;
2056 }
2057 dst = inv_arc->dst;
2058 inv_arc->count_valid = 1;
2059 inv_arc->count = total;
2060 blk->num_succ--;
2061 dst->num_pred--;
2062 if (dst->count_valid)
2063 {
2064 if (dst->num_pred == 1 && !dst->valid_chain)
2065 {
2066 dst->chain = valid_blocks;
2067 dst->valid_chain = 1;
2068 valid_blocks = dst;
2069 }
2070 }
2071 else
2072 {
2073 if (!dst->num_pred && !dst->invalid_chain)
2074 {
2075 dst->chain = invalid_blocks;
2076 dst->invalid_chain = 1;
2077 invalid_blocks = dst;
2078 }
2079 }
2080 }
2081 if (blk->num_pred == 1)
2082 {
2083 block_info *src;
2084
2085 total = blk->count;
2086 inv_arc = NULL;
2087 for (arc = blk->pred; arc; arc = arc->pred_next)
2088 {
2089 total -= arc->count;
2090 if (!arc->count_valid)
2091 inv_arc = arc;
2092 }
2093 src = inv_arc->src;
2094 inv_arc->count_valid = 1;
2095 inv_arc->count = total;
2096 blk->num_pred--;
2097 src->num_succ--;
2098 if (src->count_valid)
2099 {
2100 if (src->num_succ == 1 && !src->valid_chain)
2101 {
2102 src->chain = valid_blocks;
2103 src->valid_chain = 1;
2104 valid_blocks = src;
2105 }
2106 }
2107 else
2108 {
2109 if (!src->num_succ && !src->invalid_chain)
2110 {
2111 src->chain = invalid_blocks;
2112 src->invalid_chain = 1;
2113 invalid_blocks = src;
2114 }
2115 }
2116 }
2117 }
2118 }
2119
2120 /* If the graph has been correctly solved, every block will have a
2121 valid count. */
2122 for (unsigned i = 0; ix < fn->blocks.size (); i++)
2123 if (!fn->blocks[i].count_valid)
2124 {
2125 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
2126 bbg_file_name, fn->name);
2127 break;
2128 }
2129 }
2130
2131 /* Mark all the blocks only reachable via an incoming catch. */
2132
2133 static void
2134 find_exception_blocks (function_info *fn)
2135 {
2136 unsigned ix;
2137 block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ());
2138
2139 /* First mark all blocks as exceptional. */
2140 for (ix = fn->blocks.size (); ix--;)
2141 fn->blocks[ix].exceptional = 1;
2142
2143 /* Now mark all the blocks reachable via non-fake edges */
2144 queue[0] = &fn->blocks[0];
2145 queue[0]->exceptional = 0;
2146 for (ix = 1; ix;)
2147 {
2148 block_info *block = queue[--ix];
2149 const arc_info *arc;
2150
2151 for (arc = block->succ; arc; arc = arc->succ_next)
2152 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
2153 {
2154 arc->dst->exceptional = 0;
2155 queue[ix++] = arc->dst;
2156 }
2157 }
2158 }
2159 \f
2160
2161 /* Increment totals in COVERAGE according to arc ARC. */
2162
2163 static void
2164 add_branch_counts (coverage_info *coverage, const arc_info *arc)
2165 {
2166 if (arc->is_call_non_return)
2167 {
2168 coverage->calls++;
2169 if (arc->src->count)
2170 coverage->calls_executed++;
2171 }
2172 else if (!arc->is_unconditional)
2173 {
2174 coverage->branches++;
2175 if (arc->src->count)
2176 coverage->branches_executed++;
2177 if (arc->count)
2178 coverage->branches_taken++;
2179 }
2180 }
2181
2182 /* Format COUNT, if flag_human_readable_numbers is set, return it human
2183 readable format. */
2184
2185 static char const *
2186 format_count (gcov_type count)
2187 {
2188 static char buffer[64];
2189 const char *units = " kMGTPEZY";
2190
2191 if (count < 1000 || !flag_human_readable_numbers)
2192 {
2193 sprintf (buffer, "%" PRId64, count);
2194 return buffer;
2195 }
2196
2197 unsigned i;
2198 gcov_type divisor = 1;
2199 for (i = 0; units[i+1]; i++, divisor *= 1000)
2200 {
2201 if (count + divisor / 2 < 1000 * divisor)
2202 break;
2203 }
2204 gcov_type r = (count + divisor / 2) / divisor;
2205 sprintf (buffer, "%" PRId64 "%c", r, units[i]);
2206 return buffer;
2207 }
2208
2209 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
2210 count. If DECIMAL_PLACES >= 0, format TOP/BOTTOM * 100 to DECIMAL_PLACES.
2211 If DECIMAL_PLACES is zero, no decimal point is printed. Only print 100% when
2212 TOP==BOTTOM and only print 0% when TOP=0. If DECIMAL_PLACES < 0, then simply
2213 format TOP. Return pointer to a static string. */
2214
2215 static char const *
2216 format_gcov (gcov_type top, gcov_type bottom, int decimal_places)
2217 {
2218 static char buffer[20];
2219
2220 if (decimal_places >= 0)
2221 {
2222 float ratio = bottom ? 100.0f * top / bottom: 0;
2223
2224 /* Round up to 1% if there's a small non-zero value. */
2225 if (ratio > 0.0f && ratio < 0.5f && decimal_places == 0)
2226 ratio = 1.0f;
2227 sprintf (buffer, "%.*f%%", decimal_places, ratio);
2228 }
2229 else
2230 return format_count (top);
2231
2232 return buffer;
2233 }
2234
2235 /* Summary of execution */
2236
2237 static void
2238 executed_summary (unsigned lines, unsigned executed)
2239 {
2240 if (lines)
2241 fnotice (stdout, "Lines executed:%s of %d\n",
2242 format_gcov (executed, lines, 2), lines);
2243 else
2244 fnotice (stdout, "No executable lines\n");
2245 }
2246
2247 /* Output summary info for a function or file. */
2248
2249 static void
2250 function_summary (const coverage_info *coverage, const char *title)
2251 {
2252 fnotice (stdout, "%s '%s'\n", title, coverage->name);
2253 executed_summary (coverage->lines, coverage->lines_executed);
2254
2255 if (flag_branches)
2256 {
2257 if (coverage->branches)
2258 {
2259 fnotice (stdout, "Branches executed:%s of %d\n",
2260 format_gcov (coverage->branches_executed,
2261 coverage->branches, 2),
2262 coverage->branches);
2263 fnotice (stdout, "Taken at least once:%s of %d\n",
2264 format_gcov (coverage->branches_taken,
2265 coverage->branches, 2),
2266 coverage->branches);
2267 }
2268 else
2269 fnotice (stdout, "No branches\n");
2270 if (coverage->calls)
2271 fnotice (stdout, "Calls executed:%s of %d\n",
2272 format_gcov (coverage->calls_executed, coverage->calls, 2),
2273 coverage->calls);
2274 else
2275 fnotice (stdout, "No calls\n");
2276 }
2277 }
2278
2279 /* Canonicalize the filename NAME by canonicalizing directory
2280 separators, eliding . components and resolving .. components
2281 appropriately. Always returns a unique string. */
2282
2283 static char *
2284 canonicalize_name (const char *name)
2285 {
2286 /* The canonical name cannot be longer than the incoming name. */
2287 char *result = XNEWVEC (char, strlen (name) + 1);
2288 const char *base = name, *probe;
2289 char *ptr = result;
2290 char *dd_base;
2291 int slash = 0;
2292
2293 #if HAVE_DOS_BASED_FILE_SYSTEM
2294 if (base[0] && base[1] == ':')
2295 {
2296 result[0] = base[0];
2297 result[1] = ':';
2298 base += 2;
2299 ptr += 2;
2300 }
2301 #endif
2302 for (dd_base = ptr; *base; base = probe)
2303 {
2304 size_t len;
2305
2306 for (probe = base; *probe; probe++)
2307 if (IS_DIR_SEPARATOR (*probe))
2308 break;
2309
2310 len = probe - base;
2311 if (len == 1 && base[0] == '.')
2312 /* Elide a '.' directory */
2313 ;
2314 else if (len == 2 && base[0] == '.' && base[1] == '.')
2315 {
2316 /* '..', we can only elide it and the previous directory, if
2317 we're not a symlink. */
2318 struct stat ATTRIBUTE_UNUSED buf;
2319
2320 *ptr = 0;
2321 if (dd_base == ptr
2322 #if defined (S_ISLNK)
2323 /* S_ISLNK is not POSIX.1-1996. */
2324 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2325 #endif
2326 )
2327 {
2328 /* Cannot elide, or unreadable or a symlink. */
2329 dd_base = ptr + 2 + slash;
2330 goto regular;
2331 }
2332 while (ptr != dd_base && *ptr != '/')
2333 ptr--;
2334 slash = ptr != result;
2335 }
2336 else
2337 {
2338 regular:
2339 /* Regular pathname component. */
2340 if (slash)
2341 *ptr++ = '/';
2342 memcpy (ptr, base, len);
2343 ptr += len;
2344 slash = 1;
2345 }
2346
2347 for (; IS_DIR_SEPARATOR (*probe); probe++)
2348 continue;
2349 }
2350 *ptr = 0;
2351
2352 return result;
2353 }
2354
2355 /* Print hex representation of 16 bytes from SUM and write it to BUFFER. */
2356
2357 static void
2358 md5sum_to_hex (const char *sum, char *buffer)
2359 {
2360 for (unsigned i = 0; i < 16; i++)
2361 sprintf (buffer + (2 * i), "%02x", (unsigned char)sum[i]);
2362 }
2363
2364 /* Generate an output file name. INPUT_NAME is the canonicalized main
2365 input file and SRC_NAME is the canonicalized file name.
2366 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
2367 long_output_names we prepend the processed name of the input file
2368 to each output name (except when the current source file is the
2369 input file, so you don't get a double concatenation). The two
2370 components are separated by '##'. With preserve_paths we create a
2371 filename from all path components of the source file, replacing '/'
2372 with '#', and .. with '^', without it we simply take the basename
2373 component. (Remember, the canonicalized name will already have
2374 elided '.' components and converted \\ separators.) */
2375
2376 static char *
2377 make_gcov_file_name (const char *input_name, const char *src_name)
2378 {
2379 char *ptr;
2380 char *result;
2381
2382 if (flag_long_names && input_name && strcmp (src_name, input_name))
2383 {
2384 /* Generate the input filename part. */
2385 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
2386
2387 ptr = result;
2388 ptr = mangle_name (input_name, ptr);
2389 ptr[0] = ptr[1] = '#';
2390 ptr += 2;
2391 }
2392 else
2393 {
2394 result = XNEWVEC (char, strlen (src_name) + 10);
2395 ptr = result;
2396 }
2397
2398 ptr = mangle_name (src_name, ptr);
2399 strcpy (ptr, ".gcov");
2400
2401 /* When hashing filenames, we shorten them by only using the filename
2402 component and appending a hash of the full (mangled) pathname. */
2403 if (flag_hash_filenames)
2404 {
2405 md5_ctx ctx;
2406 char md5sum[16];
2407 char md5sum_hex[33];
2408
2409 md5_init_ctx (&ctx);
2410 md5_process_bytes (src_name, strlen (src_name), &ctx);
2411 md5_finish_ctx (&ctx, md5sum);
2412 md5sum_to_hex (md5sum, md5sum_hex);
2413 free (result);
2414
2415 result = XNEWVEC (char, strlen (src_name) + 50);
2416 ptr = result;
2417 ptr = mangle_name (src_name, ptr);
2418 ptr[0] = ptr[1] = '#';
2419 ptr += 2;
2420 memcpy (ptr, md5sum_hex, 32);
2421 ptr += 32;
2422 strcpy (ptr, ".gcov");
2423 }
2424
2425 return result;
2426 }
2427
2428 static char *
2429 mangle_name (char const *base, char *ptr)
2430 {
2431 size_t len;
2432
2433 /* Generate the source filename part. */
2434 if (!flag_preserve_paths)
2435 {
2436 base = lbasename (base);
2437 len = strlen (base);
2438 memcpy (ptr, base, len);
2439 ptr += len;
2440 }
2441 else
2442 ptr = mangle_path (base);
2443
2444 return ptr;
2445 }
2446
2447 /* Scan through the bb_data for each line in the block, increment
2448 the line number execution count indicated by the execution count of
2449 the appropriate basic block. */
2450
2451 static void
2452 add_line_counts (coverage_info *coverage, function_info *fn)
2453 {
2454 bool has_any_line = false;
2455 /* Scan each basic block. */
2456 for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
2457 {
2458 line_info *line = NULL;
2459 block_info *block = &fn->blocks[ix];
2460 if (block->count && ix && ix + 1 != fn->blocks.size ())
2461 fn->blocks_executed++;
2462 for (unsigned i = 0; i < block->locations.size (); i++)
2463 {
2464 unsigned src_idx = block->locations[i].source_file_idx;
2465 vector<unsigned> &lines = block->locations[i].lines;
2466
2467 block->cycle.arc = NULL;
2468 block->cycle.ident = ~0U;
2469
2470 for (unsigned j = 0; j < lines.size (); j++)
2471 {
2472 unsigned ln = lines[j];
2473
2474 /* Line belongs to a function that is in a group. */
2475 if (fn->group_line_p (ln, src_idx))
2476 {
2477 gcc_assert (lines[j] - fn->start_line < fn->lines.size ());
2478 line = &(fn->lines[lines[j] - fn->start_line]);
2479 line->exists = 1;
2480 if (!block->exceptional)
2481 {
2482 line->unexceptional = 1;
2483 if (block->count == 0)
2484 line->has_unexecuted_block = 1;
2485 }
2486 line->count += block->count;
2487 }
2488 else
2489 {
2490 gcc_assert (ln < sources[src_idx].lines.size ());
2491 line = &(sources[src_idx].lines[ln]);
2492 if (coverage)
2493 {
2494 if (!line->exists)
2495 coverage->lines++;
2496 if (!line->count && block->count)
2497 coverage->lines_executed++;
2498 }
2499 line->exists = 1;
2500 if (!block->exceptional)
2501 {
2502 line->unexceptional = 1;
2503 if (block->count == 0)
2504 line->has_unexecuted_block = 1;
2505 }
2506 line->count += block->count;
2507 }
2508 }
2509
2510 has_any_line = true;
2511
2512 if (!ix || ix + 1 == fn->blocks.size ())
2513 /* Entry or exit block. */;
2514 else if (line != NULL)
2515 {
2516 line->blocks.push_back (block);
2517
2518 if (flag_branches)
2519 {
2520 arc_info *arc;
2521
2522 for (arc = block->succ; arc; arc = arc->succ_next)
2523 line->branches.push_back (arc);
2524 }
2525 }
2526 }
2527 }
2528
2529 if (!has_any_line)
2530 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
2531 }
2532
2533 /* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE
2534 is set to true, update source file summary. */
2535
2536 static void accumulate_line_info (line_info *line, source_info *src,
2537 bool add_coverage)
2538 {
2539 if (add_coverage)
2540 for (vector<arc_info *>::iterator it = line->branches.begin ();
2541 it != line->branches.end (); it++)
2542 add_branch_counts (&src->coverage, *it);
2543
2544 if (!line->blocks.empty ())
2545 {
2546 /* The user expects the line count to be the number of times
2547 a line has been executed. Simply summing the block count
2548 will give an artificially high number. The Right Thing
2549 is to sum the entry counts to the graph of blocks on this
2550 line, then find the elementary cycles of the local graph
2551 and add the transition counts of those cycles. */
2552 gcov_type count = 0;
2553
2554 /* Cycle detection. */
2555 for (vector<block_info *>::iterator it = line->blocks.begin ();
2556 it != line->blocks.end (); it++)
2557 {
2558 for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next)
2559 if (!line->has_block (arc->src))
2560 count += arc->count;
2561 for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next)
2562 arc->cs_count = arc->count;
2563 }
2564
2565 /* Now, add the count of loops entirely on this line. */
2566 count += get_cycles_count (*line);
2567 line->count = count;
2568 }
2569
2570 if (line->exists && add_coverage)
2571 {
2572 src->coverage.lines++;
2573 if (line->count)
2574 src->coverage.lines_executed++;
2575 }
2576 }
2577
2578 /* Accumulate the line counts of a file. */
2579
2580 static void
2581 accumulate_line_counts (source_info *src)
2582 {
2583 /* First work on group functions. */
2584 for (vector<function_info *>::iterator it = src->functions.begin ();
2585 it != src->functions.end (); it++)
2586 {
2587 function_info *fn = *it;
2588
2589 if (fn->src != src->index || !fn->is_group)
2590 continue;
2591
2592 for (vector<line_info>::iterator it2 = fn->lines.begin ();
2593 it2 != fn->lines.end (); it2++)
2594 {
2595 line_info *line = &(*it2);
2596 accumulate_line_info (line, src, false);
2597 }
2598 }
2599
2600 /* Work on global lines that line in source file SRC. */
2601 for (vector<line_info>::iterator it = src->lines.begin ();
2602 it != src->lines.end (); it++)
2603 accumulate_line_info (&(*it), src, true);
2604
2605 /* If not using intermediate mode, sum lines of group functions and
2606 add them to lines that live in a source file. */
2607 if (!flag_intermediate_format)
2608 for (vector<function_info *>::iterator it = src->functions.begin ();
2609 it != src->functions.end (); it++)
2610 {
2611 function_info *fn = *it;
2612
2613 if (fn->src != src->index || !fn->is_group)
2614 continue;
2615
2616 for (unsigned i = 0; i < fn->lines.size (); i++)
2617 {
2618 line_info *fn_line = &fn->lines[i];
2619 if (fn_line->exists)
2620 {
2621 unsigned ln = fn->start_line + i;
2622 line_info *src_line = &src->lines[ln];
2623
2624 if (!src_line->exists)
2625 src->coverage.lines++;
2626 if (!src_line->count && fn_line->count)
2627 src->coverage.lines_executed++;
2628
2629 src_line->count += fn_line->count;
2630 src_line->exists = 1;
2631
2632 if (fn_line->has_unexecuted_block)
2633 src_line->has_unexecuted_block = 1;
2634
2635 if (fn_line->unexceptional)
2636 src_line->unexceptional = 1;
2637 }
2638 }
2639 }
2640 }
2641
2642 /* Output information about ARC number IX. Returns nonzero if
2643 anything is output. */
2644
2645 static int
2646 output_branch_count (FILE *gcov_file, int ix, const arc_info *arc)
2647 {
2648 if (arc->is_call_non_return)
2649 {
2650 if (arc->src->count)
2651 {
2652 fnotice (gcov_file, "call %2d returned %s\n", ix,
2653 format_gcov (arc->src->count - arc->count,
2654 arc->src->count, -flag_counts));
2655 }
2656 else
2657 fnotice (gcov_file, "call %2d never executed\n", ix);
2658 }
2659 else if (!arc->is_unconditional)
2660 {
2661 if (arc->src->count)
2662 fnotice (gcov_file, "branch %2d taken %s%s", ix,
2663 format_gcov (arc->count, arc->src->count, -flag_counts),
2664 arc->fall_through ? " (fallthrough)"
2665 : arc->is_throw ? " (throw)" : "");
2666 else
2667 fnotice (gcov_file, "branch %2d never executed", ix);
2668
2669 if (flag_verbose)
2670 fnotice (gcov_file, " (BB %d)", arc->dst->id);
2671
2672 fnotice (gcov_file, "\n");
2673 }
2674 else if (flag_unconditional && !arc->dst->is_call_return)
2675 {
2676 if (arc->src->count)
2677 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2678 format_gcov (arc->count, arc->src->count, -flag_counts));
2679 else
2680 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2681 }
2682 else
2683 return 0;
2684 return 1;
2685 }
2686
2687 static const char *
2688 read_line (FILE *file)
2689 {
2690 static char *string;
2691 static size_t string_len;
2692 size_t pos = 0;
2693 char *ptr;
2694
2695 if (!string_len)
2696 {
2697 string_len = 200;
2698 string = XNEWVEC (char, string_len);
2699 }
2700
2701 while ((ptr = fgets (string + pos, string_len - pos, file)))
2702 {
2703 size_t len = strlen (string + pos);
2704
2705 if (len && string[pos + len - 1] == '\n')
2706 {
2707 string[pos + len - 1] = 0;
2708 return string;
2709 }
2710 pos += len;
2711 /* If the file contains NUL characters or an incomplete
2712 last line, which can happen more than once in one run,
2713 we have to avoid doubling the STRING_LEN unnecessarily. */
2714 if (pos > string_len / 2)
2715 {
2716 string_len *= 2;
2717 string = XRESIZEVEC (char, string, string_len);
2718 }
2719 }
2720
2721 return pos ? string : NULL;
2722 }
2723
2724 /* Pad string S with spaces from left to have total width equal to 9. */
2725
2726 static void
2727 pad_count_string (string &s)
2728 {
2729 if (s.size () < 9)
2730 s.insert (0, 9 - s.size (), ' ');
2731 }
2732
2733 /* Print GCOV line beginning to F stream. If EXISTS is set to true, the
2734 line exists in source file. UNEXCEPTIONAL indicated that it's not in
2735 an exceptional statement. The output is printed for LINE_NUM of given
2736 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2737 used to indicate non-executed blocks. */
2738
2739 static void
2740 output_line_beginning (FILE *f, bool exists, bool unexceptional,
2741 bool has_unexecuted_block,
2742 gcov_type count, unsigned line_num,
2743 const char *exceptional_string,
2744 const char *unexceptional_string)
2745 {
2746 string s;
2747 if (exists)
2748 {
2749 if (count > 0)
2750 {
2751 s = format_gcov (count, 0, -1);
2752 if (has_unexecuted_block
2753 && bbg_supports_has_unexecuted_blocks)
2754 {
2755 if (flag_use_colors)
2756 {
2757 pad_count_string (s);
2758 s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
2759 COLOR_SEPARATOR COLOR_FG_WHITE));
2760 s += SGR_RESET;
2761 }
2762 else
2763 s += "*";
2764 }
2765 pad_count_string (s);
2766 }
2767 else
2768 {
2769 if (flag_use_colors)
2770 {
2771 s = "0";
2772 pad_count_string (s);
2773 if (unexceptional)
2774 s.insert (0, SGR_SEQ (COLOR_BG_RED
2775 COLOR_SEPARATOR COLOR_FG_WHITE));
2776 else
2777 s.insert (0, SGR_SEQ (COLOR_BG_CYAN
2778 COLOR_SEPARATOR COLOR_FG_WHITE));
2779 s += SGR_RESET;
2780 }
2781 else
2782 {
2783 s = unexceptional ? unexceptional_string : exceptional_string;
2784 pad_count_string (s);
2785 }
2786 }
2787 }
2788 else
2789 {
2790 s = "-";
2791 pad_count_string (s);
2792 }
2793
2794 fprintf (f, "%s:%5u", s.c_str (), line_num);
2795 }
2796
2797 static void
2798 print_source_line (FILE *f, const vector<const char *> &source_lines,
2799 unsigned line)
2800 {
2801 gcc_assert (line >= 1);
2802 gcc_assert (line <= source_lines.size ());
2803
2804 fprintf (f, ":%s\n", source_lines[line - 1]);
2805 }
2806
2807 /* Output line details for LINE and print it to F file. LINE lives on
2808 LINE_NUM. */
2809
2810 static void
2811 output_line_details (FILE *f, const line_info *line, unsigned line_num)
2812 {
2813 if (flag_all_blocks)
2814 {
2815 arc_info *arc;
2816 int ix, jx;
2817
2818 ix = jx = 0;
2819 for (vector<block_info *>::const_iterator it = line->blocks.begin ();
2820 it != line->blocks.end (); it++)
2821 {
2822 if (!(*it)->is_call_return)
2823 {
2824 output_line_beginning (f, line->exists,
2825 (*it)->exceptional, false,
2826 (*it)->count, line_num,
2827 "%%%%%", "$$$$$");
2828 fprintf (f, "-block %2d", ix++);
2829 if (flag_verbose)
2830 fprintf (f, " (BB %u)", (*it)->id);
2831 fprintf (f, "\n");
2832 }
2833 if (flag_branches)
2834 for (arc = (*it)->succ; arc; arc = arc->succ_next)
2835 jx += output_branch_count (f, jx, arc);
2836 }
2837 }
2838 else if (flag_branches)
2839 {
2840 int ix;
2841
2842 ix = 0;
2843 for (vector<arc_info *>::const_iterator it = line->branches.begin ();
2844 it != line->branches.end (); it++)
2845 ix += output_branch_count (f, ix, (*it));
2846 }
2847 }
2848
2849 /* Output detail statistics about function FN to file F. */
2850
2851 static void
2852 output_function_details (FILE *f, const function_info *fn)
2853 {
2854 if (!flag_branches)
2855 return;
2856
2857 arc_info *arc = fn->blocks[EXIT_BLOCK].pred;
2858 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2859 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2860
2861 for (; arc; arc = arc->pred_next)
2862 if (arc->fake)
2863 return_count -= arc->count;
2864
2865 fprintf (f, "function %s",
2866 flag_demangled_names ? fn->demangled_name : fn->name);
2867 fprintf (f, " called %s",
2868 format_gcov (called_count, 0, -1));
2869 fprintf (f, " returned %s",
2870 format_gcov (return_count, called_count, 0));
2871 fprintf (f, " blocks executed %s",
2872 format_gcov (fn->blocks_executed, fn->blocks.size () - 2,
2873 0));
2874 fprintf (f, "\n");
2875 }
2876
2877 /* Read in the source file one line at a time, and output that line to
2878 the gcov file preceded by its execution count and other
2879 information. */
2880
2881 static void
2882 output_lines (FILE *gcov_file, const source_info *src)
2883 {
2884 #define DEFAULT_LINE_START " -: 0:"
2885 #define FN_SEPARATOR "------------------\n"
2886
2887 FILE *source_file;
2888 const char *retval;
2889
2890 fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
2891 if (!multiple_files)
2892 {
2893 fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
2894 fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
2895 no_data_file ? "-" : da_file_name);
2896 fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
2897 }
2898 fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
2899
2900 source_file = fopen (src->name, "r");
2901 if (!source_file)
2902 fnotice (stderr, "Cannot open source file %s\n", src->name);
2903 else if (src->file_time == 0)
2904 fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
2905
2906 vector<const char *> source_lines;
2907 if (source_file)
2908 while ((retval = read_line (source_file)) != NULL)
2909 source_lines.push_back (xstrdup (retval));
2910
2911 unsigned line_start_group = 0;
2912 vector<function_info *> fns;
2913
2914 for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++)
2915 {
2916 if (line_num >= src->lines.size ())
2917 {
2918 fprintf (gcov_file, "%9s:%5u", "-", line_num);
2919 print_source_line (gcov_file, source_lines, line_num);
2920 continue;
2921 }
2922
2923 const line_info *line = &src->lines[line_num];
2924
2925 if (line_start_group == 0)
2926 {
2927 fns = src->get_functions_at_location (line_num);
2928 if (fns.size () > 1)
2929 {
2930 /* It's possible to have functions that partially overlap,
2931 thus take the maximum end_line of functions starting
2932 at LINE_NUM. */
2933 for (unsigned i = 0; i < fns.size (); i++)
2934 if (fns[i]->end_line > line_start_group)
2935 line_start_group = fns[i]->end_line;
2936 }
2937 else if (fns.size () == 1)
2938 {
2939 function_info *fn = fns[0];
2940 output_function_details (gcov_file, fn);
2941 }
2942 }
2943
2944 /* For lines which don't exist in the .bb file, print '-' before
2945 the source line. For lines which exist but were never
2946 executed, print '#####' or '=====' before the source line.
2947 Otherwise, print the execution count before the source line.
2948 There are 16 spaces of indentation added before the source
2949 line so that tabs won't be messed up. */
2950 output_line_beginning (gcov_file, line->exists, line->unexceptional,
2951 line->has_unexecuted_block, line->count,
2952 line_num, "=====", "#####");
2953
2954 print_source_line (gcov_file, source_lines, line_num);
2955 output_line_details (gcov_file, line, line_num);
2956
2957 if (line_start_group == line_num)
2958 {
2959 for (vector<function_info *>::iterator it = fns.begin ();
2960 it != fns.end (); it++)
2961 {
2962 function_info *fn = *it;
2963 vector<line_info> &lines = fn->lines;
2964
2965 fprintf (gcov_file, FN_SEPARATOR);
2966
2967 string fn_name
2968 = flag_demangled_names ? fn->demangled_name : fn->name;
2969
2970 if (flag_use_colors)
2971 {
2972 fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN));
2973 fn_name += SGR_RESET;
2974 }
2975
2976 fprintf (gcov_file, "%s:\n", fn_name.c_str ());
2977
2978 output_function_details (gcov_file, fn);
2979
2980 /* Print all lines covered by the function. */
2981 for (unsigned i = 0; i < lines.size (); i++)
2982 {
2983 line_info *line = &lines[i];
2984 unsigned l = fn->start_line + i;
2985
2986 /* For lines which don't exist in the .bb file, print '-'
2987 before the source line. For lines which exist but
2988 were never executed, print '#####' or '=====' before
2989 the source line. Otherwise, print the execution count
2990 before the source line.
2991 There are 16 spaces of indentation added before the source
2992 line so that tabs won't be messed up. */
2993 output_line_beginning (gcov_file, line->exists,
2994 line->unexceptional,
2995 line->has_unexecuted_block,
2996 line->count,
2997 l, "=====", "#####");
2998
2999 print_source_line (gcov_file, source_lines, l);
3000 output_line_details (gcov_file, line, l);
3001 }
3002 }
3003
3004 fprintf (gcov_file, FN_SEPARATOR);
3005 line_start_group = 0;
3006 }
3007 }
3008
3009 if (source_file)
3010 fclose (source_file);
3011 }