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 int strip
; /* leading chars to strip from filename */
76 char *prefix
; /* prefix string */
79 static struct gcov_fn_buffer
*
80 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
83 struct gcov_fn_buffer
*next
;
84 unsigned ix
, n_ctr
= 0;
90 for (ix
= 0; ix
!= limit
; ix
++)
91 if (gi_ptr
->merge
[ix
])
92 free (buffer
->info
.ctrs
[n_ctr
++].values
);
97 static struct gcov_fn_buffer
**
98 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
99 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
101 unsigned n_ctrs
= 0, ix
= 0;
102 struct gcov_fn_buffer
*fn_buffer
;
105 for (ix
= GCOV_COUNTERS
; ix
--;)
106 if (gi_ptr
->merge
[ix
])
109 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
110 fn_buffer
= (struct gcov_fn_buffer
*) xmalloc (len
);
116 fn_buffer
->fn_ix
= fn_ix
;
117 fn_buffer
->info
.ident
= gcov_read_unsigned ();
118 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
119 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
121 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
123 gcov_unsigned_t length
;
126 if (!gi_ptr
->merge
[ix
])
129 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
135 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
136 len
= length
* sizeof (gcov_type
);
137 values
= (gcov_type
*) xmalloc (len
);
141 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
142 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
145 *values
++ = gcov_read_counter ();
149 *end_ptr
= fn_buffer
;
150 return &fn_buffer
->next
;
153 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
154 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
156 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
159 /* Add an unsigned value to the current crc */
161 static gcov_unsigned_t
162 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
166 for (ix
= 32; ix
--; value
<<= 1)
170 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
178 /* Check if VERSION of the info block PTR matches libgcov one.
179 Return 1 on success, or zero in case of versions mismatch.
180 If FILENAME is not NULL, its value used for reporting purposes
181 instead of value from the info block. */
184 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
185 const char *filename
)
187 if (version
!= GCOV_VERSION
)
191 GCOV_UNSIGNED2STRING (v
, version
);
192 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
194 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
195 filename
? filename
: ptr
->filename
, e
, v
);
201 /* Insert counter VALUE into HISTOGRAM. */
204 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
208 i
= gcov_histo_index(value
);
209 histogram
[i
].num_counters
++;
210 histogram
[i
].cum_value
+= value
;
211 if (value
< histogram
[i
].min_value
)
212 histogram
[i
].min_value
= value
;
215 /* Computes a histogram of the arc counters to place in the summary SUM. */
218 gcov_compute_histogram (struct gcov_info
*list
, struct gcov_summary
*sum
)
220 struct gcov_info
*gi_ptr
;
221 const struct gcov_fn_info
*gfi_ptr
;
222 const struct gcov_ctr_info
*ci_ptr
;
226 /* First check if there are any counts recorded for this counter. */
230 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
232 sum
->histogram
[h_ix
].num_counters
= 0;
233 sum
->histogram
[h_ix
].min_value
= sum
->run_max
;
234 sum
->histogram
[h_ix
].cum_value
= 0;
237 /* Walk through all the per-object structures and record each of
238 the count values in histogram. */
239 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
241 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
243 gfi_ptr
= gi_ptr
->functions
[f_ix
];
245 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
248 ci_ptr
= &gfi_ptr
->ctrs
[0];
249 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
250 gcov_histogram_insert (sum
->histogram
, ci_ptr
->values
[ix
]);
255 /* buffer for the fn_data from another program. */
256 static struct gcov_fn_buffer
*fn_buffer
;
257 /* buffer for summary from other programs to be written out. */
258 static struct gcov_summary_buffer
*sum_buffer
;
260 /* This function computes the program level summary and the histo-gram.
261 It computes and returns CRC32 and stored summary in THIS_PRG. */
267 compute_summary (struct gcov_info
*list
, struct gcov_summary
*this_prg
)
269 struct gcov_info
*gi_ptr
;
270 const struct gcov_fn_info
*gfi_ptr
;
271 const struct gcov_ctr_info
*ci_ptr
;
273 gcov_unsigned_t c_num
;
274 gcov_unsigned_t crc32
= 0;
276 /* Find the totals for this execution. */
277 memset (this_prg
, 0, sizeof (*this_prg
));
278 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
280 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
281 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
283 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
285 gfi_ptr
= gi_ptr
->functions
[f_ix
];
287 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
290 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
291 crc32
= crc32_unsigned (crc32
,
292 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
296 ci_ptr
= gfi_ptr
->ctrs
;
297 this_prg
->num
+= ci_ptr
->num
;
298 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
300 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
302 this_prg
->sum_all
+= ci_ptr
->values
[c_num
];
303 if (this_prg
->run_max
< ci_ptr
->values
[c_num
])
304 this_prg
->run_max
= ci_ptr
->values
[c_num
];
309 gcov_compute_histogram (list
, this_prg
);
313 /* Including system dependent components. */
314 #include "libgcov-driver-system.c"
316 /* This function merges counters in GI_PTR to an existing gcda file.
318 Return -1 on error. In this case, caller will goto read_fatal. */
321 merge_one_data (const char *filename
,
322 struct gcov_info
*gi_ptr
,
323 struct gcov_summary
*prg_p
,
324 struct gcov_summary
*this_prg
,
325 gcov_position_t
*summary_pos_p
,
326 gcov_position_t
*eof_pos_p
,
327 gcov_unsigned_t crc32
)
329 gcov_unsigned_t tag
, length
;
333 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
334 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
336 length
= gcov_read_unsigned ();
337 if (!gcov_version (gi_ptr
, length
, filename
))
340 length
= gcov_read_unsigned ();
341 if (length
!= gi_ptr
->stamp
)
343 /* Read from a different compilation. Overwrite the file. */
344 gcov_error ("profiling:%s:overwriting an existing profile data "
345 "with a different timestamp\n", filename
);
349 /* Look for program summary. */
352 struct gcov_summary tmp
;
354 *eof_pos_p
= gcov_position ();
355 tag
= gcov_read_unsigned ();
356 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
360 length
= gcov_read_unsigned ();
361 gcov_read_summary (&tmp
);
362 if ((error
= gcov_is_error ()))
366 /* Save all summaries after the one that will be
367 merged into below. These will need to be rewritten
368 as histogram merging may change the number of non-zero
369 histogram entries that will be emitted, and thus the
370 size of the merged summary. */
371 (*sum_tail
) = (struct gcov_summary_buffer
*)
372 xmalloc (sizeof(struct gcov_summary_buffer
));
373 (*sum_tail
)->summary
= tmp
;
374 (*sum_tail
)->next
= 0;
375 sum_tail
= &((*sum_tail
)->next
);
378 if (tmp
.checksum
!= crc32
)
381 if (tmp
.num
!= this_prg
->num
)
384 *summary_pos_p
= *eof_pos_p
;
389 /* Merge execution counts for each function. */
390 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
391 f_ix
++, tag
= gcov_read_unsigned ())
393 const struct gcov_ctr_info
*ci_ptr
;
394 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
396 if (tag
!= GCOV_TAG_FUNCTION
)
399 length
= gcov_read_unsigned ();
401 /* This function did not appear in the other program.
402 We have nothing to merge. */
405 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
408 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
410 /* This function appears in the other program. We
411 need to buffer the information in order to write
412 it back out -- we'll be inserting data before
413 this point, so cannot simply keep the data in the
415 fn_tail
= buffer_fn_data (filename
, gi_ptr
, fn_tail
, f_ix
);
421 length
= gcov_read_unsigned ();
422 if (length
!= gfi_ptr
->ident
)
425 length
= gcov_read_unsigned ();
426 if (length
!= gfi_ptr
->lineno_checksum
)
429 length
= gcov_read_unsigned ();
430 if (length
!= gfi_ptr
->cfg_checksum
)
433 ci_ptr
= gfi_ptr
->ctrs
;
434 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
436 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
441 tag
= gcov_read_unsigned ();
442 length
= gcov_read_unsigned ();
443 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
444 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
446 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
449 if ((error
= gcov_is_error ()))
456 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
457 filename
, f_ix
>= 0 ? "function" : "summary",
458 f_ix
< 0 ? -1 - f_ix
: f_ix
);
464 gcov_error ("profiling:%s:%s merging\n", filename
,
465 error
< 0 ? "Overflow": "Error");
469 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
470 the case of appending to an existing file, SUMMARY_POS will be non-zero.
471 We will write the file starting from SUMMAY_POS. */
474 write_one_data (const struct gcov_info
*gi_ptr
,
475 const struct gcov_summary
*prg_p
,
476 const gcov_position_t eof_pos
,
477 const gcov_position_t summary_pos
)
480 struct gcov_summary_buffer
*next_sum_buffer
;
482 /* Write out the data. */
485 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
486 gcov_write_unsigned (gi_ptr
->stamp
);
490 gcov_seek (summary_pos
);
492 /* Generate whole program statistics. */
493 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
495 /* Rewrite all the summaries that were after the summary we merged
496 into. This is necessary as the merged summary may have a different
497 size due to the number of non-zero histogram entries changing after
502 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
503 next_sum_buffer
= sum_buffer
->next
;
505 sum_buffer
= next_sum_buffer
;
508 /* Write execution counts for each function. */
509 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
511 unsigned buffered
= 0;
512 const struct gcov_fn_info
*gfi_ptr
;
513 const struct gcov_ctr_info
*ci_ptr
;
514 gcov_unsigned_t length
;
517 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
519 /* Buffered data from another program. */
521 gfi_ptr
= &fn_buffer
->info
;
522 length
= GCOV_TAG_FUNCTION_LENGTH
;
526 gfi_ptr
= gi_ptr
->functions
[f_ix
];
527 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
528 length
= GCOV_TAG_FUNCTION_LENGTH
;
533 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
537 gcov_write_unsigned (gfi_ptr
->ident
);
538 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
539 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
541 ci_ptr
= gfi_ptr
->ctrs
;
542 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
544 gcov_unsigned_t n_counts
;
547 if (!gi_ptr
->merge
[t_ix
])
550 n_counts
= ci_ptr
->num
;
551 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
552 GCOV_TAG_COUNTER_LENGTH (n_counts
));
553 c_ptr
= ci_ptr
->values
;
555 gcov_write_counter (*c_ptr
++);
559 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
562 gcov_write_unsigned (0);
565 /* Helper function for merging summary.
566 Return -1 on error. Return 0 on success. */
569 merge_summary (const char *filename
__attribute__ ((unused
)), int run_counted
,
570 struct gcov_summary
*prg
,
571 struct gcov_summary
*this_prg
, gcov_unsigned_t crc32
,
572 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
575 /* summary for all instances of program. */
576 struct gcov_summary
*all
;
579 /* Merge the summary. */
580 int first
= !prg
->runs
;
585 prg
->num
= this_prg
->num
;
586 prg
->sum_all
+= this_prg
->sum_all
;
587 if (prg
->run_max
< this_prg
->run_max
)
588 prg
->run_max
= this_prg
->run_max
;
589 prg
->sum_max
+= this_prg
->run_max
;
591 memcpy (prg
->histogram
, this_prg
->histogram
,
592 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
594 gcov_histogram_merge (prg
->histogram
, this_prg
->histogram
);
597 if (!all
->runs
&& prg
->runs
)
600 all
->runs
= prg
->runs
;
601 all
->sum_all
= prg
->sum_all
;
602 all
->run_max
= prg
->run_max
;
603 all
->sum_max
= prg
->sum_max
;
605 else if (!all_prg
->checksum
606 /* Don't compare the histograms, which may have slight
607 variations depending on the order they were updated
608 due to the truncating integer divides used in the
610 && (all
->num
!= prg
->num
611 || all
->runs
!= prg
->runs
612 || all
->sum_all
!= prg
->sum_all
613 || all
->run_max
!= prg
->run_max
614 || all
->sum_max
!= prg
->sum_max
))
616 gcov_error ("profiling:%s:Data file mismatch - some "
617 "data files may have been concurrently "
618 "updated without locking support\n", filename
);
619 all_prg
->checksum
= ~0u;
623 prg
->checksum
= crc32
;
629 /* Sort N entries in VALUE_ARRAY in descending order.
630 Each entry in VALUE_ARRAY has two values. The sorting
631 is based on the second value. */
634 gcov_sort_n_vals (gcov_type
*value_array
, int n
)
638 for (j
= 2; j
< n
; j
+= 2)
640 gcov_type cur_ent
[2];
642 cur_ent
[0] = value_array
[j
];
643 cur_ent
[1] = value_array
[j
+ 1];
645 while (k
>= 0 && value_array
[k
+ 1] < cur_ent
[1])
647 value_array
[k
+ 2] = value_array
[k
];
648 value_array
[k
+ 3] = value_array
[k
+1];
651 value_array
[k
+ 2] = cur_ent
[0];
652 value_array
[k
+ 3] = cur_ent
[1];
656 /* Sort the profile counters for all indirect call sites. Counters
657 for each call site are allocated in array COUNTERS. */
660 gcov_sort_icall_topn_counter (const struct gcov_ctr_info
*counters
)
664 int n
= counters
->num
;
666 gcc_assert (!(n
% GCOV_ICALL_TOPN_NCOUNTS
));
667 values
= counters
->values
;
669 for (i
= 0; i
< n
; i
+= GCOV_ICALL_TOPN_NCOUNTS
)
671 gcov_type
*value_array
= &values
[i
+ 1];
672 gcov_sort_n_vals (value_array
, GCOV_ICALL_TOPN_NCOUNTS
- 1);
676 /* Sort topn indirect_call profile counters in GI_PTR. */
679 gcov_sort_topn_counter_arrays (const struct gcov_info
*gi_ptr
)
683 const struct gcov_fn_info
*gfi_ptr
;
684 const struct gcov_ctr_info
*ci_ptr
;
686 if (!gi_ptr
->merge
[GCOV_COUNTER_ICALL_TOPNV
])
689 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
691 gfi_ptr
= gi_ptr
->functions
[f_ix
];
692 ci_ptr
= gfi_ptr
->ctrs
;
693 for (i
= 0; i
< GCOV_COUNTERS
; i
++)
695 if (!gi_ptr
->merge
[i
])
697 if (i
== GCOV_COUNTER_ICALL_TOPNV
)
699 gcov_sort_icall_topn_counter (ci_ptr
);
707 /* Dump the coverage counts for one gcov_info object. We merge with existing
708 counts when possible, to avoid growing the .da files ad infinitum. We use
709 this program's checksum to make sure we only accumulate whole program
710 statistics to the correct summary. An object file might be embedded
711 in two separate programs, and we must keep the two program
712 summaries separate. */
715 dump_one_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename
*gf
,
716 unsigned run_counted
,
717 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
,
718 struct gcov_summary
*this_prg
)
720 struct gcov_summary prg
; /* summary for this object over all program. */
723 gcov_position_t summary_pos
= 0;
724 gcov_position_t eof_pos
= 0;
729 gcov_sort_topn_counter_arrays (gi_ptr
);
731 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
735 tag
= gcov_read_unsigned ();
738 /* Merge data from file. */
739 if (tag
!= GCOV_DATA_MAGIC
)
741 gcov_error ("profiling:%s:Not a gcov data file\n", gf
->filename
);
744 error
= merge_one_data (gf
->filename
, gi_ptr
, &prg
, this_prg
,
745 &summary_pos
, &eof_pos
, crc32
);
754 memset (&prg
, 0, sizeof (prg
));
755 summary_pos
= eof_pos
;
758 error
= merge_summary (gf
->filename
, run_counted
, &prg
, this_prg
,
763 write_one_data (gi_ptr
, &prg
, eof_pos
, summary_pos
);
768 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
770 if ((error
= gcov_close ()))
771 gcov_error (error
< 0 ?
772 "profiling:%s:Overflow writing\n" :
773 "profiling:%s:Error writing\n",
778 /* Dump all the coverage counts for the program. It first computes program
779 summary and then traverses gcov_list list and dumps the gcov_info
780 objects one by one. */
786 gcov_do_dump (struct gcov_info
*list
, int run_counted
)
788 struct gcov_info
*gi_ptr
;
789 struct gcov_filename gf
;
790 gcov_unsigned_t crc32
;
791 struct gcov_summary all_prg
;
792 struct gcov_summary this_prg
;
794 crc32
= compute_summary (list
, &this_prg
);
796 allocate_filename_struct (&gf
);
798 memset (&all_prg
, 0, sizeof (all_prg
));
801 /* Now merge each file. */
802 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
804 dump_one_gcov (gi_ptr
, &gf
, run_counted
, crc32
, &all_prg
, &this_prg
);
813 __attribute__ ((unused
))
814 gcov_get_filename (struct gcov_info
*list
)
816 return list
->filename
;
822 __gcov_dump_one (struct gcov_root
*root
)
827 gcov_do_dump (root
->list
, root
->run_counted
);
830 root
->run_counted
= 1;
833 /* Per-dynamic-object gcov state. */
834 struct gcov_root __gcov_root
;
836 /* Exactly one of these will be live in the process image. */
837 struct gcov_master __gcov_master
=
843 __gcov_dump_one (&__gcov_root
);
844 if (__gcov_root
.next
)
845 __gcov_root
.next
->prev
= __gcov_root
.prev
;
846 if (__gcov_root
.prev
)
847 __gcov_root
.prev
->next
= __gcov_root
.next
;
849 __gcov_master
.root
= __gcov_root
.next
;
854 /* Add a new object file onto the bb chain. Invoked automatically
855 when running an object file's global ctors. */
858 __gcov_init (struct gcov_info
*info
)
860 if (!info
->version
|| !info
->n_functions
)
862 if (gcov_version (info
, info
->version
, 0))
864 if (!__gcov_root
.list
)
866 /* Add to master list and at exit function. */
867 if (gcov_version (NULL
, __gcov_master
.version
, "<master>"))
869 __gcov_root
.next
= __gcov_master
.root
;
870 if (__gcov_master
.root
)
871 __gcov_master
.root
->prev
= &__gcov_root
;
872 __gcov_master
.root
= &__gcov_root
;
876 info
->next
= __gcov_root
.list
;
877 __gcov_root
.list
= info
;
880 #endif /* !IN_GCOV_TOOL */
882 #endif /* inhibit_libc */