PR c++/86342 - -Wdeprecated-copy and system headers.
[official-gcc.git] / libgcc / libgcov-driver.c
blob1f2c4a74298cb7255faed62347a1835165553f80
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2018 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 outputting errors. */
47 static int gcov_error (const char *, ...);
49 #if !IN_GCOV_TOOL
50 static void gcov_error_exit (void);
51 #endif
53 #include "gcov-io.c"
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 /* A struct that bundles all the related information about the
70 gcda filename. */
72 struct gcov_filename
74 char *filename; /* filename buffer */
75 int strip; /* leading chars to strip from filename */
76 char *prefix; /* prefix string */
79 static struct gcov_fn_buffer *
80 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
81 unsigned limit)
83 struct gcov_fn_buffer *next;
84 unsigned ix, n_ctr = 0;
86 if (!buffer)
87 return 0;
88 next = buffer->next;
90 for (ix = 0; ix != limit; ix++)
91 if (gi_ptr->merge[ix])
92 free (buffer->info.ctrs[n_ctr++].values);
93 free (buffer);
94 return next;
97 static struct gcov_fn_buffer **
98 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
99 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
101 unsigned n_ctrs = 0, ix = 0;
102 struct gcov_fn_buffer *fn_buffer;
103 unsigned len;
105 for (ix = GCOV_COUNTERS; ix--;)
106 if (gi_ptr->merge[ix])
107 n_ctrs++;
109 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
110 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
112 if (!fn_buffer)
113 goto fail;
115 fn_buffer->next = 0;
116 fn_buffer->fn_ix = fn_ix;
117 fn_buffer->info.ident = gcov_read_unsigned ();
118 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
119 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
121 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
123 gcov_unsigned_t length;
124 gcov_type *values;
126 if (!gi_ptr->merge[ix])
127 continue;
129 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
131 len = 0;
132 goto fail;
135 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
136 len = length * sizeof (gcov_type);
137 values = (gcov_type *) xmalloc (len);
138 if (!values)
139 goto fail;
141 fn_buffer->info.ctrs[n_ctrs].num = length;
142 fn_buffer->info.ctrs[n_ctrs].values = values;
144 while (length--)
145 *values++ = gcov_read_counter ();
146 n_ctrs++;
149 *end_ptr = fn_buffer;
150 return &fn_buffer->next;
152 fail:
153 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
154 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
156 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
159 /* Add an unsigned value to the current crc */
161 static gcov_unsigned_t
162 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
164 unsigned ix;
166 for (ix = 32; ix--; value <<= 1)
168 unsigned feedback;
170 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
171 crc32 <<= 1;
172 crc32 ^= feedback;
175 return crc32;
178 /* Check if VERSION of the info block PTR matches libgcov one.
179 Return 1 on success, or zero in case of versions mismatch.
180 If FILENAME is not NULL, its value used for reporting purposes
181 instead of value from the info block. */
183 static int
184 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
185 const char *filename)
187 if (version != GCOV_VERSION)
189 char v[4], e[4];
191 GCOV_UNSIGNED2STRING (v, version);
192 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
194 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
195 filename? filename : ptr->filename, e, v);
196 return 0;
198 return 1;
201 /* Insert counter VALUE into HISTOGRAM. */
203 static void
204 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
206 unsigned i;
208 i = gcov_histo_index(value);
209 histogram[i].num_counters++;
210 histogram[i].cum_value += value;
211 if (value < histogram[i].min_value)
212 histogram[i].min_value = value;
215 /* Computes a histogram of the arc counters to place in the summary SUM. */
217 static void
218 gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
220 struct gcov_info *gi_ptr;
221 const struct gcov_fn_info *gfi_ptr;
222 const struct gcov_ctr_info *ci_ptr;
223 unsigned f_ix, ix;
224 int h_ix;
226 /* First check if there are any counts recorded for this counter. */
227 if (!sum->num)
228 return;
230 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
232 sum->histogram[h_ix].num_counters = 0;
233 sum->histogram[h_ix].min_value = sum->run_max;
234 sum->histogram[h_ix].cum_value = 0;
237 /* Walk through all the per-object structures and record each of
238 the count values in histogram. */
239 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
241 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
243 gfi_ptr = gi_ptr->functions[f_ix];
245 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
246 continue;
248 ci_ptr = &gfi_ptr->ctrs[0];
249 for (ix = 0; ix < ci_ptr->num; ix++)
250 gcov_histogram_insert (sum->histogram, ci_ptr->values[ix]);
255 /* buffer for the fn_data from another program. */
256 static struct gcov_fn_buffer *fn_buffer;
257 /* buffer for summary from other programs to be written out. */
258 static struct gcov_summary_buffer *sum_buffer;
260 /* This function computes the program level summary and the histo-gram.
261 It computes and returns CRC32 and stored summary in THIS_PRG. */
263 #if !IN_GCOV_TOOL
264 static
265 #endif
266 gcov_unsigned_t
267 compute_summary (struct gcov_info *list, struct gcov_summary *this_prg)
269 struct gcov_info *gi_ptr;
270 const struct gcov_fn_info *gfi_ptr;
271 const struct gcov_ctr_info *ci_ptr;
272 int f_ix;
273 gcov_unsigned_t c_num;
274 gcov_unsigned_t crc32 = 0;
276 /* Find the totals for this execution. */
277 memset (this_prg, 0, sizeof (*this_prg));
278 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
280 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
281 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
283 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
285 gfi_ptr = gi_ptr->functions[f_ix];
287 if (gfi_ptr && gfi_ptr->key != gi_ptr)
288 gfi_ptr = 0;
290 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
291 crc32 = crc32_unsigned (crc32,
292 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
293 if (!gfi_ptr)
294 continue;
296 ci_ptr = gfi_ptr->ctrs;
297 this_prg->num += ci_ptr->num;
298 crc32 = crc32_unsigned (crc32, ci_ptr->num);
300 for (c_num = 0; c_num < ci_ptr->num; c_num++)
302 this_prg->sum_all += ci_ptr->values[c_num];
303 if (this_prg->run_max < ci_ptr->values[c_num])
304 this_prg->run_max = ci_ptr->values[c_num];
306 ci_ptr++;
309 gcov_compute_histogram (list, this_prg);
310 return crc32;
313 /* Including system dependent components. */
314 #include "libgcov-driver-system.c"
316 /* This function merges counters in GI_PTR to an existing gcda file.
317 Return 0 on success.
318 Return -1 on error. In this case, caller will goto read_fatal. */
320 static int
321 merge_one_data (const char *filename,
322 struct gcov_info *gi_ptr,
323 struct gcov_summary *prg_p,
324 struct gcov_summary *this_prg,
325 gcov_position_t *summary_pos_p,
326 gcov_position_t *eof_pos_p,
327 gcov_unsigned_t crc32)
329 gcov_unsigned_t tag, length;
330 unsigned t_ix;
331 int f_ix;
332 int error = 0;
333 struct gcov_fn_buffer **fn_tail = &fn_buffer;
334 struct gcov_summary_buffer **sum_tail = &sum_buffer;
336 length = gcov_read_unsigned ();
337 if (!gcov_version (gi_ptr, length, filename))
338 return -1;
340 length = gcov_read_unsigned ();
341 if (length != gi_ptr->stamp)
343 /* Read from a different compilation. Overwrite the file. */
344 gcov_error ("profiling:%s:overwriting an existing profile data "
345 "with a different timestamp\n", filename);
346 return 0;
349 /* Look for program summary. */
350 for (f_ix = 0;;)
352 struct gcov_summary tmp;
354 *eof_pos_p = gcov_position ();
355 tag = gcov_read_unsigned ();
356 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
357 break;
359 f_ix--;
360 length = gcov_read_unsigned ();
361 gcov_read_summary (&tmp);
362 if ((error = gcov_is_error ()))
363 goto read_error;
364 if (*summary_pos_p)
366 /* Save all summaries after the one that will be
367 merged into below. These will need to be rewritten
368 as histogram merging may change the number of non-zero
369 histogram entries that will be emitted, and thus the
370 size of the merged summary. */
371 (*sum_tail) = (struct gcov_summary_buffer *)
372 xmalloc (sizeof(struct gcov_summary_buffer));
373 (*sum_tail)->summary = tmp;
374 (*sum_tail)->next = 0;
375 sum_tail = &((*sum_tail)->next);
376 goto next_summary;
378 if (tmp.checksum != crc32)
379 goto next_summary;
381 if (tmp.num != this_prg->num)
382 goto next_summary;
383 *prg_p = tmp;
384 *summary_pos_p = *eof_pos_p;
386 next_summary:;
389 /* Merge execution counts for each function. */
390 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
391 f_ix++, tag = gcov_read_unsigned ())
393 const struct gcov_ctr_info *ci_ptr;
394 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
396 if (tag != GCOV_TAG_FUNCTION)
397 goto read_mismatch;
399 length = gcov_read_unsigned ();
400 if (!length)
401 /* This function did not appear in the other program.
402 We have nothing to merge. */
403 continue;
405 if (length != GCOV_TAG_FUNCTION_LENGTH)
406 goto read_mismatch;
408 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
410 /* This function appears in the other program. We
411 need to buffer the information in order to write
412 it back out -- we'll be inserting data before
413 this point, so cannot simply keep the data in the
414 file. */
415 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
416 if (!fn_tail)
417 goto read_mismatch;
418 continue;
421 length = gcov_read_unsigned ();
422 if (length != gfi_ptr->ident)
423 goto read_mismatch;
425 length = gcov_read_unsigned ();
426 if (length != gfi_ptr->lineno_checksum)
427 goto read_mismatch;
429 length = gcov_read_unsigned ();
430 if (length != gfi_ptr->cfg_checksum)
431 goto read_mismatch;
433 ci_ptr = gfi_ptr->ctrs;
434 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
436 gcov_merge_fn merge = gi_ptr->merge[t_ix];
438 if (!merge)
439 continue;
441 tag = gcov_read_unsigned ();
442 length = gcov_read_unsigned ();
443 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
444 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
445 goto read_mismatch;
446 (*merge) (ci_ptr->values, ci_ptr->num);
447 ci_ptr++;
449 if ((error = gcov_is_error ()))
450 goto read_error;
453 if (tag)
455 read_mismatch:;
456 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
457 filename, f_ix >= 0 ? "function" : "summary",
458 f_ix < 0 ? -1 - f_ix : f_ix);
459 return -1;
461 return 0;
463 read_error:
464 gcov_error ("profiling:%s:%s merging\n", filename,
465 error < 0 ? "Overflow": "Error");
466 return -1;
469 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
470 the case of appending to an existing file, SUMMARY_POS will be non-zero.
471 We will write the file starting from SUMMAY_POS. */
473 static void
474 write_one_data (const struct gcov_info *gi_ptr,
475 const struct gcov_summary *prg_p,
476 const gcov_position_t eof_pos,
477 const gcov_position_t summary_pos)
479 unsigned f_ix;
480 struct gcov_summary_buffer *next_sum_buffer;
482 /* Write out the data. */
483 if (!eof_pos)
485 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
486 gcov_write_unsigned (gi_ptr->stamp);
489 if (summary_pos)
490 gcov_seek (summary_pos);
492 /* Generate whole program statistics. */
493 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
495 /* Rewrite all the summaries that were after the summary we merged
496 into. This is necessary as the merged summary may have a different
497 size due to the number of non-zero histogram entries changing after
498 merging. */
500 while (sum_buffer)
502 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
503 next_sum_buffer = sum_buffer->next;
504 free (sum_buffer);
505 sum_buffer = next_sum_buffer;
508 /* Write execution counts for each function. */
509 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
511 unsigned buffered = 0;
512 const struct gcov_fn_info *gfi_ptr;
513 const struct gcov_ctr_info *ci_ptr;
514 gcov_unsigned_t length;
515 unsigned t_ix;
517 if (fn_buffer && fn_buffer->fn_ix == f_ix)
519 /* Buffered data from another program. */
520 buffered = 1;
521 gfi_ptr = &fn_buffer->info;
522 length = GCOV_TAG_FUNCTION_LENGTH;
524 else
526 gfi_ptr = gi_ptr->functions[f_ix];
527 if (gfi_ptr && gfi_ptr->key == gi_ptr)
528 length = GCOV_TAG_FUNCTION_LENGTH;
529 else
530 length = 0;
533 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
534 if (!length)
535 continue;
537 gcov_write_unsigned (gfi_ptr->ident);
538 gcov_write_unsigned (gfi_ptr->lineno_checksum);
539 gcov_write_unsigned (gfi_ptr->cfg_checksum);
541 ci_ptr = gfi_ptr->ctrs;
542 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
544 gcov_unsigned_t n_counts;
545 gcov_type *c_ptr;
547 if (!gi_ptr->merge[t_ix])
548 continue;
550 n_counts = ci_ptr->num;
551 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
552 GCOV_TAG_COUNTER_LENGTH (n_counts));
553 c_ptr = ci_ptr->values;
554 while (n_counts--)
555 gcov_write_counter (*c_ptr++);
556 ci_ptr++;
558 if (buffered)
559 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
562 gcov_write_unsigned (0);
565 /* Helper function for merging summary.
566 Return -1 on error. Return 0 on success. */
568 static int
569 merge_summary (const char *filename __attribute__ ((unused)), int run_counted,
570 struct gcov_summary *prg,
571 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
572 struct gcov_summary *all_prg __attribute__ ((unused)))
574 #if !GCOV_LOCKED
575 /* summary for all instances of program. */
576 struct gcov_summary *all;
577 #endif
579 /* Merge the summary. */
580 int first = !prg->runs;
582 if (!run_counted)
583 prg->runs++;
584 if (first)
585 prg->num = this_prg->num;
586 prg->sum_all += this_prg->sum_all;
587 if (prg->run_max < this_prg->run_max)
588 prg->run_max = this_prg->run_max;
589 prg->sum_max += this_prg->run_max;
590 if (first)
591 memcpy (prg->histogram, this_prg->histogram,
592 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
593 else
594 gcov_histogram_merge (prg->histogram, this_prg->histogram);
595 #if !GCOV_LOCKED
596 all = all_prg;
597 if (!all->runs && prg->runs)
599 all->num = prg->num;
600 all->runs = prg->runs;
601 all->sum_all = prg->sum_all;
602 all->run_max = prg->run_max;
603 all->sum_max = prg->sum_max;
605 else if (!all_prg->checksum
606 /* Don't compare the histograms, which may have slight
607 variations depending on the order they were updated
608 due to the truncating integer divides used in the
609 merge. */
610 && (all->num != prg->num
611 || all->runs != prg->runs
612 || all->sum_all != prg->sum_all
613 || all->run_max != prg->run_max
614 || all->sum_max != prg->sum_max))
616 gcov_error ("profiling:%s:Data file mismatch - some "
617 "data files may have been concurrently "
618 "updated without locking support\n", filename);
619 all_prg->checksum = ~0u;
621 #endif
623 prg->checksum = crc32;
625 return 0;
629 /* Sort N entries in VALUE_ARRAY in descending order.
630 Each entry in VALUE_ARRAY has two values. The sorting
631 is based on the second value. */
633 GCOV_LINKAGE void
634 gcov_sort_n_vals (gcov_type *value_array, int n)
636 int j, k;
638 for (j = 2; j < n; j += 2)
640 gcov_type cur_ent[2];
642 cur_ent[0] = value_array[j];
643 cur_ent[1] = value_array[j + 1];
644 k = j - 2;
645 while (k >= 0 && value_array[k + 1] < cur_ent[1])
647 value_array[k + 2] = value_array[k];
648 value_array[k + 3] = value_array[k+1];
649 k -= 2;
651 value_array[k + 2] = cur_ent[0];
652 value_array[k + 3] = cur_ent[1];
656 /* Sort the profile counters for all indirect call sites. Counters
657 for each call site are allocated in array COUNTERS. */
659 static void
660 gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
662 int i;
663 gcov_type *values;
664 int n = counters->num;
666 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
667 values = counters->values;
669 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
671 gcov_type *value_array = &values[i + 1];
672 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
676 /* Sort topn indirect_call profile counters in GI_PTR. */
678 static void
679 gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
681 unsigned int i;
682 int f_ix;
683 const struct gcov_fn_info *gfi_ptr;
684 const struct gcov_ctr_info *ci_ptr;
686 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
687 return;
689 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
691 gfi_ptr = gi_ptr->functions[f_ix];
692 ci_ptr = gfi_ptr->ctrs;
693 for (i = 0; i < GCOV_COUNTERS; i++)
695 if (!gi_ptr->merge[i])
696 continue;
697 if (i == GCOV_COUNTER_ICALL_TOPNV)
699 gcov_sort_icall_topn_counter (ci_ptr);
700 break;
702 ci_ptr++;
707 /* Dump the coverage counts for one gcov_info object. We merge with existing
708 counts when possible, to avoid growing the .da files ad infinitum. We use
709 this program's checksum to make sure we only accumulate whole program
710 statistics to the correct summary. An object file might be embedded
711 in two separate programs, and we must keep the two program
712 summaries separate. */
714 static void
715 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
716 unsigned run_counted,
717 gcov_unsigned_t crc32, struct gcov_summary *all_prg,
718 struct gcov_summary *this_prg)
720 struct gcov_summary prg; /* summary for this object over all program. */
721 int error;
722 gcov_unsigned_t tag;
723 gcov_position_t summary_pos = 0;
724 gcov_position_t eof_pos = 0;
726 fn_buffer = 0;
727 sum_buffer = 0;
729 gcov_sort_topn_counter_arrays (gi_ptr);
731 error = gcov_exit_open_gcda_file (gi_ptr, gf);
732 if (error == -1)
733 return;
735 tag = gcov_read_unsigned ();
736 if (tag)
738 /* Merge data from file. */
739 if (tag != GCOV_DATA_MAGIC)
741 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
742 goto read_fatal;
744 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
745 &summary_pos, &eof_pos, crc32);
746 if (error == -1)
747 goto read_fatal;
750 gcov_rewrite ();
752 if (!summary_pos)
754 memset (&prg, 0, sizeof (prg));
755 summary_pos = eof_pos;
758 error = merge_summary (gf->filename, run_counted, &prg, this_prg,
759 crc32, all_prg);
760 if (error == -1)
761 goto read_fatal;
763 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
764 /* fall through */
766 read_fatal:;
767 while (fn_buffer)
768 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
770 if ((error = gcov_close ()))
771 gcov_error (error < 0 ?
772 "profiling:%s:Overflow writing\n" :
773 "profiling:%s:Error writing\n",
774 gf->filename);
778 /* Dump all the coverage counts for the program. It first computes program
779 summary and then traverses gcov_list list and dumps the gcov_info
780 objects one by one. */
782 #if !IN_GCOV_TOOL
783 static
784 #endif
785 void
786 gcov_do_dump (struct gcov_info *list, int run_counted)
788 struct gcov_info *gi_ptr;
789 struct gcov_filename gf;
790 gcov_unsigned_t crc32;
791 struct gcov_summary all_prg;
792 struct gcov_summary this_prg;
794 crc32 = compute_summary (list, &this_prg);
796 allocate_filename_struct (&gf);
797 #if !GCOV_LOCKED
798 memset (&all_prg, 0, sizeof (all_prg));
799 #endif
801 /* Now merge each file. */
802 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
804 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
805 free (gf.filename);
808 free (gf.prefix);
811 #if IN_GCOV_TOOL
812 const char *
813 __attribute__ ((unused))
814 gcov_get_filename (struct gcov_info *list)
816 return list->filename;
818 #endif
820 #if !IN_GCOV_TOOL
821 void
822 __gcov_dump_one (struct gcov_root *root)
824 if (root->dumped)
825 return;
827 gcov_do_dump (root->list, root->run_counted);
829 root->dumped = 1;
830 root->run_counted = 1;
833 /* Per-dynamic-object gcov state. */
834 struct gcov_root __gcov_root;
836 /* Exactly one of these will be live in the process image. */
837 struct gcov_master __gcov_master =
838 {GCOV_VERSION, 0};
840 void
841 __gcov_exit (void)
843 __gcov_dump_one (&__gcov_root);
844 if (__gcov_root.next)
845 __gcov_root.next->prev = __gcov_root.prev;
846 if (__gcov_root.prev)
847 __gcov_root.prev->next = __gcov_root.next;
848 else
849 __gcov_master.root = __gcov_root.next;
851 gcov_error_exit ();
854 /* Add a new object file onto the bb chain. Invoked automatically
855 when running an object file's global ctors. */
857 void
858 __gcov_init (struct gcov_info *info)
860 if (!info->version || !info->n_functions)
861 return;
862 if (gcov_version (info, info->version, 0))
864 if (!__gcov_root.list)
866 /* Add to master list and at exit function. */
867 if (gcov_version (NULL, __gcov_master.version, "<master>"))
869 __gcov_root.next = __gcov_master.root;
870 if (__gcov_master.root)
871 __gcov_master.root->prev = &__gcov_root;
872 __gcov_master.root = &__gcov_root;
876 info->next = __gcov_root.list;
877 __gcov_root.list = info;
880 #endif /* !IN_GCOV_TOOL */
881 #endif /* L_gcov */
882 #endif /* inhibit_libc */