]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/libgcov-driver.c
Update copyright years.
[thirdparty/gcc.git] / libgcc / libgcov-driver.c
CommitLineData
d6d3f033
RX
1/* Routines required for instrumenting a program. */
2/* Compile this one with gcc. */
85ec4feb 3/* Copyright (C) 1989-2018 Free Software Foundation, Inc.
d6d3f033
RX
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
40d6b753 26#include "libgcov.h"
d6d3f033
RX
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
e3f0315f 45
8aa5bdd6 46/* A utility function for outputting errors. */
e3f0315f
TJ
47static int gcov_error (const char *, ...);
48
8aa5bdd6
AC
49#if !IN_GCOV_TOOL
50static void gcov_error_exit (void);
51#endif
52
d6d3f033
RX
53#include "gcov-io.c"
54
d6d3f033
RX
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
6dc33097
NS
69/* A struct that bundles all the related information about the
70 gcda filename. */
71
72struct gcov_filename
73{
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 */
78};
79
d6d3f033
RX
80static struct gcov_fn_buffer *
81free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
82 unsigned limit)
83{
84 struct gcov_fn_buffer *next;
85 unsigned ix, n_ctr = 0;
86
87 if (!buffer)
88 return 0;
89 next = buffer->next;
90
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;
96}
97
98static struct gcov_fn_buffer **
99buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
100 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
101{
102 unsigned n_ctrs = 0, ix = 0;
103 struct gcov_fn_buffer *fn_buffer;
104 unsigned len;
105
106 for (ix = GCOV_COUNTERS; ix--;)
107 if (gi_ptr->merge[ix])
108 n_ctrs++;
109
110 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
40d6b753 111 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
d6d3f033
RX
112
113 if (!fn_buffer)
114 goto fail;
115
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 ();
121
122 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
123 {
124 gcov_unsigned_t length;
125 gcov_type *values;
126
127 if (!gi_ptr->merge[ix])
128 continue;
129
130 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
131 {
132 len = 0;
133 goto fail;
134 }
135
136 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
137 len = length * sizeof (gcov_type);
40d6b753 138 values = (gcov_type *) xmalloc (len);
d6d3f033
RX
139 if (!values)
140 goto fail;
141
142 fn_buffer->info.ctrs[n_ctrs].num = length;
143 fn_buffer->info.ctrs[n_ctrs].values = values;
144
145 while (length--)
146 *values++ = gcov_read_counter ();
147 n_ctrs++;
148 }
149
150 *end_ptr = fn_buffer;
151 return &fn_buffer->next;
152
153fail:
154 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
155 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
156
157 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
158}
159
160/* Add an unsigned value to the current crc */
161
162static gcov_unsigned_t
163crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
164{
165 unsigned ix;
166
167 for (ix = 32; ix--; value <<= 1)
168 {
169 unsigned feedback;
170
171 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
172 crc32 <<= 1;
173 crc32 ^= feedback;
174 }
175
176 return crc32;
177}
178
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. */
183
184static int
185gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
186 const char *filename)
187{
188 if (version != GCOV_VERSION)
189 {
190 char v[4], e[4];
191
192 GCOV_UNSIGNED2STRING (v, version);
193 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
194
195 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
196 filename? filename : ptr->filename, e, v);
197 return 0;
198 }
199 return 1;
200}
201
202/* Insert counter VALUE into HISTOGRAM. */
203
204static void
205gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
206{
207 unsigned i;
208
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;
214}
215
216/* Computes a histogram of the arc counters to place in the summary SUM. */
217
218static void
4303c581 219gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
d6d3f033
RX
220{
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;
227
228 /* This currently only applies to arc counters. */
229 t_ix = GCOV_COUNTER_ARCS;
230
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;
235
236 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
237 {
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;
241 }
242
243 /* Walk through all the per-object structures and record each of
244 the count values in histogram. */
4303c581 245 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
d6d3f033
RX
246 {
247 if (!gi_ptr->merge[t_ix])
248 continue;
249
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++)
254 {
255 if (gi_ptr->merge[ix])
256 ctr_info_ix++;
257 }
258 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
259 {
260 gfi_ptr = gi_ptr->functions[f_ix];
261
262 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
263 continue;
264
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]);
268 }
269 }
270}
271
d6d3f033
RX
272/* buffer for the fn_data from another program. */
273static struct gcov_fn_buffer *fn_buffer;
274/* buffer for summary from other programs to be written out. */
275static struct gcov_summary_buffer *sum_buffer;
276
6dc33097
NS
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. */
d6d3f033 280
9b84e7a8
RX
281#if !IN_GCOV_TOOL
282static
283#endif
284gcov_unsigned_t
19926161
NS
285compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
286 size_t *max_length)
d6d3f033
RX
287{
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;
867c8b03 295 gcov_unsigned_t crc32 = 0;
d6d3f033 296
d6d3f033 297 /* Find the totals for this execution. */
2c973ee7 298 memset (this_prg, 0, sizeof (*this_prg));
6dc33097 299 *max_length = 0;
19926161 300 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
d6d3f033 301 {
6dc33097
NS
302 size_t len = strlen (gi_ptr->filename);
303 if (len > *max_length)
304 *max_length = len;
305
d6d3f033
RX
306 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
307 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
308
309 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
310 {
311 gfi_ptr = gi_ptr->functions[f_ix];
312
313 if (gfi_ptr && gfi_ptr->key != gi_ptr)
314 gfi_ptr = 0;
315
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;
321
322 ci_ptr = gfi_ptr->ctrs;
323 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
324 {
325 if (!gi_ptr->merge[t_ix])
326 continue;
327
2c973ee7 328 cs_ptr = &(this_prg->ctrs[t_ix]);
d6d3f033
RX
329 cs_ptr->num += ci_ptr->num;
330 crc32 = crc32_unsigned (crc32, ci_ptr->num);
331
332 for (c_num = 0; c_num < ci_ptr->num; c_num++)
333 {
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];
337 }
338 ci_ptr++;
339 }
340 }
341 }
4303c581 342 gcov_compute_histogram (list, this_prg);
867c8b03 343 return crc32;
d6d3f033
RX
344}
345
d6d3f033
RX
346/* Including system dependent components. */
347#include "libgcov-driver-system.c"
348
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. */
352
353static int
19926161
NS
354merge_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)
d6d3f033
RX
361{
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;
368
369 length = gcov_read_unsigned ();
6dc33097 370 if (!gcov_version (gi_ptr, length, filename))
d6d3f033
RX
371 return -1;
372
373 length = gcov_read_unsigned ();
374 if (length != gi_ptr->stamp)
375 /* Read from a different compilation. Overwrite the file. */
376 return 0;
377
378 /* Look for program summary. */
379 for (f_ix = 0;;)
380 {
381 struct gcov_summary tmp;
382
383 *eof_pos_p = gcov_position ();
384 tag = gcov_read_unsigned ();
385 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
386 break;
387
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)
394 {
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 *)
40d6b753 401 xmalloc (sizeof(struct gcov_summary_buffer));
d6d3f033
RX
402 (*sum_tail)->summary = tmp;
403 (*sum_tail)->next = 0;
404 sum_tail = &((*sum_tail)->next);
405 goto next_summary;
406 }
407 if (tmp.checksum != crc32)
408 goto next_summary;
409
410 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
2c973ee7 411 if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
d6d3f033
RX
412 goto next_summary;
413 *prg_p = tmp;
414 *summary_pos_p = *eof_pos_p;
415
416 next_summary:;
417 }
418
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 ())
422 {
423 const struct gcov_ctr_info *ci_ptr;
424 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
425
426 if (tag != GCOV_TAG_FUNCTION)
427 goto read_mismatch;
428
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;
434
435 if (length != GCOV_TAG_FUNCTION_LENGTH)
436 goto read_mismatch;
437
438 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
439 {
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. */
6dc33097 445 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
d6d3f033
RX
446 if (!fn_tail)
447 goto read_mismatch;
448 continue;
449 }
450
451 length = gcov_read_unsigned ();
452 if (length != gfi_ptr->ident)
453 goto read_mismatch;
454
455 length = gcov_read_unsigned ();
456 if (length != gfi_ptr->lineno_checksum)
457 goto read_mismatch;
458
459 length = gcov_read_unsigned ();
460 if (length != gfi_ptr->cfg_checksum)
461 goto read_mismatch;
462
463 ci_ptr = gfi_ptr->ctrs;
464 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
465 {
466 gcov_merge_fn merge = gi_ptr->merge[t_ix];
467
468 if (!merge)
469 continue;
470
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++;
478 }
479 if ((error = gcov_is_error ()))
480 goto read_error;
481 }
482
483 if (tag)
484 {
485 read_mismatch:;
486 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
6dc33097 487 filename, f_ix >= 0 ? "function" : "summary",
d6d3f033
RX
488 f_ix < 0 ? -1 - f_ix : f_ix);
489 return -1;
490 }
491 return 0;
492
493read_error:
6dc33097 494 gcov_error ("profiling:%s:%s merging\n", filename,
d6d3f033
RX
495 error < 0 ? "Overflow": "Error");
496 return -1;
497}
498
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. */
502
503static void
19926161
NS
504write_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)
d6d3f033
RX
508{
509 unsigned f_ix;
510 struct gcov_summary_buffer *next_sum_buffer;
511
512 /* Write out the data. */
513 if (!eof_pos)
514 {
515 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
516 gcov_write_unsigned (gi_ptr->stamp);
517 }
518
519 if (summary_pos)
520 gcov_seek (summary_pos);
521
522 /* Generate whole program statistics. */
523 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
524
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. */
529
530 while (sum_buffer)
531 {
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;
536 }
537
538 /* Write execution counts for each function. */
539 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
540 {
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;
546
547 if (fn_buffer && fn_buffer->fn_ix == f_ix)
548 {
549 /* Buffered data from another program. */
550 buffered = 1;
551 gfi_ptr = &fn_buffer->info;
552 length = GCOV_TAG_FUNCTION_LENGTH;
553 }
554 else
555 {
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;
561 }
562
563 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
564 if (!length)
565 continue;
566
567 gcov_write_unsigned (gfi_ptr->ident);
568 gcov_write_unsigned (gfi_ptr->lineno_checksum);
569 gcov_write_unsigned (gfi_ptr->cfg_checksum);
570
571 ci_ptr = gfi_ptr->ctrs;
572 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
573 {
574 gcov_unsigned_t n_counts;
575 gcov_type *c_ptr;
576
577 if (!gi_ptr->merge[t_ix])
578 continue;
579
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++;
587 }
588 if (buffered)
589 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
590 }
591
592 gcov_write_unsigned (0);
593}
594
595/* Helper function for merging summary.
596 Return -1 on error. Return 0 on success. */
597
598static int
19926161
NS
599merge_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)))
d6d3f033
RX
603{
604 struct gcov_ctr_summary *cs_prg, *cs_tprg;
d6d3f033 605 unsigned t_ix;
867c8b03
JH
606#if !GCOV_LOCKED
607 /* summary for all instances of program. */
608 struct gcov_ctr_summary *cs_all;
609#endif
d6d3f033
RX
610
611 /* Merge the summaries. */
612 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
613 {
614 cs_prg = &(prg->ctrs[t_ix]);
2c973ee7 615 cs_tprg = &(this_prg->ctrs[t_ix]);
d6d3f033
RX
616
617 if (gi_ptr->merge[t_ix])
618 {
867c8b03
JH
619 int first = !cs_prg->runs;
620
19926161 621 if (!run_counted)
867c8b03 622 cs_prg->runs++;
867c8b03 623 if (first)
d6d3f033
RX
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;
867c8b03 629 if (first)
d6d3f033
RX
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);
634 }
635 else if (cs_prg->runs)
636 {
637 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
6dc33097 638 filename);
d6d3f033
RX
639 return -1;
640 }
d6d3f033 641#if !GCOV_LOCKED
867c8b03 642 cs_all = &all_prg->ctrs[t_ix];
d6d3f033
RX
643 if (!cs_all->runs && cs_prg->runs)
644 {
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;
650 }
867c8b03 651 else if (!all_prg->checksum
d6d3f033
RX
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))
661 {
662 gcov_error ("profiling:%s:Data file mismatch - some "
663 "data files may have been concurrently "
6dc33097 664 "updated without locking support\n", filename);
867c8b03 665 all_prg->checksum = ~0u;
d6d3f033
RX
666 }
667#endif
668 }
40d6b753 669
d6d3f033
RX
670 prg->checksum = crc32;
671
672 return 0;
673}
674
afe0c5ee
RX
675
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. */
679
680GCOV_LINKAGE void
681gcov_sort_n_vals (gcov_type *value_array, int n)
682{
683 int j, k;
684
685 for (j = 2; j < n; j += 2)
686 {
687 gcov_type cur_ent[2];
688
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])
693 {
694 value_array[k + 2] = value_array[k];
695 value_array[k + 3] = value_array[k+1];
696 k -= 2;
697 }
698 value_array[k + 2] = cur_ent[0];
699 value_array[k + 3] = cur_ent[1];
700 }
701}
702
703/* Sort the profile counters for all indirect call sites. Counters
704 for each call site are allocated in array COUNTERS. */
705
706static void
707gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
708{
709 int i;
710 gcov_type *values;
711 int n = counters->num;
712
713 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
714 values = counters->values;
715
716 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
717 {
718 gcov_type *value_array = &values[i + 1];
719 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
720 }
721}
722
723/* Sort topn indirect_call profile counters in GI_PTR. */
724
725static void
726gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
727{
728 unsigned int i;
729 int f_ix;
730 const struct gcov_fn_info *gfi_ptr;
731 const struct gcov_ctr_info *ci_ptr;
732
733 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
734 return;
735
736 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
737 {
738 gfi_ptr = gi_ptr->functions[f_ix];
739 ci_ptr = gfi_ptr->ctrs;
740 for (i = 0; i < GCOV_COUNTERS; i++)
741 {
742 if (!gi_ptr->merge[i])
743 continue;
744 if (i == GCOV_COUNTER_ICALL_TOPNV)
745 {
746 gcov_sort_icall_topn_counter (ci_ptr);
747 break;
748 }
749 ci_ptr++;
750 }
751 }
752}
753
d6d3f033
RX
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. */
760
761static void
19926161
NS
762dump_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)
d6d3f033
RX
766{
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;
772
773 fn_buffer = 0;
774 sum_buffer = 0;
775
afe0c5ee
RX
776 gcov_sort_topn_counter_arrays (gi_ptr);
777
d6d3f033
RX
778 error = gcov_exit_open_gcda_file (gi_ptr, gf);
779 if (error == -1)
780 return;
781
782 tag = gcov_read_unsigned ();
783 if (tag)
784 {
785 /* Merge data from file. */
786 if (tag != GCOV_DATA_MAGIC)
787 {
6dc33097 788 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
d6d3f033
RX
789 goto read_fatal;
790 }
19926161
NS
791 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
792 &summary_pos, &eof_pos, crc32);
d6d3f033
RX
793 if (error == -1)
794 goto read_fatal;
795 }
796
797 gcov_rewrite ();
798
799 if (!summary_pos)
800 {
801 memset (&prg, 0, sizeof (prg));
802 summary_pos = eof_pos;
803 }
804
19926161
NS
805 error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
806 crc32, all_prg);
d6d3f033
RX
807 if (error == -1)
808 goto read_fatal;
809
19926161 810 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
d6d3f033
RX
811 /* fall through */
812
813read_fatal:;
814 while (fn_buffer)
815 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
816
817 if ((error = gcov_close ()))
818 gcov_error (error < 0 ?
819 "profiling:%s:Overflow writing\n" :
820 "profiling:%s:Error writing\n",
6dc33097 821 gf->filename);
d6d3f033
RX
822}
823
824
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. */
828
4303c581
NS
829#if !IN_GCOV_TOOL
830static
831#endif
832void
19926161 833gcov_do_dump (struct gcov_info *list, int run_counted)
d6d3f033
RX
834{
835 struct gcov_info *gi_ptr;
6dc33097 836 struct gcov_filename gf;
867c8b03
JH
837 gcov_unsigned_t crc32;
838 struct gcov_summary all_prg;
2c973ee7 839 struct gcov_summary this_prg;
d6d3f033 840
19926161 841 crc32 = compute_summary (list, &this_prg, &gf.max_length);
d6d3f033
RX
842
843 allocate_filename_struct (&gf);
867c8b03
JH
844#if !GCOV_LOCKED
845 memset (&all_prg, 0, sizeof (all_prg));
846#endif
d6d3f033
RX
847
848 /* Now merge each file. */
19926161
NS
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);
d6d3f033 851
6dc33097 852 free (gf.filename);
d6d3f033
RX
853}
854
63971184
ML
855#if IN_GCOV_TOOL
856const char *
857__attribute__ ((unused))
858gcov_get_filename (struct gcov_info *list)
859{
860 return list->filename;
861}
862#endif
863
b98a872b 864#if !IN_GCOV_TOOL
19926161 865void
4303c581 866__gcov_dump_one (struct gcov_root *root)
19926161 867{
4303c581 868 if (root->dumped)
19926161
NS
869 return;
870
4303c581 871 gcov_do_dump (root->list, root->run_counted);
19926161 872
4303c581
NS
873 root->dumped = 1;
874 root->run_counted = 1;
19926161
NS
875}
876
cadb2b96 877/* Per-dynamic-object gcov state. */
4303c581 878struct gcov_root __gcov_root;
d6d3f033 879
cadb2b96
NS
880/* Exactly one of these will be live in the process image. */
881struct gcov_master __gcov_master =
882 {GCOV_VERSION, 0};
883
8c9434c2
ML
884void
885__gcov_exit (void)
d6d3f033 886{
4303c581 887 __gcov_dump_one (&__gcov_root);
cadb2b96
NS
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;
8aa5bdd6
AC
894
895 gcov_error_exit ();
d6d3f033
RX
896}
897
898/* Add a new object file onto the bb chain. Invoked automatically
899 when running an object file's global ctors. */
900
901void
902__gcov_init (struct gcov_info *info)
903{
904 if (!info->version || !info->n_functions)
905 return;
906 if (gcov_version (info, info->version, 0))
907 {
4303c581 908 if (!__gcov_root.list)
cadb2b96
NS
909 {
910 /* Add to master list and at exit function. */
911 if (gcov_version (NULL, __gcov_master.version, "<master>"))
912 {
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;
917 }
cadb2b96 918 }
d6d3f033 919
4303c581
NS
920 info->next = __gcov_root.list;
921 __gcov_root.list = info;
d6d3f033 922 }
d6d3f033 923}
b98a872b 924#endif /* !IN_GCOV_TOOL */
d6d3f033
RX
925#endif /* L_gcov */
926#endif /* inhibit_libc */