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