1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2016 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 size_t max_length
; /* maximum filename length */
76 int strip
; /* leading chars to strip from filename */
77 size_t prefix
; /* chars to prepend to filename */
80 static struct gcov_fn_buffer
*
81 free_fn_data (const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
84 struct gcov_fn_buffer
*next
;
85 unsigned ix
, n_ctr
= 0;
91 for (ix
= 0; ix
!= limit
; ix
++)
92 if (gi_ptr
->merge
[ix
])
93 free (buffer
->info
.ctrs
[n_ctr
++].values
);
98 static struct gcov_fn_buffer
**
99 buffer_fn_data (const char *filename
, const struct gcov_info
*gi_ptr
,
100 struct gcov_fn_buffer
**end_ptr
, unsigned fn_ix
)
102 unsigned n_ctrs
= 0, ix
= 0;
103 struct gcov_fn_buffer
*fn_buffer
;
106 for (ix
= GCOV_COUNTERS
; ix
--;)
107 if (gi_ptr
->merge
[ix
])
110 len
= sizeof (*fn_buffer
) + sizeof (fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
111 fn_buffer
= (struct gcov_fn_buffer
*) xmalloc (len
);
117 fn_buffer
->fn_ix
= fn_ix
;
118 fn_buffer
->info
.ident
= gcov_read_unsigned ();
119 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned ();
120 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned ();
122 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
124 gcov_unsigned_t length
;
127 if (!gi_ptr
->merge
[ix
])
130 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix
))
136 length
= GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
137 len
= length
* sizeof (gcov_type
);
138 values
= (gcov_type
*) xmalloc (len
);
142 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
143 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
146 *values
++ = gcov_read_counter ();
150 *end_ptr
= fn_buffer
;
151 return &fn_buffer
->next
;
154 gcov_error ("profiling:%s:Function %u %s %u \n", filename
, fn_ix
,
155 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
157 return (struct gcov_fn_buffer
**)free_fn_data (gi_ptr
, fn_buffer
, ix
);
160 /* Add an unsigned value to the current crc */
162 static gcov_unsigned_t
163 crc32_unsigned (gcov_unsigned_t crc32
, gcov_unsigned_t value
)
167 for (ix
= 32; ix
--; value
<<= 1)
171 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
179 /* Check if VERSION of the info block PTR matches libgcov one.
180 Return 1 on success, or zero in case of versions mismatch.
181 If FILENAME is not NULL, its value used for reporting purposes
182 instead of value from the info block. */
185 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
186 const char *filename
)
188 if (version
!= GCOV_VERSION
)
192 GCOV_UNSIGNED2STRING (v
, version
);
193 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
195 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
196 filename
? filename
: ptr
->filename
, e
, v
);
202 /* Insert counter VALUE into HISTOGRAM. */
205 gcov_histogram_insert(gcov_bucket_type
*histogram
, gcov_type value
)
209 i
= gcov_histo_index(value
);
210 histogram
[i
].num_counters
++;
211 histogram
[i
].cum_value
+= value
;
212 if (value
< histogram
[i
].min_value
)
213 histogram
[i
].min_value
= value
;
216 /* Computes a histogram of the arc counters to place in the summary SUM. */
219 gcov_compute_histogram (struct gcov_info
*list
, struct gcov_summary
*sum
)
221 struct gcov_info
*gi_ptr
;
222 const struct gcov_fn_info
*gfi_ptr
;
223 const struct gcov_ctr_info
*ci_ptr
;
224 struct gcov_ctr_summary
*cs_ptr
;
225 unsigned t_ix
, f_ix
, ctr_info_ix
, ix
;
228 /* This currently only applies to arc counters. */
229 t_ix
= GCOV_COUNTER_ARCS
;
231 /* First check if there are any counts recorded for this counter. */
232 cs_ptr
= &(sum
->ctrs
[t_ix
]);
236 for (h_ix
= 0; h_ix
< GCOV_HISTOGRAM_SIZE
; h_ix
++)
238 cs_ptr
->histogram
[h_ix
].num_counters
= 0;
239 cs_ptr
->histogram
[h_ix
].min_value
= cs_ptr
->run_max
;
240 cs_ptr
->histogram
[h_ix
].cum_value
= 0;
243 /* Walk through all the per-object structures and record each of
244 the count values in histogram. */
245 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
247 if (!gi_ptr
->merge
[t_ix
])
250 /* Find the appropriate index into the gcov_ctr_info array
251 for the counter we are currently working on based on the
252 existence of the merge function pointer for this object. */
253 for (ix
= 0, ctr_info_ix
= 0; ix
< t_ix
; ix
++)
255 if (gi_ptr
->merge
[ix
])
258 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
260 gfi_ptr
= gi_ptr
->functions
[f_ix
];
262 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
265 ci_ptr
= &gfi_ptr
->ctrs
[ctr_info_ix
];
266 for (ix
= 0; ix
< ci_ptr
->num
; ix
++)
267 gcov_histogram_insert (cs_ptr
->histogram
, ci_ptr
->values
[ix
]);
272 /* buffer for the fn_data from another program. */
273 static struct gcov_fn_buffer
*fn_buffer
;
274 /* buffer for summary from other programs to be written out. */
275 static struct gcov_summary_buffer
*sum_buffer
;
277 /* This function computes the program level summary and the histo-gram.
278 It computes and returns CRC32 and stored summary in THIS_PRG.
279 Also determines the longest filename length of the info files. */
285 compute_summary (struct gcov_info
*list
, struct gcov_summary
*this_prg
,
288 struct gcov_info
*gi_ptr
;
289 const struct gcov_fn_info
*gfi_ptr
;
290 struct gcov_ctr_summary
*cs_ptr
;
291 const struct gcov_ctr_info
*ci_ptr
;
294 gcov_unsigned_t c_num
;
295 gcov_unsigned_t crc32
= 0;
297 /* Find the totals for this execution. */
298 memset (this_prg
, 0, sizeof (*this_prg
));
300 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
302 size_t len
= strlen (gi_ptr
->filename
);
303 if (len
> *max_length
)
306 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
307 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
309 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
311 gfi_ptr
= gi_ptr
->functions
[f_ix
];
313 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
316 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
317 crc32
= crc32_unsigned (crc32
,
318 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
322 ci_ptr
= gfi_ptr
->ctrs
;
323 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
325 if (!gi_ptr
->merge
[t_ix
])
328 cs_ptr
= &(this_prg
->ctrs
[t_ix
]);
329 cs_ptr
->num
+= ci_ptr
->num
;
330 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
332 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
334 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
335 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
336 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
342 gcov_compute_histogram (list
, this_prg
);
346 /* Including system dependent components. */
347 #include "libgcov-driver-system.c"
349 /* This function merges counters in GI_PTR to an existing gcda file.
351 Return -1 on error. In this case, caller will goto read_fatal. */
354 merge_one_data (const char *filename
,
355 struct gcov_info
*gi_ptr
,
356 struct gcov_summary
*prg_p
,
357 struct gcov_summary
*this_prg
,
358 gcov_position_t
*summary_pos_p
,
359 gcov_position_t
*eof_pos_p
,
360 gcov_unsigned_t crc32
)
362 gcov_unsigned_t tag
, length
;
366 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
367 struct gcov_summary_buffer
**sum_tail
= &sum_buffer
;
369 length
= gcov_read_unsigned ();
370 if (!gcov_version (gi_ptr
, length
, filename
))
373 length
= gcov_read_unsigned ();
374 if (length
!= gi_ptr
->stamp
)
375 /* Read from a different compilation. Overwrite the file. */
378 /* Look for program summary. */
381 struct gcov_summary tmp
;
383 *eof_pos_p
= gcov_position ();
384 tag
= gcov_read_unsigned ();
385 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
389 length
= gcov_read_unsigned ();
390 gcov_read_summary (&tmp
);
391 if ((error
= gcov_is_error ()))
395 /* Save all summaries after the one that will be
396 merged into below. These will need to be rewritten
397 as histogram merging may change the number of non-zero
398 histogram entries that will be emitted, and thus the
399 size of the merged summary. */
400 (*sum_tail
) = (struct gcov_summary_buffer
*)
401 xmalloc (sizeof(struct gcov_summary_buffer
));
402 (*sum_tail
)->summary
= tmp
;
403 (*sum_tail
)->next
= 0;
404 sum_tail
= &((*sum_tail
)->next
);
407 if (tmp
.checksum
!= crc32
)
410 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
411 if (tmp
.ctrs
[t_ix
].num
!= this_prg
->ctrs
[t_ix
].num
)
414 *summary_pos_p
= *eof_pos_p
;
419 /* Merge execution counts for each function. */
420 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
421 f_ix
++, tag
= gcov_read_unsigned ())
423 const struct gcov_ctr_info
*ci_ptr
;
424 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
426 if (tag
!= GCOV_TAG_FUNCTION
)
429 length
= gcov_read_unsigned ();
431 /* This function did not appear in the other program.
432 We have nothing to merge. */
435 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
438 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
440 /* This function appears in the other program. We
441 need to buffer the information in order to write
442 it back out -- we'll be inserting data before
443 this point, so cannot simply keep the data in the
445 fn_tail
= buffer_fn_data (filename
, gi_ptr
, fn_tail
, f_ix
);
451 length
= gcov_read_unsigned ();
452 if (length
!= gfi_ptr
->ident
)
455 length
= gcov_read_unsigned ();
456 if (length
!= gfi_ptr
->lineno_checksum
)
459 length
= gcov_read_unsigned ();
460 if (length
!= gfi_ptr
->cfg_checksum
)
463 ci_ptr
= gfi_ptr
->ctrs
;
464 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
466 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
471 tag
= gcov_read_unsigned ();
472 length
= gcov_read_unsigned ();
473 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
474 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
476 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
479 if ((error
= gcov_is_error ()))
486 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
487 filename
, f_ix
>= 0 ? "function" : "summary",
488 f_ix
< 0 ? -1 - f_ix
: f_ix
);
494 gcov_error ("profiling:%s:%s merging\n", filename
,
495 error
< 0 ? "Overflow": "Error");
499 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
500 the case of appending to an existing file, SUMMARY_POS will be non-zero.
501 We will write the file starting from SUMMAY_POS. */
504 write_one_data (const struct gcov_info
*gi_ptr
,
505 const struct gcov_summary
*prg_p
,
506 const gcov_position_t eof_pos
,
507 const gcov_position_t summary_pos
)
510 struct gcov_summary_buffer
*next_sum_buffer
;
512 /* Write out the data. */
515 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
516 gcov_write_unsigned (gi_ptr
->stamp
);
520 gcov_seek (summary_pos
);
522 /* Generate whole program statistics. */
523 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, prg_p
);
525 /* Rewrite all the summaries that were after the summary we merged
526 into. This is necessary as the merged summary may have a different
527 size due to the number of non-zero histogram entries changing after
532 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &sum_buffer
->summary
);
533 next_sum_buffer
= sum_buffer
->next
;
535 sum_buffer
= next_sum_buffer
;
538 /* Write execution counts for each function. */
539 for (f_ix
= 0; f_ix
!= gi_ptr
->n_functions
; f_ix
++)
541 unsigned buffered
= 0;
542 const struct gcov_fn_info
*gfi_ptr
;
543 const struct gcov_ctr_info
*ci_ptr
;
544 gcov_unsigned_t length
;
547 if (fn_buffer
&& fn_buffer
->fn_ix
== f_ix
)
549 /* Buffered data from another program. */
551 gfi_ptr
= &fn_buffer
->info
;
552 length
= GCOV_TAG_FUNCTION_LENGTH
;
556 gfi_ptr
= gi_ptr
->functions
[f_ix
];
557 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
558 length
= GCOV_TAG_FUNCTION_LENGTH
;
563 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
567 gcov_write_unsigned (gfi_ptr
->ident
);
568 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
569 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
571 ci_ptr
= gfi_ptr
->ctrs
;
572 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
574 gcov_unsigned_t n_counts
;
577 if (!gi_ptr
->merge
[t_ix
])
580 n_counts
= ci_ptr
->num
;
581 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
582 GCOV_TAG_COUNTER_LENGTH (n_counts
));
583 c_ptr
= ci_ptr
->values
;
585 gcov_write_counter (*c_ptr
++);
589 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
592 gcov_write_unsigned (0);
595 /* Helper function for merging summary.
596 Return -1 on error. Return 0 on success. */
599 merge_summary (const char *filename
, int run_counted
,
600 const struct gcov_info
*gi_ptr
, struct gcov_summary
*prg
,
601 struct gcov_summary
*this_prg
, gcov_unsigned_t crc32
,
602 struct gcov_summary
*all_prg
__attribute__ ((unused
)))
604 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
;
607 /* summary for all instances of program. */
608 struct gcov_ctr_summary
*cs_all
;
611 /* Merge the summaries. */
612 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
614 cs_prg
= &(prg
->ctrs
[t_ix
]);
615 cs_tprg
= &(this_prg
->ctrs
[t_ix
]);
617 if (gi_ptr
->merge
[t_ix
])
619 int first
= !cs_prg
->runs
;
624 cs_prg
->num
= cs_tprg
->num
;
625 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
626 if (cs_prg
->run_max
< cs_tprg
->run_max
)
627 cs_prg
->run_max
= cs_tprg
->run_max
;
628 cs_prg
->sum_max
+= cs_tprg
->run_max
;
630 memcpy (cs_prg
->histogram
, cs_tprg
->histogram
,
631 sizeof (gcov_bucket_type
) * GCOV_HISTOGRAM_SIZE
);
633 gcov_histogram_merge (cs_prg
->histogram
, cs_tprg
->histogram
);
635 else if (cs_prg
->runs
)
637 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
642 cs_all
= &all_prg
->ctrs
[t_ix
];
643 if (!cs_all
->runs
&& cs_prg
->runs
)
645 cs_all
->num
= cs_prg
->num
;
646 cs_all
->runs
= cs_prg
->runs
;
647 cs_all
->sum_all
= cs_prg
->sum_all
;
648 cs_all
->run_max
= cs_prg
->run_max
;
649 cs_all
->sum_max
= cs_prg
->sum_max
;
651 else if (!all_prg
->checksum
652 /* Don't compare the histograms, which may have slight
653 variations depending on the order they were updated
654 due to the truncating integer divides used in the
656 && (cs_all
->num
!= cs_prg
->num
657 || cs_all
->runs
!= cs_prg
->runs
658 || cs_all
->sum_all
!= cs_prg
->sum_all
659 || cs_all
->run_max
!= cs_prg
->run_max
660 || cs_all
->sum_max
!= cs_prg
->sum_max
))
662 gcov_error ("profiling:%s:Data file mismatch - some "
663 "data files may have been concurrently "
664 "updated without locking support\n", filename
);
665 all_prg
->checksum
= ~0u;
670 prg
->checksum
= crc32
;
676 /* Sort N entries in VALUE_ARRAY in descending order.
677 Each entry in VALUE_ARRAY has two values. The sorting
678 is based on the second value. */
681 gcov_sort_n_vals (gcov_type
*value_array
, int n
)
685 for (j
= 2; j
< n
; j
+= 2)
687 gcov_type cur_ent
[2];
689 cur_ent
[0] = value_array
[j
];
690 cur_ent
[1] = value_array
[j
+ 1];
692 while (k
>= 0 && value_array
[k
+ 1] < cur_ent
[1])
694 value_array
[k
+ 2] = value_array
[k
];
695 value_array
[k
+ 3] = value_array
[k
+1];
698 value_array
[k
+ 2] = cur_ent
[0];
699 value_array
[k
+ 3] = cur_ent
[1];
703 /* Sort the profile counters for all indirect call sites. Counters
704 for each call site are allocated in array COUNTERS. */
707 gcov_sort_icall_topn_counter (const struct gcov_ctr_info
*counters
)
711 int n
= counters
->num
;
713 gcc_assert (!(n
% GCOV_ICALL_TOPN_NCOUNTS
));
714 values
= counters
->values
;
716 for (i
= 0; i
< n
; i
+= GCOV_ICALL_TOPN_NCOUNTS
)
718 gcov_type
*value_array
= &values
[i
+ 1];
719 gcov_sort_n_vals (value_array
, GCOV_ICALL_TOPN_NCOUNTS
- 1);
723 /* Sort topn indirect_call profile counters in GI_PTR. */
726 gcov_sort_topn_counter_arrays (const struct gcov_info
*gi_ptr
)
730 const struct gcov_fn_info
*gfi_ptr
;
731 const struct gcov_ctr_info
*ci_ptr
;
733 if (!gi_ptr
->merge
[GCOV_COUNTER_ICALL_TOPNV
])
736 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
738 gfi_ptr
= gi_ptr
->functions
[f_ix
];
739 ci_ptr
= gfi_ptr
->ctrs
;
740 for (i
= 0; i
< GCOV_COUNTERS
; i
++)
742 if (!gi_ptr
->merge
[i
])
744 if (i
== GCOV_COUNTER_ICALL_TOPNV
)
746 gcov_sort_icall_topn_counter (ci_ptr
);
754 /* Dump the coverage counts for one gcov_info object. We merge with existing
755 counts when possible, to avoid growing the .da files ad infinitum. We use
756 this program's checksum to make sure we only accumulate whole program
757 statistics to the correct summary. An object file might be embedded
758 in two separate programs, and we must keep the two program
759 summaries separate. */
762 dump_one_gcov (struct gcov_info
*gi_ptr
, struct gcov_filename
*gf
,
763 unsigned run_counted
,
764 gcov_unsigned_t crc32
, struct gcov_summary
*all_prg
,
765 struct gcov_summary
*this_prg
)
767 struct gcov_summary prg
; /* summary for this object over all program. */
770 gcov_position_t summary_pos
= 0;
771 gcov_position_t eof_pos
= 0;
776 gcov_sort_topn_counter_arrays (gi_ptr
);
778 error
= gcov_exit_open_gcda_file (gi_ptr
, gf
);
782 tag
= gcov_read_unsigned ();
785 /* Merge data from file. */
786 if (tag
!= GCOV_DATA_MAGIC
)
788 gcov_error ("profiling:%s:Not a gcov data file\n", gf
->filename
);
791 error
= merge_one_data (gf
->filename
, gi_ptr
, &prg
, this_prg
,
792 &summary_pos
, &eof_pos
, crc32
);
801 memset (&prg
, 0, sizeof (prg
));
802 summary_pos
= eof_pos
;
805 error
= merge_summary (gf
->filename
, run_counted
, gi_ptr
, &prg
, this_prg
,
810 write_one_data (gi_ptr
, &prg
, eof_pos
, summary_pos
);
815 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
817 if ((error
= gcov_close ()))
818 gcov_error (error
< 0 ?
819 "profiling:%s:Overflow writing\n" :
820 "profiling:%s:Error writing\n",
825 /* Dump all the coverage counts for the program. It first computes program
826 summary and then traverses gcov_list list and dumps the gcov_info
827 objects one by one. */
833 gcov_do_dump (struct gcov_info
*list
, int run_counted
)
835 struct gcov_info
*gi_ptr
;
836 struct gcov_filename gf
;
837 gcov_unsigned_t crc32
;
838 struct gcov_summary all_prg
;
839 struct gcov_summary this_prg
;
841 crc32
= compute_summary (list
, &this_prg
, &gf
.max_length
);
843 allocate_filename_struct (&gf
);
845 memset (&all_prg
, 0, sizeof (all_prg
));
848 /* Now merge each file. */
849 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
850 dump_one_gcov (gi_ptr
, &gf
, run_counted
, crc32
, &all_prg
, &this_prg
);
857 __gcov_dump_one (struct gcov_root
*root
)
862 gcov_do_dump (root
->list
, root
->run_counted
);
865 root
->run_counted
= 1;
868 /* Per-dynamic-object gcov state. */
869 struct gcov_root __gcov_root
;
871 /* Exactly one of these will be live in the process image. */
872 struct gcov_master __gcov_master
=
878 __gcov_dump_one (&__gcov_root
);
879 if (__gcov_root
.next
)
880 __gcov_root
.next
->prev
= __gcov_root
.prev
;
881 if (__gcov_root
.prev
)
882 __gcov_root
.prev
->next
= __gcov_root
.next
;
884 __gcov_master
.root
= __gcov_root
.next
;
889 /* Add a new object file onto the bb chain. Invoked automatically
890 when running an object file's global ctors. */
893 __gcov_init (struct gcov_info
*info
)
895 if (!info
->version
|| !info
->n_functions
)
897 if (gcov_version (info
, info
->version
, 0))
899 if (!__gcov_root
.list
)
901 /* Add to master list and at exit function. */
902 if (gcov_version (NULL
, __gcov_master
.version
, "<master>"))
904 __gcov_root
.next
= __gcov_master
.root
;
905 if (__gcov_master
.root
)
906 __gcov_master
.root
->prev
= &__gcov_root
;
907 __gcov_master
.root
= &__gcov_root
;
911 info
->next
= __gcov_root
.list
;
912 __gcov_root
.list
= info
;
915 #endif /* !IN_GCOV_TOOL */
917 #endif /* inhibit_libc */