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 *, ...);
53 struct gcov_fn_buffer
*next
;
55 struct gcov_fn_info info
;
56 /* note gcov_fn_info ends in a trailing array. */
59 struct gcov_summary_buffer
61 struct gcov_summary_buffer
*next
;
62 struct gcov_summary summary
;
65 /* A struct that bundles all the related information about the
70 char *filename
; /* filename buffer */
71 size_t max_length
; /* maximum filename length */
72 int strip
; /* leading chars to strip from filename */
73 size_t prefix
; /* chars to prepend to filename */
76 /* Chain of per-object gcov structures. */
78 /* We need to expose this static variable when compiling for gcov-tool. */
81 struct gcov_info
*gcov_list
;
83 /* Flag when the profile has already been dumped via __gcov_dump(). */
84 static int gcov_dump_complete
;
86 static struct gcov_fn_buffer
*
87 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
90 struct gcov_fn_buffer
*next
;
91 unsigned ix
, n_ctr
= 0;
97 for (ix
= 0; ix
!= limit
; ix
++)
98 if (gi_ptr
->merge
[ix
])
99 free (buffer
->info
.ctrs
[n_ctr
++].values
);
104 static struct gcov_fn_buffer
**
105 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
106 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
108 unsigned n_ctrs
= 0, ix
= 0;
109 struct gcov_fn_buffer
*fn_buffer
;
112 for (ix
= GCOV_COUNTERS
; ix
--;)
113 if (gi_ptr
->merge
[ix
])
116 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
117 fn_buffer
= (struct gcov_fn_buffer
*) xmalloc (len
);
123 fn_buffer
->fn_ix
= fn_ix
;
124 fn_buffer
->info
.ident
= gcov_read_unsigned ();
125 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
126 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
128 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
130 gcov_unsigned_t length
;
133 if (!gi_ptr
->merge
[ix
])
136 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
142 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
143 len
= length
* sizeof (gcov_type
);
144 values
= (gcov_type
*) xmalloc (len
);
148 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
149 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
152 *values
++ = gcov_read_counter ();
156 *end_ptr
= fn_buffer
;
157 return &fn_buffer
->next
;
160 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
161 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
163 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
166 /* Add an unsigned value to the current crc */
168 static gcov_unsigned_t
169 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
173 for (ix
= 32; ix
--; value
<<= 1)
177 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
185 /* Check if VERSION of the info block PTR matches libgcov one.
186 Return 1 on success, or zero in case of versions mismatch.
187 If FILENAME is not NULL, its value used for reporting purposes
188 instead of value from the info block. */
191 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
192 const char *filename
)
194 if (version
!= GCOV_VERSION
)
198 GCOV_UNSIGNED2STRING (v
, version
);
199 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
201 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
202 filename
? filename
: ptr
->filename
, e
, v
);
208 /* Insert counter VALUE into HISTOGRAM. */
211 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
215 i
= gcov_histo_index(value
);
216 histogram
[i
].num_counters
++;
217 histogram
[i
].cum_value
+= value
;
218 if (value
< histogram
[i
].min_value
)
219 histogram
[i
].min_value
= value
;
222 /* Computes a histogram of the arc counters to place in the summary SUM. */
225 gcov_compute_histogram (struct gcov_summary
*sum
)
227 struct gcov_info
*gi_ptr
;
228 const struct gcov_fn_info
*gfi_ptr
;
229 const struct gcov_ctr_info
*ci_ptr
;
230 struct gcov_ctr_summary
*cs_ptr
;
231 unsigned t_ix
, f_ix
, ctr_info_ix
, ix
;
234 /* This currently only applies to arc counters. */
235 t_ix
= GCOV_COUNTER_ARCS
;
237 /* First check if there are any counts recorded for this counter. */
238 cs_ptr
= &(sum
->ctrs
[t_ix
]);
242 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
244 cs_ptr
->histogram
[h_ix
].num_counters
= 0;
245 cs_ptr
->histogram
[h_ix
].min_value
= cs_ptr
->run_max
;
246 cs_ptr
->histogram
[h_ix
].cum_value
= 0;
249 /* Walk through all the per-object structures and record each of
250 the count values in histogram. */
251 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
253 if (!gi_ptr
->merge
[t_ix
])
256 /* Find the appropriate index into the gcov_ctr_info array
257 for the counter we are currently working on based on the
258 existence of the merge function pointer for this object. */
259 for (ix
= 0, ctr_info_ix
= 0; ix
< t_ix
; ix
++)
261 if (gi_ptr
->merge
[ix
])
264 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
266 gfi_ptr
= gi_ptr
->functions
[f_ix
];
268 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
271 ci_ptr
= &gfi_ptr
->ctrs
[ctr_info_ix
];
272 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
273 gcov_histogram_insert (cs_ptr
->histogram
, ci_ptr
->values
[ix
]);
278 /* buffer for the fn_data from another program. */
279 static struct gcov_fn_buffer
*fn_buffer
;
280 /* buffer for summary from other programs to be written out. */
281 static struct gcov_summary_buffer
*sum_buffer
;
282 /* If application calls fork or exec multiple times, we end up storing
283 profile repeadely. We should not account this as multiple runs or
284 functions executed once may mistakely become cold. */
285 static int run_accounted
= 0;
287 /* This function computes the program level summary and the histo-gram.
288 It computes and returns CRC32 and stored summary in THIS_PRG.
289 Also determines the longest filename length of the info files. */
291 static gcov_unsigned_t
292 compute_summary (struct gcov_info
*list
, struct gcov_summary
*this_prg
,
295 struct gcov_info
*gi_ptr
;
296 const struct gcov_fn_info
*gfi_ptr
;
297 struct gcov_ctr_summary
*cs_ptr
;
298 const struct gcov_ctr_info
*ci_ptr
;
301 gcov_unsigned_t c_num
;
302 gcov_unsigned_t crc32
= 0;
304 /* Find the totals for this execution. */
305 memset (this_prg
, 0, sizeof (*this_prg
));
307 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
309 size_t len
= strlen (gi_ptr
->filename
);
310 if (len
> *max_length
)
313 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
314 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
316 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
318 gfi_ptr
= gi_ptr
->functions
[f_ix
];
320 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
323 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
324 crc32
= crc32_unsigned (crc32
,
325 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
329 ci_ptr
= gfi_ptr
->ctrs
;
330 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
332 if (!gi_ptr
->merge
[t_ix
])
335 cs_ptr
= &(this_prg
->ctrs
[t_ix
]);
336 cs_ptr
->num
+= ci_ptr
->num
;
337 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
339 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
341 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
342 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
343 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
349 gcov_compute_histogram (this_prg
);
353 /* Including system dependent components. */
354 #include "libgcov-driver-system.c"
356 /* This function merges counters in GI_PTR to an existing gcda file.
358 Return -1 on error. In this case, caller will goto read_fatal. */
361 merge_one_data (const char *filename
,
362 struct gcov_info
*gi_ptr
,
363 struct gcov_summary
*prg_p
,
364 struct gcov_summary
*this_prg
,
365 gcov_position_t
*summary_pos_p
,
366 gcov_position_t
*eof_pos_p
,
367 gcov_unsigned_t crc32
)
369 gcov_unsigned_t tag
, length
;
373 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
374 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
376 length
= gcov_read_unsigned ();
377 if (!gcov_version (gi_ptr
, length
, filename
))
380 length
= gcov_read_unsigned ();
381 if (length
!= gi_ptr
->stamp
)
382 /* Read from a different compilation. Overwrite the file. */
385 /* Look for program summary. */
388 struct gcov_summary tmp
;
390 *eof_pos_p
= gcov_position ();
391 tag
= gcov_read_unsigned ();
392 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
396 length
= gcov_read_unsigned ();
397 gcov_read_summary (&tmp
);
398 if ((error
= gcov_is_error ()))
402 /* Save all summaries after the one that will be
403 merged into below. These will need to be rewritten
404 as histogram merging may change the number of non-zero
405 histogram entries that will be emitted, and thus the
406 size of the merged summary. */
407 (*sum_tail
) = (struct gcov_summary_buffer
*)
408 xmalloc (sizeof(struct gcov_summary_buffer
));
409 (*sum_tail
)->summary
= tmp
;
410 (*sum_tail
)->next
= 0;
411 sum_tail
= &((*sum_tail
)->next
);
414 if (tmp
.checksum
!= crc32
)
417 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
418 if (tmp
.ctrs
[t_ix
].num
!= this_prg
->ctrs
[t_ix
].num
)
421 *summary_pos_p
= *eof_pos_p
;
426 /* Merge execution counts for each function. */
427 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
428 f_ix
++, tag
= gcov_read_unsigned ())
430 const struct gcov_ctr_info
*ci_ptr
;
431 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
433 if (tag
!= GCOV_TAG_FUNCTION
)
436 length
= gcov_read_unsigned ();
438 /* This function did not appear in the other program.
439 We have nothing to merge. */
442 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
445 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
447 /* This function appears in the other program. We
448 need to buffer the information in order to write
449 it back out -- we'll be inserting data before
450 this point, so cannot simply keep the data in the
452 fn_tail
= buffer_fn_data (filename
, gi_ptr
, fn_tail
, f_ix
);
458 length
= gcov_read_unsigned ();
459 if (length
!= gfi_ptr
->ident
)
462 length
= gcov_read_unsigned ();
463 if (length
!= gfi_ptr
->lineno_checksum
)
466 length
= gcov_read_unsigned ();
467 if (length
!= gfi_ptr
->cfg_checksum
)
470 ci_ptr
= gfi_ptr
->ctrs
;
471 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
473 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
478 tag
= gcov_read_unsigned ();
479 length
= gcov_read_unsigned ();
480 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
481 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
483 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
486 if ((error
= gcov_is_error ()))
493 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
494 filename
, f_ix
>= 0 ? "function" : "summary",
495 f_ix
< 0 ? -1 - f_ix
: f_ix
);
501 gcov_error ("profiling:%s:%s merging\n", filename
,
502 error
< 0 ? "Overflow": "Error");
506 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
507 the case of appending to an existing file, SUMMARY_POS will be non-zero.
508 We will write the file starting from SUMMAY_POS. */
511 write_one_data (const struct gcov_info
*gi_ptr
,
512 const struct gcov_summary
*prg_p
,
513 const gcov_position_t eof_pos
,
514 const gcov_position_t summary_pos
)
517 struct gcov_summary_buffer
*next_sum_buffer
;
519 /* Write out the data. */
522 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
523 gcov_write_unsigned (gi_ptr
->stamp
);
527 gcov_seek (summary_pos
);
529 /* Generate whole program statistics. */
530 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
532 /* Rewrite all the summaries that were after the summary we merged
533 into. This is necessary as the merged summary may have a different
534 size due to the number of non-zero histogram entries changing after
539 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
540 next_sum_buffer
= sum_buffer
->next
;
542 sum_buffer
= next_sum_buffer
;
545 /* Write execution counts for each function. */
546 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
548 unsigned buffered
= 0;
549 const struct gcov_fn_info
*gfi_ptr
;
550 const struct gcov_ctr_info
*ci_ptr
;
551 gcov_unsigned_t length
;
554 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
556 /* Buffered data from another program. */
558 gfi_ptr
= &fn_buffer
->info
;
559 length
= GCOV_TAG_FUNCTION_LENGTH
;
563 gfi_ptr
= gi_ptr
->functions
[f_ix
];
564 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
565 length
= GCOV_TAG_FUNCTION_LENGTH
;
570 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
574 gcov_write_unsigned (gfi_ptr
->ident
);
575 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
576 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
578 ci_ptr
= gfi_ptr
->ctrs
;
579 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
581 gcov_unsigned_t n_counts
;
584 if (!gi_ptr
->merge
[t_ix
])
587 n_counts
= ci_ptr
->num
;
588 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
589 GCOV_TAG_COUNTER_LENGTH (n_counts
));
590 c_ptr
= ci_ptr
->values
;
592 gcov_write_counter (*c_ptr
++);
596 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
599 gcov_write_unsigned (0);
602 /* Helper function for merging summary.
603 Return -1 on error. Return 0 on success. */
606 merge_summary (const char *filename
, int run_counted
,
607 const struct gcov_info
*gi_ptr
, struct gcov_summary
*prg
,
608 struct gcov_summary
*this_prg
, gcov_unsigned_t crc32
,
609 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
611 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
;
614 /* summary for all instances of program. */
615 struct gcov_ctr_summary
*cs_all
;
618 /* Merge the summaries. */
619 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
621 cs_prg
= &(prg
->ctrs
[t_ix
]);
622 cs_tprg
= &(this_prg
->ctrs
[t_ix
]);
624 if (gi_ptr
->merge
[t_ix
])
626 int first
= !cs_prg
->runs
;
631 cs_prg
->num
= cs_tprg
->num
;
632 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
633 if (cs_prg
->run_max
< cs_tprg
->run_max
)
634 cs_prg
->run_max
= cs_tprg
->run_max
;
635 cs_prg
->sum_max
+= cs_tprg
->run_max
;
637 memcpy (cs_prg
->histogram
, cs_tprg
->histogram
,
638 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
640 gcov_histogram_merge (cs_prg
->histogram
, cs_tprg
->histogram
);
642 else if (cs_prg
->runs
)
644 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
649 cs_all
= &all_prg
->ctrs
[t_ix
];
650 if (!cs_all
->runs
&& cs_prg
->runs
)
652 cs_all
->num
= cs_prg
->num
;
653 cs_all
->runs
= cs_prg
->runs
;
654 cs_all
->sum_all
= cs_prg
->sum_all
;
655 cs_all
->run_max
= cs_prg
->run_max
;
656 cs_all
->sum_max
= cs_prg
->sum_max
;
658 else if (!all_prg
->checksum
659 /* Don't compare the histograms, which may have slight
660 variations depending on the order they were updated
661 due to the truncating integer divides used in the
663 && (cs_all
->num
!= cs_prg
->num
664 || cs_all
->runs
!= cs_prg
->runs
665 || cs_all
->sum_all
!= cs_prg
->sum_all
666 || cs_all
->run_max
!= cs_prg
->run_max
667 || cs_all
->sum_max
!= cs_prg
->sum_max
))
669 gcov_error ("profiling:%s:Data file mismatch - some "
670 "data files may have been concurrently "
671 "updated without locking support\n", filename
);
672 all_prg
->checksum
= ~0u;
677 prg
->checksum
= crc32
;
682 /* Dump the coverage counts for one gcov_info object. We merge with existing
683 counts when possible, to avoid growing the .da files ad infinitum. We use
684 this program's checksum to make sure we only accumulate whole program
685 statistics to the correct summary. An object file might be embedded
686 in two separate programs, and we must keep the two program
687 summaries separate. */
690 dump_one_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename
*gf
,
691 unsigned run_counted
,
692 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
,
693 struct gcov_summary
*this_prg
)
695 struct gcov_summary prg
; /* summary for this object over all program. */
698 gcov_position_t summary_pos
= 0;
699 gcov_position_t eof_pos
= 0;
704 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
708 tag
= gcov_read_unsigned ();
711 /* Merge data from file. */
712 if (tag
!= GCOV_DATA_MAGIC
)
714 gcov_error ("profiling:%s:Not a gcov data file\n", gf
->filename
);
717 error
= merge_one_data (gf
->filename
, gi_ptr
, &prg
, this_prg
,
718 &summary_pos
, &eof_pos
, crc32
);
727 memset (&prg
, 0, sizeof (prg
));
728 summary_pos
= eof_pos
;
731 error
= merge_summary (gf
->filename
, run_counted
, gi_ptr
, &prg
, this_prg
,
736 write_one_data (gi_ptr
, &prg
, eof_pos
, summary_pos
);
741 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
743 if ((error
= gcov_close ()))
744 gcov_error (error
< 0 ?
745 "profiling:%s:Overflow writing\n" :
746 "profiling:%s:Error writing\n",
751 /* Dump all the coverage counts for the program. It first computes program
752 summary and then traverses gcov_list list and dumps the gcov_info
753 objects one by one. */
755 void ATTRIBUTE_HIDDEN
756 gcov_do_dump (struct gcov_info
*list
, int run_counted
)
758 struct gcov_info
*gi_ptr
;
759 struct gcov_filename gf
;
760 gcov_unsigned_t crc32
;
761 struct gcov_summary all_prg
;
762 struct gcov_summary this_prg
;
764 crc32
= compute_summary (list
, &this_prg
, &gf
.max_length
);
766 allocate_filename_struct (&gf
);
768 memset (&all_prg
, 0, sizeof (all_prg
));
771 /* Now merge each file. */
772 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
773 dump_one_gcov (gi_ptr
, &gf
, run_counted
, crc32
, &all_prg
, &this_prg
);
782 /* Prevent the counters from being dumped a second time on exit when the
783 application already wrote out the profile using __gcov_dump(). */
784 if (gcov_dump_complete
)
787 gcov_dump_complete
= 1;
789 gcov_do_dump (gcov_list
, run_accounted
);
794 /* Reset all counters to zero. */
799 const struct gcov_info
*gi_ptr
;
801 gcov_dump_complete
= 0;
802 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
806 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
809 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
811 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
813 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
814 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++)
816 if (!gi_ptr
->merge
[t_ix
])
819 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
826 /* Add a new object file onto the bb chain. Invoked automatically
827 when running an object file's global ctors. */
830 __gcov_init (struct gcov_info
*info
)
832 if (!info
->version
|| !info
->n_functions
)
834 if (gcov_version (info
, info
->version
, 0))
839 info
->next
= gcov_list
;
844 #endif /* !IN_GCOV_TOOL */
846 #endif /* inhibit_libc */