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