1 /* Gcov.c: prepend line execution counts and branch probabilities to a
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.
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 Gcov is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Gcov; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* ??? The code in final.c that produces the struct bb assumes that there is
24 no padding between the fields. This is not necessary true. The current
25 code can only be trusted if longs and pointers are the same size. */
27 /* ??? No need to print an execution count on every line, could just print
28 it on the first line of each block, and only print it on a subsequent
29 line in the same block if the count changes. */
31 /* ??? Print a list of the ten blocks with the highest execution counts,
32 and list the line numbers corresponding to those blocks. Also, perhaps
33 list the line numbers with the highest execution counts, only printing
34 the first if there are several which are all listed in the same block. */
36 /* ??? Should have an option to print the number of basic blocks, and the
37 percent of them that are covered. */
39 /* ??? Does not correctly handle the case where two .bb files refer to the
40 same included source file. For example, if one has a short file containing
41 only inline functions, which is then included in two other files, then
42 there will be two .bb files which refer to the include file, but there
43 is no way to get the total execution counts for the included file, can
44 only get execution counts for one or the other of the including files. */
54 typedef HOST_WIDEST_INT gcov_type
;
57 /* The .bb file format consists of several lists of 4-byte integers
58 which are the line numbers of each basic block in the file. Each
59 list is terminated by a zero. These lists correspond to the basic
60 blocks in the reconstructed program flow graph.
62 A line number of -1 indicates that a source file name (padded to a
63 long boundary) follows. The padded file name is followed by
64 another -1 to make it easy to scan past file names. A -2 indicates
65 that a function name (padded to a long boundary) follows; the name
66 is followed by another -2 to make it easy to scan past the function
69 The .bbg file contains enough info to enable gcov to reconstruct the
70 program flow graph. The first word is the number of basic blocks,
71 the second word is the number of arcs, followed by the list of arcs
72 (source bb, dest bb pairs), then a -1, then the number of instrumented
73 arcs followed by the instrumented arcs, followed by another -1. This
74 is repeated for each function.
76 The .da file contains the execution count for each instrumented branch.
78 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
79 and the .da files are created when an executable compiled with
80 -fprofile-arcs is run. */
82 /* The functions in this file for creating and solution program flow graphs
83 are very similar to functions in the gcc source file profile.c. */
85 /* This is the size of the buffer used to read in source file lines. */
87 #define STRING_SIZE 200
89 /* One copy of this structure is created for each source file mentioned in the
96 struct sourcefile
*next
;
99 /* This points to the head of the sourcefile structure list. */
101 struct sourcefile
*sources
;
103 /* One of these is dynamically created whenever we identify an arc in the
110 unsigned int count_valid
: 1;
111 unsigned int on_tree
: 1;
112 unsigned int fake
: 1;
113 unsigned int fall_through
: 1;
115 /* Not needed for gcov, but defined in profile.c. */
118 struct adj_list
*pred_next
;
119 struct adj_list
*succ_next
;
122 /* Count the number of basic blocks, and create an array of these structures,
123 one for each bb in the function. */
126 struct adj_list
*succ
;
127 struct adj_list
*pred
;
128 gcov_type succ_count
;
129 gcov_type pred_count
;
130 gcov_type exec_count
;
131 unsigned int count_valid
: 1;
132 unsigned int on_tree
: 1;
134 /* Not needed for gcov, but defined in profile.c. */
139 /* When outputting branch probabilities, one of these structures is created
140 for each branch/call. */
147 struct arcdata
*next
;
150 /* Used to save the list of bb_graphs, one per function. */
152 struct bb_info_list
{
153 /* Indexed by block number, holds the basic block graph for one function. */
154 struct bb_info
*bb_graph
;
156 struct bb_info_list
*next
;
159 /* Holds a list of function basic block graphs. */
161 static struct bb_info_list
*bb_graph_list
= 0;
163 /* Name and file pointer of the input file for the basic block graph. */
165 static char *bbg_file_name
;
166 static FILE *bbg_file
;
168 /* Name and file pointer of the input file for the arc count data. */
170 static char *da_file_name
;
171 static FILE *da_file
;
173 /* Name and file pointer of the input file for the basic block line counts. */
175 static char *bb_file_name
;
176 static FILE *bb_file
;
178 /* Holds the entire contents of the bb_file read into memory. */
180 static char *bb_data
;
182 /* Size of bb_data array in longs. */
184 static long bb_data_size
;
186 /* Name and file pointer of the output file. */
188 static char *gcov_file_name
;
189 static FILE *gcov_file
;
191 /* Name of the file mentioned on the command line. */
193 static char *input_file_name
= 0;
195 /* Output branch probabilities if true. */
197 static int output_branch_probs
= 0;
199 /* Output a gcov file if this is true. This is on by default, and can
200 be turned off by the -n option. */
202 static int output_gcov_file
= 1;
204 /* For included files, make the gcov output file name include the name of
205 the input source file. For example, if x.h is included in a.c, then the
206 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
207 when a single source file is specified. */
209 static int output_long_names
= 0;
211 /* Output summary info for each function. */
213 static int output_function_summary
= 0;
215 /* Object directory file prefix. This is the directory where .bb and .bbg
216 files are looked for, if non-zero. */
218 static char *object_directory
= 0;
220 /* Output the number of times a branch was taken as opposed to the percentage
221 of times it was taken. Turned on by the -c option */
223 static int output_branch_counts
= 0;
225 /* Forward declarations. */
226 static void process_args
PARAMS ((int, char **));
227 static void open_files
PARAMS ((void));
228 static void read_files
PARAMS ((void));
229 static void scan_for_source_files
PARAMS ((void));
230 static void output_data
PARAMS ((void));
231 static void print_usage
PARAMS ((int)) ATTRIBUTE_NORETURN
;
232 static void print_version
PARAMS ((void)) ATTRIBUTE_NORETURN
;
233 static void init_arc
PARAMS ((struct adj_list
*, int, int, struct bb_info
*));
234 static struct adj_list
*reverse_arcs
PARAMS ((struct adj_list
*));
235 static void create_program_flow_graph
PARAMS ((struct bb_info_list
*));
236 static void solve_program_flow_graph
PARAMS ((struct bb_info_list
*));
237 static void calculate_branch_probs
PARAMS ((struct bb_info_list
*, int,
238 struct arcdata
**, int));
239 static void function_summary
PARAMS ((void));
241 extern int main
PARAMS ((int, char **));
250 process_args (argc
, argv
);
256 scan_for_source_files ();
263 static void fnotice
PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2
;
265 fnotice
VPARAMS ((FILE *file
, const char *msgid
, ...))
268 VA_FIXEDARG (ap
, FILE *, file
);
269 VA_FIXEDARG (ap
, const char *, msgid
);
271 vfprintf (file
, _(msgid
), ap
);
275 /* More 'friendly' abort that prints the line and file.
276 config.h can #define abort fancy_abort if you like that sort of thing. */
277 extern void fancy_abort
PARAMS ((void)) ATTRIBUTE_NORETURN
;
282 fnotice (stderr
, "Internal gcov abort.\n");
283 exit (FATAL_EXIT_CODE
);
286 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
287 otherwise the output of --help. */
290 print_usage (error_p
)
293 FILE *file
= error_p
? stderr
: stdout
;
294 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
295 fnotice (file
, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
296 fnotice (file
, "Print code coverage information.\n\n");
297 fnotice (file
, " -h, --help Print this help, then exit\n");
298 fnotice (file
, " -v, --version Print version number, then exit\n");
299 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
300 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
301 rather than percentages\n");
302 fnotice (file
, " -n, --no-output Do not create an output file\n");
303 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
305 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
306 fnotice (file
, " -o, --object-directory OBJDIR Search for object files in OBJDIR\n");
307 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
312 /* Print version information and exit. */
317 fnotice (stdout
, "gcov (GCC) %s\n", version_string
);
318 fnotice (stdout
, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
320 "This is free software; see the source for copying conditions. There is NO\n\
321 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
322 exit (SUCCESS_EXIT_CODE
);
325 static const struct option options
[] =
327 { "help", no_argument
, NULL
, 'h' },
328 { "version", no_argument
, NULL
, 'v' },
329 { "branch-probabilities", no_argument
, NULL
, 'b' },
330 { "branch-counts", no_argument
, NULL
, 'c' },
331 { "no-output", no_argument
, NULL
, 'n' },
332 { "long-file-names", no_argument
, NULL
, 'l' },
333 { "function-summaries", no_argument
, NULL
, 'f' },
334 { "object-directory", required_argument
, NULL
, 'o' }
337 /* Parse the command line. */
340 process_args (argc
, argv
)
346 while ((opt
= getopt_long (argc
, argv
, "hvbclnfo:", options
, NULL
)) != -1)
352 /* print_usage will exit. */
355 /* print_version will exit. */
357 output_branch_probs
= 1;
360 output_branch_counts
= 1;
363 output_gcov_file
= 0;
366 output_long_names
= 1;
369 output_function_summary
= 1;
372 object_directory
= optarg
;
376 /* print_usage will exit. */
380 if (optind
!= argc
- 1)
383 input_file_name
= argv
[optind
];
387 /* Find and open the .bb, .da, and .bbg files. */
392 int count
, objdir_count
;
395 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
396 extension, if any, and append the new extensions. */
397 count
= strlen (input_file_name
);
398 if (object_directory
)
399 objdir_count
= strlen (object_directory
);
403 da_file_name
= xmalloc (count
+ objdir_count
+ 4);
404 bb_file_name
= xmalloc (count
+ objdir_count
+ 4);
405 bbg_file_name
= xmalloc (count
+ objdir_count
+ 5);
407 if (object_directory
)
409 strcpy (da_file_name
, object_directory
);
410 strcpy (bb_file_name
, object_directory
);
411 strcpy (bbg_file_name
, object_directory
);
413 if (object_directory
[objdir_count
- 1] != '/')
415 strcat (da_file_name
, "/");
416 strcat (bb_file_name
, "/");
417 strcat (bbg_file_name
, "/");
420 cptr
= strrchr (input_file_name
, '/');
423 strcat (da_file_name
, cptr
+ 1);
424 strcat (bb_file_name
, cptr
+ 1);
425 strcat (bbg_file_name
, cptr
+ 1);
429 strcat (da_file_name
, input_file_name
);
430 strcat (bb_file_name
, input_file_name
);
431 strcat (bbg_file_name
, input_file_name
);
436 strcpy (da_file_name
, input_file_name
);
437 strcpy (bb_file_name
, input_file_name
);
438 strcpy (bbg_file_name
, input_file_name
);
441 cptr
= strrchr (bb_file_name
, '.');
443 strcpy (cptr
, ".bb");
445 strcat (bb_file_name
, ".bb");
447 cptr
= strrchr (da_file_name
, '.');
449 strcpy (cptr
, ".da");
451 strcat (da_file_name
, ".da");
453 cptr
= strrchr (bbg_file_name
, '.');
455 strcpy (cptr
, ".bbg");
457 strcat (bbg_file_name
, ".bbg");
459 bb_file
= fopen (bb_file_name
, "rb");
462 fnotice (stderr
, "Could not open basic block file %s.\n", bb_file_name
);
463 exit (FATAL_EXIT_CODE
);
466 /* If none of the functions in the file were executed, then there won't
467 be a .da file. Just assume that all counts are zero in this case. */
468 da_file
= fopen (da_file_name
, "rb");
471 fnotice (stderr
, "Could not open data file %s.\n", da_file_name
);
472 fnotice (stderr
, "Assuming that all execution counts are zero.\n");
475 bbg_file
= fopen (bbg_file_name
, "rb");
476 if (bbg_file
== NULL
)
478 fnotice (stderr
, "Could not open program flow graph file %s.\n",
480 exit (FATAL_EXIT_CODE
);
483 /* Check for empty .bbg file. This indicates that there is no executable
484 code in this source file. */
485 /* Set the EOF condition if at the end of file. */
486 ungetc (getc (bbg_file
), bbg_file
);
489 fnotice (stderr
, "No executable code associated with file %s.\n",
491 exit (FATAL_EXIT_CODE
);
495 /* Initialize a new arc. */
498 init_arc (arcptr
, source
, target
, bb_graph
)
499 struct adj_list
*arcptr
;
501 struct bb_info
*bb_graph
;
503 arcptr
->target
= target
;
504 arcptr
->source
= source
;
506 arcptr
->arc_count
= 0;
507 arcptr
->count_valid
= 0;
510 arcptr
->fall_through
= 0;
512 arcptr
->succ_next
= bb_graph
[source
].succ
;
513 bb_graph
[source
].succ
= arcptr
;
514 bb_graph
[source
].succ_count
++;
516 arcptr
->pred_next
= bb_graph
[target
].pred
;
517 bb_graph
[target
].pred
= arcptr
;
518 bb_graph
[target
].pred_count
++;
522 /* Reverse the arcs on an arc list. */
524 static struct adj_list
*
525 reverse_arcs (arcptr
)
526 struct adj_list
*arcptr
;
528 struct adj_list
*prev
= 0;
529 struct adj_list
*next
;
531 for ( ; arcptr
; arcptr
= next
)
533 next
= arcptr
->succ_next
;
534 arcptr
->succ_next
= prev
;
542 /* Construct the program flow graph from the .bbg file, and read in the data
546 create_program_flow_graph (bptr
)
547 struct bb_info_list
*bptr
;
549 long num_blocks
, number_arcs
, src
, dest
, flag_bits
, num_arcs_per_block
;
551 struct adj_list
*arcptr
;
552 struct bb_info
*bb_graph
;
554 /* Read the number of blocks. */
555 __read_long (&num_blocks
, bbg_file
, 4);
557 /* Create an array of size bb number of bb_info structs. */
558 bb_graph
= (struct bb_info
*) xcalloc (num_blocks
, sizeof (struct bb_info
));
560 bptr
->bb_graph
= bb_graph
;
561 bptr
->num_blocks
= num_blocks
;
563 /* Read and create each arc from the .bbg file. */
564 __read_long (&number_arcs
, bbg_file
, 4);
565 for (i
= 0; i
< num_blocks
; i
++)
569 __read_long (&num_arcs_per_block
, bbg_file
, 4);
570 for (j
= 0; j
< num_arcs_per_block
; j
++)
572 if (number_arcs
-- < 0)
576 __read_long (&dest
, bbg_file
, 4);
578 arcptr
= (struct adj_list
*) xmalloc (sizeof (struct adj_list
));
579 init_arc (arcptr
, src
, dest
, bb_graph
);
581 __read_long (&flag_bits
, bbg_file
, 4);
582 arcptr
->on_tree
= flag_bits
& 0x1;
583 arcptr
->fake
= !! (flag_bits
& 0x2);
584 arcptr
->fall_through
= !! (flag_bits
& 0x4);
591 /* Read and ignore the -1 separating the arc list from the arc list of the
593 __read_long (&src
, bbg_file
, 4);
597 /* Must reverse the order of all succ arcs, to ensure that they match
598 the order of the data in the .da file. */
600 for (i
= 0; i
< num_blocks
; i
++)
601 if (bb_graph
[i
].succ
)
602 bb_graph
[i
].succ
= reverse_arcs (bb_graph
[i
].succ
);
604 /* For each arc not on the spanning tree, set its execution count from
607 /* The first count in the .da file is the number of times that the function
608 was entered. This is the exec_count for block zero. */
610 /* This duplicates code in branch_prob in profile.c. */
612 for (i
= 0; i
< num_blocks
; i
++)
613 for (arcptr
= bb_graph
[i
].succ
; arcptr
; arcptr
= arcptr
->succ_next
)
614 if (! arcptr
->on_tree
)
616 gcov_type tmp_count
= 0;
617 if (da_file
&& __read_gcov_type (&tmp_count
, da_file
, 8))
620 arcptr
->arc_count
= tmp_count
;
621 arcptr
->count_valid
= 1;
622 bb_graph
[i
].succ_count
--;
623 bb_graph
[arcptr
->target
].pred_count
--;
628 solve_program_flow_graph (bptr
)
629 struct bb_info_list
*bptr
;
634 struct adj_list
*arcptr
;
635 struct bb_info
*bb_graph
;
638 num_blocks
= bptr
->num_blocks
;
639 bb_graph
= bptr
->bb_graph
;
641 /* For every block in the file,
642 - if every exit/entrance arc has a known count, then set the block count
643 - if the block count is known, and every exit/entrance arc but one has
644 a known execution count, then set the count of the remaining arc
646 As arc counts are set, decrement the succ/pred count, but don't delete
647 the arc, that way we can easily tell when all arcs are known, or only
648 one arc is unknown. */
650 /* The order that the basic blocks are iterated through is important.
651 Since the code that finds spanning trees starts with block 0, low numbered
652 arcs are put on the spanning tree in preference to high numbered arcs.
653 Hence, most instrumented arcs are at the end. Graph solving works much
654 faster if we propagate numbers from the end to the start.
656 This takes an average of slightly more than 3 passes. */
665 for (i
= num_blocks
- 1; i
>= 0; i
--)
667 if (! bb_graph
[i
].count_valid
)
669 if (bb_graph
[i
].succ_count
== 0)
672 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
673 arcptr
= arcptr
->succ_next
)
674 total
+= arcptr
->arc_count
;
675 bb_graph
[i
].exec_count
= total
;
676 bb_graph
[i
].count_valid
= 1;
679 else if (bb_graph
[i
].pred_count
== 0)
682 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
683 arcptr
= arcptr
->pred_next
)
684 total
+= arcptr
->arc_count
;
685 bb_graph
[i
].exec_count
= total
;
686 bb_graph
[i
].count_valid
= 1;
690 if (bb_graph
[i
].count_valid
)
692 if (bb_graph
[i
].succ_count
== 1)
695 /* One of the counts will be invalid, but it is zero,
696 so adding it in also doesn't hurt. */
697 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
698 arcptr
= arcptr
->succ_next
)
699 total
+= arcptr
->arc_count
;
700 /* Calculate count for remaining arc by conservation. */
701 total
= bb_graph
[i
].exec_count
- total
;
702 /* Search for the invalid arc, and set its count. */
703 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
704 arcptr
= arcptr
->succ_next
)
705 if (! arcptr
->count_valid
)
709 arcptr
->count_valid
= 1;
710 arcptr
->arc_count
= total
;
711 bb_graph
[i
].succ_count
--;
713 bb_graph
[arcptr
->target
].pred_count
--;
716 if (bb_graph
[i
].pred_count
== 1)
719 /* One of the counts will be invalid, but it is zero,
720 so adding it in also doesn't hurt. */
721 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
722 arcptr
= arcptr
->pred_next
)
723 total
+= arcptr
->arc_count
;
724 /* Calculate count for remaining arc by conservation. */
725 total
= bb_graph
[i
].exec_count
- total
;
726 /* Search for the invalid arc, and set its count. */
727 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
728 arcptr
= arcptr
->pred_next
)
729 if (! arcptr
->count_valid
)
733 arcptr
->count_valid
= 1;
734 arcptr
->arc_count
= total
;
735 bb_graph
[i
].pred_count
--;
737 bb_graph
[arcptr
->source
].succ_count
--;
744 /* If the graph has been correctly solved, every block will have a
745 succ and pred count of zero. */
746 for (i
= 0; i
< num_blocks
; i
++)
747 if (bb_graph
[i
].succ_count
|| bb_graph
[i
].pred_count
)
756 struct bb_info_list
*list_end
= 0;
757 struct bb_info_list
*b_ptr
;
760 /* Read and ignore the first word of the .da file, which is the count of
761 how many numbers follow. */
762 if (da_file
&& __read_long (&total
, da_file
, 8))
765 while (! feof (bbg_file
))
767 b_ptr
= (struct bb_info_list
*) xmalloc (sizeof (struct bb_info_list
));
771 list_end
->next
= b_ptr
;
773 bb_graph_list
= b_ptr
;
776 /* Read in the data in the .bbg file and reconstruct the program flow
777 graph for one function. */
778 create_program_flow_graph (b_ptr
);
780 /* Set the EOF condition if at the end of file. */
781 ungetc (getc (bbg_file
), bbg_file
);
784 /* Check to make sure the .da file data is valid. */
789 fnotice (stderr
, ".da file contents exhausted too early\n");
790 /* Should be at end of file now. */
791 if (__read_long (&total
, da_file
, 8) == 0)
792 fnotice (stderr
, ".da file contents not exhausted\n");
795 /* Calculate all of the basic block execution counts and branch
796 taken probabilities. */
798 for (b_ptr
= bb_graph_list
; b_ptr
; b_ptr
= b_ptr
->next
)
799 solve_program_flow_graph (b_ptr
);
801 /* Read in all of the data from the .bb file. This info will be accessed
802 sequentially twice. */
803 stat (bb_file_name
, &buf
);
804 bb_data_size
= buf
.st_size
/ 4;
806 bb_data
= (char *) xmalloc ((unsigned) buf
.st_size
);
807 fread (bb_data
, sizeof (char), buf
.st_size
, bb_file
);
816 /* Scan the data in the .bb file to find all source files referenced,
817 and the largest line number mentioned in each one. */
820 scan_for_source_files ()
822 struct sourcefile
*s_ptr
= NULL
;
827 /* Search the bb_data to find:
828 1) The number of sources files contained herein, and
829 2) The largest line number for each source file. */
833 for (count
= 0; count
< bb_data_size
; count
++)
835 __fetch_long (&line_num
, ptr
, 4);
839 /* A source file name follows. Check to see if we already have
840 a sourcefile structure for this file. */
842 while (s_ptr
&& strcmp (s_ptr
->name
, ptr
))
847 /* No sourcefile structure for this file name exists, create
848 a new one, and append it to the front of the sources list. */
849 s_ptr
= (struct sourcefile
*) xmalloc (sizeof(struct sourcefile
));
850 s_ptr
->name
= xstrdup (ptr
);
851 s_ptr
->maxlineno
= 0;
852 s_ptr
->next
= sources
;
856 /* Scan past the file name. */
861 __fetch_long (&delim
, ptr
, 4);
863 } while (delim
!= line_num
);
866 else if (line_num
== -2)
870 /* A function name follows. Ignore it. */
873 __fetch_long (&delim
, ptr
, 4);
875 } while (delim
!= line_num
);
877 /* There will be a zero before the first file name, in which case s_ptr
878 will still be uninitialized. So, only try to set the maxlineno
879 field if line_num is non-zero. */
880 else if (line_num
> 0)
882 if (s_ptr
->maxlineno
<= line_num
)
883 s_ptr
->maxlineno
= line_num
+ 1;
885 else if (line_num
< 0)
887 /* Don't know what this is, but it's garbage. */
893 /* For calculating coverage at the function level. */
895 static int function_source_lines
;
896 static int function_source_lines_executed
;
897 static int function_branches
;
898 static int function_branches_executed
;
899 static int function_branches_taken
;
900 static int function_calls
;
901 static int function_calls_executed
;
902 static char *function_name
;
904 /* Calculate the branch taken probabilities for all arcs branches at the
905 end of this block. */
908 calculate_branch_probs (current_graph
, block_num
, branch_probs
, last_line_num
)
909 struct bb_info_list
*current_graph
;
911 struct arcdata
**branch_probs
;
915 struct adj_list
*arcptr
;
916 struct arcdata
*end_ptr
, *a_ptr
;
918 total
= current_graph
->bb_graph
[block_num
].exec_count
;
919 for (arcptr
= current_graph
->bb_graph
[block_num
].succ
; arcptr
;
920 arcptr
= arcptr
->succ_next
)
922 /* Ignore fall through arcs as they aren't really branches. */
924 if (arcptr
->fall_through
)
927 a_ptr
= (struct arcdata
*) xmalloc (sizeof (struct arcdata
));
928 a_ptr
->total
= total
;
932 a_ptr
->hits
= arcptr
->arc_count
;
933 a_ptr
->call_insn
= arcptr
->fake
;
935 if (output_function_summary
)
937 if (a_ptr
->call_insn
)
940 if (a_ptr
->total
!= 0)
941 function_calls_executed
++;
946 if (a_ptr
->total
!= 0)
947 function_branches_executed
++;
949 function_branches_taken
++;
953 /* Append the new branch to the end of the list. */
955 if (! branch_probs
[last_line_num
])
956 branch_probs
[last_line_num
] = a_ptr
;
959 end_ptr
= branch_probs
[last_line_num
];
960 while (end_ptr
->next
!= 0)
961 end_ptr
= end_ptr
->next
;
962 end_ptr
->next
= a_ptr
;
967 /* Output summary info for a function. */
972 if (function_source_lines
)
973 fnotice (stdout
, "%6.2f%% of %d source lines executed in function %s\n",
974 (((double) function_source_lines_executed
/ function_source_lines
)
975 * 100), function_source_lines
, function_name
);
977 fnotice (stdout
, "No executable source lines in function %s\n",
980 if (output_branch_probs
)
982 if (function_branches
)
984 fnotice (stdout
, "%6.2f%% of %d branches executed in function %s\n",
985 (((double) function_branches_executed
/ function_branches
)
986 * 100), function_branches
, function_name
);
988 "%6.2f%% of %d branches taken at least once in function %s\n",
989 (((double) function_branches_taken
/ function_branches
)
990 * 100), function_branches
, function_name
);
993 fnotice (stdout
, "No branches in function %s\n", function_name
);
995 fnotice (stdout
, "%6.2f%% of %d calls executed in function %s\n",
996 (((double) function_calls_executed
/ function_calls
)
997 * 100), function_calls
, function_name
);
999 fnotice (stdout
, "No calls in function %s\n", function_name
);
1003 /* Calculate line execution counts, and output the data to a .tcov file. */
1008 /* When scanning data, this is true only if the data applies to the
1009 current source file. */
1011 /* An array indexed by line number which indicates how many times that line
1013 gcov_type
*line_counts
;
1014 /* An array indexed by line number which indicates whether the line was
1015 present in the bb file (i.e. whether it had code associate with it).
1016 Lines never executed are those which both exist, and have zero execution
1019 /* An array indexed by line number, which contains a list of branch
1020 probabilities, one for each branch on that line. */
1021 struct arcdata
**branch_probs
= NULL
;
1022 struct sourcefile
*s_ptr
;
1023 char *source_file_name
;
1025 struct bb_info_list
*current_graph
;
1030 long last_line_num
= 0;
1032 struct arcdata
*a_ptr
;
1033 /* Buffer used for reading in lines from the source file. */
1034 char string
[STRING_SIZE
];
1035 /* For calculating coverage at the file level. */
1036 int total_source_lines
;
1037 int total_source_lines_executed
;
1039 int total_branches_executed
;
1040 int total_branches_taken
;
1042 int total_calls_executed
;
1044 /* Now, for each source file, allocate an array big enough to hold a count
1045 for each line. Scan through the bb_data, and when the file name matches
1046 the current file name, then for each following line number, increment
1047 the line number execution count indicated by the execution count of
1048 the appropriate basic block. */
1050 for (s_ptr
= sources
; s_ptr
; s_ptr
= s_ptr
->next
)
1052 /* If this is a relative file name, and an object directory has been
1053 specified, then make it relative to the object directory name. */
1054 if (! IS_ABSOLUTE_PATHNAME (s_ptr
->name
)
1055 && object_directory
!= 0
1056 && *object_directory
!= '\0')
1058 int objdir_count
= strlen (object_directory
);
1059 source_file_name
= xmalloc (objdir_count
+ strlen (s_ptr
->name
) + 2);
1060 strcpy (source_file_name
, object_directory
);
1061 if (object_directory
[objdir_count
- 1] != '/')
1062 source_file_name
[objdir_count
++] = '/';
1063 strcpy (source_file_name
+ objdir_count
, s_ptr
->name
);
1066 source_file_name
= s_ptr
->name
;
1068 line_counts
= (gcov_type
*) xcalloc (sizeof (gcov_type
), s_ptr
->maxlineno
);
1069 line_exists
= xcalloc (1, s_ptr
->maxlineno
);
1070 if (output_branch_probs
)
1071 branch_probs
= (struct arcdata
**)
1072 xcalloc (sizeof (struct arcdata
*), s_ptr
->maxlineno
);
1074 /* There will be a zero at the beginning of the bb info, before the
1075 first list of line numbers, so must initialize block_num to 0. */
1080 /* Pointer into the bb_data, incremented while scanning the data. */
1081 char *ptr
= bb_data
;
1082 for (count
= 0; count
< bb_data_size
; count
++)
1086 __fetch_long (&line_num
, ptr
, 4);
1090 /* Marks the beginning of a file name. Check to see whether
1091 this is the filename we are currently collecting data for. */
1093 if (strcmp (s_ptr
->name
, ptr
))
1098 /* Scan past the file name. */
1101 __fetch_long (&delim
, ptr
, 4);
1103 } while (delim
!= line_num
);
1105 else if (line_num
== -2)
1107 /* Marks the start of a new function. Advance to the next
1108 program flow graph. */
1110 if (! current_graph
)
1111 current_graph
= bb_graph_list
;
1114 if (block_num
== current_graph
->num_blocks
- 1)
1115 /* Last block falls through to exit. */
1117 else if (block_num
== current_graph
->num_blocks
- 2)
1119 if (output_branch_probs
&& this_file
)
1120 calculate_branch_probs (current_graph
, block_num
,
1121 branch_probs
, last_line_num
);
1126 "didn't use all bb entries of graph, function %s\n",
1128 fnotice (stderr
, "block_num = %ld, num_blocks = %d\n",
1129 block_num
, current_graph
->num_blocks
);
1132 current_graph
= current_graph
->next
;
1135 if (output_function_summary
&& this_file
)
1136 function_summary ();
1139 if (output_function_summary
)
1141 function_source_lines
= 0;
1142 function_source_lines_executed
= 0;
1143 function_branches
= 0;
1144 function_branches_executed
= 0;
1145 function_branches_taken
= 0;
1147 function_calls_executed
= 0;
1150 /* Save the function name for later use. */
1151 function_name
= ptr
;
1153 /* Scan past the file name. */
1156 __fetch_long (&delim
, ptr
, 4);
1158 } while (delim
!= line_num
);
1160 else if (line_num
== 0)
1162 /* Marks the end of a block. */
1164 if (block_num
>= current_graph
->num_blocks
)
1166 fnotice (stderr
, "ERROR: too many basic blocks in .bb file %s\n",
1171 if (output_branch_probs
&& this_file
)
1172 calculate_branch_probs (current_graph
, block_num
,
1173 branch_probs
, last_line_num
);
1179 if (output_function_summary
)
1181 if (line_exists
[line_num
] == 0)
1182 function_source_lines
++;
1183 if (line_counts
[line_num
] == 0
1184 && current_graph
->bb_graph
[block_num
].exec_count
!= 0)
1185 function_source_lines_executed
++;
1188 /* Accumulate execution data for this line number. */
1190 line_counts
[line_num
]
1191 += current_graph
->bb_graph
[block_num
].exec_count
;
1192 line_exists
[line_num
] = 1;
1193 last_line_num
= line_num
;
1198 if (output_function_summary
&& this_file
)
1199 function_summary ();
1201 /* Calculate summary test coverage statistics. */
1203 total_source_lines
= 0;
1204 total_source_lines_executed
= 0;
1206 total_branches_executed
= 0;
1207 total_branches_taken
= 0;
1209 total_calls_executed
= 0;
1211 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1213 if (line_exists
[count
])
1215 total_source_lines
++;
1216 if (line_counts
[count
])
1217 total_source_lines_executed
++;
1219 if (output_branch_probs
)
1221 for (a_ptr
= branch_probs
[count
]; a_ptr
; a_ptr
= a_ptr
->next
)
1223 if (a_ptr
->call_insn
)
1226 if (a_ptr
->total
!= 0)
1227 total_calls_executed
++;
1232 if (a_ptr
->total
!= 0)
1233 total_branches_executed
++;
1234 if (a_ptr
->hits
> 0)
1235 total_branches_taken
++;
1241 if (total_source_lines
)
1243 "%6.2f%% of %d source lines executed in file %s\n",
1244 (((double) total_source_lines_executed
/ total_source_lines
)
1245 * 100), total_source_lines
, source_file_name
);
1247 fnotice (stdout
, "No executable source lines in file %s\n",
1250 if (output_branch_probs
)
1254 fnotice (stdout
, "%6.2f%% of %d branches executed in file %s\n",
1255 (((double) total_branches_executed
/ total_branches
)
1256 * 100), total_branches
, source_file_name
);
1258 "%6.2f%% of %d branches taken at least once in file %s\n",
1259 (((double) total_branches_taken
/ total_branches
)
1260 * 100), total_branches
, source_file_name
);
1263 fnotice (stdout
, "No branches in file %s\n", source_file_name
);
1265 fnotice (stdout
, "%6.2f%% of %d calls executed in file %s\n",
1266 (((double) total_calls_executed
/ total_calls
)
1267 * 100), total_calls
, source_file_name
);
1269 fnotice (stdout
, "No calls in file %s\n", source_file_name
);
1272 if (output_gcov_file
)
1274 /* Now the statistics are ready. Read in the source file one line
1275 at a time, and output that line to the gcov file preceded by
1276 its execution count if non zero. */
1278 source_file
= fopen (source_file_name
, "r");
1279 if (source_file
== NULL
)
1281 fnotice (stderr
, "Could not open source file %s.\n",
1288 count
= strlen (source_file_name
);
1289 cptr
= strrchr (s_ptr
->name
, '/');
1294 if (output_long_names
&& strcmp (cptr
, input_file_name
))
1296 gcov_file_name
= xmalloc (count
+ 7 + strlen (input_file_name
));
1298 cptr
= strrchr (input_file_name
, '/');
1300 strcpy (gcov_file_name
, cptr
+ 1);
1302 strcpy (gcov_file_name
, input_file_name
);
1304 strcat (gcov_file_name
, ".");
1306 cptr
= strrchr (source_file_name
, '/');
1308 strcat (gcov_file_name
, cptr
+ 1);
1310 strcat (gcov_file_name
, source_file_name
);
1314 gcov_file_name
= xmalloc (count
+ 6);
1315 cptr
= strrchr (source_file_name
, '/');
1317 strcpy (gcov_file_name
, cptr
+ 1);
1319 strcpy (gcov_file_name
, source_file_name
);
1322 /* Don't strip off the ending for compatibility with tcov, since
1323 this results in confusion if there is more than one file with
1324 the same basename, e.g. tmp.c and tmp.h. */
1325 strcat (gcov_file_name
, ".gcov");
1327 gcov_file
= fopen (gcov_file_name
, "w");
1329 if (gcov_file
== NULL
)
1331 fnotice (stderr
, "Could not open output file %s.\n",
1333 fclose (source_file
);
1339 fnotice (stdout
, "Creating %s.\n", gcov_file_name
);
1341 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1346 retval
= fgets (string
, STRING_SIZE
, source_file
);
1348 /* For lines which don't exist in the .bb file, print nothing
1349 before the source line. For lines which exist but were never
1350 executed, print ###### before the source line. Otherwise,
1351 print the execution count before the source line. */
1352 /* There are 16 spaces of indentation added before the source
1353 line so that tabs won't be messed up. */
1354 if (line_exists
[count
])
1356 if (line_counts
[count
])
1359 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)line_counts
[count
]);
1360 fprintf (gcov_file
, "%12s %s", c
,
1364 fprintf (gcov_file
, " ###### %s", string
);
1367 fprintf (gcov_file
, "\t\t%s", string
);
1369 /* In case the source file line is larger than our buffer, keep
1370 reading and outputting lines until we get a newline. */
1371 len
= strlen (string
);
1372 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1375 retval
= fgets (string
, STRING_SIZE
, source_file
);
1376 fputs (string
, gcov_file
);
1379 if (output_branch_probs
)
1381 for (i
= 0, a_ptr
= branch_probs
[count
]; a_ptr
;
1382 a_ptr
= a_ptr
->next
, i
++)
1384 if (a_ptr
->call_insn
)
1386 if (a_ptr
->total
== 0)
1387 fnotice (gcov_file
, "call %d never executed\n", i
);
1390 if (output_branch_counts
)
1393 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1394 a_ptr
->total
- a_ptr
->hits
);
1396 "call %d returns = %s\n", i
, c
);
1401 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1402 100 - ((a_ptr
->hits
* 100)
1403 + (a_ptr
->total
>> 1))
1406 "call %d returns = %s%%\n", i
, c
);
1412 if (a_ptr
->total
== 0)
1413 fnotice (gcov_file
, "branch %d never executed\n",
1417 if (output_branch_counts
)
1420 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1423 "branch %d taken = %s\n", i
, c
);
1428 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1429 ((a_ptr
->hits
* 100)
1430 + (a_ptr
->total
>> 1))
1433 "branch %d taken = %s%%\n", i
, c
);
1440 /* Gracefully handle errors while reading the source file. */
1444 "Unexpected EOF while reading source file %s.\n",
1450 /* Handle all remaining source lines. There may be lines
1451 after the last line of code. */
1454 char *retval
= fgets (string
, STRING_SIZE
, source_file
);
1455 while (retval
!= NULL
)
1459 fprintf (gcov_file
, "\t\t%s", string
);
1461 /* In case the source file line is larger than our buffer, keep
1462 reading and outputting lines until we get a newline. */
1463 len
= strlen (string
);
1464 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1467 retval
= fgets (string
, STRING_SIZE
, source_file
);
1468 fputs (string
, gcov_file
);
1471 retval
= fgets (string
, STRING_SIZE
, source_file
);
1475 fclose (source_file
);