PR target/9700
[official-gcc.git] / gcc / gcov.c
blobdd6dfc9f0df9269939d9c4b53c2468f4e0e9243e
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
4 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5 Contributed by James E. Wilson of Cygnus Support.
6 Mangled by Bob Manson of Cygnus Support.
7 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
9 Gcov is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 Gcov is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Gcov; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 /* ??? Print a list of the ten blocks with the highest execution counts,
25 and list the line numbers corresponding to those blocks. Also, perhaps
26 list the line numbers with the highest execution counts, only printing
27 the first if there are several which are all listed in the same block. */
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
32 /* ??? Does not correctly handle the case where two .bb files refer to
33 the same included source file. For example, if one has a short
34 file containing only inline functions, which is then included in
35 two other files, then there will be two .bb files which refer to
36 the include file, but there is no way to get the total execution
37 counts for the included file, can only get execution counts for one
38 or the other of the including files. this can be fixed by --ratios
39 --long-file-names --preserve-paths and perl. */
41 /* Need an option to show individual block counts, and show
42 probabilities of fall through arcs. */
44 #include "config.h"
45 #include "system.h"
46 #include "coretypes.h"
47 #include "tm.h"
48 #include "intl.h"
49 #include "version.h"
50 #undef abort
52 #include <getopt.h>
54 typedef HOST_WIDEST_INT gcov_type;
55 #include "gcov-io.h"
57 /* The bbg file is generated by -ftest-coverage option. The da file is
58 generated by a program compiled with -fprofile-arcs. Their formats
59 are documented in gcov-io.h. */
61 /* The functions in this file for creating and solution program flow graphs
62 are very similar to functions in the gcc source file profile.c. In
63 some places we make use of the knowledge of how profile.c works to
64 select particular algorithms here. */
66 /* This is the size of the buffer used to read in source file lines. */
68 #define STRING_SIZE 200
70 struct function_info;
71 struct block_info;
73 /* Describes an arc between two basic blocks. */
75 typedef struct arc_info
77 /* source and destination blocks. */
78 struct block_info *src;
79 struct block_info *dst;
81 /* transition counts. */
82 gcov_type count;
84 unsigned int count_valid : 1;
85 unsigned int on_tree : 1;
86 unsigned int fake : 1;
87 unsigned int fall_through : 1;
89 /* Arc to a call. */
90 unsigned int is_call : 1;
92 /* Next branch on line. */
93 struct arc_info *line_next;
95 /* Links to next arc on src and dst lists. */
96 struct arc_info *succ_next;
97 struct arc_info *pred_next;
98 } arc_t;
100 /* Describes a basic block. Contains lists of arcs to successor and
101 predecessor blocks. */
103 typedef struct block_info
105 /* Chain of exit and entry arcs. */
106 arc_t *succ;
107 arc_t *pred;
109 /* Number of unprocessed exit and entry arcs. */
110 gcov_type num_succ;
111 gcov_type num_pred;
113 /* Block execution count. */
114 gcov_type count;
115 unsigned count_valid : 1;
116 unsigned valid_chain : 1;
117 unsigned invalid_chain : 1;
119 /* Array of line numbers and source files. source files are
120 introduced by a linenumber of zero, the next 'line number' is the
121 number of the source file. Always starts with a source file. */
122 unsigned *encoding;
123 unsigned num_encodings;
125 /* Temporary chain for solving graph. */
126 struct block_info *chain;
128 } block_t;
130 /* Describes a single function. Contains an array of basic blocks. */
132 typedef struct function_info
134 /* Name of function. */
135 char *name;
136 unsigned checksum;
138 /* Array of basic blocks. */
139 block_t *blocks;
140 unsigned num_blocks;
142 /* Raw arc coverage counts. */
143 gcov_type *counts;
144 unsigned num_counts;
146 /* Next function. */
147 struct function_info *next;
148 } function_t;
150 /* Describes coverage of a file or function. */
152 typedef struct coverage_info
154 int lines;
155 int lines_executed;
157 int branches;
158 int branches_executed;
159 int branches_taken;
161 int calls;
162 int calls_executed;
164 char *name;
165 } coverage_t;
167 /* Describes a single line of source. Contains a chain of basic blocks
168 with code on it. */
170 typedef struct line_info
172 gcov_type count; /* execution count */
173 arc_t *branches; /* branches from blocks that end on this
174 line. */
175 unsigned exists : 1;
176 } line_t;
178 /* Describes a file mentioned in the block graph. Contains an array
179 of line info. */
181 typedef struct source_info
183 /* Name of source file. */
184 char *name;
185 unsigned index;
187 /* Array of line information. */
188 line_t *lines;
189 unsigned num_lines;
191 coverage_t coverage;
193 /* Next source file. */
194 struct source_info *next;
195 } source_t;
197 /* Holds a list of function basic block graphs. */
199 static function_t *functions;
201 /* This points to the head of the sourcefile structure list. */
203 static source_t *sources;
205 /* Modification time of graph file. */
207 static time_t bbg_file_time;
209 /* Name and file pointer of the input file for the basic block graph. */
211 static char *bbg_file_name;
213 /* Name and file pointer of the input file for the arc count data. */
215 static char *da_file_name;
217 /* Output branch probabilities. */
219 static int flag_branches = 0;
221 /* Output a gcov file if this is true. This is on by default, and can
222 be turned off by the -n option. */
224 static int flag_gcov_file = 1;
226 /* For included files, make the gcov output file name include the name
227 of the input source file. For example, if x.h is included in a.c,
228 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
230 static int flag_long_names = 0;
232 /* Output summary info for each function. */
234 static int flag_function_summary = 0;
236 /* Object directory file prefix. This is the directory/file where the
237 graph and data files are looked for, if nonzero. */
239 static char *object_directory = 0;
241 /* Preserve all pathname components. Needed when object files and
242 source files are in subdirectories. '/' is mangled as '#', '.' is
243 elided and '..' mangled to '^'. */
245 static int flag_preserve_paths = 0;
247 /* Output the number of times a branch was taken as opposed to the percentage
248 of times it was taken. */
250 static int flag_counts = 0;
252 /* Forward declarations. */
253 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
254 static int process_args PARAMS ((int, char **));
255 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
256 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
257 static void process_file PARAMS ((const char *));
258 static void create_file_names PARAMS ((const char *));
259 static int read_graph_file PARAMS ((void));
260 static int read_count_file PARAMS ((void));
261 static void solve_flow_graph PARAMS ((function_t *));
262 static void add_branch_counts PARAMS ((coverage_t *, const arc_t *));
263 static void add_line_counts PARAMS ((coverage_t *, const function_t *));
264 static void function_summary PARAMS ((const coverage_t *, const char *));
265 static const char *format_gcov PARAMS ((gcov_type, gcov_type, int));
266 static void accumulate_line_counts PARAMS ((source_t *));
267 static void output_lines PARAMS ((FILE *, const source_t *));
268 static char *make_gcov_file_name PARAMS ((const char *, const char *));
269 static void release_structures PARAMS ((void));
270 extern int main PARAMS ((int, char **));
273 main (argc, argv)
274 int argc;
275 char **argv;
277 int argno;
279 gcc_init_libintl ();
281 argno = process_args (argc, argv);
282 if (optind == argc)
283 print_usage (true);
285 for (; argno != argc; argno++)
287 release_structures ();
289 process_file (argv[argno]);
292 return 0;
295 static void
296 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
298 VA_OPEN (ap, msgid);
299 VA_FIXEDARG (ap, FILE *, file);
300 VA_FIXEDARG (ap, const char *, msgid);
302 vfprintf (file, _(msgid), ap);
303 VA_CLOSE (ap);
306 /* More 'friendly' abort that prints the line and file.
307 config.h can #define abort fancy_abort if you like that sort of thing. */
308 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
310 void
311 fancy_abort ()
313 fnotice (stderr, "Internal gcov abort.\n");
314 exit (FATAL_EXIT_CODE);
317 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
318 otherwise the output of --help. */
320 static void
321 print_usage (error_p)
322 int error_p;
324 FILE *file = error_p ? stderr : stdout;
325 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
327 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
328 fnotice (file, "Print code coverage information.\n\n");
329 fnotice (file, " -h, --help Print this help, then exit\n");
330 fnotice (file, " -v, --version Print version number, then exit\n");
331 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
332 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
333 rather than percentages\n");
334 fnotice (file, " -n, --no-output Do not create an output file\n");
335 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
336 source files\n");
337 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
338 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
339 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
340 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
341 bug_report_url);
342 exit (status);
345 /* Print version information and exit. */
347 static void
348 print_version ()
350 char v[4];
351 unsigned version = GCOV_VERSION;
352 unsigned ix;
354 for (ix = 4; ix--; version >>= 8)
355 v[ix] = version;
356 fnotice (stdout, "gcov %.4s (GCC %s)\n", v, version_string);
357 fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
358 fnotice (stdout,
359 "This is free software; see the source for copying conditions. There is NO\n\
360 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
361 exit (SUCCESS_EXIT_CODE);
364 static const struct option options[] =
366 { "help", no_argument, NULL, 'h' },
367 { "version", no_argument, NULL, 'v' },
368 { "branch-probabilities", no_argument, NULL, 'b' },
369 { "branch-counts", no_argument, NULL, 'c' },
370 { "no-output", no_argument, NULL, 'n' },
371 { "long-file-names", no_argument, NULL, 'l' },
372 { "function-summaries", no_argument, NULL, 'f' },
373 { "preserve-paths", no_argument, NULL, 'p' },
374 { "object-directory", required_argument, NULL, 'o' },
375 { "object-file", required_argument, NULL, 'o' },
378 /* Process args, return index to first non-arg. */
380 static int
381 process_args (argc, argv)
382 int argc;
383 char **argv;
385 int opt;
387 while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
389 switch (opt)
391 case 'h':
392 print_usage (false);
393 /* print_usage will exit. */
394 case 'v':
395 print_version ();
396 /* print_version will exit. */
397 case 'b':
398 flag_branches = 1;
399 break;
400 case 'c':
401 flag_counts = 1;
402 break;
403 case 'n':
404 flag_gcov_file = 0;
405 break;
406 case 'l':
407 flag_long_names = 1;
408 break;
409 case 'f':
410 flag_function_summary = 1;
411 break;
412 case 'o':
413 object_directory = optarg;
414 break;
415 case 'p':
416 flag_preserve_paths = 1;
417 break;
418 default:
419 print_usage (true);
420 /* print_usage will exit. */
424 return optind;
427 /* Process a single source file. */
429 static void
430 process_file (file_name)
431 const char *file_name;
433 source_t *src;
434 function_t *fn;
436 create_file_names (file_name);
437 if (read_graph_file ())
438 return;
440 if (!functions)
442 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
443 return;
446 if (read_count_file ())
447 return;
449 for (fn = functions; fn; fn = fn->next)
450 solve_flow_graph (fn);
451 for (src = sources; src; src = src->next)
452 src->lines = (line_t *) xcalloc (src->num_lines, sizeof (line_t));
453 for (fn = functions; fn; fn = fn->next)
455 coverage_t coverage;
457 memset (&coverage, 0, sizeof (coverage));
458 coverage.name = fn->name;
459 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
460 if (flag_function_summary)
462 function_summary (&coverage, "Function");
463 fnotice (stdout, "\n");
467 for (src = sources; src; src = src->next)
469 accumulate_line_counts (src);
470 function_summary (&src->coverage, "File");
471 if (flag_gcov_file)
473 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
474 FILE *gcov_file = fopen (gcov_file_name, "w");
476 if (gcov_file)
478 fnotice (stdout, "%s:creating `%s'\n",
479 src->name, gcov_file_name);
480 output_lines (gcov_file, src);
481 if (ferror (gcov_file))
482 fnotice (stderr, "%s:error writing output file `%s'\n",
483 src->name, gcov_file_name);
484 fclose (gcov_file);
486 else
487 fnotice (stderr, "%s:could not open output file `%s'\n",
488 src->name, gcov_file_name);
489 free (gcov_file_name);
491 fnotice (stdout, "\n");
495 /* Release all memory used. */
497 static void
498 release_structures ()
500 function_t *fn;
501 source_t *src;
503 free (bbg_file_name);
504 free (da_file_name);
505 da_file_name = bbg_file_name = NULL;
506 bbg_file_time = 0;
508 while ((src = sources))
510 sources = src->next;
512 free (src->name);
513 free (src->lines);
516 while ((fn = functions))
518 unsigned ix;
519 block_t *block;
521 functions = fn->next;
522 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
524 arc_t *arc, *arc_n;
526 for (arc = block->succ; arc; arc = arc_n)
528 arc_n = arc->succ_next;
529 free (arc);
531 free (block->encoding);
533 free (fn->blocks);
534 free (fn->counts);
538 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
539 is not specified, these are looked for in the current directory,
540 and named from the basename of the FILE_NAME sans extension. If
541 OBJECT_DIRECTORY is specified and is a directory, the files are in
542 that directory, but named from the basename of the FILE_NAME, sans
543 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
544 the object *file*, and the data files are named from that. */
546 static void
547 create_file_names (file_name)
548 const char *file_name;
550 char *cptr;
551 char *name;
552 int length = strlen (file_name);
553 int base;
555 if (object_directory && object_directory[0])
557 struct stat status;
559 length += strlen (object_directory) + 2;
560 name = xmalloc (length);
561 name[0] = 0;
563 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
564 strcat (name, object_directory);
565 if (base && name[strlen (name) - 1] != '/')
566 strcat (name, "/");
568 else
570 name = xmalloc (length + 1);
571 name[0] = 0;
572 base = 1;
575 if (base)
577 /* Append source file name */
578 cptr = strrchr (file_name, '/');
579 strcat (name, cptr ? cptr + 1 : file_name);
582 /* Remove the extension. */
583 cptr = strrchr (name, '.');
584 if (cptr)
585 *cptr = 0;
587 length = strlen (name);
589 bbg_file_name = xmalloc (length + strlen (GCOV_GRAPH_SUFFIX) + 1);
590 strcpy (bbg_file_name, name);
591 strcpy (bbg_file_name + length, GCOV_GRAPH_SUFFIX);
593 da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
594 strcpy (da_file_name, name);
595 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
597 return;
600 /* Read the graph file. Return nonzero on fatal error. */
602 static int
603 read_graph_file ()
605 FILE *file;
606 struct stat status;
607 unsigned magic, version;
608 unsigned current_tag = 0;
609 unsigned tag;
610 struct function_info *fn = NULL;
611 source_t *src = NULL;
612 unsigned ix;
614 file = fopen (bbg_file_name, "rb");
615 if (!file)
617 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
618 return 1;
620 if (!fstat (fileno (file), &status))
621 bbg_file_time = status.st_mtime;
622 if (gcov_read_unsigned (file, &magic) || magic != GCOV_GRAPH_MAGIC)
624 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
625 fclose (file);
626 return 1;
629 if (gcov_read_unsigned (file, &version) || version != GCOV_VERSION)
631 char v[4], e[4];
633 magic = GCOV_VERSION;
635 for (ix = 4; ix--; magic >>= 8, version >>= 8)
637 v[ix] = version;
638 e[ix] = magic;
640 fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
641 bbg_file_name, v, e);
644 while (!gcov_read_unsigned (file, &tag))
646 unsigned length;
647 long base;
649 if (gcov_read_unsigned (file, &length))
650 goto corrupt;
652 base = gcov_save_position (file);
654 if (tag == GCOV_TAG_FUNCTION)
656 char *function_name = NULL;
657 unsigned checksum;
659 if (gcov_read_string (file, &function_name, NULL)
660 || gcov_read_unsigned (file, &checksum))
661 goto corrupt;
662 fn = (function_t *)xcalloc (1, sizeof (function_t));
663 fn->name = function_name;
664 fn->checksum = checksum;
666 fn->next = functions;
667 functions = fn;
668 current_tag = tag;
670 else if (fn && tag == GCOV_TAG_BLOCKS)
672 if (fn->blocks)
673 fnotice (stderr, "%s:already seen blocks for `%s'\n",
674 bbg_file_name, fn->name);
675 else
677 fn->num_blocks = length / 4;
678 fn->blocks
679 = (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
682 else if (fn && tag == GCOV_TAG_ARCS)
684 unsigned src;
685 unsigned num_dests = (length - 4) / 8;
686 unsigned dest, flags;
688 if (gcov_read_unsigned (file, &src)
689 || src >= fn->num_blocks
690 || fn->blocks[src].succ)
691 goto corrupt;
693 while (num_dests--)
695 struct arc_info *arc;
697 if (gcov_read_unsigned (file, &dest)
698 || gcov_read_unsigned (file, &flags)
699 || dest >= fn->num_blocks)
700 goto corrupt;
701 arc = (arc_t *) xcalloc (1, sizeof (arc_t));
703 arc->dst = &fn->blocks[dest];
704 arc->src = &fn->blocks[src];
706 arc->count = 0;
707 arc->count_valid = 0;
708 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
709 arc->fake = !!(flags & GCOV_ARC_FAKE);
710 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
712 arc->succ_next = fn->blocks[src].succ;
713 fn->blocks[src].succ = arc;
714 fn->blocks[src].num_succ++;
716 arc->pred_next = fn->blocks[dest].pred;
717 fn->blocks[dest].pred = arc;
718 fn->blocks[dest].num_pred++;
720 arc->is_call = arc->fake;
722 if (!arc->on_tree)
723 fn->num_counts++;
726 else if (fn && tag == GCOV_TAG_LINES)
728 unsigned blockno;
729 unsigned *line_nos
730 = (unsigned *)xcalloc ((length - 4) / 4, sizeof (unsigned));
732 if (gcov_read_unsigned (file, &blockno)
733 || blockno >= fn->num_blocks
734 || fn->blocks[blockno].encoding)
735 goto corrupt;
737 for (ix = 0; ; )
739 unsigned lineno;
741 if (gcov_read_unsigned (file, &lineno))
742 goto corrupt;
743 if (lineno)
745 if (!ix)
747 line_nos[ix++] = 0;
748 line_nos[ix++] = src->index;
750 line_nos[ix++] = lineno;
751 if (lineno >= src->num_lines)
752 src->num_lines = lineno + 1;
754 else
756 char *file_name = NULL;
758 if (gcov_read_string (file, &file_name, NULL))
759 goto corrupt;
760 if (!file_name)
761 break;
762 for (src = sources; src; src = src->next)
763 if (!strcmp (file_name, src->name))
765 free (file_name);
766 break;
768 if (!src)
770 src = (source_t *)xcalloc (1, sizeof (source_t));
771 src->name = file_name;
772 src->coverage.name = file_name;
773 src->index = sources ? sources->index + 1 : 1;
774 src->next = sources;
775 sources = src;
777 line_nos[ix++] = 0;
778 line_nos[ix++] = src->index;
782 fn->blocks[blockno].encoding = line_nos;
783 fn->blocks[blockno].num_encodings = ix;
785 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
787 fn = NULL;
788 current_tag = 0;
790 if (gcov_resync (file, base, length))
792 corrupt:;
793 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
794 fclose (file);
795 return 1;
798 fclose (file);
800 /* We built everything backwards, so nreverse them all */
802 /* Reverse sources. Not strictly necessary, but we'll then process
803 them in the 'expected' order. */
805 source_t *src, *src_p, *src_n;
807 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
809 src_n = src->next;
810 src->next = src_p;
812 sources = src_p;
815 /* Reverse functions. */
817 function_t *fn, *fn_p, *fn_n;
819 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
821 unsigned ix;
823 fn_n = fn->next;
824 fn->next = fn_p;
826 /* Reverse the arcs */
827 for (ix = fn->num_blocks; ix--;)
829 arc_t *arc, *arc_p, *arc_n;
831 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
832 arc_p = arc, arc = arc_n)
834 arc_n = arc->succ_next;
835 arc->succ_next = arc_p;
837 fn->blocks[ix].succ = arc_p;
839 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
840 arc_p = arc, arc = arc_n)
842 arc_n = arc->pred_next;
843 arc->pred_next = arc_p;
845 fn->blocks[ix].pred = arc_p;
848 functions = fn_p;
850 return 0;
853 /* Reads profiles from the count file and attach to each
854 function. Return nonzero if fatal error. */
856 static int
857 read_count_file ()
859 FILE *file;
860 unsigned ix;
861 char *function_name_buffer = NULL;
862 unsigned magic, version;
863 function_t *fn = NULL;
865 file = fopen (da_file_name, "rb");
866 if (!file)
868 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
869 return 1;
871 if (gcov_read_unsigned (file, &magic) || magic != GCOV_DATA_MAGIC)
873 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
874 cleanup:;
875 free (function_name_buffer);
876 fclose (file);
877 return 1;
879 if (gcov_read_unsigned (file, &version) || version != GCOV_VERSION)
881 char v[4], e[4];
883 magic = GCOV_VERSION;
884 for (ix = 4; ix--; magic >>= 8, version >>= 8)
886 v[ix] = version;
887 e[ix] = magic;
889 fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
890 da_file_name, v, e);
893 while (1)
895 unsigned tag, length;
896 long base;
898 if (gcov_read_unsigned (file, &tag)
899 || gcov_read_unsigned (file, &length))
901 if (feof (file))
902 break;
904 corrupt:;
905 fnotice (stderr, "%s:corrupted\n", da_file_name);
906 goto cleanup;
908 base = gcov_save_position (file);
909 if (tag == GCOV_TAG_FUNCTION)
911 unsigned checksum;
912 struct function_info *fn_n = functions;
914 if (gcov_read_string (file, &function_name_buffer, NULL)
915 || gcov_read_unsigned (file, &checksum))
916 goto corrupt;
918 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
920 if (fn)
922 else if ((fn = fn_n))
923 fn_n = NULL;
924 else
926 fnotice (stderr, "%s:unknown function `%s'\n",
927 da_file_name, function_name_buffer);
928 break;
930 if (!strcmp (fn->name, function_name_buffer))
931 break;
934 if (!fn)
936 else if (checksum != fn->checksum)
938 mismatch:;
939 fnotice (stderr, "%s:profile mismatch for `%s'\n",
940 da_file_name, function_name_buffer);
941 goto cleanup;
944 else if (tag == GCOV_TAG_ARC_COUNTS && fn)
946 if (length != 8 * fn->num_counts)
947 goto mismatch;
949 if (!fn->counts)
950 fn->counts
951 = (gcov_type *)xcalloc (fn->num_counts, sizeof (gcov_type));
953 for (ix = 0; ix != fn->num_counts; ix++)
955 gcov_type count;
957 if (gcov_read_counter (file, &count))
958 goto corrupt;
959 fn->counts[ix] += count;
962 gcov_resync (file, base, length);
965 fclose (file);
966 free (function_name_buffer);
967 return 0;
970 /* Solve the flow graph. Propagate counts from the instrumented arcs
971 to the blocks and the uninstrumented arcs. */
973 static void
974 solve_flow_graph (fn)
975 function_t *fn;
977 unsigned ix;
978 arc_t *arc;
979 gcov_type *count_ptr = fn->counts;
980 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
981 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
983 if (fn->num_blocks < 2)
984 fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
985 bbg_file_name, fn->name);
986 else
988 if (fn->blocks[0].num_pred)
989 fnotice (stderr, "%s:`%s' has arcs to entry block\n",
990 bbg_file_name, fn->name);
991 else
992 /* We can't deduce the entry block counts from the lack of
993 predecessors. */
994 fn->blocks[0].num_pred = ~(unsigned)0;
996 if (fn->blocks[fn->num_blocks - 1].num_succ)
997 fnotice (stderr, "%s:`%s' has arcs from exit block\n",
998 bbg_file_name, fn->name);
999 else
1000 /* Likewise, we can't deduce exit block counts from the lack
1001 of its successors. */
1002 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1005 /* Propagate the measured counts, this must be done in the same
1006 order as the code in profile.c */
1007 for (ix = 0; ix != fn->num_blocks; ix++)
1009 block_t const *prev_dst = NULL;
1010 int out_of_order = 0;
1012 for (arc = fn->blocks[ix].succ; arc; arc = arc->succ_next)
1014 if (!arc->on_tree)
1016 if (count_ptr)
1017 arc->count = *count_ptr++;
1018 arc->count_valid = 1;
1019 fn->blocks[ix].num_succ--;
1020 arc->dst->num_pred--;
1022 if (prev_dst && prev_dst > arc->dst)
1023 out_of_order = 1;
1024 prev_dst = arc->dst;
1027 /* Sort the successor arcs into ascending dst order. profile.c
1028 normally produces arcs in the right order, but sometimes with
1029 one or two out of order. We're not using a particularly
1030 smart sort. */
1031 if (out_of_order)
1033 arc_t *start = fn->blocks[ix].succ;
1034 unsigned changes = 1;
1036 while (changes)
1038 arc_t *arc, *arc_p, *arc_n;
1040 changes = 0;
1041 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1043 if (arc->dst > arc_n->dst)
1045 changes = 1;
1046 if (arc_p)
1047 arc_p->succ_next = arc_n;
1048 else
1049 start = arc_n;
1050 arc->succ_next = arc_n->succ_next;
1051 arc_n->succ_next = arc;
1052 arc_p = arc_n;
1054 else
1056 arc_p = arc;
1057 arc = arc_n;
1061 fn->blocks[ix].succ = start;
1064 /* Place it on the invalid chain, it will be ignored if that's
1065 wrong. */
1066 fn->blocks[ix].invalid_chain = 1;
1067 fn->blocks[ix].chain = invalid_blocks;
1068 invalid_blocks = &fn->blocks[ix];
1071 while (invalid_blocks || valid_blocks)
1073 block_t *blk;
1075 while ((blk = invalid_blocks))
1077 gcov_type total = 0;
1078 const arc_t *arc;
1080 invalid_blocks = blk->chain;
1081 blk->invalid_chain = 0;
1082 if (!blk->num_succ)
1083 for (arc = blk->succ; arc; arc = arc->succ_next)
1084 total += arc->count;
1085 else if (!blk->num_pred)
1086 for (arc = blk->pred; arc; arc = arc->pred_next)
1087 total += arc->count;
1088 else
1089 continue;
1091 blk->count = total;
1092 blk->count_valid = 1;
1093 blk->chain = valid_blocks;
1094 blk->valid_chain = 1;
1095 valid_blocks = blk;
1097 while ((blk = valid_blocks))
1099 gcov_type total;
1100 arc_t *arc, *inv_arc;
1102 valid_blocks = blk->chain;
1103 blk->valid_chain = 0;
1104 if (blk->num_succ == 1)
1106 block_t *dst;
1108 total = blk->count;
1109 inv_arc = NULL;
1110 for (arc = blk->succ; arc; arc = arc->succ_next)
1112 total -= arc->count;
1113 if (!arc->count_valid)
1114 inv_arc = arc;
1116 dst = inv_arc->dst;
1117 inv_arc->count_valid = 1;
1118 inv_arc->count = total;
1119 blk->num_succ--;
1120 dst->num_pred--;
1121 if (dst->count_valid)
1123 if (dst->num_pred == 1 && !dst->valid_chain)
1125 dst->chain = valid_blocks;
1126 dst->valid_chain = 1;
1127 valid_blocks = dst;
1130 else
1132 if (!dst->num_pred && !dst->invalid_chain)
1134 dst->chain = invalid_blocks;
1135 dst->invalid_chain = 1;
1136 invalid_blocks = dst;
1140 if (blk->num_pred == 1)
1142 block_t *src;
1144 total = blk->count;
1145 inv_arc = NULL;
1146 for (arc = blk->pred; arc; arc = arc->pred_next)
1148 total -= arc->count;
1149 if (!arc->count_valid)
1150 inv_arc = arc;
1152 src = inv_arc->src;
1153 inv_arc->count_valid = 1;
1154 inv_arc->count = total;
1155 blk->num_pred--;
1156 src->num_succ--;
1157 if (src->count_valid)
1159 if (src->num_succ == 1 && !src->valid_chain)
1161 src->chain = valid_blocks;
1162 src->valid_chain = 1;
1163 valid_blocks = src;
1166 else
1168 if (!src->num_succ && !src->invalid_chain)
1170 src->chain = invalid_blocks;
1171 src->invalid_chain = 1;
1172 invalid_blocks = src;
1179 /* If the graph has been correctly solved, every block will have a
1180 valid count. */
1181 for (ix = 0; ix < fn->num_blocks; ix++)
1182 if (!fn->blocks[ix].count_valid)
1184 fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1185 bbg_file_name, fn->name);
1186 break;
1192 /* Increment totals in COVERAGE according to arc ARC. */
1194 static void
1195 add_branch_counts (coverage, arc)
1196 coverage_t *coverage;
1197 const arc_t *arc;
1199 if (arc->is_call)
1201 coverage->calls++;
1202 if (arc->src->count)
1203 coverage->calls_executed++;
1205 else
1207 coverage->branches++;
1208 if (arc->src->count)
1209 coverage->branches_executed++;
1210 if (arc->count)
1211 coverage->branches_taken++;
1215 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1216 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1217 If DP is zero, no decimal point is printed. Only print 100% when
1218 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1219 format TOP. Return pointer to a static string. */
1221 static char const *
1222 format_gcov (top, bottom, dp)
1223 gcov_type top, bottom;
1224 int dp;
1226 static char buffer[20];
1228 if (dp >= 0)
1230 float ratio = bottom ? (float)top / bottom : 0;
1231 int ix;
1232 unsigned limit = 100;
1233 unsigned percent;
1235 for (ix = dp; ix--; )
1236 limit *= 10;
1238 percent = (unsigned) (ratio * limit + (float)0.5);
1239 if (percent <= 0 && top)
1240 percent = 1;
1241 else if (percent >= limit && top != bottom)
1242 percent = limit - 1;
1243 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1244 if (dp)
1246 dp++;
1249 buffer[ix+1] = buffer[ix];
1250 ix--;
1252 while (dp--);
1253 buffer[ix + 1] = '.';
1256 else
1257 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1259 return buffer;
1263 /* Output summary info for a function. */
1265 static void
1266 function_summary (coverage, title)
1267 const coverage_t *coverage;
1268 const char *title;
1270 fnotice (stdout, "%s `%s'\n", title, coverage->name);
1272 if (coverage->lines)
1273 fnotice (stdout, "Lines executed:%s of %d\n",
1274 format_gcov (coverage->lines_executed, coverage->lines, 2),
1275 coverage->lines);
1276 else
1277 fnotice (stdout, "No executable lines");
1279 if (flag_branches)
1281 if (coverage->branches)
1283 fnotice (stdout, "Branches executed:%s of %d\n",
1284 format_gcov (coverage->branches_executed,
1285 coverage->branches, 2),
1286 coverage->branches);
1287 fnotice (stdout, "Taken at least once:%s of %d\n",
1288 format_gcov (coverage->branches_taken,
1289 coverage->branches, 2),
1290 coverage->branches);
1292 else
1293 fnotice (stdout, "No branches\n");
1294 if (coverage->calls)
1295 fnotice (stdout, "Calls executed:%s of %d\n",
1296 format_gcov (coverage->calls_executed, coverage->calls, 2),
1297 coverage->calls);
1298 else
1299 fnotice (stdout, "No calls\n");
1303 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1304 affect name generation. With preserve_paths we create a filename
1305 from all path components of the source file, replacing '/' with
1306 '#', without it we simply take the basename component. With
1307 long_output_names we prepend the processed name of the input file
1308 to each output name (except when the current source file is the
1309 input file, so you don't get a double concatenation). The two
1310 components are separated by '##'. Also '.' filename components are
1311 removed and '..' components are renamed to '^'. */
1313 static char *
1314 make_gcov_file_name (input_name, src_name)
1315 const char *input_name;
1316 const char *src_name;
1318 char *cptr;
1319 char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1321 name[0] = 0;
1322 if (flag_long_names && strcmp (src_name, input_name))
1324 /* Generate the input filename part. */
1325 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1326 strcat (name, cptr ? cptr + 1 : input_name);
1327 strcat (name, "##");
1330 /* Generate the source filename part. */
1331 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1332 strcat (name, cptr ? cptr + 1 : src_name);
1334 if (flag_preserve_paths)
1336 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1337 char *prev;
1339 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1341 unsigned shift = 0;
1343 if (prev + 1 == cptr && prev[0] == '.')
1345 /* Remove '.' */
1346 shift = 2;
1348 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1350 /* Convert '..' */
1351 shift = 1;
1352 prev[1] = '^';
1354 else
1355 *cptr++ = '#';
1356 if (shift)
1358 cptr = prev;
1360 prev[0] = prev[shift];
1361 while (*prev++);
1366 strcat (name, ".gcov");
1367 return name;
1370 /* Scan through the bb_data for each line in the block, increment
1371 the line number execution count indicated by the execution count of
1372 the appropriate basic block. */
1374 static void
1375 add_line_counts (coverage, fn)
1376 coverage_t *coverage;
1377 const function_t *fn;
1379 unsigned ix;
1380 line_t *line = NULL; /* this is propagated from one iteration to the
1381 next. */
1383 /* Scan each basic block. */
1384 for (ix = 0; ix != fn->num_blocks; ix++)
1386 const block_t *block = &fn->blocks[ix];
1387 unsigned *encoding;
1388 const source_t *src = NULL;
1389 unsigned jx;
1391 for (jx = 0, encoding = block->encoding;
1392 jx != block->num_encodings; jx++, encoding++)
1393 if (!*encoding)
1395 unsigned src_n = *++encoding;
1397 for (src = sources; src->index != src_n; src = src->next)
1398 continue;
1399 jx++;
1401 else
1403 line = &src->lines[*encoding];
1405 if (coverage)
1407 if (!line->exists)
1408 coverage->lines++;
1409 if (!line->count && block->count)
1410 coverage->lines_executed++;
1412 line->exists = 1;
1413 line->count += block->count;
1416 if (line && flag_branches)
1418 arc_t *arc;
1420 for (arc = block->succ; arc; arc = arc->succ_next)
1422 /* Ignore fall through arcs as they aren't really branches. */
1423 if (arc->fall_through)
1424 continue;
1426 arc->line_next = line->branches;
1427 line->branches = arc;
1428 if (coverage)
1429 add_branch_counts (coverage, arc);
1433 if (!line)
1434 fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1437 /* Accumulate the line counts of a file. */
1439 static void
1440 accumulate_line_counts (src)
1441 source_t *src;
1443 line_t *line;
1444 unsigned ix;
1446 for (ix = src->num_lines, line = src->lines; ix--; line++)
1448 arc_t *arc, *arc_p, *arc_n;
1450 /* Total and reverse the branch information. */
1451 for (arc = line->branches, arc_p = NULL; arc; arc_p = arc, arc = arc_n)
1453 arc_n = arc->line_next;
1454 arc->line_next = arc_p;
1456 add_branch_counts (&src->coverage, arc);
1458 line->branches = arc_p;
1460 if (line->exists)
1462 src->coverage.lines++;
1463 if (line->count)
1464 src->coverage.lines_executed++;
1469 /* Read in the source file one line at a time, and output that line to
1470 the gcov file preceded by its execution count and other
1471 information. */
1473 static void
1474 output_lines (gcov_file, src)
1475 FILE *gcov_file;
1476 const source_t *src;
1478 FILE *source_file;
1479 unsigned line_num; /* current line number. */
1480 const line_t *line; /* current line info ptr. */
1481 char string[STRING_SIZE]; /* line buffer. */
1482 char const *retval = ""; /* status of source file reading. */
1484 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1485 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1486 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1488 source_file = fopen (src->name, "r");
1489 if (!source_file)
1491 fnotice (stderr, "%s:cannot open source file\n", src->name);
1492 retval = NULL;
1494 else
1496 struct stat status;
1498 if (!fstat (fileno (source_file), &status)
1499 && status.st_mtime > bbg_file_time)
1501 fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1502 src->name, bbg_file_name);
1503 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1504 "-", 0);
1508 for (line_num = 1, line = &src->lines[line_num];
1509 line_num < src->num_lines; line_num++, line++)
1511 /* For lines which don't exist in the .bb file, print '-' before
1512 the source line. For lines which exist but were never
1513 executed, print '#####' before the source line. Otherwise,
1514 print the execution count before the source line. There are
1515 16 spaces of indentation added before the source line so that
1516 tabs won't be messed up. */
1517 fprintf (gcov_file, "%9s:%5u:",
1518 !line->exists ? "-" : !line->count ? "#####"
1519 : format_gcov (line->count, 0, -1), line_num);
1521 if (retval)
1523 /* Copy source line. */
1526 retval = fgets (string, STRING_SIZE, source_file);
1527 if (!retval)
1529 fnotice (stderr, "%s:unexpected EOF\n", src->name);
1530 break;
1532 fputs (retval, gcov_file);
1534 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1536 if (!retval)
1537 fputs ("??\n", gcov_file);
1539 if (flag_branches)
1541 int ix;
1542 arc_t *arc;
1544 for (ix = 0, arc = line->branches; arc; arc = arc->line_next, ix++)
1546 if (arc->is_call)
1548 if (arc->src->count)
1549 fnotice
1550 (gcov_file, "call %2d returns %s\n", ix,
1551 format_gcov (arc->src->count - arc->count,
1552 arc->src->count,
1553 -flag_counts));
1554 else
1555 fnotice (gcov_file, "call %2d never executed\n", ix);
1557 else
1559 if (arc->src->count)
1560 fnotice
1561 (gcov_file, "branch %2d taken %s\n", ix,
1562 format_gcov (arc->count, arc->src->count,
1563 -flag_counts));
1564 else
1565 fnotice (gcov_file, "branch %2d never executed\n", ix);
1571 /* Handle all remaining source lines. There may be lines after the
1572 last line of code. */
1573 if (retval)
1575 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1577 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1579 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1581 retval = fgets (string, STRING_SIZE, source_file);
1582 if (!retval)
1583 break;
1584 fputs (retval, gcov_file);
1589 if (source_file)
1590 fclose (source_file);