1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 91, 92, 93, 94, 96, 1997, 1998 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 setlocale (LC_MESSAGES, "");
229 bindtextdomain (PACKAGE, localedir);
230 textdomain (PACKAGE);
232 process_args (argc, argv);
238 scan_for_source_files ();
245 static void fnotice PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
247 fnotice VPROTO ((const char *msgid, ...))
249 #ifndef ANSI_PROTOTYPES
254 VA_START (ap, msgid);
256 #ifndef ANSI_PROTOTYPES
257 msgid = va_arg (ap, const char *);
260 vfprintf (stderr, _(msgid), ap);
269 register PTR value = (PTR) malloc (size);
272 fnotice (stderr, "error: virtual memory exhausted");
273 exit (FATAL_EXIT_CODE);
278 /* More 'friendly' abort that prints the line and file.
279 config.h can #define abort fancy_abort if you like that sort of thing. */
284 fnotice (stderr, "Internal gcc abort.\n");
285 exit (FATAL_EXIT_CODE);
288 /* Print a usage message and exit. */
293 fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
294 exit (FATAL_EXIT_CODE);
297 /* Parse the command line. */
300 process_args (argc, argv)
306 for (i = 1; i < argc; i++)
308 if (argv[i][0] == '-')
310 if (argv[i][1] == 'b')
311 output_branch_probs = 1;
312 else if (argv[i][1] == 'v')
313 fputs (gcov_version_string, stderr);
314 else if (argv[i][1] == 'n')
315 output_gcov_file = 0;
316 else if (argv[i][1] == 'l')
317 output_long_names = 1;
318 else if (argv[i][1] == 'f')
319 output_function_summary = 1;
320 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
321 object_directory = argv[++i];
325 else if (! input_file_name)
326 input_file_name = argv[i];
331 if (! input_file_name)
336 /* Find and open the .bb, .da, and .bbg files. */
341 int count, objdir_count;
344 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
345 extension, if any, and append the new extensions. */
346 count = strlen (input_file_name);
347 if (object_directory)
348 objdir_count = strlen (object_directory);
352 da_file_name = xmalloc (count + objdir_count + 4);
353 bb_file_name = xmalloc (count + objdir_count + 4);
354 bbg_file_name = xmalloc (count + objdir_count + 5);
356 if (object_directory)
358 strcpy (da_file_name, object_directory);
359 strcpy (bb_file_name, object_directory);
360 strcpy (bbg_file_name, object_directory);
362 if (object_directory[objdir_count - 1] != '/')
364 strcat (da_file_name, "/");
365 strcat (bb_file_name, "/");
366 strcat (bbg_file_name, "/");
369 cptr = rindex (input_file_name, '/');
372 strcat (da_file_name, cptr + 1);
373 strcat (bb_file_name, cptr + 1);
374 strcat (bbg_file_name, cptr + 1);
378 strcat (da_file_name, input_file_name);
379 strcat (bb_file_name, input_file_name);
380 strcat (bbg_file_name, input_file_name);
385 strcpy (da_file_name, input_file_name);
386 strcpy (bb_file_name, input_file_name);
387 strcpy (bbg_file_name, input_file_name);
390 cptr = rindex (bb_file_name, '.');
392 strcpy (cptr, ".bb");
394 strcat (bb_file_name, ".bb");
396 cptr = rindex (da_file_name, '.');
398 strcpy (cptr, ".da");
400 strcat (da_file_name, ".da");
402 cptr = rindex (bbg_file_name, '.');
404 strcpy (cptr, ".bbg");
406 strcat (bbg_file_name, ".bbg");
408 bb_file = fopen (bb_file_name, "r");
411 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
412 exit (FATAL_EXIT_CODE);
415 /* If none of the functions in the file were executed, then there won't
416 be a .da file. Just assume that all counts are zero in this case. */
417 da_file = fopen (da_file_name, "r");
420 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
421 fnotice (stderr, "Assuming that all execution counts are zero.\n");
424 bbg_file = fopen (bbg_file_name, "r");
425 if (bbg_file == NULL)
427 fnotice (stderr, "Could not open program flow graph file %s.\n",
429 exit (FATAL_EXIT_CODE);
432 /* Check for empty .bbg file. This indicates that there is no executable
433 code in this source file. */
434 /* Set the EOF condition if at the end of file. */
435 ungetc (getc (bbg_file), bbg_file);
438 fnotice (stderr, "No executable code associated with file %s.\n",
440 exit (FATAL_EXIT_CODE);
444 /* Initialize a new arc. */
447 init_arc (arcptr, source, target, bb_graph)
448 struct adj_list *arcptr;
450 struct bb_info *bb_graph;
452 arcptr->target = target;
453 arcptr->source = source;
455 arcptr->arc_count = 0;
456 arcptr->count_valid = 0;
459 arcptr->fall_through = 0;
461 arcptr->succ_next = bb_graph[source].succ;
462 bb_graph[source].succ = arcptr;
463 bb_graph[source].succ_count++;
465 arcptr->pred_next = bb_graph[target].pred;
466 bb_graph[target].pred = arcptr;
467 bb_graph[target].pred_count++;
471 /* Reverse the arcs on a arc list. */
473 static struct adj_list *
474 reverse_arcs (arcptr)
475 struct adj_list *arcptr;
477 struct adj_list *prev = 0;
478 struct adj_list *next;
480 for ( ; arcptr; arcptr = next)
482 next = arcptr->succ_next;
483 arcptr->succ_next = prev;
491 /* Construct the program flow graph from the .bbg file, and read in the data
495 create_program_flow_graph (bptr)
496 struct bb_info_list *bptr;
498 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
500 struct adj_list *arcptr;
501 struct bb_info *bb_graph;
503 /* Read the number of blocks. */
504 __read_long (&num_blocks, bbg_file, 4);
506 /* Create an array of size bb number of bb_info structs. Bzero it. */
507 bb_graph = (struct bb_info *) xmalloc (num_blocks
508 * sizeof (struct bb_info));
509 bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
511 bptr->bb_graph = bb_graph;
512 bptr->num_blocks = num_blocks;
514 /* Read and create each arc from the .bbg file. */
515 __read_long (&number_arcs, bbg_file, 4);
516 for (i = 0; i < num_blocks; i++)
520 __read_long (&num_arcs_per_block, bbg_file, 4);
521 for (j = 0; j < num_arcs_per_block; j++)
523 if (number_arcs-- < 0)
527 __read_long (&dest, bbg_file, 4);
529 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
530 init_arc (arcptr, src, dest, bb_graph);
532 __read_long (&flag_bits, bbg_file, 4);
533 arcptr->on_tree = flag_bits & 0x1;
534 arcptr->fake = !! (flag_bits & 0x2);
535 arcptr->fall_through = !! (flag_bits & 0x4);
542 /* Read and ignore the -1 separating the arc list from the arc list of the
544 __read_long (&src, bbg_file, 4);
548 /* Must reverse the order of all succ arcs, to ensure that they match
549 the order of the data in the .da file. */
551 for (i = 0; i < num_blocks; i++)
552 if (bb_graph[i].succ)
553 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
555 /* For each arc not on the spanning tree, set its execution count from
558 /* The first count in the .da file is the number of times that the function
559 was entered. This is the exec_count for block zero. */
561 /* This duplicates code in branch_prob in profile.c. */
563 for (i = 0; i < num_blocks; i++)
564 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
565 if (! arcptr->on_tree)
568 if (da_file && __read_long (&tmp_count, da_file, 8))
571 arcptr->arc_count = tmp_count;
572 arcptr->count_valid = 1;
573 bb_graph[i].succ_count--;
574 bb_graph[arcptr->target].pred_count--;
579 solve_program_flow_graph (bptr)
580 struct bb_info_list *bptr;
582 int passes, changes, total;
584 struct adj_list *arcptr;
585 struct bb_info *bb_graph;
588 num_blocks = bptr->num_blocks;
589 bb_graph = bptr->bb_graph;
591 /* For every block in the file,
592 - if every exit/entrance arc has a known count, then set the block count
593 - if the block count is known, and every exit/entrance arc but one has
594 a known execution count, then set the count of the remaining arc
596 As arc counts are set, decrement the succ/pred count, but don't delete
597 the arc, that way we can easily tell when all arcs are known, or only
598 one arc is unknown. */
600 /* The order that the basic blocks are iterated through is important.
601 Since the code that finds spanning trees starts with block 0, low numbered
602 arcs are put on the spanning tree in preference to high numbered arcs.
603 Hence, most instrumented arcs are at the end. Graph solving works much
604 faster if we propagate numbers from the end to the start.
606 This takes an average of slightly more than 3 passes. */
615 for (i = num_blocks - 1; i >= 0; i--)
617 if (! bb_graph[i].count_valid)
619 if (bb_graph[i].succ_count == 0)
622 for (arcptr = bb_graph[i].succ; arcptr;
623 arcptr = arcptr->succ_next)
624 total += arcptr->arc_count;
625 bb_graph[i].exec_count = total;
626 bb_graph[i].count_valid = 1;
629 else if (bb_graph[i].pred_count == 0)
632 for (arcptr = bb_graph[i].pred; arcptr;
633 arcptr = arcptr->pred_next)
634 total += arcptr->arc_count;
635 bb_graph[i].exec_count = total;
636 bb_graph[i].count_valid = 1;
640 if (bb_graph[i].count_valid)
642 if (bb_graph[i].succ_count == 1)
645 /* One of the counts will be invalid, but it is zero,
646 so adding it in also doesn't hurt. */
647 for (arcptr = bb_graph[i].succ; arcptr;
648 arcptr = arcptr->succ_next)
649 total += arcptr->arc_count;
650 /* Calculate count for remaining arc by conservation. */
651 total = bb_graph[i].exec_count - total;
652 /* Search for the invalid arc, and set its count. */
653 for (arcptr = bb_graph[i].succ; arcptr;
654 arcptr = arcptr->succ_next)
655 if (! arcptr->count_valid)
659 arcptr->count_valid = 1;
660 arcptr->arc_count = total;
661 bb_graph[i].succ_count--;
663 bb_graph[arcptr->target].pred_count--;
666 if (bb_graph[i].pred_count == 1)
669 /* One of the counts will be invalid, but it is zero,
670 so adding it in also doesn't hurt. */
671 for (arcptr = bb_graph[i].pred; arcptr;
672 arcptr = arcptr->pred_next)
673 total += arcptr->arc_count;
674 /* Calculate count for remaining arc by conservation. */
675 total = bb_graph[i].exec_count - total;
676 /* Search for the invalid arc, and set its count. */
677 for (arcptr = bb_graph[i].pred; arcptr;
678 arcptr = arcptr->pred_next)
679 if (! arcptr->count_valid)
683 arcptr->count_valid = 1;
684 arcptr->arc_count = total;
685 bb_graph[i].pred_count--;
687 bb_graph[arcptr->source].succ_count--;
694 /* If the graph has been correctly solved, every block will have a
695 succ and pred count of zero. */
696 for (i = 0; i < num_blocks; i++)
697 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
706 struct bb_info_list *list_end = 0;
707 struct bb_info_list *b_ptr;
710 /* Read and ignore the first word of the .da file, which is the count of
711 how many numbers follow. */
712 if (da_file && __read_long (&total, da_file, 8))
715 while (! feof (bbg_file))
717 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
721 list_end->next = b_ptr;
723 bb_graph_list = b_ptr;
726 /* Read in the data in the .bbg file and reconstruct the program flow
727 graph for one function. */
728 create_program_flow_graph (b_ptr);
730 /* Set the EOF condition if at the end of file. */
731 ungetc (getc (bbg_file), bbg_file);
734 /* Check to make sure the .da file data is valid. */
739 fnotice (stderr, ".da file contents exhausted too early\n");
740 /* Should be at end of file now. */
741 if (__read_long (&total, da_file, 8) == 0)
742 fnotice (stderr, ".da file contents not exhausted\n");
745 /* Calculate all of the basic block execution counts and branch
746 taken probabilities. */
748 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
749 solve_program_flow_graph (b_ptr);
751 /* Read in all of the data from the .bb file. This info will be accessed
752 sequentially twice. */
753 stat (bb_file_name, &buf);
754 bb_data_size = buf.st_size / 4;
756 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
757 fread (bb_data, sizeof (char), buf.st_size, bb_file);
766 /* Scan the data in the .bb file to find all source files referenced,
767 and the largest line number mentioned in each one. */
770 scan_for_source_files ()
772 struct sourcefile *s_ptr = NULL;
777 /* Search the bb_data to find:
778 1) The number of sources files contained herein, and
779 2) The largest line number for each source file. */
783 for (count = 0; count < bb_data_size; count++)
785 __fetch_long (&line_num, ptr, 4);
789 /* A source file name follows. Check to see if we already have
790 a sourcefile structure for this file. */
792 while (s_ptr && strcmp (s_ptr->name, ptr))
797 /* No sourcefile structure for this file name exists, create
798 a new one, and append it to the front of the sources list. */
799 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
800 s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
801 strcpy (s_ptr->name, (char *) ptr);
802 s_ptr->maxlineno = 0;
803 s_ptr->next = sources;
807 /* Scan past the file name. */
812 __fetch_long (&delim, ptr, 4);
814 } while (delim != line_num);
817 else if (line_num == -2)
821 /* A function name follows. Ignore it. */
824 __fetch_long (&delim, ptr, 4);
826 } while (delim != line_num);
828 /* There will be a zero before the first file name, in which case s_ptr
829 will still be uninitialized. So, only try to set the maxlineno
830 field if line_num is non-zero. */
831 else if (line_num > 0)
833 if (s_ptr->maxlineno <= line_num)
834 s_ptr->maxlineno = line_num + 1;
836 else if (line_num < 0)
838 /* Don't know what this is, but it's garbage. */
844 /* For calculating coverage at the function level. */
846 static int function_source_lines;
847 static int function_source_lines_executed;
848 static int function_branches;
849 static int function_branches_executed;
850 static int function_branches_taken;
851 static int function_calls;
852 static int function_calls_executed;
853 static char *function_name;
855 /* Calculate the branch taken probabilities for all arcs branches at the
856 end of this block. */
859 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
860 struct bb_info_list *current_graph;
862 struct arcdata **branch_probs;
866 struct adj_list *arcptr;
867 struct arcdata *end_ptr, *a_ptr;
869 total = current_graph->bb_graph[block_num].exec_count;
870 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
871 arcptr = arcptr->succ_next)
873 /* Ignore fall through arcs as they aren't really branches. */
875 if (arcptr->fall_through)
878 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
882 a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
883 a_ptr->call_insn = arcptr->fake;
885 if (output_function_summary)
887 if (a_ptr->call_insn)
890 if (a_ptr->prob != -1)
891 function_calls_executed++;
896 if (a_ptr->prob != -1)
897 function_branches_executed++;
899 function_branches_taken++;
903 /* Append the new branch to the end of the list. */
905 if (! branch_probs[last_line_num])
906 branch_probs[last_line_num] = a_ptr;
909 end_ptr = branch_probs[last_line_num];
910 while (end_ptr->next != 0)
911 end_ptr = end_ptr->next;
912 end_ptr->next = a_ptr;
917 /* Output summary info for a function. */
922 if (function_source_lines)
923 fnotice (stdout, "%6.2lf%% of %d source lines executed in function %s\n",
924 (((double) function_source_lines_executed / function_source_lines)
925 * 100), function_source_lines, function_name);
927 fnotice (stdout, "No executable source lines in function %s\n",
930 if (output_branch_probs)
932 if (function_branches)
934 fnotice (stdout, "%6.2lf%% of %d branches executed in function %s\n",
935 (((double) function_branches_executed / function_branches)
936 * 100), function_branches, function_name);
938 "%6.2lf%% of %d branches taken at least once in function %s\n",
939 (((double) function_branches_taken / function_branches)
940 * 100), function_branches, function_name);
943 fnotice (stdout, "No branches in function %s\n", function_name);
945 fnotice (stdout, "%6.2lf%% of %d calls executed in function %s\n",
946 (((double) function_calls_executed / function_calls)
947 * 100), function_calls, function_name);
949 fnotice (stdout, "No calls in function %s\n", function_name);
953 /* Calculate line execution counts, and output the data to a .tcov file. */
958 /* When scanning data, this is true only if the data applies to the
959 current source file. */
961 /* An array indexed by line number which indicates how many times that line
964 /* An array indexed by line number which indicates whether the line was
965 present in the bb file (i.e. whether it had code associate with it).
966 Lines never executed are those which both exist, and have zero execution
969 /* An array indexed by line number, which contains a list of branch
970 probabilities, one for each branch on that line. */
971 struct arcdata **branch_probs = NULL;
972 struct sourcefile *s_ptr;
973 char *source_file_name;
975 struct bb_info_list *current_graph;
980 long last_line_num = 0;
982 struct arcdata *a_ptr;
983 /* Buffer used for reading in lines from the source file. */
984 char string[STRING_SIZE];
985 /* For calculating coverage at the file level. */
986 int total_source_lines;
987 int total_source_lines_executed;
989 int total_branches_executed;
990 int total_branches_taken;
992 int total_calls_executed;
994 /* Now, for each source file, allocate an array big enough to hold a count
995 for each line. Scan through the bb_data, and when the file name matches
996 the current file name, then for each following line number, increment
997 the line number execution count indicated by the execution count of
998 the appropriate basic block. */
1000 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1002 /* If this is a relative file name, and an object directory has been
1003 specified, then make it relative to the object directory name. */
1004 if (*s_ptr->name != '/' && object_directory != 0
1005 && *object_directory != '\0')
1007 int objdir_count = strlen (object_directory);
1008 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1009 strcpy (source_file_name, object_directory);
1010 if (object_directory[objdir_count - 1] != '/')
1011 source_file_name[objdir_count++] = '/';
1012 strcpy (source_file_name + objdir_count, s_ptr->name);
1015 source_file_name = s_ptr->name;
1017 line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
1018 bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
1019 line_exists = xmalloc (s_ptr->maxlineno);
1020 bzero (line_exists, s_ptr->maxlineno);
1021 if (output_branch_probs)
1023 branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata *)
1024 * s_ptr->maxlineno);
1025 bzero ((char *) branch_probs,
1026 sizeof (struct arcdata *) * s_ptr->maxlineno);
1029 /* There will be a zero at the beginning of the bb info, before the
1030 first list of line numbers, so must initialize block_num to 0. */
1035 /* Pointer into the bb_data, incremented while scanning the data. */
1036 char *ptr = bb_data;
1037 for (count = 0; count < bb_data_size; count++)
1041 __fetch_long (&line_num, ptr, 4);
1045 /* Marks the beginning of a file name. Check to see whether
1046 this is the filename we are currently collecting data for. */
1048 if (strcmp (s_ptr->name, ptr))
1053 /* Scan past the file name. */
1056 __fetch_long (&delim, ptr, 4);
1058 } while (delim != line_num);
1060 else if (line_num == -2)
1062 /* Marks the start of a new function. Advance to the next
1063 program flow graph. */
1065 if (! current_graph)
1066 current_graph = bb_graph_list;
1069 if (block_num == current_graph->num_blocks - 1)
1070 /* Last block falls through to exit. */
1072 else if (block_num == current_graph->num_blocks - 2)
1074 if (output_branch_probs && this_file)
1075 calculate_branch_probs (current_graph, block_num,
1076 branch_probs, last_line_num);
1081 "didn't use all bb entries of graph, function %s\n",
1083 fnotice (stderr, "block_num = %d, num_blocks = %d\n",
1084 block_num, current_graph->num_blocks);
1087 current_graph = current_graph->next;
1090 if (output_function_summary && this_file)
1091 function_summary ();
1094 if (output_function_summary)
1096 function_source_lines = 0;
1097 function_source_lines_executed = 0;
1098 function_branches = 0;
1099 function_branches_executed = 0;
1100 function_branches_taken = 0;
1102 function_calls_executed = 0;
1105 /* Save the function name for later use. */
1106 function_name = ptr;
1108 /* Scan past the file name. */
1111 __fetch_long (&delim, ptr, 4);
1113 } while (delim != line_num);
1115 else if (line_num == 0)
1117 /* Marks the end of a block. */
1119 if (block_num >= current_graph->num_blocks)
1121 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1126 if (output_branch_probs && this_file)
1127 calculate_branch_probs (current_graph, block_num,
1128 branch_probs, last_line_num);
1134 if (output_function_summary)
1136 if (line_exists[line_num] == 0)
1137 function_source_lines++;
1138 if (line_counts[line_num] == 0
1139 && current_graph->bb_graph[block_num].exec_count != 0)
1140 function_source_lines_executed++;
1143 /* Accumulate execution data for this line number. */
1145 line_counts[line_num]
1146 += current_graph->bb_graph[block_num].exec_count;
1147 line_exists[line_num] = 1;
1148 last_line_num = line_num;
1153 if (output_function_summary && this_file)
1154 function_summary ();
1156 /* Calculate summary test coverage statistics. */
1158 total_source_lines = 0;
1159 total_source_lines_executed = 0;
1161 total_branches_executed = 0;
1162 total_branches_taken = 0;
1164 total_calls_executed = 0;
1166 for (count = 1; count < s_ptr->maxlineno; count++)
1168 if (line_exists[count])
1170 total_source_lines++;
1171 if (line_counts[count])
1172 total_source_lines_executed++;
1174 if (output_branch_probs)
1176 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1178 if (a_ptr->call_insn)
1181 if (a_ptr->prob != -1)
1182 total_calls_executed++;
1187 if (a_ptr->prob != -1)
1188 total_branches_executed++;
1189 if (a_ptr->prob > 0)
1190 total_branches_taken++;
1196 if (total_source_lines)
1198 "%6.2lf%% of %d source lines executed in file %s\n",
1199 (((double) total_source_lines_executed / total_source_lines)
1200 * 100), total_source_lines, source_file_name);
1202 fnotice (stdout, "No executable source lines in file %s\n",
1205 if (output_branch_probs)
1209 fnotice (stdout, "%6.2lf%% of %d branches executed in file %s\n",
1210 (((double) total_branches_executed / total_branches)
1211 * 100), total_branches, source_file_name);
1213 "%6.2lf%% of %d branches taken at least once in file %s\n",
1214 (((double) total_branches_taken / total_branches)
1215 * 100), total_branches, source_file_name);
1218 fnotice (stdout, "No branches in file %s\n", source_file_name);
1220 fnotice (stdout, "%6.2lf%% of %d calls executed in file %s\n",
1221 (((double) total_calls_executed / total_calls)
1222 * 100), total_calls, source_file_name);
1224 fnotice (stdout, "No calls in file %s\n", source_file_name);
1227 if (output_gcov_file)
1229 /* Now the statistics are ready. Read in the source file one line
1230 at a time, and output that line to the gcov file preceded by
1231 its execution count if non zero. */
1233 source_file = fopen (source_file_name, "r");
1234 if (source_file == NULL)
1236 fnotice (stderr, "Could not open source file %s.\n",
1243 count = strlen (source_file_name);
1244 cptr = rindex (s_ptr->name, '/');
1249 if (output_long_names && strcmp (cptr, input_file_name))
1251 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1253 cptr = rindex (input_file_name, '/');
1255 strcpy (gcov_file_name, cptr + 1);
1257 strcpy (gcov_file_name, input_file_name);
1259 strcat (gcov_file_name, ".");
1261 cptr = rindex (source_file_name, '/');
1263 strcat (gcov_file_name, cptr + 1);
1265 strcat (gcov_file_name, source_file_name);
1269 gcov_file_name = xmalloc (count + 6);
1270 cptr = rindex (source_file_name, '/');
1272 strcpy (gcov_file_name, cptr + 1);
1274 strcpy (gcov_file_name, source_file_name);
1277 /* Don't strip off the ending for compatibility with tcov, since
1278 this results in confusion if there is more than one file with
1279 the same basename, e.g. tmp.c and tmp.h. */
1280 strcat (gcov_file_name, ".gcov");
1282 gcov_file = fopen (gcov_file_name, "w");
1284 if (gcov_file == NULL)
1286 fnotice (stderr, "Could not open output file %s.\n",
1288 fclose (source_file);
1294 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1296 for (count = 1; count < s_ptr->maxlineno; count++)
1301 retval = fgets (string, STRING_SIZE, source_file);
1303 /* For lines which don't exist in the .bb file, print nothing
1304 before the source line. For lines which exist but were never
1305 executed, print ###### before the source line. Otherwise,
1306 print the execution count before the source line. */
1307 /* There are 16 spaces of indentation added before the source
1308 line so that tabs won't be messed up. */
1309 if (line_exists[count])
1311 if (line_counts[count])
1312 fprintf (gcov_file, "%12ld %s", line_counts[count],
1315 fprintf (gcov_file, " ###### %s", string);
1318 fprintf (gcov_file, "\t\t%s", string);
1320 /* In case the source file line is larger than our buffer, keep
1321 reading and outputting lines until we get a newline. */
1322 len = strlen (string);
1323 while ((len == 0 || string[strlen (string) - 1] != '\n')
1326 retval = fgets (string, STRING_SIZE, source_file);
1327 fputs (string, gcov_file);
1330 if (output_branch_probs)
1332 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1333 a_ptr = a_ptr->next, i++)
1335 if (a_ptr->call_insn)
1337 if (a_ptr->prob == -1)
1338 fnotice (gcov_file, "call %d never executed\n", i);
1341 "call %d returns = %d%%\n",
1342 i, 100 - a_ptr->prob);
1346 if (a_ptr->prob == -1)
1347 fnotice (gcov_file, "branch %d never executed\n",
1350 fnotice (gcov_file, "branch %d taken = %d%%\n", i,
1356 /* Gracefully handle errors while reading the source file. */
1360 "Unexpected EOF while reading source file %s.\n",
1366 /* Handle all remaining source lines. There may be lines
1367 after the last line of code. */
1370 char *retval = fgets (string, STRING_SIZE, source_file);
1371 while (retval != NULL)
1375 fprintf (gcov_file, "\t\t%s", string);
1377 /* In case the source file line is larger than our buffer, keep
1378 reading and outputting lines until we get a newline. */
1379 len = strlen (string);
1380 while ((len == 0 || string[strlen (string) - 1] != '\n')
1383 retval = fgets (string, STRING_SIZE, source_file);
1384 fputs (string, gcov_file);
1387 retval = fgets (string, STRING_SIZE, source_file);
1391 fclose (source_file);