1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 91, 92, 93, 94, 96, 1997 Free Software Foundation, Inc.
4 Contributed by James E. Wilson of Cygnus Support.
5 Mongled by Bob Manson of Cygnus Support.
7 Gcov is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 Gcov is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Gcov; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* ??? The code in final.c that produces the struct bb assumes that there is
22 no padding between the fields. This is not necessary true. The current
23 code can only be trusted if longs and pointers are the same size. */
25 /* ??? No need to print an execution count on every line, could just print
26 it on the first line of each block, and only print it on a subsequent
27 line in the same block if the count changes. */
29 /* ??? Print a list of the ten blocks with the highest execution counts,
30 and list the line numbers corresponding to those blocks. Also, perhaps
31 list the line numbers with the highest execution counts, only printing
32 the first if there are several which are all listed in the same block. */
34 /* ??? Should have an option to print the number of basic blocks, and the
35 percent of them that are covered. */
37 /* ??? Does not correctly handle the case where two .bb files refer to the
38 same included source file. For example, if one has a short file containing
39 only inline functions, which is then included in two other files, then
40 there will be two .bb files which refer to the include file, but there
41 is no way to get the total execution counts for the included file, can
42 only get execution counts for one or the other of the including files. */
45 #include <sys/types.h>
48 /* The only need for this is so that we get macro definitions for rindex
54 extern char * rindex ();
56 /* The .bb file format consists of several lists of 4-byte integers
57 which are the line numbers of each basic block in the file. Each
58 list is terminated by a zero. These lists correspond to the basic
59 blocks in the reconstructed program flow graph.
61 A line number of -1 indicates that a source file name (padded to a
62 long boundary) follows. The padded file name is followed by
63 another -1 to make it easy to scan past file names. A -2 indicates
64 that a function name (padded to a long boundary) follows; the name
65 is followed by another -2 to make it easy to scan past the function
68 The .bbg file contains enough info to enable gcov to reconstruct the
69 program flow graph. The first word is the number of basic blocks,
70 the second word is the number of arcs, followed by the list of arcs
71 (source bb, dest bb pairs), then a -1, then the number of instrumented
72 arcs followed by the instrumented arcs, followed by another -1. This
73 is repeated for each function.
75 The .da file contains the execution count for each instrumented branch.
77 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
78 and the .da files are created when an executable compiled with
79 -fprofile-arcs is run. */
81 /* The functions in this file for creating and solution program flow graphs
82 are very similar to functions in the gcc source file profile.c. */
84 char gcov_version_string
[] = "GNU gcov version 1.5\n";
86 /* This is the size of the buffer used to read in source file lines. */
88 #define STRING_SIZE 200
90 /* One copy of this structure is created for each source file mentioned in the
97 struct sourcefile
*next
;
100 /* This points to the head of the sourcefile structure list. */
102 struct sourcefile
*sources
;
104 /* One of these is dynamically created whenever we identify an arc in the
111 unsigned int count_valid
: 1;
112 unsigned int on_tree
: 1;
113 unsigned int fake
: 1;
114 unsigned int fall_through
: 1;
116 /* Not needed for gcov, but defined in profile.c. */
119 struct adj_list
*pred_next
;
120 struct adj_list
*succ_next
;
123 /* Count the number of basic blocks, and create an array of these structures,
124 one for each bb in the function. */
127 struct adj_list
*succ
;
128 struct adj_list
*pred
;
132 unsigned int count_valid
: 1;
133 unsigned int on_tree
: 1;
135 /* Not needed for gcov, but defined in profile.c. */
140 /* When outputting branch probabilities, one of these structures is created
141 for each branch/call. */
147 struct arcdata
*next
;
150 /* Used to save the list of bb_graphs, one per function. */
152 struct bb_info_list
{
153 /* Indexed by block number, holds the basic block graph for one function. */
154 struct bb_info
*bb_graph
;
156 struct bb_info_list
*next
;
159 /* Holds a list of function basic block graphs. */
161 static struct bb_info_list
*bb_graph_list
= 0;
163 /* Name and file pointer of the input file for the basic block graph. */
165 static char *bbg_file_name
;
166 static FILE *bbg_file
;
168 /* Name and file pointer of the input file for the arc count data. */
170 static char *da_file_name
;
171 static FILE *da_file
;
173 /* Name and file pointer of the input file for the basic block line counts. */
175 static char *bb_file_name
;
176 static FILE *bb_file
;
178 /* Holds the entire contents of the bb_file read into memory. */
180 static char *bb_data
;
182 /* Size of bb_data array in longs. */
184 static long bb_data_size
;
186 /* Name and file pointer of the output file. */
188 static char *gcov_file_name
;
189 static FILE *gcov_file
;
191 /* Name of the file mentioned on the command line. */
193 static char *input_file_name
= 0;
195 /* Output branch probabilities if true. */
197 static int output_branch_probs
= 0;
199 /* Output a gcov file if this is true. This is on by default, and can
200 be turned off by the -n option. */
202 static int output_gcov_file
= 1;
204 /* For included files, make the gcov output file name include the name of
205 the input source file. For example, if x.h is included in a.c, then the
206 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
207 when a single source file is specified. */
209 static int output_long_names
= 0;
211 /* Output summary info for each function. */
213 static int output_function_summary
= 0;
215 /* Object directory file prefix. This is the directory where .bb and .bbg
216 files are looked for, if non-zero. */
218 static char *object_directory
= 0;
220 /* Forward declarations. */
221 static void process_args ();
222 static void open_files ();
223 static void read_files ();
224 static void scan_for_source_files ();
225 static void output_data ();
233 process_args (argc
, argv
);
239 scan_for_source_files ();
250 register char *value
= (char *) malloc (size
);
253 fprintf (stderr
, "error: virtual memory exhausted");
254 exit (FATAL_EXIT_CODE
);
259 /* More 'friendly' abort that prints the line and file.
260 config.h can #define abort fancy_abort if you like that sort of thing. */
265 fprintf (stderr
, "Internal gcc abort.\n");
266 exit (FATAL_EXIT_CODE
);
269 /* Print a usage message and exit. */
274 fprintf (stderr
, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
275 exit (FATAL_EXIT_CODE
);
278 /* Parse the command line. */
281 process_args (argc
, argv
)
287 for (i
= 1; i
< argc
; i
++)
289 if (argv
[i
][0] == '-')
291 if (argv
[i
][1] == 'b')
292 output_branch_probs
= 1;
293 else if (argv
[i
][1] == 'v')
294 fputs (gcov_version_string
, stderr
);
295 else if (argv
[i
][1] == 'n')
296 output_gcov_file
= 0;
297 else if (argv
[i
][1] == 'l')
298 output_long_names
= 1;
299 else if (argv
[i
][1] == 'f')
300 output_function_summary
= 1;
301 else if (argv
[i
][1] == 'o' && argv
[i
][2] == '\0')
302 object_directory
= argv
[++i
];
306 else if (! input_file_name
)
307 input_file_name
= argv
[i
];
312 if (! input_file_name
)
317 /* Find and open the .bb, .da, and .bbg files. */
322 int count
, objdir_count
;
325 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
326 extension, if any, and append the new extensions. */
327 count
= strlen (input_file_name
);
328 if (object_directory
)
329 objdir_count
= strlen (object_directory
);
333 da_file_name
= xmalloc (count
+ objdir_count
+ 4);
334 bb_file_name
= xmalloc (count
+ objdir_count
+ 4);
335 bbg_file_name
= xmalloc (count
+ objdir_count
+ 5);
337 if (object_directory
)
339 strcpy (da_file_name
, object_directory
);
340 strcpy (bb_file_name
, object_directory
);
341 strcpy (bbg_file_name
, object_directory
);
343 if (object_directory
[objdir_count
- 1] != '/')
345 strcat (da_file_name
, "/");
346 strcat (bb_file_name
, "/");
347 strcat (bbg_file_name
, "/");
350 cptr
= rindex (input_file_name
, '/');
353 strcat (da_file_name
, cptr
+ 1);
354 strcat (bb_file_name
, cptr
+ 1);
355 strcat (bbg_file_name
, cptr
+ 1);
359 strcat (da_file_name
, input_file_name
);
360 strcat (bb_file_name
, input_file_name
);
361 strcat (bbg_file_name
, input_file_name
);
366 strcpy (da_file_name
, input_file_name
);
367 strcpy (bb_file_name
, input_file_name
);
368 strcpy (bbg_file_name
, input_file_name
);
371 cptr
= rindex (bb_file_name
, '.');
373 strcpy (cptr
, ".bb");
375 strcat (bb_file_name
, ".bb");
377 cptr
= rindex (da_file_name
, '.');
379 strcpy (cptr
, ".da");
381 strcat (da_file_name
, ".da");
383 cptr
= rindex (bbg_file_name
, '.');
385 strcpy (cptr
, ".bbg");
387 strcat (bbg_file_name
, ".bbg");
389 bb_file
= fopen (bb_file_name
, "r");
392 fprintf (stderr
, "Could not open basic block file %s.\n", bb_file_name
);
393 exit (FATAL_EXIT_CODE
);
396 /* If none of the functions in the file were executed, then there won't
397 be a .da file. Just assume that all counts are zero in this case. */
398 da_file
= fopen (da_file_name
, "r");
401 fprintf (stderr
, "Could not open data file %s.\n", da_file_name
);
402 fprintf (stderr
, "Assuming that all execution counts are zero.\n");
405 bbg_file
= fopen (bbg_file_name
, "r");
406 if (bbg_file
== NULL
)
408 fprintf (stderr
, "Could not open program flow graph file %s.\n",
410 exit (FATAL_EXIT_CODE
);
413 /* Check for empty .bbg file. This indicates that there is no executable
414 code in this source file. */
415 /* Set the EOF condition if at the end of file. */
416 ungetc (getc (bbg_file
), bbg_file
);
419 fprintf (stderr
, "No executable code associated with file %s.\n",
421 exit (FATAL_EXIT_CODE
);
425 /* Initialize a new arc. */
428 init_arc (arcptr
, source
, target
, bb_graph
)
429 struct adj_list
*arcptr
;
431 struct bb_info
*bb_graph
;
433 arcptr
->target
= target
;
434 arcptr
->source
= source
;
436 arcptr
->arc_count
= 0;
437 arcptr
->count_valid
= 0;
440 arcptr
->fall_through
= 0;
442 arcptr
->succ_next
= bb_graph
[source
].succ
;
443 bb_graph
[source
].succ
= arcptr
;
444 bb_graph
[source
].succ_count
++;
446 arcptr
->pred_next
= bb_graph
[target
].pred
;
447 bb_graph
[target
].pred
= arcptr
;
448 bb_graph
[target
].pred_count
++;
452 /* Reverse the arcs on a arc list. */
454 static struct adj_list
*
455 reverse_arcs (arcptr
)
456 struct adj_list
*arcptr
;
458 struct adj_list
*prev
= 0;
459 struct adj_list
*next
;
461 for ( ; arcptr
; arcptr
= next
)
463 next
= arcptr
->succ_next
;
464 arcptr
->succ_next
= prev
;
472 /* Construct the program flow graph from the .bbg file, and read in the data
476 create_program_flow_graph (bptr
)
477 struct bb_info_list
*bptr
;
479 long num_blocks
, number_arcs
, src
, dest
, flag_bits
, num_arcs_per_block
;
481 struct adj_list
*arcptr
;
482 struct bb_info
*bb_graph
;
484 /* Read the number of blocks. */
485 __read_long (&num_blocks
, bbg_file
, 4);
487 /* Create an array of size bb number of bb_info structs. Bzero it. */
488 bb_graph
= (struct bb_info
*) xmalloc (num_blocks
489 * sizeof (struct bb_info
));
490 bzero ((char *) bb_graph
, sizeof (struct bb_info
) * num_blocks
);
492 bptr
->bb_graph
= bb_graph
;
493 bptr
->num_blocks
= num_blocks
;
495 /* Read and create each arc from the .bbg file. */
496 __read_long (&number_arcs
, bbg_file
, 4);
497 for (i
= 0; i
< num_blocks
; i
++)
501 __read_long (&num_arcs_per_block
, bbg_file
, 4);
502 for (j
= 0; j
< num_arcs_per_block
; j
++)
504 if (number_arcs
-- < 0)
508 __read_long (&dest
, bbg_file
, 4);
510 arcptr
= (struct adj_list
*) xmalloc (sizeof (struct adj_list
));
511 init_arc (arcptr
, src
, dest
, bb_graph
);
513 __read_long (&flag_bits
, bbg_file
, 4);
514 arcptr
->on_tree
= flag_bits
& 0x1;
515 arcptr
->fake
= !! (flag_bits
& 0x2);
516 arcptr
->fall_through
= !! (flag_bits
& 0x4);
523 /* Read and ignore the -1 separating the arc list from the arc list of the
525 __read_long (&src
, bbg_file
, 4);
529 /* Must reverse the order of all succ arcs, to ensure that they match
530 the order of the data in the .da file. */
532 for (i
= 0; i
< num_blocks
; i
++)
533 if (bb_graph
[i
].succ
)
534 bb_graph
[i
].succ
= reverse_arcs (bb_graph
[i
].succ
);
536 /* For each arc not on the spanning tree, set its execution count from
539 /* The first count in the .da file is the number of times that the function
540 was entered. This is the exec_count for block zero. */
542 /* This duplicates code in branch_prob in profile.c. */
544 for (i
= 0; i
< num_blocks
; i
++)
545 for (arcptr
= bb_graph
[i
].succ
; arcptr
; arcptr
= arcptr
->succ_next
)
546 if (! arcptr
->on_tree
)
549 if (da_file
&& __read_long (&tmp_count
, da_file
, 8))
552 arcptr
->arc_count
= tmp_count
;
553 arcptr
->count_valid
= 1;
554 bb_graph
[i
].succ_count
--;
555 bb_graph
[arcptr
->target
].pred_count
--;
560 solve_program_flow_graph (bptr
)
561 struct bb_info_list
*bptr
;
563 int passes
, changes
, total
;
565 struct adj_list
*arcptr
;
566 struct bb_info
*bb_graph
;
569 num_blocks
= bptr
->num_blocks
;
570 bb_graph
= bptr
->bb_graph
;
572 /* For every block in the file,
573 - if every exit/entrance arc has a known count, then set the block count
574 - if the block count is known, and every exit/entrance arc but one has
575 a known execution count, then set the count of the remaining arc
577 As arc counts are set, decrement the succ/pred count, but don't delete
578 the arc, that way we can easily tell when all arcs are known, or only
579 one arc is unknown. */
581 /* The order that the basic blocks are iterated through is important.
582 Since the code that finds spanning trees starts with block 0, low numbered
583 arcs are put on the spanning tree in preference to high numbered arcs.
584 Hence, most instrumented arcs are at the end. Graph solving works much
585 faster if we propagate numbers from the end to the start.
587 This takes an average of slightly more than 3 passes. */
596 for (i
= num_blocks
- 1; i
>= 0; i
--)
598 if (! bb_graph
[i
].count_valid
)
600 if (bb_graph
[i
].succ_count
== 0)
603 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
604 arcptr
= arcptr
->succ_next
)
605 total
+= arcptr
->arc_count
;
606 bb_graph
[i
].exec_count
= total
;
607 bb_graph
[i
].count_valid
= 1;
610 else if (bb_graph
[i
].pred_count
== 0)
613 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
614 arcptr
= arcptr
->pred_next
)
615 total
+= arcptr
->arc_count
;
616 bb_graph
[i
].exec_count
= total
;
617 bb_graph
[i
].count_valid
= 1;
621 if (bb_graph
[i
].count_valid
)
623 if (bb_graph
[i
].succ_count
== 1)
626 /* One of the counts will be invalid, but it is zero,
627 so adding it in also doesn't hurt. */
628 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
629 arcptr
= arcptr
->succ_next
)
630 total
+= arcptr
->arc_count
;
631 /* Calculate count for remaining arc by conservation. */
632 total
= bb_graph
[i
].exec_count
- total
;
633 /* Search for the invalid arc, and set its count. */
634 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
635 arcptr
= arcptr
->succ_next
)
636 if (! arcptr
->count_valid
)
640 arcptr
->count_valid
= 1;
641 arcptr
->arc_count
= total
;
642 bb_graph
[i
].succ_count
--;
644 bb_graph
[arcptr
->target
].pred_count
--;
647 if (bb_graph
[i
].pred_count
== 1)
650 /* One of the counts will be invalid, but it is zero,
651 so adding it in also doesn't hurt. */
652 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
653 arcptr
= arcptr
->pred_next
)
654 total
+= arcptr
->arc_count
;
655 /* Calculate count for remaining arc by conservation. */
656 total
= bb_graph
[i
].exec_count
- total
;
657 /* Search for the invalid arc, and set its count. */
658 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
659 arcptr
= arcptr
->pred_next
)
660 if (! arcptr
->count_valid
)
664 arcptr
->count_valid
= 1;
665 arcptr
->arc_count
= total
;
666 bb_graph
[i
].pred_count
--;
668 bb_graph
[arcptr
->source
].succ_count
--;
675 /* If the graph has been correctly solved, every block will have a
676 succ and pred count of zero. */
677 for (i
= 0; i
< num_blocks
; i
++)
678 if (bb_graph
[i
].succ_count
|| bb_graph
[i
].pred_count
)
687 struct bb_info_list
*list_end
= 0;
688 struct bb_info_list
*b_ptr
;
689 long total
, first_time
;
691 /* Read and ignore the first word of the .da file, which is the count of
692 how many numbers follow. */
693 if (da_file
&& __read_long (&total
, da_file
, 8))
696 while (! feof (bbg_file
))
698 b_ptr
= (struct bb_info_list
*) xmalloc (sizeof (struct bb_info_list
));
702 list_end
->next
= b_ptr
;
704 bb_graph_list
= b_ptr
;
707 /* Read in the data in the .bbg file and reconstruct the program flow
708 graph for one function. */
709 create_program_flow_graph (b_ptr
, first_time
);
711 /* Set the EOF condition if at the end of file. */
712 ungetc (getc (bbg_file
), bbg_file
);
715 /* Check to make sure the .da file data is valid. */
720 fprintf (stderr
, ".da file contents exhausted too early\n");
721 /* Should be at end of file now. */
722 if (__read_long (&total
, da_file
, 8) == 0)
723 fprintf (stderr
, ".da file contents not exhausted\n");
726 /* Calculate all of the basic block execution counts and branch
727 taken probabilities. */
729 for (b_ptr
= bb_graph_list
; b_ptr
; b_ptr
= b_ptr
->next
)
730 solve_program_flow_graph (b_ptr
);
732 /* Read in all of the data from the .bb file. This info will be accessed
733 sequentially twice. */
734 stat (bb_file_name
, &buf
);
735 bb_data_size
= buf
.st_size
/ 4;
737 bb_data
= (char *) xmalloc (buf
.st_size
);
738 fread (bb_data
, sizeof (char), buf
.st_size
, bb_file
);
747 /* Scan the data in the .bb file to find all source files referenced,
748 and the largest line number mentioned in each one. */
751 scan_for_source_files ()
753 struct sourcefile
*s_ptr
;
758 /* Search the bb_data to find:
759 1) The number of sources files contained herein, and
760 2) The largest line number for each source file. */
764 for (count
= 0; count
< bb_data_size
; count
++)
766 __fetch_long (&line_num
, ptr
, 4);
770 /* A source file name follows. Check to see if we already have
771 a sourcefile structure for this file. */
773 while (s_ptr
&& strcmp (s_ptr
->name
, ptr
))
778 /* No sourcefile structure for this file name exists, create
779 a new one, and append it to the front of the sources list. */
780 s_ptr
= (struct sourcefile
*) xmalloc (sizeof(struct sourcefile
));
781 s_ptr
->name
= xmalloc (strlen ((char *) ptr
) + 1);
782 strcpy (s_ptr
->name
, (char *) ptr
);
783 s_ptr
->maxlineno
= 0;
784 s_ptr
->next
= sources
;
788 /* Scan past the file name. */
793 __fetch_long (&delim
, ptr
, 4);
795 } while (delim
!= line_num
);
798 else if (line_num
== -2)
802 /* A function name follows. Ignore it. */
805 __fetch_long (&delim
, ptr
, 4);
807 } while (delim
!= line_num
);
809 /* There will be a zero before the first file name, in which case s_ptr
810 will still be uninitialized. So, only try to set the maxlineno
811 field if line_num is non-zero. */
812 else if (line_num
> 0)
814 if (s_ptr
->maxlineno
<= line_num
)
815 s_ptr
->maxlineno
= line_num
+ 1;
817 else if (line_num
< 0)
819 /* Don't know what this is, but it's garbage. */
825 /* For calculating coverage at the function level. */
827 static int function_source_lines
;
828 static int function_source_lines_executed
;
829 static int function_branches
;
830 static int function_branches_executed
;
831 static int function_branches_taken
;
832 static int function_calls
;
833 static int function_calls_executed
;
834 static char *function_name
;
836 /* Calculate the branch taken probabilities for all arcs branches at the
837 end of this block. */
840 calculate_branch_probs (current_graph
, block_num
, branch_probs
, last_line_num
)
841 struct bb_info_list
*current_graph
;
843 struct arcdata
**branch_probs
;
847 struct adj_list
*arcptr
;
848 struct arcdata
*end_ptr
, *a_ptr
;
850 total
= current_graph
->bb_graph
[block_num
].exec_count
;
851 for (arcptr
= current_graph
->bb_graph
[block_num
].succ
; arcptr
;
852 arcptr
= arcptr
->succ_next
)
854 /* Ignore fall through arcs as they aren't really branches. */
856 if (arcptr
->fall_through
)
859 a_ptr
= (struct arcdata
*) xmalloc (sizeof (struct arcdata
));
863 a_ptr
->prob
= ((arcptr
->arc_count
* 100) + (total
>> 1)) / total
;
864 a_ptr
->call_insn
= arcptr
->fake
;
866 if (output_function_summary
)
868 if (a_ptr
->call_insn
)
871 if (a_ptr
->prob
!= -1)
872 function_calls_executed
++;
877 if (a_ptr
->prob
!= -1)
878 function_branches_executed
++;
880 function_branches_taken
++;
884 /* Append the new branch to the end of the list. */
886 if (! branch_probs
[last_line_num
])
887 branch_probs
[last_line_num
] = a_ptr
;
890 end_ptr
= branch_probs
[last_line_num
];
891 while (end_ptr
->next
!= 0)
892 end_ptr
= end_ptr
->next
;
893 end_ptr
->next
= a_ptr
;
898 /* Output summary info for a function. */
903 if (function_source_lines
)
904 fprintf (stdout
, "%6.2lf%% of %d source lines executed in function %s\n",
905 (((double) function_source_lines_executed
/ function_source_lines
)
906 * 100), function_source_lines
, function_name
);
908 fprintf (stdout
, "No executable source lines in function %s\n",
911 if (output_branch_probs
)
913 if (function_branches
)
915 fprintf (stdout
, "%6.2lf%% of %d branches executed in funcion %s\n",
916 (((double) function_branches_executed
/ function_branches
)
917 * 100), function_branches
, function_name
);
919 "%6.2lf%% of %d branches taken at least once in function %s\n",
920 (((double) function_branches_taken
/ function_branches
)
921 * 100), function_branches
, function_name
);
924 fprintf (stdout
, "No branches in function %s\n", function_name
);
926 fprintf (stdout
, "%6.2lf%% of %d calls executed in function %s\n",
927 (((double) function_calls_executed
/ function_calls
)
928 * 100), function_calls
, function_name
);
930 fprintf (stdout
, "No calls in function %s\n", function_name
);
934 /* Calculate line execution counts, and output the data to a .tcov file. */
939 /* When scanning data, this is true only if the data applies to the
940 current source file. */
942 /* An array indexed by line number which indicates how many times that line
945 /* An array indexed by line number which indicates whether the line was
946 present in the bb file (i.e. whether it had code associate with it).
947 Lines never executed are those which both exist, and have zero execution
950 /* An array indexed by line number, which contains a list of branch
951 probabilities, one for each branch on that line. */
952 struct arcdata
**branch_probs
;
953 struct sourcefile
*s_ptr
;
954 char *source_file_name
;
956 struct bb_info_list
*current_graph
;
963 struct arcdata
*a_ptr
;
964 /* Buffer used for reading in lines from the source file. */
965 char string
[STRING_SIZE
];
966 /* For calculating coverage at the file level. */
967 int total_source_lines
;
968 int total_source_lines_executed
;
970 int total_branches_executed
;
971 int total_branches_taken
;
973 int total_calls_executed
;
975 /* Now, for each source file, allocate an array big enough to hold a count
976 for each line. Scan through the bb_data, and when the file name matches
977 the current file name, then for each following line number, increment
978 the line number execution count indicated by the execution count of
979 the appropriate basic block. */
981 for (s_ptr
= sources
; s_ptr
; s_ptr
= s_ptr
->next
)
983 /* If this is a relative file name, and an object directory has been
984 specified, then make it relative to the object directory name. */
985 if (*s_ptr
->name
!= '/' && object_directory
!= 0
986 && *object_directory
!= '\0')
988 int objdir_count
= strlen (object_directory
);
989 source_file_name
= xmalloc (objdir_count
+ strlen (s_ptr
->name
) + 2);
990 strcpy (source_file_name
, object_directory
);
991 if (object_directory
[objdir_count
- 1] != '/')
992 source_file_name
[objdir_count
++] = '/';
993 strcpy (source_file_name
+ objdir_count
, s_ptr
->name
);
996 source_file_name
= s_ptr
->name
;
998 line_counts
= (long *) xmalloc (sizeof (long) * s_ptr
->maxlineno
);
999 bzero ((char *) line_counts
, sizeof (long) * s_ptr
->maxlineno
);
1000 line_exists
= xmalloc (s_ptr
->maxlineno
);
1001 bzero (line_exists
, s_ptr
->maxlineno
);
1002 if (output_branch_probs
)
1004 branch_probs
= (struct arcdata
**) xmalloc (sizeof (struct arcdata
**)
1005 * s_ptr
->maxlineno
);
1006 bzero ((char *) branch_probs
,
1007 sizeof (struct arcdata
**) * s_ptr
->maxlineno
);
1010 /* There will be a zero at the beginning of the bb info, before the
1011 first list of line numbers, so must initialize block_num to 0. */
1016 /* Pointer into the bb_data, incremented while scanning the data. */
1017 char *ptr
= bb_data
;
1018 for (count
= 0; count
< bb_data_size
; count
++)
1022 __fetch_long (&line_num
, ptr
, 4);
1026 /* Marks the beginning of a file name. Check to see whether
1027 this is the filename we are currently collecting data for. */
1029 if (strcmp (s_ptr
->name
, ptr
))
1034 /* Scan past the file name. */
1037 __fetch_long (&delim
, ptr
, 4);
1039 } while (delim
!= line_num
);
1041 else if (line_num
== -2)
1043 /* Marks the start of a new function. Advance to the next
1044 program flow graph. */
1046 if (! current_graph
)
1047 current_graph
= bb_graph_list
;
1050 if (block_num
== current_graph
->num_blocks
- 1)
1051 /* Last block falls through to exit. */
1053 else if (block_num
== current_graph
->num_blocks
- 2)
1055 if (output_branch_probs
&& this_file
)
1056 calculate_branch_probs (current_graph
, block_num
,
1057 branch_probs
, last_line_num
);
1062 "didn't use all bb entries of graph, function %s\n",
1064 fprintf (stderr
, "block_num = %d, num_blocks = %d\n",
1065 block_num
, current_graph
->num_blocks
);
1068 current_graph
= current_graph
->next
;
1071 if (output_function_summary
&& this_file
)
1072 function_summary ();
1075 if (output_function_summary
)
1077 function_source_lines
= 0;
1078 function_source_lines_executed
= 0;
1079 function_branches
= 0;
1080 function_branches_executed
= 0;
1081 function_branches_taken
= 0;
1083 function_calls_executed
= 0;
1086 /* Save the function name for later use. */
1087 function_name
= ptr
;
1089 /* Scan past the file name. */
1092 __fetch_long (&delim
, ptr
, 4);
1094 } while (delim
!= line_num
);
1096 else if (line_num
== 0)
1098 /* Marks the end of a block. */
1100 if (block_num
>= current_graph
->num_blocks
)
1102 fprintf (stderr
, "ERROR: too many basic blocks in .bb file %s\n",
1107 if (output_branch_probs
&& this_file
)
1108 calculate_branch_probs (current_graph
, block_num
,
1109 branch_probs
, last_line_num
);
1115 if (output_function_summary
)
1117 if (line_exists
[line_num
] == 0)
1118 function_source_lines
++;
1119 if (line_counts
[line_num
] == 0
1120 && current_graph
->bb_graph
[block_num
].exec_count
!= 0)
1121 function_source_lines_executed
++;
1124 /* Accumulate execution data for this line number. */
1126 line_counts
[line_num
]
1127 += current_graph
->bb_graph
[block_num
].exec_count
;
1128 line_exists
[line_num
] = 1;
1129 last_line_num
= line_num
;
1134 if (output_function_summary
&& this_file
)
1135 function_summary ();
1137 /* Calculate summary test coverage statistics. */
1139 total_source_lines
= 0;
1140 total_source_lines_executed
= 0;
1142 total_branches_executed
= 0;
1143 total_branches_taken
= 0;
1145 total_calls_executed
= 0;
1147 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1149 if (line_exists
[count
])
1151 total_source_lines
++;
1152 if (line_counts
[count
])
1153 total_source_lines_executed
++;
1155 if (output_branch_probs
)
1157 for (a_ptr
= branch_probs
[count
]; a_ptr
; a_ptr
= a_ptr
->next
)
1159 if (a_ptr
->call_insn
)
1162 if (a_ptr
->prob
!= -1)
1163 total_calls_executed
++;
1168 if (a_ptr
->prob
!= -1)
1169 total_branches_executed
++;
1170 if (a_ptr
->prob
> 0)
1171 total_branches_taken
++;
1177 if (total_source_lines
)
1179 "%6.2lf%% of %d source lines executed in file %s\n",
1180 (((double) total_source_lines_executed
/ total_source_lines
)
1181 * 100), total_source_lines
, source_file_name
);
1183 fprintf (stdout
, "No executable source lines in file %s\n",
1186 if (output_branch_probs
)
1190 fprintf (stdout
, "%6.2lf%% of %d branches executed in file %s\n",
1191 (((double) total_branches_executed
/ total_branches
)
1192 * 100), total_branches
, source_file_name
);
1194 "%6.2lf%% of %d branches taken at least once in file %s\n",
1195 (((double) total_branches_taken
/ total_branches
)
1196 * 100), total_branches
, source_file_name
);
1199 fprintf (stdout
, "No branches in file %s\n", source_file_name
);
1201 fprintf (stdout
, "%6.2lf%% of %d calls executed in file %s\n",
1202 (((double) total_calls_executed
/ total_calls
)
1203 * 100), total_calls
, source_file_name
);
1205 fprintf (stdout
, "No calls in file %s\n", source_file_name
);
1208 if (output_gcov_file
)
1210 /* Now the statistics are ready. Read in the source file one line
1211 at a time, and output that line to the gcov file preceeded by
1212 its execution count if non zero. */
1214 source_file
= fopen (source_file_name
, "r");
1215 if (source_file
== NULL
)
1217 fprintf (stderr
, "Could not open source file %s.\n",
1224 count
= strlen (source_file_name
);
1225 cptr
= rindex (s_ptr
->name
, '/');
1230 if (output_long_names
&& strcmp (cptr
, input_file_name
))
1232 gcov_file_name
= xmalloc (count
+ 7 + strlen (input_file_name
));
1234 cptr
= rindex (input_file_name
, '/');
1236 strcpy (gcov_file_name
, cptr
+ 1);
1238 strcpy (gcov_file_name
, input_file_name
);
1240 strcat (gcov_file_name
, ".");
1242 cptr
= rindex (source_file_name
, '/');
1244 strcat (gcov_file_name
, cptr
+ 1);
1246 strcat (gcov_file_name
, source_file_name
);
1250 gcov_file_name
= xmalloc (count
+ 6);
1251 cptr
= rindex (source_file_name
, '/');
1253 strcpy (gcov_file_name
, cptr
+ 1);
1255 strcpy (gcov_file_name
, source_file_name
);
1258 /* Don't strip off the ending for compatibility with tcov, since
1259 this results in confusion if there is more than one file with
1260 the same basename, e.g. tmp.c and tmp.h. */
1261 strcat (gcov_file_name
, ".gcov");
1263 gcov_file
= fopen (gcov_file_name
, "w");
1265 if (gcov_file
== NULL
)
1267 fprintf (stderr
, "Could not open output file %s.\n",
1269 fclose (source_file
);
1275 fprintf (stdout
, "Creating %s.\n", gcov_file_name
);
1277 for (count
= 1; count
< s_ptr
->maxlineno
; count
++)
1282 retval
= fgets (string
, STRING_SIZE
, source_file
);
1284 /* For lines which don't exist in the .bb file, print nothing
1285 before the source line. For lines which exist but were never
1286 executed, print ###### before the source line. Otherwise,
1287 print the execution count before the source line. */
1288 /* There are 16 spaces of identation added before the source line
1289 so that tabs won't be messed up. */
1290 if (line_exists
[count
])
1292 if (line_counts
[count
])
1293 fprintf (gcov_file
, "%12d %s", line_counts
[count
],
1296 fprintf (gcov_file
, " ###### %s", string
);
1299 fprintf (gcov_file
, "\t\t%s", string
);
1301 /* In case the source file line is larger than our buffer, keep
1302 reading and outputing lines until we get a newline. */
1303 len
= strlen (string
);
1304 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1307 retval
= fgets (string
, STRING_SIZE
, source_file
);
1308 fputs (string
, gcov_file
);
1311 if (output_branch_probs
)
1313 for (i
= 0, a_ptr
= branch_probs
[count
]; a_ptr
;
1314 a_ptr
= a_ptr
->next
, i
++)
1316 if (a_ptr
->call_insn
)
1318 if (a_ptr
->prob
== -1)
1319 fprintf (gcov_file
, "call %d never executed\n", i
);
1322 "call %d returns = %d%%\n",
1323 i
, 100 - a_ptr
->prob
);
1327 if (a_ptr
->prob
== -1)
1328 fprintf (gcov_file
, "branch %d never executed\n",
1331 fprintf (gcov_file
, "branch %d taken = %d%%\n", i
,
1337 /* Gracefully handle errors while reading the source file. */
1341 "Unexpected EOF while reading source file %s.\n",
1347 /* Handle all remaining source lines. There may be lines
1348 after the last line of code. */
1351 char *retval
= fgets (string
, STRING_SIZE
, source_file
);
1352 while (retval
!= NULL
)
1356 fprintf (gcov_file
, "\t\t%s", string
);
1358 /* In case the source file line is larger than our buffer, keep
1359 reading and outputing lines until we get a newline. */
1360 len
= strlen (string
);
1361 while ((len
== 0 || string
[strlen (string
) - 1] != '\n')
1364 retval
= fgets (string
, STRING_SIZE
, source_file
);
1365 fputs (string
, gcov_file
);
1368 retval
= fgets (string
, STRING_SIZE
, source_file
);
1372 fclose (source_file
);