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 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. */
53 /* The .bb file format consists of several lists of 4-byte integers
54 which are the line numbers of each basic block in the file. Each
55 list is terminated by a zero. These lists correspond to the basic
56 blocks in the reconstructed program flow graph.
58 A line number of -1 indicates that a source file name (padded to a
59 long boundary) follows. The padded file name is followed by
60 another -1 to make it easy to scan past file names. A -2 indicates
61 that a function name (padded to a long boundary) follows; the name
62 is followed by another -2 to make it easy to scan past the function
65 The .bbg file contains enough info to enable gcov to reconstruct the
66 program flow graph. The first word is the number of basic blocks,
67 the second word is the number of arcs, followed by the list of arcs
68 (source bb, dest bb pairs), then a -1, then the number of instrumented
69 arcs followed by the instrumented arcs, followed by another -1. This
70 is repeated for each function.
72 The .da file contains the execution count for each instrumented branch.
74 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
75 and the .da files are created when an executable compiled with
76 -fprofile-arcs is run. */
78 /* The functions in this file for creating and solution program flow graphs
79 are very similar to functions in the gcc source file profile.c. */
81 char gcov_version_string
[] = "GNU gcov version 1.5\n";
83 /* This is the size of the buffer used to read in source file lines. */
85 #define STRING_SIZE 200
87 /* One copy of this structure is created for each source file mentioned in the
94 struct sourcefile
*next
;
97 /* This points to the head of the sourcefile structure list. */
99 struct sourcefile
*sources
;
101 /* One of these is dynamically created whenever we identify an arc in the
108 unsigned int count_valid
: 1;
109 unsigned int on_tree
: 1;
110 unsigned int fake
: 1;
111 unsigned int fall_through
: 1;
113 /* Not needed for gcov, but defined in profile.c. */
116 struct adj_list
*pred_next
;
117 struct adj_list
*succ_next
;
120 /* Count the number of basic blocks, and create an array of these structures,
121 one for each bb in the function. */
124 struct adj_list
*succ
;
125 struct adj_list
*pred
;
129 unsigned int count_valid
: 1;
130 unsigned int on_tree
: 1;
132 /* Not needed for gcov, but defined in profile.c. */
137 /* When outputting branch probabilities, one of these structures is created
138 for each branch/call. */
145 struct arcdata
*next
;
148 /* Used to save the list of bb_graphs, one per function. */
150 struct bb_info_list
{
151 /* Indexed by block number, holds the basic block graph for one function. */
152 struct bb_info
*bb_graph
;
154 struct bb_info_list
*next
;
157 /* Holds a list of function basic block graphs. */
159 static struct bb_info_list
*bb_graph_list
= 0;
161 /* Name and file pointer of the input file for the basic block graph. */
163 static char *bbg_file_name
;
164 static FILE *bbg_file
;
166 /* Name and file pointer of the input file for the arc count data. */
168 static char *da_file_name
;
169 static FILE *da_file
;
171 /* Name and file pointer of the input file for the basic block line counts. */
173 static char *bb_file_name
;
174 static FILE *bb_file
;
176 /* Holds the entire contents of the bb_file read into memory. */
178 static char *bb_data
;
180 /* Size of bb_data array in longs. */
182 static long bb_data_size
;
184 /* Name and file pointer of the output file. */
186 static char *gcov_file_name
;
187 static FILE *gcov_file
;
189 /* Name of the file mentioned on the command line. */
191 static char *input_file_name
= 0;
193 /* Output branch probabilities if true. */
195 static int output_branch_probs
= 0;
197 /* Output a gcov file if this is true. This is on by default, and can
198 be turned off by the -n option. */
200 static int output_gcov_file
= 1;
202 /* For included files, make the gcov output file name include the name of
203 the input source file. For example, if x.h is included in a.c, then the
204 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
205 when a single source file is specified. */
207 static int output_long_names
= 0;
209 /* Output summary info for each function. */
211 static int output_function_summary
= 0;
213 /* Object directory file prefix. This is the directory where .bb and .bbg
214 files are looked for, if non-zero. */
216 static char *object_directory
= 0;
218 /* Output the number of times a branch was taken as opposed to the percentage
219 of times it was taken. Turned on by the -c option */
221 static int output_branch_counts
= 0;
223 /* Forward declarations. */
224 static void process_args
PARAMS ((int, char **));
225 static void open_files
PARAMS ((void));
226 static void read_files
PARAMS ((void));
227 static void scan_for_source_files
PARAMS ((void));
228 static void output_data
PARAMS ((void));
229 static void print_usage
PARAMS ((void)) ATTRIBUTE_NORETURN
;
230 static void init_arc
PARAMS ((struct adj_list
*, int, int, struct bb_info
*));
231 static struct adj_list
*reverse_arcs
PARAMS ((struct adj_list
*));
232 static void create_program_flow_graph
PARAMS ((struct bb_info_list
*));
233 static void solve_program_flow_graph
PARAMS ((struct bb_info_list
*));
234 static void calculate_branch_probs
PARAMS ((struct bb_info_list
*, int,
235 struct arcdata
**, int));
236 static void function_summary
PARAMS ((void));
238 extern int main
PARAMS ((int, char **));
245 /* LC_CTYPE determines the character set used by the terminal so it has be set
246 to output messages correctly. */
248 #ifdef HAVE_LC_MESSAGES
249 setlocale (LC_CTYPE
, "");
250 setlocale (LC_MESSAGES
, "");
252 setlocale (LC_ALL
, "");
255 (void) bindtextdomain (PACKAGE
, localedir
);
256 (void) textdomain (PACKAGE
);
258 process_args (argc
, argv
);
264 scan_for_source_files ();
271 static void fnotice
PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2
;
273 fnotice
VPARAMS ((FILE *file
, const char *msgid
, ...))
275 #ifndef ANSI_PROTOTYPES
281 VA_START (ap
, msgid
);
283 #ifndef ANSI_PROTOTYPES
284 file
= va_arg (ap
, FILE *);
285 msgid
= va_arg (ap
, const char *);
288 vfprintf (file
, _(msgid
), ap
);
292 /* More 'friendly' abort that prints the line and file.
293 config.h can #define abort fancy_abort if you like that sort of thing. */
294 extern void fancy_abort
PARAMS ((void)) ATTRIBUTE_NORETURN
;
299 fnotice (stderr
, "Internal gcov abort.\n");
300 exit (FATAL_EXIT_CODE
);
303 /* Print a usage message and exit. */
308 fnotice (stderr
, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
309 exit (FATAL_EXIT_CODE
);
312 /* Parse the command line. */
315 process_args (argc
, argv
)
321 for (i
= 1; i
< argc
; i
++)
323 if (argv
[i
][0] == '-')
325 if (argv
[i
][1] == 'b')
326 output_branch_probs
= 1;
327 else if (argv
[i
][1] == 'c')
328 output_branch_counts
= 1;
329 else if (argv
[i
][1] == 'v')
330 fputs (gcov_version_string
, stderr
);
331 else if (argv
[i
][1] == 'n')
332 output_gcov_file
= 0;
333 else if (argv
[i
][1] == 'l')
334 output_long_names
= 1;
335 else if (argv
[i
][1] == 'f')
336 output_function_summary
= 1;
337 else if (argv
[i
][1] == 'o' && argv
[i
][2] == '\0')
338 object_directory
= argv
[++i
];
342 else if (! input_file_name
)
343 input_file_name
= argv
[i
];
348 if (! input_file_name
)
353 /* Find and open the .bb, .da, and .bbg files. */
358 int count
, objdir_count
;
361 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
362 extension, if any, and append the new extensions. */
363 count
= strlen (input_file_name
);
364 if (object_directory
)
365 objdir_count
= strlen (object_directory
);
369 da_file_name
= xmalloc (count
+ objdir_count
+ 4);
370 bb_file_name
= xmalloc (count
+ objdir_count
+ 4);
371 bbg_file_name
= xmalloc (count
+ objdir_count
+ 5);
373 if (object_directory
)
375 strcpy (da_file_name
, object_directory
);
376 strcpy (bb_file_name
, object_directory
);
377 strcpy (bbg_file_name
, object_directory
);
379 if (object_directory
[objdir_count
- 1] != '/')
381 strcat (da_file_name
, "/");
382 strcat (bb_file_name
, "/");
383 strcat (bbg_file_name
, "/");
386 cptr
= strrchr (input_file_name
, '/');
389 strcat (da_file_name
, cptr
+ 1);
390 strcat (bb_file_name
, cptr
+ 1);
391 strcat (bbg_file_name
, cptr
+ 1);
395 strcat (da_file_name
, input_file_name
);
396 strcat (bb_file_name
, input_file_name
);
397 strcat (bbg_file_name
, input_file_name
);
402 strcpy (da_file_name
, input_file_name
);
403 strcpy (bb_file_name
, input_file_name
);
404 strcpy (bbg_file_name
, input_file_name
);
407 cptr
= strrchr (bb_file_name
, '.');
409 strcpy (cptr
, ".bb");
411 strcat (bb_file_name
, ".bb");
413 cptr
= strrchr (da_file_name
, '.');
415 strcpy (cptr
, ".da");
417 strcat (da_file_name
, ".da");
419 cptr
= strrchr (bbg_file_name
, '.');
421 strcpy (cptr
, ".bbg");
423 strcat (bbg_file_name
, ".bbg");
425 bb_file
= fopen (bb_file_name
, "rb");
428 fnotice (stderr
, "Could not open basic block file %s.\n", bb_file_name
);
429 exit (FATAL_EXIT_CODE
);
432 /* If none of the functions in the file were executed, then there won't
433 be a .da file. Just assume that all counts are zero in this case. */
434 da_file
= fopen (da_file_name
, "rb");
437 fnotice (stderr
, "Could not open data file %s.\n", da_file_name
);
438 fnotice (stderr
, "Assuming that all execution counts are zero.\n");
441 bbg_file
= fopen (bbg_file_name
, "rb");
442 if (bbg_file
== NULL
)
444 fnotice (stderr
, "Could not open program flow graph file %s.\n",
446 exit (FATAL_EXIT_CODE
);
449 /* Check for empty .bbg file. This indicates that there is no executable
450 code in this source file. */
451 /* Set the EOF condition if at the end of file. */
452 ungetc (getc (bbg_file
), bbg_file
);
455 fnotice (stderr
, "No executable code associated with file %s.\n",
457 exit (FATAL_EXIT_CODE
);
461 /* Initialize a new arc. */
464 init_arc (arcptr
, source
, target
, bb_graph
)
465 struct adj_list
*arcptr
;
467 struct bb_info
*bb_graph
;
469 arcptr
->target
= target
;
470 arcptr
->source
= source
;
472 arcptr
->arc_count
= 0;
473 arcptr
->count_valid
= 0;
476 arcptr
->fall_through
= 0;
478 arcptr
->succ_next
= bb_graph
[source
].succ
;
479 bb_graph
[source
].succ
= arcptr
;
480 bb_graph
[source
].succ_count
++;
482 arcptr
->pred_next
= bb_graph
[target
].pred
;
483 bb_graph
[target
].pred
= arcptr
;
484 bb_graph
[target
].pred_count
++;
488 /* Reverse the arcs on a arc list. */
490 static struct adj_list
*
491 reverse_arcs (arcptr
)
492 struct adj_list
*arcptr
;
494 struct adj_list
*prev
= 0;
495 struct adj_list
*next
;
497 for ( ; arcptr
; arcptr
= next
)
499 next
= arcptr
->succ_next
;
500 arcptr
->succ_next
= prev
;
508 /* Construct the program flow graph from the .bbg file, and read in the data
512 create_program_flow_graph (bptr
)
513 struct bb_info_list
*bptr
;
515 long num_blocks
, number_arcs
, src
, dest
, flag_bits
, num_arcs_per_block
;
517 struct adj_list
*arcptr
;
518 struct bb_info
*bb_graph
;
520 /* Read the number of blocks. */
521 __read_long (&num_blocks
, bbg_file
, 4);
523 /* Create an array of size bb number of bb_info structs. */
524 bb_graph
= (struct bb_info
*) xcalloc (num_blocks
, sizeof (struct bb_info
));
526 bptr
->bb_graph
= bb_graph
;
527 bptr
->num_blocks
= num_blocks
;
529 /* Read and create each arc from the .bbg file. */
530 __read_long (&number_arcs
, bbg_file
, 4);
531 for (i
= 0; i
< num_blocks
; i
++)
535 __read_long (&num_arcs_per_block
, bbg_file
, 4);
536 for (j
= 0; j
< num_arcs_per_block
; j
++)
538 if (number_arcs
-- < 0)
542 __read_long (&dest
, bbg_file
, 4);
544 arcptr
= (struct adj_list
*) xmalloc (sizeof (struct adj_list
));
545 init_arc (arcptr
, src
, dest
, bb_graph
);
547 __read_long (&flag_bits
, bbg_file
, 4);
548 arcptr
->on_tree
= flag_bits
& 0x1;
549 arcptr
->fake
= !! (flag_bits
& 0x2);
550 arcptr
->fall_through
= !! (flag_bits
& 0x4);
557 /* Read and ignore the -1 separating the arc list from the arc list of the
559 __read_long (&src
, bbg_file
, 4);
563 /* Must reverse the order of all succ arcs, to ensure that they match
564 the order of the data in the .da file. */
566 for (i
= 0; i
< num_blocks
; i
++)
567 if (bb_graph
[i
].succ
)
568 bb_graph
[i
].succ
= reverse_arcs (bb_graph
[i
].succ
);
570 /* For each arc not on the spanning tree, set its execution count from
573 /* The first count in the .da file is the number of times that the function
574 was entered. This is the exec_count for block zero. */
576 /* This duplicates code in branch_prob in profile.c. */
578 for (i
= 0; i
< num_blocks
; i
++)
579 for (arcptr
= bb_graph
[i
].succ
; arcptr
; arcptr
= arcptr
->succ_next
)
580 if (! arcptr
->on_tree
)
583 if (da_file
&& __read_long (&tmp_count
, da_file
, 8))
586 arcptr
->arc_count
= tmp_count
;
587 arcptr
->count_valid
= 1;
588 bb_graph
[i
].succ_count
--;
589 bb_graph
[arcptr
->target
].pred_count
--;
594 solve_program_flow_graph (bptr
)
595 struct bb_info_list
*bptr
;
597 int passes
, changes
, total
;
599 struct adj_list
*arcptr
;
600 struct bb_info
*bb_graph
;
603 num_blocks
= bptr
->num_blocks
;
604 bb_graph
= bptr
->bb_graph
;
606 /* For every block in the file,
607 - if every exit/entrance arc has a known count, then set the block count
608 - if the block count is known, and every exit/entrance arc but one has
609 a known execution count, then set the count of the remaining arc
611 As arc counts are set, decrement the succ/pred count, but don't delete
612 the arc, that way we can easily tell when all arcs are known, or only
613 one arc is unknown. */
615 /* The order that the basic blocks are iterated through is important.
616 Since the code that finds spanning trees starts with block 0, low numbered
617 arcs are put on the spanning tree in preference to high numbered arcs.
618 Hence, most instrumented arcs are at the end. Graph solving works much
619 faster if we propagate numbers from the end to the start.
621 This takes an average of slightly more than 3 passes. */
630 for (i
= num_blocks
- 1; i
>= 0; i
--)
632 if (! bb_graph
[i
].count_valid
)
634 if (bb_graph
[i
].succ_count
== 0)
637 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
638 arcptr
= arcptr
->succ_next
)
639 total
+= arcptr
->arc_count
;
640 bb_graph
[i
].exec_count
= total
;
641 bb_graph
[i
].count_valid
= 1;
644 else if (bb_graph
[i
].pred_count
== 0)
647 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
648 arcptr
= arcptr
->pred_next
)
649 total
+= arcptr
->arc_count
;
650 bb_graph
[i
].exec_count
= total
;
651 bb_graph
[i
].count_valid
= 1;
655 if (bb_graph
[i
].count_valid
)
657 if (bb_graph
[i
].succ_count
== 1)
660 /* One of the counts will be invalid, but it is zero,
661 so adding it in also doesn't hurt. */
662 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
663 arcptr
= arcptr
->succ_next
)
664 total
+= arcptr
->arc_count
;
665 /* Calculate count for remaining arc by conservation. */
666 total
= bb_graph
[i
].exec_count
- total
;
667 /* Search for the invalid arc, and set its count. */
668 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
669 arcptr
= arcptr
->succ_next
)
670 if (! arcptr
->count_valid
)
674 arcptr
->count_valid
= 1;
675 arcptr
->arc_count
= total
;
676 bb_graph
[i
].succ_count
--;
678 bb_graph
[arcptr
->target
].pred_count
--;
681 if (bb_graph
[i
].pred_count
== 1)
684 /* One of the counts will be invalid, but it is zero,
685 so adding it in also doesn't hurt. */
686 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
687 arcptr
= arcptr
->pred_next
)
688 total
+= arcptr
->arc_count
;
689 /* Calculate count for remaining arc by conservation. */
690 total
= bb_graph
[i
].exec_count
- total
;
691 /* Search for the invalid arc, and set its count. */
692 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
693 arcptr
= arcptr
->pred_next
)
694 if (! arcptr
->count_valid
)
698 arcptr
->count_valid
= 1;
699 arcptr
->arc_count
= total
;
700 bb_graph
[i
].pred_count
--;
702 bb_graph
[arcptr
->source
].succ_count
--;
709 /* If the graph has been correctly solved, every block will have a
710 succ and pred count of zero. */
711 for (i
= 0; i
< num_blocks
; i
++)
712 if (bb_graph
[i
].succ_count
|| bb_graph
[i
].pred_count
)
721 struct bb_info_list
*list_end
= 0;
722 struct bb_info_list
*b_ptr
;
725 /* Read and ignore the first word of the .da file, which is the count of
726 how many numbers follow. */
727 if (da_file
&& __read_long (&total
, da_file
, 8))
730 while (! feof (bbg_file
))
732 b_ptr
= (struct bb_info_list
*) xmalloc (sizeof (struct bb_info_list
));
736 list_end
->next
= b_ptr
;
738 bb_graph_list
= b_ptr
;
741 /* Read in the data in the .bbg file and reconstruct the program flow
742 graph for one function. */
743 create_program_flow_graph (b_ptr
);
745 /* Set the EOF condition if at the end of file. */
746 ungetc (getc (bbg_file
), bbg_file
);
749 /* Check to make sure the .da file data is valid. */
754 fnotice (stderr
, ".da file contents exhausted too early\n");
755 /* Should be at end of file now. */
756 if (__read_long (&total
, da_file
, 8) == 0)
757 fnotice (stderr
, ".da file contents not exhausted\n");
760 /* Calculate all of the basic block execution counts and branch
761 taken probabilities. */
763 for (b_ptr
= bb_graph_list
; b_ptr
; b_ptr
= b_ptr
->next
)
764 solve_program_flow_graph (b_ptr
);
766 /* Read in all of the data from the .bb file. This info will be accessed
767 sequentially twice. */
768 stat (bb_file_name
, &buf
);
769 bb_data_size
= buf
.st_size
/ 4;
771 bb_data
= (char *) xmalloc ((unsigned) buf
.st_size
);
772 fread (bb_data
, sizeof (char), buf
.st_size
, bb_file
);
781 /* Scan the data in the .bb file to find all source files referenced,
782 and the largest line number mentioned in each one. */
785 scan_for_source_files ()
787 struct sourcefile
*s_ptr
= NULL
;
792 /* Search the bb_data to find:
793 1) The number of sources files contained herein, and
794 2) The largest line number for each source file. */
798 for (count
= 0; count
< bb_data_size
; count
++)
800 __fetch_long (&line_num
, ptr
, 4);
804 /* A source file name follows. Check to see if we already have
805 a sourcefile structure for this file. */
807 while (s_ptr
&& strcmp (s_ptr
->name
, ptr
))
812 /* No sourcefile structure for this file name exists, create
813 a new one, and append it to the front of the sources list. */
814 s_ptr
= (struct sourcefile
*) xmalloc (sizeof(struct sourcefile
));
815 s_ptr
->name
= xstrdup (ptr
);
816 s_ptr
->maxlineno
= 0;
817 s_ptr
->next
= sources
;
821 /* Scan past the file name. */
826 __fetch_long (&delim
, ptr
, 4);
828 } while (delim
!= line_num
);
831 else if (line_num
== -2)
835 /* A function name follows. Ignore it. */
838 __fetch_long (&delim
, ptr
, 4);
840 } while (delim
!= line_num
);
842 /* There will be a zero before the first file name, in which case s_ptr
843 will still be uninitialized. So, only try to set the maxlineno
844 field if line_num is non-zero. */
845 else if (line_num
> 0)
847 if (s_ptr
->maxlineno
<= line_num
)
848 s_ptr
->maxlineno
= line_num
+ 1;
850 else if (line_num
< 0)
852 /* Don't know what this is, but it's garbage. */
858 /* For calculating coverage at the function level. */
860 static int function_source_lines
;
861 static int function_source_lines_executed
;
862 static int function_branches
;
863 static int function_branches_executed
;
864 static int function_branches_taken
;
865 static int function_calls
;
866 static int function_calls_executed
;
867 static char *function_name
;
869 /* Calculate the branch taken probabilities for all arcs branches at the
870 end of this block. */
873 calculate_branch_probs (current_graph
, block_num
, branch_probs
, last_line_num
)
874 struct bb_info_list
*current_graph
;
876 struct arcdata
**branch_probs
;
880 struct adj_list
*arcptr
;
881 struct arcdata
*end_ptr
, *a_ptr
;
883 total
= current_graph
->bb_graph
[block_num
].exec_count
;
884 for (arcptr
= current_graph
->bb_graph
[block_num
].succ
; arcptr
;
885 arcptr
= arcptr
->succ_next
)
887 /* Ignore fall through arcs as they aren't really branches. */
889 if (arcptr
->fall_through
)
892 a_ptr
= (struct arcdata
*) xmalloc (sizeof (struct arcdata
));
893 a_ptr
->total
= total
;
897 a_ptr
->hits
= arcptr
->arc_count
;
898 a_ptr
->call_insn
= arcptr
->fake
;
900 if (output_function_summary
)
902 if (a_ptr
->call_insn
)
905 if (a_ptr
->total
!= 0)
906 function_calls_executed
++;
911 if (a_ptr
->total
!= 0)
912 function_branches_executed
++;
914 function_branches_taken
++;
918 /* Append the new branch to the end of the list. */
920 if (! branch_probs
[last_line_num
])
921 branch_probs
[last_line_num
] = a_ptr
;
924 end_ptr
= branch_probs
[last_line_num
];
925 while (end_ptr
->next
!= 0)
926 end_ptr
= end_ptr
->next
;
927 end_ptr
->next
= a_ptr
;
932 /* Output summary info for a function. */
937 if (function_source_lines
)
938 fnotice (stdout
, "%6.2f%% of %d source lines executed in function %s\n",
939 (((double) function_source_lines_executed
/ function_source_lines
)
940 * 100), function_source_lines
, function_name
);
942 fnotice (stdout
, "No executable source lines in function %s\n",
945 if (output_branch_probs
)
947 if (function_branches
)
949 fnotice (stdout
, "%6.2f%% of %d branches executed in function %s\n",
950 (((double) function_branches_executed
/ function_branches
)
951 * 100), function_branches
, function_name
);
953 "%6.2f%% of %d branches taken at least once in function %s\n",
954 (((double) function_branches_taken
/ function_branches
)
955 * 100), function_branches
, function_name
);
958 fnotice (stdout
, "No branches in function %s\n", function_name
);
960 fnotice (stdout
, "%6.2f%% of %d calls executed in function %s\n",
961 (((double) function_calls_executed
/ function_calls
)
962 * 100), function_calls
, function_name
);
964 fnotice (stdout
, "No calls in function %s\n", function_name
);
968 /* Calculate line execution counts, and output the data to a .tcov file. */
973 /* When scanning data, this is true only if the data applies to the
974 current source file. */
976 /* An array indexed by line number which indicates how many times that line
979 /* An array indexed by line number which indicates whether the line was
980 present in the bb file (i.e. whether it had code associate with it).
981 Lines never executed are those which both exist, and have zero execution
984 /* An array indexed by line number, which contains a list of branch
985 probabilities, one for each branch on that line. */
986 struct arcdata
**branch_probs
= NULL
;
987 struct sourcefile
*s_ptr
;
988 char *source_file_name
;
990 struct bb_info_list
*current_graph
;
995 long last_line_num
= 0;
997 struct arcdata
*a_ptr
;
998 /* Buffer used for reading in lines from the source file. */
999 char string
[STRING_SIZE
];
1000 /* For calculating coverage at the file level. */
1001 int total_source_lines
;
1002 int total_source_lines_executed
;
1004 int total_branches_executed
;
1005 int total_branches_taken
;
1007 int total_calls_executed
;
1009 /* Now, for each source file, allocate an array big enough to hold a count
1010 for each line. Scan through the bb_data, and when the file name matches
1011 the current file name, then for each following line number, increment
1012 the line number execution count indicated by the execution count of
1013 the appropriate basic block. */
1015 for (s_ptr
= sources
; s_ptr
; s_ptr
= s_ptr
->next
)
1017 /* If this is a relative file name, and an object directory has been
1018 specified, then make it relative to the object directory name. */
1019 if (! (*s_ptr
->name
== '/' || *s_ptr
->name
== DIR_SEPARATOR
1020 /* Check for disk name on MS-DOS-based systems. */
1021 || (DIR_SEPARATOR
== '\\'
1022 && s_ptr
->name
[1] == ':'
1023 && (s_ptr
->name
[2] == DIR_SEPARATOR
1024 || s_ptr
->name
[2] == '/')))
1025 && object_directory
!= 0
1026 && *object_directory
!= '\0')
1028 int objdir_count
= strlen (object_directory
);
1029 source_file_name
= xmalloc (objdir_count
+ strlen (s_ptr
->name
) + 2);
1030 strcpy (source_file_name
, object_directory
);
1031 if (object_directory
[objdir_count
- 1] != '/')
1032 source_file_name
[objdir_count
++] = '/';
1033 strcpy (source_file_name
+ objdir_count
, s_ptr
->name
);
1036 source_file_name
= s_ptr
->name
;
1038 line_counts
= (long *) xcalloc (sizeof (long), s_ptr
->maxlineno
);
1039 line_exists
= xcalloc (1, s_ptr
->maxlineno
);
1040 if (output_branch_probs
)
1041 branch_probs
= (struct arcdata
**)
1042 xcalloc (sizeof (struct arcdata
*), s_ptr
->maxlineno
);
1044 /* There will be a zero at the beginning of the bb info, before the
1045 first list of line numbers, so must initialize block_num to 0. */
1050 /* Pointer into the bb_data, incremented while scanning the data. */
1051 char *ptr
= bb_data
;
1052 for (count
= 0; count
< bb_data_size
; count
++)
1056 __fetch_long (&line_num
, ptr
, 4);
1060 /* Marks the beginning of a file name. Check to see whether
1061 this is the filename we are currently collecting data for. */
1063 if (strcmp (s_ptr
->name
, ptr
))
1068 /* Scan past the file name. */
1071 __fetch_long (&delim
, ptr
, 4);
1073 } while (delim
!= line_num
);
1075 else if (line_num
== -2)
1077 /* Marks the start of a new function. Advance to the next
1078 program flow graph. */
1080 if (! current_graph
)
1081 current_graph
= bb_graph_list
;
1084 if (block_num
== current_graph
->num_blocks
- 1)
1085 /* Last block falls through to exit. */
1087 else if (block_num
== current_graph
->num_blocks
- 2)
1089 if (output_branch_probs
&& this_file
)
1090 calculate_branch_probs (current_graph
, block_num
,
1091 branch_probs
, last_line_num
);
1096 "didn't use all bb entries of graph, function %s\n",
1098 fnotice (stderr
, "block_num = %ld, num_blocks = %d\n",
1099 block_num
, current_graph
->num_blocks
);
1102 current_graph
= current_graph
->next
;
1105 if (output_function_summary
&& this_file
)
1106 function_summary ();
1109 if (output_function_summary
)
1111 function_source_lines
= 0;
1112 function_source_lines_executed
= 0;
1113 function_branches
= 0;
1114 function_branches_executed
= 0;
1115 function_branches_taken
= 0;
1117 function_calls_executed
= 0;
1120 /* Save the function name for later use. */
1121 function_name
= ptr
;
1123 /* Scan past the file name. */
1126 __fetch_long (&delim
, ptr
, 4);
1128 } while (delim
!= line_num
);
1130 else if (line_num
== 0)
1132 /* Marks the end of a block. */
1134 if (block_num
>= current_graph
->num_blocks
)
1136 fnotice (stderr
, "ERROR: too many basic blocks in .bb file %s\n",
1141 if (output_branch_probs
&& this_file
)
1142 calculate_branch_probs (current_graph
, block_num
,
1143 branch_probs
, last_line_num
);
1149 if (output_function_summary
)
1151 if (line_exists
[line_num
] == 0)
1152 function_source_lines
++;
1153 if (line_counts
[line_num
] == 0
1154 && current_graph
->bb_graph
[block_num
].exec_count
!= 0)
1155 function_source_lines_executed
++;
1158 /* Accumulate execution data for this line number. */
1160 line_counts
[line_num
]
1161 += current_graph
->bb_graph
[block_num
].exec_count
;
1162 line_exists
[line_num
] = 1;
1163 last_line_num
= line_num
;
1168 if (output_function_summary
&& this_file
)
1169 function_summary ();
1171 /* Calculate summary test coverage statistics. */
1173 total_source_lines
= 0;
1174 total_source_lines_executed
= 0;
1176 total_branches_executed
= 0;
1177 total_branches_taken
= 0;
1179 total_calls_executed
= 0;
1181 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1183 if (line_exists
[count
])
1185 total_source_lines
++;
1186 if (line_counts
[count
])
1187 total_source_lines_executed
++;
1189 if (output_branch_probs
)
1191 for (a_ptr
= branch_probs
[count
]; a_ptr
; a_ptr
= a_ptr
->next
)
1193 if (a_ptr
->call_insn
)
1196 if (a_ptr
->total
!= 0)
1197 total_calls_executed
++;
1202 if (a_ptr
->total
!= 0)
1203 total_branches_executed
++;
1204 if (a_ptr
->hits
> 0)
1205 total_branches_taken
++;
1211 if (total_source_lines
)
1213 "%6.2f%% of %d source lines executed in file %s\n",
1214 (((double) total_source_lines_executed
/ total_source_lines
)
1215 * 100), total_source_lines
, source_file_name
);
1217 fnotice (stdout
, "No executable source lines in file %s\n",
1220 if (output_branch_probs
)
1224 fnotice (stdout
, "%6.2f%% of %d branches executed in file %s\n",
1225 (((double) total_branches_executed
/ total_branches
)
1226 * 100), total_branches
, source_file_name
);
1228 "%6.2f%% of %d branches taken at least once in file %s\n",
1229 (((double) total_branches_taken
/ total_branches
)
1230 * 100), total_branches
, source_file_name
);
1233 fnotice (stdout
, "No branches in file %s\n", source_file_name
);
1235 fnotice (stdout
, "%6.2f%% of %d calls executed in file %s\n",
1236 (((double) total_calls_executed
/ total_calls
)
1237 * 100), total_calls
, source_file_name
);
1239 fnotice (stdout
, "No calls in file %s\n", source_file_name
);
1242 if (output_gcov_file
)
1244 /* Now the statistics are ready. Read in the source file one line
1245 at a time, and output that line to the gcov file preceded by
1246 its execution count if non zero. */
1248 source_file
= fopen (source_file_name
, "r");
1249 if (source_file
== NULL
)
1251 fnotice (stderr
, "Could not open source file %s.\n",
1258 count
= strlen (source_file_name
);
1259 cptr
= strrchr (s_ptr
->name
, '/');
1264 if (output_long_names
&& strcmp (cptr
, input_file_name
))
1266 gcov_file_name
= xmalloc (count
+ 7 + strlen (input_file_name
));
1268 cptr
= strrchr (input_file_name
, '/');
1270 strcpy (gcov_file_name
, cptr
+ 1);
1272 strcpy (gcov_file_name
, input_file_name
);
1274 strcat (gcov_file_name
, ".");
1276 cptr
= strrchr (source_file_name
, '/');
1278 strcat (gcov_file_name
, cptr
+ 1);
1280 strcat (gcov_file_name
, source_file_name
);
1284 gcov_file_name
= xmalloc (count
+ 6);
1285 cptr
= strrchr (source_file_name
, '/');
1287 strcpy (gcov_file_name
, cptr
+ 1);
1289 strcpy (gcov_file_name
, source_file_name
);
1292 /* Don't strip off the ending for compatibility with tcov, since
1293 this results in confusion if there is more than one file with
1294 the same basename, e.g. tmp.c and tmp.h. */
1295 strcat (gcov_file_name
, ".gcov");
1297 gcov_file
= fopen (gcov_file_name
, "w");
1299 if (gcov_file
== NULL
)
1301 fnotice (stderr
, "Could not open output file %s.\n",
1303 fclose (source_file
);
1309 fnotice (stdout
, "Creating %s.\n", gcov_file_name
);
1311 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1316 retval
= fgets (string
, STRING_SIZE
, source_file
);
1318 /* For lines which don't exist in the .bb file, print nothing
1319 before the source line. For lines which exist but were never
1320 executed, print ###### before the source line. Otherwise,
1321 print the execution count before the source line. */
1322 /* There are 16 spaces of indentation added before the source
1323 line so that tabs won't be messed up. */
1324 if (line_exists
[count
])
1326 if (line_counts
[count
])
1327 fprintf (gcov_file
, "%12ld %s", line_counts
[count
],
1330 fprintf (gcov_file
, " ###### %s", string
);
1333 fprintf (gcov_file
, "\t\t%s", string
);
1335 /* In case the source file line is larger than our buffer, keep
1336 reading and outputting lines until we get a newline. */
1337 len
= strlen (string
);
1338 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1341 retval
= fgets (string
, STRING_SIZE
, source_file
);
1342 fputs (string
, gcov_file
);
1345 if (output_branch_probs
)
1347 for (i
= 0, a_ptr
= branch_probs
[count
]; a_ptr
;
1348 a_ptr
= a_ptr
->next
, i
++)
1350 if (a_ptr
->call_insn
)
1352 if (a_ptr
->total
== 0)
1353 fnotice (gcov_file
, "call %d never executed\n", i
);
1356 if (output_branch_counts
)
1358 "call %d returns = %d\n",
1359 i
, a_ptr
->total
- a_ptr
->hits
);
1362 "call %d returns = %d%%\n",
1363 i
, 100 - ((a_ptr
->hits
* 100) +
1364 (a_ptr
->total
>> 1))/a_ptr
->total
);
1369 if (a_ptr
->total
== 0)
1370 fnotice (gcov_file
, "branch %d never executed\n",
1374 if (output_branch_counts
)
1376 "branch %d taken = %d\n",
1380 "branch %d taken = %d%%\n", i
,
1381 ((a_ptr
->hits
* 100) +
1382 (a_ptr
->total
>> 1))/
1390 /* Gracefully handle errors while reading the source file. */
1394 "Unexpected EOF while reading source file %s.\n",
1400 /* Handle all remaining source lines. There may be lines
1401 after the last line of code. */
1404 char *retval
= fgets (string
, STRING_SIZE
, source_file
);
1405 while (retval
!= NULL
)
1409 fprintf (gcov_file
, "\t\t%s", string
);
1411 /* In case the source file line is larger than our buffer, keep
1412 reading and outputting lines until we get a newline. */
1413 len
= strlen (string
);
1414 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1417 retval
= fgets (string
, STRING_SIZE
, source_file
);
1418 fputs (string
, gcov_file
);
1421 retval
= fgets (string
, STRING_SIZE
, source_file
);
1425 fclose (source_file
);