]> gcc.gnu.org Git - gcc.git/blob - libgcc/libgcov-driver.c
gcov: dump in a static dtor instead of in an atexit handler
[gcc.git] / libgcc / libgcov-driver.c
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2016 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
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.
11
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.
16
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.
20
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/>. */
25
26 #include "libgcov.h"
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)
32 void __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
45
46 /* A utility function for outputting errors. */
47 static int gcov_error (const char *, ...);
48
49 #if !IN_GCOV_TOOL
50 static void gcov_error_exit (void);
51 #endif
52
53 #include "gcov-io.c"
54
55 struct 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
63 struct gcov_summary_buffer
64 {
65 struct gcov_summary_buffer *next;
66 struct gcov_summary summary;
67 };
68
69 /* A struct that bundles all the related information about the
70 gcda filename. */
71
72 struct 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
80 static struct gcov_fn_buffer *
81 free_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
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)
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;
111 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
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);
138 values = (gcov_type *) xmalloc (len);
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
153 fail:
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
162 static gcov_unsigned_t
163 crc32_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
184 static int
185 gcov_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
204 static void
205 gcov_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
218 static void
219 gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
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. */
245 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
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
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;
276
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. */
280
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)
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;
295 gcov_unsigned_t crc32 = 0;
296
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)
301 {
302 size_t len = strlen (gi_ptr->filename);
303 if (len > *max_length)
304 *max_length = len;
305
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
328 cs_ptr = &(this_prg->ctrs[t_ix]);
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 }
342 gcov_compute_histogram (list, this_prg);
343 return crc32;
344 }
345
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
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)
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 ();
370 if (!gcov_version (gi_ptr, length, filename))
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 *)
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;
406 }
407 if (tmp.checksum != crc32)
408 goto next_summary;
409
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;
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. */
445 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
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",
487 filename, f_ix >= 0 ? "function" : "summary",
488 f_ix < 0 ? -1 - f_ix : f_ix);
489 return -1;
490 }
491 return 0;
492
493 read_error:
494 gcov_error ("profiling:%s:%s merging\n", filename,
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
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)
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
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)))
603 {
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
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]);
615 cs_tprg = &(this_prg->ctrs[t_ix]);
616
617 if (gi_ptr->merge[t_ix])
618 {
619 int first = !cs_prg->runs;
620
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);
634 }
635 else if (cs_prg->runs)
636 {
637 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
638 filename);
639 return -1;
640 }
641 #if !GCOV_LOCKED
642 cs_all = &all_prg->ctrs[t_ix];
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 }
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))
661 {
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;
666 }
667 #endif
668 }
669
670 prg->checksum = crc32;
671
672 return 0;
673 }
674
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
680 GCOV_LINKAGE void
681 gcov_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
706 static void
707 gcov_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
725 static void
726 gcov_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
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
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)
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
776 gcov_sort_topn_counter_arrays (gi_ptr);
777
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 {
788 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
789 goto read_fatal;
790 }
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;
795 }
796
797 gcov_rewrite ();
798
799 if (!summary_pos)
800 {
801 memset (&prg, 0, sizeof (prg));
802 summary_pos = eof_pos;
803 }
804
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;
809
810 write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
811 /* fall through */
812
813 read_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",
821 gf->filename);
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
829 #if !IN_GCOV_TOOL
830 static
831 #endif
832 void
833 gcov_do_dump (struct gcov_info *list, int run_counted)
834 {
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;
840
841 crc32 = compute_summary (list, &this_prg, &gf.max_length);
842
843 allocate_filename_struct (&gf);
844 #if !GCOV_LOCKED
845 memset (&all_prg, 0, sizeof (all_prg));
846 #endif
847
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);
851
852 free (gf.filename);
853 }
854
855 #if !IN_GCOV_TOOL
856 void
857 __gcov_dump_one (struct gcov_root *root)
858 {
859 if (root->dumped)
860 return;
861
862 gcov_do_dump (root->list, root->run_counted);
863
864 root->dumped = 1;
865 root->run_counted = 1;
866 }
867
868 /* Per-dynamic-object gcov state. */
869 struct gcov_root __gcov_root;
870
871 /* Exactly one of these will be live in the process image. */
872 struct gcov_master __gcov_master =
873 {GCOV_VERSION, 0};
874
875 void
876 __gcov_exit (void)
877 {
878 __gcov_dump_one (&__gcov_root);
879 if (__gcov_root.next)
880 __gcov_root.next->prev = __gcov_root.prev;
881 if (__gcov_root.prev)
882 __gcov_root.prev->next = __gcov_root.next;
883 else
884 __gcov_master.root = __gcov_root.next;
885
886 gcov_error_exit ();
887 }
888
889 /* Add a new object file onto the bb chain. Invoked automatically
890 when running an object file's global ctors. */
891
892 void
893 __gcov_init (struct gcov_info *info)
894 {
895 if (!info->version || !info->n_functions)
896 return;
897 if (gcov_version (info, info->version, 0))
898 {
899 if (!__gcov_root.list)
900 {
901 /* Add to master list and at exit function. */
902 if (gcov_version (NULL, __gcov_master.version, "<master>"))
903 {
904 __gcov_root.next = __gcov_master.root;
905 if (__gcov_master.root)
906 __gcov_master.root->prev = &__gcov_root;
907 __gcov_master.root = &__gcov_root;
908 }
909 }
910
911 info->next = __gcov_root.list;
912 __gcov_root.list = info;
913 }
914 }
915 #endif /* !IN_GCOV_TOOL */
916 #endif /* L_gcov */
917 #endif /* inhibit_libc */
This page took 0.087599 seconds and 6 git commands to generate.