runtime: Fix runtime/pprof test when libgo is not optimized.
[official-gcc.git] / libgcc / libgcov-driver.c
blob221ac0c00d05881248f7e2edc4a08b75233acbac
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2015 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 #if !IN_GCOV_TOOL
278 static
279 #endif
280 gcov_unsigned_t
281 compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
282 size_t *max_length)
284 struct gcov_info *gi_ptr;
285 const struct gcov_fn_info *gfi_ptr;
286 struct gcov_ctr_summary *cs_ptr;
287 const struct gcov_ctr_info *ci_ptr;
288 int f_ix;
289 unsigned t_ix;
290 gcov_unsigned_t c_num;
291 gcov_unsigned_t crc32 = 0;
293 /* Find the totals for this execution. */
294 memset (this_prg, 0, sizeof (*this_prg));
295 *max_length = 0;
296 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
298 size_t len = strlen (gi_ptr->filename);
299 if (len > *max_length)
300 *max_length = len;
302 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
303 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
305 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
307 gfi_ptr = gi_ptr->functions[f_ix];
309 if (gfi_ptr && gfi_ptr->key != gi_ptr)
310 gfi_ptr = 0;
312 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
313 crc32 = crc32_unsigned (crc32,
314 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
315 if (!gfi_ptr)
316 continue;
318 ci_ptr = gfi_ptr->ctrs;
319 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
321 if (!gi_ptr->merge[t_ix])
322 continue;
324 cs_ptr = &(this_prg->ctrs[t_ix]);
325 cs_ptr->num += ci_ptr->num;
326 crc32 = crc32_unsigned (crc32, ci_ptr->num);
328 for (c_num = 0; c_num < ci_ptr->num; c_num++)
330 cs_ptr->sum_all += ci_ptr->values[c_num];
331 if (cs_ptr->run_max < ci_ptr->values[c_num])
332 cs_ptr->run_max = ci_ptr->values[c_num];
334 ci_ptr++;
338 gcov_compute_histogram (list, this_prg);
339 return crc32;
342 /* Including system dependent components. */
343 #include "libgcov-driver-system.c"
345 /* This function merges counters in GI_PTR to an existing gcda file.
346 Return 0 on success.
347 Return -1 on error. In this case, caller will goto read_fatal. */
349 static int
350 merge_one_data (const char *filename,
351 struct gcov_info *gi_ptr,
352 struct gcov_summary *prg_p,
353 struct gcov_summary *this_prg,
354 gcov_position_t *summary_pos_p,
355 gcov_position_t *eof_pos_p,
356 gcov_unsigned_t crc32)
358 gcov_unsigned_t tag, length;
359 unsigned t_ix;
360 int f_ix;
361 int error = 0;
362 struct gcov_fn_buffer **fn_tail = &fn_buffer;
363 struct gcov_summary_buffer **sum_tail = &sum_buffer;
365 length = gcov_read_unsigned ();
366 if (!gcov_version (gi_ptr, length, filename))
367 return -1;
369 length = gcov_read_unsigned ();
370 if (length != gi_ptr->stamp)
371 /* Read from a different compilation. Overwrite the file. */
372 return 0;
374 /* Look for program summary. */
375 for (f_ix = 0;;)
377 struct gcov_summary tmp;
379 *eof_pos_p = gcov_position ();
380 tag = gcov_read_unsigned ();
381 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
382 break;
384 f_ix--;
385 length = gcov_read_unsigned ();
386 gcov_read_summary (&tmp);
387 if ((error = gcov_is_error ()))
388 goto read_error;
389 if (*summary_pos_p)
391 /* Save all summaries after the one that will be
392 merged into below. These will need to be rewritten
393 as histogram merging may change the number of non-zero
394 histogram entries that will be emitted, and thus the
395 size of the merged summary. */
396 (*sum_tail) = (struct gcov_summary_buffer *)
397 xmalloc (sizeof(struct gcov_summary_buffer));
398 (*sum_tail)->summary = tmp;
399 (*sum_tail)->next = 0;
400 sum_tail = &((*sum_tail)->next);
401 goto next_summary;
403 if (tmp.checksum != crc32)
404 goto next_summary;
406 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
407 if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
408 goto next_summary;
409 *prg_p = tmp;
410 *summary_pos_p = *eof_pos_p;
412 next_summary:;
415 /* Merge execution counts for each function. */
416 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
417 f_ix++, tag = gcov_read_unsigned ())
419 const struct gcov_ctr_info *ci_ptr;
420 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
422 if (tag != GCOV_TAG_FUNCTION)
423 goto read_mismatch;
425 length = gcov_read_unsigned ();
426 if (!length)
427 /* This function did not appear in the other program.
428 We have nothing to merge. */
429 continue;
431 if (length != GCOV_TAG_FUNCTION_LENGTH)
432 goto read_mismatch;
434 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
436 /* This function appears in the other program. We
437 need to buffer the information in order to write
438 it back out -- we'll be inserting data before
439 this point, so cannot simply keep the data in the
440 file. */
441 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
442 if (!fn_tail)
443 goto read_mismatch;
444 continue;
447 length = gcov_read_unsigned ();
448 if (length != gfi_ptr->ident)
449 goto read_mismatch;
451 length = gcov_read_unsigned ();
452 if (length != gfi_ptr->lineno_checksum)
453 goto read_mismatch;
455 length = gcov_read_unsigned ();
456 if (length != gfi_ptr->cfg_checksum)
457 goto read_mismatch;
459 ci_ptr = gfi_ptr->ctrs;
460 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
462 gcov_merge_fn merge = gi_ptr->merge[t_ix];
464 if (!merge)
465 continue;
467 tag = gcov_read_unsigned ();
468 length = gcov_read_unsigned ();
469 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
470 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
471 goto read_mismatch;
472 (*merge) (ci_ptr->values, ci_ptr->num);
473 ci_ptr++;
475 if ((error = gcov_is_error ()))
476 goto read_error;
479 if (tag)
481 read_mismatch:;
482 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
483 filename, f_ix >= 0 ? "function" : "summary",
484 f_ix < 0 ? -1 - f_ix : f_ix);
485 return -1;
487 return 0;
489 read_error:
490 gcov_error ("profiling:%s:%s merging\n", filename,
491 error < 0 ? "Overflow": "Error");
492 return -1;
495 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
496 the case of appending to an existing file, SUMMARY_POS will be non-zero.
497 We will write the file starting from SUMMAY_POS. */
499 static void
500 write_one_data (const struct gcov_info *gi_ptr,
501 const struct gcov_summary *prg_p,
502 const gcov_position_t eof_pos,
503 const gcov_position_t summary_pos)
505 unsigned f_ix;
506 struct gcov_summary_buffer *next_sum_buffer;
508 /* Write out the data. */
509 if (!eof_pos)
511 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
512 gcov_write_unsigned (gi_ptr->stamp);
515 if (summary_pos)
516 gcov_seek (summary_pos);
518 /* Generate whole program statistics. */
519 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
521 /* Rewrite all the summaries that were after the summary we merged
522 into. This is necessary as the merged summary may have a different
523 size due to the number of non-zero histogram entries changing after
524 merging. */
526 while (sum_buffer)
528 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
529 next_sum_buffer = sum_buffer->next;
530 free (sum_buffer);
531 sum_buffer = next_sum_buffer;
534 /* Write execution counts for each function. */
535 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
537 unsigned buffered = 0;
538 const struct gcov_fn_info *gfi_ptr;
539 const struct gcov_ctr_info *ci_ptr;
540 gcov_unsigned_t length;
541 unsigned t_ix;
543 if (fn_buffer && fn_buffer->fn_ix == f_ix)
545 /* Buffered data from another program. */
546 buffered = 1;
547 gfi_ptr = &fn_buffer->info;
548 length = GCOV_TAG_FUNCTION_LENGTH;
550 else
552 gfi_ptr = gi_ptr->functions[f_ix];
553 if (gfi_ptr && gfi_ptr->key == gi_ptr)
554 length = GCOV_TAG_FUNCTION_LENGTH;
555 else
556 length = 0;
559 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
560 if (!length)
561 continue;
563 gcov_write_unsigned (gfi_ptr->ident);
564 gcov_write_unsigned (gfi_ptr->lineno_checksum);
565 gcov_write_unsigned (gfi_ptr->cfg_checksum);
567 ci_ptr = gfi_ptr->ctrs;
568 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
570 gcov_unsigned_t n_counts;
571 gcov_type *c_ptr;
573 if (!gi_ptr->merge[t_ix])
574 continue;
576 n_counts = ci_ptr->num;
577 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
578 GCOV_TAG_COUNTER_LENGTH (n_counts));
579 c_ptr = ci_ptr->values;
580 while (n_counts--)
581 gcov_write_counter (*c_ptr++);
582 ci_ptr++;
584 if (buffered)
585 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
588 gcov_write_unsigned (0);
591 /* Helper function for merging summary.
592 Return -1 on error. Return 0 on success. */
594 static int
595 merge_summary (const char *filename, int run_counted,
596 const struct gcov_info *gi_ptr, struct gcov_summary *prg,
597 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
598 struct gcov_summary *all_prg __attribute__ ((unused)))
600 struct gcov_ctr_summary *cs_prg, *cs_tprg;
601 unsigned t_ix;
602 #if !GCOV_LOCKED
603 /* summary for all instances of program. */
604 struct gcov_ctr_summary *cs_all;
605 #endif
607 /* Merge the summaries. */
608 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
610 cs_prg = &(prg->ctrs[t_ix]);
611 cs_tprg = &(this_prg->ctrs[t_ix]);
613 if (gi_ptr->merge[t_ix])
615 int first = !cs_prg->runs;
617 if (!run_counted)
618 cs_prg->runs++;
619 if (first)
620 cs_prg->num = cs_tprg->num;
621 cs_prg->sum_all += cs_tprg->sum_all;
622 if (cs_prg->run_max < cs_tprg->run_max)
623 cs_prg->run_max = cs_tprg->run_max;
624 cs_prg->sum_max += cs_tprg->run_max;
625 if (first)
626 memcpy (cs_prg->histogram, cs_tprg->histogram,
627 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
628 else
629 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
631 else if (cs_prg->runs)
633 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
634 filename);
635 return -1;
637 #if !GCOV_LOCKED
638 cs_all = &all_prg->ctrs[t_ix];
639 if (!cs_all->runs && cs_prg->runs)
641 cs_all->num = cs_prg->num;
642 cs_all->runs = cs_prg->runs;
643 cs_all->sum_all = cs_prg->sum_all;
644 cs_all->run_max = cs_prg->run_max;
645 cs_all->sum_max = cs_prg->sum_max;
647 else if (!all_prg->checksum
648 /* Don't compare the histograms, which may have slight
649 variations depending on the order they were updated
650 due to the truncating integer divides used in the
651 merge. */
652 && (cs_all->num != cs_prg->num
653 || cs_all->runs != cs_prg->runs
654 || cs_all->sum_all != cs_prg->sum_all
655 || cs_all->run_max != cs_prg->run_max
656 || cs_all->sum_max != cs_prg->sum_max))
658 gcov_error ("profiling:%s:Data file mismatch - some "
659 "data files may have been concurrently "
660 "updated without locking support\n", filename);
661 all_prg->checksum = ~0u;
663 #endif
666 prg->checksum = crc32;
668 return 0;
672 /* Sort N entries in VALUE_ARRAY in descending order.
673 Each entry in VALUE_ARRAY has two values. The sorting
674 is based on the second value. */
676 GCOV_LINKAGE void
677 gcov_sort_n_vals (gcov_type *value_array, int n)
679 int j, k;
681 for (j = 2; j < n; j += 2)
683 gcov_type cur_ent[2];
685 cur_ent[0] = value_array[j];
686 cur_ent[1] = value_array[j + 1];
687 k = j - 2;
688 while (k >= 0 && value_array[k + 1] < cur_ent[1])
690 value_array[k + 2] = value_array[k];
691 value_array[k + 3] = value_array[k+1];
692 k -= 2;
694 value_array[k + 2] = cur_ent[0];
695 value_array[k + 3] = cur_ent[1];
699 /* Sort the profile counters for all indirect call sites. Counters
700 for each call site are allocated in array COUNTERS. */
702 static void
703 gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
705 int i;
706 gcov_type *values;
707 int n = counters->num;
709 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
710 values = counters->values;
712 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
714 gcov_type *value_array = &values[i + 1];
715 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
719 /* Sort topn indirect_call profile counters in GI_PTR. */
721 static void
722 gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
724 unsigned int i;
725 int f_ix;
726 const struct gcov_fn_info *gfi_ptr;
727 const struct gcov_ctr_info *ci_ptr;
729 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
730 return;
732 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
734 gfi_ptr = gi_ptr->functions[f_ix];
735 ci_ptr = gfi_ptr->ctrs;
736 for (i = 0; i < GCOV_COUNTERS; i++)
738 if (!gi_ptr->merge[i])
739 continue;
740 if (i == GCOV_COUNTER_ICALL_TOPNV)
742 gcov_sort_icall_topn_counter (ci_ptr);
743 break;
745 ci_ptr++;
750 /* Dump the coverage counts for one gcov_info object. We merge with existing
751 counts when possible, to avoid growing the .da files ad infinitum. We use
752 this program's checksum to make sure we only accumulate whole program
753 statistics to the correct summary. An object file might be embedded
754 in two separate programs, and we must keep the two program
755 summaries separate. */
757 static void
758 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
759 unsigned run_counted,
760 gcov_unsigned_t crc32, struct gcov_summary *all_prg,
761 struct gcov_summary *this_prg)
763 struct gcov_summary prg; /* summary for this object over all program. */
764 int error;
765 gcov_unsigned_t tag;
766 gcov_position_t summary_pos = 0;
767 gcov_position_t eof_pos = 0;
769 fn_buffer = 0;
770 sum_buffer = 0;
772 gcov_sort_topn_counter_arrays (gi_ptr);
774 error = gcov_exit_open_gcda_file (gi_ptr, gf);
775 if (error == -1)
776 return;
778 tag = gcov_read_unsigned ();
779 if (tag)
781 /* Merge data from file. */
782 if (tag != GCOV_DATA_MAGIC)
784 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
785 goto read_fatal;
787 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
788 &summary_pos, &eof_pos, crc32);
789 if (error == -1)
790 goto read_fatal;
793 gcov_rewrite ();
795 if (!summary_pos)
797 memset (&prg, 0, sizeof (prg));
798 summary_pos = eof_pos;
801 error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
802 crc32, all_prg);
803 if (error == -1)
804 goto read_fatal;
806 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
807 /* fall through */
809 read_fatal:;
810 while (fn_buffer)
811 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
813 if ((error = gcov_close ()))
814 gcov_error (error < 0 ?
815 "profiling:%s:Overflow writing\n" :
816 "profiling:%s:Error writing\n",
817 gf->filename);
821 /* Dump all the coverage counts for the program. It first computes program
822 summary and then traverses gcov_list list and dumps the gcov_info
823 objects one by one. */
825 #if !IN_GCOV_TOOL
826 static
827 #endif
828 void
829 gcov_do_dump (struct gcov_info *list, int run_counted)
831 struct gcov_info *gi_ptr;
832 struct gcov_filename gf;
833 gcov_unsigned_t crc32;
834 struct gcov_summary all_prg;
835 struct gcov_summary this_prg;
837 crc32 = compute_summary (list, &this_prg, &gf.max_length);
839 allocate_filename_struct (&gf);
840 #if !GCOV_LOCKED
841 memset (&all_prg, 0, sizeof (all_prg));
842 #endif
844 /* Now merge each file. */
845 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
846 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
848 free (gf.filename);
851 #if !IN_GCOV_TOOL
852 void
853 __gcov_dump_one (struct gcov_root *root)
855 if (root->dumped)
856 return;
858 gcov_do_dump (root->list, root->run_counted);
860 root->dumped = 1;
861 root->run_counted = 1;
864 /* Per-dynamic-object gcov state. */
865 struct gcov_root __gcov_root;
867 /* Exactly one of these will be live in the process image. */
868 struct gcov_master __gcov_master =
869 {GCOV_VERSION, 0};
871 static void
872 gcov_exit (void)
874 __gcov_dump_one (&__gcov_root);
875 if (__gcov_root.next)
876 __gcov_root.next->prev = __gcov_root.prev;
877 if (__gcov_root.prev)
878 __gcov_root.prev->next = __gcov_root.next;
879 else
880 __gcov_master.root = __gcov_root.next;
883 /* Add a new object file onto the bb chain. Invoked automatically
884 when running an object file's global ctors. */
886 void
887 __gcov_init (struct gcov_info *info)
889 if (!info->version || !info->n_functions)
890 return;
891 if (gcov_version (info, info->version, 0))
893 if (!__gcov_root.list)
895 /* Add to master list and at exit function. */
896 if (gcov_version (NULL, __gcov_master.version, "<master>"))
898 __gcov_root.next = __gcov_master.root;
899 if (__gcov_master.root)
900 __gcov_master.root->prev = &__gcov_root;
901 __gcov_master.root = &__gcov_root;
903 atexit (gcov_exit);
906 info->next = __gcov_root.list;
907 __gcov_root.list = info;
910 #endif /* !IN_GCOV_TOOL */
911 #endif /* L_gcov */
912 #endif /* inhibit_libc */