2014-01-09 Max Ostapenko <m.ostapenko@partner.samsung.com>
[official-gcc.git] / libgcc / libgcov-driver.c
blob8429c69085a48a64189e6b87316624f3f4facecb
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
45 #include "gcov-io.c"
47 /* The following functions can be called from outside of this file. */
48 extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
49 extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
50 extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
51 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
52 extern int get_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
53 extern void set_gcov_list (struct gcov_info *) ATTRIBUTE_HIDDEN;
55 struct gcov_fn_buffer
57 struct gcov_fn_buffer *next;
58 unsigned fn_ix;
59 struct gcov_fn_info info;
60 /* note gcov_fn_info ends in a trailing array. */
63 struct gcov_summary_buffer
65 struct gcov_summary_buffer *next;
66 struct gcov_summary summary;
69 /* Chain of per-object gcov structures. */
70 static struct gcov_info *gcov_list;
72 /* Set the head of gcov_list. */
73 void
74 set_gcov_list (struct gcov_info *head)
76 gcov_list = head;
79 /* Size of the longest file name. */
80 static size_t gcov_max_filename = 0;
82 /* Flag when the profile has already been dumped via __gcov_dump(). */
83 static int gcov_dump_complete;
85 /* A global function that get the vaule of gcov_dump_complete. */
87 int
88 get_gcov_dump_complete (void)
90 return gcov_dump_complete;
93 /* A global functino that set the vaule of gcov_dump_complete. Will
94 be used in __gcov_dump() in libgcov-interface.c. */
96 void
97 set_gcov_dump_complete (void)
99 gcov_dump_complete = 1;
102 /* A global functino that set the vaule of gcov_dump_complete. Will
103 be used in __gcov_reset() in libgcov-interface.c. */
105 void
106 reset_gcov_dump_complete (void)
108 gcov_dump_complete = 0;
111 /* A utility function for outputing errors. */
112 static int gcov_error (const char *, ...);
114 static struct gcov_fn_buffer *
115 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
116 unsigned limit)
118 struct gcov_fn_buffer *next;
119 unsigned ix, n_ctr = 0;
121 if (!buffer)
122 return 0;
123 next = buffer->next;
125 for (ix = 0; ix != limit; ix++)
126 if (gi_ptr->merge[ix])
127 free (buffer->info.ctrs[n_ctr++].values);
128 free (buffer);
129 return next;
132 static struct gcov_fn_buffer **
133 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
134 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
136 unsigned n_ctrs = 0, ix = 0;
137 struct gcov_fn_buffer *fn_buffer;
138 unsigned len;
140 for (ix = GCOV_COUNTERS; ix--;)
141 if (gi_ptr->merge[ix])
142 n_ctrs++;
144 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
145 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
147 if (!fn_buffer)
148 goto fail;
150 fn_buffer->next = 0;
151 fn_buffer->fn_ix = fn_ix;
152 fn_buffer->info.ident = gcov_read_unsigned ();
153 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
154 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
156 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
158 gcov_unsigned_t length;
159 gcov_type *values;
161 if (!gi_ptr->merge[ix])
162 continue;
164 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
166 len = 0;
167 goto fail;
170 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
171 len = length * sizeof (gcov_type);
172 values = (gcov_type *) xmalloc (len);
173 if (!values)
174 goto fail;
176 fn_buffer->info.ctrs[n_ctrs].num = length;
177 fn_buffer->info.ctrs[n_ctrs].values = values;
179 while (length--)
180 *values++ = gcov_read_counter ();
181 n_ctrs++;
184 *end_ptr = fn_buffer;
185 return &fn_buffer->next;
187 fail:
188 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
189 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
191 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
194 /* Add an unsigned value to the current crc */
196 static gcov_unsigned_t
197 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
199 unsigned ix;
201 for (ix = 32; ix--; value <<= 1)
203 unsigned feedback;
205 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
206 crc32 <<= 1;
207 crc32 ^= feedback;
210 return crc32;
213 /* Check if VERSION of the info block PTR matches libgcov one.
214 Return 1 on success, or zero in case of versions mismatch.
215 If FILENAME is not NULL, its value used for reporting purposes
216 instead of value from the info block. */
218 static int
219 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
220 const char *filename)
222 if (version != GCOV_VERSION)
224 char v[4], e[4];
226 GCOV_UNSIGNED2STRING (v, version);
227 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
229 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
230 filename? filename : ptr->filename, e, v);
231 return 0;
233 return 1;
236 /* Insert counter VALUE into HISTOGRAM. */
238 static void
239 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
241 unsigned i;
243 i = gcov_histo_index(value);
244 histogram[i].num_counters++;
245 histogram[i].cum_value += value;
246 if (value < histogram[i].min_value)
247 histogram[i].min_value = value;
250 /* Computes a histogram of the arc counters to place in the summary SUM. */
252 static void
253 gcov_compute_histogram (struct gcov_summary *sum)
255 struct gcov_info *gi_ptr;
256 const struct gcov_fn_info *gfi_ptr;
257 const struct gcov_ctr_info *ci_ptr;
258 struct gcov_ctr_summary *cs_ptr;
259 unsigned t_ix, f_ix, ctr_info_ix, ix;
260 int h_ix;
262 /* This currently only applies to arc counters. */
263 t_ix = GCOV_COUNTER_ARCS;
265 /* First check if there are any counts recorded for this counter. */
266 cs_ptr = &(sum->ctrs[t_ix]);
267 if (!cs_ptr->num)
268 return;
270 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
272 cs_ptr->histogram[h_ix].num_counters = 0;
273 cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
274 cs_ptr->histogram[h_ix].cum_value = 0;
277 /* Walk through all the per-object structures and record each of
278 the count values in histogram. */
279 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
281 if (!gi_ptr->merge[t_ix])
282 continue;
284 /* Find the appropriate index into the gcov_ctr_info array
285 for the counter we are currently working on based on the
286 existence of the merge function pointer for this object. */
287 for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
289 if (gi_ptr->merge[ix])
290 ctr_info_ix++;
292 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
294 gfi_ptr = gi_ptr->functions[f_ix];
296 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
297 continue;
299 ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
300 for (ix = 0; ix < ci_ptr->num; ix++)
301 gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
306 /* summary for program. */
307 static struct gcov_summary this_prg;
308 /* gcda filename. */
309 static char *gi_filename;
310 /* buffer for the fn_data from another program. */
311 static struct gcov_fn_buffer *fn_buffer;
312 /* buffer for summary from other programs to be written out. */
313 static struct gcov_summary_buffer *sum_buffer;
314 /* If application calls fork or exec multiple times, we end up storing
315 profile repeadely. We should not account this as multiple runs or
316 functions executed once may mistakely become cold. */
317 static int run_accounted = 0;
319 /* This funtions computes the program level summary and the histo-gram.
320 It computes and returns CRC32 and stored summari in THIS_PRG. */
322 static gcov_unsigned_t
323 gcov_exit_compute_summary (void)
325 struct gcov_info *gi_ptr;
326 const struct gcov_fn_info *gfi_ptr;
327 struct gcov_ctr_summary *cs_ptr;
328 const struct gcov_ctr_info *ci_ptr;
329 int f_ix;
330 unsigned t_ix;
331 gcov_unsigned_t c_num;
332 gcov_unsigned_t crc32 = 0;
334 /* Find the totals for this execution. */
335 memset (&this_prg, 0, sizeof (this_prg));
336 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
338 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
339 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
341 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
343 gfi_ptr = gi_ptr->functions[f_ix];
345 if (gfi_ptr && gfi_ptr->key != gi_ptr)
346 gfi_ptr = 0;
348 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
349 crc32 = crc32_unsigned (crc32,
350 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
351 if (!gfi_ptr)
352 continue;
354 ci_ptr = gfi_ptr->ctrs;
355 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
357 if (!gi_ptr->merge[t_ix])
358 continue;
360 cs_ptr = &this_prg.ctrs[t_ix];
361 cs_ptr->num += ci_ptr->num;
362 crc32 = crc32_unsigned (crc32, ci_ptr->num);
364 for (c_num = 0; c_num < ci_ptr->num; c_num++)
366 cs_ptr->sum_all += ci_ptr->values[c_num];
367 if (cs_ptr->run_max < ci_ptr->values[c_num])
368 cs_ptr->run_max = ci_ptr->values[c_num];
370 ci_ptr++;
374 gcov_compute_histogram (&this_prg);
375 return crc32;
378 /* A struct that bundles all the related information about the
379 gcda filename. */
380 struct gcov_filename_aux{
381 char *gi_filename_up;
382 int gcov_prefix_strip;
383 size_t prefix_length;
386 /* Including system dependent components. */
387 #include "libgcov-driver-system.c"
389 /* This function merges counters in GI_PTR to an existing gcda file.
390 Return 0 on success.
391 Return -1 on error. In this case, caller will goto read_fatal. */
393 static int
394 gcov_exit_merge_gcda (struct gcov_info *gi_ptr,
395 struct gcov_summary *prg_p,
396 gcov_position_t *summary_pos_p,
397 gcov_position_t *eof_pos_p,
398 gcov_unsigned_t crc32)
400 gcov_unsigned_t tag, length;
401 unsigned t_ix;
402 int f_ix;
403 int error = 0;
404 struct gcov_fn_buffer **fn_tail = &fn_buffer;
405 struct gcov_summary_buffer **sum_tail = &sum_buffer;
407 length = gcov_read_unsigned ();
408 if (!gcov_version (gi_ptr, length, gi_filename))
409 return -1;
411 length = gcov_read_unsigned ();
412 if (length != gi_ptr->stamp)
413 /* Read from a different compilation. Overwrite the file. */
414 return 0;
416 /* Look for program summary. */
417 for (f_ix = 0;;)
419 struct gcov_summary tmp;
421 *eof_pos_p = gcov_position ();
422 tag = gcov_read_unsigned ();
423 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
424 break;
426 f_ix--;
427 length = gcov_read_unsigned ();
428 gcov_read_summary (&tmp);
429 if ((error = gcov_is_error ()))
430 goto read_error;
431 if (*summary_pos_p)
433 /* Save all summaries after the one that will be
434 merged into below. These will need to be rewritten
435 as histogram merging may change the number of non-zero
436 histogram entries that will be emitted, and thus the
437 size of the merged summary. */
438 (*sum_tail) = (struct gcov_summary_buffer *)
439 xmalloc (sizeof(struct gcov_summary_buffer));
440 (*sum_tail)->summary = tmp;
441 (*sum_tail)->next = 0;
442 sum_tail = &((*sum_tail)->next);
443 goto next_summary;
445 if (tmp.checksum != crc32)
446 goto next_summary;
448 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
449 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
450 goto next_summary;
451 *prg_p = tmp;
452 *summary_pos_p = *eof_pos_p;
454 next_summary:;
457 /* Merge execution counts for each function. */
458 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
459 f_ix++, tag = gcov_read_unsigned ())
461 const struct gcov_ctr_info *ci_ptr;
462 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
464 if (tag != GCOV_TAG_FUNCTION)
465 goto read_mismatch;
467 length = gcov_read_unsigned ();
468 if (!length)
469 /* This function did not appear in the other program.
470 We have nothing to merge. */
471 continue;
473 if (length != GCOV_TAG_FUNCTION_LENGTH)
474 goto read_mismatch;
476 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
478 /* This function appears in the other program. We
479 need to buffer the information in order to write
480 it back out -- we'll be inserting data before
481 this point, so cannot simply keep the data in the
482 file. */
483 fn_tail = buffer_fn_data (gi_filename,
484 gi_ptr, fn_tail, f_ix);
485 if (!fn_tail)
486 goto read_mismatch;
487 continue;
490 length = gcov_read_unsigned ();
491 if (length != gfi_ptr->ident)
492 goto read_mismatch;
494 length = gcov_read_unsigned ();
495 if (length != gfi_ptr->lineno_checksum)
496 goto read_mismatch;
498 length = gcov_read_unsigned ();
499 if (length != gfi_ptr->cfg_checksum)
500 goto read_mismatch;
502 ci_ptr = gfi_ptr->ctrs;
503 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
505 gcov_merge_fn merge = gi_ptr->merge[t_ix];
507 if (!merge)
508 continue;
510 tag = gcov_read_unsigned ();
511 length = gcov_read_unsigned ();
512 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
513 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
514 goto read_mismatch;
515 (*merge) (ci_ptr->values, ci_ptr->num);
516 ci_ptr++;
518 if ((error = gcov_is_error ()))
519 goto read_error;
522 if (tag)
524 read_mismatch:;
525 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
526 gi_filename, f_ix >= 0 ? "function" : "summary",
527 f_ix < 0 ? -1 - f_ix : f_ix);
528 return -1;
530 return 0;
532 read_error:
533 gcov_error ("profiling:%s:%s merging\n", gi_filename,
534 error < 0 ? "Overflow": "Error");
535 return -1;
538 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
539 the case of appending to an existing file, SUMMARY_POS will be non-zero.
540 We will write the file starting from SUMMAY_POS. */
542 static void
543 gcov_exit_write_gcda (const struct gcov_info *gi_ptr,
544 const struct gcov_summary *prg_p,
545 const gcov_position_t eof_pos,
546 const gcov_position_t summary_pos)
548 unsigned f_ix;
549 struct gcov_summary_buffer *next_sum_buffer;
551 /* Write out the data. */
552 if (!eof_pos)
554 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
555 gcov_write_unsigned (gi_ptr->stamp);
558 if (summary_pos)
559 gcov_seek (summary_pos);
561 /* Generate whole program statistics. */
562 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
564 /* Rewrite all the summaries that were after the summary we merged
565 into. This is necessary as the merged summary may have a different
566 size due to the number of non-zero histogram entries changing after
567 merging. */
569 while (sum_buffer)
571 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
572 next_sum_buffer = sum_buffer->next;
573 free (sum_buffer);
574 sum_buffer = next_sum_buffer;
577 /* Write execution counts for each function. */
578 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
580 unsigned buffered = 0;
581 const struct gcov_fn_info *gfi_ptr;
582 const struct gcov_ctr_info *ci_ptr;
583 gcov_unsigned_t length;
584 unsigned t_ix;
586 if (fn_buffer && fn_buffer->fn_ix == f_ix)
588 /* Buffered data from another program. */
589 buffered = 1;
590 gfi_ptr = &fn_buffer->info;
591 length = GCOV_TAG_FUNCTION_LENGTH;
593 else
595 gfi_ptr = gi_ptr->functions[f_ix];
596 if (gfi_ptr && gfi_ptr->key == gi_ptr)
597 length = GCOV_TAG_FUNCTION_LENGTH;
598 else
599 length = 0;
602 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
603 if (!length)
604 continue;
606 gcov_write_unsigned (gfi_ptr->ident);
607 gcov_write_unsigned (gfi_ptr->lineno_checksum);
608 gcov_write_unsigned (gfi_ptr->cfg_checksum);
610 ci_ptr = gfi_ptr->ctrs;
611 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
613 gcov_unsigned_t n_counts;
614 gcov_type *c_ptr;
616 if (!gi_ptr->merge[t_ix])
617 continue;
619 n_counts = ci_ptr->num;
620 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
621 GCOV_TAG_COUNTER_LENGTH (n_counts));
622 c_ptr = ci_ptr->values;
623 while (n_counts--)
624 gcov_write_counter (*c_ptr++);
625 ci_ptr++;
627 if (buffered)
628 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
631 gcov_write_unsigned (0);
634 /* Helper function for merging summary.
635 Return -1 on error. Return 0 on success. */
637 static int
638 gcov_exit_merge_summary (const struct gcov_info *gi_ptr, struct gcov_summary *prg,
639 gcov_unsigned_t crc32,
640 struct gcov_summary *all_prg __attribute__ ((unused)))
642 struct gcov_ctr_summary *cs_prg, *cs_tprg;
643 unsigned t_ix;
644 #if !GCOV_LOCKED
645 /* summary for all instances of program. */
646 struct gcov_ctr_summary *cs_all;
647 #endif
649 /* Merge the summaries. */
650 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
652 cs_prg = &(prg->ctrs[t_ix]);
653 cs_tprg = &this_prg.ctrs[t_ix];
655 if (gi_ptr->merge[t_ix])
657 int first = !cs_prg->runs;
659 if (!run_accounted)
660 cs_prg->runs++;
661 if (first)
662 cs_prg->num = cs_tprg->num;
663 cs_prg->sum_all += cs_tprg->sum_all;
664 if (cs_prg->run_max < cs_tprg->run_max)
665 cs_prg->run_max = cs_tprg->run_max;
666 cs_prg->sum_max += cs_tprg->run_max;
667 if (first)
668 memcpy (cs_prg->histogram, cs_tprg->histogram,
669 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
670 else
671 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
673 else if (cs_prg->runs)
675 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
676 gi_filename);
677 return -1;
679 #if !GCOV_LOCKED
680 cs_all = &all_prg->ctrs[t_ix];
681 if (!cs_all->runs && cs_prg->runs)
683 cs_all->num = cs_prg->num;
684 cs_all->runs = cs_prg->runs;
685 cs_all->sum_all = cs_prg->sum_all;
686 cs_all->run_max = cs_prg->run_max;
687 cs_all->sum_max = cs_prg->sum_max;
689 else if (!all_prg->checksum
690 /* Don't compare the histograms, which may have slight
691 variations depending on the order they were updated
692 due to the truncating integer divides used in the
693 merge. */
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 gcov_error ("profiling:%s:Data file mismatch - some "
701 "data files may have been concurrently "
702 "updated without locking support\n", gi_filename);
703 all_prg->checksum = ~0u;
705 #endif
708 prg->checksum = crc32;
710 return 0;
713 /* Dump the coverage counts for one gcov_info object. We merge with existing
714 counts when possible, to avoid growing the .da files ad infinitum. We use
715 this program's checksum to make sure we only accumulate whole program
716 statistics to the correct summary. An object file might be embedded
717 in two separate programs, and we must keep the two program
718 summaries separate. */
720 static void
721 gcov_exit_dump_gcov (struct gcov_info *gi_ptr, struct gcov_filename_aux *gf,
722 gcov_unsigned_t crc32, struct gcov_summary *all_prg)
724 struct gcov_summary prg; /* summary for this object over all program. */
725 int error;
726 gcov_unsigned_t tag;
727 gcov_position_t summary_pos = 0;
728 gcov_position_t eof_pos = 0;
730 fn_buffer = 0;
731 sum_buffer = 0;
733 error = gcov_exit_open_gcda_file (gi_ptr, gf);
734 if (error == -1)
735 return;
737 tag = gcov_read_unsigned ();
738 if (tag)
740 /* Merge data from file. */
741 if (tag != GCOV_DATA_MAGIC)
743 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename);
744 goto read_fatal;
746 error = gcov_exit_merge_gcda (gi_ptr, &prg, &summary_pos, &eof_pos,
747 crc32);
748 if (error == -1)
749 goto read_fatal;
752 gcov_rewrite ();
754 if (!summary_pos)
756 memset (&prg, 0, sizeof (prg));
757 summary_pos = eof_pos;
760 error = gcov_exit_merge_summary (gi_ptr, &prg, crc32, all_prg);
761 if (error == -1)
762 goto read_fatal;
764 gcov_exit_write_gcda (gi_ptr, &prg, eof_pos, summary_pos);
765 /* fall through */
767 read_fatal:;
768 while (fn_buffer)
769 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
771 if ((error = gcov_close ()))
772 gcov_error (error < 0 ?
773 "profiling:%s:Overflow writing\n" :
774 "profiling:%s:Error writing\n",
775 gi_filename);
779 /* Dump all the coverage counts for the program. It first computes program
780 summary and then traverses gcov_list list and dumps the gcov_info
781 objects one by one. */
783 void
784 gcov_exit (void)
786 struct gcov_info *gi_ptr;
787 struct gcov_filename_aux gf;
788 gcov_unsigned_t crc32;
789 struct gcov_summary all_prg;
791 /* Prevent the counters from being dumped a second time on exit when the
792 application already wrote out the profile using __gcov_dump(). */
793 if (gcov_dump_complete)
794 return;
796 crc32 = gcov_exit_compute_summary ();
798 allocate_filename_struct (&gf);
799 #if !GCOV_LOCKED
800 memset (&all_prg, 0, sizeof (all_prg));
801 #endif
803 /* Now merge each file. */
804 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
805 gcov_exit_dump_gcov (gi_ptr, &gf, crc32, &all_prg);
806 run_accounted = 1;
808 if (gi_filename)
809 free (gi_filename);
812 /* Reset all counters to zero. */
814 void
815 gcov_clear (void)
817 const struct gcov_info *gi_ptr;
819 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
821 unsigned f_ix;
823 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
825 unsigned t_ix;
826 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
828 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
829 continue;
830 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
831 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
833 if (!gi_ptr->merge[t_ix])
834 continue;
836 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
837 ci_ptr++;
843 /* Add a new object file onto the bb chain. Invoked automatically
844 when running an object file's global ctors. */
846 void
847 __gcov_init (struct gcov_info *info)
849 if (!info->version || !info->n_functions)
850 return;
851 if (gcov_version (info, info->version, 0))
853 size_t filename_length = strlen(info->filename);
855 /* Refresh the longest file name information */
856 if (filename_length > gcov_max_filename)
857 gcov_max_filename = filename_length;
859 if (!gcov_list)
860 atexit (gcov_exit);
862 info->next = gcov_list;
863 gcov_list = info;
865 info->version = 0;
868 #endif /* L_gcov */
869 #endif /* inhibit_libc */