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 #ifdef HAVE_LC_MESSAGES
246 setlocale (LC_MESSAGES
, "");
248 (void) bindtextdomain (PACKAGE
, localedir
);
249 (void) textdomain (PACKAGE
);
251 process_args (argc
, argv
);
257 scan_for_source_files ();
264 static void fnotice
PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2
;
266 fnotice
VPARAMS ((FILE *file
, const char *msgid
, ...))
268 #ifndef ANSI_PROTOTYPES
274 VA_START (ap
, msgid
);
276 #ifndef ANSI_PROTOTYPES
277 file
= va_arg (ap
, FILE *);
278 msgid
= va_arg (ap
, const char *);
281 vfprintf (file
, _(msgid
), ap
);
285 /* More 'friendly' abort that prints the line and file.
286 config.h can #define abort fancy_abort if you like that sort of thing. */
287 extern void fancy_abort
PARAMS ((void)) ATTRIBUTE_NORETURN
;
292 fnotice (stderr
, "Internal gcov abort.\n");
293 exit (FATAL_EXIT_CODE
);
296 /* Print a usage message and exit. */
301 fnotice (stderr
, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
302 exit (FATAL_EXIT_CODE
);
305 /* Parse the command line. */
308 process_args (argc
, argv
)
314 for (i
= 1; i
< argc
; i
++)
316 if (argv
[i
][0] == '-')
318 if (argv
[i
][1] == 'b')
319 output_branch_probs
= 1;
320 else if (argv
[i
][1] == 'c')
321 output_branch_counts
= 1;
322 else if (argv
[i
][1] == 'v')
323 fputs (gcov_version_string
, stderr
);
324 else if (argv
[i
][1] == 'n')
325 output_gcov_file
= 0;
326 else if (argv
[i
][1] == 'l')
327 output_long_names
= 1;
328 else if (argv
[i
][1] == 'f')
329 output_function_summary
= 1;
330 else if (argv
[i
][1] == 'o' && argv
[i
][2] == '\0')
331 object_directory
= argv
[++i
];
335 else if (! input_file_name
)
336 input_file_name
= argv
[i
];
341 if (! input_file_name
)
346 /* Find and open the .bb, .da, and .bbg files. */
351 int count
, objdir_count
;
354 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
355 extension, if any, and append the new extensions. */
356 count
= strlen (input_file_name
);
357 if (object_directory
)
358 objdir_count
= strlen (object_directory
);
362 da_file_name
= xmalloc (count
+ objdir_count
+ 4);
363 bb_file_name
= xmalloc (count
+ objdir_count
+ 4);
364 bbg_file_name
= xmalloc (count
+ objdir_count
+ 5);
366 if (object_directory
)
368 strcpy (da_file_name
, object_directory
);
369 strcpy (bb_file_name
, object_directory
);
370 strcpy (bbg_file_name
, object_directory
);
372 if (object_directory
[objdir_count
- 1] != '/')
374 strcat (da_file_name
, "/");
375 strcat (bb_file_name
, "/");
376 strcat (bbg_file_name
, "/");
379 cptr
= strrchr (input_file_name
, '/');
382 strcat (da_file_name
, cptr
+ 1);
383 strcat (bb_file_name
, cptr
+ 1);
384 strcat (bbg_file_name
, cptr
+ 1);
388 strcat (da_file_name
, input_file_name
);
389 strcat (bb_file_name
, input_file_name
);
390 strcat (bbg_file_name
, input_file_name
);
395 strcpy (da_file_name
, input_file_name
);
396 strcpy (bb_file_name
, input_file_name
);
397 strcpy (bbg_file_name
, input_file_name
);
400 cptr
= strrchr (bb_file_name
, '.');
402 strcpy (cptr
, ".bb");
404 strcat (bb_file_name
, ".bb");
406 cptr
= strrchr (da_file_name
, '.');
408 strcpy (cptr
, ".da");
410 strcat (da_file_name
, ".da");
412 cptr
= strrchr (bbg_file_name
, '.');
414 strcpy (cptr
, ".bbg");
416 strcat (bbg_file_name
, ".bbg");
418 bb_file
= fopen (bb_file_name
, "rb");
421 fnotice (stderr
, "Could not open basic block file %s.\n", bb_file_name
);
422 exit (FATAL_EXIT_CODE
);
425 /* If none of the functions in the file were executed, then there won't
426 be a .da file. Just assume that all counts are zero in this case. */
427 da_file
= fopen (da_file_name
, "rb");
430 fnotice (stderr
, "Could not open data file %s.\n", da_file_name
);
431 fnotice (stderr
, "Assuming that all execution counts are zero.\n");
434 bbg_file
= fopen (bbg_file_name
, "rb");
435 if (bbg_file
== NULL
)
437 fnotice (stderr
, "Could not open program flow graph file %s.\n",
439 exit (FATAL_EXIT_CODE
);
442 /* Check for empty .bbg file. This indicates that there is no executable
443 code in this source file. */
444 /* Set the EOF condition if at the end of file. */
445 ungetc (getc (bbg_file
), bbg_file
);
448 fnotice (stderr
, "No executable code associated with file %s.\n",
450 exit (FATAL_EXIT_CODE
);
454 /* Initialize a new arc. */
457 init_arc (arcptr
, source
, target
, bb_graph
)
458 struct adj_list
*arcptr
;
460 struct bb_info
*bb_graph
;
462 arcptr
->target
= target
;
463 arcptr
->source
= source
;
465 arcptr
->arc_count
= 0;
466 arcptr
->count_valid
= 0;
469 arcptr
->fall_through
= 0;
471 arcptr
->succ_next
= bb_graph
[source
].succ
;
472 bb_graph
[source
].succ
= arcptr
;
473 bb_graph
[source
].succ_count
++;
475 arcptr
->pred_next
= bb_graph
[target
].pred
;
476 bb_graph
[target
].pred
= arcptr
;
477 bb_graph
[target
].pred_count
++;
481 /* Reverse the arcs on a arc list. */
483 static struct adj_list
*
484 reverse_arcs (arcptr
)
485 struct adj_list
*arcptr
;
487 struct adj_list
*prev
= 0;
488 struct adj_list
*next
;
490 for ( ; arcptr
; arcptr
= next
)
492 next
= arcptr
->succ_next
;
493 arcptr
->succ_next
= prev
;
501 /* Construct the program flow graph from the .bbg file, and read in the data
505 create_program_flow_graph (bptr
)
506 struct bb_info_list
*bptr
;
508 long num_blocks
, number_arcs
, src
, dest
, flag_bits
, num_arcs_per_block
;
510 struct adj_list
*arcptr
;
511 struct bb_info
*bb_graph
;
513 /* Read the number of blocks. */
514 __read_long (&num_blocks
, bbg_file
, 4);
516 /* Create an array of size bb number of bb_info structs. */
517 bb_graph
= (struct bb_info
*) xcalloc (num_blocks
, sizeof (struct bb_info
));
519 bptr
->bb_graph
= bb_graph
;
520 bptr
->num_blocks
= num_blocks
;
522 /* Read and create each arc from the .bbg file. */
523 __read_long (&number_arcs
, bbg_file
, 4);
524 for (i
= 0; i
< num_blocks
; i
++)
528 __read_long (&num_arcs_per_block
, bbg_file
, 4);
529 for (j
= 0; j
< num_arcs_per_block
; j
++)
531 if (number_arcs
-- < 0)
535 __read_long (&dest
, bbg_file
, 4);
537 arcptr
= (struct adj_list
*) xmalloc (sizeof (struct adj_list
));
538 init_arc (arcptr
, src
, dest
, bb_graph
);
540 __read_long (&flag_bits
, bbg_file
, 4);
541 arcptr
->on_tree
= flag_bits
& 0x1;
542 arcptr
->fake
= !! (flag_bits
& 0x2);
543 arcptr
->fall_through
= !! (flag_bits
& 0x4);
550 /* Read and ignore the -1 separating the arc list from the arc list of the
552 __read_long (&src
, bbg_file
, 4);
556 /* Must reverse the order of all succ arcs, to ensure that they match
557 the order of the data in the .da file. */
559 for (i
= 0; i
< num_blocks
; i
++)
560 if (bb_graph
[i
].succ
)
561 bb_graph
[i
].succ
= reverse_arcs (bb_graph
[i
].succ
);
563 /* For each arc not on the spanning tree, set its execution count from
566 /* The first count in the .da file is the number of times that the function
567 was entered. This is the exec_count for block zero. */
569 /* This duplicates code in branch_prob in profile.c. */
571 for (i
= 0; i
< num_blocks
; i
++)
572 for (arcptr
= bb_graph
[i
].succ
; arcptr
; arcptr
= arcptr
->succ_next
)
573 if (! arcptr
->on_tree
)
576 if (da_file
&& __read_long (&tmp_count
, da_file
, 8))
579 arcptr
->arc_count
= tmp_count
;
580 arcptr
->count_valid
= 1;
581 bb_graph
[i
].succ_count
--;
582 bb_graph
[arcptr
->target
].pred_count
--;
587 solve_program_flow_graph (bptr
)
588 struct bb_info_list
*bptr
;
590 int passes
, changes
, total
;
592 struct adj_list
*arcptr
;
593 struct bb_info
*bb_graph
;
596 num_blocks
= bptr
->num_blocks
;
597 bb_graph
= bptr
->bb_graph
;
599 /* For every block in the file,
600 - if every exit/entrance arc has a known count, then set the block count
601 - if the block count is known, and every exit/entrance arc but one has
602 a known execution count, then set the count of the remaining arc
604 As arc counts are set, decrement the succ/pred count, but don't delete
605 the arc, that way we can easily tell when all arcs are known, or only
606 one arc is unknown. */
608 /* The order that the basic blocks are iterated through is important.
609 Since the code that finds spanning trees starts with block 0, low numbered
610 arcs are put on the spanning tree in preference to high numbered arcs.
611 Hence, most instrumented arcs are at the end. Graph solving works much
612 faster if we propagate numbers from the end to the start.
614 This takes an average of slightly more than 3 passes. */
623 for (i
= num_blocks
- 1; i
>= 0; i
--)
625 if (! bb_graph
[i
].count_valid
)
627 if (bb_graph
[i
].succ_count
== 0)
630 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
631 arcptr
= arcptr
->succ_next
)
632 total
+= arcptr
->arc_count
;
633 bb_graph
[i
].exec_count
= total
;
634 bb_graph
[i
].count_valid
= 1;
637 else if (bb_graph
[i
].pred_count
== 0)
640 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
641 arcptr
= arcptr
->pred_next
)
642 total
+= arcptr
->arc_count
;
643 bb_graph
[i
].exec_count
= total
;
644 bb_graph
[i
].count_valid
= 1;
648 if (bb_graph
[i
].count_valid
)
650 if (bb_graph
[i
].succ_count
== 1)
653 /* One of the counts will be invalid, but it is zero,
654 so adding it in also doesn't hurt. */
655 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
656 arcptr
= arcptr
->succ_next
)
657 total
+= arcptr
->arc_count
;
658 /* Calculate count for remaining arc by conservation. */
659 total
= bb_graph
[i
].exec_count
- total
;
660 /* Search for the invalid arc, and set its count. */
661 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
662 arcptr
= arcptr
->succ_next
)
663 if (! arcptr
->count_valid
)
667 arcptr
->count_valid
= 1;
668 arcptr
->arc_count
= total
;
669 bb_graph
[i
].succ_count
--;
671 bb_graph
[arcptr
->target
].pred_count
--;
674 if (bb_graph
[i
].pred_count
== 1)
677 /* One of the counts will be invalid, but it is zero,
678 so adding it in also doesn't hurt. */
679 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
680 arcptr
= arcptr
->pred_next
)
681 total
+= arcptr
->arc_count
;
682 /* Calculate count for remaining arc by conservation. */
683 total
= bb_graph
[i
].exec_count
- total
;
684 /* Search for the invalid arc, and set its count. */
685 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
686 arcptr
= arcptr
->pred_next
)
687 if (! arcptr
->count_valid
)
691 arcptr
->count_valid
= 1;
692 arcptr
->arc_count
= total
;
693 bb_graph
[i
].pred_count
--;
695 bb_graph
[arcptr
->source
].succ_count
--;
702 /* If the graph has been correctly solved, every block will have a
703 succ and pred count of zero. */
704 for (i
= 0; i
< num_blocks
; i
++)
705 if (bb_graph
[i
].succ_count
|| bb_graph
[i
].pred_count
)
714 struct bb_info_list
*list_end
= 0;
715 struct bb_info_list
*b_ptr
;
718 /* Read and ignore the first word of the .da file, which is the count of
719 how many numbers follow. */
720 if (da_file
&& __read_long (&total
, da_file
, 8))
723 while (! feof (bbg_file
))
725 b_ptr
= (struct bb_info_list
*) xmalloc (sizeof (struct bb_info_list
));
729 list_end
->next
= b_ptr
;
731 bb_graph_list
= b_ptr
;
734 /* Read in the data in the .bbg file and reconstruct the program flow
735 graph for one function. */
736 create_program_flow_graph (b_ptr
);
738 /* Set the EOF condition if at the end of file. */
739 ungetc (getc (bbg_file
), bbg_file
);
742 /* Check to make sure the .da file data is valid. */
747 fnotice (stderr
, ".da file contents exhausted too early\n");
748 /* Should be at end of file now. */
749 if (__read_long (&total
, da_file
, 8) == 0)
750 fnotice (stderr
, ".da file contents not exhausted\n");
753 /* Calculate all of the basic block execution counts and branch
754 taken probabilities. */
756 for (b_ptr
= bb_graph_list
; b_ptr
; b_ptr
= b_ptr
->next
)
757 solve_program_flow_graph (b_ptr
);
759 /* Read in all of the data from the .bb file. This info will be accessed
760 sequentially twice. */
761 stat (bb_file_name
, &buf
);
762 bb_data_size
= buf
.st_size
/ 4;
764 bb_data
= (char *) xmalloc ((unsigned) buf
.st_size
);
765 fread (bb_data
, sizeof (char), buf
.st_size
, bb_file
);
774 /* Scan the data in the .bb file to find all source files referenced,
775 and the largest line number mentioned in each one. */
778 scan_for_source_files ()
780 struct sourcefile
*s_ptr
= NULL
;
785 /* Search the bb_data to find:
786 1) The number of sources files contained herein, and
787 2) The largest line number for each source file. */
791 for (count
= 0; count
< bb_data_size
; count
++)
793 __fetch_long (&line_num
, ptr
, 4);
797 /* A source file name follows. Check to see if we already have
798 a sourcefile structure for this file. */
800 while (s_ptr
&& strcmp (s_ptr
->name
, ptr
))
805 /* No sourcefile structure for this file name exists, create
806 a new one, and append it to the front of the sources list. */
807 s_ptr
= (struct sourcefile
*) xmalloc (sizeof(struct sourcefile
));
808 s_ptr
->name
= xstrdup (ptr
);
809 s_ptr
->maxlineno
= 0;
810 s_ptr
->next
= sources
;
814 /* Scan past the file name. */
819 __fetch_long (&delim
, ptr
, 4);
821 } while (delim
!= line_num
);
824 else if (line_num
== -2)
828 /* A function name follows. Ignore it. */
831 __fetch_long (&delim
, ptr
, 4);
833 } while (delim
!= line_num
);
835 /* There will be a zero before the first file name, in which case s_ptr
836 will still be uninitialized. So, only try to set the maxlineno
837 field if line_num is non-zero. */
838 else if (line_num
> 0)
840 if (s_ptr
->maxlineno
<= line_num
)
841 s_ptr
->maxlineno
= line_num
+ 1;
843 else if (line_num
< 0)
845 /* Don't know what this is, but it's garbage. */
851 /* For calculating coverage at the function level. */
853 static int function_source_lines
;
854 static int function_source_lines_executed
;
855 static int function_branches
;
856 static int function_branches_executed
;
857 static int function_branches_taken
;
858 static int function_calls
;
859 static int function_calls_executed
;
860 static char *function_name
;
862 /* Calculate the branch taken probabilities for all arcs branches at the
863 end of this block. */
866 calculate_branch_probs (current_graph
, block_num
, branch_probs
, last_line_num
)
867 struct bb_info_list
*current_graph
;
869 struct arcdata
**branch_probs
;
873 struct adj_list
*arcptr
;
874 struct arcdata
*end_ptr
, *a_ptr
;
876 total
= current_graph
->bb_graph
[block_num
].exec_count
;
877 for (arcptr
= current_graph
->bb_graph
[block_num
].succ
; arcptr
;
878 arcptr
= arcptr
->succ_next
)
880 /* Ignore fall through arcs as they aren't really branches. */
882 if (arcptr
->fall_through
)
885 a_ptr
= (struct arcdata
*) xmalloc (sizeof (struct arcdata
));
886 a_ptr
->total
= total
;
890 a_ptr
->hits
= arcptr
->arc_count
;
891 a_ptr
->call_insn
= arcptr
->fake
;
893 if (output_function_summary
)
895 if (a_ptr
->call_insn
)
898 if (a_ptr
->total
!= 0)
899 function_calls_executed
++;
904 if (a_ptr
->total
!= 0)
905 function_branches_executed
++;
907 function_branches_taken
++;
911 /* Append the new branch to the end of the list. */
913 if (! branch_probs
[last_line_num
])
914 branch_probs
[last_line_num
] = a_ptr
;
917 end_ptr
= branch_probs
[last_line_num
];
918 while (end_ptr
->next
!= 0)
919 end_ptr
= end_ptr
->next
;
920 end_ptr
->next
= a_ptr
;
925 /* Output summary info for a function. */
930 if (function_source_lines
)
931 fnotice (stdout
, "%6.2f%% of %d source lines executed in function %s\n",
932 (((double) function_source_lines_executed
/ function_source_lines
)
933 * 100), function_source_lines
, function_name
);
935 fnotice (stdout
, "No executable source lines in function %s\n",
938 if (output_branch_probs
)
940 if (function_branches
)
942 fnotice (stdout
, "%6.2f%% of %d branches executed in function %s\n",
943 (((double) function_branches_executed
/ function_branches
)
944 * 100), function_branches
, function_name
);
946 "%6.2f%% of %d branches taken at least once in function %s\n",
947 (((double) function_branches_taken
/ function_branches
)
948 * 100), function_branches
, function_name
);
951 fnotice (stdout
, "No branches in function %s\n", function_name
);
953 fnotice (stdout
, "%6.2f%% of %d calls executed in function %s\n",
954 (((double) function_calls_executed
/ function_calls
)
955 * 100), function_calls
, function_name
);
957 fnotice (stdout
, "No calls in function %s\n", function_name
);
961 /* Calculate line execution counts, and output the data to a .tcov file. */
966 /* When scanning data, this is true only if the data applies to the
967 current source file. */
969 /* An array indexed by line number which indicates how many times that line
972 /* An array indexed by line number which indicates whether the line was
973 present in the bb file (i.e. whether it had code associate with it).
974 Lines never executed are those which both exist, and have zero execution
977 /* An array indexed by line number, which contains a list of branch
978 probabilities, one for each branch on that line. */
979 struct arcdata
**branch_probs
= NULL
;
980 struct sourcefile
*s_ptr
;
981 char *source_file_name
;
983 struct bb_info_list
*current_graph
;
988 long last_line_num
= 0;
990 struct arcdata
*a_ptr
;
991 /* Buffer used for reading in lines from the source file. */
992 char string
[STRING_SIZE
];
993 /* For calculating coverage at the file level. */
994 int total_source_lines
;
995 int total_source_lines_executed
;
997 int total_branches_executed
;
998 int total_branches_taken
;
1000 int total_calls_executed
;
1002 /* Now, for each source file, allocate an array big enough to hold a count
1003 for each line. Scan through the bb_data, and when the file name matches
1004 the current file name, then for each following line number, increment
1005 the line number execution count indicated by the execution count of
1006 the appropriate basic block. */
1008 for (s_ptr
= sources
; s_ptr
; s_ptr
= s_ptr
->next
)
1010 /* If this is a relative file name, and an object directory has been
1011 specified, then make it relative to the object directory name. */
1012 if (! (*s_ptr
->name
== '/' || *s_ptr
->name
== DIR_SEPARATOR
1013 /* Check for disk name on MS-DOS-based systems. */
1014 || (DIR_SEPARATOR
== '\\'
1015 && s_ptr
->name
[1] == ':'
1016 && (s_ptr
->name
[2] == DIR_SEPARATOR
1017 || s_ptr
->name
[2] == '/')))
1018 && object_directory
!= 0
1019 && *object_directory
!= '\0')
1021 int objdir_count
= strlen (object_directory
);
1022 source_file_name
= xmalloc (objdir_count
+ strlen (s_ptr
->name
) + 2);
1023 strcpy (source_file_name
, object_directory
);
1024 if (object_directory
[objdir_count
- 1] != '/')
1025 source_file_name
[objdir_count
++] = '/';
1026 strcpy (source_file_name
+ objdir_count
, s_ptr
->name
);
1029 source_file_name
= s_ptr
->name
;
1031 line_counts
= (long *) xcalloc (sizeof (long), s_ptr
->maxlineno
);
1032 line_exists
= xcalloc (1, s_ptr
->maxlineno
);
1033 if (output_branch_probs
)
1034 branch_probs
= (struct arcdata
**)
1035 xcalloc (sizeof (struct arcdata
*), s_ptr
->maxlineno
);
1037 /* There will be a zero at the beginning of the bb info, before the
1038 first list of line numbers, so must initialize block_num to 0. */
1043 /* Pointer into the bb_data, incremented while scanning the data. */
1044 char *ptr
= bb_data
;
1045 for (count
= 0; count
< bb_data_size
; count
++)
1049 __fetch_long (&line_num
, ptr
, 4);
1053 /* Marks the beginning of a file name. Check to see whether
1054 this is the filename we are currently collecting data for. */
1056 if (strcmp (s_ptr
->name
, ptr
))
1061 /* Scan past the file name. */
1064 __fetch_long (&delim
, ptr
, 4);
1066 } while (delim
!= line_num
);
1068 else if (line_num
== -2)
1070 /* Marks the start of a new function. Advance to the next
1071 program flow graph. */
1073 if (! current_graph
)
1074 current_graph
= bb_graph_list
;
1077 if (block_num
== current_graph
->num_blocks
- 1)
1078 /* Last block falls through to exit. */
1080 else if (block_num
== current_graph
->num_blocks
- 2)
1082 if (output_branch_probs
&& this_file
)
1083 calculate_branch_probs (current_graph
, block_num
,
1084 branch_probs
, last_line_num
);
1089 "didn't use all bb entries of graph, function %s\n",
1091 fnotice (stderr
, "block_num = %ld, num_blocks = %d\n",
1092 block_num
, current_graph
->num_blocks
);
1095 current_graph
= current_graph
->next
;
1098 if (output_function_summary
&& this_file
)
1099 function_summary ();
1102 if (output_function_summary
)
1104 function_source_lines
= 0;
1105 function_source_lines_executed
= 0;
1106 function_branches
= 0;
1107 function_branches_executed
= 0;
1108 function_branches_taken
= 0;
1110 function_calls_executed
= 0;
1113 /* Save the function name for later use. */
1114 function_name
= ptr
;
1116 /* Scan past the file name. */
1119 __fetch_long (&delim
, ptr
, 4);
1121 } while (delim
!= line_num
);
1123 else if (line_num
== 0)
1125 /* Marks the end of a block. */
1127 if (block_num
>= current_graph
->num_blocks
)
1129 fnotice (stderr
, "ERROR: too many basic blocks in .bb file %s\n",
1134 if (output_branch_probs
&& this_file
)
1135 calculate_branch_probs (current_graph
, block_num
,
1136 branch_probs
, last_line_num
);
1142 if (output_function_summary
)
1144 if (line_exists
[line_num
] == 0)
1145 function_source_lines
++;
1146 if (line_counts
[line_num
] == 0
1147 && current_graph
->bb_graph
[block_num
].exec_count
!= 0)
1148 function_source_lines_executed
++;
1151 /* Accumulate execution data for this line number. */
1153 line_counts
[line_num
]
1154 += current_graph
->bb_graph
[block_num
].exec_count
;
1155 line_exists
[line_num
] = 1;
1156 last_line_num
= line_num
;
1161 if (output_function_summary
&& this_file
)
1162 function_summary ();
1164 /* Calculate summary test coverage statistics. */
1166 total_source_lines
= 0;
1167 total_source_lines_executed
= 0;
1169 total_branches_executed
= 0;
1170 total_branches_taken
= 0;
1172 total_calls_executed
= 0;
1174 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1176 if (line_exists
[count
])
1178 total_source_lines
++;
1179 if (line_counts
[count
])
1180 total_source_lines_executed
++;
1182 if (output_branch_probs
)
1184 for (a_ptr
= branch_probs
[count
]; a_ptr
; a_ptr
= a_ptr
->next
)
1186 if (a_ptr
->call_insn
)
1189 if (a_ptr
->total
!= 0)
1190 total_calls_executed
++;
1195 if (a_ptr
->total
!= 0)
1196 total_branches_executed
++;
1197 if (a_ptr
->hits
> 0)
1198 total_branches_taken
++;
1204 if (total_source_lines
)
1206 "%6.2f%% of %d source lines executed in file %s\n",
1207 (((double) total_source_lines_executed
/ total_source_lines
)
1208 * 100), total_source_lines
, source_file_name
);
1210 fnotice (stdout
, "No executable source lines in file %s\n",
1213 if (output_branch_probs
)
1217 fnotice (stdout
, "%6.2f%% of %d branches executed in file %s\n",
1218 (((double) total_branches_executed
/ total_branches
)
1219 * 100), total_branches
, source_file_name
);
1221 "%6.2f%% of %d branches taken at least once in file %s\n",
1222 (((double) total_branches_taken
/ total_branches
)
1223 * 100), total_branches
, source_file_name
);
1226 fnotice (stdout
, "No branches in file %s\n", source_file_name
);
1228 fnotice (stdout
, "%6.2f%% of %d calls executed in file %s\n",
1229 (((double) total_calls_executed
/ total_calls
)
1230 * 100), total_calls
, source_file_name
);
1232 fnotice (stdout
, "No calls in file %s\n", source_file_name
);
1235 if (output_gcov_file
)
1237 /* Now the statistics are ready. Read in the source file one line
1238 at a time, and output that line to the gcov file preceded by
1239 its execution count if non zero. */
1241 source_file
= fopen (source_file_name
, "r");
1242 if (source_file
== NULL
)
1244 fnotice (stderr
, "Could not open source file %s.\n",
1251 count
= strlen (source_file_name
);
1252 cptr
= strrchr (s_ptr
->name
, '/');
1257 if (output_long_names
&& strcmp (cptr
, input_file_name
))
1259 gcov_file_name
= xmalloc (count
+ 7 + strlen (input_file_name
));
1261 cptr
= strrchr (input_file_name
, '/');
1263 strcpy (gcov_file_name
, cptr
+ 1);
1265 strcpy (gcov_file_name
, input_file_name
);
1267 strcat (gcov_file_name
, ".");
1269 cptr
= strrchr (source_file_name
, '/');
1271 strcat (gcov_file_name
, cptr
+ 1);
1273 strcat (gcov_file_name
, source_file_name
);
1277 gcov_file_name
= xmalloc (count
+ 6);
1278 cptr
= strrchr (source_file_name
, '/');
1280 strcpy (gcov_file_name
, cptr
+ 1);
1282 strcpy (gcov_file_name
, source_file_name
);
1285 /* Don't strip off the ending for compatibility with tcov, since
1286 this results in confusion if there is more than one file with
1287 the same basename, e.g. tmp.c and tmp.h. */
1288 strcat (gcov_file_name
, ".gcov");
1290 gcov_file
= fopen (gcov_file_name
, "w");
1292 if (gcov_file
== NULL
)
1294 fnotice (stderr
, "Could not open output file %s.\n",
1296 fclose (source_file
);
1302 fnotice (stdout
, "Creating %s.\n", gcov_file_name
);
1304 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1309 retval
= fgets (string
, STRING_SIZE
, source_file
);
1311 /* For lines which don't exist in the .bb file, print nothing
1312 before the source line. For lines which exist but were never
1313 executed, print ###### before the source line. Otherwise,
1314 print the execution count before the source line. */
1315 /* There are 16 spaces of indentation added before the source
1316 line so that tabs won't be messed up. */
1317 if (line_exists
[count
])
1319 if (line_counts
[count
])
1320 fprintf (gcov_file
, "%12ld %s", line_counts
[count
],
1323 fprintf (gcov_file
, " ###### %s", string
);
1326 fprintf (gcov_file
, "\t\t%s", string
);
1328 /* In case the source file line is larger than our buffer, keep
1329 reading and outputting lines until we get a newline. */
1330 len
= strlen (string
);
1331 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1334 retval
= fgets (string
, STRING_SIZE
, source_file
);
1335 fputs (string
, gcov_file
);
1338 if (output_branch_probs
)
1340 for (i
= 0, a_ptr
= branch_probs
[count
]; a_ptr
;
1341 a_ptr
= a_ptr
->next
, i
++)
1343 if (a_ptr
->call_insn
)
1345 if (a_ptr
->total
== 0)
1346 fnotice (gcov_file
, "call %d never executed\n", i
);
1349 if (output_branch_counts
)
1351 "call %d returns = %d\n",
1352 i
, a_ptr
->total
- a_ptr
->hits
);
1355 "call %d returns = %d%%\n",
1356 i
, 100 - ((a_ptr
->hits
* 100) +
1357 (a_ptr
->total
>> 1))/a_ptr
->total
);
1362 if (a_ptr
->total
== 0)
1363 fnotice (gcov_file
, "branch %d never executed\n",
1367 if (output_branch_counts
)
1369 "branch %d taken = %d\n",
1373 "branch %d taken = %d%%\n", i
,
1374 ((a_ptr
->hits
* 100) +
1375 (a_ptr
->total
>> 1))/
1383 /* Gracefully handle errors while reading the source file. */
1387 "Unexpected EOF while reading source file %s.\n",
1393 /* Handle all remaining source lines. There may be lines
1394 after the last line of code. */
1397 char *retval
= fgets (string
, STRING_SIZE
, source_file
);
1398 while (retval
!= NULL
)
1402 fprintf (gcov_file
, "\t\t%s", string
);
1404 /* In case the source file line is larger than our buffer, keep
1405 reading and outputting lines until we get a newline. */
1406 len
= strlen (string
);
1407 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1410 retval
= fgets (string
, STRING_SIZE
, source_file
);
1411 fputs (string
, gcov_file
);
1414 retval
= fgets (string
, STRING_SIZE
, source_file
);
1418 fclose (source_file
);