1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2014 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 outputing errors. */
47 static int gcov_error (const char *, ...);
51 /* The following functions can be called from outside of this file. */
52 extern void gcov_clear (void) ATTRIBUTE_HIDDEN
;
53 extern void gcov_exit (void) ATTRIBUTE_HIDDEN
;
54 extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN
;
55 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN
;
56 extern int get_gcov_dump_complete (void) ATTRIBUTE_HIDDEN
;
57 extern void set_gcov_list (struct gcov_info
*) ATTRIBUTE_HIDDEN
;
61 struct gcov_fn_buffer
*next
;
63 struct gcov_fn_info info
;
64 /* note gcov_fn_info ends in a trailing array. */
67 struct gcov_summary_buffer
69 struct gcov_summary_buffer
*next
;
70 struct gcov_summary summary
;
73 /* Chain of per-object gcov structures. */
74 static struct gcov_info
*gcov_list
;
76 /* Set the head of gcov_list. */
78 set_gcov_list (struct gcov_info
*head
)
83 /* Size of the longest file name. */
84 /* We need to expose this static variable when compiling for gcov-tool. */
88 size_t gcov_max_filename
= 0;
90 /* Flag when the profile has already been dumped via __gcov_dump(). */
91 static int gcov_dump_complete
;
93 /* A global function that get the vaule of gcov_dump_complete. */
96 get_gcov_dump_complete (void)
98 return gcov_dump_complete
;
101 /* A global functino that set the vaule of gcov_dump_complete. Will
102 be used in __gcov_dump() in libgcov-interface.c. */
105 set_gcov_dump_complete (void)
107 gcov_dump_complete
= 1;
110 /* A global functino that set the vaule of gcov_dump_complete. Will
111 be used in __gcov_reset() in libgcov-interface.c. */
114 reset_gcov_dump_complete (void)
116 gcov_dump_complete
= 0;
119 static struct gcov_fn_buffer
*
120 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
123 struct gcov_fn_buffer
*next
;
124 unsigned ix
, n_ctr
= 0;
130 for (ix
= 0; ix
!= limit
; ix
++)
131 if (gi_ptr
->merge
[ix
])
132 free (buffer
->info
.ctrs
[n_ctr
++].values
);
137 static struct gcov_fn_buffer
**
138 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
139 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
141 unsigned n_ctrs
= 0, ix
= 0;
142 struct gcov_fn_buffer
*fn_buffer
;
145 for (ix
= GCOV_COUNTERS
; ix
--;)
146 if (gi_ptr
->merge
[ix
])
149 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
150 fn_buffer
= (struct gcov_fn_buffer
*) xmalloc (len
);
156 fn_buffer
->fn_ix
= fn_ix
;
157 fn_buffer
->info
.ident
= gcov_read_unsigned ();
158 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
159 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
161 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
163 gcov_unsigned_t length
;
166 if (!gi_ptr
->merge
[ix
])
169 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
175 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
176 len
= length
* sizeof (gcov_type
);
177 values
= (gcov_type
*) xmalloc (len
);
181 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
182 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
185 *values
++ = gcov_read_counter ();
189 *end_ptr
= fn_buffer
;
190 return &fn_buffer
->next
;
193 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
194 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
196 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
199 /* Add an unsigned value to the current crc */
201 static gcov_unsigned_t
202 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
206 for (ix
= 32; ix
--; value
<<= 1)
210 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
218 /* Check if VERSION of the info block PTR matches libgcov one.
219 Return 1 on success, or zero in case of versions mismatch.
220 If FILENAME is not NULL, its value used for reporting purposes
221 instead of value from the info block. */
224 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
225 const char *filename
)
227 if (version
!= GCOV_VERSION
)
231 GCOV_UNSIGNED2STRING (v
, version
);
232 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
234 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
235 filename
? filename
: ptr
->filename
, e
, v
);
241 /* Insert counter VALUE into HISTOGRAM. */
244 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
248 i
= gcov_histo_index(value
);
249 histogram
[i
].num_counters
++;
250 histogram
[i
].cum_value
+= value
;
251 if (value
< histogram
[i
].min_value
)
252 histogram
[i
].min_value
= value
;
255 /* Computes a histogram of the arc counters to place in the summary SUM. */
258 gcov_compute_histogram (struct gcov_summary
*sum
)
260 struct gcov_info
*gi_ptr
;
261 const struct gcov_fn_info
*gfi_ptr
;
262 const struct gcov_ctr_info
*ci_ptr
;
263 struct gcov_ctr_summary
*cs_ptr
;
264 unsigned t_ix
, f_ix
, ctr_info_ix
, ix
;
267 /* This currently only applies to arc counters. */
268 t_ix
= GCOV_COUNTER_ARCS
;
270 /* First check if there are any counts recorded for this counter. */
271 cs_ptr
= &(sum
->ctrs
[t_ix
]);
275 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
277 cs_ptr
->histogram
[h_ix
].num_counters
= 0;
278 cs_ptr
->histogram
[h_ix
].min_value
= cs_ptr
->run_max
;
279 cs_ptr
->histogram
[h_ix
].cum_value
= 0;
282 /* Walk through all the per-object structures and record each of
283 the count values in histogram. */
284 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
286 if (!gi_ptr
->merge
[t_ix
])
289 /* Find the appropriate index into the gcov_ctr_info array
290 for the counter we are currently working on based on the
291 existence of the merge function pointer for this object. */
292 for (ix
= 0, ctr_info_ix
= 0; ix
< t_ix
; ix
++)
294 if (gi_ptr
->merge
[ix
])
297 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
299 gfi_ptr
= gi_ptr
->functions
[f_ix
];
301 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
304 ci_ptr
= &gfi_ptr
->ctrs
[ctr_info_ix
];
305 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
306 gcov_histogram_insert (cs_ptr
->histogram
, ci_ptr
->values
[ix
]);
312 static char *gi_filename
;
313 /* buffer for the fn_data from another program. */
314 static struct gcov_fn_buffer
*fn_buffer
;
315 /* buffer for summary from other programs to be written out. */
316 static struct gcov_summary_buffer
*sum_buffer
;
317 /* If application calls fork or exec multiple times, we end up storing
318 profile repeadely. We should not account this as multiple runs or
319 functions executed once may mistakely become cold. */
320 static int run_accounted
= 0;
322 /* This funtions computes the program level summary and the histo-gram.
323 It computes and returns CRC32 and stored summary in THIS_PRG. */
325 static gcov_unsigned_t
326 gcov_exit_compute_summary (struct gcov_summary
*this_prg
)
328 struct gcov_info
*gi_ptr
;
329 const struct gcov_fn_info
*gfi_ptr
;
330 struct gcov_ctr_summary
*cs_ptr
;
331 const struct gcov_ctr_info
*ci_ptr
;
334 gcov_unsigned_t c_num
;
335 gcov_unsigned_t crc32
= 0;
337 /* Find the totals for this execution. */
338 memset (this_prg
, 0, sizeof (*this_prg
));
339 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
341 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
342 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
344 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
346 gfi_ptr
= gi_ptr
->functions
[f_ix
];
348 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
351 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
352 crc32
= crc32_unsigned (crc32
,
353 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
357 ci_ptr
= gfi_ptr
->ctrs
;
358 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
360 if (!gi_ptr
->merge
[t_ix
])
363 cs_ptr
= &(this_prg
->ctrs
[t_ix
]);
364 cs_ptr
->num
+= ci_ptr
->num
;
365 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
367 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
369 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
370 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
371 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
377 gcov_compute_histogram (this_prg
);
381 /* A struct that bundles all the related information about the
383 struct gcov_filename_aux
{
384 char *gi_filename_up
;
385 int gcov_prefix_strip
;
386 size_t prefix_length
;
389 /* Including system dependent components. */
390 #include "libgcov-driver-system.c"
392 /* This function merges counters in GI_PTR to an existing gcda file.
394 Return -1 on error. In this case, caller will goto read_fatal. */
397 gcov_exit_merge_gcda (struct gcov_info
*gi_ptr
,
398 struct gcov_summary
*prg_p
,
399 struct gcov_summary
*this_prg
,
400 gcov_position_t
*summary_pos_p
,
401 gcov_position_t
*eof_pos_p
,
402 gcov_unsigned_t crc32
)
404 gcov_unsigned_t tag
, length
;
408 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
409 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
411 length
= gcov_read_unsigned ();
412 if (!gcov_version (gi_ptr
, length
, gi_filename
))
415 length
= gcov_read_unsigned ();
416 if (length
!= gi_ptr
->stamp
)
417 /* Read from a different compilation. Overwrite the file. */
420 /* Look for program summary. */
423 struct gcov_summary tmp
;
425 *eof_pos_p
= gcov_position ();
426 tag
= gcov_read_unsigned ();
427 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
431 length
= gcov_read_unsigned ();
432 gcov_read_summary (&tmp
);
433 if ((error
= gcov_is_error ()))
437 /* Save all summaries after the one that will be
438 merged into below. These will need to be rewritten
439 as histogram merging may change the number of non-zero
440 histogram entries that will be emitted, and thus the
441 size of the merged summary. */
442 (*sum_tail
) = (struct gcov_summary_buffer
*)
443 xmalloc (sizeof(struct gcov_summary_buffer
));
444 (*sum_tail
)->summary
= tmp
;
445 (*sum_tail
)->next
= 0;
446 sum_tail
= &((*sum_tail
)->next
);
449 if (tmp
.checksum
!= crc32
)
452 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
453 if (tmp
.ctrs
[t_ix
].num
!= this_prg
->ctrs
[t_ix
].num
)
456 *summary_pos_p
= *eof_pos_p
;
461 /* Merge execution counts for each function. */
462 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
463 f_ix
++, tag
= gcov_read_unsigned ())
465 const struct gcov_ctr_info
*ci_ptr
;
466 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
468 if (tag
!= GCOV_TAG_FUNCTION
)
471 length
= gcov_read_unsigned ();
473 /* This function did not appear in the other program.
474 We have nothing to merge. */
477 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
480 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
482 /* This function appears in the other program. We
483 need to buffer the information in order to write
484 it back out -- we'll be inserting data before
485 this point, so cannot simply keep the data in the
487 fn_tail
= buffer_fn_data (gi_filename
,
488 gi_ptr
, fn_tail
, f_ix
);
494 length
= gcov_read_unsigned ();
495 if (length
!= gfi_ptr
->ident
)
498 length
= gcov_read_unsigned ();
499 if (length
!= gfi_ptr
->lineno_checksum
)
502 length
= gcov_read_unsigned ();
503 if (length
!= gfi_ptr
->cfg_checksum
)
506 ci_ptr
= gfi_ptr
->ctrs
;
507 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
509 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
514 tag
= gcov_read_unsigned ();
515 length
= gcov_read_unsigned ();
516 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
517 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
519 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
522 if ((error
= gcov_is_error ()))
529 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
530 gi_filename
, f_ix
>= 0 ? "function" : "summary",
531 f_ix
< 0 ? -1 - f_ix
: f_ix
);
537 gcov_error ("profiling:%s:%s merging\n", gi_filename
,
538 error
< 0 ? "Overflow": "Error");
542 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
543 the case of appending to an existing file, SUMMARY_POS will be non-zero.
544 We will write the file starting from SUMMAY_POS. */
547 gcov_exit_write_gcda (const struct gcov_info
*gi_ptr
,
548 const struct gcov_summary
*prg_p
,
549 const gcov_position_t eof_pos
,
550 const gcov_position_t summary_pos
)
553 struct gcov_summary_buffer
*next_sum_buffer
;
555 /* Write out the data. */
558 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
559 gcov_write_unsigned (gi_ptr
->stamp
);
563 gcov_seek (summary_pos
);
565 /* Generate whole program statistics. */
566 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
568 /* Rewrite all the summaries that were after the summary we merged
569 into. This is necessary as the merged summary may have a different
570 size due to the number of non-zero histogram entries changing after
575 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
576 next_sum_buffer
= sum_buffer
->next
;
578 sum_buffer
= next_sum_buffer
;
581 /* Write execution counts for each function. */
582 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
584 unsigned buffered
= 0;
585 const struct gcov_fn_info
*gfi_ptr
;
586 const struct gcov_ctr_info
*ci_ptr
;
587 gcov_unsigned_t length
;
590 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
592 /* Buffered data from another program. */
594 gfi_ptr
= &fn_buffer
->info
;
595 length
= GCOV_TAG_FUNCTION_LENGTH
;
599 gfi_ptr
= gi_ptr
->functions
[f_ix
];
600 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
601 length
= GCOV_TAG_FUNCTION_LENGTH
;
606 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
610 gcov_write_unsigned (gfi_ptr
->ident
);
611 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
612 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
614 ci_ptr
= gfi_ptr
->ctrs
;
615 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
617 gcov_unsigned_t n_counts
;
620 if (!gi_ptr
->merge
[t_ix
])
623 n_counts
= ci_ptr
->num
;
624 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
625 GCOV_TAG_COUNTER_LENGTH (n_counts
));
626 c_ptr
= ci_ptr
->values
;
628 gcov_write_counter (*c_ptr
++);
632 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
635 gcov_write_unsigned (0);
638 /* Helper function for merging summary.
639 Return -1 on error. Return 0 on success. */
642 gcov_exit_merge_summary (const struct gcov_info
*gi_ptr
, struct gcov_summary
*prg
,
643 struct gcov_summary
*this_prg
, gcov_unsigned_t crc32
,
644 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
646 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
;
649 /* summary for all instances of program. */
650 struct gcov_ctr_summary
*cs_all
;
653 /* Merge the summaries. */
654 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
656 cs_prg
= &(prg
->ctrs
[t_ix
]);
657 cs_tprg
= &(this_prg
->ctrs
[t_ix
]);
659 if (gi_ptr
->merge
[t_ix
])
661 int first
= !cs_prg
->runs
;
666 cs_prg
->num
= cs_tprg
->num
;
667 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
668 if (cs_prg
->run_max
< cs_tprg
->run_max
)
669 cs_prg
->run_max
= cs_tprg
->run_max
;
670 cs_prg
->sum_max
+= cs_tprg
->run_max
;
672 memcpy (cs_prg
->histogram
, cs_tprg
->histogram
,
673 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
675 gcov_histogram_merge (cs_prg
->histogram
, cs_tprg
->histogram
);
677 else if (cs_prg
->runs
)
679 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
684 cs_all
= &all_prg
->ctrs
[t_ix
];
685 if (!cs_all
->runs
&& cs_prg
->runs
)
687 cs_all
->num
= cs_prg
->num
;
688 cs_all
->runs
= cs_prg
->runs
;
689 cs_all
->sum_all
= cs_prg
->sum_all
;
690 cs_all
->run_max
= cs_prg
->run_max
;
691 cs_all
->sum_max
= cs_prg
->sum_max
;
693 else if (!all_prg
->checksum
694 /* Don't compare the histograms, which may have slight
695 variations depending on the order they were updated
696 due to the truncating integer divides used in the
698 && (cs_all
->num
!= cs_prg
->num
699 || cs_all
->runs
!= cs_prg
->runs
700 || cs_all
->sum_all
!= cs_prg
->sum_all
701 || cs_all
->run_max
!= cs_prg
->run_max
702 || cs_all
->sum_max
!= cs_prg
->sum_max
))
704 gcov_error ("profiling:%s:Data file mismatch - some "
705 "data files may have been concurrently "
706 "updated without locking support\n", gi_filename
);
707 all_prg
->checksum
= ~0u;
712 prg
->checksum
= crc32
;
717 /* Dump the coverage counts for one gcov_info object. We merge with existing
718 counts when possible, to avoid growing the .da files ad infinitum. We use
719 this program's checksum to make sure we only accumulate whole program
720 statistics to the correct summary. An object file might be embedded
721 in two separate programs, and we must keep the two program
722 summaries separate. */
725 gcov_exit_dump_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename_aux
*gf
,
726 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
,
727 struct gcov_summary
*this_prg
)
729 struct gcov_summary prg
; /* summary for this object over all program. */
732 gcov_position_t summary_pos
= 0;
733 gcov_position_t eof_pos
= 0;
738 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
742 tag
= gcov_read_unsigned ();
745 /* Merge data from file. */
746 if (tag
!= GCOV_DATA_MAGIC
)
748 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename
);
751 error
= gcov_exit_merge_gcda (gi_ptr
, &prg
, this_prg
, &summary_pos
, &eof_pos
,
761 memset (&prg
, 0, sizeof (prg
));
762 summary_pos
= eof_pos
;
765 error
= gcov_exit_merge_summary (gi_ptr
, &prg
, this_prg
, crc32
, all_prg
);
769 gcov_exit_write_gcda (gi_ptr
, &prg
, eof_pos
, summary_pos
);
774 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
776 if ((error
= gcov_close ()))
777 gcov_error (error
< 0 ?
778 "profiling:%s:Overflow writing\n" :
779 "profiling:%s:Error writing\n",
784 /* Dump all the coverage counts for the program. It first computes program
785 summary and then traverses gcov_list list and dumps the gcov_info
786 objects one by one. */
791 struct gcov_info
*gi_ptr
;
792 struct gcov_filename_aux gf
;
793 gcov_unsigned_t crc32
;
794 struct gcov_summary all_prg
;
795 struct gcov_summary this_prg
;
797 /* Prevent the counters from being dumped a second time on exit when the
798 application already wrote out the profile using __gcov_dump(). */
799 if (gcov_dump_complete
)
802 crc32
= gcov_exit_compute_summary (&this_prg
);
804 allocate_filename_struct (&gf
);
806 memset (&all_prg
, 0, sizeof (all_prg
));
809 /* Now merge each file. */
810 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
811 gcov_exit_dump_gcov (gi_ptr
, &gf
, crc32
, &all_prg
, &this_prg
);
818 /* Reset all counters to zero. */
823 const struct gcov_info
*gi_ptr
;
825 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
829 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
832 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
834 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
836 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
837 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++)
839 if (!gi_ptr
->merge
[t_ix
])
842 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
849 /* Add a new object file onto the bb chain. Invoked automatically
850 when running an object file's global ctors. */
853 __gcov_init (struct gcov_info
*info
)
855 if (!info
->version
|| !info
->n_functions
)
857 if (gcov_version (info
, info
->version
, 0))
859 size_t filename_length
= strlen(info
->filename
);
861 /* Refresh the longest file name information */
862 if (filename_length
> gcov_max_filename
)
863 gcov_max_filename
= filename_length
;
868 info
->next
= gcov_list
;
875 #endif /* inhibit_libc */