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