1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2018 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
28 #if defined(inhibit_libc)
29 /* If libc and its header files are not available, provide dummy functions. */
32 void __gcov_init (struct gcov_info
*p
__attribute__ ((unused
))) {}
35 #else /* inhibit_libc */
46 /* A utility function for outputting errors. */
47 static int gcov_error (const char *, ...);
50 static void gcov_error_exit (void);
57 struct gcov_fn_buffer
*next
;
59 struct gcov_fn_info info
;
60 /* note gcov_fn_info ends in a trailing array. */
63 struct gcov_summary_buffer
65 struct gcov_summary_buffer
*next
;
66 struct gcov_summary summary
;
69 /* A struct that bundles all the related information about the
74 char *filename
; /* filename buffer */
75 size_t max_length
; /* maximum filename length */
76 int strip
; /* leading chars to strip from filename */
77 size_t prefix
; /* chars to prepend to filename */
80 static struct gcov_fn_buffer
*
81 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
84 struct gcov_fn_buffer
*next
;
85 unsigned ix
, n_ctr
= 0;
91 for (ix
= 0; ix
!= limit
; ix
++)
92 if (gi_ptr
->merge
[ix
])
93 free (buffer
->info
.ctrs
[n_ctr
++].values
);
98 static struct gcov_fn_buffer
**
99 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
100 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
102 unsigned n_ctrs
= 0, ix
= 0;
103 struct gcov_fn_buffer
*fn_buffer
;
106 for (ix
= GCOV_COUNTERS
; ix
--;)
107 if (gi_ptr
->merge
[ix
])
110 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
111 fn_buffer
= (struct gcov_fn_buffer
*) xmalloc (len
);
117 fn_buffer
->fn_ix
= fn_ix
;
118 fn_buffer
->info
.ident
= gcov_read_unsigned ();
119 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
120 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
122 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
124 gcov_unsigned_t length
;
127 if (!gi_ptr
->merge
[ix
])
130 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
136 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
137 len
= length
* sizeof (gcov_type
);
138 values
= (gcov_type
*) xmalloc (len
);
142 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
143 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
146 *values
++ = gcov_read_counter ();
150 *end_ptr
= fn_buffer
;
151 return &fn_buffer
->next
;
154 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
155 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
157 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
160 /* Add an unsigned value to the current crc */
162 static gcov_unsigned_t
163 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
167 for (ix
= 32; ix
--; value
<<= 1)
171 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
179 /* Check if VERSION of the info block PTR matches libgcov one.
180 Return 1 on success, or zero in case of versions mismatch.
181 If FILENAME is not NULL, its value used for reporting purposes
182 instead of value from the info block. */
185 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
186 const char *filename
)
188 if (version
!= GCOV_VERSION
)
192 GCOV_UNSIGNED2STRING (v
, version
);
193 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
195 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
196 filename
? filename
: ptr
->filename
, e
, v
);
202 /* Insert counter VALUE into HISTOGRAM. */
205 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
209 i
= gcov_histo_index(value
);
210 histogram
[i
].num_counters
++;
211 histogram
[i
].cum_value
+= value
;
212 if (value
< histogram
[i
].min_value
)
213 histogram
[i
].min_value
= value
;
216 /* Computes a histogram of the arc counters to place in the summary SUM. */
219 gcov_compute_histogram (struct gcov_info
*list
, struct gcov_summary
*sum
)
221 struct gcov_info
*gi_ptr
;
222 const struct gcov_fn_info
*gfi_ptr
;
223 const struct gcov_ctr_info
*ci_ptr
;
224 struct gcov_ctr_summary
*cs_ptr
;
225 unsigned t_ix
, f_ix
, ctr_info_ix
, ix
;
228 /* This currently only applies to arc counters. */
229 t_ix
= GCOV_COUNTER_ARCS
;
231 /* First check if there are any counts recorded for this counter. */
232 cs_ptr
= &(sum
->ctrs
[t_ix
]);
236 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
238 cs_ptr
->histogram
[h_ix
].num_counters
= 0;
239 cs_ptr
->histogram
[h_ix
].min_value
= cs_ptr
->run_max
;
240 cs_ptr
->histogram
[h_ix
].cum_value
= 0;
243 /* Walk through all the per-object structures and record each of
244 the count values in histogram. */
245 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
247 if (!gi_ptr
->merge
[t_ix
])
250 /* Find the appropriate index into the gcov_ctr_info array
251 for the counter we are currently working on based on the
252 existence of the merge function pointer for this object. */
253 for (ix
= 0, ctr_info_ix
= 0; ix
< t_ix
; ix
++)
255 if (gi_ptr
->merge
[ix
])
258 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
260 gfi_ptr
= gi_ptr
->functions
[f_ix
];
262 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
265 ci_ptr
= &gfi_ptr
->ctrs
[ctr_info_ix
];
266 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
267 gcov_histogram_insert (cs_ptr
->histogram
, ci_ptr
->values
[ix
]);
272 /* buffer for the fn_data from another program. */
273 static struct gcov_fn_buffer
*fn_buffer
;
274 /* buffer for summary from other programs to be written out. */
275 static struct gcov_summary_buffer
*sum_buffer
;
277 /* This function computes the program level summary and the histo-gram.
278 It computes and returns CRC32 and stored summary in THIS_PRG.
279 Also determines the longest filename length of the info files. */
285 compute_summary (struct gcov_info
*list
, struct gcov_summary
*this_prg
,
288 struct gcov_info
*gi_ptr
;
289 const struct gcov_fn_info
*gfi_ptr
;
290 struct gcov_ctr_summary
*cs_ptr
;
291 const struct gcov_ctr_info
*ci_ptr
;
294 gcov_unsigned_t c_num
;
295 gcov_unsigned_t crc32
= 0;
297 /* Find the totals for this execution. */
298 memset (this_prg
, 0, sizeof (*this_prg
));
300 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
302 size_t len
= strlen (gi_ptr
->filename
);
303 if (len
> *max_length
)
306 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
307 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
309 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
311 gfi_ptr
= gi_ptr
->functions
[f_ix
];
313 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
316 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
317 crc32
= crc32_unsigned (crc32
,
318 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
322 ci_ptr
= gfi_ptr
->ctrs
;
323 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
325 if (!gi_ptr
->merge
[t_ix
])
328 cs_ptr
= &(this_prg
->ctrs
[t_ix
]);
329 cs_ptr
->num
+= ci_ptr
->num
;
330 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
332 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
334 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
335 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
336 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
342 gcov_compute_histogram (list
, this_prg
);
346 /* Including system dependent components. */
347 #include "libgcov-driver-system.c"
349 /* This function merges counters in GI_PTR to an existing gcda file.
351 Return -1 on error. In this case, caller will goto read_fatal. */
354 merge_one_data (const char *filename
,
355 struct gcov_info
*gi_ptr
,
356 struct gcov_summary
*prg_p
,
357 struct gcov_summary
*this_prg
,
358 gcov_position_t
*summary_pos_p
,
359 gcov_position_t
*eof_pos_p
,
360 gcov_unsigned_t crc32
)
362 gcov_unsigned_t tag
, length
;
366 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
367 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
369 length
= gcov_read_unsigned ();
370 if (!gcov_version (gi_ptr
, length
, filename
))
373 length
= gcov_read_unsigned ();
374 if (length
!= gi_ptr
->stamp
)
376 /* Read from a different compilation. Overwrite the file. */
377 gcov_error ("profiling:%s:overwriting an existing profile data "
378 "with a different timestamp\n", filename
);
382 /* Look for program summary. */
385 struct gcov_summary tmp
;
387 *eof_pos_p
= gcov_position ();
388 tag
= gcov_read_unsigned ();
389 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
393 length
= gcov_read_unsigned ();
394 gcov_read_summary (&tmp
);
395 if ((error
= gcov_is_error ()))
399 /* Save all summaries after the one that will be
400 merged into below. These will need to be rewritten
401 as histogram merging may change the number of non-zero
402 histogram entries that will be emitted, and thus the
403 size of the merged summary. */
404 (*sum_tail
) = (struct gcov_summary_buffer
*)
405 xmalloc (sizeof(struct gcov_summary_buffer
));
406 (*sum_tail
)->summary
= tmp
;
407 (*sum_tail
)->next
= 0;
408 sum_tail
= &((*sum_tail
)->next
);
411 if (tmp
.checksum
!= crc32
)
414 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
415 if (tmp
.ctrs
[t_ix
].num
!= this_prg
->ctrs
[t_ix
].num
)
418 *summary_pos_p
= *eof_pos_p
;
423 /* Merge execution counts for each function. */
424 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
425 f_ix
++, tag
= gcov_read_unsigned ())
427 const struct gcov_ctr_info
*ci_ptr
;
428 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
430 if (tag
!= GCOV_TAG_FUNCTION
)
433 length
= gcov_read_unsigned ();
435 /* This function did not appear in the other program.
436 We have nothing to merge. */
439 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
442 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
444 /* This function appears in the other program. We
445 need to buffer the information in order to write
446 it back out -- we'll be inserting data before
447 this point, so cannot simply keep the data in the
449 fn_tail
= buffer_fn_data (filename
, gi_ptr
, fn_tail
, f_ix
);
455 length
= gcov_read_unsigned ();
456 if (length
!= gfi_ptr
->ident
)
459 length
= gcov_read_unsigned ();
460 if (length
!= gfi_ptr
->lineno_checksum
)
463 length
= gcov_read_unsigned ();
464 if (length
!= gfi_ptr
->cfg_checksum
)
467 ci_ptr
= gfi_ptr
->ctrs
;
468 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
470 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
475 tag
= gcov_read_unsigned ();
476 length
= gcov_read_unsigned ();
477 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
478 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
480 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
483 if ((error
= gcov_is_error ()))
490 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
491 filename
, f_ix
>= 0 ? "function" : "summary",
492 f_ix
< 0 ? -1 - f_ix
: f_ix
);
498 gcov_error ("profiling:%s:%s merging\n", filename
,
499 error
< 0 ? "Overflow": "Error");
503 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
504 the case of appending to an existing file, SUMMARY_POS will be non-zero.
505 We will write the file starting from SUMMAY_POS. */
508 write_one_data (const struct gcov_info
*gi_ptr
,
509 const struct gcov_summary
*prg_p
,
510 const gcov_position_t eof_pos
,
511 const gcov_position_t summary_pos
)
514 struct gcov_summary_buffer
*next_sum_buffer
;
516 /* Write out the data. */
519 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
520 gcov_write_unsigned (gi_ptr
->stamp
);
524 gcov_seek (summary_pos
);
526 /* Generate whole program statistics. */
527 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
529 /* Rewrite all the summaries that were after the summary we merged
530 into. This is necessary as the merged summary may have a different
531 size due to the number of non-zero histogram entries changing after
536 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
537 next_sum_buffer
= sum_buffer
->next
;
539 sum_buffer
= next_sum_buffer
;
542 /* Write execution counts for each function. */
543 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
545 unsigned buffered
= 0;
546 const struct gcov_fn_info
*gfi_ptr
;
547 const struct gcov_ctr_info
*ci_ptr
;
548 gcov_unsigned_t length
;
551 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
553 /* Buffered data from another program. */
555 gfi_ptr
= &fn_buffer
->info
;
556 length
= GCOV_TAG_FUNCTION_LENGTH
;
560 gfi_ptr
= gi_ptr
->functions
[f_ix
];
561 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
562 length
= GCOV_TAG_FUNCTION_LENGTH
;
567 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
571 gcov_write_unsigned (gfi_ptr
->ident
);
572 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
573 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
575 ci_ptr
= gfi_ptr
->ctrs
;
576 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
578 gcov_unsigned_t n_counts
;
581 if (!gi_ptr
->merge
[t_ix
])
584 n_counts
= ci_ptr
->num
;
585 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
586 GCOV_TAG_COUNTER_LENGTH (n_counts
));
587 c_ptr
= ci_ptr
->values
;
589 gcov_write_counter (*c_ptr
++);
593 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
596 gcov_write_unsigned (0);
599 /* Helper function for merging summary.
600 Return -1 on error. Return 0 on success. */
603 merge_summary (const char *filename
, int run_counted
,
604 const struct gcov_info
*gi_ptr
, struct gcov_summary
*prg
,
605 struct gcov_summary
*this_prg
, gcov_unsigned_t crc32
,
606 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
608 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
;
611 /* summary for all instances of program. */
612 struct gcov_ctr_summary
*cs_all
;
615 /* Merge the summaries. */
616 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
618 cs_prg
= &(prg
->ctrs
[t_ix
]);
619 cs_tprg
= &(this_prg
->ctrs
[t_ix
]);
621 if (gi_ptr
->merge
[t_ix
])
623 int first
= !cs_prg
->runs
;
628 cs_prg
->num
= cs_tprg
->num
;
629 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
630 if (cs_prg
->run_max
< cs_tprg
->run_max
)
631 cs_prg
->run_max
= cs_tprg
->run_max
;
632 cs_prg
->sum_max
+= cs_tprg
->run_max
;
634 memcpy (cs_prg
->histogram
, cs_tprg
->histogram
,
635 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
637 gcov_histogram_merge (cs_prg
->histogram
, cs_tprg
->histogram
);
639 else if (cs_prg
->runs
)
641 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
646 cs_all
= &all_prg
->ctrs
[t_ix
];
647 if (!cs_all
->runs
&& cs_prg
->runs
)
649 cs_all
->num
= cs_prg
->num
;
650 cs_all
->runs
= cs_prg
->runs
;
651 cs_all
->sum_all
= cs_prg
->sum_all
;
652 cs_all
->run_max
= cs_prg
->run_max
;
653 cs_all
->sum_max
= cs_prg
->sum_max
;
655 else if (!all_prg
->checksum
656 /* Don't compare the histograms, which may have slight
657 variations depending on the order they were updated
658 due to the truncating integer divides used in the
660 && (cs_all
->num
!= cs_prg
->num
661 || cs_all
->runs
!= cs_prg
->runs
662 || cs_all
->sum_all
!= cs_prg
->sum_all
663 || cs_all
->run_max
!= cs_prg
->run_max
664 || cs_all
->sum_max
!= cs_prg
->sum_max
))
666 gcov_error ("profiling:%s:Data file mismatch - some "
667 "data files may have been concurrently "
668 "updated without locking support\n", filename
);
669 all_prg
->checksum
= ~0u;
674 prg
->checksum
= crc32
;
680 /* Sort N entries in VALUE_ARRAY in descending order.
681 Each entry in VALUE_ARRAY has two values. The sorting
682 is based on the second value. */
685 gcov_sort_n_vals (gcov_type
*value_array
, int n
)
689 for (j
= 2; j
< n
; j
+= 2)
691 gcov_type cur_ent
[2];
693 cur_ent
[0] = value_array
[j
];
694 cur_ent
[1] = value_array
[j
+ 1];
696 while (k
>= 0 && value_array
[k
+ 1] < cur_ent
[1])
698 value_array
[k
+ 2] = value_array
[k
];
699 value_array
[k
+ 3] = value_array
[k
+1];
702 value_array
[k
+ 2] = cur_ent
[0];
703 value_array
[k
+ 3] = cur_ent
[1];
707 /* Sort the profile counters for all indirect call sites. Counters
708 for each call site are allocated in array COUNTERS. */
711 gcov_sort_icall_topn_counter (const struct gcov_ctr_info
*counters
)
715 int n
= counters
->num
;
717 gcc_assert (!(n
% GCOV_ICALL_TOPN_NCOUNTS
));
718 values
= counters
->values
;
720 for (i
= 0; i
< n
; i
+= GCOV_ICALL_TOPN_NCOUNTS
)
722 gcov_type
*value_array
= &values
[i
+ 1];
723 gcov_sort_n_vals (value_array
, GCOV_ICALL_TOPN_NCOUNTS
- 1);
727 /* Sort topn indirect_call profile counters in GI_PTR. */
730 gcov_sort_topn_counter_arrays (const struct gcov_info
*gi_ptr
)
734 const struct gcov_fn_info
*gfi_ptr
;
735 const struct gcov_ctr_info
*ci_ptr
;
737 if (!gi_ptr
->merge
[GCOV_COUNTER_ICALL_TOPNV
])
740 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
742 gfi_ptr
= gi_ptr
->functions
[f_ix
];
743 ci_ptr
= gfi_ptr
->ctrs
;
744 for (i
= 0; i
< GCOV_COUNTERS
; i
++)
746 if (!gi_ptr
->merge
[i
])
748 if (i
== GCOV_COUNTER_ICALL_TOPNV
)
750 gcov_sort_icall_topn_counter (ci_ptr
);
758 /* Dump the coverage counts for one gcov_info object. We merge with existing
759 counts when possible, to avoid growing the .da files ad infinitum. We use
760 this program's checksum to make sure we only accumulate whole program
761 statistics to the correct summary. An object file might be embedded
762 in two separate programs, and we must keep the two program
763 summaries separate. */
766 dump_one_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename
*gf
,
767 unsigned run_counted
,
768 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
,
769 struct gcov_summary
*this_prg
)
771 struct gcov_summary prg
; /* summary for this object over all program. */
774 gcov_position_t summary_pos
= 0;
775 gcov_position_t eof_pos
= 0;
780 gcov_sort_topn_counter_arrays (gi_ptr
);
782 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
786 tag
= gcov_read_unsigned ();
789 /* Merge data from file. */
790 if (tag
!= GCOV_DATA_MAGIC
)
792 gcov_error ("profiling:%s:Not a gcov data file\n", gf
->filename
);
795 error
= merge_one_data (gf
->filename
, gi_ptr
, &prg
, this_prg
,
796 &summary_pos
, &eof_pos
, crc32
);
805 memset (&prg
, 0, sizeof (prg
));
806 summary_pos
= eof_pos
;
809 error
= merge_summary (gf
->filename
, run_counted
, gi_ptr
, &prg
, this_prg
,
814 write_one_data (gi_ptr
, &prg
, eof_pos
, summary_pos
);
819 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
821 if ((error
= gcov_close ()))
822 gcov_error (error
< 0 ?
823 "profiling:%s:Overflow writing\n" :
824 "profiling:%s:Error writing\n",
829 /* Dump all the coverage counts for the program. It first computes program
830 summary and then traverses gcov_list list and dumps the gcov_info
831 objects one by one. */
837 gcov_do_dump (struct gcov_info
*list
, int run_counted
)
839 struct gcov_info
*gi_ptr
;
840 struct gcov_filename gf
;
841 gcov_unsigned_t crc32
;
842 struct gcov_summary all_prg
;
843 struct gcov_summary this_prg
;
845 crc32
= compute_summary (list
, &this_prg
, &gf
.max_length
);
847 allocate_filename_struct (&gf
);
849 memset (&all_prg
, 0, sizeof (all_prg
));
852 /* Now merge each file. */
853 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
854 dump_one_gcov (gi_ptr
, &gf
, run_counted
, crc32
, &all_prg
, &this_prg
);
861 __attribute__ ((unused
))
862 gcov_get_filename (struct gcov_info
*list
)
864 return list
->filename
;
870 __gcov_dump_one (struct gcov_root
*root
)
875 gcov_do_dump (root
->list
, root
->run_counted
);
878 root
->run_counted
= 1;
881 /* Per-dynamic-object gcov state. */
882 struct gcov_root __gcov_root
;
884 /* Exactly one of these will be live in the process image. */
885 struct gcov_master __gcov_master
=
891 __gcov_dump_one (&__gcov_root
);
892 if (__gcov_root
.next
)
893 __gcov_root
.next
->prev
= __gcov_root
.prev
;
894 if (__gcov_root
.prev
)
895 __gcov_root
.prev
->next
= __gcov_root
.next
;
897 __gcov_master
.root
= __gcov_root
.next
;
902 /* Add a new object file onto the bb chain. Invoked automatically
903 when running an object file's global ctors. */
906 __gcov_init (struct gcov_info
*info
)
908 if (!info
->version
|| !info
->n_functions
)
910 if (gcov_version (info
, info
->version
, 0))
912 if (!__gcov_root
.list
)
914 /* Add to master list and at exit function. */
915 if (gcov_version (NULL
, __gcov_master
.version
, "<master>"))
917 __gcov_root
.next
= __gcov_master
.root
;
918 if (__gcov_master
.root
)
919 __gcov_master
.root
->prev
= &__gcov_root
;
920 __gcov_master
.root
= &__gcov_root
;
924 info
->next
= __gcov_root
.list
;
925 __gcov_root
.list
= info
;
928 #endif /* !IN_GCOV_TOOL */
930 #endif /* inhibit_libc */