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 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. */
51 typedef HOST_WIDEST_INT gcov_type
;
54 /* The .bb file format consists of several lists of 4-byte integers
55 which are the line numbers of each basic block in the file. Each
56 list is terminated by a zero. These lists correspond to the basic
57 blocks in the reconstructed program flow graph.
59 A line number of -1 indicates that a source file name (padded to a
60 long boundary) follows. The padded file name is followed by
61 another -1 to make it easy to scan past file names. A -2 indicates
62 that a function name (padded to a long boundary) follows; the name
63 is followed by another -2 to make it easy to scan past the function
66 The .bbg file contains enough info to enable gcov to reconstruct the
67 program flow graph. The first word is the number of basic blocks,
68 the second word is the number of arcs, followed by the list of arcs
69 (source bb, dest bb pairs), then a -1, then the number of instrumented
70 arcs followed by the instrumented arcs, followed by another -1. This
71 is repeated for each function.
73 The .da file contains the execution count for each instrumented branch.
75 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
76 and the .da files are created when an executable compiled with
77 -fprofile-arcs is run. */
79 /* The functions in this file for creating and solution program flow graphs
80 are very similar to functions in the gcc source file profile.c. */
82 static const char gcov_version_string
[] = "GNU gcov version 1.5\n";
84 /* This is the size of the buffer used to read in source file lines. */
86 #define STRING_SIZE 200
88 /* One copy of this structure is created for each source file mentioned in the
95 struct sourcefile
*next
;
98 /* This points to the head of the sourcefile structure list. */
100 struct sourcefile
*sources
;
102 /* One of these is dynamically created whenever we identify an arc in the
109 unsigned int count_valid
: 1;
110 unsigned int on_tree
: 1;
111 unsigned int fake
: 1;
112 unsigned int fall_through
: 1;
114 /* Not needed for gcov, but defined in profile.c. */
117 struct adj_list
*pred_next
;
118 struct adj_list
*succ_next
;
121 /* Count the number of basic blocks, and create an array of these structures,
122 one for each bb in the function. */
125 struct adj_list
*succ
;
126 struct adj_list
*pred
;
127 gcov_type succ_count
;
128 gcov_type pred_count
;
129 gcov_type exec_count
;
130 unsigned int count_valid
: 1;
131 unsigned int on_tree
: 1;
133 /* Not needed for gcov, but defined in profile.c. */
138 /* When outputting branch probabilities, one of these structures is created
139 for each branch/call. */
146 struct arcdata
*next
;
149 /* Used to save the list of bb_graphs, one per function. */
151 struct bb_info_list
{
152 /* Indexed by block number, holds the basic block graph for one function. */
153 struct bb_info
*bb_graph
;
155 struct bb_info_list
*next
;
158 /* Holds a list of function basic block graphs. */
160 static struct bb_info_list
*bb_graph_list
= 0;
162 /* Name and file pointer of the input file for the basic block graph. */
164 static char *bbg_file_name
;
165 static FILE *bbg_file
;
167 /* Name and file pointer of the input file for the arc count data. */
169 static char *da_file_name
;
170 static FILE *da_file
;
172 /* Name and file pointer of the input file for the basic block line counts. */
174 static char *bb_file_name
;
175 static FILE *bb_file
;
177 /* Holds the entire contents of the bb_file read into memory. */
179 static char *bb_data
;
181 /* Size of bb_data array in longs. */
183 static long bb_data_size
;
185 /* Name and file pointer of the output file. */
187 static char *gcov_file_name
;
188 static FILE *gcov_file
;
190 /* Name of the file mentioned on the command line. */
192 static char *input_file_name
= 0;
194 /* Output branch probabilities if true. */
196 static int output_branch_probs
= 0;
198 /* Output a gcov file if this is true. This is on by default, and can
199 be turned off by the -n option. */
201 static int output_gcov_file
= 1;
203 /* For included files, make the gcov output file name include the name of
204 the input source file. For example, if x.h is included in a.c, then the
205 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
206 when a single source file is specified. */
208 static int output_long_names
= 0;
210 /* Output summary info for each function. */
212 static int output_function_summary
= 0;
214 /* Object directory file prefix. This is the directory where .bb and .bbg
215 files are looked for, if non-zero. */
217 static char *object_directory
= 0;
219 /* Output the number of times a branch was taken as opposed to the percentage
220 of times it was taken. Turned on by the -c option */
222 static int output_branch_counts
= 0;
224 /* Forward declarations. */
225 static void process_args
PARAMS ((int, char **));
226 static void open_files
PARAMS ((void));
227 static void read_files
PARAMS ((void));
228 static void scan_for_source_files
PARAMS ((void));
229 static void output_data
PARAMS ((void));
230 static void print_usage
PARAMS ((void)) ATTRIBUTE_NORETURN
;
231 static void init_arc
PARAMS ((struct adj_list
*, int, int, struct bb_info
*));
232 static struct adj_list
*reverse_arcs
PARAMS ((struct adj_list
*));
233 static void create_program_flow_graph
PARAMS ((struct bb_info_list
*));
234 static void solve_program_flow_graph
PARAMS ((struct bb_info_list
*));
235 static void calculate_branch_probs
PARAMS ((struct bb_info_list
*, int,
236 struct arcdata
**, int));
237 static void function_summary
PARAMS ((void));
239 extern int main
PARAMS ((int, char **));
248 process_args (argc
, argv
);
254 scan_for_source_files ();
261 static void fnotice
PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2
;
263 fnotice
VPARAMS ((FILE *file
, const char *msgid
, ...))
266 VA_FIXEDARG (ap
, FILE *, file
);
267 VA_FIXEDARG (ap
, const char *, msgid
);
269 vfprintf (file
, _(msgid
), ap
);
273 /* More 'friendly' abort that prints the line and file.
274 config.h can #define abort fancy_abort if you like that sort of thing. */
275 extern void fancy_abort
PARAMS ((void)) ATTRIBUTE_NORETURN
;
280 fnotice (stderr
, "Internal gcov abort.\n");
281 exit (FATAL_EXIT_CODE
);
284 /* Print a usage message and exit. */
289 fnotice (stderr
, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
290 exit (FATAL_EXIT_CODE
);
293 /* Parse the command line. */
296 process_args (argc
, argv
)
302 for (i
= 1; i
< argc
; i
++)
304 if (argv
[i
][0] == '-')
306 if (argv
[i
][1] == 'b')
307 output_branch_probs
= 1;
308 else if (argv
[i
][1] == 'c')
309 output_branch_counts
= 1;
310 else if (argv
[i
][1] == 'v')
311 fputs (gcov_version_string
, stderr
);
312 else if (argv
[i
][1] == 'n')
313 output_gcov_file
= 0;
314 else if (argv
[i
][1] == 'l')
315 output_long_names
= 1;
316 else if (argv
[i
][1] == 'f')
317 output_function_summary
= 1;
318 else if (argv
[i
][1] == 'o' && argv
[i
][2] == '\0')
319 object_directory
= argv
[++i
];
323 else if (! input_file_name
)
324 input_file_name
= argv
[i
];
329 if (! input_file_name
)
334 /* Find and open the .bb, .da, and .bbg files. */
339 int count
, objdir_count
;
342 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
343 extension, if any, and append the new extensions. */
344 count
= strlen (input_file_name
);
345 if (object_directory
)
346 objdir_count
= strlen (object_directory
);
350 da_file_name
= xmalloc (count
+ objdir_count
+ 4);
351 bb_file_name
= xmalloc (count
+ objdir_count
+ 4);
352 bbg_file_name
= xmalloc (count
+ objdir_count
+ 5);
354 if (object_directory
)
356 strcpy (da_file_name
, object_directory
);
357 strcpy (bb_file_name
, object_directory
);
358 strcpy (bbg_file_name
, object_directory
);
360 if (object_directory
[objdir_count
- 1] != '/')
362 strcat (da_file_name
, "/");
363 strcat (bb_file_name
, "/");
364 strcat (bbg_file_name
, "/");
367 cptr
= strrchr (input_file_name
, '/');
370 strcat (da_file_name
, cptr
+ 1);
371 strcat (bb_file_name
, cptr
+ 1);
372 strcat (bbg_file_name
, cptr
+ 1);
376 strcat (da_file_name
, input_file_name
);
377 strcat (bb_file_name
, input_file_name
);
378 strcat (bbg_file_name
, input_file_name
);
383 strcpy (da_file_name
, input_file_name
);
384 strcpy (bb_file_name
, input_file_name
);
385 strcpy (bbg_file_name
, input_file_name
);
388 cptr
= strrchr (bb_file_name
, '.');
390 strcpy (cptr
, ".bb");
392 strcat (bb_file_name
, ".bb");
394 cptr
= strrchr (da_file_name
, '.');
396 strcpy (cptr
, ".da");
398 strcat (da_file_name
, ".da");
400 cptr
= strrchr (bbg_file_name
, '.');
402 strcpy (cptr
, ".bbg");
404 strcat (bbg_file_name
, ".bbg");
406 bb_file
= fopen (bb_file_name
, "rb");
409 fnotice (stderr
, "Could not open basic block file %s.\n", bb_file_name
);
410 exit (FATAL_EXIT_CODE
);
413 /* If none of the functions in the file were executed, then there won't
414 be a .da file. Just assume that all counts are zero in this case. */
415 da_file
= fopen (da_file_name
, "rb");
418 fnotice (stderr
, "Could not open data file %s.\n", da_file_name
);
419 fnotice (stderr
, "Assuming that all execution counts are zero.\n");
422 bbg_file
= fopen (bbg_file_name
, "rb");
423 if (bbg_file
== NULL
)
425 fnotice (stderr
, "Could not open program flow graph file %s.\n",
427 exit (FATAL_EXIT_CODE
);
430 /* Check for empty .bbg file. This indicates that there is no executable
431 code in this source file. */
432 /* Set the EOF condition if at the end of file. */
433 ungetc (getc (bbg_file
), bbg_file
);
436 fnotice (stderr
, "No executable code associated with file %s.\n",
438 exit (FATAL_EXIT_CODE
);
442 /* Initialize a new arc. */
445 init_arc (arcptr
, source
, target
, bb_graph
)
446 struct adj_list
*arcptr
;
448 struct bb_info
*bb_graph
;
450 arcptr
->target
= target
;
451 arcptr
->source
= source
;
453 arcptr
->arc_count
= 0;
454 arcptr
->count_valid
= 0;
457 arcptr
->fall_through
= 0;
459 arcptr
->succ_next
= bb_graph
[source
].succ
;
460 bb_graph
[source
].succ
= arcptr
;
461 bb_graph
[source
].succ_count
++;
463 arcptr
->pred_next
= bb_graph
[target
].pred
;
464 bb_graph
[target
].pred
= arcptr
;
465 bb_graph
[target
].pred_count
++;
469 /* Reverse the arcs on an arc list. */
471 static struct adj_list
*
472 reverse_arcs (arcptr
)
473 struct adj_list
*arcptr
;
475 struct adj_list
*prev
= 0;
476 struct adj_list
*next
;
478 for ( ; arcptr
; arcptr
= next
)
480 next
= arcptr
->succ_next
;
481 arcptr
->succ_next
= prev
;
489 /* Construct the program flow graph from the .bbg file, and read in the data
493 create_program_flow_graph (bptr
)
494 struct bb_info_list
*bptr
;
496 long num_blocks
, number_arcs
, src
, dest
, flag_bits
, num_arcs_per_block
;
498 struct adj_list
*arcptr
;
499 struct bb_info
*bb_graph
;
501 /* Read the number of blocks. */
502 __read_long (&num_blocks
, bbg_file
, 4);
504 /* Create an array of size bb number of bb_info structs. */
505 bb_graph
= (struct bb_info
*) xcalloc (num_blocks
, sizeof (struct bb_info
));
507 bptr
->bb_graph
= bb_graph
;
508 bptr
->num_blocks
= num_blocks
;
510 /* Read and create each arc from the .bbg file. */
511 __read_long (&number_arcs
, bbg_file
, 4);
512 for (i
= 0; i
< num_blocks
; i
++)
516 __read_long (&num_arcs_per_block
, bbg_file
, 4);
517 for (j
= 0; j
< num_arcs_per_block
; j
++)
519 if (number_arcs
-- < 0)
523 __read_long (&dest
, bbg_file
, 4);
525 arcptr
= (struct adj_list
*) xmalloc (sizeof (struct adj_list
));
526 init_arc (arcptr
, src
, dest
, bb_graph
);
528 __read_long (&flag_bits
, bbg_file
, 4);
529 arcptr
->on_tree
= flag_bits
& 0x1;
530 arcptr
->fake
= !! (flag_bits
& 0x2);
531 arcptr
->fall_through
= !! (flag_bits
& 0x4);
538 /* Read and ignore the -1 separating the arc list from the arc list of the
540 __read_long (&src
, bbg_file
, 4);
544 /* Must reverse the order of all succ arcs, to ensure that they match
545 the order of the data in the .da file. */
547 for (i
= 0; i
< num_blocks
; i
++)
548 if (bb_graph
[i
].succ
)
549 bb_graph
[i
].succ
= reverse_arcs (bb_graph
[i
].succ
);
551 /* For each arc not on the spanning tree, set its execution count from
554 /* The first count in the .da file is the number of times that the function
555 was entered. This is the exec_count for block zero. */
557 /* This duplicates code in branch_prob in profile.c. */
559 for (i
= 0; i
< num_blocks
; i
++)
560 for (arcptr
= bb_graph
[i
].succ
; arcptr
; arcptr
= arcptr
->succ_next
)
561 if (! arcptr
->on_tree
)
563 gcov_type tmp_count
= 0;
564 if (da_file
&& __read_gcov_type (&tmp_count
, da_file
, 8))
567 arcptr
->arc_count
= tmp_count
;
568 arcptr
->count_valid
= 1;
569 bb_graph
[i
].succ_count
--;
570 bb_graph
[arcptr
->target
].pred_count
--;
575 solve_program_flow_graph (bptr
)
576 struct bb_info_list
*bptr
;
581 struct adj_list
*arcptr
;
582 struct bb_info
*bb_graph
;
585 num_blocks
= bptr
->num_blocks
;
586 bb_graph
= bptr
->bb_graph
;
588 /* For every block in the file,
589 - if every exit/entrance arc has a known count, then set the block count
590 - if the block count is known, and every exit/entrance arc but one has
591 a known execution count, then set the count of the remaining arc
593 As arc counts are set, decrement the succ/pred count, but don't delete
594 the arc, that way we can easily tell when all arcs are known, or only
595 one arc is unknown. */
597 /* The order that the basic blocks are iterated through is important.
598 Since the code that finds spanning trees starts with block 0, low numbered
599 arcs are put on the spanning tree in preference to high numbered arcs.
600 Hence, most instrumented arcs are at the end. Graph solving works much
601 faster if we propagate numbers from the end to the start.
603 This takes an average of slightly more than 3 passes. */
612 for (i
= num_blocks
- 1; i
>= 0; i
--)
614 if (! bb_graph
[i
].count_valid
)
616 if (bb_graph
[i
].succ_count
== 0)
619 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
620 arcptr
= arcptr
->succ_next
)
621 total
+= arcptr
->arc_count
;
622 bb_graph
[i
].exec_count
= total
;
623 bb_graph
[i
].count_valid
= 1;
626 else if (bb_graph
[i
].pred_count
== 0)
629 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
630 arcptr
= arcptr
->pred_next
)
631 total
+= arcptr
->arc_count
;
632 bb_graph
[i
].exec_count
= total
;
633 bb_graph
[i
].count_valid
= 1;
637 if (bb_graph
[i
].count_valid
)
639 if (bb_graph
[i
].succ_count
== 1)
642 /* One of the counts will be invalid, but it is zero,
643 so adding it in also doesn't hurt. */
644 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
645 arcptr
= arcptr
->succ_next
)
646 total
+= arcptr
->arc_count
;
647 /* Calculate count for remaining arc by conservation. */
648 total
= bb_graph
[i
].exec_count
- total
;
649 /* Search for the invalid arc, and set its count. */
650 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
651 arcptr
= arcptr
->succ_next
)
652 if (! arcptr
->count_valid
)
656 arcptr
->count_valid
= 1;
657 arcptr
->arc_count
= total
;
658 bb_graph
[i
].succ_count
--;
660 bb_graph
[arcptr
->target
].pred_count
--;
663 if (bb_graph
[i
].pred_count
== 1)
666 /* One of the counts will be invalid, but it is zero,
667 so adding it in also doesn't hurt. */
668 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
669 arcptr
= arcptr
->pred_next
)
670 total
+= arcptr
->arc_count
;
671 /* Calculate count for remaining arc by conservation. */
672 total
= bb_graph
[i
].exec_count
- total
;
673 /* Search for the invalid arc, and set its count. */
674 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
675 arcptr
= arcptr
->pred_next
)
676 if (! arcptr
->count_valid
)
680 arcptr
->count_valid
= 1;
681 arcptr
->arc_count
= total
;
682 bb_graph
[i
].pred_count
--;
684 bb_graph
[arcptr
->source
].succ_count
--;
691 /* If the graph has been correctly solved, every block will have a
692 succ and pred count of zero. */
693 for (i
= 0; i
< num_blocks
; i
++)
694 if (bb_graph
[i
].succ_count
|| bb_graph
[i
].pred_count
)
703 struct bb_info_list
*list_end
= 0;
704 struct bb_info_list
*b_ptr
;
707 /* Read and ignore the first word of the .da file, which is the count of
708 how many numbers follow. */
709 if (da_file
&& __read_long (&total
, da_file
, 8))
712 while (! feof (bbg_file
))
714 b_ptr
= (struct bb_info_list
*) xmalloc (sizeof (struct bb_info_list
));
718 list_end
->next
= b_ptr
;
720 bb_graph_list
= b_ptr
;
723 /* Read in the data in the .bbg file and reconstruct the program flow
724 graph for one function. */
725 create_program_flow_graph (b_ptr
);
727 /* Set the EOF condition if at the end of file. */
728 ungetc (getc (bbg_file
), bbg_file
);
731 /* Check to make sure the .da file data is valid. */
736 fnotice (stderr
, ".da file contents exhausted too early\n");
737 /* Should be at end of file now. */
738 if (__read_long (&total
, da_file
, 8) == 0)
739 fnotice (stderr
, ".da file contents not exhausted\n");
742 /* Calculate all of the basic block execution counts and branch
743 taken probabilities. */
745 for (b_ptr
= bb_graph_list
; b_ptr
; b_ptr
= b_ptr
->next
)
746 solve_program_flow_graph (b_ptr
);
748 /* Read in all of the data from the .bb file. This info will be accessed
749 sequentially twice. */
750 stat (bb_file_name
, &buf
);
751 bb_data_size
= buf
.st_size
/ 4;
753 bb_data
= (char *) xmalloc ((unsigned) buf
.st_size
);
754 fread (bb_data
, sizeof (char), buf
.st_size
, bb_file
);
763 /* Scan the data in the .bb file to find all source files referenced,
764 and the largest line number mentioned in each one. */
767 scan_for_source_files ()
769 struct sourcefile
*s_ptr
= NULL
;
774 /* Search the bb_data to find:
775 1) The number of sources files contained herein, and
776 2) The largest line number for each source file. */
780 for (count
= 0; count
< bb_data_size
; count
++)
782 __fetch_long (&line_num
, ptr
, 4);
786 /* A source file name follows. Check to see if we already have
787 a sourcefile structure for this file. */
789 while (s_ptr
&& strcmp (s_ptr
->name
, ptr
))
794 /* No sourcefile structure for this file name exists, create
795 a new one, and append it to the front of the sources list. */
796 s_ptr
= (struct sourcefile
*) xmalloc (sizeof(struct sourcefile
));
797 s_ptr
->name
= xstrdup (ptr
);
798 s_ptr
->maxlineno
= 0;
799 s_ptr
->next
= sources
;
803 /* Scan past the file name. */
808 __fetch_long (&delim
, ptr
, 4);
810 } while (delim
!= line_num
);
813 else if (line_num
== -2)
817 /* A function name follows. Ignore it. */
820 __fetch_long (&delim
, ptr
, 4);
822 } while (delim
!= line_num
);
824 /* There will be a zero before the first file name, in which case s_ptr
825 will still be uninitialized. So, only try to set the maxlineno
826 field if line_num is non-zero. */
827 else if (line_num
> 0)
829 if (s_ptr
->maxlineno
<= line_num
)
830 s_ptr
->maxlineno
= line_num
+ 1;
832 else if (line_num
< 0)
834 /* Don't know what this is, but it's garbage. */
840 /* For calculating coverage at the function level. */
842 static int function_source_lines
;
843 static int function_source_lines_executed
;
844 static int function_branches
;
845 static int function_branches_executed
;
846 static int function_branches_taken
;
847 static int function_calls
;
848 static int function_calls_executed
;
849 static char *function_name
;
851 /* Calculate the branch taken probabilities for all arcs branches at the
852 end of this block. */
855 calculate_branch_probs (current_graph
, block_num
, branch_probs
, last_line_num
)
856 struct bb_info_list
*current_graph
;
858 struct arcdata
**branch_probs
;
862 struct adj_list
*arcptr
;
863 struct arcdata
*end_ptr
, *a_ptr
;
865 total
= current_graph
->bb_graph
[block_num
].exec_count
;
866 for (arcptr
= current_graph
->bb_graph
[block_num
].succ
; arcptr
;
867 arcptr
= arcptr
->succ_next
)
869 /* Ignore fall through arcs as they aren't really branches. */
871 if (arcptr
->fall_through
)
874 a_ptr
= (struct arcdata
*) xmalloc (sizeof (struct arcdata
));
875 a_ptr
->total
= total
;
879 a_ptr
->hits
= arcptr
->arc_count
;
880 a_ptr
->call_insn
= arcptr
->fake
;
882 if (output_function_summary
)
884 if (a_ptr
->call_insn
)
887 if (a_ptr
->total
!= 0)
888 function_calls_executed
++;
893 if (a_ptr
->total
!= 0)
894 function_branches_executed
++;
896 function_branches_taken
++;
900 /* Append the new branch to the end of the list. */
902 if (! branch_probs
[last_line_num
])
903 branch_probs
[last_line_num
] = a_ptr
;
906 end_ptr
= branch_probs
[last_line_num
];
907 while (end_ptr
->next
!= 0)
908 end_ptr
= end_ptr
->next
;
909 end_ptr
->next
= a_ptr
;
914 /* Output summary info for a function. */
919 if (function_source_lines
)
920 fnotice (stdout
, "%6.2f%% of %d source lines executed in function %s\n",
921 (((double) function_source_lines_executed
/ function_source_lines
)
922 * 100), function_source_lines
, function_name
);
924 fnotice (stdout
, "No executable source lines in function %s\n",
927 if (output_branch_probs
)
929 if (function_branches
)
931 fnotice (stdout
, "%6.2f%% of %d branches executed in function %s\n",
932 (((double) function_branches_executed
/ function_branches
)
933 * 100), function_branches
, function_name
);
935 "%6.2f%% of %d branches taken at least once in function %s\n",
936 (((double) function_branches_taken
/ function_branches
)
937 * 100), function_branches
, function_name
);
940 fnotice (stdout
, "No branches in function %s\n", function_name
);
942 fnotice (stdout
, "%6.2f%% of %d calls executed in function %s\n",
943 (((double) function_calls_executed
/ function_calls
)
944 * 100), function_calls
, function_name
);
946 fnotice (stdout
, "No calls in function %s\n", function_name
);
950 /* Calculate line execution counts, and output the data to a .tcov file. */
955 /* When scanning data, this is true only if the data applies to the
956 current source file. */
958 /* An array indexed by line number which indicates how many times that line
960 gcov_type
*line_counts
;
961 /* An array indexed by line number which indicates whether the line was
962 present in the bb file (i.e. whether it had code associate with it).
963 Lines never executed are those which both exist, and have zero execution
966 /* An array indexed by line number, which contains a list of branch
967 probabilities, one for each branch on that line. */
968 struct arcdata
**branch_probs
= NULL
;
969 struct sourcefile
*s_ptr
;
970 char *source_file_name
;
972 struct bb_info_list
*current_graph
;
977 long last_line_num
= 0;
979 struct arcdata
*a_ptr
;
980 /* Buffer used for reading in lines from the source file. */
981 char string
[STRING_SIZE
];
982 /* For calculating coverage at the file level. */
983 int total_source_lines
;
984 int total_source_lines_executed
;
986 int total_branches_executed
;
987 int total_branches_taken
;
989 int total_calls_executed
;
991 /* Now, for each source file, allocate an array big enough to hold a count
992 for each line. Scan through the bb_data, and when the file name matches
993 the current file name, then for each following line number, increment
994 the line number execution count indicated by the execution count of
995 the appropriate basic block. */
997 for (s_ptr
= sources
; s_ptr
; s_ptr
= s_ptr
->next
)
999 /* If this is a relative file name, and an object directory has been
1000 specified, then make it relative to the object directory name. */
1001 if (! (*s_ptr
->name
== '/' || *s_ptr
->name
== DIR_SEPARATOR
1002 /* Check for disk name on MS-DOS-based systems. */
1003 || (DIR_SEPARATOR
== '\\'
1004 && s_ptr
->name
[1] == ':'
1005 && (s_ptr
->name
[2] == DIR_SEPARATOR
1006 || s_ptr
->name
[2] == '/')))
1007 && object_directory
!= 0
1008 && *object_directory
!= '\0')
1010 int objdir_count
= strlen (object_directory
);
1011 source_file_name
= xmalloc (objdir_count
+ strlen (s_ptr
->name
) + 2);
1012 strcpy (source_file_name
, object_directory
);
1013 if (object_directory
[objdir_count
- 1] != '/')
1014 source_file_name
[objdir_count
++] = '/';
1015 strcpy (source_file_name
+ objdir_count
, s_ptr
->name
);
1018 source_file_name
= s_ptr
->name
;
1020 line_counts
= (gcov_type
*) xcalloc (sizeof (gcov_type
), s_ptr
->maxlineno
);
1021 line_exists
= xcalloc (1, s_ptr
->maxlineno
);
1022 if (output_branch_probs
)
1023 branch_probs
= (struct arcdata
**)
1024 xcalloc (sizeof (struct arcdata
*), s_ptr
->maxlineno
);
1026 /* There will be a zero at the beginning of the bb info, before the
1027 first list of line numbers, so must initialize block_num to 0. */
1032 /* Pointer into the bb_data, incremented while scanning the data. */
1033 char *ptr
= bb_data
;
1034 for (count
= 0; count
< bb_data_size
; count
++)
1038 __fetch_long (&line_num
, ptr
, 4);
1042 /* Marks the beginning of a file name. Check to see whether
1043 this is the filename we are currently collecting data for. */
1045 if (strcmp (s_ptr
->name
, ptr
))
1050 /* Scan past the file name. */
1053 __fetch_long (&delim
, ptr
, 4);
1055 } while (delim
!= line_num
);
1057 else if (line_num
== -2)
1059 /* Marks the start of a new function. Advance to the next
1060 program flow graph. */
1062 if (! current_graph
)
1063 current_graph
= bb_graph_list
;
1066 if (block_num
== current_graph
->num_blocks
- 1)
1067 /* Last block falls through to exit. */
1069 else if (block_num
== current_graph
->num_blocks
- 2)
1071 if (output_branch_probs
&& this_file
)
1072 calculate_branch_probs (current_graph
, block_num
,
1073 branch_probs
, last_line_num
);
1078 "didn't use all bb entries of graph, function %s\n",
1080 fnotice (stderr
, "block_num = %ld, num_blocks = %d\n",
1081 block_num
, current_graph
->num_blocks
);
1084 current_graph
= current_graph
->next
;
1087 if (output_function_summary
&& this_file
)
1088 function_summary ();
1091 if (output_function_summary
)
1093 function_source_lines
= 0;
1094 function_source_lines_executed
= 0;
1095 function_branches
= 0;
1096 function_branches_executed
= 0;
1097 function_branches_taken
= 0;
1099 function_calls_executed
= 0;
1102 /* Save the function name for later use. */
1103 function_name
= ptr
;
1105 /* Scan past the file name. */
1108 __fetch_long (&delim
, ptr
, 4);
1110 } while (delim
!= line_num
);
1112 else if (line_num
== 0)
1114 /* Marks the end of a block. */
1116 if (block_num
>= current_graph
->num_blocks
)
1118 fnotice (stderr
, "ERROR: too many basic blocks in .bb file %s\n",
1123 if (output_branch_probs
&& this_file
)
1124 calculate_branch_probs (current_graph
, block_num
,
1125 branch_probs
, last_line_num
);
1131 if (output_function_summary
)
1133 if (line_exists
[line_num
] == 0)
1134 function_source_lines
++;
1135 if (line_counts
[line_num
] == 0
1136 && current_graph
->bb_graph
[block_num
].exec_count
!= 0)
1137 function_source_lines_executed
++;
1140 /* Accumulate execution data for this line number. */
1142 line_counts
[line_num
]
1143 += current_graph
->bb_graph
[block_num
].exec_count
;
1144 line_exists
[line_num
] = 1;
1145 last_line_num
= line_num
;
1150 if (output_function_summary
&& this_file
)
1151 function_summary ();
1153 /* Calculate summary test coverage statistics. */
1155 total_source_lines
= 0;
1156 total_source_lines_executed
= 0;
1158 total_branches_executed
= 0;
1159 total_branches_taken
= 0;
1161 total_calls_executed
= 0;
1163 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1165 if (line_exists
[count
])
1167 total_source_lines
++;
1168 if (line_counts
[count
])
1169 total_source_lines_executed
++;
1171 if (output_branch_probs
)
1173 for (a_ptr
= branch_probs
[count
]; a_ptr
; a_ptr
= a_ptr
->next
)
1175 if (a_ptr
->call_insn
)
1178 if (a_ptr
->total
!= 0)
1179 total_calls_executed
++;
1184 if (a_ptr
->total
!= 0)
1185 total_branches_executed
++;
1186 if (a_ptr
->hits
> 0)
1187 total_branches_taken
++;
1193 if (total_source_lines
)
1195 "%6.2f%% of %d source lines executed in file %s\n",
1196 (((double) total_source_lines_executed
/ total_source_lines
)
1197 * 100), total_source_lines
, source_file_name
);
1199 fnotice (stdout
, "No executable source lines in file %s\n",
1202 if (output_branch_probs
)
1206 fnotice (stdout
, "%6.2f%% of %d branches executed in file %s\n",
1207 (((double) total_branches_executed
/ total_branches
)
1208 * 100), total_branches
, source_file_name
);
1210 "%6.2f%% of %d branches taken at least once in file %s\n",
1211 (((double) total_branches_taken
/ total_branches
)
1212 * 100), total_branches
, source_file_name
);
1215 fnotice (stdout
, "No branches in file %s\n", source_file_name
);
1217 fnotice (stdout
, "%6.2f%% of %d calls executed in file %s\n",
1218 (((double) total_calls_executed
/ total_calls
)
1219 * 100), total_calls
, source_file_name
);
1221 fnotice (stdout
, "No calls in file %s\n", source_file_name
);
1224 if (output_gcov_file
)
1226 /* Now the statistics are ready. Read in the source file one line
1227 at a time, and output that line to the gcov file preceded by
1228 its execution count if non zero. */
1230 source_file
= fopen (source_file_name
, "r");
1231 if (source_file
== NULL
)
1233 fnotice (stderr
, "Could not open source file %s.\n",
1240 count
= strlen (source_file_name
);
1241 cptr
= strrchr (s_ptr
->name
, '/');
1246 if (output_long_names
&& strcmp (cptr
, input_file_name
))
1248 gcov_file_name
= xmalloc (count
+ 7 + strlen (input_file_name
));
1250 cptr
= strrchr (input_file_name
, '/');
1252 strcpy (gcov_file_name
, cptr
+ 1);
1254 strcpy (gcov_file_name
, input_file_name
);
1256 strcat (gcov_file_name
, ".");
1258 cptr
= strrchr (source_file_name
, '/');
1260 strcat (gcov_file_name
, cptr
+ 1);
1262 strcat (gcov_file_name
, source_file_name
);
1266 gcov_file_name
= xmalloc (count
+ 6);
1267 cptr
= strrchr (source_file_name
, '/');
1269 strcpy (gcov_file_name
, cptr
+ 1);
1271 strcpy (gcov_file_name
, source_file_name
);
1274 /* Don't strip off the ending for compatibility with tcov, since
1275 this results in confusion if there is more than one file with
1276 the same basename, e.g. tmp.c and tmp.h. */
1277 strcat (gcov_file_name
, ".gcov");
1279 gcov_file
= fopen (gcov_file_name
, "w");
1281 if (gcov_file
== NULL
)
1283 fnotice (stderr
, "Could not open output file %s.\n",
1285 fclose (source_file
);
1291 fnotice (stdout
, "Creating %s.\n", gcov_file_name
);
1293 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1298 retval
= fgets (string
, STRING_SIZE
, source_file
);
1300 /* For lines which don't exist in the .bb file, print nothing
1301 before the source line. For lines which exist but were never
1302 executed, print ###### before the source line. Otherwise,
1303 print the execution count before the source line. */
1304 /* There are 16 spaces of indentation added before the source
1305 line so that tabs won't be messed up. */
1306 if (line_exists
[count
])
1308 if (line_counts
[count
])
1311 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)line_counts
[count
]);
1312 fprintf (gcov_file
, "%12s %s", c
,
1316 fprintf (gcov_file
, " ###### %s", string
);
1319 fprintf (gcov_file
, "\t\t%s", string
);
1321 /* In case the source file line is larger than our buffer, keep
1322 reading and outputting lines until we get a newline. */
1323 len
= strlen (string
);
1324 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1327 retval
= fgets (string
, STRING_SIZE
, source_file
);
1328 fputs (string
, gcov_file
);
1331 if (output_branch_probs
)
1333 for (i
= 0, a_ptr
= branch_probs
[count
]; a_ptr
;
1334 a_ptr
= a_ptr
->next
, i
++)
1336 if (a_ptr
->call_insn
)
1338 if (a_ptr
->total
== 0)
1339 fnotice (gcov_file
, "call %d never executed\n", i
);
1342 if (output_branch_counts
)
1345 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1346 a_ptr
->total
- a_ptr
->hits
);
1348 "call %d returns = %s\n", i
, c
);
1353 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1354 100 - ((a_ptr
->hits
* 100)
1355 + (a_ptr
->total
>> 1))
1358 "call %d returns = %s%%\n", i
, c
);
1364 if (a_ptr
->total
== 0)
1365 fnotice (gcov_file
, "branch %d never executed\n",
1369 if (output_branch_counts
)
1372 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1375 "branch %d taken = %s\n", i
, c
);
1380 sprintf (c
, HOST_WIDEST_INT_PRINT_DEC
,
1381 ((a_ptr
->hits
* 100)
1382 + (a_ptr
->total
>> 1))
1385 "branch %d taken = %s%%\n", i
, c
);
1392 /* Gracefully handle errors while reading the source file. */
1396 "Unexpected EOF while reading source file %s.\n",
1402 /* Handle all remaining source lines. There may be lines
1403 after the last line of code. */
1406 char *retval
= fgets (string
, STRING_SIZE
, source_file
);
1407 while (retval
!= NULL
)
1411 fprintf (gcov_file
, "\t\t%s", string
);
1413 /* In case the source file line is larger than our buffer, keep
1414 reading and outputting lines until we get a newline. */
1415 len
= strlen (string
);
1416 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1419 retval
= fgets (string
, STRING_SIZE
, source_file
);
1420 fputs (string
, gcov_file
);
1423 retval
= fgets (string
, STRING_SIZE
, source_file
);
1427 fclose (source_file
);