* soft-fp/op-4.h: Update from glibc.
[official-gcc.git] / libgcc / libgcov-driver.c
blobec6dffd76b36e0222f407c9c1b875ec93016d042
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;
328 /* If application calls fork or exec multiple times, we end up storing
329 profile repeadely. We should not account this as multiple runs or
330 functions executed once may mistakely become cold. */
331 static int run_accounted = 0;
333 /* This funtions computes the program level summary and the histo-gram.
334 It computes and returns CRC32 and stored summari in THIS_PRG. */
336 static gcov_unsigned_t
337 gcov_exit_compute_summary (void)
339 struct gcov_info *gi_ptr;
340 const struct gcov_fn_info *gfi_ptr;
341 struct gcov_ctr_summary *cs_ptr;
342 const struct gcov_ctr_info *ci_ptr;
343 int f_ix;
344 unsigned t_ix;
345 gcov_unsigned_t c_num;
346 gcov_unsigned_t crc32 = 0;
348 /* Find the totals for this execution. */
349 memset (&this_prg, 0, sizeof (this_prg));
350 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
352 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
353 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
355 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
357 gfi_ptr = gi_ptr->functions[f_ix];
359 if (gfi_ptr && gfi_ptr->key != gi_ptr)
360 gfi_ptr = 0;
362 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
363 crc32 = crc32_unsigned (crc32,
364 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
365 if (!gfi_ptr)
366 continue;
368 ci_ptr = gfi_ptr->ctrs;
369 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
371 if (!gi_ptr->merge[t_ix])
372 continue;
374 cs_ptr = &this_prg.ctrs[t_ix];
375 cs_ptr->num += ci_ptr->num;
376 crc32 = crc32_unsigned (crc32, ci_ptr->num);
378 for (c_num = 0; c_num < ci_ptr->num; c_num++)
380 cs_ptr->sum_all += ci_ptr->values[c_num];
381 if (cs_ptr->run_max < ci_ptr->values[c_num])
382 cs_ptr->run_max = ci_ptr->values[c_num];
384 ci_ptr++;
388 gcov_compute_histogram (&this_prg);
389 return crc32;
392 /* A struct that bundles all the related information about the
393 gcda filename. */
394 struct gcov_filename_aux{
395 char *gi_filename_up;
396 int gcov_prefix_strip;
397 size_t prefix_length;
400 /* Including system dependent components. */
401 #include "libgcov-driver-system.c"
403 /* This function merges counters in GI_PTR to an existing gcda file.
404 Return 0 on success.
405 Return -1 on error. In this case, caller will goto read_fatal. */
407 static int
408 gcov_exit_merge_gcda (struct gcov_info *gi_ptr,
409 struct gcov_summary *prg_p,
410 gcov_position_t *summary_pos_p,
411 gcov_position_t *eof_pos_p,
412 gcov_unsigned_t crc32)
414 gcov_unsigned_t tag, length;
415 unsigned t_ix;
416 int f_ix;
417 int error = 0;
418 struct gcov_fn_buffer **fn_tail = &fn_buffer;
419 struct gcov_summary_buffer **sum_tail = &sum_buffer;
421 length = gcov_read_unsigned ();
422 if (!gcov_version (gi_ptr, length, gi_filename))
423 return -1;
425 length = gcov_read_unsigned ();
426 if (length != gi_ptr->stamp)
427 /* Read from a different compilation. Overwrite the file. */
428 return 0;
430 /* Look for program summary. */
431 for (f_ix = 0;;)
433 struct gcov_summary tmp;
435 *eof_pos_p = gcov_position ();
436 tag = gcov_read_unsigned ();
437 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
438 break;
440 f_ix--;
441 length = gcov_read_unsigned ();
442 gcov_read_summary (&tmp);
443 if ((error = gcov_is_error ()))
444 goto read_error;
445 if (*summary_pos_p)
447 /* Save all summaries after the one that will be
448 merged into below. These will need to be rewritten
449 as histogram merging may change the number of non-zero
450 histogram entries that will be emitted, and thus the
451 size of the merged summary. */
452 (*sum_tail) = (struct gcov_summary_buffer *)
453 malloc (sizeof(struct gcov_summary_buffer));
454 (*sum_tail)->summary = tmp;
455 (*sum_tail)->next = 0;
456 sum_tail = &((*sum_tail)->next);
457 goto next_summary;
459 if (tmp.checksum != crc32)
460 goto next_summary;
462 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
463 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
464 goto next_summary;
465 *prg_p = tmp;
466 *summary_pos_p = *eof_pos_p;
468 next_summary:;
471 /* Merge execution counts for each function. */
472 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
473 f_ix++, tag = gcov_read_unsigned ())
475 const struct gcov_ctr_info *ci_ptr;
476 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
478 if (tag != GCOV_TAG_FUNCTION)
479 goto read_mismatch;
481 length = gcov_read_unsigned ();
482 if (!length)
483 /* This function did not appear in the other program.
484 We have nothing to merge. */
485 continue;
487 if (length != GCOV_TAG_FUNCTION_LENGTH)
488 goto read_mismatch;
490 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
492 /* This function appears in the other program. We
493 need to buffer the information in order to write
494 it back out -- we'll be inserting data before
495 this point, so cannot simply keep the data in the
496 file. */
497 fn_tail = buffer_fn_data (gi_filename,
498 gi_ptr, fn_tail, f_ix);
499 if (!fn_tail)
500 goto read_mismatch;
501 continue;
504 length = gcov_read_unsigned ();
505 if (length != gfi_ptr->ident)
506 goto read_mismatch;
508 length = gcov_read_unsigned ();
509 if (length != gfi_ptr->lineno_checksum)
510 goto read_mismatch;
512 length = gcov_read_unsigned ();
513 if (length != gfi_ptr->cfg_checksum)
514 goto read_mismatch;
516 ci_ptr = gfi_ptr->ctrs;
517 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
519 gcov_merge_fn merge = gi_ptr->merge[t_ix];
521 if (!merge)
522 continue;
524 tag = gcov_read_unsigned ();
525 length = gcov_read_unsigned ();
526 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
527 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
528 goto read_mismatch;
529 (*merge) (ci_ptr->values, ci_ptr->num);
530 ci_ptr++;
532 if ((error = gcov_is_error ()))
533 goto read_error;
536 if (tag)
538 read_mismatch:;
539 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
540 gi_filename, f_ix >= 0 ? "function" : "summary",
541 f_ix < 0 ? -1 - f_ix : f_ix);
542 return -1;
544 return 0;
546 read_error:
547 gcov_error ("profiling:%s:%s merging\n", gi_filename,
548 error < 0 ? "Overflow": "Error");
549 return -1;
552 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
553 the case of appending to an existing file, SUMMARY_POS will be non-zero.
554 We will write the file starting from SUMMAY_POS. */
556 static void
557 gcov_exit_write_gcda (const struct gcov_info *gi_ptr,
558 const struct gcov_summary *prg_p,
559 const gcov_position_t eof_pos,
560 const gcov_position_t summary_pos)
562 unsigned f_ix;
563 struct gcov_summary_buffer *next_sum_buffer;
565 /* Write out the data. */
566 if (!eof_pos)
568 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
569 gcov_write_unsigned (gi_ptr->stamp);
572 if (summary_pos)
573 gcov_seek (summary_pos);
575 /* Generate whole program statistics. */
576 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
578 /* Rewrite all the summaries that were after the summary we merged
579 into. This is necessary as the merged summary may have a different
580 size due to the number of non-zero histogram entries changing after
581 merging. */
583 while (sum_buffer)
585 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
586 next_sum_buffer = sum_buffer->next;
587 free (sum_buffer);
588 sum_buffer = next_sum_buffer;
591 /* Write execution counts for each function. */
592 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
594 unsigned buffered = 0;
595 const struct gcov_fn_info *gfi_ptr;
596 const struct gcov_ctr_info *ci_ptr;
597 gcov_unsigned_t length;
598 unsigned t_ix;
600 if (fn_buffer && fn_buffer->fn_ix == f_ix)
602 /* Buffered data from another program. */
603 buffered = 1;
604 gfi_ptr = &fn_buffer->info;
605 length = GCOV_TAG_FUNCTION_LENGTH;
607 else
609 gfi_ptr = gi_ptr->functions[f_ix];
610 if (gfi_ptr && gfi_ptr->key == gi_ptr)
611 length = GCOV_TAG_FUNCTION_LENGTH;
612 else
613 length = 0;
616 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
617 if (!length)
618 continue;
620 gcov_write_unsigned (gfi_ptr->ident);
621 gcov_write_unsigned (gfi_ptr->lineno_checksum);
622 gcov_write_unsigned (gfi_ptr->cfg_checksum);
624 ci_ptr = gfi_ptr->ctrs;
625 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
627 gcov_unsigned_t n_counts;
628 gcov_type *c_ptr;
630 if (!gi_ptr->merge[t_ix])
631 continue;
633 n_counts = ci_ptr->num;
634 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
635 GCOV_TAG_COUNTER_LENGTH (n_counts));
636 c_ptr = ci_ptr->values;
637 while (n_counts--)
638 gcov_write_counter (*c_ptr++);
639 ci_ptr++;
641 if (buffered)
642 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
645 gcov_write_unsigned (0);
648 /* Helper function for merging summary.
649 Return -1 on error. Return 0 on success. */
651 static int
652 gcov_exit_merge_summary (const struct gcov_info *gi_ptr, struct gcov_summary *prg,
653 gcov_unsigned_t crc32,
654 struct gcov_summary *all_prg __attribute__ ((unused)))
656 struct gcov_ctr_summary *cs_prg, *cs_tprg;
657 unsigned t_ix;
658 #if !GCOV_LOCKED
659 /* summary for all instances of program. */
660 struct gcov_ctr_summary *cs_all;
661 #endif
663 /* Merge the summaries. */
664 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
666 cs_prg = &(prg->ctrs[t_ix]);
667 cs_tprg = &this_prg.ctrs[t_ix];
669 if (gi_ptr->merge[t_ix])
671 int first = !cs_prg->runs;
673 if (!run_accounted)
674 cs_prg->runs++;
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);
820 run_accounted = 1;
822 if (gi_filename)
823 free (gi_filename);
826 /* Reset all counters to zero. */
828 void
829 gcov_clear (void)
831 const struct gcov_info *gi_ptr;
833 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
835 unsigned f_ix;
837 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
839 unsigned t_ix;
840 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
842 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
843 continue;
844 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
845 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
847 if (!gi_ptr->merge[t_ix])
848 continue;
850 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
851 ci_ptr++;
857 /* Add a new object file onto the bb chain. Invoked automatically
858 when running an object file's global ctors. */
860 void
861 __gcov_init (struct gcov_info *info)
863 if (!info->version || !info->n_functions)
864 return;
865 if (gcov_version (info, info->version, 0))
867 size_t filename_length = strlen(info->filename);
869 /* Refresh the longest file name information */
870 if (filename_length > gcov_max_filename)
871 gcov_max_filename = filename_length;
873 if (!gcov_list)
874 atexit (gcov_exit);
876 info->next = gcov_list;
877 gcov_list = info;
879 info->version = 0;
882 #endif /* L_gcov */
883 #endif /* inhibit_libc */