1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 91-94, 96, 97, 98, 1999 Free Software Foundation, Inc.
4 Contributed by James E. Wilson of Cygnus Support.
5 Mangled 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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* ??? The code in final.c that produces the struct bb assumes that there is
23 no padding between the fields. This is not necessary true. The current
24 code can only be trusted if longs and pointers are the same size. */
26 /* ??? No need to print an execution count on every line, could just print
27 it on the first line of each block, and only print it on a subsequent
28 line in the same block if the count changes. */
30 /* ??? Print a list of the ten blocks with the highest execution counts,
31 and list the line numbers corresponding to those blocks. Also, perhaps
32 list the line numbers with the highest execution counts, only printing
33 the first if there are several which are all listed in the same block. */
35 /* ??? Should have an option to print the number of basic blocks, and the
36 percent of them that are covered. */
38 /* ??? Does not correctly handle the case where two .bb files refer to the
39 same included source file. For example, if one has a short file containing
40 only inline functions, which is then included in two other files, then
41 there will be two .bb files which refer to the include file, but there
42 is no way to get the total execution counts for the included file, can
43 only get execution counts for one or the other of the including files. */
51 /* The .bb file format consists of several lists of 4-byte integers
52 which are the line numbers of each basic block in the file. Each
53 list is terminated by a zero. These lists correspond to the basic
54 blocks in the reconstructed program flow graph.
56 A line number of -1 indicates that a source file name (padded to a
57 long boundary) follows. The padded file name is followed by
58 another -1 to make it easy to scan past file names. A -2 indicates
59 that a function name (padded to a long boundary) follows; the name
60 is followed by another -2 to make it easy to scan past the function
63 The .bbg file contains enough info to enable gcov to reconstruct the
64 program flow graph. The first word is the number of basic blocks,
65 the second word is the number of arcs, followed by the list of arcs
66 (source bb, dest bb pairs), then a -1, then the number of instrumented
67 arcs followed by the instrumented arcs, followed by another -1. This
68 is repeated for each function.
70 The .da file contains the execution count for each instrumented branch.
72 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
73 and the .da files are created when an executable compiled with
74 -fprofile-arcs is run. */
76 /* The functions in this file for creating and solution program flow graphs
77 are very similar to functions in the gcc source file profile.c. */
79 char gcov_version_string[] = "GNU gcov version 1.5\n";
81 /* This is the size of the buffer used to read in source file lines. */
83 #define STRING_SIZE 200
85 /* One copy of this structure is created for each source file mentioned in the
92 struct sourcefile *next;
95 /* This points to the head of the sourcefile structure list. */
97 struct sourcefile *sources;
99 /* One of these is dynamically created whenever we identify an arc in the
106 unsigned int count_valid : 1;
107 unsigned int on_tree : 1;
108 unsigned int fake : 1;
109 unsigned int fall_through : 1;
111 /* Not needed for gcov, but defined in profile.c. */
114 struct adj_list *pred_next;
115 struct adj_list *succ_next;
118 /* Count the number of basic blocks, and create an array of these structures,
119 one for each bb in the function. */
122 struct adj_list *succ;
123 struct adj_list *pred;
127 unsigned int count_valid : 1;
128 unsigned int on_tree : 1;
130 /* Not needed for gcov, but defined in profile.c. */
135 /* When outputting branch probabilities, one of these structures is created
136 for each branch/call. */
142 struct arcdata *next;
145 /* Used to save the list of bb_graphs, one per function. */
147 struct bb_info_list {
148 /* Indexed by block number, holds the basic block graph for one function. */
149 struct bb_info *bb_graph;
151 struct bb_info_list *next;
154 /* Holds a list of function basic block graphs. */
156 static struct bb_info_list *bb_graph_list = 0;
158 /* Name and file pointer of the input file for the basic block graph. */
160 static char *bbg_file_name;
161 static FILE *bbg_file;
163 /* Name and file pointer of the input file for the arc count data. */
165 static char *da_file_name;
166 static FILE *da_file;
168 /* Name and file pointer of the input file for the basic block line counts. */
170 static char *bb_file_name;
171 static FILE *bb_file;
173 /* Holds the entire contents of the bb_file read into memory. */
175 static char *bb_data;
177 /* Size of bb_data array in longs. */
179 static long bb_data_size;
181 /* Name and file pointer of the output file. */
183 static char *gcov_file_name;
184 static FILE *gcov_file;
186 /* Name of the file mentioned on the command line. */
188 static char *input_file_name = 0;
190 /* Output branch probabilities if true. */
192 static int output_branch_probs = 0;
194 /* Output a gcov file if this is true. This is on by default, and can
195 be turned off by the -n option. */
197 static int output_gcov_file = 1;
199 /* For included files, make the gcov output file name include the name of
200 the input source file. For example, if x.h is included in a.c, then the
201 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
202 when a single source file is specified. */
204 static int output_long_names = 0;
206 /* Output summary info for each function. */
208 static int output_function_summary = 0;
210 /* Object directory file prefix. This is the directory where .bb and .bbg
211 files are looked for, if non-zero. */
213 static char *object_directory = 0;
215 /* Forward declarations. */
216 static void process_args PROTO ((int, char **));
217 static void open_files PROTO ((void));
218 static void read_files PROTO ((void));
219 static void scan_for_source_files PROTO ((void));
220 static void output_data PROTO ((void));
221 static void print_usage PROTO ((void)) ATTRIBUTE_NORETURN;
228 #ifdef HAVE_LC_MESSAGES
229 setlocale (LC_MESSAGES, "");
231 bindtextdomain (PACKAGE, localedir);
232 textdomain (PACKAGE);
234 process_args (argc, argv);
240 scan_for_source_files ();
247 static void fnotice PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
249 fnotice VPROTO ((const char *msgid, ...))
251 #ifndef ANSI_PROTOTYPES
256 VA_START (ap, msgid);
258 #ifndef ANSI_PROTOTYPES
259 msgid = va_arg (ap, const char *);
262 vfprintf (stderr, _(msgid), ap);
271 register PTR value = (PTR) malloc (size);
274 fnotice (stderr, "error: virtual memory exhausted");
275 exit (FATAL_EXIT_CODE);
280 /* More 'friendly' abort that prints the line and file.
281 config.h can #define abort fancy_abort if you like that sort of thing. */
286 fnotice (stderr, "Internal gcc abort.\n");
287 exit (FATAL_EXIT_CODE);
290 /* Print a usage message and exit. */
295 fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
296 exit (FATAL_EXIT_CODE);
299 /* Parse the command line. */
302 process_args (argc, argv)
308 for (i = 1; i < argc; i++)
310 if (argv[i][0] == '-')
312 if (argv[i][1] == 'b')
313 output_branch_probs = 1;
314 else if (argv[i][1] == 'v')
315 fputs (gcov_version_string, stderr);
316 else if (argv[i][1] == 'n')
317 output_gcov_file = 0;
318 else if (argv[i][1] == 'l')
319 output_long_names = 1;
320 else if (argv[i][1] == 'f')
321 output_function_summary = 1;
322 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
323 object_directory = argv[++i];
327 else if (! input_file_name)
328 input_file_name = argv[i];
333 if (! input_file_name)
338 /* Find and open the .bb, .da, and .bbg files. */
343 int count, objdir_count;
346 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
347 extension, if any, and append the new extensions. */
348 count = strlen (input_file_name);
349 if (object_directory)
350 objdir_count = strlen (object_directory);
354 da_file_name = xmalloc (count + objdir_count + 4);
355 bb_file_name = xmalloc (count + objdir_count + 4);
356 bbg_file_name = xmalloc (count + objdir_count + 5);
358 if (object_directory)
360 strcpy (da_file_name, object_directory);
361 strcpy (bb_file_name, object_directory);
362 strcpy (bbg_file_name, object_directory);
364 if (object_directory[objdir_count - 1] != '/')
366 strcat (da_file_name, "/");
367 strcat (bb_file_name, "/");
368 strcat (bbg_file_name, "/");
371 cptr = rindex (input_file_name, '/');
374 strcat (da_file_name, cptr + 1);
375 strcat (bb_file_name, cptr + 1);
376 strcat (bbg_file_name, cptr + 1);
380 strcat (da_file_name, input_file_name);
381 strcat (bb_file_name, input_file_name);
382 strcat (bbg_file_name, input_file_name);
387 strcpy (da_file_name, input_file_name);
388 strcpy (bb_file_name, input_file_name);
389 strcpy (bbg_file_name, input_file_name);
392 cptr = rindex (bb_file_name, '.');
394 strcpy (cptr, ".bb");
396 strcat (bb_file_name, ".bb");
398 cptr = rindex (da_file_name, '.');
400 strcpy (cptr, ".da");
402 strcat (da_file_name, ".da");
404 cptr = rindex (bbg_file_name, '.');
406 strcpy (cptr, ".bbg");
408 strcat (bbg_file_name, ".bbg");
410 bb_file = fopen (bb_file_name, "r");
413 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
414 exit (FATAL_EXIT_CODE);
417 /* If none of the functions in the file were executed, then there won't
418 be a .da file. Just assume that all counts are zero in this case. */
419 da_file = fopen (da_file_name, "r");
422 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
423 fnotice (stderr, "Assuming that all execution counts are zero.\n");
426 bbg_file = fopen (bbg_file_name, "r");
427 if (bbg_file == NULL)
429 fnotice (stderr, "Could not open program flow graph file %s.\n",
431 exit (FATAL_EXIT_CODE);
434 /* Check for empty .bbg file. This indicates that there is no executable
435 code in this source file. */
436 /* Set the EOF condition if at the end of file. */
437 ungetc (getc (bbg_file), bbg_file);
440 fnotice (stderr, "No executable code associated with file %s.\n",
442 exit (FATAL_EXIT_CODE);
446 /* Initialize a new arc. */
449 init_arc (arcptr, source, target, bb_graph)
450 struct adj_list *arcptr;
452 struct bb_info *bb_graph;
454 arcptr->target = target;
455 arcptr->source = source;
457 arcptr->arc_count = 0;
458 arcptr->count_valid = 0;
461 arcptr->fall_through = 0;
463 arcptr->succ_next = bb_graph[source].succ;
464 bb_graph[source].succ = arcptr;
465 bb_graph[source].succ_count++;
467 arcptr->pred_next = bb_graph[target].pred;
468 bb_graph[target].pred = arcptr;
469 bb_graph[target].pred_count++;
473 /* Reverse the arcs on a arc list. */
475 static struct adj_list *
476 reverse_arcs (arcptr)
477 struct adj_list *arcptr;
479 struct adj_list *prev = 0;
480 struct adj_list *next;
482 for ( ; arcptr; arcptr = next)
484 next = arcptr->succ_next;
485 arcptr->succ_next = prev;
493 /* Construct the program flow graph from the .bbg file, and read in the data
497 create_program_flow_graph (bptr)
498 struct bb_info_list *bptr;
500 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
502 struct adj_list *arcptr;
503 struct bb_info *bb_graph;
505 /* Read the number of blocks. */
506 __read_long (&num_blocks, bbg_file, 4);
508 /* Create an array of size bb number of bb_info structs. Bzero it. */
509 bb_graph = (struct bb_info *) xmalloc (num_blocks
510 * sizeof (struct bb_info));
511 bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
513 bptr->bb_graph = bb_graph;
514 bptr->num_blocks = num_blocks;
516 /* Read and create each arc from the .bbg file. */
517 __read_long (&number_arcs, bbg_file, 4);
518 for (i = 0; i < num_blocks; i++)
522 __read_long (&num_arcs_per_block, bbg_file, 4);
523 for (j = 0; j < num_arcs_per_block; j++)
525 if (number_arcs-- < 0)
529 __read_long (&dest, bbg_file, 4);
531 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
532 init_arc (arcptr, src, dest, bb_graph);
534 __read_long (&flag_bits, bbg_file, 4);
535 arcptr->on_tree = flag_bits & 0x1;
536 arcptr->fake = !! (flag_bits & 0x2);
537 arcptr->fall_through = !! (flag_bits & 0x4);
544 /* Read and ignore the -1 separating the arc list from the arc list of the
546 __read_long (&src, bbg_file, 4);
550 /* Must reverse the order of all succ arcs, to ensure that they match
551 the order of the data in the .da file. */
553 for (i = 0; i < num_blocks; i++)
554 if (bb_graph[i].succ)
555 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
557 /* For each arc not on the spanning tree, set its execution count from
560 /* The first count in the .da file is the number of times that the function
561 was entered. This is the exec_count for block zero. */
563 /* This duplicates code in branch_prob in profile.c. */
565 for (i = 0; i < num_blocks; i++)
566 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
567 if (! arcptr->on_tree)
570 if (da_file && __read_long (&tmp_count, da_file, 8))
573 arcptr->arc_count = tmp_count;
574 arcptr->count_valid = 1;
575 bb_graph[i].succ_count--;
576 bb_graph[arcptr->target].pred_count--;
581 solve_program_flow_graph (bptr)
582 struct bb_info_list *bptr;
584 int passes, changes, total;
586 struct adj_list *arcptr;
587 struct bb_info *bb_graph;
590 num_blocks = bptr->num_blocks;
591 bb_graph = bptr->bb_graph;
593 /* For every block in the file,
594 - if every exit/entrance arc has a known count, then set the block count
595 - if the block count is known, and every exit/entrance arc but one has
596 a known execution count, then set the count of the remaining arc
598 As arc counts are set, decrement the succ/pred count, but don't delete
599 the arc, that way we can easily tell when all arcs are known, or only
600 one arc is unknown. */
602 /* The order that the basic blocks are iterated through is important.
603 Since the code that finds spanning trees starts with block 0, low numbered
604 arcs are put on the spanning tree in preference to high numbered arcs.
605 Hence, most instrumented arcs are at the end. Graph solving works much
606 faster if we propagate numbers from the end to the start.
608 This takes an average of slightly more than 3 passes. */
617 for (i = num_blocks - 1; i >= 0; i--)
619 if (! bb_graph[i].count_valid)
621 if (bb_graph[i].succ_count == 0)
624 for (arcptr = bb_graph[i].succ; arcptr;
625 arcptr = arcptr->succ_next)
626 total += arcptr->arc_count;
627 bb_graph[i].exec_count = total;
628 bb_graph[i].count_valid = 1;
631 else if (bb_graph[i].pred_count == 0)
634 for (arcptr = bb_graph[i].pred; arcptr;
635 arcptr = arcptr->pred_next)
636 total += arcptr->arc_count;
637 bb_graph[i].exec_count = total;
638 bb_graph[i].count_valid = 1;
642 if (bb_graph[i].count_valid)
644 if (bb_graph[i].succ_count == 1)
647 /* One of the counts will be invalid, but it is zero,
648 so adding it in also doesn't hurt. */
649 for (arcptr = bb_graph[i].succ; arcptr;
650 arcptr = arcptr->succ_next)
651 total += arcptr->arc_count;
652 /* Calculate count for remaining arc by conservation. */
653 total = bb_graph[i].exec_count - total;
654 /* Search for the invalid arc, and set its count. */
655 for (arcptr = bb_graph[i].succ; arcptr;
656 arcptr = arcptr->succ_next)
657 if (! arcptr->count_valid)
661 arcptr->count_valid = 1;
662 arcptr->arc_count = total;
663 bb_graph[i].succ_count--;
665 bb_graph[arcptr->target].pred_count--;
668 if (bb_graph[i].pred_count == 1)
671 /* One of the counts will be invalid, but it is zero,
672 so adding it in also doesn't hurt. */
673 for (arcptr = bb_graph[i].pred; arcptr;
674 arcptr = arcptr->pred_next)
675 total += arcptr->arc_count;
676 /* Calculate count for remaining arc by conservation. */
677 total = bb_graph[i].exec_count - total;
678 /* Search for the invalid arc, and set its count. */
679 for (arcptr = bb_graph[i].pred; arcptr;
680 arcptr = arcptr->pred_next)
681 if (! arcptr->count_valid)
685 arcptr->count_valid = 1;
686 arcptr->arc_count = total;
687 bb_graph[i].pred_count--;
689 bb_graph[arcptr->source].succ_count--;
696 /* If the graph has been correctly solved, every block will have a
697 succ and pred count of zero. */
698 for (i = 0; i < num_blocks; i++)
699 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
708 struct bb_info_list *list_end = 0;
709 struct bb_info_list *b_ptr;
712 /* Read and ignore the first word of the .da file, which is the count of
713 how many numbers follow. */
714 if (da_file && __read_long (&total, da_file, 8))
717 while (! feof (bbg_file))
719 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
723 list_end->next = b_ptr;
725 bb_graph_list = b_ptr;
728 /* Read in the data in the .bbg file and reconstruct the program flow
729 graph for one function. */
730 create_program_flow_graph (b_ptr);
732 /* Set the EOF condition if at the end of file. */
733 ungetc (getc (bbg_file), bbg_file);
736 /* Check to make sure the .da file data is valid. */
741 fnotice (stderr, ".da file contents exhausted too early\n");
742 /* Should be at end of file now. */
743 if (__read_long (&total, da_file, 8) == 0)
744 fnotice (stderr, ".da file contents not exhausted\n");
747 /* Calculate all of the basic block execution counts and branch
748 taken probabilities. */
750 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
751 solve_program_flow_graph (b_ptr);
753 /* Read in all of the data from the .bb file. This info will be accessed
754 sequentially twice. */
755 stat (bb_file_name, &buf);
756 bb_data_size = buf.st_size / 4;
758 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
759 fread (bb_data, sizeof (char), buf.st_size, bb_file);
768 /* Scan the data in the .bb file to find all source files referenced,
769 and the largest line number mentioned in each one. */
772 scan_for_source_files ()
774 struct sourcefile *s_ptr = NULL;
779 /* Search the bb_data to find:
780 1) The number of sources files contained herein, and
781 2) The largest line number for each source file. */
785 for (count = 0; count < bb_data_size; count++)
787 __fetch_long (&line_num, ptr, 4);
791 /* A source file name follows. Check to see if we already have
792 a sourcefile structure for this file. */
794 while (s_ptr && strcmp (s_ptr->name, ptr))
799 /* No sourcefile structure for this file name exists, create
800 a new one, and append it to the front of the sources list. */
801 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
802 s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
803 strcpy (s_ptr->name, (char *) ptr);
804 s_ptr->maxlineno = 0;
805 s_ptr->next = sources;
809 /* Scan past the file name. */
814 __fetch_long (&delim, ptr, 4);
816 } while (delim != line_num);
819 else if (line_num == -2)
823 /* A function name follows. Ignore it. */
826 __fetch_long (&delim, ptr, 4);
828 } while (delim != line_num);
830 /* There will be a zero before the first file name, in which case s_ptr
831 will still be uninitialized. So, only try to set the maxlineno
832 field if line_num is non-zero. */
833 else if (line_num > 0)
835 if (s_ptr->maxlineno <= line_num)
836 s_ptr->maxlineno = line_num + 1;
838 else if (line_num < 0)
840 /* Don't know what this is, but it's garbage. */
846 /* For calculating coverage at the function level. */
848 static int function_source_lines;
849 static int function_source_lines_executed;
850 static int function_branches;
851 static int function_branches_executed;
852 static int function_branches_taken;
853 static int function_calls;
854 static int function_calls_executed;
855 static char *function_name;
857 /* Calculate the branch taken probabilities for all arcs branches at the
858 end of this block. */
861 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
862 struct bb_info_list *current_graph;
864 struct arcdata **branch_probs;
868 struct adj_list *arcptr;
869 struct arcdata *end_ptr, *a_ptr;
871 total = current_graph->bb_graph[block_num].exec_count;
872 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
873 arcptr = arcptr->succ_next)
875 /* Ignore fall through arcs as they aren't really branches. */
877 if (arcptr->fall_through)
880 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
884 a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
885 a_ptr->call_insn = arcptr->fake;
887 if (output_function_summary)
889 if (a_ptr->call_insn)
892 if (a_ptr->prob != -1)
893 function_calls_executed++;
898 if (a_ptr->prob != -1)
899 function_branches_executed++;
901 function_branches_taken++;
905 /* Append the new branch to the end of the list. */
907 if (! branch_probs[last_line_num])
908 branch_probs[last_line_num] = a_ptr;
911 end_ptr = branch_probs[last_line_num];
912 while (end_ptr->next != 0)
913 end_ptr = end_ptr->next;
914 end_ptr->next = a_ptr;
919 /* Output summary info for a function. */
924 if (function_source_lines)
925 fnotice (stdout, "%6.2lf%% of %d source lines executed in function %s\n",
926 (((double) function_source_lines_executed / function_source_lines)
927 * 100), function_source_lines, function_name);
929 fnotice (stdout, "No executable source lines in function %s\n",
932 if (output_branch_probs)
934 if (function_branches)
936 fnotice (stdout, "%6.2lf%% of %d branches executed in function %s\n",
937 (((double) function_branches_executed / function_branches)
938 * 100), function_branches, function_name);
940 "%6.2lf%% of %d branches taken at least once in function %s\n",
941 (((double) function_branches_taken / function_branches)
942 * 100), function_branches, function_name);
945 fnotice (stdout, "No branches in function %s\n", function_name);
947 fnotice (stdout, "%6.2lf%% of %d calls executed in function %s\n",
948 (((double) function_calls_executed / function_calls)
949 * 100), function_calls, function_name);
951 fnotice (stdout, "No calls in function %s\n", function_name);
955 /* Calculate line execution counts, and output the data to a .tcov file. */
960 /* When scanning data, this is true only if the data applies to the
961 current source file. */
963 /* An array indexed by line number which indicates how many times that line
966 /* An array indexed by line number which indicates whether the line was
967 present in the bb file (i.e. whether it had code associate with it).
968 Lines never executed are those which both exist, and have zero execution
971 /* An array indexed by line number, which contains a list of branch
972 probabilities, one for each branch on that line. */
973 struct arcdata **branch_probs = NULL;
974 struct sourcefile *s_ptr;
975 char *source_file_name;
977 struct bb_info_list *current_graph;
982 long last_line_num = 0;
984 struct arcdata *a_ptr;
985 /* Buffer used for reading in lines from the source file. */
986 char string[STRING_SIZE];
987 /* For calculating coverage at the file level. */
988 int total_source_lines;
989 int total_source_lines_executed;
991 int total_branches_executed;
992 int total_branches_taken;
994 int total_calls_executed;
996 /* Now, for each source file, allocate an array big enough to hold a count
997 for each line. Scan through the bb_data, and when the file name matches
998 the current file name, then for each following line number, increment
999 the line number execution count indicated by the execution count of
1000 the appropriate basic block. */
1002 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1004 /* If this is a relative file name, and an object directory has been
1005 specified, then make it relative to the object directory name. */
1006 if (*s_ptr->name != '/' && object_directory != 0
1007 && *object_directory != '\0')
1009 int objdir_count = strlen (object_directory);
1010 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1011 strcpy (source_file_name, object_directory);
1012 if (object_directory[objdir_count - 1] != '/')
1013 source_file_name[objdir_count++] = '/';
1014 strcpy (source_file_name + objdir_count, s_ptr->name);
1017 source_file_name = s_ptr->name;
1019 line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
1020 bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
1021 line_exists = xmalloc (s_ptr->maxlineno);
1022 bzero (line_exists, s_ptr->maxlineno);
1023 if (output_branch_probs)
1025 branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata *)
1026 * s_ptr->maxlineno);
1027 bzero ((char *) branch_probs,
1028 sizeof (struct arcdata *) * s_ptr->maxlineno);
1031 /* There will be a zero at the beginning of the bb info, before the
1032 first list of line numbers, so must initialize block_num to 0. */
1037 /* Pointer into the bb_data, incremented while scanning the data. */
1038 char *ptr = bb_data;
1039 for (count = 0; count < bb_data_size; count++)
1043 __fetch_long (&line_num, ptr, 4);
1047 /* Marks the beginning of a file name. Check to see whether
1048 this is the filename we are currently collecting data for. */
1050 if (strcmp (s_ptr->name, ptr))
1055 /* Scan past the file name. */
1058 __fetch_long (&delim, ptr, 4);
1060 } while (delim != line_num);
1062 else if (line_num == -2)
1064 /* Marks the start of a new function. Advance to the next
1065 program flow graph. */
1067 if (! current_graph)
1068 current_graph = bb_graph_list;
1071 if (block_num == current_graph->num_blocks - 1)
1072 /* Last block falls through to exit. */
1074 else if (block_num == current_graph->num_blocks - 2)
1076 if (output_branch_probs && this_file)
1077 calculate_branch_probs (current_graph, block_num,
1078 branch_probs, last_line_num);
1083 "didn't use all bb entries of graph, function %s\n",
1085 fnotice (stderr, "block_num = %d, num_blocks = %d\n",
1086 block_num, current_graph->num_blocks);
1089 current_graph = current_graph->next;
1092 if (output_function_summary && this_file)
1093 function_summary ();
1096 if (output_function_summary)
1098 function_source_lines = 0;
1099 function_source_lines_executed = 0;
1100 function_branches = 0;
1101 function_branches_executed = 0;
1102 function_branches_taken = 0;
1104 function_calls_executed = 0;
1107 /* Save the function name for later use. */
1108 function_name = ptr;
1110 /* Scan past the file name. */
1113 __fetch_long (&delim, ptr, 4);
1115 } while (delim != line_num);
1117 else if (line_num == 0)
1119 /* Marks the end of a block. */
1121 if (block_num >= current_graph->num_blocks)
1123 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1128 if (output_branch_probs && this_file)
1129 calculate_branch_probs (current_graph, block_num,
1130 branch_probs, last_line_num);
1136 if (output_function_summary)
1138 if (line_exists[line_num] == 0)
1139 function_source_lines++;
1140 if (line_counts[line_num] == 0
1141 && current_graph->bb_graph[block_num].exec_count != 0)
1142 function_source_lines_executed++;
1145 /* Accumulate execution data for this line number. */
1147 line_counts[line_num]
1148 += current_graph->bb_graph[block_num].exec_count;
1149 line_exists[line_num] = 1;
1150 last_line_num = line_num;
1155 if (output_function_summary && this_file)
1156 function_summary ();
1158 /* Calculate summary test coverage statistics. */
1160 total_source_lines = 0;
1161 total_source_lines_executed = 0;
1163 total_branches_executed = 0;
1164 total_branches_taken = 0;
1166 total_calls_executed = 0;
1168 for (count = 1; count < s_ptr->maxlineno; count++)
1170 if (line_exists[count])
1172 total_source_lines++;
1173 if (line_counts[count])
1174 total_source_lines_executed++;
1176 if (output_branch_probs)
1178 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1180 if (a_ptr->call_insn)
1183 if (a_ptr->prob != -1)
1184 total_calls_executed++;
1189 if (a_ptr->prob != -1)
1190 total_branches_executed++;
1191 if (a_ptr->prob > 0)
1192 total_branches_taken++;
1198 if (total_source_lines)
1200 "%6.2lf%% of %d source lines executed in file %s\n",
1201 (((double) total_source_lines_executed / total_source_lines)
1202 * 100), total_source_lines, source_file_name);
1204 fnotice (stdout, "No executable source lines in file %s\n",
1207 if (output_branch_probs)
1211 fnotice (stdout, "%6.2lf%% of %d branches executed in file %s\n",
1212 (((double) total_branches_executed / total_branches)
1213 * 100), total_branches, source_file_name);
1215 "%6.2lf%% of %d branches taken at least once in file %s\n",
1216 (((double) total_branches_taken / total_branches)
1217 * 100), total_branches, source_file_name);
1220 fnotice (stdout, "No branches in file %s\n", source_file_name);
1222 fnotice (stdout, "%6.2lf%% of %d calls executed in file %s\n",
1223 (((double) total_calls_executed / total_calls)
1224 * 100), total_calls, source_file_name);
1226 fnotice (stdout, "No calls in file %s\n", source_file_name);
1229 if (output_gcov_file)
1231 /* Now the statistics are ready. Read in the source file one line
1232 at a time, and output that line to the gcov file preceded by
1233 its execution count if non zero. */
1235 source_file = fopen (source_file_name, "r");
1236 if (source_file == NULL)
1238 fnotice (stderr, "Could not open source file %s.\n",
1245 count = strlen (source_file_name);
1246 cptr = rindex (s_ptr->name, '/');
1251 if (output_long_names && strcmp (cptr, input_file_name))
1253 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1255 cptr = rindex (input_file_name, '/');
1257 strcpy (gcov_file_name, cptr + 1);
1259 strcpy (gcov_file_name, input_file_name);
1261 strcat (gcov_file_name, ".");
1263 cptr = rindex (source_file_name, '/');
1265 strcat (gcov_file_name, cptr + 1);
1267 strcat (gcov_file_name, source_file_name);
1271 gcov_file_name = xmalloc (count + 6);
1272 cptr = rindex (source_file_name, '/');
1274 strcpy (gcov_file_name, cptr + 1);
1276 strcpy (gcov_file_name, source_file_name);
1279 /* Don't strip off the ending for compatibility with tcov, since
1280 this results in confusion if there is more than one file with
1281 the same basename, e.g. tmp.c and tmp.h. */
1282 strcat (gcov_file_name, ".gcov");
1284 gcov_file = fopen (gcov_file_name, "w");
1286 if (gcov_file == NULL)
1288 fnotice (stderr, "Could not open output file %s.\n",
1290 fclose (source_file);
1296 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1298 for (count = 1; count < s_ptr->maxlineno; count++)
1303 retval = fgets (string, STRING_SIZE, source_file);
1305 /* For lines which don't exist in the .bb file, print nothing
1306 before the source line. For lines which exist but were never
1307 executed, print ###### before the source line. Otherwise,
1308 print the execution count before the source line. */
1309 /* There are 16 spaces of indentation added before the source
1310 line so that tabs won't be messed up. */
1311 if (line_exists[count])
1313 if (line_counts[count])
1314 fprintf (gcov_file, "%12ld %s", line_counts[count],
1317 fprintf (gcov_file, " ###### %s", string);
1320 fprintf (gcov_file, "\t\t%s", string);
1322 /* In case the source file line is larger than our buffer, keep
1323 reading and outputting lines until we get a newline. */
1324 len = strlen (string);
1325 while ((len == 0 || string[strlen (string) - 1] != '\n')
1328 retval = fgets (string, STRING_SIZE, source_file);
1329 fputs (string, gcov_file);
1332 if (output_branch_probs)
1334 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1335 a_ptr = a_ptr->next, i++)
1337 if (a_ptr->call_insn)
1339 if (a_ptr->prob == -1)
1340 fnotice (gcov_file, "call %d never executed\n", i);
1343 "call %d returns = %d%%\n",
1344 i, 100 - a_ptr->prob);
1348 if (a_ptr->prob == -1)
1349 fnotice (gcov_file, "branch %d never executed\n",
1352 fnotice (gcov_file, "branch %d taken = %d%%\n", i,
1358 /* Gracefully handle errors while reading the source file. */
1362 "Unexpected EOF while reading source file %s.\n",
1368 /* Handle all remaining source lines. There may be lines
1369 after the last line of code. */
1372 char *retval = fgets (string, STRING_SIZE, source_file);
1373 while (retval != NULL)
1377 fprintf (gcov_file, "\t\t%s", string);
1379 /* In case the source file line is larger than our buffer, keep
1380 reading and outputting lines until we get a newline. */
1381 len = strlen (string);
1382 while ((len == 0 || string[strlen (string) - 1] != '\n')
1385 retval = fgets (string, STRING_SIZE, source_file);
1386 fputs (string, gcov_file);
1389 retval = fgets (string, STRING_SIZE, source_file);
1393 fclose (source_file);