2018-04-14 Thomas Koenig <tkoenig@gcc.gnu.org>
[official-gcc.git] / libgcc / libgcov-driver.c
blobb4f195b825928d239fc7cca1110046ba36d73856
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 size_t max_length; /* maximum filename length */
76 int strip; /* leading chars to strip from filename */
77 size_t prefix; /* chars to prepend to filename */
80 static struct gcov_fn_buffer *
81 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
82 unsigned limit)
84 struct gcov_fn_buffer *next;
85 unsigned ix, n_ctr = 0;
87 if (!buffer)
88 return 0;
89 next = buffer->next;
91 for (ix = 0; ix != limit; ix++)
92 if (gi_ptr->merge[ix])
93 free (buffer->info.ctrs[n_ctr++].values);
94 free (buffer);
95 return next;
98 static struct gcov_fn_buffer **
99 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
100 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
102 unsigned n_ctrs = 0, ix = 0;
103 struct gcov_fn_buffer *fn_buffer;
104 unsigned len;
106 for (ix = GCOV_COUNTERS; ix--;)
107 if (gi_ptr->merge[ix])
108 n_ctrs++;
110 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
111 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
113 if (!fn_buffer)
114 goto fail;
116 fn_buffer->next = 0;
117 fn_buffer->fn_ix = fn_ix;
118 fn_buffer->info.ident = gcov_read_unsigned ();
119 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
120 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
122 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
124 gcov_unsigned_t length;
125 gcov_type *values;
127 if (!gi_ptr->merge[ix])
128 continue;
130 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
132 len = 0;
133 goto fail;
136 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
137 len = length * sizeof (gcov_type);
138 values = (gcov_type *) xmalloc (len);
139 if (!values)
140 goto fail;
142 fn_buffer->info.ctrs[n_ctrs].num = length;
143 fn_buffer->info.ctrs[n_ctrs].values = values;
145 while (length--)
146 *values++ = gcov_read_counter ();
147 n_ctrs++;
150 *end_ptr = fn_buffer;
151 return &fn_buffer->next;
153 fail:
154 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
155 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
157 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
160 /* Add an unsigned value to the current crc */
162 static gcov_unsigned_t
163 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
165 unsigned ix;
167 for (ix = 32; ix--; value <<= 1)
169 unsigned feedback;
171 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
172 crc32 <<= 1;
173 crc32 ^= feedback;
176 return crc32;
179 /* Check if VERSION of the info block PTR matches libgcov one.
180 Return 1 on success, or zero in case of versions mismatch.
181 If FILENAME is not NULL, its value used for reporting purposes
182 instead of value from the info block. */
184 static int
185 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
186 const char *filename)
188 if (version != GCOV_VERSION)
190 char v[4], e[4];
192 GCOV_UNSIGNED2STRING (v, version);
193 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
195 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
196 filename? filename : ptr->filename, e, v);
197 return 0;
199 return 1;
202 /* Insert counter VALUE into HISTOGRAM. */
204 static void
205 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
207 unsigned i;
209 i = gcov_histo_index(value);
210 histogram[i].num_counters++;
211 histogram[i].cum_value += value;
212 if (value < histogram[i].min_value)
213 histogram[i].min_value = value;
216 /* Computes a histogram of the arc counters to place in the summary SUM. */
218 static void
219 gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
221 struct gcov_info *gi_ptr;
222 const struct gcov_fn_info *gfi_ptr;
223 const struct gcov_ctr_info *ci_ptr;
224 struct gcov_ctr_summary *cs_ptr;
225 unsigned t_ix, f_ix, ctr_info_ix, ix;
226 int h_ix;
228 /* This currently only applies to arc counters. */
229 t_ix = GCOV_COUNTER_ARCS;
231 /* First check if there are any counts recorded for this counter. */
232 cs_ptr = &(sum->ctrs[t_ix]);
233 if (!cs_ptr->num)
234 return;
236 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
238 cs_ptr->histogram[h_ix].num_counters = 0;
239 cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
240 cs_ptr->histogram[h_ix].cum_value = 0;
243 /* Walk through all the per-object structures and record each of
244 the count values in histogram. */
245 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
247 if (!gi_ptr->merge[t_ix])
248 continue;
250 /* Find the appropriate index into the gcov_ctr_info array
251 for the counter we are currently working on based on the
252 existence of the merge function pointer for this object. */
253 for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
255 if (gi_ptr->merge[ix])
256 ctr_info_ix++;
258 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
260 gfi_ptr = gi_ptr->functions[f_ix];
262 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
263 continue;
265 ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
266 for (ix = 0; ix < ci_ptr->num; ix++)
267 gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
272 /* buffer for the fn_data from another program. */
273 static struct gcov_fn_buffer *fn_buffer;
274 /* buffer for summary from other programs to be written out. */
275 static struct gcov_summary_buffer *sum_buffer;
277 /* This function computes the program level summary and the histo-gram.
278 It computes and returns CRC32 and stored summary in THIS_PRG.
279 Also determines the longest filename length of the info files. */
281 #if !IN_GCOV_TOOL
282 static
283 #endif
284 gcov_unsigned_t
285 compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
286 size_t *max_length)
288 struct gcov_info *gi_ptr;
289 const struct gcov_fn_info *gfi_ptr;
290 struct gcov_ctr_summary *cs_ptr;
291 const struct gcov_ctr_info *ci_ptr;
292 int f_ix;
293 unsigned t_ix;
294 gcov_unsigned_t c_num;
295 gcov_unsigned_t crc32 = 0;
297 /* Find the totals for this execution. */
298 memset (this_prg, 0, sizeof (*this_prg));
299 *max_length = 0;
300 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
302 size_t len = strlen (gi_ptr->filename);
303 if (len > *max_length)
304 *max_length = len;
306 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
307 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
309 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
311 gfi_ptr = gi_ptr->functions[f_ix];
313 if (gfi_ptr && gfi_ptr->key != gi_ptr)
314 gfi_ptr = 0;
316 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
317 crc32 = crc32_unsigned (crc32,
318 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
319 if (!gfi_ptr)
320 continue;
322 ci_ptr = gfi_ptr->ctrs;
323 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
325 if (!gi_ptr->merge[t_ix])
326 continue;
328 cs_ptr = &(this_prg->ctrs[t_ix]);
329 cs_ptr->num += ci_ptr->num;
330 crc32 = crc32_unsigned (crc32, ci_ptr->num);
332 for (c_num = 0; c_num < ci_ptr->num; c_num++)
334 cs_ptr->sum_all += ci_ptr->values[c_num];
335 if (cs_ptr->run_max < ci_ptr->values[c_num])
336 cs_ptr->run_max = ci_ptr->values[c_num];
338 ci_ptr++;
342 gcov_compute_histogram (list, this_prg);
343 return crc32;
346 /* Including system dependent components. */
347 #include "libgcov-driver-system.c"
349 /* This function merges counters in GI_PTR to an existing gcda file.
350 Return 0 on success.
351 Return -1 on error. In this case, caller will goto read_fatal. */
353 static int
354 merge_one_data (const char *filename,
355 struct gcov_info *gi_ptr,
356 struct gcov_summary *prg_p,
357 struct gcov_summary *this_prg,
358 gcov_position_t *summary_pos_p,
359 gcov_position_t *eof_pos_p,
360 gcov_unsigned_t crc32)
362 gcov_unsigned_t tag, length;
363 unsigned t_ix;
364 int f_ix;
365 int error = 0;
366 struct gcov_fn_buffer **fn_tail = &fn_buffer;
367 struct gcov_summary_buffer **sum_tail = &sum_buffer;
369 length = gcov_read_unsigned ();
370 if (!gcov_version (gi_ptr, length, filename))
371 return -1;
373 length = gcov_read_unsigned ();
374 if (length != gi_ptr->stamp)
375 /* Read from a different compilation. Overwrite the file. */
376 return 0;
378 /* Look for program summary. */
379 for (f_ix = 0;;)
381 struct gcov_summary tmp;
383 *eof_pos_p = gcov_position ();
384 tag = gcov_read_unsigned ();
385 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
386 break;
388 f_ix--;
389 length = gcov_read_unsigned ();
390 gcov_read_summary (&tmp);
391 if ((error = gcov_is_error ()))
392 goto read_error;
393 if (*summary_pos_p)
395 /* Save all summaries after the one that will be
396 merged into below. These will need to be rewritten
397 as histogram merging may change the number of non-zero
398 histogram entries that will be emitted, and thus the
399 size of the merged summary. */
400 (*sum_tail) = (struct gcov_summary_buffer *)
401 xmalloc (sizeof(struct gcov_summary_buffer));
402 (*sum_tail)->summary = tmp;
403 (*sum_tail)->next = 0;
404 sum_tail = &((*sum_tail)->next);
405 goto next_summary;
407 if (tmp.checksum != crc32)
408 goto next_summary;
410 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
411 if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
412 goto next_summary;
413 *prg_p = tmp;
414 *summary_pos_p = *eof_pos_p;
416 next_summary:;
419 /* Merge execution counts for each function. */
420 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
421 f_ix++, tag = gcov_read_unsigned ())
423 const struct gcov_ctr_info *ci_ptr;
424 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
426 if (tag != GCOV_TAG_FUNCTION)
427 goto read_mismatch;
429 length = gcov_read_unsigned ();
430 if (!length)
431 /* This function did not appear in the other program.
432 We have nothing to merge. */
433 continue;
435 if (length != GCOV_TAG_FUNCTION_LENGTH)
436 goto read_mismatch;
438 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
440 /* This function appears in the other program. We
441 need to buffer the information in order to write
442 it back out -- we'll be inserting data before
443 this point, so cannot simply keep the data in the
444 file. */
445 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
446 if (!fn_tail)
447 goto read_mismatch;
448 continue;
451 length = gcov_read_unsigned ();
452 if (length != gfi_ptr->ident)
453 goto read_mismatch;
455 length = gcov_read_unsigned ();
456 if (length != gfi_ptr->lineno_checksum)
457 goto read_mismatch;
459 length = gcov_read_unsigned ();
460 if (length != gfi_ptr->cfg_checksum)
461 goto read_mismatch;
463 ci_ptr = gfi_ptr->ctrs;
464 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
466 gcov_merge_fn merge = gi_ptr->merge[t_ix];
468 if (!merge)
469 continue;
471 tag = gcov_read_unsigned ();
472 length = gcov_read_unsigned ();
473 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
474 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
475 goto read_mismatch;
476 (*merge) (ci_ptr->values, ci_ptr->num);
477 ci_ptr++;
479 if ((error = gcov_is_error ()))
480 goto read_error;
483 if (tag)
485 read_mismatch:;
486 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
487 filename, f_ix >= 0 ? "function" : "summary",
488 f_ix < 0 ? -1 - f_ix : f_ix);
489 return -1;
491 return 0;
493 read_error:
494 gcov_error ("profiling:%s:%s merging\n", filename,
495 error < 0 ? "Overflow": "Error");
496 return -1;
499 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
500 the case of appending to an existing file, SUMMARY_POS will be non-zero.
501 We will write the file starting from SUMMAY_POS. */
503 static void
504 write_one_data (const struct gcov_info *gi_ptr,
505 const struct gcov_summary *prg_p,
506 const gcov_position_t eof_pos,
507 const gcov_position_t summary_pos)
509 unsigned f_ix;
510 struct gcov_summary_buffer *next_sum_buffer;
512 /* Write out the data. */
513 if (!eof_pos)
515 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
516 gcov_write_unsigned (gi_ptr->stamp);
519 if (summary_pos)
520 gcov_seek (summary_pos);
522 /* Generate whole program statistics. */
523 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
525 /* Rewrite all the summaries that were after the summary we merged
526 into. This is necessary as the merged summary may have a different
527 size due to the number of non-zero histogram entries changing after
528 merging. */
530 while (sum_buffer)
532 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
533 next_sum_buffer = sum_buffer->next;
534 free (sum_buffer);
535 sum_buffer = next_sum_buffer;
538 /* Write execution counts for each function. */
539 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
541 unsigned buffered = 0;
542 const struct gcov_fn_info *gfi_ptr;
543 const struct gcov_ctr_info *ci_ptr;
544 gcov_unsigned_t length;
545 unsigned t_ix;
547 if (fn_buffer && fn_buffer->fn_ix == f_ix)
549 /* Buffered data from another program. */
550 buffered = 1;
551 gfi_ptr = &fn_buffer->info;
552 length = GCOV_TAG_FUNCTION_LENGTH;
554 else
556 gfi_ptr = gi_ptr->functions[f_ix];
557 if (gfi_ptr && gfi_ptr->key == gi_ptr)
558 length = GCOV_TAG_FUNCTION_LENGTH;
559 else
560 length = 0;
563 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
564 if (!length)
565 continue;
567 gcov_write_unsigned (gfi_ptr->ident);
568 gcov_write_unsigned (gfi_ptr->lineno_checksum);
569 gcov_write_unsigned (gfi_ptr->cfg_checksum);
571 ci_ptr = gfi_ptr->ctrs;
572 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
574 gcov_unsigned_t n_counts;
575 gcov_type *c_ptr;
577 if (!gi_ptr->merge[t_ix])
578 continue;
580 n_counts = ci_ptr->num;
581 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
582 GCOV_TAG_COUNTER_LENGTH (n_counts));
583 c_ptr = ci_ptr->values;
584 while (n_counts--)
585 gcov_write_counter (*c_ptr++);
586 ci_ptr++;
588 if (buffered)
589 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
592 gcov_write_unsigned (0);
595 /* Helper function for merging summary.
596 Return -1 on error. Return 0 on success. */
598 static int
599 merge_summary (const char *filename, int run_counted,
600 const struct gcov_info *gi_ptr, struct gcov_summary *prg,
601 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
602 struct gcov_summary *all_prg __attribute__ ((unused)))
604 struct gcov_ctr_summary *cs_prg, *cs_tprg;
605 unsigned t_ix;
606 #if !GCOV_LOCKED
607 /* summary for all instances of program. */
608 struct gcov_ctr_summary *cs_all;
609 #endif
611 /* Merge the summaries. */
612 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
614 cs_prg = &(prg->ctrs[t_ix]);
615 cs_tprg = &(this_prg->ctrs[t_ix]);
617 if (gi_ptr->merge[t_ix])
619 int first = !cs_prg->runs;
621 if (!run_counted)
622 cs_prg->runs++;
623 if (first)
624 cs_prg->num = cs_tprg->num;
625 cs_prg->sum_all += cs_tprg->sum_all;
626 if (cs_prg->run_max < cs_tprg->run_max)
627 cs_prg->run_max = cs_tprg->run_max;
628 cs_prg->sum_max += cs_tprg->run_max;
629 if (first)
630 memcpy (cs_prg->histogram, cs_tprg->histogram,
631 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
632 else
633 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
635 else if (cs_prg->runs)
637 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
638 filename);
639 return -1;
641 #if !GCOV_LOCKED
642 cs_all = &all_prg->ctrs[t_ix];
643 if (!cs_all->runs && cs_prg->runs)
645 cs_all->num = cs_prg->num;
646 cs_all->runs = cs_prg->runs;
647 cs_all->sum_all = cs_prg->sum_all;
648 cs_all->run_max = cs_prg->run_max;
649 cs_all->sum_max = cs_prg->sum_max;
651 else if (!all_prg->checksum
652 /* Don't compare the histograms, which may have slight
653 variations depending on the order they were updated
654 due to the truncating integer divides used in the
655 merge. */
656 && (cs_all->num != cs_prg->num
657 || cs_all->runs != cs_prg->runs
658 || cs_all->sum_all != cs_prg->sum_all
659 || cs_all->run_max != cs_prg->run_max
660 || cs_all->sum_max != cs_prg->sum_max))
662 gcov_error ("profiling:%s:Data file mismatch - some "
663 "data files may have been concurrently "
664 "updated without locking support\n", filename);
665 all_prg->checksum = ~0u;
667 #endif
670 prg->checksum = crc32;
672 return 0;
676 /* Sort N entries in VALUE_ARRAY in descending order.
677 Each entry in VALUE_ARRAY has two values. The sorting
678 is based on the second value. */
680 GCOV_LINKAGE void
681 gcov_sort_n_vals (gcov_type *value_array, int n)
683 int j, k;
685 for (j = 2; j < n; j += 2)
687 gcov_type cur_ent[2];
689 cur_ent[0] = value_array[j];
690 cur_ent[1] = value_array[j + 1];
691 k = j - 2;
692 while (k >= 0 && value_array[k + 1] < cur_ent[1])
694 value_array[k + 2] = value_array[k];
695 value_array[k + 3] = value_array[k+1];
696 k -= 2;
698 value_array[k + 2] = cur_ent[0];
699 value_array[k + 3] = cur_ent[1];
703 /* Sort the profile counters for all indirect call sites. Counters
704 for each call site are allocated in array COUNTERS. */
706 static void
707 gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
709 int i;
710 gcov_type *values;
711 int n = counters->num;
713 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
714 values = counters->values;
716 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
718 gcov_type *value_array = &values[i + 1];
719 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
723 /* Sort topn indirect_call profile counters in GI_PTR. */
725 static void
726 gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
728 unsigned int i;
729 int f_ix;
730 const struct gcov_fn_info *gfi_ptr;
731 const struct gcov_ctr_info *ci_ptr;
733 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
734 return;
736 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
738 gfi_ptr = gi_ptr->functions[f_ix];
739 ci_ptr = gfi_ptr->ctrs;
740 for (i = 0; i < GCOV_COUNTERS; i++)
742 if (!gi_ptr->merge[i])
743 continue;
744 if (i == GCOV_COUNTER_ICALL_TOPNV)
746 gcov_sort_icall_topn_counter (ci_ptr);
747 break;
749 ci_ptr++;
754 /* Dump the coverage counts for one gcov_info object. We merge with existing
755 counts when possible, to avoid growing the .da files ad infinitum. We use
756 this program's checksum to make sure we only accumulate whole program
757 statistics to the correct summary. An object file might be embedded
758 in two separate programs, and we must keep the two program
759 summaries separate. */
761 static void
762 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
763 unsigned run_counted,
764 gcov_unsigned_t crc32, struct gcov_summary *all_prg,
765 struct gcov_summary *this_prg)
767 struct gcov_summary prg; /* summary for this object over all program. */
768 int error;
769 gcov_unsigned_t tag;
770 gcov_position_t summary_pos = 0;
771 gcov_position_t eof_pos = 0;
773 fn_buffer = 0;
774 sum_buffer = 0;
776 gcov_sort_topn_counter_arrays (gi_ptr);
778 error = gcov_exit_open_gcda_file (gi_ptr, gf);
779 if (error == -1)
780 return;
782 tag = gcov_read_unsigned ();
783 if (tag)
785 /* Merge data from file. */
786 if (tag != GCOV_DATA_MAGIC)
788 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
789 goto read_fatal;
791 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
792 &summary_pos, &eof_pos, crc32);
793 if (error == -1)
794 goto read_fatal;
797 gcov_rewrite ();
799 if (!summary_pos)
801 memset (&prg, 0, sizeof (prg));
802 summary_pos = eof_pos;
805 error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
806 crc32, all_prg);
807 if (error == -1)
808 goto read_fatal;
810 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
811 /* fall through */
813 read_fatal:;
814 while (fn_buffer)
815 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
817 if ((error = gcov_close ()))
818 gcov_error (error < 0 ?
819 "profiling:%s:Overflow writing\n" :
820 "profiling:%s:Error writing\n",
821 gf->filename);
825 /* Dump all the coverage counts for the program. It first computes program
826 summary and then traverses gcov_list list and dumps the gcov_info
827 objects one by one. */
829 #if !IN_GCOV_TOOL
830 static
831 #endif
832 void
833 gcov_do_dump (struct gcov_info *list, int run_counted)
835 struct gcov_info *gi_ptr;
836 struct gcov_filename gf;
837 gcov_unsigned_t crc32;
838 struct gcov_summary all_prg;
839 struct gcov_summary this_prg;
841 crc32 = compute_summary (list, &this_prg, &gf.max_length);
843 allocate_filename_struct (&gf);
844 #if !GCOV_LOCKED
845 memset (&all_prg, 0, sizeof (all_prg));
846 #endif
848 /* Now merge each file. */
849 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
850 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
852 free (gf.filename);
855 #if IN_GCOV_TOOL
856 const char *
857 __attribute__ ((unused))
858 gcov_get_filename (struct gcov_info *list)
860 return list->filename;
862 #endif
864 #if !IN_GCOV_TOOL
865 void
866 __gcov_dump_one (struct gcov_root *root)
868 if (root->dumped)
869 return;
871 gcov_do_dump (root->list, root->run_counted);
873 root->dumped = 1;
874 root->run_counted = 1;
877 /* Per-dynamic-object gcov state. */
878 struct gcov_root __gcov_root;
880 /* Exactly one of these will be live in the process image. */
881 struct gcov_master __gcov_master =
882 {GCOV_VERSION, 0};
884 void
885 __gcov_exit (void)
887 __gcov_dump_one (&__gcov_root);
888 if (__gcov_root.next)
889 __gcov_root.next->prev = __gcov_root.prev;
890 if (__gcov_root.prev)
891 __gcov_root.prev->next = __gcov_root.next;
892 else
893 __gcov_master.root = __gcov_root.next;
895 gcov_error_exit ();
898 /* Add a new object file onto the bb chain. Invoked automatically
899 when running an object file's global ctors. */
901 void
902 __gcov_init (struct gcov_info *info)
904 if (!info->version || !info->n_functions)
905 return;
906 if (gcov_version (info, info->version, 0))
908 if (!__gcov_root.list)
910 /* Add to master list and at exit function. */
911 if (gcov_version (NULL, __gcov_master.version, "<master>"))
913 __gcov_root.next = __gcov_master.root;
914 if (__gcov_master.root)
915 __gcov_master.root->prev = &__gcov_root;
916 __gcov_master.root = &__gcov_root;
920 info->next = __gcov_root.list;
921 __gcov_root.list = info;
924 #endif /* !IN_GCOV_TOOL */
925 #endif /* L_gcov */
926 #endif /* inhibit_libc */