1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2015 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 static struct gcov_fn_buffer
*
77 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
80 struct gcov_fn_buffer
*next
;
81 unsigned ix
, n_ctr
= 0;
87 for (ix
= 0; ix
!= limit
; ix
++)
88 if (gi_ptr
->merge
[ix
])
89 free (buffer
->info
.ctrs
[n_ctr
++].values
);
94 static struct gcov_fn_buffer
**
95 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
96 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
98 unsigned n_ctrs
= 0, ix
= 0;
99 struct gcov_fn_buffer
*fn_buffer
;
102 for (ix
= GCOV_COUNTERS
; ix
--;)
103 if (gi_ptr
->merge
[ix
])
106 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
107 fn_buffer
= (struct gcov_fn_buffer
*) xmalloc (len
);
113 fn_buffer
->fn_ix
= fn_ix
;
114 fn_buffer
->info
.ident
= gcov_read_unsigned ();
115 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
116 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
118 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
120 gcov_unsigned_t length
;
123 if (!gi_ptr
->merge
[ix
])
126 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
132 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
133 len
= length
* sizeof (gcov_type
);
134 values
= (gcov_type
*) xmalloc (len
);
138 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
139 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
142 *values
++ = gcov_read_counter ();
146 *end_ptr
= fn_buffer
;
147 return &fn_buffer
->next
;
150 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
151 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
153 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
156 /* Add an unsigned value to the current crc */
158 static gcov_unsigned_t
159 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
163 for (ix
= 32; ix
--; value
<<= 1)
167 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
175 /* Check if VERSION of the info block PTR matches libgcov one.
176 Return 1 on success, or zero in case of versions mismatch.
177 If FILENAME is not NULL, its value used for reporting purposes
178 instead of value from the info block. */
181 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
182 const char *filename
)
184 if (version
!= GCOV_VERSION
)
188 GCOV_UNSIGNED2STRING (v
, version
);
189 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
191 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
192 filename
? filename
: ptr
->filename
, e
, v
);
198 /* Insert counter VALUE into HISTOGRAM. */
201 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
205 i
= gcov_histo_index(value
);
206 histogram
[i
].num_counters
++;
207 histogram
[i
].cum_value
+= value
;
208 if (value
< histogram
[i
].min_value
)
209 histogram
[i
].min_value
= value
;
212 /* Computes a histogram of the arc counters to place in the summary SUM. */
215 gcov_compute_histogram (struct gcov_info
*list
, struct gcov_summary
*sum
)
217 struct gcov_info
*gi_ptr
;
218 const struct gcov_fn_info
*gfi_ptr
;
219 const struct gcov_ctr_info
*ci_ptr
;
220 struct gcov_ctr_summary
*cs_ptr
;
221 unsigned t_ix
, f_ix
, ctr_info_ix
, ix
;
224 /* This currently only applies to arc counters. */
225 t_ix
= GCOV_COUNTER_ARCS
;
227 /* First check if there are any counts recorded for this counter. */
228 cs_ptr
= &(sum
->ctrs
[t_ix
]);
232 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
234 cs_ptr
->histogram
[h_ix
].num_counters
= 0;
235 cs_ptr
->histogram
[h_ix
].min_value
= cs_ptr
->run_max
;
236 cs_ptr
->histogram
[h_ix
].cum_value
= 0;
239 /* Walk through all the per-object structures and record each of
240 the count values in histogram. */
241 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
243 if (!gi_ptr
->merge
[t_ix
])
246 /* Find the appropriate index into the gcov_ctr_info array
247 for the counter we are currently working on based on the
248 existence of the merge function pointer for this object. */
249 for (ix
= 0, ctr_info_ix
= 0; ix
< t_ix
; ix
++)
251 if (gi_ptr
->merge
[ix
])
254 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
256 gfi_ptr
= gi_ptr
->functions
[f_ix
];
258 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
261 ci_ptr
= &gfi_ptr
->ctrs
[ctr_info_ix
];
262 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
263 gcov_histogram_insert (cs_ptr
->histogram
, ci_ptr
->values
[ix
]);
268 /* buffer for the fn_data from another program. */
269 static struct gcov_fn_buffer
*fn_buffer
;
270 /* buffer for summary from other programs to be written out. */
271 static struct gcov_summary_buffer
*sum_buffer
;
273 /* This function computes the program level summary and the histo-gram.
274 It computes and returns CRC32 and stored summary in THIS_PRG.
275 Also determines the longest filename length of the info files. */
281 compute_summary (struct gcov_info
*list
, struct gcov_summary
*this_prg
,
284 struct gcov_info
*gi_ptr
;
285 const struct gcov_fn_info
*gfi_ptr
;
286 struct gcov_ctr_summary
*cs_ptr
;
287 const struct gcov_ctr_info
*ci_ptr
;
290 gcov_unsigned_t c_num
;
291 gcov_unsigned_t crc32
= 0;
293 /* Find the totals for this execution. */
294 memset (this_prg
, 0, sizeof (*this_prg
));
296 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
298 size_t len
= strlen (gi_ptr
->filename
);
299 if (len
> *max_length
)
302 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
303 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
305 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
307 gfi_ptr
= gi_ptr
->functions
[f_ix
];
309 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
312 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
313 crc32
= crc32_unsigned (crc32
,
314 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
318 ci_ptr
= gfi_ptr
->ctrs
;
319 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
321 if (!gi_ptr
->merge
[t_ix
])
324 cs_ptr
= &(this_prg
->ctrs
[t_ix
]);
325 cs_ptr
->num
+= ci_ptr
->num
;
326 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
328 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
330 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
331 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
332 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
338 gcov_compute_histogram (list
, this_prg
);
342 /* Including system dependent components. */
343 #include "libgcov-driver-system.c"
345 /* This function merges counters in GI_PTR to an existing gcda file.
347 Return -1 on error. In this case, caller will goto read_fatal. */
350 merge_one_data (const char *filename
,
351 struct gcov_info
*gi_ptr
,
352 struct gcov_summary
*prg_p
,
353 struct gcov_summary
*this_prg
,
354 gcov_position_t
*summary_pos_p
,
355 gcov_position_t
*eof_pos_p
,
356 gcov_unsigned_t crc32
)
358 gcov_unsigned_t tag
, length
;
362 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
363 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
365 length
= gcov_read_unsigned ();
366 if (!gcov_version (gi_ptr
, length
, filename
))
369 length
= gcov_read_unsigned ();
370 if (length
!= gi_ptr
->stamp
)
371 /* Read from a different compilation. Overwrite the file. */
374 /* Look for program summary. */
377 struct gcov_summary tmp
;
379 *eof_pos_p
= gcov_position ();
380 tag
= gcov_read_unsigned ();
381 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
385 length
= gcov_read_unsigned ();
386 gcov_read_summary (&tmp
);
387 if ((error
= gcov_is_error ()))
391 /* Save all summaries after the one that will be
392 merged into below. These will need to be rewritten
393 as histogram merging may change the number of non-zero
394 histogram entries that will be emitted, and thus the
395 size of the merged summary. */
396 (*sum_tail
) = (struct gcov_summary_buffer
*)
397 xmalloc (sizeof(struct gcov_summary_buffer
));
398 (*sum_tail
)->summary
= tmp
;
399 (*sum_tail
)->next
= 0;
400 sum_tail
= &((*sum_tail
)->next
);
403 if (tmp
.checksum
!= crc32
)
406 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
407 if (tmp
.ctrs
[t_ix
].num
!= this_prg
->ctrs
[t_ix
].num
)
410 *summary_pos_p
= *eof_pos_p
;
415 /* Merge execution counts for each function. */
416 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
417 f_ix
++, tag
= gcov_read_unsigned ())
419 const struct gcov_ctr_info
*ci_ptr
;
420 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
422 if (tag
!= GCOV_TAG_FUNCTION
)
425 length
= gcov_read_unsigned ();
427 /* This function did not appear in the other program.
428 We have nothing to merge. */
431 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
434 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
436 /* This function appears in the other program. We
437 need to buffer the information in order to write
438 it back out -- we'll be inserting data before
439 this point, so cannot simply keep the data in the
441 fn_tail
= buffer_fn_data (filename
, gi_ptr
, fn_tail
, f_ix
);
447 length
= gcov_read_unsigned ();
448 if (length
!= gfi_ptr
->ident
)
451 length
= gcov_read_unsigned ();
452 if (length
!= gfi_ptr
->lineno_checksum
)
455 length
= gcov_read_unsigned ();
456 if (length
!= gfi_ptr
->cfg_checksum
)
459 ci_ptr
= gfi_ptr
->ctrs
;
460 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
462 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
467 tag
= gcov_read_unsigned ();
468 length
= gcov_read_unsigned ();
469 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
470 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
472 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
475 if ((error
= gcov_is_error ()))
482 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
483 filename
, f_ix
>= 0 ? "function" : "summary",
484 f_ix
< 0 ? -1 - f_ix
: f_ix
);
490 gcov_error ("profiling:%s:%s merging\n", filename
,
491 error
< 0 ? "Overflow": "Error");
495 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
496 the case of appending to an existing file, SUMMARY_POS will be non-zero.
497 We will write the file starting from SUMMAY_POS. */
500 write_one_data (const struct gcov_info
*gi_ptr
,
501 const struct gcov_summary
*prg_p
,
502 const gcov_position_t eof_pos
,
503 const gcov_position_t summary_pos
)
506 struct gcov_summary_buffer
*next_sum_buffer
;
508 /* Write out the data. */
511 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
512 gcov_write_unsigned (gi_ptr
->stamp
);
516 gcov_seek (summary_pos
);
518 /* Generate whole program statistics. */
519 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
521 /* Rewrite all the summaries that were after the summary we merged
522 into. This is necessary as the merged summary may have a different
523 size due to the number of non-zero histogram entries changing after
528 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
529 next_sum_buffer
= sum_buffer
->next
;
531 sum_buffer
= next_sum_buffer
;
534 /* Write execution counts for each function. */
535 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
537 unsigned buffered
= 0;
538 const struct gcov_fn_info
*gfi_ptr
;
539 const struct gcov_ctr_info
*ci_ptr
;
540 gcov_unsigned_t length
;
543 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
545 /* Buffered data from another program. */
547 gfi_ptr
= &fn_buffer
->info
;
548 length
= GCOV_TAG_FUNCTION_LENGTH
;
552 gfi_ptr
= gi_ptr
->functions
[f_ix
];
553 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
554 length
= GCOV_TAG_FUNCTION_LENGTH
;
559 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
563 gcov_write_unsigned (gfi_ptr
->ident
);
564 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
565 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
567 ci_ptr
= gfi_ptr
->ctrs
;
568 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
570 gcov_unsigned_t n_counts
;
573 if (!gi_ptr
->merge
[t_ix
])
576 n_counts
= ci_ptr
->num
;
577 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
578 GCOV_TAG_COUNTER_LENGTH (n_counts
));
579 c_ptr
= ci_ptr
->values
;
581 gcov_write_counter (*c_ptr
++);
585 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
588 gcov_write_unsigned (0);
591 /* Helper function for merging summary.
592 Return -1 on error. Return 0 on success. */
595 merge_summary (const char *filename
, int run_counted
,
596 const struct gcov_info
*gi_ptr
, struct gcov_summary
*prg
,
597 struct gcov_summary
*this_prg
, gcov_unsigned_t crc32
,
598 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
600 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
;
603 /* summary for all instances of program. */
604 struct gcov_ctr_summary
*cs_all
;
607 /* Merge the summaries. */
608 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
610 cs_prg
= &(prg
->ctrs
[t_ix
]);
611 cs_tprg
= &(this_prg
->ctrs
[t_ix
]);
613 if (gi_ptr
->merge
[t_ix
])
615 int first
= !cs_prg
->runs
;
620 cs_prg
->num
= cs_tprg
->num
;
621 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
622 if (cs_prg
->run_max
< cs_tprg
->run_max
)
623 cs_prg
->run_max
= cs_tprg
->run_max
;
624 cs_prg
->sum_max
+= cs_tprg
->run_max
;
626 memcpy (cs_prg
->histogram
, cs_tprg
->histogram
,
627 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
629 gcov_histogram_merge (cs_prg
->histogram
, cs_tprg
->histogram
);
631 else if (cs_prg
->runs
)
633 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
638 cs_all
= &all_prg
->ctrs
[t_ix
];
639 if (!cs_all
->runs
&& cs_prg
->runs
)
641 cs_all
->num
= cs_prg
->num
;
642 cs_all
->runs
= cs_prg
->runs
;
643 cs_all
->sum_all
= cs_prg
->sum_all
;
644 cs_all
->run_max
= cs_prg
->run_max
;
645 cs_all
->sum_max
= cs_prg
->sum_max
;
647 else if (!all_prg
->checksum
648 /* Don't compare the histograms, which may have slight
649 variations depending on the order they were updated
650 due to the truncating integer divides used in the
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 gcov_error ("profiling:%s:Data file mismatch - some "
659 "data files may have been concurrently "
660 "updated without locking support\n", filename
);
661 all_prg
->checksum
= ~0u;
666 prg
->checksum
= crc32
;
672 /* Sort N entries in VALUE_ARRAY in descending order.
673 Each entry in VALUE_ARRAY has two values. The sorting
674 is based on the second value. */
677 gcov_sort_n_vals (gcov_type
*value_array
, int n
)
681 for (j
= 2; j
< n
; j
+= 2)
683 gcov_type cur_ent
[2];
685 cur_ent
[0] = value_array
[j
];
686 cur_ent
[1] = value_array
[j
+ 1];
688 while (k
>= 0 && value_array
[k
+ 1] < cur_ent
[1])
690 value_array
[k
+ 2] = value_array
[k
];
691 value_array
[k
+ 3] = value_array
[k
+1];
694 value_array
[k
+ 2] = cur_ent
[0];
695 value_array
[k
+ 3] = cur_ent
[1];
699 /* Sort the profile counters for all indirect call sites. Counters
700 for each call site are allocated in array COUNTERS. */
703 gcov_sort_icall_topn_counter (const struct gcov_ctr_info
*counters
)
707 int n
= counters
->num
;
709 gcc_assert (!(n
% GCOV_ICALL_TOPN_NCOUNTS
));
710 values
= counters
->values
;
712 for (i
= 0; i
< n
; i
+= GCOV_ICALL_TOPN_NCOUNTS
)
714 gcov_type
*value_array
= &values
[i
+ 1];
715 gcov_sort_n_vals (value_array
, GCOV_ICALL_TOPN_NCOUNTS
- 1);
719 /* Sort topn indirect_call profile counters in GI_PTR. */
722 gcov_sort_topn_counter_arrays (const struct gcov_info
*gi_ptr
)
726 const struct gcov_fn_info
*gfi_ptr
;
727 const struct gcov_ctr_info
*ci_ptr
;
729 if (!gi_ptr
->merge
[GCOV_COUNTER_ICALL_TOPNV
])
732 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
734 gfi_ptr
= gi_ptr
->functions
[f_ix
];
735 ci_ptr
= gfi_ptr
->ctrs
;
736 for (i
= 0; i
< GCOV_COUNTERS
; i
++)
738 if (!gi_ptr
->merge
[i
])
740 if (i
== GCOV_COUNTER_ICALL_TOPNV
)
742 gcov_sort_icall_topn_counter (ci_ptr
);
750 /* Dump the coverage counts for one gcov_info object. We merge with existing
751 counts when possible, to avoid growing the .da files ad infinitum. We use
752 this program's checksum to make sure we only accumulate whole program
753 statistics to the correct summary. An object file might be embedded
754 in two separate programs, and we must keep the two program
755 summaries separate. */
758 dump_one_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename
*gf
,
759 unsigned run_counted
,
760 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
,
761 struct gcov_summary
*this_prg
)
763 struct gcov_summary prg
; /* summary for this object over all program. */
766 gcov_position_t summary_pos
= 0;
767 gcov_position_t eof_pos
= 0;
772 gcov_sort_topn_counter_arrays (gi_ptr
);
774 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
778 tag
= gcov_read_unsigned ();
781 /* Merge data from file. */
782 if (tag
!= GCOV_DATA_MAGIC
)
784 gcov_error ("profiling:%s:Not a gcov data file\n", gf
->filename
);
787 error
= merge_one_data (gf
->filename
, gi_ptr
, &prg
, this_prg
,
788 &summary_pos
, &eof_pos
, crc32
);
797 memset (&prg
, 0, sizeof (prg
));
798 summary_pos
= eof_pos
;
801 error
= merge_summary (gf
->filename
, run_counted
, gi_ptr
, &prg
, this_prg
,
806 write_one_data (gi_ptr
, &prg
, eof_pos
, summary_pos
);
811 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
813 if ((error
= gcov_close ()))
814 gcov_error (error
< 0 ?
815 "profiling:%s:Overflow writing\n" :
816 "profiling:%s:Error writing\n",
821 /* Dump all the coverage counts for the program. It first computes program
822 summary and then traverses gcov_list list and dumps the gcov_info
823 objects one by one. */
829 gcov_do_dump (struct gcov_info
*list
, int run_counted
)
831 struct gcov_info
*gi_ptr
;
832 struct gcov_filename gf
;
833 gcov_unsigned_t crc32
;
834 struct gcov_summary all_prg
;
835 struct gcov_summary this_prg
;
837 crc32
= compute_summary (list
, &this_prg
, &gf
.max_length
);
839 allocate_filename_struct (&gf
);
841 memset (&all_prg
, 0, sizeof (all_prg
));
844 /* Now merge each file. */
845 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
846 dump_one_gcov (gi_ptr
, &gf
, run_counted
, crc32
, &all_prg
, &this_prg
);
853 __gcov_dump_one (struct gcov_root
*root
)
858 gcov_do_dump (root
->list
, root
->run_counted
);
861 root
->run_counted
= 1;
864 /* Per-dynamic-object gcov state. */
865 struct gcov_root __gcov_root
;
867 /* Exactly one of these will be live in the process image. */
868 struct gcov_master __gcov_master
=
874 __gcov_dump_one (&__gcov_root
);
875 if (__gcov_root
.next
)
876 __gcov_root
.next
->prev
= __gcov_root
.prev
;
877 if (__gcov_root
.prev
)
878 __gcov_root
.prev
->next
= __gcov_root
.next
;
880 __gcov_master
.root
= __gcov_root
.next
;
883 /* Add a new object file onto the bb chain. Invoked automatically
884 when running an object file's global ctors. */
887 __gcov_init (struct gcov_info
*info
)
889 if (!info
->version
|| !info
->n_functions
)
891 if (gcov_version (info
, info
->version
, 0))
893 if (!__gcov_root
.list
)
895 /* Add to master list and at exit function. */
896 if (gcov_version (NULL
, __gcov_master
.version
, "<master>"))
898 __gcov_root
.next
= __gcov_master
.root
;
899 if (__gcov_master
.root
)
900 __gcov_master
.root
->prev
= &__gcov_root
;
901 __gcov_master
.root
= &__gcov_root
;
906 info
->next
= __gcov_root
.list
;
907 __gcov_root
.list
= info
;
910 #endif /* !IN_GCOV_TOOL */
912 #endif /* inhibit_libc */