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