1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
4 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5 Contributed by James E. Wilson of Cygnus Support.
6 Mangled by Bob Manson of Cygnus Support.
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 Gcov is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Gcov; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* ??? The code in final.c that produces the struct bb assumes that there is
24 no padding between the fields. This is not necessary true. The current
25 code can only be trusted if longs and pointers are the same size. */
27 /* ??? No need to print an execution count on every line, could just print
28 it on the first line of each block, and only print it on a subsequent
29 line in the same block if the count changes. */
31 /* ??? Print a list of the ten blocks with the highest execution counts,
32 and list the line numbers corresponding to those blocks. Also, perhaps
33 list the line numbers with the highest execution counts, only printing
34 the first if there are several which are all listed in the same block. */
36 /* ??? Should have an option to print the number of basic blocks, and the
37 percent of them that are covered. */
39 /* ??? Does not correctly handle the case where two .bb files refer to the
40 same included source file. For example, if one has a short file containing
41 only inline functions, which is then included in two other files, then
42 there will be two .bb files which refer to the include file, but there
43 is no way to get the total execution counts for the included file, can
44 only get execution counts for one or the other of the including files. */
54 typedef HOST_WIDEST_INT gcov_type
;
57 /* The .bb file format consists of several lists of 4-byte integers
58 which are the line numbers of each basic block in the file. Each
59 list is terminated by a zero. These lists correspond to the basic
60 blocks in the reconstructed program flow graph.
62 A line number of -1 indicates that a source file name (padded to a
63 long boundary) follows. The padded file name is followed by
64 another -1 to make it easy to scan past file names. A -2 indicates
65 that a function name (padded to a long boundary) follows; the name
66 is followed by another -2 to make it easy to scan past the function
69 The .bbg file contains enough info to enable gcov to reconstruct the
70 program flow graph. The first word is the number of basic blocks,
71 the second word is the number of arcs, followed by the list of arcs
72 (source bb, dest bb pairs), then a -1, then the number of instrumented
73 arcs followed by the instrumented arcs, followed by another -1. This
74 is repeated for each function.
76 The .da file contains the execution count for each instrumented branch.
78 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
79 and the .da files are created when an executable compiled with
80 -fprofile-arcs is run. */
82 /* The functions in this file for creating and solution program flow graphs
83 are very similar to functions in the gcc source file profile.c. */
85 /* This is the size of the buffer used to read in source file lines. */
87 #define STRING_SIZE 200
89 /* One copy of this structure is created for each source file mentioned in the
96 struct sourcefile
*next
;
99 /* This points to the head of the sourcefile structure list. */
101 struct sourcefile
*sources
;
103 /* One of these is dynamically created whenever we identify an arc in the
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. */
128 struct adj_list
*succ
;
129 struct adj_list
*pred
;
130 gcov_type succ_count
;
131 gcov_type pred_count
;
132 gcov_type exec_count
;
133 unsigned int count_valid
: 1;
134 unsigned int on_tree
: 1;
136 /* Not needed for gcov, but defined in profile.c. */
141 /* When outputting branch probabilities, one of these structures is created
142 for each branch/call. */
149 struct arcdata
*next
;
152 /* Used to save the list of bb_graphs, one per function. */
156 /* Indexed by block number, holds the basic block graph for one function. */
157 struct bb_info
*bb_graph
;
159 struct bb_info_list
*next
;
162 /* Used to hold information about each line. */
165 gcov_type count
; /* execution count */
166 struct arcdata
*branches
; /* list of branch probabilities for line. */
167 unsigned exists
: 1; /* has code associated with it. */
176 int branches_executed
;
185 /* Holds a list of function basic block graphs. */
187 static struct bb_info_list
*bb_graph_list
= 0;
189 /* Modification time of data files. */
191 static time_t bb_file_time
;
193 /* Name and file pointer of the input file for the basic block graph. */
195 static char *bbg_file_name
;
196 static FILE *bbg_file
;
198 /* Name and file pointer of the input file for the arc count data. */
200 static char *da_file_name
;
201 static FILE *da_file
;
203 /* Name and file pointer of the input file for the basic block line counts. */
205 static char *bb_file_name
;
206 static FILE *bb_file
;
208 /* Holds the entire contents of the bb_file read into memory. */
210 static char *bb_data
;
212 /* Size of bb_data array in longs. */
214 static long bb_data_size
;
216 /* Name of the file mentioned on the command line. */
218 static char *input_file_name
= 0;
220 /* Output branch probabilities if true. */
222 static int output_branch_probs
= 0;
224 /* Output a gcov file if this is true. This is on by default, and can
225 be turned off by the -n option. */
227 static int output_gcov_file
= 1;
229 /* For included files, make the gcov output file name include the name of
230 the input source file. For example, if x.h is included in a.c, then the
231 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
232 when a single source file is specified. */
234 static int output_long_names
= 0;
236 /* Output summary info for each function. */
238 static int output_function_summary
= 0;
240 /* Object directory file prefix. This is the directory/file
241 where .bb and .bbg files are looked for, if nonzero. */
243 static char *object_directory
= 0;
245 /* Preserve all pathname components. Needed when object files and
246 source files are in subdirectories. */
247 static int preserve_paths
= 0;
249 /* Output the number of times a branch was taken as opposed to the percentage
250 of times it was taken. Turned on by the -c option */
252 static int output_branch_counts
= 0;
254 /* Forward declarations. */
255 static void process_args
PARAMS ((int, char **));
256 static void open_files
PARAMS ((void));
257 static void read_files
PARAMS ((void));
258 static void scan_for_source_files
PARAMS ((void));
259 static void output_data
PARAMS ((struct sourcefile
*));
260 static void print_usage
PARAMS ((int)) ATTRIBUTE_NORETURN
;
261 static void print_version
PARAMS ((void)) ATTRIBUTE_NORETURN
;
262 static void init_arc
PARAMS ((struct adj_list
*, int, int, struct bb_info
*));
263 static struct adj_list
*reverse_arcs
PARAMS ((struct adj_list
*));
264 static gcov_type
*read_profile
PARAMS ((char *, long, int));
265 static void create_program_flow_graph
PARAMS ((struct bb_info_list
*));
266 static void solve_program_flow_graph
PARAMS ((struct bb_info_list
*));
267 static void accumulate_branch_counts
PARAMS ((struct coverage
*,
269 static void calculate_branch_probs
PARAMS ((struct bb_info
*,
272 static void function_summary
PARAMS ((struct coverage
*, const char *));
273 static void init_line_info
PARAMS ((struct line_info
*,
274 struct coverage
*, long));
275 static void output_line_info
PARAMS ((FILE *, const struct line_info
*,
276 const struct coverage
*, long));
277 static char *make_gcov_file_name
PARAMS ((char *));
278 static const char *format_hwint
PARAMS ((HOST_WIDEST_INT
, HOST_WIDEST_INT
,
281 extern int main
PARAMS ((int, char **));
288 struct sourcefile
*s_ptr
;
292 process_args (argc
, argv
);
298 scan_for_source_files ();
300 for (s_ptr
= sources
; s_ptr
; s_ptr
= s_ptr
->next
)
306 static void fnotice
PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2
;
308 fnotice
VPARAMS ((FILE *file
, const char *msgid
, ...))
311 VA_FIXEDARG (ap
, FILE *, file
);
312 VA_FIXEDARG (ap
, const char *, msgid
);
314 vfprintf (file
, _(msgid
), ap
);
318 /* More 'friendly' abort that prints the line and file.
319 config.h can #define abort fancy_abort if you like that sort of thing. */
320 extern void fancy_abort
PARAMS ((void)) ATTRIBUTE_NORETURN
;
325 fnotice (stderr
, "Internal gcov abort.\n");
326 exit (FATAL_EXIT_CODE
);
329 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
330 otherwise the output of --help. */
333 print_usage (error_p
)
336 FILE *file
= error_p
? stderr
: stdout
;
337 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
338 fnotice (file
, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
339 fnotice (file
, "Print code coverage information.\n\n");
340 fnotice (file
, " -h, --help Print this help, then exit\n");
341 fnotice (file
, " -v, --version Print version number, then exit\n");
342 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
343 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
344 rather than percentages\n");
345 fnotice (file
, " -n, --no-output Do not create an output file\n");
346 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
348 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
349 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
350 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
351 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
356 /* Print version information and exit. */
361 fnotice (stdout
, "gcov (GCC) %s\n", version_string
);
362 fnotice (stdout
, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
364 "This is free software; see the source for copying conditions. There is NO\n\
365 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
366 exit (SUCCESS_EXIT_CODE
);
369 static const struct option options
[] =
371 { "help", no_argument
, NULL
, 'h' },
372 { "version", no_argument
, NULL
, 'v' },
373 { "branch-probabilities", no_argument
, NULL
, 'b' },
374 { "branch-counts", no_argument
, NULL
, 'c' },
375 { "no-output", no_argument
, NULL
, 'n' },
376 { "long-file-names", no_argument
, NULL
, 'l' },
377 { "function-summaries", no_argument
, NULL
, 'f' },
378 { "preserve-paths", no_argument
, NULL
, 'p' },
379 { "object-directory", required_argument
, NULL
, 'o' },
380 { "object-file", required_argument
, NULL
, 'o' },
383 /* Parse the command line. */
386 process_args (argc
, argv
)
392 while ((opt
= getopt_long (argc
, argv
, "hvbclnfo:p", options
, NULL
)) != -1)
398 /* print_usage will exit. */
401 /* print_version will exit. */
403 output_branch_probs
= 1;
406 output_branch_counts
= 1;
409 output_gcov_file
= 0;
412 output_long_names
= 1;
415 output_function_summary
= 1;
418 object_directory
= optarg
;
425 /* print_usage will exit. */
429 if (optind
!= argc
- 1)
432 input_file_name
= argv
[optind
];
436 /* Find and open the .bb, .da, and .bbg files. If OBJECT_DIRECTORY is
437 not specified, these are looked for in the current directory, and
438 named from the basename of the input_file_name sans extension. If
439 OBJECT_DIRECTORY is specified and is a directory, the files are in
440 that directory, but named from the basename of the input_file_name,
441 sans extension. Otherwise OBJECT_DIRECTORY is taken to be the name
442 of the object *file*, and the data files are named from that. */
449 int length
= strlen (input_file_name
);
452 if (object_directory
&& object_directory
[0])
456 length
+= strlen (object_directory
) + 2;
457 name
= xmalloc (length
);
460 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
461 strcat (name
, object_directory
);
462 if (base
&& name
[strlen (name
) - 1] != '/')
467 name
= xmalloc (length
+ 1);
474 /* Append source file name */
475 cptr
= strrchr (input_file_name
, '/');
476 cptr
= cptr
? cptr
+ 1 : input_file_name
;
480 /* Remove the extension. */
481 cptr
= strrchr (name
, '.');
485 length
= strlen (name
);
486 da_file_name
= xmalloc (length
+ 4);
487 bb_file_name
= xmalloc (length
+ 4);
488 bbg_file_name
= xmalloc (length
+ 5);
490 strcpy (da_file_name
, name
);
491 strcpy (bb_file_name
, name
);
492 strcpy (bbg_file_name
, name
);
493 strcpy (da_file_name
+ length
, ".da");
494 strcpy (bb_file_name
+ length
, ".bb");
495 strcpy (bbg_file_name
+ length
, ".bbg");
497 bb_file
= fopen (bb_file_name
, "rb");
500 fnotice (stderr
, "Could not open basic block file %s.\n", bb_file_name
);
501 exit (FATAL_EXIT_CODE
);
504 bbg_file
= fopen (bbg_file_name
, "rb");
505 if (bbg_file
== NULL
)
507 fnotice (stderr
, "Could not open program flow graph file %s.\n",
509 exit (FATAL_EXIT_CODE
);
515 if (!fstat (fileno (bb_file
), &status
))
516 bb_file_time
= status
.st_mtime
;
519 /* If none of the functions in the file were executed, then there won't
520 be a .da file. Just assume that all counts are zero in this case. */
521 da_file
= fopen (da_file_name
, "rb");
524 fnotice (stderr
, "Could not open data file %s.\n", da_file_name
);
525 fnotice (stderr
, "Assuming that all execution counts are zero.\n");
528 /* Check for empty .bbg file. This indicates that there is no executable
529 code in this source file. */
530 /* Set the EOF condition if at the end of file. */
531 ungetc (getc (bbg_file
), bbg_file
);
534 fnotice (stderr
, "No executable code associated with file %s.\n",
536 exit (FATAL_EXIT_CODE
);
540 /* Initialize a new arc. */
543 init_arc (arcptr
, source
, target
, bb_graph
)
544 struct adj_list
*arcptr
;
546 struct bb_info
*bb_graph
;
548 arcptr
->target
= target
;
549 arcptr
->source
= source
;
551 arcptr
->arc_count
= 0;
552 arcptr
->count_valid
= 0;
555 arcptr
->fall_through
= 0;
557 arcptr
->succ_next
= bb_graph
[source
].succ
;
558 bb_graph
[source
].succ
= arcptr
;
559 bb_graph
[source
].succ_count
++;
561 arcptr
->pred_next
= bb_graph
[target
].pred
;
562 bb_graph
[target
].pred
= arcptr
;
563 bb_graph
[target
].pred_count
++;
566 /* Reverse the arcs on an arc list. */
568 static struct adj_list
*
569 reverse_arcs (arcptr
)
570 struct adj_list
*arcptr
;
572 struct adj_list
*prev
= 0;
573 struct adj_list
*next
;
575 for ( ; arcptr
; arcptr
= next
)
577 next
= arcptr
->succ_next
;
578 arcptr
->succ_next
= prev
;
585 /* Reads profiles from the .da file and compute a hybrid profile. */
588 read_profile (function_name
, cfg_checksum
, instr_arcs
)
596 char *function_name_buffer
;
597 int function_name_buffer_len
;
599 profile
= xmalloc (sizeof (gcov_type
) * instr_arcs
);
600 function_name_buffer_len
= strlen (function_name
) + 1;
601 function_name_buffer
= xmalloc (function_name_buffer_len
+ 1);
603 for (i
= 0; i
< instr_arcs
; i
++)
612 long magic
, extra_bytes
;
616 if (__read_long (&magic
, da_file
, 4) != 0)
625 if (__read_long (&func_count
, da_file
, 4) != 0)
631 if (__read_long (&extra_bytes
, da_file
, 4) != 0)
637 /* skip extra data emited by __bb_exit_func. */
638 fseek (da_file
, extra_bytes
, SEEK_CUR
);
640 for (i
= 0; i
< func_count
; i
++)
646 if (__read_gcov_string
647 (function_name_buffer
, function_name_buffer_len
, da_file
,
654 if (__read_long (&chksum
, da_file
, 4) != 0)
660 if (__read_long (&arc_count
, da_file
, 4) != 0)
666 if (strcmp (function_name_buffer
, function_name
) != 0
667 || arc_count
!= instr_arcs
|| chksum
!= cfg_checksum
)
670 if (fseek (da_file
, arc_count
* 8, SEEK_CUR
) < 0)
680 for (j
= 0; j
< arc_count
; j
++)
681 if (__read_gcov_type (&tmp
, da_file
, 8) != 0)
698 free (function_name_buffer
);
702 fprintf (stderr
, ".da file corrupted!\n");
710 /* Construct the program flow graph from the .bbg file, and read in the data
714 create_program_flow_graph (bptr
)
715 struct bb_info_list
*bptr
;
717 long num_blocks
, number_arcs
, src
, dest
, flag_bits
, num_arcs_per_block
;
719 struct adj_list
*arcptr
;
720 struct bb_info
*bb_graph
;
726 long function_name_len
, tmp
;
728 /* Read function name. */
729 __read_long (&tmp
, bbg_file
, 4); /* ignore -1. */
730 __read_long (&function_name_len
, bbg_file
, 4);
731 function_name
= xmalloc (function_name_len
+ 1);
732 fread (function_name
, 1, function_name_len
+ 1, bbg_file
);
735 tmp
= (function_name_len
+ 1) % 4;
738 fseek (bbg_file
, 4 - tmp
, SEEK_CUR
);
740 __read_long (&tmp
, bbg_file
, 4); /* ignore -1. */
742 /* Read the cfg checksum. */
743 __read_long (&cfg_checksum
, bbg_file
, 4);
745 /* Read the number of blocks. */
746 __read_long (&num_blocks
, bbg_file
, 4);
748 /* Create an array of size bb number of bb_info structs. */
749 bb_graph
= (struct bb_info
*) xcalloc (num_blocks
, sizeof (struct bb_info
));
751 bptr
->bb_graph
= bb_graph
;
752 bptr
->num_blocks
= num_blocks
;
754 /* Read and create each arc from the .bbg file. */
755 __read_long (&number_arcs
, bbg_file
, 4);
756 for (i
= 0; i
< num_blocks
; i
++)
760 __read_long (&num_arcs_per_block
, bbg_file
, 4);
761 for (j
= 0; j
< num_arcs_per_block
; j
++)
763 if (number_arcs
-- < 0)
767 __read_long (&dest
, bbg_file
, 4);
769 arcptr
= (struct adj_list
*) xmalloc (sizeof (struct adj_list
));
770 init_arc (arcptr
, src
, dest
, bb_graph
);
772 __read_long (&flag_bits
, bbg_file
, 4);
777 arcptr
->fake
= !! (flag_bits
& 0x2);
778 arcptr
->fall_through
= !! (flag_bits
& 0x4);
785 /* Read and ignore the -1 separating the arc list from the arc list of the
787 __read_long (&src
, bbg_file
, 4);
791 /* Must reverse the order of all succ arcs, to ensure that they match
792 the order of the data in the .da file. */
794 for (i
= 0; i
< num_blocks
; i
++)
795 if (bb_graph
[i
].succ
)
796 bb_graph
[i
].succ
= reverse_arcs (bb_graph
[i
].succ
);
798 /* Read profile from the .da file. */
800 profile
= read_profile (function_name
, cfg_checksum
, instr_arcs
);
802 /* For each arc not on the spanning tree, set its execution count from
805 /* The first count in the .da file is the number of times that the function
806 was entered. This is the exec_count for block zero. */
808 /* This duplicates code in branch_prob in profile.c. */
810 for (i
= 0; i
< num_blocks
; i
++)
811 for (arcptr
= bb_graph
[i
].succ
; arcptr
; arcptr
= arcptr
->succ_next
)
812 if (! arcptr
->on_tree
)
814 arcptr
->arc_count
= profile
[profile_pos
++];
815 arcptr
->count_valid
= 1;
816 bb_graph
[i
].succ_count
--;
817 bb_graph
[arcptr
->target
].pred_count
--;
820 free (function_name
);
824 solve_program_flow_graph (bptr
)
825 struct bb_info_list
*bptr
;
830 struct adj_list
*arcptr
;
831 struct bb_info
*bb_graph
;
834 num_blocks
= bptr
->num_blocks
;
835 bb_graph
= bptr
->bb_graph
;
837 /* For every block in the file,
838 - if every exit/entrance arc has a known count, then set the block count
839 - if the block count is known, and every exit/entrance arc but one has
840 a known execution count, then set the count of the remaining arc
842 As arc counts are set, decrement the succ/pred count, but don't delete
843 the arc, that way we can easily tell when all arcs are known, or only
844 one arc is unknown. */
846 /* The order that the basic blocks are iterated through is important.
847 Since the code that finds spanning trees starts with block 0, low numbered
848 arcs are put on the spanning tree in preference to high numbered arcs.
849 Hence, most instrumented arcs are at the end. Graph solving works much
850 faster if we propagate numbers from the end to the start.
852 This takes an average of slightly more than 3 passes. */
861 for (i
= num_blocks
- 1; i
>= 0; i
--)
863 if (! bb_graph
[i
].count_valid
)
865 if (bb_graph
[i
].succ_count
== 0)
868 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
869 arcptr
= arcptr
->succ_next
)
870 total
+= arcptr
->arc_count
;
871 bb_graph
[i
].exec_count
= total
;
872 bb_graph
[i
].count_valid
= 1;
875 else if (bb_graph
[i
].pred_count
== 0)
878 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
879 arcptr
= arcptr
->pred_next
)
880 total
+= arcptr
->arc_count
;
881 bb_graph
[i
].exec_count
= total
;
882 bb_graph
[i
].count_valid
= 1;
886 if (bb_graph
[i
].count_valid
)
888 if (bb_graph
[i
].succ_count
== 1)
891 /* One of the counts will be invalid, but it is zero,
892 so adding it in also doesn't hurt. */
893 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
894 arcptr
= arcptr
->succ_next
)
895 total
+= arcptr
->arc_count
;
896 /* Calculate count for remaining arc by conservation. */
897 total
= bb_graph
[i
].exec_count
- total
;
898 /* Search for the invalid arc, and set its count. */
899 for (arcptr
= bb_graph
[i
].succ
; arcptr
;
900 arcptr
= arcptr
->succ_next
)
901 if (! arcptr
->count_valid
)
905 arcptr
->count_valid
= 1;
906 arcptr
->arc_count
= total
;
907 bb_graph
[i
].succ_count
--;
909 bb_graph
[arcptr
->target
].pred_count
--;
912 if (bb_graph
[i
].pred_count
== 1)
915 /* One of the counts will be invalid, but it is zero,
916 so adding it in also doesn't hurt. */
917 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
918 arcptr
= arcptr
->pred_next
)
919 total
+= arcptr
->arc_count
;
920 /* Calculate count for remaining arc by conservation. */
921 total
= bb_graph
[i
].exec_count
- total
;
922 /* Search for the invalid arc, and set its count. */
923 for (arcptr
= bb_graph
[i
].pred
; arcptr
;
924 arcptr
= arcptr
->pred_next
)
925 if (! arcptr
->count_valid
)
929 arcptr
->count_valid
= 1;
930 arcptr
->arc_count
= total
;
931 bb_graph
[i
].pred_count
--;
933 bb_graph
[arcptr
->source
].succ_count
--;
940 /* If the graph has been correctly solved, every block will have a
941 succ and pred count of zero. */
942 for (i
= 0; i
< num_blocks
; i
++)
943 if (bb_graph
[i
].succ_count
|| bb_graph
[i
].pred_count
)
952 struct bb_info_list
*list_end
= 0;
953 struct bb_info_list
*b_ptr
;
955 while (! feof (bbg_file
))
957 b_ptr
= (struct bb_info_list
*) xmalloc (sizeof (struct bb_info_list
));
961 list_end
->next
= b_ptr
;
963 bb_graph_list
= b_ptr
;
966 /* Read in the data in the .bbg file and reconstruct the program flow
967 graph for one function. */
968 create_program_flow_graph (b_ptr
);
970 /* Set the EOF condition if at the end of file. */
971 ungetc (getc (bbg_file
), bbg_file
);
974 /* Calculate all of the basic block execution counts and branch
975 taken probabilities. */
977 for (b_ptr
= bb_graph_list
; b_ptr
; b_ptr
= b_ptr
->next
)
978 solve_program_flow_graph (b_ptr
);
980 /* Read in all of the data from the .bb file. This info will be accessed
981 sequentially twice. */
982 stat (bb_file_name
, &buf
);
983 bb_data_size
= buf
.st_size
/ 4;
985 bb_data
= (char *) xmalloc ((unsigned) buf
.st_size
);
986 fread (bb_data
, sizeof (char), buf
.st_size
, bb_file
);
995 /* Scan the data in the .bb file to find all source files referenced,
996 and the largest line number mentioned in each one. */
999 scan_for_source_files ()
1001 struct sourcefile
*s_ptr
= NULL
;
1006 /* Search the bb_data to find:
1007 1) The number of sources files contained herein, and
1008 2) The largest line number for each source file. */
1012 for (count
= 0; count
< bb_data_size
; count
++)
1014 __fetch_long (&line_num
, ptr
, 4);
1018 /* A source file name follows. Check to see if we already have
1019 a sourcefile structure for this file. */
1021 while (s_ptr
&& strcmp (s_ptr
->name
, ptr
))
1022 s_ptr
= s_ptr
->next
;
1026 /* No sourcefile structure for this file name exists, create
1027 a new one, and append it to the front of the sources list. */
1028 s_ptr
= (struct sourcefile
*) xmalloc (sizeof(struct sourcefile
));
1029 s_ptr
->name
= xstrdup (ptr
);
1030 s_ptr
->maxlineno
= 0;
1031 s_ptr
->next
= sources
;
1035 /* Scan past the file name. */
1040 __fetch_long (&delim
, ptr
, 4);
1042 } while (delim
!= line_num
);
1045 else if (line_num
== -2)
1049 /* A function name follows. Ignore it. */
1052 __fetch_long (&delim
, ptr
, 4);
1054 } while (delim
!= line_num
);
1056 /* There will be a zero before the first file name, in which case s_ptr
1057 will still be uninitialized. So, only try to set the maxlineno
1058 field if line_num is nonzero. */
1059 else if (line_num
> 0)
1061 if (s_ptr
->maxlineno
<= line_num
)
1062 s_ptr
->maxlineno
= line_num
+ 1;
1064 else if (line_num
< 0)
1066 /* Don't know what this is, but it's garbage. */
1073 /* Increment totals in FUNCTION according to arc A_PTR. */
1076 accumulate_branch_counts (function
, a_ptr
)
1077 struct coverage
*function
;
1078 struct arcdata
*a_ptr
;
1080 if (a_ptr
->call_insn
)
1084 function
->calls_executed
++;
1088 function
->branches
++;
1090 function
->branches_executed
++;
1092 function
->branches_taken
++;
1096 /* Calculate the branch taken probabilities for all arcs branches at the
1097 end of this block. */
1100 calculate_branch_probs (block_ptr
, line_info
, function
)
1101 struct bb_info
*block_ptr
;
1102 struct line_info
*line_info
;
1103 struct coverage
*function
;
1106 struct adj_list
*arcptr
;
1108 total
= block_ptr
->exec_count
;
1109 for (arcptr
= block_ptr
->succ
; arcptr
; arcptr
= arcptr
->succ_next
)
1111 struct arcdata
*a_ptr
;
1113 /* Ignore fall through arcs as they aren't really branches. */
1114 if (arcptr
->fall_through
)
1117 a_ptr
= (struct arcdata
*) xmalloc (sizeof (struct arcdata
));
1118 a_ptr
->total
= total
;
1119 a_ptr
->hits
= total
? arcptr
->arc_count
: 0;
1120 a_ptr
->call_insn
= arcptr
->fake
;
1123 accumulate_branch_counts (function
, a_ptr
);
1124 /* Prepend the new branch to the list. */
1125 a_ptr
->next
= line_info
->branches
;
1126 line_info
->branches
= a_ptr
;
1130 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1131 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1132 If DP is zero, no decimal point is printed. Only print 100% when
1133 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1134 format TOP. Return pointer to a static string. */
1137 format_hwint (top
, bottom
, dp
)
1138 HOST_WIDEST_INT top
, bottom
;
1141 static char buffer
[20];
1145 float ratio
= bottom
? (float)top
/ bottom
: 0;
1147 unsigned limit
= 100;
1150 for (ix
= dp
; ix
--; )
1153 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1154 if (percent
<= 0 && top
)
1156 else if (percent
>= limit
&& top
!= bottom
)
1157 percent
= limit
- 1;
1158 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1164 buffer
[ix
+1] = buffer
[ix
];
1168 buffer
[ix
+ 1] = '.';
1172 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, top
);
1178 /* Output summary info for a function. */
1181 function_summary (function
, title
)
1182 struct coverage
*function
;
1185 if (function
->lines
)
1186 fnotice (stdout
, "%s of %d lines executed in %s %s\n",
1187 format_hwint (function
->lines_executed
,
1188 function
->lines
, 2),
1189 function
->lines
, title
, function
->name
);
1191 fnotice (stdout
, "No executable lines in %s %s\n",
1192 title
, function
->name
);
1194 if (output_branch_probs
)
1196 if (function
->branches
)
1198 fnotice (stdout
, "%s of %d branches executed in %s %s\n",
1199 format_hwint (function
->branches_executed
,
1200 function
->branches
, 2),
1201 function
->branches
, title
, function
->name
);
1203 "%s of %d branches taken at least once in %s %s\n",
1204 format_hwint (function
->branches_taken
,
1205 function
->branches
, 2),
1206 function
->branches
, title
, function
->name
);
1209 fnotice (stdout
, "No branches in %s %s\n", title
, function
->name
);
1210 if (function
->calls
)
1211 fnotice (stdout
, "%s of %d calls executed in %s %s\n",
1212 format_hwint (function
->calls_executed
,
1213 function
->calls
, 2),
1214 function
->calls
, title
, function
->name
);
1216 fnotice (stdout
, "No calls in %s %s\n", title
, function
->name
);
1220 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1221 affect name generation. With preserve_paths we create a filename
1222 from all path components of the source file, replacing '/' with
1223 '#', without it we simply take the basename component. With
1224 long_output_names we prepend the processed name of the input file
1225 to each output name (except when the current source file is the
1226 input file, so you don't get a double concatenation). The two
1227 components are separated by '##'. Also '.' filename components are
1228 removed and '..' components are renamed to '^'. */
1231 make_gcov_file_name (src_name
)
1235 char *name
= xmalloc (strlen (src_name
) + strlen (input_file_name
) + 10);
1238 if (output_long_names
&& strcmp (src_name
, input_file_name
))
1240 /* Generate the input filename part. */
1241 cptr
= preserve_paths
? NULL
: strrchr (input_file_name
, '/');
1242 cptr
= cptr
? cptr
+ 1 : input_file_name
;
1243 strcat (name
, cptr
);
1244 strcat (name
, "##");
1247 /* Generate the source filename part. */
1248 cptr
= preserve_paths
? NULL
: strrchr (src_name
, '/');
1249 cptr
= cptr
? cptr
+ 1 : src_name
;
1250 strcat (name
, cptr
);
1254 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1257 for (cptr
= name
; (cptr
= strchr ((prev
= cptr
), '/'));)
1261 if (prev
+ 1 == cptr
&& prev
[0] == '.')
1266 else if (prev
+ 2 == cptr
&& prev
[0] == '.' && prev
[1] == '.')
1278 prev
[0] = prev
[shift
];
1284 /* Don't strip off the ending for compatibility with tcov, since
1285 this results in confusion if there is more than one file with the
1286 same basename, e.g. tmp.c and tmp.h. */
1287 strcat (name
, ".gcov");
1291 /* Scan through the bb_data, and when the file name matches the
1292 source file name, then for each following line number, increment
1293 the line number execution count indicated by the execution count of
1294 the appropriate basic block. */
1297 init_line_info (line_info
, total
, maxlineno
)
1298 struct line_info
*line_info
;
1299 struct coverage
*total
;
1302 long block_num
= 0; /* current block number */
1303 struct bb_info
*block_ptr
= NULL
; /* current block ptr */
1304 struct coverage function
;
1305 struct coverage
*func_ptr
= NULL
;
1306 struct bb_info_list
*current_graph
= NULL
; /* Graph for current function. */
1307 int is_this_file
= 0; /* We're scanning a block from the desired file. */
1308 char *ptr
= bb_data
;
1311 struct line_info
*line_ptr
= 0; /* line info ptr. */
1313 memset (&function
, 0, sizeof (function
));
1314 if (output_function_summary
)
1315 func_ptr
= &function
;
1317 for (count
= 0; count
< bb_data_size
; count
++)
1319 __fetch_long (&line_num
, ptr
, 4);
1327 /* Marks the beginning of a file name. Check to see
1328 whether this is the filename we are currently
1329 collecting data for. */
1330 is_this_file
= !strcmp (total
->name
, ptr
);
1332 else if (line_num
== -2)
1334 /* Marks the start of a new function. Advance to the
1335 next program flow graph. */
1337 current_graph
= bb_graph_list
;
1340 if (block_num
== current_graph
->num_blocks
- 1)
1341 /* Last block falls through to exit. */
1343 else if (block_num
== current_graph
->num_blocks
- 2)
1345 if (output_branch_probs
&& is_this_file
)
1346 calculate_branch_probs (block_ptr
, line_ptr
, func_ptr
);
1351 "didn't use all bb entries of graph, function %s\n",
1353 fnotice (stderr
, "block_num = %ld, num_blocks = %d\n",
1354 block_num
, current_graph
->num_blocks
);
1356 if (func_ptr
&& is_this_file
)
1357 function_summary (func_ptr
, "function");
1358 current_graph
= current_graph
->next
;
1361 block_ptr
= current_graph
->bb_graph
;
1362 memset (&function
, 0, sizeof (function
));
1363 function
.name
= ptr
;
1367 fnotice (stderr
, "ERROR: unexpected line number %ld\n", line_num
);
1371 /* Scan past the string. */
1372 for (delim
= 0; delim
!= line_num
; count
++)
1374 __fetch_long (&delim
, ptr
, 4);
1380 /* Marks the end of a block. */
1381 if (block_num
>= current_graph
->num_blocks
)
1383 fnotice (stderr
, "ERROR: too many basic blocks in function %s\n",
1388 if (output_branch_probs
&& is_this_file
)
1389 calculate_branch_probs (block_ptr
, line_ptr
, func_ptr
);
1394 else if (is_this_file
)
1396 if (line_num
>= maxlineno
)
1398 fnotice (stderr
, "ERROR: out of range line number in function %s\n",
1403 line_ptr
= &line_info
[line_num
];
1406 if (!line_ptr
->exists
)
1408 if (!line_ptr
->count
&& block_ptr
->exec_count
)
1409 func_ptr
->lines_executed
++;
1412 /* Accumulate execution data for this line number. */
1413 line_ptr
->count
+= block_ptr
->exec_count
;
1414 line_ptr
->exists
= 1;
1418 if (func_ptr
&& is_this_file
)
1419 function_summary (func_ptr
, "function");
1421 /* Calculate summary test coverage statistics. */
1422 for (line_num
= 1, line_ptr
= &line_info
[line_num
];
1423 line_num
< maxlineno
; line_num
++, line_ptr
++)
1425 struct arcdata
*a_ptr
, *prev
, *next
;
1427 if (line_ptr
->exists
)
1430 if (line_ptr
->count
)
1431 total
->lines_executed
++;
1434 /* Total and reverse the branch information. */
1435 for (a_ptr
= line_ptr
->branches
, prev
= NULL
; a_ptr
; a_ptr
= next
)
1441 accumulate_branch_counts (total
, a_ptr
);
1443 line_ptr
->branches
= prev
;
1447 /* Read in the source file one line at a time, and output that line to
1448 the gcov file preceded by its execution count and other
1452 output_line_info (gcov_file
, line_info
, total
, maxlineno
)
1454 const struct line_info
*line_info
;
1455 const struct coverage
*total
;
1459 long line_num
; /* current line number */
1460 const struct line_info
*line_ptr
; /* current line info ptr. */
1461 char string
[STRING_SIZE
]; /* line buffer. */
1462 char const *retval
= ""; /* status of source file reading. */
1464 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, total
->name
);
1465 fprintf (gcov_file
, "%9s:%5d:Object:%s\n", "-", 0, bb_file_name
);
1467 source_file
= fopen (total
->name
, "r");
1470 fnotice (stderr
, "Could not open source file %s.\n", total
->name
);
1477 if (!fstat (fileno (source_file
), &status
)
1478 && status
.st_mtime
> bb_file_time
)
1480 fnotice (stderr
, "Warning: source file %s is newer than %s\n",
1481 total
->name
, bb_file_name
);
1482 fprintf (gcov_file
, "%9s:%5d:Source is newer than compiler output\n",
1487 for (line_num
= 1, line_ptr
= &line_info
[line_num
];
1488 line_num
< maxlineno
; line_num
++, line_ptr
++)
1490 /* For lines which don't exist in the .bb file, print '-' before
1491 the source line. For lines which exist but were never
1492 executed, print '#####' before the source line. Otherwise,
1493 print the execution count before the source line. There are
1494 16 spaces of indentation added before the source line so that
1495 tabs won't be messed up. */
1496 fprintf (gcov_file
, "%9s:%5ld:",
1497 !line_ptr
->exists
? "-"
1498 : !line_ptr
->count
? "#####"
1499 : format_hwint (line_ptr
->count
, 0, -1), line_num
);
1503 /* Copy source line. */
1506 retval
= fgets (string
, STRING_SIZE
, source_file
);
1510 "Unexpected EOF while reading source file %s.\n",
1514 fputs (retval
, gcov_file
);
1516 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
1519 fputs ("??\n", gcov_file
);
1521 if (output_branch_probs
)
1524 struct arcdata
*a_ptr
;
1526 for (i
= 0, a_ptr
= line_ptr
->branches
; a_ptr
;
1527 a_ptr
= a_ptr
->next
, i
++)
1529 if (a_ptr
->call_insn
)
1531 if (a_ptr
->total
== 0)
1532 fnotice (gcov_file
, "call %2d never executed\n", i
);
1535 (gcov_file
, "call %2d returns %s\n", i
,
1536 format_hwint (a_ptr
->total
- a_ptr
->hits
,
1538 -output_branch_counts
));
1542 if (a_ptr
->total
== 0)
1543 fnotice (gcov_file
, "branch %2d never executed\n", i
);
1546 (gcov_file
, "branch %2d taken %s\n", i
,
1547 format_hwint (a_ptr
->hits
, a_ptr
->total
,
1548 -output_branch_counts
));
1554 /* Handle all remaining source lines. There may be lines after the
1555 last line of code. */
1558 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
1560 fprintf (gcov_file
, "%9s:%5ld:%s", "-", line_num
, retval
);
1562 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
1564 retval
= fgets (string
, STRING_SIZE
, source_file
);
1567 fputs (retval
, gcov_file
);
1573 fclose (source_file
);
1576 /* Calculate line execution counts, and output a .gcov file for source
1577 file S_PTR. Allocate an array big enough to hold a count for each
1578 line. Scan through the bb_data, and when the file name matches the
1579 current file name, then for each following line number, increment
1580 the line number execution count indicated by the execution count of
1581 the appropriate basic block. */
1585 struct sourcefile
*s_ptr
;
1587 struct line_info
*line_info
/* line info data */
1588 = (struct line_info
*) xcalloc (s_ptr
->maxlineno
,
1589 sizeof (struct line_info
));
1591 struct coverage total
;
1593 memset (&total
, 0, sizeof (total
));
1594 total
.name
= s_ptr
->name
;
1596 init_line_info (line_info
, &total
, s_ptr
->maxlineno
);
1597 function_summary (&total
, "file");
1599 if (output_gcov_file
)
1601 /* Now the statistics are ready. Read in the source file one
1602 line at a time, and output that line to the gcov file
1603 preceded by its execution information. */
1605 char *gcov_file_name
= make_gcov_file_name (total
.name
);
1606 FILE *gcov_file
= fopen (gcov_file_name
, "w");
1610 fnotice (stdout
, "Creating %s.\n", gcov_file_name
);
1611 output_line_info (gcov_file
, line_info
, &total
, s_ptr
->maxlineno
);
1612 if (ferror (gcov_file
))
1613 fnotice (stderr
, "Error writing output file %s.\n",
1618 fnotice (stderr
, "Could not open output file %s.\n", gcov_file_name
);
1619 free (gcov_file_name
);
1623 for (line_num
= 1; line_num
!= s_ptr
->maxlineno
; line_num
++)
1625 struct arcdata
*branch
, *next
;
1627 for (branch
= line_info
[line_num
].branches
; branch
; branch
= next
)
1629 next
= branch
->next
;