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