1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
4 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
5 Free Software Foundation, Inc.
6 Contributed by James E. Wilson of Cygnus Support.
7 Mangled by Bob Manson of Cygnus Support.
8 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
10 Gcov is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
15 Gcov is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with Gcov; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
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 /* Need an option to show individual block counts, and show
33 probabilities of fall through arcs. */
37 #include "coretypes.h"
48 /* The gcno file is generated by -ftest-coverage option. The gcda file is
49 generated by a program compiled with -fprofile-arcs. Their formats
50 are documented in gcov-io.h. */
52 /* The functions in this file for creating and solution program flow graphs
53 are very similar to functions in the gcc source file profile.c. In
54 some places we make use of the knowledge of how profile.c works to
55 select particular algorithms here. */
57 /* The code validates that the profile information read in corresponds
58 to the code currently being compiled. Rather than checking for
59 identical files, the code below computes a checksum on the CFG
60 (based on the order of basic blocks and the arcs in the CFG). If
61 the CFG checksum in the gcda file match the CFG checksum for the
62 code currently being compiled, the profile data will be used. */
64 /* This is the size of the buffer used to read in source file lines. */
66 #define STRING_SIZE 200
72 /* Describes an arc between two basic blocks. */
74 typedef struct arc_info
76 /* source and destination blocks. */
77 struct block_info
*src
;
78 struct block_info
*dst
;
80 /* transition counts. */
82 /* used in cycle search, so that we do not clobber original counts. */
85 unsigned int count_valid
: 1;
86 unsigned int on_tree
: 1;
87 unsigned int fake
: 1;
88 unsigned int fall_through
: 1;
90 /* Arc is for a function that abnormally returns. */
91 unsigned int is_call_non_return
: 1;
93 /* Arc is for catch/setjmp. */
94 unsigned int is_nonlocal_return
: 1;
96 /* Is an unconditional branch. */
97 unsigned int is_unconditional
: 1;
99 /* Loop making arc. */
100 unsigned int cycle
: 1;
102 /* Next branch on line. */
103 struct arc_info
*line_next
;
105 /* Links to next arc on src and dst lists. */
106 struct arc_info
*succ_next
;
107 struct arc_info
*pred_next
;
110 /* Describes a basic block. Contains lists of arcs to successor and
111 predecessor blocks. */
113 typedef struct block_info
115 /* Chain of exit and entry arcs. */
119 /* Number of unprocessed exit and entry arcs. */
123 /* Block execution count. */
126 unsigned count_valid
: 1;
127 unsigned valid_chain
: 1;
128 unsigned invalid_chain
: 1;
130 /* Block is a call instrumenting site. */
131 unsigned is_call_site
: 1; /* Does the call. */
132 unsigned is_call_return
: 1; /* Is the return. */
134 /* Block is a landing pad for longjmp or throw. */
135 unsigned is_nonlocal_return
: 1;
141 /* Array of line numbers and source files. source files are
142 introduced by a linenumber of zero, the next 'line number' is
143 the number of the source file. Always starts with a source
147 } line
; /* Valid until blocks are linked onto lines */
150 /* Single line graph cycle workspace. Used for all-blocks
154 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
158 /* Temporary chain for solving graph, and for chaining blocks on one
160 struct block_info
*chain
;
164 /* Describes a single function. Contains an array of basic blocks. */
166 typedef struct function_info
168 /* Name of function. */
171 unsigned lineno_checksum
;
172 unsigned cfg_checksum
;
174 /* Array of basic blocks. */
177 unsigned blocks_executed
;
179 /* Raw arc coverage counts. */
183 /* First line number. */
185 struct source_info
*src
;
187 /* Next function in same source file. */
188 struct function_info
*line_next
;
191 struct function_info
*next
;
194 /* Describes coverage of a file or function. */
196 typedef struct coverage_info
202 int branches_executed
;
211 /* Describes a single line of source. Contains a chain of basic blocks
214 typedef struct line_info
216 gcov_type count
; /* execution count */
219 arc_t
*branches
; /* branches from blocks that end on this
220 line. Used for branch-counts when not
222 block_t
*blocks
; /* blocks which start on this line. Used
223 in all-blocks mode. */
228 /* Describes a file mentioned in the block graph. Contains an array
231 typedef struct source_info
233 /* Name of source file. */
238 /* Array of line information. */
244 /* Functions in this source file. These are in ascending line
246 function_t
*functions
;
248 /* Next source file. */
249 struct source_info
*next
;
252 /* Holds a list of function basic block graphs. */
254 static function_t
*functions
;
256 /* This points to the head of the sourcefile structure list. New elements
257 are always prepended. */
259 static source_t
*sources
;
261 /* Next index for a source file. */
263 static unsigned source_index
;
265 /* This holds data summary information. */
267 static struct gcov_summary object_summary
;
268 static unsigned program_count
;
270 /* Modification time of graph file. */
272 static time_t bbg_file_time
;
274 /* Name and file pointer of the input file for the basic block graph. */
276 static char *bbg_file_name
;
278 /* Stamp of the bbg file */
279 static unsigned bbg_stamp
;
281 /* Name and file pointer of the input file for the arc count data. */
283 static char *da_file_name
;
285 /* Data file is missing. */
287 static int no_data_file
;
289 /* If there is several input files, compute and display results after
290 reading all data files. This way if two or more gcda file refer to
291 the same source file (eg inline subprograms in a .h file), the
294 static int multiple_files
= 0;
296 /* Output branch probabilities. */
298 static int flag_branches
= 0;
300 /* Show unconditional branches too. */
301 static int flag_unconditional
= 0;
303 /* Output a gcov file if this is true. This is on by default, and can
304 be turned off by the -n option. */
306 static int flag_gcov_file
= 1;
308 /* Output progress indication if this is true. This is off by default
309 and can be turned on by the -d option. */
311 static int flag_display_progress
= 0;
313 /* For included files, make the gcov output file name include the name
314 of the input source file. For example, if x.h is included in a.c,
315 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
317 static int flag_long_names
= 0;
319 /* Output count information for every basic block, not merely those
320 that contain line number information. */
322 static int flag_all_blocks
= 0;
324 /* Output summary info for each function. */
326 static int flag_function_summary
= 0;
328 /* Object directory file prefix. This is the directory/file where the
329 graph and data files are looked for, if nonzero. */
331 static char *object_directory
= 0;
333 /* Preserve all pathname components. Needed when object files and
334 source files are in subdirectories. '/' is mangled as '#', '.' is
335 elided and '..' mangled to '^'. */
337 static int flag_preserve_paths
= 0;
339 /* Output the number of times a branch was taken as opposed to the percentage
340 of times it was taken. */
342 static int flag_counts
= 0;
344 /* Forward declarations. */
345 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2
;
346 static int process_args (int, char **);
347 static void print_usage (int) ATTRIBUTE_NORETURN
;
348 static void print_version (void) ATTRIBUTE_NORETURN
;
349 static void process_file (const char *);
350 static void generate_results (const char *);
351 static void create_file_names (const char *);
352 static source_t
*find_source (const char *);
353 static int read_graph_file (void);
354 static int read_count_file (void);
355 static void solve_flow_graph (function_t
*);
356 static void add_branch_counts (coverage_t
*, const arc_t
*);
357 static void add_line_counts (coverage_t
*, function_t
*);
358 static void function_summary (const coverage_t
*, const char *);
359 static const char *format_gcov (gcov_type
, gcov_type
, int);
360 static void accumulate_line_counts (source_t
*);
361 static int output_branch_count (FILE *, int, const arc_t
*);
362 static void output_lines (FILE *, const source_t
*);
363 static char *make_gcov_file_name (const char *, const char *);
364 static void release_structures (void);
365 extern int main (int, char **);
368 main (int argc
, char **argv
)
373 /* Unlock the stdio streams. */
374 unlock_std_streams ();
378 /* Handle response files. */
379 expandargv (&argc
, &argv
);
381 argno
= process_args (argc
, argv
);
385 if (argc
- argno
> 1)
390 for (; argno
!= argc
; argno
++)
392 if (flag_display_progress
)
393 printf("Processing file %d out of %d\n",
394 argno
- first_arg
+ 1, argc
- first_arg
);
395 process_file (argv
[argno
]);
398 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
400 release_structures ();
406 fnotice (FILE *file
, const char *cmsgid
, ...)
410 va_start (ap
, cmsgid
);
411 vfprintf (file
, _(cmsgid
), ap
);
415 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
416 otherwise the output of --help. */
419 print_usage (int error_p
)
421 FILE *file
= error_p
? stderr
: stdout
;
422 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
424 fnotice (file
, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
425 fnotice (file
, "Print code coverage information.\n\n");
426 fnotice (file
, " -h, --help Print this help, then exit\n");
427 fnotice (file
, " -v, --version Print version number, then exit\n");
428 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
429 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
430 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
431 rather than percentages\n");
432 fnotice (file
, " -n, --no-output Do not create an output file\n");
433 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
435 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
436 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
437 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
438 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
439 fnotice (file
, " -d, --display-progress Display progress information\n");
440 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
445 /* Print version information and exit. */
450 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
451 fprintf (stdout
, "Copyright %s 2011 Free Software Foundation, Inc.\n",
454 _("This is free software; see the source for copying conditions.\n"
455 "There is NO warranty; not even for MERCHANTABILITY or \n"
456 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
457 exit (SUCCESS_EXIT_CODE
);
460 static const struct option options
[] =
462 { "help", no_argument
, NULL
, 'h' },
463 { "version", no_argument
, NULL
, 'v' },
464 { "all-blocks", no_argument
, NULL
, 'a' },
465 { "branch-probabilities", no_argument
, NULL
, 'b' },
466 { "branch-counts", no_argument
, NULL
, 'c' },
467 { "no-output", no_argument
, NULL
, 'n' },
468 { "long-file-names", no_argument
, NULL
, 'l' },
469 { "function-summaries", no_argument
, NULL
, 'f' },
470 { "preserve-paths", no_argument
, NULL
, 'p' },
471 { "object-directory", required_argument
, NULL
, 'o' },
472 { "object-file", required_argument
, NULL
, 'o' },
473 { "unconditional-branches", no_argument
, NULL
, 'u' },
474 { "display-progress", no_argument
, NULL
, 'd' },
478 /* Process args, return index to first non-arg. */
481 process_args (int argc
, char **argv
)
485 while ((opt
= getopt_long (argc
, argv
, "abcdfhlno:puv", options
, NULL
)) != -1)
499 flag_function_summary
= 1;
503 /* print_usage will exit. */
511 object_directory
= optarg
;
514 flag_preserve_paths
= 1;
517 flag_unconditional
= 1;
520 flag_display_progress
= 1;
524 /* print_version will exit. */
527 /* print_usage will exit. */
534 /* Process a single source file. */
537 process_file (const char *file_name
)
541 function_t
*old_functions
;
543 /* Save and clear the list of current functions. They will be appended
545 old_functions
= functions
;
548 create_file_names (file_name
);
549 if (read_graph_file ())
554 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
558 if (read_count_file ())
561 for (fn_p
= NULL
, fn
= functions
; fn
; fn_p
= fn
, fn
= fn
->next
)
562 solve_flow_graph (fn
);
565 fn_p
->next
= old_functions
;
569 generate_results (const char *file_name
)
574 for (src
= sources
; src
; src
= src
->next
)
575 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
576 for (fn
= functions
; fn
; fn
= fn
->next
)
580 memset (&coverage
, 0, sizeof (coverage
));
581 coverage
.name
= fn
->name
;
582 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
583 if (flag_function_summary
)
585 function_summary (&coverage
, "Function");
586 fnotice (stdout
, "\n");
590 for (src
= sources
; src
; src
= src
->next
)
592 accumulate_line_counts (src
);
593 function_summary (&src
->coverage
, "File");
596 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->name
);
597 FILE *gcov_file
= fopen (gcov_file_name
, "w");
601 fnotice (stdout
, "%s:creating '%s'\n",
602 src
->name
, gcov_file_name
);
603 output_lines (gcov_file
, src
);
604 if (ferror (gcov_file
))
605 fnotice (stderr
, "%s:error writing output file '%s'\n",
606 src
->name
, gcov_file_name
);
610 fnotice (stderr
, "%s:could not open output file '%s'\n",
611 src
->name
, gcov_file_name
);
612 free (gcov_file_name
);
614 fnotice (stdout
, "\n");
618 /* Release all memory used. */
621 release_structures (void)
626 while ((src
= sources
))
634 while ((fn
= functions
))
639 functions
= fn
->next
;
640 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
644 for (arc
= block
->succ
; arc
; arc
= arc_n
)
646 arc_n
= arc
->succ_next
;
655 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
656 is not specified, these are looked for in the current directory,
657 and named from the basename of the FILE_NAME sans extension. If
658 OBJECT_DIRECTORY is specified and is a directory, the files are in
659 that directory, but named from the basename of the FILE_NAME, sans
660 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
661 the object *file*, and the data files are named from that. */
664 create_file_names (const char *file_name
)
668 int length
= strlen (file_name
);
671 /* Free previous file names. */
672 free (bbg_file_name
);
674 da_file_name
= bbg_file_name
= NULL
;
678 if (object_directory
&& object_directory
[0])
682 length
+= strlen (object_directory
) + 2;
683 name
= XNEWVEC (char, length
);
686 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
687 strcat (name
, object_directory
);
688 if (base
&& (! IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
693 name
= XNEWVEC (char, length
+ 1);
700 /* Append source file name. */
701 const char *cptr
= lbasename (file_name
);
702 strcat (name
, cptr
? cptr
: file_name
);
705 /* Remove the extension. */
706 cptr
= strrchr (name
, '.');
710 length
= strlen (name
);
712 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
713 strcpy (bbg_file_name
, name
);
714 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
716 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
717 strcpy (da_file_name
, name
);
718 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
724 /* Find or create a source file structure for FILE_NAME. Copies
725 FILE_NAME on creation */
728 find_source (const char *file_name
)
734 file_name
= "<unknown>";
736 for (src
= sources
; src
; src
= src
->next
)
737 if (!filename_cmp (file_name
, src
->name
))
742 src
= XCNEW (source_t
);
743 src
->name
= xstrdup (file_name
);
744 src
->coverage
.name
= src
->name
;
745 src
->index
= source_index
++;
749 if (!stat (file_name
, &status
))
750 src
->file_time
= status
.st_mtime
;
753 if (src
->file_time
> bbg_file_time
)
755 static int info_emitted
;
757 fnotice (stderr
, "%s:source file is newer than graph file '%s'\n",
758 src
->name
, bbg_file_name
);
762 "(the message is only displayed one per source file)\n");
771 /* Read the graph file. Return nonzero on fatal error. */
774 read_graph_file (void)
777 unsigned current_tag
= 0;
778 struct function_info
*fn
= NULL
;
779 function_t
*old_functions_head
= functions
;
780 source_t
*src
= NULL
;
784 if (!gcov_open (bbg_file_name
, 1))
786 fnotice (stderr
, "%s:cannot open graph file\n", bbg_file_name
);
789 bbg_file_time
= gcov_time ();
790 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
792 fnotice (stderr
, "%s:not a gcov graph file\n", bbg_file_name
);
797 version
= gcov_read_unsigned ();
798 if (version
!= GCOV_VERSION
)
802 GCOV_UNSIGNED2STRING (v
, version
);
803 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
805 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
806 bbg_file_name
, v
, e
);
808 bbg_stamp
= gcov_read_unsigned ();
810 while ((tag
= gcov_read_unsigned ()))
812 unsigned length
= gcov_read_unsigned ();
813 gcov_position_t base
= gcov_position ();
815 if (tag
== GCOV_TAG_FUNCTION
)
818 unsigned ident
, lineno
;
819 unsigned lineno_checksum
, cfg_checksum
;
821 function_t
*probe
, *prev
;
823 ident
= gcov_read_unsigned ();
824 lineno_checksum
= gcov_read_unsigned ();
825 cfg_checksum
= gcov_read_unsigned ();
826 function_name
= xstrdup (gcov_read_string ());
827 src
= find_source (gcov_read_string ());
828 lineno
= gcov_read_unsigned ();
830 fn
= XCNEW (function_t
);
831 fn
->name
= function_name
;
833 fn
->lineno_checksum
= lineno_checksum
;
834 fn
->cfg_checksum
= cfg_checksum
;
838 fn
->next
= functions
;
842 if (lineno
>= src
->num_lines
)
843 src
->num_lines
= lineno
+ 1;
844 /* Now insert it into the source file's list of
845 functions. Normally functions will be encountered in
846 ascending order, so a simple scan is quick. */
847 for (probe
= src
->functions
, prev
= NULL
;
848 probe
&& probe
->line
> lineno
;
849 prev
= probe
, probe
= probe
->line_next
)
851 fn
->line_next
= probe
;
853 prev
->line_next
= fn
;
857 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
860 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
861 bbg_file_name
, fn
->name
);
864 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
865 fn
->num_blocks
= num_blocks
;
867 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
868 for (ix
= 0; ix
!= num_blocks
; ix
++)
869 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
872 else if (fn
&& tag
== GCOV_TAG_ARCS
)
874 unsigned src
= gcov_read_unsigned ();
875 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
877 if (src
>= fn
->num_blocks
|| fn
->blocks
[src
].succ
)
882 struct arc_info
*arc
;
883 unsigned dest
= gcov_read_unsigned ();
884 unsigned flags
= gcov_read_unsigned ();
886 if (dest
>= fn
->num_blocks
)
890 arc
->dst
= &fn
->blocks
[dest
];
891 arc
->src
= &fn
->blocks
[src
];
894 arc
->count_valid
= 0;
895 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
896 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
897 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
899 arc
->succ_next
= fn
->blocks
[src
].succ
;
900 fn
->blocks
[src
].succ
= arc
;
901 fn
->blocks
[src
].num_succ
++;
903 arc
->pred_next
= fn
->blocks
[dest
].pred
;
904 fn
->blocks
[dest
].pred
= arc
;
905 fn
->blocks
[dest
].num_pred
++;
911 /* Exceptional exit from this function, the
912 source block must be a call. */
913 fn
->blocks
[src
].is_call_site
= 1;
914 arc
->is_call_non_return
= 1;
918 /* Non-local return from a callee of this
919 function. The destination block is a catch or
921 arc
->is_nonlocal_return
= 1;
922 fn
->blocks
[dest
].is_nonlocal_return
= 1;
930 else if (fn
&& tag
== GCOV_TAG_LINES
)
932 unsigned blockno
= gcov_read_unsigned ();
933 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
935 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
940 unsigned lineno
= gcov_read_unsigned ();
947 line_nos
[ix
++] = src
->index
;
949 line_nos
[ix
++] = lineno
;
950 if (lineno
>= src
->num_lines
)
951 src
->num_lines
= lineno
+ 1;
955 const char *file_name
= gcov_read_string ();
959 src
= find_source (file_name
);
962 line_nos
[ix
++] = src
->index
;
966 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
967 fn
->blocks
[blockno
].u
.line
.num
= ix
;
969 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
974 gcov_sync (base
, length
);
975 if (gcov_is_error ())
978 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
985 /* We built everything backwards, so nreverse them all. */
987 /* Reverse sources. Not strictly necessary, but we'll then process
988 them in the 'expected' order. */
990 source_t
*src
, *src_p
, *src_n
;
992 for (src_p
= NULL
, src
= sources
; src
; src_p
= src
, src
= src_n
)
1000 /* Reverse functions. */
1002 function_t
*fn
, *fn_p
, *fn_n
;
1004 for (fn_p
= old_functions_head
, fn
= functions
;
1005 fn
!= old_functions_head
;
1006 fn_p
= fn
, fn
= fn_n
)
1013 /* Reverse the arcs. */
1014 for (ix
= fn
->num_blocks
; ix
--;)
1016 arc_t
*arc
, *arc_p
, *arc_n
;
1018 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1019 arc_p
= arc
, arc
= arc_n
)
1021 arc_n
= arc
->succ_next
;
1022 arc
->succ_next
= arc_p
;
1024 fn
->blocks
[ix
].succ
= arc_p
;
1026 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1027 arc_p
= arc
, arc
= arc_n
)
1029 arc_n
= arc
->pred_next
;
1030 arc
->pred_next
= arc_p
;
1032 fn
->blocks
[ix
].pred
= arc_p
;
1040 /* Reads profiles from the count file and attach to each
1041 function. Return nonzero if fatal error. */
1044 read_count_file (void)
1049 function_t
*fn
= NULL
;
1052 if (!gcov_open (da_file_name
, 1))
1054 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1059 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1061 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1066 version
= gcov_read_unsigned ();
1067 if (version
!= GCOV_VERSION
)
1071 GCOV_UNSIGNED2STRING (v
, version
);
1072 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1074 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1075 da_file_name
, v
, e
);
1077 tag
= gcov_read_unsigned ();
1078 if (tag
!= bbg_stamp
)
1080 fnotice (stderr
, "%s:stamp mismatch with graph file\n", da_file_name
);
1084 while ((tag
= gcov_read_unsigned ()))
1086 unsigned length
= gcov_read_unsigned ();
1087 unsigned long base
= gcov_position ();
1089 if (tag
== GCOV_TAG_OBJECT_SUMMARY
)
1090 gcov_read_summary (&object_summary
);
1091 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1093 else if (tag
== GCOV_TAG_FUNCTION
)
1096 unsigned ident
= gcov_read_unsigned ();
1097 struct function_info
*fn_n
= functions
;
1099 /* Try to find the function in the list.
1100 To speed up the search, first start from the last function
1102 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1106 else if ((fn
= fn_n
))
1110 fnotice (stderr
, "%s:unknown function '%u'\n",
1111 da_file_name
, ident
);
1114 if (fn
->ident
== ident
)
1121 else if (gcov_read_unsigned () != fn
->lineno_checksum
1122 || gcov_read_unsigned () != fn
->cfg_checksum
)
1125 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1126 da_file_name
, fn
->name
);
1130 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1132 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1136 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1138 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1139 fn
->counts
[ix
] += gcov_read_counter ();
1141 gcov_sync (base
, length
);
1142 if ((error
= gcov_is_error ()))
1144 fnotice (stderr
, error
< 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1154 /* Solve the flow graph. Propagate counts from the instrumented arcs
1155 to the blocks and the uninstrumented arcs. */
1158 solve_flow_graph (function_t
*fn
)
1162 gcov_type
*count_ptr
= fn
->counts
;
1164 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1165 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1167 if (fn
->num_blocks
< 2)
1168 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1169 bbg_file_name
, fn
->name
);
1172 if (fn
->blocks
[0].num_pred
)
1173 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1174 bbg_file_name
, fn
->name
);
1176 /* We can't deduce the entry block counts from the lack of
1178 fn
->blocks
[0].num_pred
= ~(unsigned)0;
1180 if (fn
->blocks
[fn
->num_blocks
- 1].num_succ
)
1181 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1182 bbg_file_name
, fn
->name
);
1184 /* Likewise, we can't deduce exit block counts from the lack
1185 of its successors. */
1186 fn
->blocks
[fn
->num_blocks
- 1].num_succ
= ~(unsigned)0;
1189 /* Propagate the measured counts, this must be done in the same
1190 order as the code in profile.c */
1191 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1193 block_t
const *prev_dst
= NULL
;
1194 int out_of_order
= 0;
1195 int non_fake_succ
= 0;
1197 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1205 arc
->count
= *count_ptr
++;
1206 arc
->count_valid
= 1;
1208 arc
->dst
->num_pred
--;
1210 if (prev_dst
&& prev_dst
> arc
->dst
)
1212 prev_dst
= arc
->dst
;
1214 if (non_fake_succ
== 1)
1216 /* If there is only one non-fake exit, it is an
1217 unconditional branch. */
1218 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1221 arc
->is_unconditional
= 1;
1222 /* If this block is instrumenting a call, it might be
1223 an artificial block. It is not artificial if it has
1224 a non-fallthrough exit, or the destination of this
1225 arc has more than one entry. Mark the destination
1226 block as a return site, if none of those conditions
1228 if (blk
->is_call_site
&& arc
->fall_through
1229 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1230 arc
->dst
->is_call_return
= 1;
1234 /* Sort the successor arcs into ascending dst order. profile.c
1235 normally produces arcs in the right order, but sometimes with
1236 one or two out of order. We're not using a particularly
1240 arc_t
*start
= blk
->succ
;
1241 unsigned changes
= 1;
1245 arc_t
*arc
, *arc_p
, *arc_n
;
1248 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1250 if (arc
->dst
> arc_n
->dst
)
1254 arc_p
->succ_next
= arc_n
;
1257 arc
->succ_next
= arc_n
->succ_next
;
1258 arc_n
->succ_next
= arc
;
1271 /* Place it on the invalid chain, it will be ignored if that's
1273 blk
->invalid_chain
= 1;
1274 blk
->chain
= invalid_blocks
;
1275 invalid_blocks
= blk
;
1278 while (invalid_blocks
|| valid_blocks
)
1280 while ((blk
= invalid_blocks
))
1282 gcov_type total
= 0;
1285 invalid_blocks
= blk
->chain
;
1286 blk
->invalid_chain
= 0;
1288 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1289 total
+= arc
->count
;
1290 else if (!blk
->num_pred
)
1291 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1292 total
+= arc
->count
;
1297 blk
->count_valid
= 1;
1298 blk
->chain
= valid_blocks
;
1299 blk
->valid_chain
= 1;
1302 while ((blk
= valid_blocks
))
1305 arc_t
*arc
, *inv_arc
;
1307 valid_blocks
= blk
->chain
;
1308 blk
->valid_chain
= 0;
1309 if (blk
->num_succ
== 1)
1315 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1317 total
-= arc
->count
;
1318 if (!arc
->count_valid
)
1322 inv_arc
->count_valid
= 1;
1323 inv_arc
->count
= total
;
1326 if (dst
->count_valid
)
1328 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1330 dst
->chain
= valid_blocks
;
1331 dst
->valid_chain
= 1;
1337 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1339 dst
->chain
= invalid_blocks
;
1340 dst
->invalid_chain
= 1;
1341 invalid_blocks
= dst
;
1345 if (blk
->num_pred
== 1)
1351 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1353 total
-= arc
->count
;
1354 if (!arc
->count_valid
)
1358 inv_arc
->count_valid
= 1;
1359 inv_arc
->count
= total
;
1362 if (src
->count_valid
)
1364 if (src
->num_succ
== 1 && !src
->valid_chain
)
1366 src
->chain
= valid_blocks
;
1367 src
->valid_chain
= 1;
1373 if (!src
->num_succ
&& !src
->invalid_chain
)
1375 src
->chain
= invalid_blocks
;
1376 src
->invalid_chain
= 1;
1377 invalid_blocks
= src
;
1384 /* If the graph has been correctly solved, every block will have a
1386 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1387 if (!fn
->blocks
[ix
].count_valid
)
1389 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1390 bbg_file_name
, fn
->name
);
1397 /* Increment totals in COVERAGE according to arc ARC. */
1400 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1402 if (arc
->is_call_non_return
)
1405 if (arc
->src
->count
)
1406 coverage
->calls_executed
++;
1408 else if (!arc
->is_unconditional
)
1410 coverage
->branches
++;
1411 if (arc
->src
->count
)
1412 coverage
->branches_executed
++;
1414 coverage
->branches_taken
++;
1418 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1419 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1420 If DP is zero, no decimal point is printed. Only print 100% when
1421 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1422 format TOP. Return pointer to a static string. */
1425 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1427 static char buffer
[20];
1431 float ratio
= bottom
? (float)top
/ bottom
: 0;
1433 unsigned limit
= 100;
1436 for (ix
= dp
; ix
--; )
1439 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1440 if (percent
<= 0 && top
)
1442 else if (percent
>= limit
&& top
!= bottom
)
1443 percent
= limit
- 1;
1444 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1450 buffer
[ix
+1] = buffer
[ix
];
1454 buffer
[ix
+ 1] = '.';
1458 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)top
);
1464 /* Output summary info for a function. */
1467 function_summary (const coverage_t
*coverage
, const char *title
)
1469 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
1471 if (coverage
->lines
)
1472 fnotice (stdout
, "Lines executed:%s of %d\n",
1473 format_gcov (coverage
->lines_executed
, coverage
->lines
, 2),
1476 fnotice (stdout
, "No executable lines\n");
1480 if (coverage
->branches
)
1482 fnotice (stdout
, "Branches executed:%s of %d\n",
1483 format_gcov (coverage
->branches_executed
,
1484 coverage
->branches
, 2),
1485 coverage
->branches
);
1486 fnotice (stdout
, "Taken at least once:%s of %d\n",
1487 format_gcov (coverage
->branches_taken
,
1488 coverage
->branches
, 2),
1489 coverage
->branches
);
1492 fnotice (stdout
, "No branches\n");
1493 if (coverage
->calls
)
1494 fnotice (stdout
, "Calls executed:%s of %d\n",
1495 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
1498 fnotice (stdout
, "No calls\n");
1502 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1503 affect name generation. With preserve_paths we create a filename
1504 from all path components of the source file, replacing '/' with
1505 '#', without it we simply take the basename component. With
1506 long_output_names we prepend the processed name of the input file
1507 to each output name (except when the current source file is the
1508 input file, so you don't get a double concatenation). The two
1509 components are separated by '##'. Also '.' filename components are
1510 removed and '..' components are renamed to '^'. */
1513 make_gcov_file_name (const char *input_name
, const char *src_name
)
1518 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
1520 name
= XNEWVEC (char, strlen (src_name
) + strlen (input_name
) + 10);
1522 /* Generate the input filename part. */
1523 cptr
= flag_preserve_paths
? NULL
: lbasename (input_name
);
1524 strcat (name
, cptr
? cptr
: input_name
);
1525 strcat (name
, "##");
1529 name
= XNEWVEC (char, strlen (src_name
) + 10);
1533 /* Generate the source filename part. */
1535 cptr
= flag_preserve_paths
? NULL
: lbasename (src_name
);
1536 strcat (name
, cptr
? cptr
: src_name
);
1538 if (flag_preserve_paths
)
1540 /* Convert '/' and '\' to '#', remove '/./', convert '/../' to '#^#',
1541 convert ':' to '~' on DOS based file system. */
1542 char *pnew
= name
, *pold
= name
;
1544 /* First check for leading drive separator. */
1546 while (*pold
!= '\0')
1548 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1557 && (strstr (pold
, "/./") == pold
1558 || strstr (pold
, "/.\\") == pold
))
1560 && (strstr (pold
, "\\.\\") == pold
1561 || strstr (pold
, "\\./") == pold
)))
1563 else if (*pold
== '/'
1564 && (strstr (pold
, "/../") == pold
1565 || strstr (pold
, "/..\\") == pold
))
1567 strcpy (pnew
, "#^#");
1571 else if (*pold
== '\\'
1572 && (strstr (pold
, "\\..\\") == pold
1573 || strstr (pold
, "\\../") == pold
))
1575 strcpy (pnew
, "#^#");
1579 else if (*pold
== '/' || *pold
== '\\')
1591 strcat (name
, ".gcov");
1595 /* Scan through the bb_data for each line in the block, increment
1596 the line number execution count indicated by the execution count of
1597 the appropriate basic block. */
1600 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
1603 line_t
*line
= NULL
; /* This is propagated from one iteration to the
1606 /* Scan each basic block. */
1607 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
1609 block_t
*block
= &fn
->blocks
[ix
];
1611 const source_t
*src
= NULL
;
1614 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
1615 fn
->blocks_executed
++;
1616 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
1617 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
1620 unsigned src_n
= *++encoding
;
1622 for (src
= sources
; src
->index
!= src_n
; src
= src
->next
)
1628 line
= &src
->lines
[*encoding
];
1634 if (!line
->count
&& block
->count
)
1635 coverage
->lines_executed
++;
1638 line
->count
+= block
->count
;
1640 free (block
->u
.line
.encoding
);
1641 block
->u
.cycle
.arc
= NULL
;
1642 block
->u
.cycle
.ident
= ~0U;
1644 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
1645 /* Entry or exit block */;
1646 else if (flag_all_blocks
)
1648 line_t
*block_line
= line
? line
: &fn
->src
->lines
[fn
->line
];
1650 block
->chain
= block_line
->u
.blocks
;
1651 block_line
->u
.blocks
= block
;
1653 else if (flag_branches
)
1657 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1659 arc
->line_next
= line
->u
.branches
;
1660 line
->u
.branches
= arc
;
1661 if (coverage
&& !arc
->is_unconditional
)
1662 add_branch_counts (coverage
, arc
);
1667 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
1670 /* Accumulate the line counts of a file. */
1673 accumulate_line_counts (source_t
*src
)
1676 function_t
*fn
, *fn_p
, *fn_n
;
1679 /* Reverse the function order. */
1680 for (fn
= src
->functions
, fn_p
= NULL
; fn
;
1681 fn_p
= fn
, fn
= fn_n
)
1683 fn_n
= fn
->line_next
;
1684 fn
->line_next
= fn_p
;
1686 src
->functions
= fn_p
;
1688 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
1690 if (!flag_all_blocks
)
1692 arc_t
*arc
, *arc_p
, *arc_n
;
1694 /* Total and reverse the branch information. */
1695 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
1696 arc_p
= arc
, arc
= arc_n
)
1698 arc_n
= arc
->line_next
;
1699 arc
->line_next
= arc_p
;
1701 add_branch_counts (&src
->coverage
, arc
);
1703 line
->u
.branches
= arc_p
;
1705 else if (line
->u
.blocks
)
1707 /* The user expects the line count to be the number of times
1708 a line has been executed. Simply summing the block count
1709 will give an artificially high number. The Right Thing
1710 is to sum the entry counts to the graph of blocks on this
1711 line, then find the elementary cycles of the local graph
1712 and add the transition counts of those cycles. */
1713 block_t
*block
, *block_p
, *block_n
;
1714 gcov_type count
= 0;
1716 /* Reverse the block information. */
1717 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
1718 block_p
= block
, block
= block_n
)
1720 block_n
= block
->chain
;
1721 block
->chain
= block_p
;
1722 block
->u
.cycle
.ident
= ix
;
1724 line
->u
.blocks
= block_p
;
1726 /* Sum the entry arcs. */
1727 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1731 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
1733 if (arc
->src
->u
.cycle
.ident
!= ix
)
1734 count
+= arc
->count
;
1736 add_branch_counts (&src
->coverage
, arc
);
1739 /* Initialize the cs_count. */
1740 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1741 arc
->cs_count
= arc
->count
;
1744 /* Find the loops. This uses the algorithm described in
1745 Tiernan 'An Efficient Search Algorithm to Find the
1746 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1747 the P array by having each block point to the arc that
1748 connects to the previous block. The H array is implicitly
1749 held because of the arc ordering, and the block's
1750 previous arc pointer.
1752 Although the algorithm is O(N^3) for highly connected
1753 graphs, at worst we'll have O(N^2), as most blocks have
1754 only one or two exits. Most graphs will be small.
1756 For each loop we find, locate the arc with the smallest
1757 transition count, and add that to the cumulative
1758 count. Decrease flow over the cycle and remove the arc
1759 from consideration. */
1760 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1762 block_t
*head
= block
;
1770 block_t
*dst
= arc
->dst
;
1771 if (/* Already used that arc. */
1773 /* Not to same graph, or before first vertex. */
1774 || dst
->u
.cycle
.ident
!= ix
1775 /* Already in path. */
1776 || dst
->u
.cycle
.arc
)
1778 arc
= arc
->succ_next
;
1784 /* Found a closing arc. */
1785 gcov_type cycle_count
= arc
->cs_count
;
1786 arc_t
*cycle_arc
= arc
;
1789 /* Locate the smallest arc count of the loop. */
1790 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1791 dst
= probe_arc
->src
)
1792 if (cycle_count
> probe_arc
->cs_count
)
1794 cycle_count
= probe_arc
->cs_count
;
1795 cycle_arc
= probe_arc
;
1798 count
+= cycle_count
;
1799 cycle_arc
->cycle
= 1;
1801 /* Remove the flow from the cycle. */
1802 arc
->cs_count
-= cycle_count
;
1803 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1804 dst
= probe_arc
->src
)
1805 probe_arc
->cs_count
-= cycle_count
;
1807 /* Unwind to the cyclic arc. */
1808 while (head
!= cycle_arc
->src
)
1810 arc
= head
->u
.cycle
.arc
;
1811 head
->u
.cycle
.arc
= NULL
;
1815 arc
= arc
->succ_next
;
1819 /* Add new block to chain. */
1820 dst
->u
.cycle
.arc
= arc
;
1824 /* We could not add another vertex to the path. Remove
1825 the last vertex from the list. */
1826 arc
= head
->u
.cycle
.arc
;
1829 /* It was not the first vertex. Move onto next arc. */
1830 head
->u
.cycle
.arc
= NULL
;
1832 arc
= arc
->succ_next
;
1833 goto current_vertex
;
1835 /* Mark this block as unusable. */
1836 block
->u
.cycle
.ident
= ~0U;
1839 line
->count
= count
;
1844 src
->coverage
.lines
++;
1846 src
->coverage
.lines_executed
++;
1851 /* Output information about ARC number IX. Returns nonzero if
1852 anything is output. */
1855 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
1858 if (arc
->is_call_non_return
)
1860 if (arc
->src
->count
)
1862 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
1863 format_gcov (arc
->src
->count
- arc
->count
,
1864 arc
->src
->count
, -flag_counts
));
1867 fnotice (gcov_file
, "call %2d never executed\n", ix
);
1869 else if (!arc
->is_unconditional
)
1871 if (arc
->src
->count
)
1872 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
1873 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
1874 arc
->fall_through
? " (fallthrough)" : "");
1876 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
1878 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
1880 if (arc
->src
->count
)
1881 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
1882 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
1884 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
1892 /* Read in the source file one line at a time, and output that line to
1893 the gcov file preceded by its execution count and other
1897 output_lines (FILE *gcov_file
, const source_t
*src
)
1900 unsigned line_num
; /* current line number. */
1901 const line_t
*line
; /* current line info ptr. */
1902 char string
[STRING_SIZE
]; /* line buffer. */
1903 char const *retval
= ""; /* status of source file reading. */
1904 function_t
*fn
= NULL
;
1906 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->name
);
1907 if (!multiple_files
)
1909 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
1910 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
1911 no_data_file
? "-" : da_file_name
);
1912 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0,
1913 object_summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
);
1915 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
1917 source_file
= fopen (src
->name
, "r");
1920 fnotice (stderr
, "%s:cannot open source file\n", src
->name
);
1923 else if (src
->file_time
== 0)
1924 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
1927 fn
= src
->functions
;
1929 for (line_num
= 1, line
= &src
->lines
[line_num
];
1930 line_num
< src
->num_lines
; line_num
++, line
++)
1932 for (; fn
&& fn
->line
== line_num
; fn
= fn
->line_next
)
1934 arc_t
*arc
= fn
->blocks
[fn
->num_blocks
- 1].pred
;
1935 gcov_type return_count
= fn
->blocks
[fn
->num_blocks
- 1].count
;
1937 for (; arc
; arc
= arc
->pred_next
)
1939 return_count
-= arc
->count
;
1941 fprintf (gcov_file
, "function %s", fn
->name
);
1942 fprintf (gcov_file
, " called %s",
1943 format_gcov (fn
->blocks
[0].count
, 0, -1));
1944 fprintf (gcov_file
, " returned %s",
1945 format_gcov (return_count
, fn
->blocks
[0].count
, 0));
1946 fprintf (gcov_file
, " blocks executed %s",
1947 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
1948 fprintf (gcov_file
, "\n");
1951 /* For lines which don't exist in the .bb file, print '-' before
1952 the source line. For lines which exist but were never
1953 executed, print '#####' before the source line. Otherwise,
1954 print the execution count before the source line. There are
1955 16 spaces of indentation added before the source line so that
1956 tabs won't be messed up. */
1957 fprintf (gcov_file
, "%9s:%5u:",
1958 !line
->exists
? "-" : !line
->count
? "#####"
1959 : format_gcov (line
->count
, 0, -1), line_num
);
1963 /* Copy source line. */
1966 retval
= fgets (string
, STRING_SIZE
, source_file
);
1969 fputs (retval
, gcov_file
);
1971 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
1974 fputs ("/*EOF*/\n", gcov_file
);
1976 if (flag_all_blocks
)
1982 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
1983 block
= block
->chain
)
1985 if (!block
->is_call_return
)
1986 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
1987 !line
->exists
? "-" : !block
->count
? "$$$$$"
1988 : format_gcov (block
->count
, 0, -1),
1991 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1992 jx
+= output_branch_count (gcov_file
, jx
, arc
);
1995 else if (flag_branches
)
2000 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
2001 ix
+= output_branch_count (gcov_file
, ix
, arc
);
2005 /* Handle all remaining source lines. There may be lines after the
2006 last line of code. */
2009 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
2011 fprintf (gcov_file
, "%9s:%5u:%s", "-", line_num
, retval
);
2013 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
2015 retval
= fgets (string
, STRING_SIZE
, source_file
);
2018 fputs (retval
, gcov_file
);
2024 fclose (source_file
);