* gimple-fold.c (gimple_fold_stmt_to_constant_1): Avoid warning.
[gcc.git] / libgcc / libgcov.c
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011
5 Free Software Foundation, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
22
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
27
28 #include "tconfig.h"
29 #include "tsystem.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "libgcc_tm.h"
33 #include "gthr.h"
34
35 #if defined(inhibit_libc)
36 #define IN_LIBGCOV (-1)
37 #else
38 #define IN_LIBGCOV 1
39 #if defined(L_gcov)
40 #define GCOV_LINKAGE /* nothing */
41 #endif
42 #endif
43 #include "gcov-io.h"
44
45 #if defined(inhibit_libc)
46 /* If libc and its header files are not available, provide dummy functions. */
47
48 #ifdef L_gcov
49 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
50 void __gcov_flush (void) {}
51 #endif
52
53 #ifdef L_gcov_merge_add
54 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
55 unsigned n_counters __attribute__ ((unused))) {}
56 #endif
57
58 #ifdef L_gcov_merge_single
59 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
60 unsigned n_counters __attribute__ ((unused))) {}
61 #endif
62
63 #ifdef L_gcov_merge_delta
64 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
65 unsigned n_counters __attribute__ ((unused))) {}
66 #endif
67
68 #else
69
70 #include <string.h>
71 #if GCOV_LOCKED
72 #include <fcntl.h>
73 #include <errno.h>
74 #include <sys/stat.h>
75 #endif
76
77 #ifdef L_gcov
78 #include "gcov-io.c"
79
80 struct gcov_fn_buffer
81 {
82 struct gcov_fn_buffer *next;
83 unsigned fn_ix;
84 struct gcov_fn_info info;
85 /* note gcov_fn_info ends in a trailing array. */
86 };
87
88 /* Chain of per-object gcov structures. */
89 static struct gcov_info *gcov_list;
90
91 /* Size of the longest file name. */
92 static size_t gcov_max_filename = 0;
93
94 /* Make sure path component of the given FILENAME exists, create
95 missing directories. FILENAME must be writable.
96 Returns zero on success, or -1 if an error occurred. */
97
98 static int
99 create_file_directory (char *filename)
100 {
101 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
102 (void) filename;
103 return -1;
104 #else
105 char *s;
106
107 s = filename;
108
109 if (HAS_DRIVE_SPEC(s))
110 s += 2;
111 if (IS_DIR_SEPARATOR(*s))
112 ++s;
113 for (; *s != '\0'; s++)
114 if (IS_DIR_SEPARATOR(*s))
115 {
116 char sep = *s;
117 *s = '\0';
118
119 /* Try to make directory if it doesn't already exist. */
120 if (access (filename, F_OK) == -1
121 #ifdef TARGET_POSIX_IO
122 && mkdir (filename, 0755) == -1
123 #else
124 && mkdir (filename) == -1
125 #endif
126 /* The directory might have been made by another process. */
127 && errno != EEXIST)
128 {
129 fprintf (stderr, "profiling:%s:Cannot create directory\n",
130 filename);
131 *s = sep;
132 return -1;
133 };
134
135 *s = sep;
136 };
137 return 0;
138 #endif
139 }
140
141 static struct gcov_fn_buffer *
142 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
143 unsigned limit)
144 {
145 struct gcov_fn_buffer *next;
146 unsigned ix, n_ctr = 0;
147
148 if (!buffer)
149 return 0;
150 next = buffer->next;
151
152 for (ix = 0; ix != limit; ix++)
153 if (gi_ptr->merge[ix])
154 free (buffer->info.ctrs[n_ctr++].values);
155 free (buffer);
156 return next;
157 }
158
159 static struct gcov_fn_buffer **
160 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
161 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
162 {
163 unsigned n_ctrs = 0, ix = 0;
164 struct gcov_fn_buffer *fn_buffer;
165 unsigned len;
166
167 for (ix = GCOV_COUNTERS; ix--;)
168 if (gi_ptr->merge[ix])
169 n_ctrs++;
170
171 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
172 fn_buffer = (struct gcov_fn_buffer *)malloc (len);
173
174 if (!fn_buffer)
175 goto fail;
176
177 fn_buffer->next = 0;
178 fn_buffer->fn_ix = fn_ix;
179 fn_buffer->info.ident = gcov_read_unsigned ();
180 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
181 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
182
183 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
184 {
185 gcov_unsigned_t length;
186 gcov_type *values;
187
188 if (!gi_ptr->merge[ix])
189 continue;
190
191 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
192 {
193 len = 0;
194 goto fail;
195 }
196
197 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
198 len = length * sizeof (gcov_type);
199 values = (gcov_type *)malloc (len);
200 if (!values)
201 goto fail;
202
203 fn_buffer->info.ctrs[n_ctrs].num = length;
204 fn_buffer->info.ctrs[n_ctrs].values = values;
205
206 while (length--)
207 *values++ = gcov_read_counter ();
208 n_ctrs++;
209 }
210
211 *end_ptr = fn_buffer;
212 return &fn_buffer->next;
213
214 fail:
215 fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
216 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
217
218 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
219 }
220
221 /* Add an unsigned value to the current crc */
222
223 static gcov_unsigned_t
224 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
225 {
226 unsigned ix;
227
228 for (ix = 32; ix--; value <<= 1)
229 {
230 unsigned feedback;
231
232 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
233 crc32 <<= 1;
234 crc32 ^= feedback;
235 }
236
237 return crc32;
238 }
239
240 /* Check if VERSION of the info block PTR matches libgcov one.
241 Return 1 on success, or zero in case of versions mismatch.
242 If FILENAME is not NULL, its value used for reporting purposes
243 instead of value from the info block. */
244
245 static int
246 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
247 const char *filename)
248 {
249 if (version != GCOV_VERSION)
250 {
251 char v[4], e[4];
252
253 GCOV_UNSIGNED2STRING (v, version);
254 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
255
256 fprintf (stderr,
257 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
258 filename? filename : ptr->filename, e, v);
259 return 0;
260 }
261 return 1;
262 }
263
264 /* Dump the coverage counts. We merge with existing counts when
265 possible, to avoid growing the .da files ad infinitum. We use this
266 program's checksum to make sure we only accumulate whole program
267 statistics to the correct summary. An object file might be embedded
268 in two separate programs, and we must keep the two program
269 summaries separate. */
270
271 static void
272 gcov_exit (void)
273 {
274 struct gcov_info *gi_ptr;
275 const struct gcov_fn_info *gfi_ptr;
276 struct gcov_summary this_prg; /* summary for program. */
277 struct gcov_summary all_prg; /* summary for all instances of program. */
278 struct gcov_ctr_summary *cs_ptr;
279 const struct gcov_ctr_info *ci_ptr;
280 unsigned t_ix;
281 int f_ix;
282 gcov_unsigned_t c_num;
283 const char *gcov_prefix;
284 int gcov_prefix_strip = 0;
285 size_t prefix_length;
286 char *gi_filename, *gi_filename_up;
287 gcov_unsigned_t crc32 = 0;
288
289 memset (&all_prg, 0, sizeof (all_prg));
290 /* Find the totals for this execution. */
291 memset (&this_prg, 0, sizeof (this_prg));
292 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
293 {
294 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
295 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
296
297 for (f_ix = 0; (unsigned)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 gfi_ptr = 0;
303
304 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
305 crc32 = crc32_unsigned (crc32,
306 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
307 if (!gfi_ptr)
308 continue;
309
310 ci_ptr = gfi_ptr->ctrs;
311 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
312 {
313 if (!gi_ptr->merge[t_ix])
314 continue;
315
316 cs_ptr = &this_prg.ctrs[t_ix];
317 cs_ptr->num += ci_ptr->num;
318 crc32 = crc32_unsigned (crc32, ci_ptr->num);
319
320 for (c_num = 0; c_num < ci_ptr->num; c_num++)
321 {
322 cs_ptr->sum_all += ci_ptr->values[c_num];
323 if (cs_ptr->run_max < ci_ptr->values[c_num])
324 cs_ptr->run_max = ci_ptr->values[c_num];
325 }
326 ci_ptr++;
327 }
328 }
329 }
330
331 {
332 /* Check if the level of dirs to strip off specified. */
333 char *tmp = getenv("GCOV_PREFIX_STRIP");
334 if (tmp)
335 {
336 gcov_prefix_strip = atoi (tmp);
337 /* Do not consider negative values. */
338 if (gcov_prefix_strip < 0)
339 gcov_prefix_strip = 0;
340 }
341 }
342
343 /* Get file name relocation prefix. Non-absolute values are ignored. */
344 gcov_prefix = getenv("GCOV_PREFIX");
345 if (gcov_prefix)
346 {
347 prefix_length = strlen(gcov_prefix);
348
349 /* Remove an unnecessary trailing '/' */
350 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
351 prefix_length--;
352 }
353 else
354 prefix_length = 0;
355
356 /* If no prefix was specified and a prefix stip, then we assume
357 relative. */
358 if (gcov_prefix_strip != 0 && prefix_length == 0)
359 {
360 gcov_prefix = ".";
361 prefix_length = 1;
362 }
363 /* Allocate and initialize the filename scratch space plus one. */
364 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
365 if (prefix_length)
366 memcpy (gi_filename, gcov_prefix, prefix_length);
367 gi_filename_up = gi_filename + prefix_length;
368
369 /* Now merge each file. */
370 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
371 {
372 unsigned n_counts;
373 struct gcov_summary prg; /* summary for this object over all
374 program. */
375 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
376 int error = 0;
377 gcov_unsigned_t tag, length;
378 gcov_position_t summary_pos = 0;
379 gcov_position_t eof_pos = 0;
380 const char *fname, *s;
381 struct gcov_fn_buffer *fn_buffer = 0;
382 struct gcov_fn_buffer **fn_tail = &fn_buffer;
383
384 fname = gi_ptr->filename;
385
386 /* Avoid to add multiple drive letters into combined path. */
387 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
388 fname += 2;
389
390 /* Build relocated filename, stripping off leading
391 directories from the initial filename if requested. */
392 if (gcov_prefix_strip > 0)
393 {
394 int level = 0;
395 s = fname;
396 if (IS_DIR_SEPARATOR(*s))
397 ++s;
398
399 /* Skip selected directory levels. */
400 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
401 if (IS_DIR_SEPARATOR(*s))
402 {
403 fname = s;
404 level++;
405 }
406 }
407
408 /* Update complete filename with stripped original. */
409 if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
410 {
411 /* If prefix is given, add directory separator. */
412 strcpy (gi_filename_up, "/");
413 strcpy (gi_filename_up + 1, fname);
414 }
415 else
416 strcpy (gi_filename_up, fname);
417
418 if (!gcov_open (gi_filename))
419 {
420 /* Open failed likely due to missed directory.
421 Create directory and retry to open file. */
422 if (create_file_directory (gi_filename))
423 {
424 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
425 continue;
426 }
427 if (!gcov_open (gi_filename))
428 {
429 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
430 continue;
431 }
432 }
433
434 tag = gcov_read_unsigned ();
435 if (tag)
436 {
437 /* Merge data from file. */
438 if (tag != GCOV_DATA_MAGIC)
439 {
440 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
441 gi_filename);
442 goto read_fatal;
443 }
444 length = gcov_read_unsigned ();
445 if (!gcov_version (gi_ptr, length, gi_filename))
446 goto read_fatal;
447
448 length = gcov_read_unsigned ();
449 if (length != gi_ptr->stamp)
450 /* Read from a different compilation. Overwrite the file. */
451 goto rewrite;
452
453 /* Look for program summary. */
454 for (f_ix = 0;;)
455 {
456 struct gcov_summary tmp;
457
458 eof_pos = gcov_position ();
459 tag = gcov_read_unsigned ();
460 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
461 break;
462
463 f_ix--;
464 length = gcov_read_unsigned ();
465 if (length != GCOV_TAG_SUMMARY_LENGTH)
466 goto read_mismatch;
467 gcov_read_summary (&tmp);
468 if ((error = gcov_is_error ()))
469 goto read_error;
470 if (summary_pos || tmp.checksum != crc32)
471 goto next_summary;
472
473 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
474 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
475 goto next_summary;
476 prg = tmp;
477 summary_pos = eof_pos;
478
479 next_summary:;
480 }
481
482 /* Merge execution counts for each function. */
483 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
484 f_ix++, tag = gcov_read_unsigned ())
485 {
486 gfi_ptr = gi_ptr->functions[f_ix];
487
488 if (tag != GCOV_TAG_FUNCTION)
489 goto read_mismatch;
490
491 length = gcov_read_unsigned ();
492 if (!length)
493 /* This function did not appear in the other program.
494 We have nothing to merge. */
495 continue;
496
497 if (length != GCOV_TAG_FUNCTION_LENGTH)
498 goto read_mismatch;
499
500 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
501 {
502 /* This function appears in the other program. We
503 need to buffer the information in order to write
504 it back out -- we'll be inserting data before
505 this point, so cannot simply keep the data in the
506 file. */
507 fn_tail = buffer_fn_data (gi_filename,
508 gi_ptr, fn_tail, f_ix);
509 if (!fn_tail)
510 goto read_mismatch;
511 continue;
512 }
513
514 length = gcov_read_unsigned ();
515 if (length != gfi_ptr->ident)
516 goto read_mismatch;
517
518 length = gcov_read_unsigned ();
519 if (length != gfi_ptr->lineno_checksum)
520 goto read_mismatch;
521
522 length = gcov_read_unsigned ();
523 if (length != gfi_ptr->cfg_checksum)
524 goto read_mismatch;
525
526 ci_ptr = gfi_ptr->ctrs;
527 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
528 {
529 gcov_merge_fn merge = gi_ptr->merge[t_ix];
530
531 if (!merge)
532 continue;
533
534 tag = gcov_read_unsigned ();
535 length = gcov_read_unsigned ();
536 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
537 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
538 goto read_mismatch;
539 (*merge) (ci_ptr->values, ci_ptr->num);
540 ci_ptr++;
541 }
542 if ((error = gcov_is_error ()))
543 goto read_error;
544 }
545
546 if (tag)
547 {
548 read_mismatch:;
549 fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n",
550 gi_filename, f_ix >= 0 ? "function" : "summary",
551 f_ix < 0 ? -1 - f_ix : f_ix);
552 goto read_fatal;
553 }
554 }
555 goto rewrite;
556
557 read_error:;
558 fprintf (stderr, "profiling:%s:%s merging\n", gi_filename,
559 error < 0 ? "Overflow": "Error");
560
561 goto read_fatal;
562
563 rewrite:;
564 gcov_rewrite ();
565 if (!summary_pos)
566 {
567 memset (&prg, 0, sizeof (prg));
568 summary_pos = eof_pos;
569 }
570
571 /* Merge the summaries. */
572 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
573 {
574 cs_prg = &prg.ctrs[t_ix];
575 cs_tprg = &this_prg.ctrs[t_ix];
576 cs_all = &all_prg.ctrs[t_ix];
577
578 if (gi_ptr->merge[t_ix])
579 {
580 if (!cs_prg->runs++)
581 cs_prg->num = cs_tprg->num;
582 cs_prg->sum_all += cs_tprg->sum_all;
583 if (cs_prg->run_max < cs_tprg->run_max)
584 cs_prg->run_max = cs_tprg->run_max;
585 cs_prg->sum_max += cs_tprg->run_max;
586 }
587 else if (cs_prg->runs)
588 goto read_mismatch;
589
590 if (!cs_all->runs && cs_prg->runs)
591 memcpy (cs_all, cs_prg, sizeof (*cs_all));
592 else if (!all_prg.checksum
593 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
594 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
595 {
596 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
597 gi_filename, GCOV_LOCKED
598 ? "" : " or concurrently updated without locking support");
599 all_prg.checksum = ~0u;
600 }
601 }
602
603 prg.checksum = crc32;
604
605 /* Write out the data. */
606 if (!eof_pos)
607 {
608 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
609 gcov_write_unsigned (gi_ptr->stamp);
610 }
611
612 if (summary_pos)
613 gcov_seek (summary_pos);
614
615 /* Generate whole program statistics. */
616 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg);
617
618 if (summary_pos < eof_pos)
619 gcov_seek (eof_pos);
620
621 /* Write execution counts for each function. */
622 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
623 {
624 unsigned buffered = 0;
625
626 if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix)
627 {
628 /* Buffered data from another program. */
629 buffered = 1;
630 gfi_ptr = &fn_buffer->info;
631 length = GCOV_TAG_FUNCTION_LENGTH;
632 }
633 else
634 {
635 gfi_ptr = gi_ptr->functions[f_ix];
636 if (gfi_ptr && gfi_ptr->key == gi_ptr)
637 length = GCOV_TAG_FUNCTION_LENGTH;
638 else
639 length = 0;
640 }
641
642 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
643 if (!length)
644 continue;
645
646 gcov_write_unsigned (gfi_ptr->ident);
647 gcov_write_unsigned (gfi_ptr->lineno_checksum);
648 gcov_write_unsigned (gfi_ptr->cfg_checksum);
649
650 ci_ptr = gfi_ptr->ctrs;
651 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
652 {
653 if (!gi_ptr->merge[t_ix])
654 continue;
655
656 n_counts = ci_ptr->num;
657 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
658 GCOV_TAG_COUNTER_LENGTH (n_counts));
659 gcov_type *c_ptr = ci_ptr->values;
660 while (n_counts--)
661 gcov_write_counter (*c_ptr++);
662 ci_ptr++;
663 }
664 if (buffered)
665 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
666 }
667
668 gcov_write_unsigned (0);
669
670 read_fatal:;
671 while (fn_buffer)
672 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
673
674 if ((error = gcov_close ()))
675 fprintf (stderr, error < 0 ?
676 "profiling:%s:Overflow writing\n" :
677 "profiling:%s:Error writing\n",
678 gi_filename);
679 }
680 }
681
682 /* Add a new object file onto the bb chain. Invoked automatically
683 when running an object file's global ctors. */
684
685 void
686 __gcov_init (struct gcov_info *info)
687 {
688 if (!info->version || !info->n_functions)
689 return;
690 if (gcov_version (info, info->version, 0))
691 {
692 size_t filename_length = strlen(info->filename);
693
694 /* Refresh the longest file name information */
695 if (filename_length > gcov_max_filename)
696 gcov_max_filename = filename_length;
697
698 if (!gcov_list)
699 atexit (gcov_exit);
700
701 info->next = gcov_list;
702 gcov_list = info;
703 }
704 info->version = 0;
705 }
706
707 #ifdef __GTHREAD_MUTEX_INIT
708 ATTRIBUTE_HIDDEN __gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
709 #define init_mx_once()
710 #else
711 __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
712
713 static void
714 init_mx (void)
715 {
716 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
717 }
718 static void
719 init_mx_once (void)
720 {
721 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
722 __gthread_once (&once, init_mx);
723 }
724 #endif
725
726 /* Called before fork or exec - write out profile information gathered so
727 far and reset it to zero. This avoids duplication or loss of the
728 profile information gathered so far. */
729
730 void
731 __gcov_flush (void)
732 {
733 const struct gcov_info *gi_ptr;
734
735 init_mx_once ();
736 __gthread_mutex_lock (&__gcov_flush_mx);
737
738 gcov_exit ();
739 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
740 {
741 unsigned f_ix;
742
743 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
744 {
745 unsigned t_ix;
746 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
747
748 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
749 continue;
750 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
751 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
752 {
753 if (!gi_ptr->merge[t_ix])
754 continue;
755
756 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
757 ci_ptr++;
758 }
759 }
760 }
761
762 __gthread_mutex_unlock (&__gcov_flush_mx);
763 }
764
765 #endif /* L_gcov */
766
767 #ifdef L_gcov_merge_add
768 /* The profile merging function that just adds the counters. It is given
769 an array COUNTERS of N_COUNTERS old counters and it reads the same number
770 of counters from the gcov file. */
771 void
772 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
773 {
774 for (; n_counters; counters++, n_counters--)
775 *counters += gcov_read_counter ();
776 }
777 #endif /* L_gcov_merge_add */
778
779 #ifdef L_gcov_merge_ior
780 /* The profile merging function that just adds the counters. It is given
781 an array COUNTERS of N_COUNTERS old counters and it reads the same number
782 of counters from the gcov file. */
783 void
784 __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
785 {
786 for (; n_counters; counters++, n_counters--)
787 *counters |= gcov_read_counter ();
788 }
789 #endif
790
791 #ifdef L_gcov_merge_single
792 /* The profile merging function for choosing the most common value.
793 It is given an array COUNTERS of N_COUNTERS old counters and it
794 reads the same number of counters from the gcov file. The counters
795 are split into 3-tuples where the members of the tuple have
796 meanings:
797
798 -- the stored candidate on the most common value of the measured entity
799 -- counter
800 -- total number of evaluations of the value */
801 void
802 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
803 {
804 unsigned i, n_measures;
805 gcov_type value, counter, all;
806
807 gcc_assert (!(n_counters % 3));
808 n_measures = n_counters / 3;
809 for (i = 0; i < n_measures; i++, counters += 3)
810 {
811 value = gcov_read_counter ();
812 counter = gcov_read_counter ();
813 all = gcov_read_counter ();
814
815 if (counters[0] == value)
816 counters[1] += counter;
817 else if (counter > counters[1])
818 {
819 counters[0] = value;
820 counters[1] = counter - counters[1];
821 }
822 else
823 counters[1] -= counter;
824 counters[2] += all;
825 }
826 }
827 #endif /* L_gcov_merge_single */
828
829 #ifdef L_gcov_merge_delta
830 /* The profile merging function for choosing the most common
831 difference between two consecutive evaluations of the value. It is
832 given an array COUNTERS of N_COUNTERS old counters and it reads the
833 same number of counters from the gcov file. The counters are split
834 into 4-tuples where the members of the tuple have meanings:
835
836 -- the last value of the measured entity
837 -- the stored candidate on the most common difference
838 -- counter
839 -- total number of evaluations of the value */
840 void
841 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
842 {
843 unsigned i, n_measures;
844 gcov_type value, counter, all;
845
846 gcc_assert (!(n_counters % 4));
847 n_measures = n_counters / 4;
848 for (i = 0; i < n_measures; i++, counters += 4)
849 {
850 /* last = */ gcov_read_counter ();
851 value = gcov_read_counter ();
852 counter = gcov_read_counter ();
853 all = gcov_read_counter ();
854
855 if (counters[1] == value)
856 counters[2] += counter;
857 else if (counter > counters[2])
858 {
859 counters[1] = value;
860 counters[2] = counter - counters[2];
861 }
862 else
863 counters[2] -= counter;
864 counters[3] += all;
865 }
866 }
867 #endif /* L_gcov_merge_delta */
868
869 #ifdef L_gcov_interval_profiler
870 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
871 corresponding counter in COUNTERS. If the VALUE is above or below
872 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
873 instead. */
874
875 void
876 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
877 int start, unsigned steps)
878 {
879 gcov_type delta = value - start;
880 if (delta < 0)
881 counters[steps + 1]++;
882 else if (delta >= steps)
883 counters[steps]++;
884 else
885 counters[delta]++;
886 }
887 #endif
888
889 #ifdef L_gcov_pow2_profiler
890 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
891 COUNTERS[0] is incremented. */
892
893 void
894 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
895 {
896 if (value & (value - 1))
897 counters[0]++;
898 else
899 counters[1]++;
900 }
901 #endif
902
903 /* Tries to determine the most common value among its inputs. Checks if the
904 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
905 is incremented. If this is not the case and COUNTERS[1] is not zero,
906 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
907 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
908 function is called more than 50% of the time with one value, this value
909 will be in COUNTERS[0] in the end.
910
911 In any case, COUNTERS[2] is incremented. */
912
913 static inline void
914 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
915 {
916 if (value == counters[0])
917 counters[1]++;
918 else if (counters[1] == 0)
919 {
920 counters[1] = 1;
921 counters[0] = value;
922 }
923 else
924 counters[1]--;
925 counters[2]++;
926 }
927
928 #ifdef L_gcov_one_value_profiler
929 void
930 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
931 {
932 __gcov_one_value_profiler_body (counters, value);
933 }
934 #endif
935
936 #ifdef L_gcov_indirect_call_profiler
937
938 /* By default, the C++ compiler will use function addresses in the
939 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
940 tells the compiler to use function descriptors instead. The value
941 of this macro says how many words wide the descriptor is (normally 2),
942 but it may be dependent on target flags. Since we do not have access
943 to the target flags here we just check to see if it is set and use
944 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
945
946 It is assumed that the address of a function descriptor may be treated
947 as a pointer to a function. */
948
949 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
950 #define VTABLE_USES_DESCRIPTORS 1
951 #else
952 #define VTABLE_USES_DESCRIPTORS 0
953 #endif
954
955 /* Tries to determine the most common value among its inputs. */
956 void
957 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
958 void* cur_func, void* callee_func)
959 {
960 /* If the C++ virtual tables contain function descriptors then one
961 function may have multiple descriptors and we need to dereference
962 the descriptors to see if they point to the same function. */
963 if (cur_func == callee_func
964 || (VTABLE_USES_DESCRIPTORS && callee_func
965 && *(void **) cur_func == *(void **) callee_func))
966 __gcov_one_value_profiler_body (counter, value);
967 }
968 #endif
969
970
971 #ifdef L_gcov_average_profiler
972 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
973 to saturate up. */
974
975 void
976 __gcov_average_profiler (gcov_type *counters, gcov_type value)
977 {
978 counters[0] += value;
979 counters[1] ++;
980 }
981 #endif
982
983 #ifdef L_gcov_ior_profiler
984 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
985 to saturate up. */
986
987 void
988 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
989 {
990 *counters |= value;
991 }
992 #endif
993
994 #ifdef L_gcov_fork
995 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
996 that they are not counted twice. */
997
998 pid_t
999 __gcov_fork (void)
1000 {
1001 pid_t pid;
1002 extern __gthread_mutex_t __gcov_flush_mx;
1003 __gcov_flush ();
1004 pid = fork ();
1005 if (pid == 0)
1006 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
1007 return pid;
1008 }
1009 #endif
1010
1011 #ifdef L_gcov_execl
1012 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1013 that they are not lost. */
1014
1015 int
1016 __gcov_execl (const char *path, char *arg, ...)
1017 {
1018 va_list ap, aq;
1019 unsigned i, length;
1020 char **args;
1021
1022 __gcov_flush ();
1023
1024 va_start (ap, arg);
1025 va_copy (aq, ap);
1026
1027 length = 2;
1028 while (va_arg (ap, char *))
1029 length++;
1030 va_end (ap);
1031
1032 args = (char **) alloca (length * sizeof (void *));
1033 args[0] = arg;
1034 for (i = 1; i < length; i++)
1035 args[i] = va_arg (aq, char *);
1036 va_end (aq);
1037
1038 return execv (path, args);
1039 }
1040 #endif
1041
1042 #ifdef L_gcov_execlp
1043 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1044 that they are not lost. */
1045
1046 int
1047 __gcov_execlp (const char *path, char *arg, ...)
1048 {
1049 va_list ap, aq;
1050 unsigned i, length;
1051 char **args;
1052
1053 __gcov_flush ();
1054
1055 va_start (ap, arg);
1056 va_copy (aq, ap);
1057
1058 length = 2;
1059 while (va_arg (ap, char *))
1060 length++;
1061 va_end (ap);
1062
1063 args = (char **) alloca (length * sizeof (void *));
1064 args[0] = arg;
1065 for (i = 1; i < length; i++)
1066 args[i] = va_arg (aq, char *);
1067 va_end (aq);
1068
1069 return execvp (path, args);
1070 }
1071 #endif
1072
1073 #ifdef L_gcov_execle
1074 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
1075 that they are not lost. */
1076
1077 int
1078 __gcov_execle (const char *path, char *arg, ...)
1079 {
1080 va_list ap, aq;
1081 unsigned i, length;
1082 char **args;
1083 char **envp;
1084
1085 __gcov_flush ();
1086
1087 va_start (ap, arg);
1088 va_copy (aq, ap);
1089
1090 length = 2;
1091 while (va_arg (ap, char *))
1092 length++;
1093 va_end (ap);
1094
1095 args = (char **) alloca (length * sizeof (void *));
1096 args[0] = arg;
1097 for (i = 1; i < length; i++)
1098 args[i] = va_arg (aq, char *);
1099 envp = va_arg (aq, char **);
1100 va_end (aq);
1101
1102 return execve (path, args, envp);
1103 }
1104 #endif
1105
1106 #ifdef L_gcov_execv
1107 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1108 that they are not lost. */
1109
1110 int
1111 __gcov_execv (const char *path, char *const argv[])
1112 {
1113 __gcov_flush ();
1114 return execv (path, argv);
1115 }
1116 #endif
1117
1118 #ifdef L_gcov_execvp
1119 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1120 that they are not lost. */
1121
1122 int
1123 __gcov_execvp (const char *path, char *const argv[])
1124 {
1125 __gcov_flush ();
1126 return execvp (path, argv);
1127 }
1128 #endif
1129
1130 #ifdef L_gcov_execve
1131 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
1132 that they are not lost. */
1133
1134 int
1135 __gcov_execve (const char *path, char *const argv[], char *const envp[])
1136 {
1137 __gcov_flush ();
1138 return execve (path, argv, envp);
1139 }
1140 #endif
1141 #endif /* inhibit_libc */