Reverting merge from trunk
[official-gcc.git] / libgcc / libgcov-driver.c
blob93bf2fb7ace61add010a3c3f8d9eeda59c1b7908
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 functino 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 #if !GCOV_LOCKED
323 /* summary for all instances of program. */
324 static struct gcov_summary all_prg;
325 #endif
326 /* crc32 for this program. */
327 static gcov_unsigned_t crc32;
328 /* gcda filename. */
329 static char *gi_filename;
330 /* buffer for the fn_data from another program. */
331 static struct gcov_fn_buffer *fn_buffer;
332 /* buffer for summary from other programs to be written out. */
333 static struct gcov_summary_buffer *sum_buffer;
335 /* This funtions computes the program level summary and the histo-gram.
336 It initializes ALL_PRG, computes CRC32, and stores the summary in
337 THIS_PRG. All these three variables are file statics. */
339 static void
340 gcov_exit_compute_summary (void)
342 struct gcov_info *gi_ptr;
343 const struct gcov_fn_info *gfi_ptr;
344 struct gcov_ctr_summary *cs_ptr;
345 const struct gcov_ctr_info *ci_ptr;
346 int f_ix;
347 unsigned t_ix;
348 gcov_unsigned_t c_num;
350 #if !GCOV_LOCKED
351 memset (&all_prg, 0, sizeof (all_prg));
352 #endif
353 /* Find the totals for this execution. */
354 memset (&this_prg, 0, sizeof (this_prg));
355 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
357 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
358 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
360 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
362 gfi_ptr = gi_ptr->functions[f_ix];
364 if (gfi_ptr && gfi_ptr->key != gi_ptr)
365 gfi_ptr = 0;
367 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
368 crc32 = crc32_unsigned (crc32,
369 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
370 if (!gfi_ptr)
371 continue;
373 ci_ptr = gfi_ptr->ctrs;
374 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
376 if (!gi_ptr->merge[t_ix])
377 continue;
379 cs_ptr = &this_prg.ctrs[t_ix];
380 cs_ptr->num += ci_ptr->num;
381 crc32 = crc32_unsigned (crc32, ci_ptr->num);
383 for (c_num = 0; c_num < ci_ptr->num; c_num++)
385 cs_ptr->sum_all += ci_ptr->values[c_num];
386 if (cs_ptr->run_max < ci_ptr->values[c_num])
387 cs_ptr->run_max = ci_ptr->values[c_num];
389 ci_ptr++;
393 gcov_compute_histogram (&this_prg);
396 /* A struct that bundles all the related information about the
397 gcda filename. */
398 struct gcov_filename_aux{
399 char *gi_filename_up;
400 int gcov_prefix_strip;
401 size_t prefix_length;
404 /* Including system dependent components. */
405 #include "libgcov-driver-system.c"
407 /* This function merges counters in GI_PTR to an existing gcda file.
408 Return 0 on success.
409 Return -1 on error. In this case, caller will goto read_fatal. */
411 static int
412 gcov_exit_merge_gcda (struct gcov_info *gi_ptr,
413 struct gcov_summary *prg_p,
414 gcov_position_t *summary_pos_p,
415 gcov_position_t *eof_pos_p)
417 gcov_unsigned_t tag, length;
418 unsigned t_ix;
419 int f_ix;
420 int error = 0;
421 struct gcov_fn_buffer **fn_tail = &fn_buffer;
422 struct gcov_summary_buffer **sum_tail = &sum_buffer;
424 length = gcov_read_unsigned ();
425 if (!gcov_version (gi_ptr, length, gi_filename))
426 return -1;
428 length = gcov_read_unsigned ();
429 if (length != gi_ptr->stamp)
430 /* Read from a different compilation. Overwrite the file. */
431 return 0;
433 /* Look for program summary. */
434 for (f_ix = 0;;)
436 struct gcov_summary tmp;
438 *eof_pos_p = gcov_position ();
439 tag = gcov_read_unsigned ();
440 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
441 break;
443 f_ix--;
444 length = gcov_read_unsigned ();
445 gcov_read_summary (&tmp);
446 if ((error = gcov_is_error ()))
447 goto read_error;
448 if (*summary_pos_p)
450 /* Save all summaries after the one that will be
451 merged into below. These will need to be rewritten
452 as histogram merging may change the number of non-zero
453 histogram entries that will be emitted, and thus the
454 size of the merged summary. */
455 (*sum_tail) = (struct gcov_summary_buffer *)
456 malloc (sizeof(struct gcov_summary_buffer));
457 (*sum_tail)->summary = tmp;
458 (*sum_tail)->next = 0;
459 sum_tail = &((*sum_tail)->next);
460 goto next_summary;
462 if (tmp.checksum != crc32)
463 goto next_summary;
465 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
466 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
467 goto next_summary;
468 *prg_p = tmp;
469 *summary_pos_p = *eof_pos_p;
471 next_summary:;
474 /* Merge execution counts for each function. */
475 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
476 f_ix++, tag = gcov_read_unsigned ())
478 const struct gcov_ctr_info *ci_ptr;
479 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
481 if (tag != GCOV_TAG_FUNCTION)
482 goto read_mismatch;
484 length = gcov_read_unsigned ();
485 if (!length)
486 /* This function did not appear in the other program.
487 We have nothing to merge. */
488 continue;
490 if (length != GCOV_TAG_FUNCTION_LENGTH)
491 goto read_mismatch;
493 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
495 /* This function appears in the other program. We
496 need to buffer the information in order to write
497 it back out -- we'll be inserting data before
498 this point, so cannot simply keep the data in the
499 file. */
500 fn_tail = buffer_fn_data (gi_filename,
501 gi_ptr, fn_tail, f_ix);
502 if (!fn_tail)
503 goto read_mismatch;
504 continue;
507 length = gcov_read_unsigned ();
508 if (length != gfi_ptr->ident)
509 goto read_mismatch;
511 length = gcov_read_unsigned ();
512 if (length != gfi_ptr->lineno_checksum)
513 goto read_mismatch;
515 length = gcov_read_unsigned ();
516 if (length != gfi_ptr->cfg_checksum)
517 goto read_mismatch;
519 ci_ptr = gfi_ptr->ctrs;
520 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
522 gcov_merge_fn merge = gi_ptr->merge[t_ix];
524 if (!merge)
525 continue;
527 tag = gcov_read_unsigned ();
528 length = gcov_read_unsigned ();
529 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
530 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
531 goto read_mismatch;
532 (*merge) (ci_ptr->values, ci_ptr->num);
533 ci_ptr++;
535 if ((error = gcov_is_error ()))
536 goto read_error;
539 if (tag)
541 read_mismatch:;
542 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
543 gi_filename, f_ix >= 0 ? "function" : "summary",
544 f_ix < 0 ? -1 - f_ix : f_ix);
545 return -1;
547 return 0;
549 read_error:
550 gcov_error ("profiling:%s:%s merging\n", gi_filename,
551 error < 0 ? "Overflow": "Error");
552 return -1;
555 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
556 the case of appending to an existing file, SUMMARY_POS will be non-zero.
557 We will write the file starting from SUMMAY_POS. */
559 static void
560 gcov_exit_write_gcda (const struct gcov_info *gi_ptr,
561 const struct gcov_summary *prg_p,
562 const gcov_position_t eof_pos,
563 const gcov_position_t summary_pos)
565 unsigned f_ix;
566 struct gcov_summary_buffer *next_sum_buffer;
568 /* Write out the data. */
569 if (!eof_pos)
571 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
572 gcov_write_unsigned (gi_ptr->stamp);
575 if (summary_pos)
576 gcov_seek (summary_pos);
578 /* Generate whole program statistics. */
579 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
581 /* Rewrite all the summaries that were after the summary we merged
582 into. This is necessary as the merged summary may have a different
583 size due to the number of non-zero histogram entries changing after
584 merging. */
586 while (sum_buffer)
588 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
589 next_sum_buffer = sum_buffer->next;
590 free (sum_buffer);
591 sum_buffer = next_sum_buffer;
594 /* Write execution counts for each function. */
595 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
597 unsigned buffered = 0;
598 const struct gcov_fn_info *gfi_ptr;
599 const struct gcov_ctr_info *ci_ptr;
600 gcov_unsigned_t length;
601 unsigned t_ix;
603 if (fn_buffer && fn_buffer->fn_ix == f_ix)
605 /* Buffered data from another program. */
606 buffered = 1;
607 gfi_ptr = &fn_buffer->info;
608 length = GCOV_TAG_FUNCTION_LENGTH;
610 else
612 gfi_ptr = gi_ptr->functions[f_ix];
613 if (gfi_ptr && gfi_ptr->key == gi_ptr)
614 length = GCOV_TAG_FUNCTION_LENGTH;
615 else
616 length = 0;
619 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
620 if (!length)
621 continue;
623 gcov_write_unsigned (gfi_ptr->ident);
624 gcov_write_unsigned (gfi_ptr->lineno_checksum);
625 gcov_write_unsigned (gfi_ptr->cfg_checksum);
627 ci_ptr = gfi_ptr->ctrs;
628 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
630 gcov_unsigned_t n_counts;
631 gcov_type *c_ptr;
633 if (!gi_ptr->merge[t_ix])
634 continue;
636 n_counts = ci_ptr->num;
637 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
638 GCOV_TAG_COUNTER_LENGTH (n_counts));
639 c_ptr = ci_ptr->values;
640 while (n_counts--)
641 gcov_write_counter (*c_ptr++);
642 ci_ptr++;
644 if (buffered)
645 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
648 gcov_write_unsigned (0);
651 /* Helper function for merging summary.
652 Return -1 on error. Return 0 on success. */
654 static int
655 gcov_exit_merge_summary (const struct gcov_info *gi_ptr, struct gcov_summary *prg)
657 struct gcov_ctr_summary *cs_prg, *cs_tprg;
658 #if !GCOV_LOCKED
659 struct gcov_ctr_summary *cs_all;
660 #endif
661 unsigned t_ix;
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 if (!cs_prg->runs++)
672 cs_prg->num = cs_tprg->num;
673 cs_prg->sum_all += cs_tprg->sum_all;
674 if (cs_prg->run_max < cs_tprg->run_max)
675 cs_prg->run_max = cs_tprg->run_max;
676 cs_prg->sum_max += cs_tprg->run_max;
677 if (cs_prg->runs == 1)
678 memcpy (cs_prg->histogram, cs_tprg->histogram,
679 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
680 else
681 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
683 else if (cs_prg->runs)
685 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
686 gi_filename);
687 return -1;
690 #if !GCOV_LOCKED
691 cs_all = &all_prg.ctrs[t_ix];
692 if (!cs_all->runs && cs_prg->runs)
694 cs_all->num = cs_prg->num;
695 cs_all->runs = cs_prg->runs;
696 cs_all->sum_all = cs_prg->sum_all;
697 cs_all->run_max = cs_prg->run_max;
698 cs_all->sum_max = cs_prg->sum_max;
700 else if (!all_prg.checksum
701 /* Don't compare the histograms, which may have slight
702 variations depending on the order they were updated
703 due to the truncating integer divides used in the
704 merge. */
705 && (cs_all->num != cs_prg->num
706 || cs_all->runs != cs_prg->runs
707 || cs_all->sum_all != cs_prg->sum_all
708 || cs_all->run_max != cs_prg->run_max
709 || cs_all->sum_max != cs_prg->sum_max))
711 gcov_error ("profiling:%s:Data file mismatch - some "
712 "data files may have been concurrently "
713 "updated without locking support\n", gi_filename);
714 all_prg.checksum = ~0u;
716 #endif
719 prg->checksum = crc32;
721 return 0;
724 /* Dump the coverage counts for one gcov_info object. We merge with existing
725 counts when possible, to avoid growing the .da files ad infinitum. We use
726 this program's checksum to make sure we only accumulate whole program
727 statistics to the correct summary. An object file might be embedded
728 in two separate programs, and we must keep the two program
729 summaries separate. */
731 static void
732 gcov_exit_dump_gcov (struct gcov_info *gi_ptr, struct gcov_filename_aux *gf)
734 struct gcov_summary prg; /* summary for this object over all program. */
735 int error;
736 gcov_unsigned_t tag;
737 gcov_position_t summary_pos = 0;
738 gcov_position_t eof_pos = 0;
740 fn_buffer = 0;
741 sum_buffer = 0;
743 error = gcov_exit_open_gcda_file (gi_ptr, gf);
744 if (error == -1)
745 return;
747 tag = gcov_read_unsigned ();
748 if (tag)
750 /* Merge data from file. */
751 if (tag != GCOV_DATA_MAGIC)
753 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename);
754 goto read_fatal;
756 error = gcov_exit_merge_gcda (gi_ptr, &prg, &summary_pos, &eof_pos);
757 if (error == -1)
758 goto read_fatal;
761 gcov_rewrite ();
763 if (!summary_pos)
765 memset (&prg, 0, sizeof (prg));
766 summary_pos = eof_pos;
769 error = gcov_exit_merge_summary (gi_ptr, &prg);
770 if (error == -1)
771 goto read_fatal;
773 gcov_exit_write_gcda (gi_ptr, &prg, eof_pos, summary_pos);
774 /* fall through */
776 read_fatal:;
777 while (fn_buffer)
778 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
780 if ((error = gcov_close ()))
781 gcov_error (error < 0 ?
782 "profiling:%s:Overflow writing\n" :
783 "profiling:%s:Error writing\n",
784 gi_filename);
788 /* Dump all the coverage counts for the program. It first computes program
789 summary and then traverses gcov_list list and dumps the gcov_info
790 objects one by one. */
792 void
793 gcov_exit (void)
795 struct gcov_info *gi_ptr;
796 struct gcov_filename_aux gf;
798 /* Prevent the counters from being dumped a second time on exit when the
799 application already wrote out the profile using __gcov_dump(). */
800 if (gcov_dump_complete)
801 return;
803 gcov_exit_compute_summary ();
805 allocate_filename_struct (&gf);
807 /* Now merge each file. */
808 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
809 gcov_exit_dump_gcov (gi_ptr, &gf);
811 if (gi_filename)
812 free (gi_filename);
815 /* Reset all counters to zero. */
817 void
818 gcov_clear (void)
820 const struct gcov_info *gi_ptr;
822 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
824 unsigned f_ix;
826 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
828 unsigned t_ix;
829 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
831 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
832 continue;
833 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
834 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
836 if (!gi_ptr->merge[t_ix])
837 continue;
839 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
840 ci_ptr++;
846 /* Add a new object file onto the bb chain. Invoked automatically
847 when running an object file's global ctors. */
849 void
850 __gcov_init (struct gcov_info *info)
852 if (!info->version || !info->n_functions)
853 return;
854 if (gcov_version (info, info->version, 0))
856 size_t filename_length = strlen(info->filename);
858 /* Refresh the longest file name information */
859 if (filename_length > gcov_max_filename)
860 gcov_max_filename = filename_length;
862 if (!gcov_list)
863 atexit (gcov_exit);
865 info->next = gcov_list;
866 gcov_list = info;
868 info->version = 0;
871 #endif /* L_gcov */
872 #endif /* inhibit_libc */