Rebase.
[official-gcc.git] / libgcc / libgcov-driver.c
blob50755358d6eabefee18d15a1b8ad2302dd93745c
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
10 version.
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
15 for more details.
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/>. */
26 #include "libgcov.h"
28 #if defined(inhibit_libc)
29 /* If libc and its header files are not available, provide dummy functions. */
31 #if defined(L_gcov)
32 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
33 #endif
35 #else /* inhibit_libc */
37 #include <string.h>
38 #if GCOV_LOCKED
39 #include <fcntl.h>
40 #include <errno.h>
41 #include <sys/stat.h>
42 #endif
44 #ifdef L_gcov
46 /* A utility function for outputing errors. */
47 static int gcov_error (const char *, ...);
49 #include "gcov-io.c"
51 struct gcov_fn_buffer
53 struct gcov_fn_buffer *next;
54 unsigned fn_ix;
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
66 gcda filename. */
68 struct gcov_filename
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. */
77 #ifndef IN_GCOV_TOOL
78 /* We need to expose this static variable when compiling for gcov-tool. */
79 static
80 #endif
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,
88 unsigned limit)
90 struct gcov_fn_buffer *next;
91 unsigned ix, n_ctr = 0;
93 if (!buffer)
94 return 0;
95 next = buffer->next;
97 for (ix = 0; ix != limit; ix++)
98 if (gi_ptr->merge[ix])
99 free (buffer->info.ctrs[n_ctr++].values);
100 free (buffer);
101 return next;
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;
110 unsigned len;
112 for (ix = GCOV_COUNTERS; ix--;)
113 if (gi_ptr->merge[ix])
114 n_ctrs++;
116 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
117 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
119 if (!fn_buffer)
120 goto fail;
122 fn_buffer->next = 0;
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;
131 gcov_type *values;
133 if (!gi_ptr->merge[ix])
134 continue;
136 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
138 len = 0;
139 goto fail;
142 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
143 len = length * sizeof (gcov_type);
144 values = (gcov_type *) xmalloc (len);
145 if (!values)
146 goto fail;
148 fn_buffer->info.ctrs[n_ctrs].num = length;
149 fn_buffer->info.ctrs[n_ctrs].values = values;
151 while (length--)
152 *values++ = gcov_read_counter ();
153 n_ctrs++;
156 *end_ptr = fn_buffer;
157 return &fn_buffer->next;
159 fail:
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)
171 unsigned ix;
173 for (ix = 32; ix--; value <<= 1)
175 unsigned feedback;
177 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
178 crc32 <<= 1;
179 crc32 ^= feedback;
182 return crc32;
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. */
190 static int
191 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
192 const char *filename)
194 if (version != GCOV_VERSION)
196 char v[4], e[4];
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);
203 return 0;
205 return 1;
208 /* Insert counter VALUE into HISTOGRAM. */
210 static void
211 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
213 unsigned i;
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. */
224 static void
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;
232 int h_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]);
239 if (!cs_ptr->num)
240 return;
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])
254 continue;
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])
262 ctr_info_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)
269 continue;
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,
293 size_t *max_length)
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;
299 int f_ix;
300 unsigned t_ix;
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));
306 *max_length = 0;
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)
311 *max_length = len;
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)
321 gfi_ptr = 0;
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);
326 if (!gfi_ptr)
327 continue;
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])
333 continue;
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];
345 ci_ptr++;
349 gcov_compute_histogram (this_prg);
350 return crc32;
353 /* Including system dependent components. */
354 #include "libgcov-driver-system.c"
356 /* This function merges counters in GI_PTR to an existing gcda file.
357 Return 0 on success.
358 Return -1 on error. In this case, caller will goto read_fatal. */
360 static int
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;
370 unsigned t_ix;
371 int f_ix;
372 int error = 0;
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))
378 return -1;
380 length = gcov_read_unsigned ();
381 if (length != gi_ptr->stamp)
382 /* Read from a different compilation. Overwrite the file. */
383 return 0;
385 /* Look for program summary. */
386 for (f_ix = 0;;)
388 struct gcov_summary tmp;
390 *eof_pos_p = gcov_position ();
391 tag = gcov_read_unsigned ();
392 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
393 break;
395 f_ix--;
396 length = gcov_read_unsigned ();
397 gcov_read_summary (&tmp);
398 if ((error = gcov_is_error ()))
399 goto read_error;
400 if (*summary_pos_p)
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);
412 goto next_summary;
414 if (tmp.checksum != crc32)
415 goto next_summary;
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)
419 goto next_summary;
420 *prg_p = tmp;
421 *summary_pos_p = *eof_pos_p;
423 next_summary:;
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)
434 goto read_mismatch;
436 length = gcov_read_unsigned ();
437 if (!length)
438 /* This function did not appear in the other program.
439 We have nothing to merge. */
440 continue;
442 if (length != GCOV_TAG_FUNCTION_LENGTH)
443 goto read_mismatch;
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
451 file. */
452 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
453 if (!fn_tail)
454 goto read_mismatch;
455 continue;
458 length = gcov_read_unsigned ();
459 if (length != gfi_ptr->ident)
460 goto read_mismatch;
462 length = gcov_read_unsigned ();
463 if (length != gfi_ptr->lineno_checksum)
464 goto read_mismatch;
466 length = gcov_read_unsigned ();
467 if (length != gfi_ptr->cfg_checksum)
468 goto read_mismatch;
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];
475 if (!merge)
476 continue;
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))
482 goto read_mismatch;
483 (*merge) (ci_ptr->values, ci_ptr->num);
484 ci_ptr++;
486 if ((error = gcov_is_error ()))
487 goto read_error;
490 if (tag)
492 read_mismatch:;
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);
496 return -1;
498 return 0;
500 read_error:
501 gcov_error ("profiling:%s:%s merging\n", filename,
502 error < 0 ? "Overflow": "Error");
503 return -1;
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. */
510 static void
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)
516 unsigned f_ix;
517 struct gcov_summary_buffer *next_sum_buffer;
519 /* Write out the data. */
520 if (!eof_pos)
522 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
523 gcov_write_unsigned (gi_ptr->stamp);
526 if (summary_pos)
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
535 merging. */
537 while (sum_buffer)
539 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
540 next_sum_buffer = sum_buffer->next;
541 free (sum_buffer);
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;
552 unsigned t_ix;
554 if (fn_buffer && fn_buffer->fn_ix == f_ix)
556 /* Buffered data from another program. */
557 buffered = 1;
558 gfi_ptr = &fn_buffer->info;
559 length = GCOV_TAG_FUNCTION_LENGTH;
561 else
563 gfi_ptr = gi_ptr->functions[f_ix];
564 if (gfi_ptr && gfi_ptr->key == gi_ptr)
565 length = GCOV_TAG_FUNCTION_LENGTH;
566 else
567 length = 0;
570 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
571 if (!length)
572 continue;
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;
582 gcov_type *c_ptr;
584 if (!gi_ptr->merge[t_ix])
585 continue;
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;
591 while (n_counts--)
592 gcov_write_counter (*c_ptr++);
593 ci_ptr++;
595 if (buffered)
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. */
605 static int
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;
612 unsigned t_ix;
613 #if !GCOV_LOCKED
614 /* summary for all instances of program. */
615 struct gcov_ctr_summary *cs_all;
616 #endif
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;
628 if (!run_counted)
629 cs_prg->runs++;
630 if (first)
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;
636 if (first)
637 memcpy (cs_prg->histogram, cs_tprg->histogram,
638 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
639 else
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",
645 filename);
646 return -1;
648 #if !GCOV_LOCKED
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
662 merge. */
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;
674 #endif
677 prg->checksum = crc32;
679 return 0;
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. */
689 static void
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. */
696 int error;
697 gcov_unsigned_t tag;
698 gcov_position_t summary_pos = 0;
699 gcov_position_t eof_pos = 0;
701 fn_buffer = 0;
702 sum_buffer = 0;
704 error = gcov_exit_open_gcda_file (gi_ptr, gf);
705 if (error == -1)
706 return;
708 tag = gcov_read_unsigned ();
709 if (tag)
711 /* Merge data from file. */
712 if (tag != GCOV_DATA_MAGIC)
714 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
715 goto read_fatal;
717 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
718 &summary_pos, &eof_pos, crc32);
719 if (error == -1)
720 goto read_fatal;
723 gcov_rewrite ();
725 if (!summary_pos)
727 memset (&prg, 0, sizeof (prg));
728 summary_pos = eof_pos;
731 error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
732 crc32, all_prg);
733 if (error == -1)
734 goto read_fatal;
736 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
737 /* fall through */
739 read_fatal:;
740 while (fn_buffer)
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",
747 gf->filename);
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);
767 #if !GCOV_LOCKED
768 memset (&all_prg, 0, sizeof (all_prg));
769 #endif
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);
775 free (gf.filename);
778 #if !IN_GCOV_TOOL
779 void
780 gcov_exit (void)
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)
785 return;
787 gcov_dump_complete = 1;
789 gcov_do_dump (gcov_list, run_accounted);
791 run_accounted = 1;
794 /* Reset all counters to zero. */
796 void
797 gcov_clear (void)
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)
804 unsigned f_ix;
806 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
808 unsigned t_ix;
809 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
811 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
812 continue;
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])
817 continue;
819 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
820 ci_ptr++;
826 /* Add a new object file onto the bb chain. Invoked automatically
827 when running an object file's global ctors. */
829 void
830 __gcov_init (struct gcov_info *info)
832 if (!info->version || !info->n_functions)
833 return;
834 if (gcov_version (info, info->version, 0))
836 if (!gcov_list)
837 atexit (gcov_exit);
839 info->next = gcov_list;
840 gcov_list = info;
842 info->version = 0;
844 #endif /* !IN_GCOV_TOOL */
845 #endif /* L_gcov */
846 #endif /* inhibit_libc */