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