1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2013 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 #include "coretypes.h"
30 #include "libgcc_tm.h"
32 #if defined(inhibit_libc)
33 #define IN_LIBGCOV (-1)
37 #define GCOV_LINKAGE /* nothing */
42 #if defined(inhibit_libc)
43 /* If libc and its header files are not available, provide dummy functions. */
46 void __gcov_init (struct gcov_info
*p
__attribute__ ((unused
))) {}
49 #else /* inhibit_libc */
61 /* The following functions can be called from outside of this file. */
62 extern void gcov_clear (void) ATTRIBUTE_HIDDEN
;
63 extern void gcov_exit (void) ATTRIBUTE_HIDDEN
;
64 extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN
;
65 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN
;
66 extern int get_gcov_dump_complete (void) ATTRIBUTE_HIDDEN
;
67 extern void set_gcov_list (struct gcov_info
*) ATTRIBUTE_HIDDEN
;
71 struct gcov_fn_buffer
*next
;
73 struct gcov_fn_info info
;
74 /* note gcov_fn_info ends in a trailing array. */
77 struct gcov_summary_buffer
79 struct gcov_summary_buffer
*next
;
80 struct gcov_summary summary
;
83 /* Chain of per-object gcov structures. */
84 static struct gcov_info
*gcov_list
;
86 /* Set the head of gcov_list. */
88 set_gcov_list (struct gcov_info
*head
)
93 /* Size of the longest file name. */
94 static size_t gcov_max_filename
= 0;
96 /* Flag when the profile has already been dumped via __gcov_dump(). */
97 static int gcov_dump_complete
;
99 /* A global function that get the vaule of gcov_dump_complete. */
102 get_gcov_dump_complete (void)
104 return gcov_dump_complete
;
107 /* A global functino that set the vaule of gcov_dump_complete. Will
108 be used in __gcov_dump() in libgcov-interface.c. */
111 set_gcov_dump_complete (void)
113 gcov_dump_complete
= 1;
116 /* A global functino that set the vaule of gcov_dump_complete. Will
117 be used in __gcov_reset() in libgcov-interface.c. */
120 reset_gcov_dump_complete (void)
122 gcov_dump_complete
= 0;
125 /* A utility function for outputing errors. */
126 static int gcov_error (const char *, ...);
128 static struct gcov_fn_buffer
*
129 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
132 struct gcov_fn_buffer
*next
;
133 unsigned ix
, n_ctr
= 0;
139 for (ix
= 0; ix
!= limit
; ix
++)
140 if (gi_ptr
->merge
[ix
])
141 free (buffer
->info
.ctrs
[n_ctr
++].values
);
146 static struct gcov_fn_buffer
**
147 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
148 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
150 unsigned n_ctrs
= 0, ix
= 0;
151 struct gcov_fn_buffer
*fn_buffer
;
154 for (ix
= GCOV_COUNTERS
; ix
--;)
155 if (gi_ptr
->merge
[ix
])
158 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
159 fn_buffer
= (struct gcov_fn_buffer
*)malloc (len
);
165 fn_buffer
->fn_ix
= fn_ix
;
166 fn_buffer
->info
.ident
= gcov_read_unsigned ();
167 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
168 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
170 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
172 gcov_unsigned_t length
;
175 if (!gi_ptr
->merge
[ix
])
178 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
184 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
185 len
= length
* sizeof (gcov_type
);
186 values
= (gcov_type
*)malloc (len
);
190 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
191 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
194 *values
++ = gcov_read_counter ();
198 *end_ptr
= fn_buffer
;
199 return &fn_buffer
->next
;
202 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
203 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
205 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
208 /* Add an unsigned value to the current crc */
210 static gcov_unsigned_t
211 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
215 for (ix
= 32; ix
--; value
<<= 1)
219 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
227 /* Check if VERSION of the info block PTR matches libgcov one.
228 Return 1 on success, or zero in case of versions mismatch.
229 If FILENAME is not NULL, its value used for reporting purposes
230 instead of value from the info block. */
233 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
234 const char *filename
)
236 if (version
!= GCOV_VERSION
)
240 GCOV_UNSIGNED2STRING (v
, version
);
241 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
243 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
244 filename
? filename
: ptr
->filename
, e
, v
);
250 /* Insert counter VALUE into HISTOGRAM. */
253 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
257 i
= gcov_histo_index(value
);
258 histogram
[i
].num_counters
++;
259 histogram
[i
].cum_value
+= value
;
260 if (value
< histogram
[i
].min_value
)
261 histogram
[i
].min_value
= value
;
264 /* Computes a histogram of the arc counters to place in the summary SUM. */
267 gcov_compute_histogram (struct gcov_summary
*sum
)
269 struct gcov_info
*gi_ptr
;
270 const struct gcov_fn_info
*gfi_ptr
;
271 const struct gcov_ctr_info
*ci_ptr
;
272 struct gcov_ctr_summary
*cs_ptr
;
273 unsigned t_ix
, f_ix
, ctr_info_ix
, ix
;
276 /* This currently only applies to arc counters. */
277 t_ix
= GCOV_COUNTER_ARCS
;
279 /* First check if there are any counts recorded for this counter. */
280 cs_ptr
= &(sum
->ctrs
[t_ix
]);
284 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
286 cs_ptr
->histogram
[h_ix
].num_counters
= 0;
287 cs_ptr
->histogram
[h_ix
].min_value
= cs_ptr
->run_max
;
288 cs_ptr
->histogram
[h_ix
].cum_value
= 0;
291 /* Walk through all the per-object structures and record each of
292 the count values in histogram. */
293 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
295 if (!gi_ptr
->merge
[t_ix
])
298 /* Find the appropriate index into the gcov_ctr_info array
299 for the counter we are currently working on based on the
300 existence of the merge function pointer for this object. */
301 for (ix
= 0, ctr_info_ix
= 0; ix
< t_ix
; ix
++)
303 if (gi_ptr
->merge
[ix
])
306 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
308 gfi_ptr
= gi_ptr
->functions
[f_ix
];
310 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
313 ci_ptr
= &gfi_ptr
->ctrs
[ctr_info_ix
];
314 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
315 gcov_histogram_insert (cs_ptr
->histogram
, ci_ptr
->values
[ix
]);
320 /* summary for program. */
321 static struct gcov_summary this_prg
;
323 static char *gi_filename
;
324 /* buffer for the fn_data from another program. */
325 static struct gcov_fn_buffer
*fn_buffer
;
326 /* buffer for summary from other programs to be written out. */
327 static struct gcov_summary_buffer
*sum_buffer
;
328 /* If application calls fork or exec multiple times, we end up storing
329 profile repeadely. We should not account this as multiple runs or
330 functions executed once may mistakely become cold. */
331 static int run_accounted
= 0;
333 /* This funtions computes the program level summary and the histo-gram.
334 It computes and returns CRC32 and stored summari in THIS_PRG. */
336 static gcov_unsigned_t
337 gcov_exit_compute_summary (void)
339 struct gcov_info
*gi_ptr
;
340 const struct gcov_fn_info
*gfi_ptr
;
341 struct gcov_ctr_summary
*cs_ptr
;
342 const struct gcov_ctr_info
*ci_ptr
;
345 gcov_unsigned_t c_num
;
346 gcov_unsigned_t crc32
= 0;
348 /* Find the totals for this execution. */
349 memset (&this_prg
, 0, sizeof (this_prg
));
350 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
352 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
353 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
355 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
357 gfi_ptr
= gi_ptr
->functions
[f_ix
];
359 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
362 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
363 crc32
= crc32_unsigned (crc32
,
364 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
368 ci_ptr
= gfi_ptr
->ctrs
;
369 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
371 if (!gi_ptr
->merge
[t_ix
])
374 cs_ptr
= &this_prg
.ctrs
[t_ix
];
375 cs_ptr
->num
+= ci_ptr
->num
;
376 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
378 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
380 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
381 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
382 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
388 gcov_compute_histogram (&this_prg
);
392 /* A struct that bundles all the related information about the
394 struct gcov_filename_aux
{
395 char *gi_filename_up
;
396 int gcov_prefix_strip
;
397 size_t prefix_length
;
400 /* Including system dependent components. */
401 #include "libgcov-driver-system.c"
403 /* This function merges counters in GI_PTR to an existing gcda file.
405 Return -1 on error. In this case, caller will goto read_fatal. */
408 gcov_exit_merge_gcda (struct gcov_info
*gi_ptr
,
409 struct gcov_summary
*prg_p
,
410 gcov_position_t
*summary_pos_p
,
411 gcov_position_t
*eof_pos_p
,
412 gcov_unsigned_t crc32
)
414 gcov_unsigned_t tag
, length
;
418 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
419 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
421 length
= gcov_read_unsigned ();
422 if (!gcov_version (gi_ptr
, length
, gi_filename
))
425 length
= gcov_read_unsigned ();
426 if (length
!= gi_ptr
->stamp
)
427 /* Read from a different compilation. Overwrite the file. */
430 /* Look for program summary. */
433 struct gcov_summary tmp
;
435 *eof_pos_p
= gcov_position ();
436 tag
= gcov_read_unsigned ();
437 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
441 length
= gcov_read_unsigned ();
442 gcov_read_summary (&tmp
);
443 if ((error
= gcov_is_error ()))
447 /* Save all summaries after the one that will be
448 merged into below. These will need to be rewritten
449 as histogram merging may change the number of non-zero
450 histogram entries that will be emitted, and thus the
451 size of the merged summary. */
452 (*sum_tail
) = (struct gcov_summary_buffer
*)
453 malloc (sizeof(struct gcov_summary_buffer
));
454 (*sum_tail
)->summary
= tmp
;
455 (*sum_tail
)->next
= 0;
456 sum_tail
= &((*sum_tail
)->next
);
459 if (tmp
.checksum
!= crc32
)
462 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
463 if (tmp
.ctrs
[t_ix
].num
!= this_prg
.ctrs
[t_ix
].num
)
466 *summary_pos_p
= *eof_pos_p
;
471 /* Merge execution counts for each function. */
472 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
473 f_ix
++, tag
= gcov_read_unsigned ())
475 const struct gcov_ctr_info
*ci_ptr
;
476 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
478 if (tag
!= GCOV_TAG_FUNCTION
)
481 length
= gcov_read_unsigned ();
483 /* This function did not appear in the other program.
484 We have nothing to merge. */
487 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
490 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
492 /* This function appears in the other program. We
493 need to buffer the information in order to write
494 it back out -- we'll be inserting data before
495 this point, so cannot simply keep the data in the
497 fn_tail
= buffer_fn_data (gi_filename
,
498 gi_ptr
, fn_tail
, f_ix
);
504 length
= gcov_read_unsigned ();
505 if (length
!= gfi_ptr
->ident
)
508 length
= gcov_read_unsigned ();
509 if (length
!= gfi_ptr
->lineno_checksum
)
512 length
= gcov_read_unsigned ();
513 if (length
!= gfi_ptr
->cfg_checksum
)
516 ci_ptr
= gfi_ptr
->ctrs
;
517 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
519 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
524 tag
= gcov_read_unsigned ();
525 length
= gcov_read_unsigned ();
526 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
527 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
529 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
532 if ((error
= gcov_is_error ()))
539 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
540 gi_filename
, f_ix
>= 0 ? "function" : "summary",
541 f_ix
< 0 ? -1 - f_ix
: f_ix
);
547 gcov_error ("profiling:%s:%s merging\n", gi_filename
,
548 error
< 0 ? "Overflow": "Error");
552 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
553 the case of appending to an existing file, SUMMARY_POS will be non-zero.
554 We will write the file starting from SUMMAY_POS. */
557 gcov_exit_write_gcda (const struct gcov_info
*gi_ptr
,
558 const struct gcov_summary
*prg_p
,
559 const gcov_position_t eof_pos
,
560 const gcov_position_t summary_pos
)
563 struct gcov_summary_buffer
*next_sum_buffer
;
565 /* Write out the data. */
568 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
569 gcov_write_unsigned (gi_ptr
->stamp
);
573 gcov_seek (summary_pos
);
575 /* Generate whole program statistics. */
576 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
578 /* Rewrite all the summaries that were after the summary we merged
579 into. This is necessary as the merged summary may have a different
580 size due to the number of non-zero histogram entries changing after
585 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
586 next_sum_buffer
= sum_buffer
->next
;
588 sum_buffer
= next_sum_buffer
;
591 /* Write execution counts for each function. */
592 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
594 unsigned buffered
= 0;
595 const struct gcov_fn_info
*gfi_ptr
;
596 const struct gcov_ctr_info
*ci_ptr
;
597 gcov_unsigned_t length
;
600 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
602 /* Buffered data from another program. */
604 gfi_ptr
= &fn_buffer
->info
;
605 length
= GCOV_TAG_FUNCTION_LENGTH
;
609 gfi_ptr
= gi_ptr
->functions
[f_ix
];
610 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
611 length
= GCOV_TAG_FUNCTION_LENGTH
;
616 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
620 gcov_write_unsigned (gfi_ptr
->ident
);
621 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
622 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
624 ci_ptr
= gfi_ptr
->ctrs
;
625 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
627 gcov_unsigned_t n_counts
;
630 if (!gi_ptr
->merge
[t_ix
])
633 n_counts
= ci_ptr
->num
;
634 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
635 GCOV_TAG_COUNTER_LENGTH (n_counts
));
636 c_ptr
= ci_ptr
->values
;
638 gcov_write_counter (*c_ptr
++);
642 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
645 gcov_write_unsigned (0);
648 /* Helper function for merging summary.
649 Return -1 on error. Return 0 on success. */
652 gcov_exit_merge_summary (const struct gcov_info
*gi_ptr
, struct gcov_summary
*prg
,
653 gcov_unsigned_t crc32
,
654 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
656 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
;
659 /* summary for all instances of program. */
660 struct gcov_ctr_summary
*cs_all
;
663 /* Merge the summaries. */
664 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
666 cs_prg
= &(prg
->ctrs
[t_ix
]);
667 cs_tprg
= &this_prg
.ctrs
[t_ix
];
669 if (gi_ptr
->merge
[t_ix
])
671 int first
= !cs_prg
->runs
;
676 cs_prg
->num
= cs_tprg
->num
;
677 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
678 if (cs_prg
->run_max
< cs_tprg
->run_max
)
679 cs_prg
->run_max
= cs_tprg
->run_max
;
680 cs_prg
->sum_max
+= cs_tprg
->run_max
;
682 memcpy (cs_prg
->histogram
, cs_tprg
->histogram
,
683 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
685 gcov_histogram_merge (cs_prg
->histogram
, cs_tprg
->histogram
);
687 else if (cs_prg
->runs
)
689 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
694 cs_all
= &all_prg
->ctrs
[t_ix
];
695 if (!cs_all
->runs
&& cs_prg
->runs
)
697 cs_all
->num
= cs_prg
->num
;
698 cs_all
->runs
= cs_prg
->runs
;
699 cs_all
->sum_all
= cs_prg
->sum_all
;
700 cs_all
->run_max
= cs_prg
->run_max
;
701 cs_all
->sum_max
= cs_prg
->sum_max
;
703 else if (!all_prg
->checksum
704 /* Don't compare the histograms, which may have slight
705 variations depending on the order they were updated
706 due to the truncating integer divides used in the
708 && (cs_all
->num
!= cs_prg
->num
709 || cs_all
->runs
!= cs_prg
->runs
710 || cs_all
->sum_all
!= cs_prg
->sum_all
711 || cs_all
->run_max
!= cs_prg
->run_max
712 || cs_all
->sum_max
!= cs_prg
->sum_max
))
714 gcov_error ("profiling:%s:Data file mismatch - some "
715 "data files may have been concurrently "
716 "updated without locking support\n", gi_filename
);
717 all_prg
->checksum
= ~0u;
722 prg
->checksum
= crc32
;
727 /* Dump the coverage counts for one gcov_info object. We merge with existing
728 counts when possible, to avoid growing the .da files ad infinitum. We use
729 this program's checksum to make sure we only accumulate whole program
730 statistics to the correct summary. An object file might be embedded
731 in two separate programs, and we must keep the two program
732 summaries separate. */
735 gcov_exit_dump_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename_aux
*gf
,
736 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
)
738 struct gcov_summary prg
; /* summary for this object over all program. */
741 gcov_position_t summary_pos
= 0;
742 gcov_position_t eof_pos
= 0;
747 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
751 tag
= gcov_read_unsigned ();
754 /* Merge data from file. */
755 if (tag
!= GCOV_DATA_MAGIC
)
757 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename
);
760 error
= gcov_exit_merge_gcda (gi_ptr
, &prg
, &summary_pos
, &eof_pos
,
770 memset (&prg
, 0, sizeof (prg
));
771 summary_pos
= eof_pos
;
774 error
= gcov_exit_merge_summary (gi_ptr
, &prg
, crc32
, all_prg
);
778 gcov_exit_write_gcda (gi_ptr
, &prg
, eof_pos
, summary_pos
);
783 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
785 if ((error
= gcov_close ()))
786 gcov_error (error
< 0 ?
787 "profiling:%s:Overflow writing\n" :
788 "profiling:%s:Error writing\n",
793 /* Dump all the coverage counts for the program. It first computes program
794 summary and then traverses gcov_list list and dumps the gcov_info
795 objects one by one. */
800 struct gcov_info
*gi_ptr
;
801 struct gcov_filename_aux gf
;
802 gcov_unsigned_t crc32
;
803 struct gcov_summary all_prg
;
805 /* Prevent the counters from being dumped a second time on exit when the
806 application already wrote out the profile using __gcov_dump(). */
807 if (gcov_dump_complete
)
810 crc32
= gcov_exit_compute_summary ();
812 allocate_filename_struct (&gf
);
814 memset (&all_prg
, 0, sizeof (all_prg
));
817 /* Now merge each file. */
818 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
819 gcov_exit_dump_gcov (gi_ptr
, &gf
, crc32
, &all_prg
);
826 /* Reset all counters to zero. */
831 const struct gcov_info
*gi_ptr
;
833 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
837 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
840 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
842 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
844 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
845 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++)
847 if (!gi_ptr
->merge
[t_ix
])
850 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
857 /* Add a new object file onto the bb chain. Invoked automatically
858 when running an object file's global ctors. */
861 __gcov_init (struct gcov_info
*info
)
863 if (!info
->version
|| !info
->n_functions
)
865 if (gcov_version (info
, info
->version
, 0))
867 size_t filename_length
= strlen(info
->filename
);
869 /* Refresh the longest file name information */
870 if (filename_length
> gcov_max_filename
)
871 gcov_max_filename
= filename_length
;
876 info
->next
= gcov_list
;
883 #endif /* inhibit_libc */