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