gcov-io.c (gcov_position): Use gcov_nonruntime_assert.
[gcc.git] / libgcc / libgcov-driver.c
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2014 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 outputing errors. */
47 static int gcov_error (const char *, ...);
48
49 #include "gcov-io.c"
50
51 /* The following functions can be called from outside of this file. */
52 extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
53 extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
54 extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
55 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
56 extern int get_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
57 extern void set_gcov_list (struct gcov_info *) ATTRIBUTE_HIDDEN;
58
59 struct gcov_fn_buffer
60 {
61 struct gcov_fn_buffer *next;
62 unsigned fn_ix;
63 struct gcov_fn_info info;
64 /* note gcov_fn_info ends in a trailing array. */
65 };
66
67 struct gcov_summary_buffer
68 {
69 struct gcov_summary_buffer *next;
70 struct gcov_summary summary;
71 };
72
73 /* Chain of per-object gcov structures. */
74 static struct gcov_info *gcov_list;
75
76 /* Set the head of gcov_list. */
77 void
78 set_gcov_list (struct gcov_info *head)
79 {
80 gcov_list = head;
81 }
82
83 /* Size of the longest file name. */
84 static size_t gcov_max_filename = 0;
85
86 /* Flag when the profile has already been dumped via __gcov_dump(). */
87 static int gcov_dump_complete;
88
89 /* A global function that get the vaule of gcov_dump_complete. */
90
91 int
92 get_gcov_dump_complete (void)
93 {
94 return gcov_dump_complete;
95 }
96
97 /* A global functino that set the vaule of gcov_dump_complete. Will
98 be used in __gcov_dump() in libgcov-interface.c. */
99
100 void
101 set_gcov_dump_complete (void)
102 {
103 gcov_dump_complete = 1;
104 }
105
106 /* A global functino that set the vaule of gcov_dump_complete. Will
107 be used in __gcov_reset() in libgcov-interface.c. */
108
109 void
110 reset_gcov_dump_complete (void)
111 {
112 gcov_dump_complete = 0;
113 }
114
115 static struct gcov_fn_buffer *
116 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
117 unsigned limit)
118 {
119 struct gcov_fn_buffer *next;
120 unsigned ix, n_ctr = 0;
121
122 if (!buffer)
123 return 0;
124 next = buffer->next;
125
126 for (ix = 0; ix != limit; ix++)
127 if (gi_ptr->merge[ix])
128 free (buffer->info.ctrs[n_ctr++].values);
129 free (buffer);
130 return next;
131 }
132
133 static struct gcov_fn_buffer **
134 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
135 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
136 {
137 unsigned n_ctrs = 0, ix = 0;
138 struct gcov_fn_buffer *fn_buffer;
139 unsigned len;
140
141 for (ix = GCOV_COUNTERS; ix--;)
142 if (gi_ptr->merge[ix])
143 n_ctrs++;
144
145 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
146 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
147
148 if (!fn_buffer)
149 goto fail;
150
151 fn_buffer->next = 0;
152 fn_buffer->fn_ix = fn_ix;
153 fn_buffer->info.ident = gcov_read_unsigned ();
154 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
155 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
156
157 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
158 {
159 gcov_unsigned_t length;
160 gcov_type *values;
161
162 if (!gi_ptr->merge[ix])
163 continue;
164
165 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
166 {
167 len = 0;
168 goto fail;
169 }
170
171 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
172 len = length * sizeof (gcov_type);
173 values = (gcov_type *) xmalloc (len);
174 if (!values)
175 goto fail;
176
177 fn_buffer->info.ctrs[n_ctrs].num = length;
178 fn_buffer->info.ctrs[n_ctrs].values = values;
179
180 while (length--)
181 *values++ = gcov_read_counter ();
182 n_ctrs++;
183 }
184
185 *end_ptr = fn_buffer;
186 return &fn_buffer->next;
187
188 fail:
189 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
190 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
191
192 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
193 }
194
195 /* Add an unsigned value to the current crc */
196
197 static gcov_unsigned_t
198 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
199 {
200 unsigned ix;
201
202 for (ix = 32; ix--; value <<= 1)
203 {
204 unsigned feedback;
205
206 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
207 crc32 <<= 1;
208 crc32 ^= feedback;
209 }
210
211 return crc32;
212 }
213
214 /* Check if VERSION of the info block PTR matches libgcov one.
215 Return 1 on success, or zero in case of versions mismatch.
216 If FILENAME is not NULL, its value used for reporting purposes
217 instead of value from the info block. */
218
219 static int
220 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
221 const char *filename)
222 {
223 if (version != GCOV_VERSION)
224 {
225 char v[4], e[4];
226
227 GCOV_UNSIGNED2STRING (v, version);
228 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
229
230 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
231 filename? filename : ptr->filename, e, v);
232 return 0;
233 }
234 return 1;
235 }
236
237 /* Insert counter VALUE into HISTOGRAM. */
238
239 static void
240 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
241 {
242 unsigned i;
243
244 i = gcov_histo_index(value);
245 histogram[i].num_counters++;
246 histogram[i].cum_value += value;
247 if (value < histogram[i].min_value)
248 histogram[i].min_value = value;
249 }
250
251 /* Computes a histogram of the arc counters to place in the summary SUM. */
252
253 static void
254 gcov_compute_histogram (struct gcov_summary *sum)
255 {
256 struct gcov_info *gi_ptr;
257 const struct gcov_fn_info *gfi_ptr;
258 const struct gcov_ctr_info *ci_ptr;
259 struct gcov_ctr_summary *cs_ptr;
260 unsigned t_ix, f_ix, ctr_info_ix, ix;
261 int h_ix;
262
263 /* This currently only applies to arc counters. */
264 t_ix = GCOV_COUNTER_ARCS;
265
266 /* First check if there are any counts recorded for this counter. */
267 cs_ptr = &(sum->ctrs[t_ix]);
268 if (!cs_ptr->num)
269 return;
270
271 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
272 {
273 cs_ptr->histogram[h_ix].num_counters = 0;
274 cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
275 cs_ptr->histogram[h_ix].cum_value = 0;
276 }
277
278 /* Walk through all the per-object structures and record each of
279 the count values in histogram. */
280 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
281 {
282 if (!gi_ptr->merge[t_ix])
283 continue;
284
285 /* Find the appropriate index into the gcov_ctr_info array
286 for the counter we are currently working on based on the
287 existence of the merge function pointer for this object. */
288 for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
289 {
290 if (gi_ptr->merge[ix])
291 ctr_info_ix++;
292 }
293 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
294 {
295 gfi_ptr = gi_ptr->functions[f_ix];
296
297 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
298 continue;
299
300 ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
301 for (ix = 0; ix < ci_ptr->num; ix++)
302 gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
303 }
304 }
305 }
306
307 /* gcda filename. */
308 static char *gi_filename;
309 /* buffer for the fn_data from another program. */
310 static struct gcov_fn_buffer *fn_buffer;
311 /* buffer for summary from other programs to be written out. */
312 static struct gcov_summary_buffer *sum_buffer;
313 /* If application calls fork or exec multiple times, we end up storing
314 profile repeadely. We should not account this as multiple runs or
315 functions executed once may mistakely become cold. */
316 static int run_accounted = 0;
317
318 /* This funtions computes the program level summary and the histo-gram.
319 It computes and returns CRC32 and stored summary in THIS_PRG. */
320
321 static gcov_unsigned_t
322 gcov_exit_compute_summary (struct gcov_summary *this_prg)
323 {
324 struct gcov_info *gi_ptr;
325 const struct gcov_fn_info *gfi_ptr;
326 struct gcov_ctr_summary *cs_ptr;
327 const struct gcov_ctr_info *ci_ptr;
328 int f_ix;
329 unsigned t_ix;
330 gcov_unsigned_t c_num;
331 gcov_unsigned_t crc32 = 0;
332
333 /* Find the totals for this execution. */
334 memset (this_prg, 0, sizeof (*this_prg));
335 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
336 {
337 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
338 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
339
340 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
341 {
342 gfi_ptr = gi_ptr->functions[f_ix];
343
344 if (gfi_ptr && gfi_ptr->key != gi_ptr)
345 gfi_ptr = 0;
346
347 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
348 crc32 = crc32_unsigned (crc32,
349 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
350 if (!gfi_ptr)
351 continue;
352
353 ci_ptr = gfi_ptr->ctrs;
354 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
355 {
356 if (!gi_ptr->merge[t_ix])
357 continue;
358
359 cs_ptr = &(this_prg->ctrs[t_ix]);
360 cs_ptr->num += ci_ptr->num;
361 crc32 = crc32_unsigned (crc32, ci_ptr->num);
362
363 for (c_num = 0; c_num < ci_ptr->num; c_num++)
364 {
365 cs_ptr->sum_all += ci_ptr->values[c_num];
366 if (cs_ptr->run_max < ci_ptr->values[c_num])
367 cs_ptr->run_max = ci_ptr->values[c_num];
368 }
369 ci_ptr++;
370 }
371 }
372 }
373 gcov_compute_histogram (this_prg);
374 return crc32;
375 }
376
377 /* A struct that bundles all the related information about the
378 gcda filename. */
379 struct gcov_filename_aux{
380 char *gi_filename_up;
381 int gcov_prefix_strip;
382 size_t prefix_length;
383 };
384
385 /* Including system dependent components. */
386 #include "libgcov-driver-system.c"
387
388 /* This function merges counters in GI_PTR to an existing gcda file.
389 Return 0 on success.
390 Return -1 on error. In this case, caller will goto read_fatal. */
391
392 static int
393 gcov_exit_merge_gcda (struct gcov_info *gi_ptr,
394 struct gcov_summary *prg_p,
395 struct gcov_summary *this_prg,
396 gcov_position_t *summary_pos_p,
397 gcov_position_t *eof_pos_p,
398 gcov_unsigned_t crc32)
399 {
400 gcov_unsigned_t tag, length;
401 unsigned t_ix;
402 int f_ix;
403 int error = 0;
404 struct gcov_fn_buffer **fn_tail = &fn_buffer;
405 struct gcov_summary_buffer **sum_tail = &sum_buffer;
406
407 length = gcov_read_unsigned ();
408 if (!gcov_version (gi_ptr, length, gi_filename))
409 return -1;
410
411 length = gcov_read_unsigned ();
412 if (length != gi_ptr->stamp)
413 /* Read from a different compilation. Overwrite the file. */
414 return 0;
415
416 /* Look for program summary. */
417 for (f_ix = 0;;)
418 {
419 struct gcov_summary tmp;
420
421 *eof_pos_p = gcov_position ();
422 tag = gcov_read_unsigned ();
423 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
424 break;
425
426 f_ix--;
427 length = gcov_read_unsigned ();
428 gcov_read_summary (&tmp);
429 if ((error = gcov_is_error ()))
430 goto read_error;
431 if (*summary_pos_p)
432 {
433 /* Save all summaries after the one that will be
434 merged into below. These will need to be rewritten
435 as histogram merging may change the number of non-zero
436 histogram entries that will be emitted, and thus the
437 size of the merged summary. */
438 (*sum_tail) = (struct gcov_summary_buffer *)
439 xmalloc (sizeof(struct gcov_summary_buffer));
440 (*sum_tail)->summary = tmp;
441 (*sum_tail)->next = 0;
442 sum_tail = &((*sum_tail)->next);
443 goto next_summary;
444 }
445 if (tmp.checksum != crc32)
446 goto next_summary;
447
448 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
449 if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
450 goto next_summary;
451 *prg_p = tmp;
452 *summary_pos_p = *eof_pos_p;
453
454 next_summary:;
455 }
456
457 /* Merge execution counts for each function. */
458 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
459 f_ix++, tag = gcov_read_unsigned ())
460 {
461 const struct gcov_ctr_info *ci_ptr;
462 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
463
464 if (tag != GCOV_TAG_FUNCTION)
465 goto read_mismatch;
466
467 length = gcov_read_unsigned ();
468 if (!length)
469 /* This function did not appear in the other program.
470 We have nothing to merge. */
471 continue;
472
473 if (length != GCOV_TAG_FUNCTION_LENGTH)
474 goto read_mismatch;
475
476 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
477 {
478 /* This function appears in the other program. We
479 need to buffer the information in order to write
480 it back out -- we'll be inserting data before
481 this point, so cannot simply keep the data in the
482 file. */
483 fn_tail = buffer_fn_data (gi_filename,
484 gi_ptr, fn_tail, f_ix);
485 if (!fn_tail)
486 goto read_mismatch;
487 continue;
488 }
489
490 length = gcov_read_unsigned ();
491 if (length != gfi_ptr->ident)
492 goto read_mismatch;
493
494 length = gcov_read_unsigned ();
495 if (length != gfi_ptr->lineno_checksum)
496 goto read_mismatch;
497
498 length = gcov_read_unsigned ();
499 if (length != gfi_ptr->cfg_checksum)
500 goto read_mismatch;
501
502 ci_ptr = gfi_ptr->ctrs;
503 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
504 {
505 gcov_merge_fn merge = gi_ptr->merge[t_ix];
506
507 if (!merge)
508 continue;
509
510 tag = gcov_read_unsigned ();
511 length = gcov_read_unsigned ();
512 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
513 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
514 goto read_mismatch;
515 (*merge) (ci_ptr->values, ci_ptr->num);
516 ci_ptr++;
517 }
518 if ((error = gcov_is_error ()))
519 goto read_error;
520 }
521
522 if (tag)
523 {
524 read_mismatch:;
525 gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
526 gi_filename, f_ix >= 0 ? "function" : "summary",
527 f_ix < 0 ? -1 - f_ix : f_ix);
528 return -1;
529 }
530 return 0;
531
532 read_error:
533 gcov_error ("profiling:%s:%s merging\n", gi_filename,
534 error < 0 ? "Overflow": "Error");
535 return -1;
536 }
537
538 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
539 the case of appending to an existing file, SUMMARY_POS will be non-zero.
540 We will write the file starting from SUMMAY_POS. */
541
542 static void
543 gcov_exit_write_gcda (const struct gcov_info *gi_ptr,
544 const struct gcov_summary *prg_p,
545 const gcov_position_t eof_pos,
546 const gcov_position_t summary_pos)
547 {
548 unsigned f_ix;
549 struct gcov_summary_buffer *next_sum_buffer;
550
551 /* Write out the data. */
552 if (!eof_pos)
553 {
554 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
555 gcov_write_unsigned (gi_ptr->stamp);
556 }
557
558 if (summary_pos)
559 gcov_seek (summary_pos);
560
561 /* Generate whole program statistics. */
562 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
563
564 /* Rewrite all the summaries that were after the summary we merged
565 into. This is necessary as the merged summary may have a different
566 size due to the number of non-zero histogram entries changing after
567 merging. */
568
569 while (sum_buffer)
570 {
571 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
572 next_sum_buffer = sum_buffer->next;
573 free (sum_buffer);
574 sum_buffer = next_sum_buffer;
575 }
576
577 /* Write execution counts for each function. */
578 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
579 {
580 unsigned buffered = 0;
581 const struct gcov_fn_info *gfi_ptr;
582 const struct gcov_ctr_info *ci_ptr;
583 gcov_unsigned_t length;
584 unsigned t_ix;
585
586 if (fn_buffer && fn_buffer->fn_ix == f_ix)
587 {
588 /* Buffered data from another program. */
589 buffered = 1;
590 gfi_ptr = &fn_buffer->info;
591 length = GCOV_TAG_FUNCTION_LENGTH;
592 }
593 else
594 {
595 gfi_ptr = gi_ptr->functions[f_ix];
596 if (gfi_ptr && gfi_ptr->key == gi_ptr)
597 length = GCOV_TAG_FUNCTION_LENGTH;
598 else
599 length = 0;
600 }
601
602 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
603 if (!length)
604 continue;
605
606 gcov_write_unsigned (gfi_ptr->ident);
607 gcov_write_unsigned (gfi_ptr->lineno_checksum);
608 gcov_write_unsigned (gfi_ptr->cfg_checksum);
609
610 ci_ptr = gfi_ptr->ctrs;
611 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
612 {
613 gcov_unsigned_t n_counts;
614 gcov_type *c_ptr;
615
616 if (!gi_ptr->merge[t_ix])
617 continue;
618
619 n_counts = ci_ptr->num;
620 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
621 GCOV_TAG_COUNTER_LENGTH (n_counts));
622 c_ptr = ci_ptr->values;
623 while (n_counts--)
624 gcov_write_counter (*c_ptr++);
625 ci_ptr++;
626 }
627 if (buffered)
628 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
629 }
630
631 gcov_write_unsigned (0);
632 }
633
634 /* Helper function for merging summary.
635 Return -1 on error. Return 0 on success. */
636
637 static int
638 gcov_exit_merge_summary (const struct gcov_info *gi_ptr, struct gcov_summary *prg,
639 struct gcov_summary *this_prg, gcov_unsigned_t crc32,
640 struct gcov_summary *all_prg __attribute__ ((unused)))
641 {
642 struct gcov_ctr_summary *cs_prg, *cs_tprg;
643 unsigned t_ix;
644 #if !GCOV_LOCKED
645 /* summary for all instances of program. */
646 struct gcov_ctr_summary *cs_all;
647 #endif
648
649 /* Merge the summaries. */
650 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
651 {
652 cs_prg = &(prg->ctrs[t_ix]);
653 cs_tprg = &(this_prg->ctrs[t_ix]);
654
655 if (gi_ptr->merge[t_ix])
656 {
657 int first = !cs_prg->runs;
658
659 if (!run_accounted)
660 cs_prg->runs++;
661 if (first)
662 cs_prg->num = cs_tprg->num;
663 cs_prg->sum_all += cs_tprg->sum_all;
664 if (cs_prg->run_max < cs_tprg->run_max)
665 cs_prg->run_max = cs_tprg->run_max;
666 cs_prg->sum_max += cs_tprg->run_max;
667 if (first)
668 memcpy (cs_prg->histogram, cs_tprg->histogram,
669 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
670 else
671 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
672 }
673 else if (cs_prg->runs)
674 {
675 gcov_error ("profiling:%s:Merge mismatch for summary.\n",
676 gi_filename);
677 return -1;
678 }
679 #if !GCOV_LOCKED
680 cs_all = &all_prg->ctrs[t_ix];
681 if (!cs_all->runs && cs_prg->runs)
682 {
683 cs_all->num = cs_prg->num;
684 cs_all->runs = cs_prg->runs;
685 cs_all->sum_all = cs_prg->sum_all;
686 cs_all->run_max = cs_prg->run_max;
687 cs_all->sum_max = cs_prg->sum_max;
688 }
689 else if (!all_prg->checksum
690 /* Don't compare the histograms, which may have slight
691 variations depending on the order they were updated
692 due to the truncating integer divides used in the
693 merge. */
694 && (cs_all->num != cs_prg->num
695 || cs_all->runs != cs_prg->runs
696 || cs_all->sum_all != cs_prg->sum_all
697 || cs_all->run_max != cs_prg->run_max
698 || cs_all->sum_max != cs_prg->sum_max))
699 {
700 gcov_error ("profiling:%s:Data file mismatch - some "
701 "data files may have been concurrently "
702 "updated without locking support\n", gi_filename);
703 all_prg->checksum = ~0u;
704 }
705 #endif
706 }
707
708 prg->checksum = crc32;
709
710 return 0;
711 }
712
713 /* Dump the coverage counts for one gcov_info object. We merge with existing
714 counts when possible, to avoid growing the .da files ad infinitum. We use
715 this program's checksum to make sure we only accumulate whole program
716 statistics to the correct summary. An object file might be embedded
717 in two separate programs, and we must keep the two program
718 summaries separate. */
719
720 static void
721 gcov_exit_dump_gcov (struct gcov_info *gi_ptr, struct gcov_filename_aux *gf,
722 gcov_unsigned_t crc32, struct gcov_summary *all_prg,
723 struct gcov_summary *this_prg)
724 {
725 struct gcov_summary prg; /* summary for this object over all program. */
726 int error;
727 gcov_unsigned_t tag;
728 gcov_position_t summary_pos = 0;
729 gcov_position_t eof_pos = 0;
730
731 fn_buffer = 0;
732 sum_buffer = 0;
733
734 error = gcov_exit_open_gcda_file (gi_ptr, gf);
735 if (error == -1)
736 return;
737
738 tag = gcov_read_unsigned ();
739 if (tag)
740 {
741 /* Merge data from file. */
742 if (tag != GCOV_DATA_MAGIC)
743 {
744 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename);
745 goto read_fatal;
746 }
747 error = gcov_exit_merge_gcda (gi_ptr, &prg, this_prg, &summary_pos, &eof_pos,
748 crc32);
749 if (error == -1)
750 goto read_fatal;
751 }
752
753 gcov_rewrite ();
754
755 if (!summary_pos)
756 {
757 memset (&prg, 0, sizeof (prg));
758 summary_pos = eof_pos;
759 }
760
761 error = gcov_exit_merge_summary (gi_ptr, &prg, this_prg, crc32, all_prg);
762 if (error == -1)
763 goto read_fatal;
764
765 gcov_exit_write_gcda (gi_ptr, &prg, eof_pos, summary_pos);
766 /* fall through */
767
768 read_fatal:;
769 while (fn_buffer)
770 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
771
772 if ((error = gcov_close ()))
773 gcov_error (error < 0 ?
774 "profiling:%s:Overflow writing\n" :
775 "profiling:%s:Error writing\n",
776 gi_filename);
777 }
778
779
780 /* Dump all the coverage counts for the program. It first computes program
781 summary and then traverses gcov_list list and dumps the gcov_info
782 objects one by one. */
783
784 void
785 gcov_exit (void)
786 {
787 struct gcov_info *gi_ptr;
788 struct gcov_filename_aux gf;
789 gcov_unsigned_t crc32;
790 struct gcov_summary all_prg;
791 struct gcov_summary this_prg;
792
793 /* Prevent the counters from being dumped a second time on exit when the
794 application already wrote out the profile using __gcov_dump(). */
795 if (gcov_dump_complete)
796 return;
797
798 crc32 = gcov_exit_compute_summary (&this_prg);
799
800 allocate_filename_struct (&gf);
801 #if !GCOV_LOCKED
802 memset (&all_prg, 0, sizeof (all_prg));
803 #endif
804
805 /* Now merge each file. */
806 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
807 gcov_exit_dump_gcov (gi_ptr, &gf, crc32, &all_prg, &this_prg);
808 run_accounted = 1;
809
810 if (gi_filename)
811 free (gi_filename);
812 }
813
814 /* Reset all counters to zero. */
815
816 void
817 gcov_clear (void)
818 {
819 const struct gcov_info *gi_ptr;
820
821 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
822 {
823 unsigned f_ix;
824
825 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
826 {
827 unsigned t_ix;
828 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
829
830 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
831 continue;
832 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
833 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
834 {
835 if (!gi_ptr->merge[t_ix])
836 continue;
837
838 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
839 ci_ptr++;
840 }
841 }
842 }
843 }
844
845 /* Add a new object file onto the bb chain. Invoked automatically
846 when running an object file's global ctors. */
847
848 void
849 __gcov_init (struct gcov_info *info)
850 {
851 if (!info->version || !info->n_functions)
852 return;
853 if (gcov_version (info, info->version, 0))
854 {
855 size_t filename_length = strlen(info->filename);
856
857 /* Refresh the longest file name information */
858 if (filename_length > gcov_max_filename)
859 gcov_max_filename = filename_length;
860
861 if (!gcov_list)
862 atexit (gcov_exit);
863
864 info->next = gcov_list;
865 gcov_list = info;
866 }
867 info->version = 0;
868 }
869
870 #endif /* L_gcov */
871 #endif /* inhibit_libc */