PR fortran/56408
[official-gcc.git] / libgcc / libgcov-driver.c
blob34c58cd5feca5c6db06c14c8f8c691f9d780bca2
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgcov.h"
28 #if defined(inhibit_libc)
29 /* If libc and its header files are not available, provide dummy functions. */
31 #if defined(L_gcov)
32 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
33 #endif
35 #else /* inhibit_libc */
37 #include <string.h>
38 #if GCOV_LOCKED
39 #include <fcntl.h>
40 #include <errno.h>
41 #include <sys/stat.h>
42 #endif
44 #ifdef L_gcov
46 /* A utility function for outputing errors. */
47 static int gcov_error (const char *, ...);
49 #include "gcov-io.c"
51 struct gcov_fn_buffer
53 struct gcov_fn_buffer *next;
54 unsigned fn_ix;
55 struct gcov_fn_info info;
56 /* note gcov_fn_info ends in a trailing array. */
59 struct gcov_summary_buffer
61 struct gcov_summary_buffer *next;
62 struct gcov_summary summary;
65 /* A struct that bundles all the related information about the
66 gcda filename. */
68 struct gcov_filename
70 char *filename; /* filename buffer */
71 size_t max_length; /* maximum filename length */
72 int strip; /* leading chars to strip from filename */
73 size_t prefix; /* chars to prepend to filename */
76 static struct gcov_fn_buffer *
77 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
78 unsigned limit)
80 struct gcov_fn_buffer *next;
81 unsigned ix, n_ctr = 0;
83 if (!buffer)
84 return 0;
85 next = buffer->next;
87 for (ix = 0; ix != limit; ix++)
88 if (gi_ptr->merge[ix])
89 free (buffer->info.ctrs[n_ctr++].values);
90 free (buffer);
91 return next;
94 static struct gcov_fn_buffer **
95 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
96 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
98 unsigned n_ctrs = 0, ix = 0;
99 struct gcov_fn_buffer *fn_buffer;
100 unsigned len;
102 for (ix = GCOV_COUNTERS; ix--;)
103 if (gi_ptr->merge[ix])
104 n_ctrs++;
106 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
107 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
109 if (!fn_buffer)
110 goto fail;
112 fn_buffer->next = 0;
113 fn_buffer->fn_ix = fn_ix;
114 fn_buffer->info.ident = gcov_read_unsigned ();
115 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
116 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
118 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
120 gcov_unsigned_t length;
121 gcov_type *values;
123 if (!gi_ptr->merge[ix])
124 continue;
126 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
128 len = 0;
129 goto fail;
132 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
133 len = length * sizeof (gcov_type);
134 values = (gcov_type *) xmalloc (len);
135 if (!values)
136 goto fail;
138 fn_buffer->info.ctrs[n_ctrs].num = length;
139 fn_buffer->info.ctrs[n_ctrs].values = values;
141 while (length--)
142 *values++ = gcov_read_counter ();
143 n_ctrs++;
146 *end_ptr = fn_buffer;
147 return &fn_buffer->next;
149 fail:
150 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
151 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
153 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
156 /* Add an unsigned value to the current crc */
158 static gcov_unsigned_t
159 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
161 unsigned ix;
163 for (ix = 32; ix--; value <<= 1)
165 unsigned feedback;
167 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
168 crc32 <<= 1;
169 crc32 ^= feedback;
172 return crc32;
175 /* Check if VERSION of the info block PTR matches libgcov one.
176 Return 1 on success, or zero in case of versions mismatch.
177 If FILENAME is not NULL, its value used for reporting purposes
178 instead of value from the info block. */
180 static int
181 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
182 const char *filename)
184 if (version != GCOV_VERSION)
186 char v[4], e[4];
188 GCOV_UNSIGNED2STRING (v, version);
189 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
191 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
192 filename? filename : ptr->filename, e, v);
193 return 0;
195 return 1;
198 /* Insert counter VALUE into HISTOGRAM. */
200 static void
201 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
203 unsigned i;
205 i = gcov_histo_index(value);
206 histogram[i].num_counters++;
207 histogram[i].cum_value += value;
208 if (value < histogram[i].min_value)
209 histogram[i].min_value = value;
212 /* Computes a histogram of the arc counters to place in the summary SUM. */
214 static void
215 gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
217 struct gcov_info *gi_ptr;
218 const struct gcov_fn_info *gfi_ptr;
219 const struct gcov_ctr_info *ci_ptr;
220 struct gcov_ctr_summary *cs_ptr;
221 unsigned t_ix, f_ix, ctr_info_ix, ix;
222 int h_ix;
224 /* This currently only applies to arc counters. */
225 t_ix = GCOV_COUNTER_ARCS;
227 /* First check if there are any counts recorded for this counter. */
228 cs_ptr = &(sum->ctrs[t_ix]);
229 if (!cs_ptr->num)
230 return;
232 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
234 cs_ptr->histogram[h_ix].num_counters = 0;
235 cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
236 cs_ptr->histogram[h_ix].cum_value = 0;
239 /* Walk through all the per-object structures and record each of
240 the count values in histogram. */
241 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
243 if (!gi_ptr->merge[t_ix])
244 continue;
246 /* Find the appropriate index into the gcov_ctr_info array
247 for the counter we are currently working on based on the
248 existence of the merge function pointer for this object. */
249 for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
251 if (gi_ptr->merge[ix])
252 ctr_info_ix++;
254 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
256 gfi_ptr = gi_ptr->functions[f_ix];
258 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
259 continue;
261 ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
262 for (ix = 0; ix < ci_ptr->num; ix++)
263 gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
268 /* buffer for the fn_data from another program. */
269 static struct gcov_fn_buffer *fn_buffer;
270 /* buffer for summary from other programs to be written out. */
271 static struct gcov_summary_buffer *sum_buffer;
273 /* This function computes the program level summary and the histo-gram.
274 It computes and returns CRC32 and stored summary in THIS_PRG.
275 Also determines the longest filename length of the info files. */
277 static gcov_unsigned_t
278 compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
279 size_t *max_length)
281 struct gcov_info *gi_ptr;
282 const struct gcov_fn_info *gfi_ptr;
283 struct gcov_ctr_summary *cs_ptr;
284 const struct gcov_ctr_info *ci_ptr;
285 int f_ix;
286 unsigned t_ix;
287 gcov_unsigned_t c_num;
288 gcov_unsigned_t crc32 = 0;
290 /* Find the totals for this execution. */
291 memset (this_prg, 0, sizeof (*this_prg));
292 *max_length = 0;
293 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
295 size_t len = strlen (gi_ptr->filename);
296 if (len > *max_length)
297 *max_length = len;
299 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
300 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
302 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
304 gfi_ptr = gi_ptr->functions[f_ix];
306 if (gfi_ptr && gfi_ptr->key != gi_ptr)
307 gfi_ptr = 0;
309 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
310 crc32 = crc32_unsigned (crc32,
311 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
312 if (!gfi_ptr)
313 continue;
315 ci_ptr = gfi_ptr->ctrs;
316 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
318 if (!gi_ptr->merge[t_ix])
319 continue;
321 cs_ptr = &(this_prg->ctrs[t_ix]);
322 cs_ptr->num += ci_ptr->num;
323 crc32 = crc32_unsigned (crc32, ci_ptr->num);
325 for (c_num = 0; c_num < ci_ptr->num; c_num++)
327 cs_ptr->sum_all += ci_ptr->values[c_num];
328 if (cs_ptr->run_max < ci_ptr->values[c_num])
329 cs_ptr->run_max = ci_ptr->values[c_num];
331 ci_ptr++;
335 gcov_compute_histogram (list, this_prg);
336 return crc32;
339 /* Including system dependent components. */
340 #include "libgcov-driver-system.c"
342 /* This function merges counters in GI_PTR to an existing gcda file.
343 Return 0 on success.
344 Return -1 on error. In this case, caller will goto read_fatal. */
346 static int
347 merge_one_data (const char *filename,
348 struct gcov_info *gi_ptr,
349 struct gcov_summary *prg_p,
350 struct gcov_summary *this_prg,
351 gcov_position_t *summary_pos_p,
352 gcov_position_t *eof_pos_p,
353 gcov_unsigned_t crc32)
355 gcov_unsigned_t tag, length;
356 unsigned t_ix;
357 int f_ix;
358 int error = 0;
359 struct gcov_fn_buffer **fn_tail = &fn_buffer;
360 struct gcov_summary_buffer **sum_tail = &sum_buffer;
362 length = gcov_read_unsigned ();
363 if (!gcov_version (gi_ptr, length, filename))
364 return -1;
366 length = gcov_read_unsigned ();
367 if (length != gi_ptr->stamp)
368 /* Read from a different compilation. Overwrite the file. */
369 return 0;
371 /* Look for program summary. */
372 for (f_ix = 0;;)
374 struct gcov_summary tmp;
376 *eof_pos_p = gcov_position ();
377 tag = gcov_read_unsigned ();
378 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
379 break;
381 f_ix--;
382 length = gcov_read_unsigned ();
383 gcov_read_summary (&tmp);
384 if ((error = gcov_is_error ()))
385 goto read_error;
386 if (*summary_pos_p)
388 /* Save all summaries after the one that will be
389 merged into below. These will need to be rewritten
390 as histogram merging may change the number of non-zero
391 histogram entries that will be emitted, and thus the
392 size of the merged summary. */
393 (*sum_tail) = (struct gcov_summary_buffer *)
394 xmalloc (sizeof(struct gcov_summary_buffer));
395 (*sum_tail)->summary = tmp;
396 (*sum_tail)->next = 0;
397 sum_tail = &((*sum_tail)->next);
398 goto next_summary;
400 if (tmp.checksum != crc32)
401 goto next_summary;
403 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
404 if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
405 goto next_summary;
406 *prg_p = tmp;
407 *summary_pos_p = *eof_pos_p;
409 next_summary:;
412 /* Merge execution counts for each function. */
413 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
414 f_ix++, tag = gcov_read_unsigned ())
416 const struct gcov_ctr_info *ci_ptr;
417 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
419 if (tag != GCOV_TAG_FUNCTION)
420 goto read_mismatch;
422 length = gcov_read_unsigned ();
423 if (!length)
424 /* This function did not appear in the other program.
425 We have nothing to merge. */
426 continue;
428 if (length != GCOV_TAG_FUNCTION_LENGTH)
429 goto read_mismatch;
431 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
433 /* This function appears in the other program. We
434 need to buffer the information in order to write
435 it back out -- we'll be inserting data before
436 this point, so cannot simply keep the data in the
437 file. */
438 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
439 if (!fn_tail)
440 goto read_mismatch;
441 continue;
444 length = gcov_read_unsigned ();
445 if (length != gfi_ptr->ident)
446 goto read_mismatch;
448 length = gcov_read_unsigned ();
449 if (length != gfi_ptr->lineno_checksum)
450 goto read_mismatch;
452 length = gcov_read_unsigned ();
453 if (length != gfi_ptr->cfg_checksum)
454 goto read_mismatch;
456 ci_ptr = gfi_ptr->ctrs;
457 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
459 gcov_merge_fn merge = gi_ptr->merge[t_ix];
461 if (!merge)
462 continue;
464 tag = gcov_read_unsigned ();
465 length = gcov_read_unsigned ();
466 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
467 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
468 goto read_mismatch;
469 (*merge) (ci_ptr->values, ci_ptr->num);
470 ci_ptr++;
472 if ((error = gcov_is_error ()))
473 goto read_error;
476 if (tag)
478 read_mismatch:;
479 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
480 filename, f_ix >= 0 ? "function" : "summary",
481 f_ix < 0 ? -1 - f_ix : f_ix);
482 return -1;
484 return 0;
486 read_error:
487 gcov_error ("profiling:%s:%s merging\n", filename,
488 error < 0 ? "Overflow": "Error");
489 return -1;
492 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
493 the case of appending to an existing file, SUMMARY_POS will be non-zero.
494 We will write the file starting from SUMMAY_POS. */
496 static void
497 write_one_data (const struct gcov_info *gi_ptr,
498 const struct gcov_summary *prg_p,
499 const gcov_position_t eof_pos,
500 const gcov_position_t summary_pos)
502 unsigned f_ix;
503 struct gcov_summary_buffer *next_sum_buffer;
505 /* Write out the data. */
506 if (!eof_pos)
508 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
509 gcov_write_unsigned (gi_ptr->stamp);
512 if (summary_pos)
513 gcov_seek (summary_pos);
515 /* Generate whole program statistics. */
516 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
518 /* Rewrite all the summaries that were after the summary we merged
519 into. This is necessary as the merged summary may have a different
520 size due to the number of non-zero histogram entries changing after
521 merging. */
523 while (sum_buffer)
525 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
526 next_sum_buffer = sum_buffer->next;
527 free (sum_buffer);
528 sum_buffer = next_sum_buffer;
531 /* Write execution counts for each function. */
532 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
534 unsigned buffered = 0;
535 const struct gcov_fn_info *gfi_ptr;
536 const struct gcov_ctr_info *ci_ptr;
537 gcov_unsigned_t length;
538 unsigned t_ix;
540 if (fn_buffer && fn_buffer->fn_ix == f_ix)
542 /* Buffered data from another program. */
543 buffered = 1;
544 gfi_ptr = &fn_buffer->info;
545 length = GCOV_TAG_FUNCTION_LENGTH;
547 else
549 gfi_ptr = gi_ptr->functions[f_ix];
550 if (gfi_ptr && gfi_ptr->key == gi_ptr)
551 length = GCOV_TAG_FUNCTION_LENGTH;
552 else
553 length = 0;
556 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
557 if (!length)
558 continue;
560 gcov_write_unsigned (gfi_ptr->ident);
561 gcov_write_unsigned (gfi_ptr->lineno_checksum);
562 gcov_write_unsigned (gfi_ptr->cfg_checksum);
564 ci_ptr = gfi_ptr->ctrs;
565 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
567 gcov_unsigned_t n_counts;
568 gcov_type *c_ptr;
570 if (!gi_ptr->merge[t_ix])
571 continue;
573 n_counts = ci_ptr->num;
574 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
575 GCOV_TAG_COUNTER_LENGTH (n_counts));
576 c_ptr = ci_ptr->values;
577 while (n_counts--)
578 gcov_write_counter (*c_ptr++);
579 ci_ptr++;
581 if (buffered)
582 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
585 gcov_write_unsigned (0);
588 /* Helper function for merging summary.
589 Return -1 on error. Return 0 on success. */
591 static int
592 merge_summary (const char *filename, int run_counted,
593 const struct gcov_info *gi_ptr, struct gcov_summary *prg,
594 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
595 struct gcov_summary *all_prg __attribute__ ((unused)))
597 struct gcov_ctr_summary *cs_prg, *cs_tprg;
598 unsigned t_ix;
599 #if !GCOV_LOCKED
600 /* summary for all instances of program. */
601 struct gcov_ctr_summary *cs_all;
602 #endif
604 /* Merge the summaries. */
605 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
607 cs_prg = &(prg->ctrs[t_ix]);
608 cs_tprg = &(this_prg->ctrs[t_ix]);
610 if (gi_ptr->merge[t_ix])
612 int first = !cs_prg->runs;
614 if (!run_counted)
615 cs_prg->runs++;
616 if (first)
617 cs_prg->num = cs_tprg->num;
618 cs_prg->sum_all += cs_tprg->sum_all;
619 if (cs_prg->run_max < cs_tprg->run_max)
620 cs_prg->run_max = cs_tprg->run_max;
621 cs_prg->sum_max += cs_tprg->run_max;
622 if (first)
623 memcpy (cs_prg->histogram, cs_tprg->histogram,
624 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
625 else
626 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
628 else if (cs_prg->runs)
630 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
631 filename);
632 return -1;
634 #if !GCOV_LOCKED
635 cs_all = &all_prg->ctrs[t_ix];
636 if (!cs_all->runs && cs_prg->runs)
638 cs_all->num = cs_prg->num;
639 cs_all->runs = cs_prg->runs;
640 cs_all->sum_all = cs_prg->sum_all;
641 cs_all->run_max = cs_prg->run_max;
642 cs_all->sum_max = cs_prg->sum_max;
644 else if (!all_prg->checksum
645 /* Don't compare the histograms, which may have slight
646 variations depending on the order they were updated
647 due to the truncating integer divides used in the
648 merge. */
649 && (cs_all->num != cs_prg->num
650 || cs_all->runs != cs_prg->runs
651 || cs_all->sum_all != cs_prg->sum_all
652 || cs_all->run_max != cs_prg->run_max
653 || cs_all->sum_max != cs_prg->sum_max))
655 gcov_error ("profiling:%s:Data file mismatch - some "
656 "data files may have been concurrently "
657 "updated without locking support\n", filename);
658 all_prg->checksum = ~0u;
660 #endif
663 prg->checksum = crc32;
665 return 0;
668 /* Dump the coverage counts for one gcov_info object. We merge with existing
669 counts when possible, to avoid growing the .da files ad infinitum. We use
670 this program's checksum to make sure we only accumulate whole program
671 statistics to the correct summary. An object file might be embedded
672 in two separate programs, and we must keep the two program
673 summaries separate. */
675 static void
676 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
677 unsigned run_counted,
678 gcov_unsigned_t crc32, struct gcov_summary *all_prg,
679 struct gcov_summary *this_prg)
681 struct gcov_summary prg; /* summary for this object over all program. */
682 int error;
683 gcov_unsigned_t tag;
684 gcov_position_t summary_pos = 0;
685 gcov_position_t eof_pos = 0;
687 fn_buffer = 0;
688 sum_buffer = 0;
690 error = gcov_exit_open_gcda_file (gi_ptr, gf);
691 if (error == -1)
692 return;
694 tag = gcov_read_unsigned ();
695 if (tag)
697 /* Merge data from file. */
698 if (tag != GCOV_DATA_MAGIC)
700 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
701 goto read_fatal;
703 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
704 &summary_pos, &eof_pos, crc32);
705 if (error == -1)
706 goto read_fatal;
709 gcov_rewrite ();
711 if (!summary_pos)
713 memset (&prg, 0, sizeof (prg));
714 summary_pos = eof_pos;
717 error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
718 crc32, all_prg);
719 if (error == -1)
720 goto read_fatal;
722 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
723 /* fall through */
725 read_fatal:;
726 while (fn_buffer)
727 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
729 if ((error = gcov_close ()))
730 gcov_error (error < 0 ?
731 "profiling:%s:Overflow writing\n" :
732 "profiling:%s:Error writing\n",
733 gf->filename);
737 /* Dump all the coverage counts for the program. It first computes program
738 summary and then traverses gcov_list list and dumps the gcov_info
739 objects one by one. */
741 #if !IN_GCOV_TOOL
742 static
743 #endif
744 void
745 gcov_do_dump (struct gcov_info *list, int run_counted)
747 struct gcov_info *gi_ptr;
748 struct gcov_filename gf;
749 gcov_unsigned_t crc32;
750 struct gcov_summary all_prg;
751 struct gcov_summary this_prg;
753 crc32 = compute_summary (list, &this_prg, &gf.max_length);
755 allocate_filename_struct (&gf);
756 #if !GCOV_LOCKED
757 memset (&all_prg, 0, sizeof (all_prg));
758 #endif
760 /* Now merge each file. */
761 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
762 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
764 free (gf.filename);
767 #if !IN_GCOV_TOOL
768 void
769 __gcov_dump_one (struct gcov_root *root)
771 if (root->dumped)
772 return;
774 gcov_do_dump (root->list, root->run_counted);
776 root->dumped = 1;
777 root->run_counted = 1;
780 /* Per-program/shared-object gcov state. */
781 struct gcov_root __gcov_root;
783 static void
784 gcov_exit (void)
786 __gcov_dump_one (&__gcov_root);
789 /* Add a new object file onto the bb chain. Invoked automatically
790 when running an object file's global ctors. */
792 void
793 __gcov_init (struct gcov_info *info)
795 if (!info->version || !info->n_functions)
796 return;
797 if (gcov_version (info, info->version, 0))
799 if (!__gcov_root.list)
800 atexit (gcov_exit);
802 info->next = __gcov_root.list;
803 __gcov_root.list = info;
805 info->version = 0;
807 #endif /* !IN_GCOV_TOOL */
808 #endif /* L_gcov */
809 #endif /* inhibit_libc */