]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/libgcov-driver.c
Use v2 map syntax in libgcc-unwind.map if Solaris ld supports it
[thirdparty/gcc.git] / libgcc / libgcov-driver.c
CommitLineData
ded3d3f8 1/* Routines required for instrumenting a program. */
2/* Compile this one with gcc. */
8e8f6434 3/* Copyright (C) 1989-2018 Free Software Foundation, Inc.
ded3d3f8 4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
67745126 26#include "libgcov.h"
ded3d3f8 27
28#if defined(inhibit_libc)
29/* If libc and its header files are not available, provide dummy functions. */
30
31#if defined(L_gcov)
32void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
33#endif
34
35#else /* inhibit_libc */
36
37#include <string.h>
38#if GCOV_LOCKED
39#include <fcntl.h>
40#include <errno.h>
41#include <sys/stat.h>
42#endif
43
44#ifdef L_gcov
f1919901 45
3237fc56 46/* A utility function for outputting errors. */
f1919901 47static int gcov_error (const char *, ...);
48
3237fc56 49#if !IN_GCOV_TOOL
50static void gcov_error_exit (void);
51#endif
52
ded3d3f8 53#include "gcov-io.c"
54
ded3d3f8 55struct gcov_fn_buffer
56{
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. */
61};
62
63struct gcov_summary_buffer
64{
65 struct gcov_summary_buffer *next;
66 struct gcov_summary summary;
67};
68
6401b74d 69/* A struct that bundles all the related information about the
70 gcda filename. */
71
72struct gcov_filename
73{
74 char *filename; /* filename buffer */
6401b74d 75 int strip; /* leading chars to strip from filename */
5b24ad4b 76 char *prefix; /* prefix string */
6401b74d 77};
78
ded3d3f8 79static struct gcov_fn_buffer *
80free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
81 unsigned limit)
82{
83 struct gcov_fn_buffer *next;
84 unsigned ix, n_ctr = 0;
85
86 if (!buffer)
87 return 0;
88 next = buffer->next;
89
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;
95}
96
97static struct gcov_fn_buffer **
98buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
99 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
100{
101 unsigned n_ctrs = 0, ix = 0;
102 struct gcov_fn_buffer *fn_buffer;
103 unsigned len;
104
105 for (ix = GCOV_COUNTERS; ix--;)
106 if (gi_ptr->merge[ix])
107 n_ctrs++;
108
109 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
67745126 110 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
ded3d3f8 111
112 if (!fn_buffer)
113 goto fail;
114
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 ();
120
121 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
122 {
123 gcov_unsigned_t length;
124 gcov_type *values;
125
126 if (!gi_ptr->merge[ix])
127 continue;
128
129 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
130 {
131 len = 0;
132 goto fail;
133 }
134
135 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
136 len = length * sizeof (gcov_type);
67745126 137 values = (gcov_type *) xmalloc (len);
ded3d3f8 138 if (!values)
139 goto fail;
140
141 fn_buffer->info.ctrs[n_ctrs].num = length;
142 fn_buffer->info.ctrs[n_ctrs].values = values;
143
144 while (length--)
145 *values++ = gcov_read_counter ();
146 n_ctrs++;
147 }
148
149 *end_ptr = fn_buffer;
150 return &fn_buffer->next;
151
152fail:
153 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
154 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
155
156 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
157}
158
159/* Add an unsigned value to the current crc */
160
161static gcov_unsigned_t
162crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
163{
164 unsigned ix;
165
166 for (ix = 32; ix--; value <<= 1)
167 {
168 unsigned feedback;
169
170 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
171 crc32 <<= 1;
172 crc32 ^= feedback;
173 }
174
175 return crc32;
176}
177
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. */
182
183static int
184gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
185 const char *filename)
186{
187 if (version != GCOV_VERSION)
188 {
189 char v[4], e[4];
190
191 GCOV_UNSIGNED2STRING (v, version);
192 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
193
194 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
195 filename? filename : ptr->filename, e, v);
196 return 0;
197 }
198 return 1;
199}
200
201/* Insert counter VALUE into HISTOGRAM. */
202
203static void
204gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
205{
206 unsigned i;
207
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;
213}
214
215/* Computes a histogram of the arc counters to place in the summary SUM. */
216
217static void
859fa1a9 218gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
ded3d3f8 219{
220 struct gcov_info *gi_ptr;
221 const struct gcov_fn_info *gfi_ptr;
222 const struct gcov_ctr_info *ci_ptr;
5860b185 223 unsigned f_ix, ix;
ded3d3f8 224 int h_ix;
225
ded3d3f8 226 /* First check if there are any counts recorded for this counter. */
5860b185 227 if (!sum->num)
ded3d3f8 228 return;
229
230 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
231 {
5860b185 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;
ded3d3f8 235 }
236
237 /* Walk through all the per-object structures and record each of
238 the count values in histogram. */
859fa1a9 239 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
ded3d3f8 240 {
ded3d3f8 241 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
242 {
243 gfi_ptr = gi_ptr->functions[f_ix];
244
245 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
246 continue;
247
5860b185 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]);
ded3d3f8 251 }
252 }
253}
254
ded3d3f8 255/* buffer for the fn_data from another program. */
256static struct gcov_fn_buffer *fn_buffer;
257/* buffer for summary from other programs to be written out. */
258static struct gcov_summary_buffer *sum_buffer;
259
6401b74d 260/* This function computes the program level summary and the histo-gram.
5b24ad4b 261 It computes and returns CRC32 and stored summary in THIS_PRG. */
ded3d3f8 262
26054e0b 263#if !IN_GCOV_TOOL
264static
265#endif
266gcov_unsigned_t
5b24ad4b 267compute_summary (struct gcov_info *list, struct gcov_summary *this_prg)
ded3d3f8 268{
269 struct gcov_info *gi_ptr;
270 const struct gcov_fn_info *gfi_ptr;
ded3d3f8 271 const struct gcov_ctr_info *ci_ptr;
272 int f_ix;
ded3d3f8 273 gcov_unsigned_t c_num;
f75db2a8 274 gcov_unsigned_t crc32 = 0;
ded3d3f8 275
ded3d3f8 276 /* Find the totals for this execution. */
b9f9bf68 277 memset (this_prg, 0, sizeof (*this_prg));
1186f97a 278 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
ded3d3f8 279 {
280 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
281 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
282
283 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
284 {
285 gfi_ptr = gi_ptr->functions[f_ix];
286
287 if (gfi_ptr && gfi_ptr->key != gi_ptr)
288 gfi_ptr = 0;
289
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;
295
5860b185 296 ci_ptr = gfi_ptr->ctrs;
297 this_prg->num += ci_ptr->num;
298 crc32 = crc32_unsigned (crc32, ci_ptr->num);
299
300 for (c_num = 0; c_num < ci_ptr->num; c_num++)
301 {
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];
305 }
306 ci_ptr++;
307 }
ded3d3f8 308 }
859fa1a9 309 gcov_compute_histogram (list, this_prg);
f75db2a8 310 return crc32;
ded3d3f8 311}
312
ded3d3f8 313/* Including system dependent components. */
314#include "libgcov-driver-system.c"
315
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. */
319
320static int
1186f97a 321merge_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)
ded3d3f8 328{
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;
335
336 length = gcov_read_unsigned ();
6401b74d 337 if (!gcov_version (gi_ptr, length, filename))
ded3d3f8 338 return -1;
339
340 length = gcov_read_unsigned ();
341 if (length != gi_ptr->stamp)
5522d934 342 {
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;
347 }
ded3d3f8 348
349 /* Look for program summary. */
350 for (f_ix = 0;;)
351 {
352 struct gcov_summary tmp;
353
354 *eof_pos_p = gcov_position ();
355 tag = gcov_read_unsigned ();
356 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
357 break;
358
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)
365 {
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 *)
67745126 372 xmalloc (sizeof(struct gcov_summary_buffer));
ded3d3f8 373 (*sum_tail)->summary = tmp;
374 (*sum_tail)->next = 0;
375 sum_tail = &((*sum_tail)->next);
376 goto next_summary;
377 }
378 if (tmp.checksum != crc32)
379 goto next_summary;
380
5860b185 381 if (tmp.num != this_prg->num)
382 goto next_summary;
ded3d3f8 383 *prg_p = tmp;
384 *summary_pos_p = *eof_pos_p;
385
386 next_summary:;
387 }
388
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 ())
392 {
393 const struct gcov_ctr_info *ci_ptr;
394 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
395
396 if (tag != GCOV_TAG_FUNCTION)
397 goto read_mismatch;
398
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;
404
405 if (length != GCOV_TAG_FUNCTION_LENGTH)
406 goto read_mismatch;
407
408 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
409 {
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. */
6401b74d 415 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
ded3d3f8 416 if (!fn_tail)
417 goto read_mismatch;
418 continue;
419 }
420
421 length = gcov_read_unsigned ();
422 if (length != gfi_ptr->ident)
423 goto read_mismatch;
424
425 length = gcov_read_unsigned ();
426 if (length != gfi_ptr->lineno_checksum)
427 goto read_mismatch;
428
429 length = gcov_read_unsigned ();
430 if (length != gfi_ptr->cfg_checksum)
431 goto read_mismatch;
432
433 ci_ptr = gfi_ptr->ctrs;
434 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
435 {
436 gcov_merge_fn merge = gi_ptr->merge[t_ix];
437
438 if (!merge)
439 continue;
440
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++;
448 }
449 if ((error = gcov_is_error ()))
450 goto read_error;
451 }
452
453 if (tag)
454 {
455 read_mismatch:;
456 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
6401b74d 457 filename, f_ix >= 0 ? "function" : "summary",
ded3d3f8 458 f_ix < 0 ? -1 - f_ix : f_ix);
459 return -1;
460 }
461 return 0;
462
463read_error:
6401b74d 464 gcov_error ("profiling:%s:%s merging\n", filename,
ded3d3f8 465 error < 0 ? "Overflow": "Error");
466 return -1;
467}
468
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. */
472
473static void
1186f97a 474write_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)
ded3d3f8 478{
479 unsigned f_ix;
480 struct gcov_summary_buffer *next_sum_buffer;
481
482 /* Write out the data. */
483 if (!eof_pos)
484 {
485 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
486 gcov_write_unsigned (gi_ptr->stamp);
487 }
488
489 if (summary_pos)
490 gcov_seek (summary_pos);
491
492 /* Generate whole program statistics. */
493 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
494
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. */
499
500 while (sum_buffer)
501 {
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;
506 }
507
508 /* Write execution counts for each function. */
509 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
510 {
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;
516
517 if (fn_buffer && fn_buffer->fn_ix == f_ix)
518 {
519 /* Buffered data from another program. */
520 buffered = 1;
521 gfi_ptr = &fn_buffer->info;
522 length = GCOV_TAG_FUNCTION_LENGTH;
523 }
524 else
525 {
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;
531 }
532
533 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
534 if (!length)
535 continue;
536
537 gcov_write_unsigned (gfi_ptr->ident);
538 gcov_write_unsigned (gfi_ptr->lineno_checksum);
539 gcov_write_unsigned (gfi_ptr->cfg_checksum);
540
541 ci_ptr = gfi_ptr->ctrs;
542 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
543 {
544 gcov_unsigned_t n_counts;
545 gcov_type *c_ptr;
546
547 if (!gi_ptr->merge[t_ix])
548 continue;
549
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++;
557 }
558 if (buffered)
559 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
560 }
561
562 gcov_write_unsigned (0);
563}
564
565/* Helper function for merging summary.
566 Return -1 on error. Return 0 on success. */
567
568static int
5860b185 569merge_summary (const char *filename __attribute__ ((unused)), int run_counted,
570 struct gcov_summary *prg,
1186f97a 571 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
572 struct gcov_summary *all_prg __attribute__ ((unused)))
ded3d3f8 573{
f75db2a8 574#if !GCOV_LOCKED
575 /* summary for all instances of program. */
6b9cd917 576 struct gcov_summary *all;
f75db2a8 577#endif
ded3d3f8 578
5860b185 579 /* Merge the summary. */
580 int first = !prg->runs;
581
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);
ded3d3f8 595#if !GCOV_LOCKED
6b9cd917 596 all = all_prg;
5860b185 597 if (!all->runs && prg->runs)
598 {
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;
604 }
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))
615 {
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;
ded3d3f8 620 }
5860b185 621#endif
622
ded3d3f8 623 prg->checksum = crc32;
624
625 return 0;
626}
627
8ceaa1ef 628
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. */
632
633GCOV_LINKAGE void
634gcov_sort_n_vals (gcov_type *value_array, int n)
635{
636 int j, k;
637
638 for (j = 2; j < n; j += 2)
639 {
640 gcov_type cur_ent[2];
641
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])
646 {
647 value_array[k + 2] = value_array[k];
648 value_array[k + 3] = value_array[k+1];
649 k -= 2;
650 }
651 value_array[k + 2] = cur_ent[0];
652 value_array[k + 3] = cur_ent[1];
653 }
654}
655
656/* Sort the profile counters for all indirect call sites. Counters
657 for each call site are allocated in array COUNTERS. */
658
659static void
660gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
661{
662 int i;
663 gcov_type *values;
664 int n = counters->num;
665
666 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
667 values = counters->values;
668
669 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
670 {
671 gcov_type *value_array = &values[i + 1];
672 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
673 }
674}
675
676/* Sort topn indirect_call profile counters in GI_PTR. */
677
678static void
679gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
680{
681 unsigned int i;
682 int f_ix;
683 const struct gcov_fn_info *gfi_ptr;
684 const struct gcov_ctr_info *ci_ptr;
685
686 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
687 return;
688
689 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
690 {
691 gfi_ptr = gi_ptr->functions[f_ix];
692 ci_ptr = gfi_ptr->ctrs;
693 for (i = 0; i < GCOV_COUNTERS; i++)
694 {
695 if (!gi_ptr->merge[i])
696 continue;
697 if (i == GCOV_COUNTER_ICALL_TOPNV)
698 {
699 gcov_sort_icall_topn_counter (ci_ptr);
700 break;
701 }
702 ci_ptr++;
703 }
704 }
705}
706
ded3d3f8 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. */
713
714static void
1186f97a 715dump_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)
ded3d3f8 719{
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;
725
726 fn_buffer = 0;
727 sum_buffer = 0;
728
8ceaa1ef 729 gcov_sort_topn_counter_arrays (gi_ptr);
730
ded3d3f8 731 error = gcov_exit_open_gcda_file (gi_ptr, gf);
732 if (error == -1)
733 return;
734
735 tag = gcov_read_unsigned ();
736 if (tag)
737 {
738 /* Merge data from file. */
739 if (tag != GCOV_DATA_MAGIC)
740 {
6401b74d 741 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
ded3d3f8 742 goto read_fatal;
743 }
1186f97a 744 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
745 &summary_pos, &eof_pos, crc32);
ded3d3f8 746 if (error == -1)
747 goto read_fatal;
748 }
749
750 gcov_rewrite ();
751
752 if (!summary_pos)
753 {
754 memset (&prg, 0, sizeof (prg));
755 summary_pos = eof_pos;
756 }
757
5860b185 758 error = merge_summary (gf->filename, run_counted, &prg, this_prg,
1186f97a 759 crc32, all_prg);
ded3d3f8 760 if (error == -1)
761 goto read_fatal;
762
1186f97a 763 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
ded3d3f8 764 /* fall through */
765
766read_fatal:;
767 while (fn_buffer)
768 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
769
770 if ((error = gcov_close ()))
771 gcov_error (error < 0 ?
772 "profiling:%s:Overflow writing\n" :
773 "profiling:%s:Error writing\n",
6401b74d 774 gf->filename);
ded3d3f8 775}
776
777
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. */
781
859fa1a9 782#if !IN_GCOV_TOOL
783static
784#endif
785void
1186f97a 786gcov_do_dump (struct gcov_info *list, int run_counted)
ded3d3f8 787{
788 struct gcov_info *gi_ptr;
6401b74d 789 struct gcov_filename gf;
f75db2a8 790 gcov_unsigned_t crc32;
791 struct gcov_summary all_prg;
b9f9bf68 792 struct gcov_summary this_prg;
ded3d3f8 793
5b24ad4b 794 crc32 = compute_summary (list, &this_prg);
ded3d3f8 795
796 allocate_filename_struct (&gf);
f75db2a8 797#if !GCOV_LOCKED
798 memset (&all_prg, 0, sizeof (all_prg));
799#endif
ded3d3f8 800
801 /* Now merge each file. */
1186f97a 802 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
5b24ad4b 803 {
804 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
805 free (gf.filename);
806 }
ded3d3f8 807
5b24ad4b 808 free (gf.prefix);
ded3d3f8 809}
810
6db59335 811#if IN_GCOV_TOOL
812const char *
813__attribute__ ((unused))
814gcov_get_filename (struct gcov_info *list)
815{
816 return list->filename;
817}
818#endif
819
cb3ea3de 820#if !IN_GCOV_TOOL
1186f97a 821void
859fa1a9 822__gcov_dump_one (struct gcov_root *root)
1186f97a 823{
859fa1a9 824 if (root->dumped)
1186f97a 825 return;
826
859fa1a9 827 gcov_do_dump (root->list, root->run_counted);
1186f97a 828
859fa1a9 829 root->dumped = 1;
830 root->run_counted = 1;
1186f97a 831}
832
bc587267 833/* Per-dynamic-object gcov state. */
859fa1a9 834struct gcov_root __gcov_root;
ded3d3f8 835
bc587267 836/* Exactly one of these will be live in the process image. */
837struct gcov_master __gcov_master =
838 {GCOV_VERSION, 0};
839
db46bcd3 840void
841__gcov_exit (void)
ded3d3f8 842{
859fa1a9 843 __gcov_dump_one (&__gcov_root);
bc587267 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;
3237fc56 850
851 gcov_error_exit ();
ded3d3f8 852}
853
854/* Add a new object file onto the bb chain. Invoked automatically
855 when running an object file's global ctors. */
856
857void
858__gcov_init (struct gcov_info *info)
859{
860 if (!info->version || !info->n_functions)
861 return;
862 if (gcov_version (info, info->version, 0))
863 {
859fa1a9 864 if (!__gcov_root.list)
bc587267 865 {
866 /* Add to master list and at exit function. */
867 if (gcov_version (NULL, __gcov_master.version, "<master>"))
868 {
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;
873 }
bc587267 874 }
ded3d3f8 875
859fa1a9 876 info->next = __gcov_root.list;
877 __gcov_root.list = info;
ded3d3f8 878 }
ded3d3f8 879}
cb3ea3de 880#endif /* !IN_GCOV_TOOL */
ded3d3f8 881#endif /* L_gcov */
882#endif /* inhibit_libc */