Simplify gcov_histogram as it's used only for ARCS counters.
[official-gcc.git] / libgcc / libgcov-driver.c
blob922d9dde8334cabfa88f38ea6a4f11006b36dfe7
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 unsigned f_ix, ix;
225 int h_ix;
227 /* First check if there are any counts recorded for this counter. */
228 if (!sum->num)
229 return;
231 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
233 sum->histogram[h_ix].num_counters = 0;
234 sum->histogram[h_ix].min_value = sum->run_max;
235 sum->histogram[h_ix].cum_value = 0;
238 /* Walk through all the per-object structures and record each of
239 the count values in histogram. */
240 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
242 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
244 gfi_ptr = gi_ptr->functions[f_ix];
246 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
247 continue;
249 ci_ptr = &gfi_ptr->ctrs[0];
250 for (ix = 0; ix < ci_ptr->num; ix++)
251 gcov_histogram_insert (sum->histogram, ci_ptr->values[ix]);
256 /* buffer for the fn_data from another program. */
257 static struct gcov_fn_buffer *fn_buffer;
258 /* buffer for summary from other programs to be written out. */
259 static struct gcov_summary_buffer *sum_buffer;
261 /* This function computes the program level summary and the histo-gram.
262 It computes and returns CRC32 and stored summary in THIS_PRG.
263 Also determines the longest filename length of the info files. */
265 #if !IN_GCOV_TOOL
266 static
267 #endif
268 gcov_unsigned_t
269 compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
270 size_t *max_length)
272 struct gcov_info *gi_ptr;
273 const struct gcov_fn_info *gfi_ptr;
274 const struct gcov_ctr_info *ci_ptr;
275 int f_ix;
276 gcov_unsigned_t c_num;
277 gcov_unsigned_t crc32 = 0;
279 /* Find the totals for this execution. */
280 memset (this_prg, 0, sizeof (*this_prg));
281 *max_length = 0;
282 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
284 size_t len = strlen (gi_ptr->filename);
285 if (len > *max_length)
286 *max_length = len;
288 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
289 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
291 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
293 gfi_ptr = gi_ptr->functions[f_ix];
295 if (gfi_ptr && gfi_ptr->key != gi_ptr)
296 gfi_ptr = 0;
298 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
299 crc32 = crc32_unsigned (crc32,
300 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
301 if (!gfi_ptr)
302 continue;
304 ci_ptr = gfi_ptr->ctrs;
305 this_prg->num += ci_ptr->num;
306 crc32 = crc32_unsigned (crc32, ci_ptr->num);
308 for (c_num = 0; c_num < ci_ptr->num; c_num++)
310 this_prg->sum_all += ci_ptr->values[c_num];
311 if (this_prg->run_max < ci_ptr->values[c_num])
312 this_prg->run_max = ci_ptr->values[c_num];
314 ci_ptr++;
317 gcov_compute_histogram (list, this_prg);
318 return crc32;
321 /* Including system dependent components. */
322 #include "libgcov-driver-system.c"
324 /* This function merges counters in GI_PTR to an existing gcda file.
325 Return 0 on success.
326 Return -1 on error. In this case, caller will goto read_fatal. */
328 static int
329 merge_one_data (const char *filename,
330 struct gcov_info *gi_ptr,
331 struct gcov_summary *prg_p,
332 struct gcov_summary *this_prg,
333 gcov_position_t *summary_pos_p,
334 gcov_position_t *eof_pos_p,
335 gcov_unsigned_t crc32)
337 gcov_unsigned_t tag, length;
338 unsigned t_ix;
339 int f_ix;
340 int error = 0;
341 struct gcov_fn_buffer **fn_tail = &fn_buffer;
342 struct gcov_summary_buffer **sum_tail = &sum_buffer;
344 length = gcov_read_unsigned ();
345 if (!gcov_version (gi_ptr, length, filename))
346 return -1;
348 length = gcov_read_unsigned ();
349 if (length != gi_ptr->stamp)
351 /* Read from a different compilation. Overwrite the file. */
352 gcov_error ("profiling:%s:overwriting an existing profile data "
353 "with a different timestamp\n", filename);
354 return 0;
357 /* Look for program summary. */
358 for (f_ix = 0;;)
360 struct gcov_summary tmp;
362 *eof_pos_p = gcov_position ();
363 tag = gcov_read_unsigned ();
364 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
365 break;
367 f_ix--;
368 length = gcov_read_unsigned ();
369 gcov_read_summary (&tmp);
370 if ((error = gcov_is_error ()))
371 goto read_error;
372 if (*summary_pos_p)
374 /* Save all summaries after the one that will be
375 merged into below. These will need to be rewritten
376 as histogram merging may change the number of non-zero
377 histogram entries that will be emitted, and thus the
378 size of the merged summary. */
379 (*sum_tail) = (struct gcov_summary_buffer *)
380 xmalloc (sizeof(struct gcov_summary_buffer));
381 (*sum_tail)->summary = tmp;
382 (*sum_tail)->next = 0;
383 sum_tail = &((*sum_tail)->next);
384 goto next_summary;
386 if (tmp.checksum != crc32)
387 goto next_summary;
389 if (tmp.num != this_prg->num)
390 goto next_summary;
391 *prg_p = tmp;
392 *summary_pos_p = *eof_pos_p;
394 next_summary:;
397 /* Merge execution counts for each function. */
398 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
399 f_ix++, tag = gcov_read_unsigned ())
401 const struct gcov_ctr_info *ci_ptr;
402 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
404 if (tag != GCOV_TAG_FUNCTION)
405 goto read_mismatch;
407 length = gcov_read_unsigned ();
408 if (!length)
409 /* This function did not appear in the other program.
410 We have nothing to merge. */
411 continue;
413 if (length != GCOV_TAG_FUNCTION_LENGTH)
414 goto read_mismatch;
416 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
418 /* This function appears in the other program. We
419 need to buffer the information in order to write
420 it back out -- we'll be inserting data before
421 this point, so cannot simply keep the data in the
422 file. */
423 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
424 if (!fn_tail)
425 goto read_mismatch;
426 continue;
429 length = gcov_read_unsigned ();
430 if (length != gfi_ptr->ident)
431 goto read_mismatch;
433 length = gcov_read_unsigned ();
434 if (length != gfi_ptr->lineno_checksum)
435 goto read_mismatch;
437 length = gcov_read_unsigned ();
438 if (length != gfi_ptr->cfg_checksum)
439 goto read_mismatch;
441 ci_ptr = gfi_ptr->ctrs;
442 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
444 gcov_merge_fn merge = gi_ptr->merge[t_ix];
446 if (!merge)
447 continue;
449 tag = gcov_read_unsigned ();
450 length = gcov_read_unsigned ();
451 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
452 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
453 goto read_mismatch;
454 (*merge) (ci_ptr->values, ci_ptr->num);
455 ci_ptr++;
457 if ((error = gcov_is_error ()))
458 goto read_error;
461 if (tag)
463 read_mismatch:;
464 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
465 filename, f_ix >= 0 ? "function" : "summary",
466 f_ix < 0 ? -1 - f_ix : f_ix);
467 return -1;
469 return 0;
471 read_error:
472 gcov_error ("profiling:%s:%s merging\n", filename,
473 error < 0 ? "Overflow": "Error");
474 return -1;
477 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
478 the case of appending to an existing file, SUMMARY_POS will be non-zero.
479 We will write the file starting from SUMMAY_POS. */
481 static void
482 write_one_data (const struct gcov_info *gi_ptr,
483 const struct gcov_summary *prg_p,
484 const gcov_position_t eof_pos,
485 const gcov_position_t summary_pos)
487 unsigned f_ix;
488 struct gcov_summary_buffer *next_sum_buffer;
490 /* Write out the data. */
491 if (!eof_pos)
493 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
494 gcov_write_unsigned (gi_ptr->stamp);
497 if (summary_pos)
498 gcov_seek (summary_pos);
500 /* Generate whole program statistics. */
501 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
503 /* Rewrite all the summaries that were after the summary we merged
504 into. This is necessary as the merged summary may have a different
505 size due to the number of non-zero histogram entries changing after
506 merging. */
508 while (sum_buffer)
510 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
511 next_sum_buffer = sum_buffer->next;
512 free (sum_buffer);
513 sum_buffer = next_sum_buffer;
516 /* Write execution counts for each function. */
517 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
519 unsigned buffered = 0;
520 const struct gcov_fn_info *gfi_ptr;
521 const struct gcov_ctr_info *ci_ptr;
522 gcov_unsigned_t length;
523 unsigned t_ix;
525 if (fn_buffer && fn_buffer->fn_ix == f_ix)
527 /* Buffered data from another program. */
528 buffered = 1;
529 gfi_ptr = &fn_buffer->info;
530 length = GCOV_TAG_FUNCTION_LENGTH;
532 else
534 gfi_ptr = gi_ptr->functions[f_ix];
535 if (gfi_ptr && gfi_ptr->key == gi_ptr)
536 length = GCOV_TAG_FUNCTION_LENGTH;
537 else
538 length = 0;
541 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
542 if (!length)
543 continue;
545 gcov_write_unsigned (gfi_ptr->ident);
546 gcov_write_unsigned (gfi_ptr->lineno_checksum);
547 gcov_write_unsigned (gfi_ptr->cfg_checksum);
549 ci_ptr = gfi_ptr->ctrs;
550 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
552 gcov_unsigned_t n_counts;
553 gcov_type *c_ptr;
555 if (!gi_ptr->merge[t_ix])
556 continue;
558 n_counts = ci_ptr->num;
559 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
560 GCOV_TAG_COUNTER_LENGTH (n_counts));
561 c_ptr = ci_ptr->values;
562 while (n_counts--)
563 gcov_write_counter (*c_ptr++);
564 ci_ptr++;
566 if (buffered)
567 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
570 gcov_write_unsigned (0);
573 /* Helper function for merging summary.
574 Return -1 on error. Return 0 on success. */
576 static int
577 merge_summary (const char *filename __attribute__ ((unused)), int run_counted,
578 struct gcov_summary *prg,
579 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
580 struct gcov_summary *all_prg __attribute__ ((unused)))
582 #if !GCOV_LOCKED
583 /* summary for all instances of program. */
584 struct gcov_summary *cs_all;
585 #endif
587 /* Merge the summary. */
588 int first = !prg->runs;
590 if (!run_counted)
591 prg->runs++;
592 if (first)
593 prg->num = this_prg->num;
594 prg->sum_all += this_prg->sum_all;
595 if (prg->run_max < this_prg->run_max)
596 prg->run_max = this_prg->run_max;
597 prg->sum_max += this_prg->run_max;
598 if (first)
599 memcpy (prg->histogram, this_prg->histogram,
600 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
601 else
602 gcov_histogram_merge (prg->histogram, this_prg->histogram);
603 #if !GCOV_LOCKED
604 all = &all_prg->ctrs[t_ix];
605 if (!all->runs && prg->runs)
607 all->num = prg->num;
608 all->runs = prg->runs;
609 all->sum_all = prg->sum_all;
610 all->run_max = prg->run_max;
611 all->sum_max = prg->sum_max;
613 else if (!all_prg->checksum
614 /* Don't compare the histograms, which may have slight
615 variations depending on the order they were updated
616 due to the truncating integer divides used in the
617 merge. */
618 && (all->num != prg->num
619 || all->runs != prg->runs
620 || all->sum_all != prg->sum_all
621 || all->run_max != prg->run_max
622 || all->sum_max != prg->sum_max))
624 gcov_error ("profiling:%s:Data file mismatch - some "
625 "data files may have been concurrently "
626 "updated without locking support\n", filename);
627 all_prg->checksum = ~0u;
629 #endif
631 prg->checksum = crc32;
633 return 0;
637 /* Sort N entries in VALUE_ARRAY in descending order.
638 Each entry in VALUE_ARRAY has two values. The sorting
639 is based on the second value. */
641 GCOV_LINKAGE void
642 gcov_sort_n_vals (gcov_type *value_array, int n)
644 int j, k;
646 for (j = 2; j < n; j += 2)
648 gcov_type cur_ent[2];
650 cur_ent[0] = value_array[j];
651 cur_ent[1] = value_array[j + 1];
652 k = j - 2;
653 while (k >= 0 && value_array[k + 1] < cur_ent[1])
655 value_array[k + 2] = value_array[k];
656 value_array[k + 3] = value_array[k+1];
657 k -= 2;
659 value_array[k + 2] = cur_ent[0];
660 value_array[k + 3] = cur_ent[1];
664 /* Sort the profile counters for all indirect call sites. Counters
665 for each call site are allocated in array COUNTERS. */
667 static void
668 gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
670 int i;
671 gcov_type *values;
672 int n = counters->num;
674 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
675 values = counters->values;
677 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
679 gcov_type *value_array = &values[i + 1];
680 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
684 /* Sort topn indirect_call profile counters in GI_PTR. */
686 static void
687 gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
689 unsigned int i;
690 int f_ix;
691 const struct gcov_fn_info *gfi_ptr;
692 const struct gcov_ctr_info *ci_ptr;
694 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
695 return;
697 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
699 gfi_ptr = gi_ptr->functions[f_ix];
700 ci_ptr = gfi_ptr->ctrs;
701 for (i = 0; i < GCOV_COUNTERS; i++)
703 if (!gi_ptr->merge[i])
704 continue;
705 if (i == GCOV_COUNTER_ICALL_TOPNV)
707 gcov_sort_icall_topn_counter (ci_ptr);
708 break;
710 ci_ptr++;
715 /* Dump the coverage counts for one gcov_info object. We merge with existing
716 counts when possible, to avoid growing the .da files ad infinitum. We use
717 this program's checksum to make sure we only accumulate whole program
718 statistics to the correct summary. An object file might be embedded
719 in two separate programs, and we must keep the two program
720 summaries separate. */
722 static void
723 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
724 unsigned run_counted,
725 gcov_unsigned_t crc32, struct gcov_summary *all_prg,
726 struct gcov_summary *this_prg)
728 struct gcov_summary prg; /* summary for this object over all program. */
729 int error;
730 gcov_unsigned_t tag;
731 gcov_position_t summary_pos = 0;
732 gcov_position_t eof_pos = 0;
734 fn_buffer = 0;
735 sum_buffer = 0;
737 gcov_sort_topn_counter_arrays (gi_ptr);
739 error = gcov_exit_open_gcda_file (gi_ptr, gf);
740 if (error == -1)
741 return;
743 tag = gcov_read_unsigned ();
744 if (tag)
746 /* Merge data from file. */
747 if (tag != GCOV_DATA_MAGIC)
749 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
750 goto read_fatal;
752 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
753 &summary_pos, &eof_pos, crc32);
754 if (error == -1)
755 goto read_fatal;
758 gcov_rewrite ();
760 if (!summary_pos)
762 memset (&prg, 0, sizeof (prg));
763 summary_pos = eof_pos;
766 error = merge_summary (gf->filename, run_counted, &prg, this_prg,
767 crc32, all_prg);
768 if (error == -1)
769 goto read_fatal;
771 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
772 /* fall through */
774 read_fatal:;
775 while (fn_buffer)
776 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
778 if ((error = gcov_close ()))
779 gcov_error (error < 0 ?
780 "profiling:%s:Overflow writing\n" :
781 "profiling:%s:Error writing\n",
782 gf->filename);
786 /* Dump all the coverage counts for the program. It first computes program
787 summary and then traverses gcov_list list and dumps the gcov_info
788 objects one by one. */
790 #if !IN_GCOV_TOOL
791 static
792 #endif
793 void
794 gcov_do_dump (struct gcov_info *list, int run_counted)
796 struct gcov_info *gi_ptr;
797 struct gcov_filename gf;
798 gcov_unsigned_t crc32;
799 struct gcov_summary all_prg;
800 struct gcov_summary this_prg;
802 crc32 = compute_summary (list, &this_prg, &gf.max_length);
804 allocate_filename_struct (&gf);
805 #if !GCOV_LOCKED
806 memset (&all_prg, 0, sizeof (all_prg));
807 #endif
809 /* Now merge each file. */
810 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
811 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
813 free (gf.filename);
816 #if IN_GCOV_TOOL
817 const char *
818 __attribute__ ((unused))
819 gcov_get_filename (struct gcov_info *list)
821 return list->filename;
823 #endif
825 #if !IN_GCOV_TOOL
826 void
827 __gcov_dump_one (struct gcov_root *root)
829 if (root->dumped)
830 return;
832 gcov_do_dump (root->list, root->run_counted);
834 root->dumped = 1;
835 root->run_counted = 1;
838 /* Per-dynamic-object gcov state. */
839 struct gcov_root __gcov_root;
841 /* Exactly one of these will be live in the process image. */
842 struct gcov_master __gcov_master =
843 {GCOV_VERSION, 0};
845 void
846 __gcov_exit (void)
848 __gcov_dump_one (&__gcov_root);
849 if (__gcov_root.next)
850 __gcov_root.next->prev = __gcov_root.prev;
851 if (__gcov_root.prev)
852 __gcov_root.prev->next = __gcov_root.next;
853 else
854 __gcov_master.root = __gcov_root.next;
856 gcov_error_exit ();
859 /* Add a new object file onto the bb chain. Invoked automatically
860 when running an object file's global ctors. */
862 void
863 __gcov_init (struct gcov_info *info)
865 if (!info->version || !info->n_functions)
866 return;
867 if (gcov_version (info, info->version, 0))
869 if (!__gcov_root.list)
871 /* Add to master list and at exit function. */
872 if (gcov_version (NULL, __gcov_master.version, "<master>"))
874 __gcov_root.next = __gcov_master.root;
875 if (__gcov_master.root)
876 __gcov_master.root->prev = &__gcov_root;
877 __gcov_master.root = &__gcov_root;
881 info->next = __gcov_root.list;
882 __gcov_root.list = info;
885 #endif /* !IN_GCOV_TOOL */
886 #endif /* L_gcov */
887 #endif /* inhibit_libc */