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