* libgcov-driver.c (get_gcov_dump_complete): Update comments.
[official-gcc.git] / libgcc / libgcov-driver.c
blob9d527cd93e31ee29fcfa279b5a2119315408a9db
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2013 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 "tconfig.h"
27 #include "tsystem.h"
28 #include "coretypes.h"
29 #include "tm.h"
30 #include "libgcc_tm.h"
32 #if defined(inhibit_libc)
33 #define IN_LIBGCOV (-1)
34 #else
35 #define IN_LIBGCOV 1
36 #if defined(L_gcov)
37 #define GCOV_LINKAGE /* nothing */
38 #endif
39 #endif
40 #include "gcov-io.h"
42 #if defined(inhibit_libc)
43 /* If libc and its header files are not available, provide dummy functions. */
45 #if defined(L_gcov)
46 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
47 #endif
49 #else /* inhibit_libc */
51 #include <string.h>
52 #if GCOV_LOCKED
53 #include <fcntl.h>
54 #include <errno.h>
55 #include <sys/stat.h>
56 #endif
58 #ifdef L_gcov
59 #include "gcov-io.c"
61 /* The following functions can be called from outside of this file. */
62 extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
63 extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
64 extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
65 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
66 extern int get_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
67 extern void set_gcov_list (struct gcov_info *) ATTRIBUTE_HIDDEN;
69 struct gcov_fn_buffer
71 struct gcov_fn_buffer *next;
72 unsigned fn_ix;
73 struct gcov_fn_info info;
74 /* note gcov_fn_info ends in a trailing array. */
77 struct gcov_summary_buffer
79 struct gcov_summary_buffer *next;
80 struct gcov_summary summary;
83 /* Chain of per-object gcov structures. */
84 static struct gcov_info *gcov_list;
86 /* Set the head of gcov_list. */
87 void
88 set_gcov_list (struct gcov_info *head)
90 gcov_list = head;
93 /* Size of the longest file name. */
94 static size_t gcov_max_filename = 0;
96 /* Flag when the profile has already been dumped via __gcov_dump(). */
97 static int gcov_dump_complete;
99 /* A global function that get the vaule of gcov_dump_complete. */
102 get_gcov_dump_complete (void)
104 return gcov_dump_complete;
107 /* A global functino that set the vaule of gcov_dump_complete. Will
108 be used in __gcov_dump() in libgcov-interface.c. */
110 void
111 set_gcov_dump_complete (void)
113 gcov_dump_complete = 1;
116 /* A global functino that set the vaule of gcov_dump_complete. Will
117 be used in __gcov_reset() in libgcov-interface.c. */
119 void
120 reset_gcov_dump_complete (void)
122 gcov_dump_complete = 0;
125 /* A utility function for outputing errors. */
126 static int gcov_error (const char *, ...);
128 static struct gcov_fn_buffer *
129 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
130 unsigned limit)
132 struct gcov_fn_buffer *next;
133 unsigned ix, n_ctr = 0;
135 if (!buffer)
136 return 0;
137 next = buffer->next;
139 for (ix = 0; ix != limit; ix++)
140 if (gi_ptr->merge[ix])
141 free (buffer->info.ctrs[n_ctr++].values);
142 free (buffer);
143 return next;
146 static struct gcov_fn_buffer **
147 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
148 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
150 unsigned n_ctrs = 0, ix = 0;
151 struct gcov_fn_buffer *fn_buffer;
152 unsigned len;
154 for (ix = GCOV_COUNTERS; ix--;)
155 if (gi_ptr->merge[ix])
156 n_ctrs++;
158 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
159 fn_buffer = (struct gcov_fn_buffer *)malloc (len);
161 if (!fn_buffer)
162 goto fail;
164 fn_buffer->next = 0;
165 fn_buffer->fn_ix = fn_ix;
166 fn_buffer->info.ident = gcov_read_unsigned ();
167 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
168 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
170 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
172 gcov_unsigned_t length;
173 gcov_type *values;
175 if (!gi_ptr->merge[ix])
176 continue;
178 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
180 len = 0;
181 goto fail;
184 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
185 len = length * sizeof (gcov_type);
186 values = (gcov_type *)malloc (len);
187 if (!values)
188 goto fail;
190 fn_buffer->info.ctrs[n_ctrs].num = length;
191 fn_buffer->info.ctrs[n_ctrs].values = values;
193 while (length--)
194 *values++ = gcov_read_counter ();
195 n_ctrs++;
198 *end_ptr = fn_buffer;
199 return &fn_buffer->next;
201 fail:
202 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
203 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
205 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
208 /* Add an unsigned value to the current crc */
210 static gcov_unsigned_t
211 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
213 unsigned ix;
215 for (ix = 32; ix--; value <<= 1)
217 unsigned feedback;
219 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
220 crc32 <<= 1;
221 crc32 ^= feedback;
224 return crc32;
227 /* Check if VERSION of the info block PTR matches libgcov one.
228 Return 1 on success, or zero in case of versions mismatch.
229 If FILENAME is not NULL, its value used for reporting purposes
230 instead of value from the info block. */
232 static int
233 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
234 const char *filename)
236 if (version != GCOV_VERSION)
238 char v[4], e[4];
240 GCOV_UNSIGNED2STRING (v, version);
241 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
243 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
244 filename? filename : ptr->filename, e, v);
245 return 0;
247 return 1;
250 /* Insert counter VALUE into HISTOGRAM. */
252 static void
253 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
255 unsigned i;
257 i = gcov_histo_index(value);
258 histogram[i].num_counters++;
259 histogram[i].cum_value += value;
260 if (value < histogram[i].min_value)
261 histogram[i].min_value = value;
264 /* Computes a histogram of the arc counters to place in the summary SUM. */
266 static void
267 gcov_compute_histogram (struct gcov_summary *sum)
269 struct gcov_info *gi_ptr;
270 const struct gcov_fn_info *gfi_ptr;
271 const struct gcov_ctr_info *ci_ptr;
272 struct gcov_ctr_summary *cs_ptr;
273 unsigned t_ix, f_ix, ctr_info_ix, ix;
274 int h_ix;
276 /* This currently only applies to arc counters. */
277 t_ix = GCOV_COUNTER_ARCS;
279 /* First check if there are any counts recorded for this counter. */
280 cs_ptr = &(sum->ctrs[t_ix]);
281 if (!cs_ptr->num)
282 return;
284 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
286 cs_ptr->histogram[h_ix].num_counters = 0;
287 cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
288 cs_ptr->histogram[h_ix].cum_value = 0;
291 /* Walk through all the per-object structures and record each of
292 the count values in histogram. */
293 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
295 if (!gi_ptr->merge[t_ix])
296 continue;
298 /* Find the appropriate index into the gcov_ctr_info array
299 for the counter we are currently working on based on the
300 existence of the merge function pointer for this object. */
301 for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
303 if (gi_ptr->merge[ix])
304 ctr_info_ix++;
306 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
308 gfi_ptr = gi_ptr->functions[f_ix];
310 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
311 continue;
313 ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
314 for (ix = 0; ix < ci_ptr->num; ix++)
315 gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
320 /* summary for program. */
321 static struct gcov_summary this_prg;
322 /* gcda filename. */
323 static char *gi_filename;
324 /* buffer for the fn_data from another program. */
325 static struct gcov_fn_buffer *fn_buffer;
326 /* buffer for summary from other programs to be written out. */
327 static struct gcov_summary_buffer *sum_buffer;
329 /* This funtions computes the program level summary and the histo-gram.
330 It computes and returns CRC32 and stored summari in THIS_PRG. */
332 static gcov_unsigned_t
333 gcov_exit_compute_summary (void)
335 struct gcov_info *gi_ptr;
336 const struct gcov_fn_info *gfi_ptr;
337 struct gcov_ctr_summary *cs_ptr;
338 const struct gcov_ctr_info *ci_ptr;
339 int f_ix;
340 unsigned t_ix;
341 gcov_unsigned_t c_num;
342 gcov_unsigned_t crc32 = 0;
344 /* Find the totals for this execution. */
345 memset (&this_prg, 0, sizeof (this_prg));
346 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
348 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
349 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
351 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
353 gfi_ptr = gi_ptr->functions[f_ix];
355 if (gfi_ptr && gfi_ptr->key != gi_ptr)
356 gfi_ptr = 0;
358 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
359 crc32 = crc32_unsigned (crc32,
360 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
361 if (!gfi_ptr)
362 continue;
364 ci_ptr = gfi_ptr->ctrs;
365 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
367 if (!gi_ptr->merge[t_ix])
368 continue;
370 cs_ptr = &this_prg.ctrs[t_ix];
371 cs_ptr->num += ci_ptr->num;
372 crc32 = crc32_unsigned (crc32, ci_ptr->num);
374 for (c_num = 0; c_num < ci_ptr->num; c_num++)
376 cs_ptr->sum_all += ci_ptr->values[c_num];
377 if (cs_ptr->run_max < ci_ptr->values[c_num])
378 cs_ptr->run_max = ci_ptr->values[c_num];
380 ci_ptr++;
384 gcov_compute_histogram (&this_prg);
385 return crc32;
388 /* A struct that bundles all the related information about the
389 gcda filename. */
390 struct gcov_filename_aux{
391 char *gi_filename_up;
392 int gcov_prefix_strip;
393 size_t prefix_length;
396 /* Including system dependent components. */
397 #include "libgcov-driver-system.c"
399 /* This function merges counters in GI_PTR to an existing gcda file.
400 Return 0 on success.
401 Return -1 on error. In this case, caller will goto read_fatal. */
403 static int
404 gcov_exit_merge_gcda (struct gcov_info *gi_ptr,
405 struct gcov_summary *prg_p,
406 gcov_position_t *summary_pos_p,
407 gcov_position_t *eof_pos_p,
408 gcov_unsigned_t crc32)
410 gcov_unsigned_t tag, length;
411 unsigned t_ix;
412 int f_ix;
413 int error = 0;
414 struct gcov_fn_buffer **fn_tail = &fn_buffer;
415 struct gcov_summary_buffer **sum_tail = &sum_buffer;
417 length = gcov_read_unsigned ();
418 if (!gcov_version (gi_ptr, length, gi_filename))
419 return -1;
421 length = gcov_read_unsigned ();
422 if (length != gi_ptr->stamp)
423 /* Read from a different compilation. Overwrite the file. */
424 return 0;
426 /* Look for program summary. */
427 for (f_ix = 0;;)
429 struct gcov_summary tmp;
431 *eof_pos_p = gcov_position ();
432 tag = gcov_read_unsigned ();
433 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
434 break;
436 f_ix--;
437 length = gcov_read_unsigned ();
438 gcov_read_summary (&tmp);
439 if ((error = gcov_is_error ()))
440 goto read_error;
441 if (*summary_pos_p)
443 /* Save all summaries after the one that will be
444 merged into below. These will need to be rewritten
445 as histogram merging may change the number of non-zero
446 histogram entries that will be emitted, and thus the
447 size of the merged summary. */
448 (*sum_tail) = (struct gcov_summary_buffer *)
449 malloc (sizeof(struct gcov_summary_buffer));
450 (*sum_tail)->summary = tmp;
451 (*sum_tail)->next = 0;
452 sum_tail = &((*sum_tail)->next);
453 goto next_summary;
455 if (tmp.checksum != crc32)
456 goto next_summary;
458 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
459 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
460 goto next_summary;
461 *prg_p = tmp;
462 *summary_pos_p = *eof_pos_p;
464 next_summary:;
467 /* Merge execution counts for each function. */
468 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
469 f_ix++, tag = gcov_read_unsigned ())
471 const struct gcov_ctr_info *ci_ptr;
472 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
474 if (tag != GCOV_TAG_FUNCTION)
475 goto read_mismatch;
477 length = gcov_read_unsigned ();
478 if (!length)
479 /* This function did not appear in the other program.
480 We have nothing to merge. */
481 continue;
483 if (length != GCOV_TAG_FUNCTION_LENGTH)
484 goto read_mismatch;
486 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
488 /* This function appears in the other program. We
489 need to buffer the information in order to write
490 it back out -- we'll be inserting data before
491 this point, so cannot simply keep the data in the
492 file. */
493 fn_tail = buffer_fn_data (gi_filename,
494 gi_ptr, fn_tail, f_ix);
495 if (!fn_tail)
496 goto read_mismatch;
497 continue;
500 length = gcov_read_unsigned ();
501 if (length != gfi_ptr->ident)
502 goto read_mismatch;
504 length = gcov_read_unsigned ();
505 if (length != gfi_ptr->lineno_checksum)
506 goto read_mismatch;
508 length = gcov_read_unsigned ();
509 if (length != gfi_ptr->cfg_checksum)
510 goto read_mismatch;
512 ci_ptr = gfi_ptr->ctrs;
513 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
515 gcov_merge_fn merge = gi_ptr->merge[t_ix];
517 if (!merge)
518 continue;
520 tag = gcov_read_unsigned ();
521 length = gcov_read_unsigned ();
522 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
523 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
524 goto read_mismatch;
525 (*merge) (ci_ptr->values, ci_ptr->num);
526 ci_ptr++;
528 if ((error = gcov_is_error ()))
529 goto read_error;
532 if (tag)
534 read_mismatch:;
535 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
536 gi_filename, f_ix >= 0 ? "function" : "summary",
537 f_ix < 0 ? -1 - f_ix : f_ix);
538 return -1;
540 return 0;
542 read_error:
543 gcov_error ("profiling:%s:%s merging\n", gi_filename,
544 error < 0 ? "Overflow": "Error");
545 return -1;
548 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
549 the case of appending to an existing file, SUMMARY_POS will be non-zero.
550 We will write the file starting from SUMMAY_POS. */
552 static void
553 gcov_exit_write_gcda (const struct gcov_info *gi_ptr,
554 const struct gcov_summary *prg_p,
555 const gcov_position_t eof_pos,
556 const gcov_position_t summary_pos)
558 unsigned f_ix;
559 struct gcov_summary_buffer *next_sum_buffer;
561 /* Write out the data. */
562 if (!eof_pos)
564 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
565 gcov_write_unsigned (gi_ptr->stamp);
568 if (summary_pos)
569 gcov_seek (summary_pos);
571 /* Generate whole program statistics. */
572 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
574 /* Rewrite all the summaries that were after the summary we merged
575 into. This is necessary as the merged summary may have a different
576 size due to the number of non-zero histogram entries changing after
577 merging. */
579 while (sum_buffer)
581 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
582 next_sum_buffer = sum_buffer->next;
583 free (sum_buffer);
584 sum_buffer = next_sum_buffer;
587 /* Write execution counts for each function. */
588 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
590 unsigned buffered = 0;
591 const struct gcov_fn_info *gfi_ptr;
592 const struct gcov_ctr_info *ci_ptr;
593 gcov_unsigned_t length;
594 unsigned t_ix;
596 if (fn_buffer && fn_buffer->fn_ix == f_ix)
598 /* Buffered data from another program. */
599 buffered = 1;
600 gfi_ptr = &fn_buffer->info;
601 length = GCOV_TAG_FUNCTION_LENGTH;
603 else
605 gfi_ptr = gi_ptr->functions[f_ix];
606 if (gfi_ptr && gfi_ptr->key == gi_ptr)
607 length = GCOV_TAG_FUNCTION_LENGTH;
608 else
609 length = 0;
612 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
613 if (!length)
614 continue;
616 gcov_write_unsigned (gfi_ptr->ident);
617 gcov_write_unsigned (gfi_ptr->lineno_checksum);
618 gcov_write_unsigned (gfi_ptr->cfg_checksum);
620 ci_ptr = gfi_ptr->ctrs;
621 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
623 gcov_unsigned_t n_counts;
624 gcov_type *c_ptr;
626 if (!gi_ptr->merge[t_ix])
627 continue;
629 n_counts = ci_ptr->num;
630 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
631 GCOV_TAG_COUNTER_LENGTH (n_counts));
632 c_ptr = ci_ptr->values;
633 while (n_counts--)
634 gcov_write_counter (*c_ptr++);
635 ci_ptr++;
637 if (buffered)
638 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
641 gcov_write_unsigned (0);
644 /* Helper function for merging summary.
645 Return -1 on error. Return 0 on success. */
647 static int
648 gcov_exit_merge_summary (const struct gcov_info *gi_ptr, struct gcov_summary *prg,
649 gcov_unsigned_t crc32, struct gcov_summary *all_prg)
651 struct gcov_ctr_summary *cs_prg, *cs_tprg;
652 unsigned t_ix;
653 /* If application calls fork or exec multiple times, we end up storing
654 profile repeadely. We should not account this as multiple runs or
655 functions executed once may mistakely become cold. */
656 static int run_accounted = 0;
657 #if !GCOV_LOCKED
658 /* summary for all instances of program. */
659 struct gcov_ctr_summary *cs_all;
660 #endif
662 /* Merge the summaries. */
663 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
665 cs_prg = &(prg->ctrs[t_ix]);
666 cs_tprg = &this_prg.ctrs[t_ix];
668 if (gi_ptr->merge[t_ix])
670 int first = !cs_prg->runs;
672 if (!run_accounted)
673 cs_prg->runs++;
674 run_accounted = 1;
675 if (first)
676 cs_prg->num = cs_tprg->num;
677 cs_prg->sum_all += cs_tprg->sum_all;
678 if (cs_prg->run_max < cs_tprg->run_max)
679 cs_prg->run_max = cs_tprg->run_max;
680 cs_prg->sum_max += cs_tprg->run_max;
681 if (first)
682 memcpy (cs_prg->histogram, cs_tprg->histogram,
683 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
684 else
685 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
687 else if (cs_prg->runs)
689 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
690 gi_filename);
691 return -1;
693 #if !GCOV_LOCKED
694 cs_all = &all_prg->ctrs[t_ix];
695 if (!cs_all->runs && cs_prg->runs)
697 cs_all->num = cs_prg->num;
698 cs_all->runs = cs_prg->runs;
699 cs_all->sum_all = cs_prg->sum_all;
700 cs_all->run_max = cs_prg->run_max;
701 cs_all->sum_max = cs_prg->sum_max;
703 else if (!all_prg->checksum
704 /* Don't compare the histograms, which may have slight
705 variations depending on the order they were updated
706 due to the truncating integer divides used in the
707 merge. */
708 && (cs_all->num != cs_prg->num
709 || cs_all->runs != cs_prg->runs
710 || cs_all->sum_all != cs_prg->sum_all
711 || cs_all->run_max != cs_prg->run_max
712 || cs_all->sum_max != cs_prg->sum_max))
714 gcov_error ("profiling:%s:Data file mismatch - some "
715 "data files may have been concurrently "
716 "updated without locking support\n", gi_filename);
717 all_prg->checksum = ~0u;
719 #endif
722 prg->checksum = crc32;
724 return 0;
727 /* Dump the coverage counts for one gcov_info object. We merge with existing
728 counts when possible, to avoid growing the .da files ad infinitum. We use
729 this program's checksum to make sure we only accumulate whole program
730 statistics to the correct summary. An object file might be embedded
731 in two separate programs, and we must keep the two program
732 summaries separate. */
734 static void
735 gcov_exit_dump_gcov (struct gcov_info *gi_ptr, struct gcov_filename_aux *gf,
736 gcov_unsigned_t crc32, struct gcov_summary *all_prg)
738 struct gcov_summary prg; /* summary for this object over all program. */
739 int error;
740 gcov_unsigned_t tag;
741 gcov_position_t summary_pos = 0;
742 gcov_position_t eof_pos = 0;
744 fn_buffer = 0;
745 sum_buffer = 0;
747 error = gcov_exit_open_gcda_file (gi_ptr, gf);
748 if (error == -1)
749 return;
751 tag = gcov_read_unsigned ();
752 if (tag)
754 /* Merge data from file. */
755 if (tag != GCOV_DATA_MAGIC)
757 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename);
758 goto read_fatal;
760 error = gcov_exit_merge_gcda (gi_ptr, &prg, &summary_pos, &eof_pos,
761 crc32);
762 if (error == -1)
763 goto read_fatal;
766 gcov_rewrite ();
768 if (!summary_pos)
770 memset (&prg, 0, sizeof (prg));
771 summary_pos = eof_pos;
774 error = gcov_exit_merge_summary (gi_ptr, &prg, crc32, all_prg);
775 if (error == -1)
776 goto read_fatal;
778 gcov_exit_write_gcda (gi_ptr, &prg, eof_pos, summary_pos);
779 /* fall through */
781 read_fatal:;
782 while (fn_buffer)
783 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
785 if ((error = gcov_close ()))
786 gcov_error (error < 0 ?
787 "profiling:%s:Overflow writing\n" :
788 "profiling:%s:Error writing\n",
789 gi_filename);
793 /* Dump all the coverage counts for the program. It first computes program
794 summary and then traverses gcov_list list and dumps the gcov_info
795 objects one by one. */
797 void
798 gcov_exit (void)
800 struct gcov_info *gi_ptr;
801 struct gcov_filename_aux gf;
802 gcov_unsigned_t crc32;
803 struct gcov_summary all_prg;
805 /* Prevent the counters from being dumped a second time on exit when the
806 application already wrote out the profile using __gcov_dump(). */
807 if (gcov_dump_complete)
808 return;
810 crc32 = gcov_exit_compute_summary ();
812 allocate_filename_struct (&gf);
813 #if !GCOV_LOCKED
814 memset (&all_prg, 0, sizeof (all_prg));
815 #endif
817 /* Now merge each file. */
818 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
819 gcov_exit_dump_gcov (gi_ptr, &gf, crc32, &all_prg);
821 if (gi_filename)
822 free (gi_filename);
825 /* Reset all counters to zero. */
827 void
828 gcov_clear (void)
830 const struct gcov_info *gi_ptr;
832 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
834 unsigned f_ix;
836 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
838 unsigned t_ix;
839 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
841 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
842 continue;
843 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
844 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
846 if (!gi_ptr->merge[t_ix])
847 continue;
849 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
850 ci_ptr++;
856 /* Add a new object file onto the bb chain. Invoked automatically
857 when running an object file's global ctors. */
859 void
860 __gcov_init (struct gcov_info *info)
862 if (!info->version || !info->n_functions)
863 return;
864 if (gcov_version (info, info->version, 0))
866 size_t filename_length = strlen(info->filename);
868 /* Refresh the longest file name information */
869 if (filename_length > gcov_max_filename)
870 gcov_max_filename = filename_length;
872 if (!gcov_list)
873 atexit (gcov_exit);
875 info->next = gcov_list;
876 gcov_list = info;
878 info->version = 0;
881 #endif /* L_gcov */
882 #endif /* inhibit_libc */