gcc/
[official-gcc.git] / libgcc / libgcov.c
blob8ed897117f723f2ab4f4f0b6be31414ca8b829d7
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.
7 This file is part of GCC.
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.
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.
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.
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/>. */
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"
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"
45 #if defined(inhibit_libc)
46 /* If libc and its header files are not available, provide dummy functions. */
48 #ifdef L_gcov
49 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
50 void __gcov_flush (void) {}
51 #endif
53 #ifdef L_gcov_reset
54 void __gcov_reset (void) {}
55 #endif
57 #ifdef L_gcov_dump
58 void __gcov_dump (void) {}
59 #endif
61 #ifdef L_gcov_merge_add
62 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
63 unsigned n_counters __attribute__ ((unused))) {}
64 #endif
66 #ifdef L_gcov_merge_single
67 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
68 unsigned n_counters __attribute__ ((unused))) {}
69 #endif
71 #ifdef L_gcov_merge_delta
72 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
73 unsigned n_counters __attribute__ ((unused))) {}
74 #endif
76 #else
78 #include <string.h>
79 #if GCOV_LOCKED
80 #include <fcntl.h>
81 #include <errno.h>
82 #include <sys/stat.h>
83 #endif
85 extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
86 extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
87 extern int gcov_dump_complete ATTRIBUTE_HIDDEN;
89 #ifdef L_gcov
90 #include "gcov-io.c"
92 struct gcov_fn_buffer
94 struct gcov_fn_buffer *next;
95 unsigned fn_ix;
96 struct gcov_fn_info info;
97 /* note gcov_fn_info ends in a trailing array. */
100 /* Chain of per-object gcov structures. */
101 static struct gcov_info *gcov_list;
103 /* Size of the longest file name. */
104 static size_t gcov_max_filename = 0;
106 /* Flag when the profile has already been dumped via __gcov_dump(). */
107 int gcov_dump_complete = 0;
109 /* Make sure path component of the given FILENAME exists, create
110 missing directories. FILENAME must be writable.
111 Returns zero on success, or -1 if an error occurred. */
113 static int
114 create_file_directory (char *filename)
116 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
117 (void) filename;
118 return -1;
119 #else
120 char *s;
122 s = filename;
124 if (HAS_DRIVE_SPEC(s))
125 s += 2;
126 if (IS_DIR_SEPARATOR(*s))
127 ++s;
128 for (; *s != '\0'; s++)
129 if (IS_DIR_SEPARATOR(*s))
131 char sep = *s;
132 *s = '\0';
134 /* Try to make directory if it doesn't already exist. */
135 if (access (filename, F_OK) == -1
136 #ifdef TARGET_POSIX_IO
137 && mkdir (filename, 0755) == -1
138 #else
139 && mkdir (filename) == -1
140 #endif
141 /* The directory might have been made by another process. */
142 && errno != EEXIST)
144 fprintf (stderr, "profiling:%s:Cannot create directory\n",
145 filename);
146 *s = sep;
147 return -1;
150 *s = sep;
152 return 0;
153 #endif
156 static struct gcov_fn_buffer *
157 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
158 unsigned limit)
160 struct gcov_fn_buffer *next;
161 unsigned ix, n_ctr = 0;
163 if (!buffer)
164 return 0;
165 next = buffer->next;
167 for (ix = 0; ix != limit; ix++)
168 if (gi_ptr->merge[ix])
169 free (buffer->info.ctrs[n_ctr++].values);
170 free (buffer);
171 return next;
174 static struct gcov_fn_buffer **
175 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
176 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
178 unsigned n_ctrs = 0, ix = 0;
179 struct gcov_fn_buffer *fn_buffer;
180 unsigned len;
182 for (ix = GCOV_COUNTERS; ix--;)
183 if (gi_ptr->merge[ix])
184 n_ctrs++;
186 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
187 fn_buffer = (struct gcov_fn_buffer *)malloc (len);
189 if (!fn_buffer)
190 goto fail;
192 fn_buffer->next = 0;
193 fn_buffer->fn_ix = fn_ix;
194 fn_buffer->info.ident = gcov_read_unsigned ();
195 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
196 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
198 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
200 gcov_unsigned_t length;
201 gcov_type *values;
203 if (!gi_ptr->merge[ix])
204 continue;
206 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
208 len = 0;
209 goto fail;
212 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
213 len = length * sizeof (gcov_type);
214 values = (gcov_type *)malloc (len);
215 if (!values)
216 goto fail;
218 fn_buffer->info.ctrs[n_ctrs].num = length;
219 fn_buffer->info.ctrs[n_ctrs].values = values;
221 while (length--)
222 *values++ = gcov_read_counter ();
223 n_ctrs++;
226 *end_ptr = fn_buffer;
227 return &fn_buffer->next;
229 fail:
230 fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
231 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
233 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
236 /* Add an unsigned value to the current crc */
238 static gcov_unsigned_t
239 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
241 unsigned ix;
243 for (ix = 32; ix--; value <<= 1)
245 unsigned feedback;
247 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
248 crc32 <<= 1;
249 crc32 ^= feedback;
252 return crc32;
255 /* Check if VERSION of the info block PTR matches libgcov one.
256 Return 1 on success, or zero in case of versions mismatch.
257 If FILENAME is not NULL, its value used for reporting purposes
258 instead of value from the info block. */
260 static int
261 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
262 const char *filename)
264 if (version != GCOV_VERSION)
266 char v[4], e[4];
268 GCOV_UNSIGNED2STRING (v, version);
269 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
271 fprintf (stderr,
272 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
273 filename? filename : ptr->filename, e, v);
274 return 0;
276 return 1;
279 /* Dump the coverage counts. We merge with existing counts when
280 possible, to avoid growing the .da files ad infinitum. We use this
281 program's checksum to make sure we only accumulate whole program
282 statistics to the correct summary. An object file might be embedded
283 in two separate programs, and we must keep the two program
284 summaries separate. */
286 void
287 gcov_exit (void)
289 struct gcov_info *gi_ptr;
290 const struct gcov_fn_info *gfi_ptr;
291 struct gcov_summary this_prg; /* summary for program. */
292 struct gcov_summary all_prg; /* summary for all instances of program. */
293 struct gcov_ctr_summary *cs_ptr;
294 const struct gcov_ctr_info *ci_ptr;
295 unsigned t_ix;
296 int f_ix;
297 gcov_unsigned_t c_num;
298 const char *gcov_prefix;
299 int gcov_prefix_strip = 0;
300 size_t prefix_length;
301 char *gi_filename, *gi_filename_up;
302 gcov_unsigned_t crc32 = 0;
304 /* Prevent the counters from being dumped a second time on exit when the
305 application already wrote out the profile using __gcov_dump(). */
306 if (gcov_dump_complete)
307 return;
309 memset (&all_prg, 0, sizeof (all_prg));
310 /* Find the totals for this execution. */
311 memset (&this_prg, 0, sizeof (this_prg));
312 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
314 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
315 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
317 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
319 gfi_ptr = gi_ptr->functions[f_ix];
321 if (gfi_ptr && gfi_ptr->key != gi_ptr)
322 gfi_ptr = 0;
324 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
325 crc32 = crc32_unsigned (crc32,
326 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
327 if (!gfi_ptr)
328 continue;
330 ci_ptr = gfi_ptr->ctrs;
331 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
333 if (!gi_ptr->merge[t_ix])
334 continue;
336 cs_ptr = &this_prg.ctrs[t_ix];
337 cs_ptr->num += ci_ptr->num;
338 crc32 = crc32_unsigned (crc32, ci_ptr->num);
340 for (c_num = 0; c_num < ci_ptr->num; c_num++)
342 cs_ptr->sum_all += ci_ptr->values[c_num];
343 if (cs_ptr->run_max < ci_ptr->values[c_num])
344 cs_ptr->run_max = ci_ptr->values[c_num];
346 ci_ptr++;
352 /* Check if the level of dirs to strip off specified. */
353 char *tmp = getenv("GCOV_PREFIX_STRIP");
354 if (tmp)
356 gcov_prefix_strip = atoi (tmp);
357 /* Do not consider negative values. */
358 if (gcov_prefix_strip < 0)
359 gcov_prefix_strip = 0;
363 /* Get file name relocation prefix. Non-absolute values are ignored. */
364 gcov_prefix = getenv("GCOV_PREFIX");
365 if (gcov_prefix)
367 prefix_length = strlen(gcov_prefix);
369 /* Remove an unnecessary trailing '/' */
370 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
371 prefix_length--;
373 else
374 prefix_length = 0;
376 /* If no prefix was specified and a prefix stip, then we assume
377 relative. */
378 if (gcov_prefix_strip != 0 && prefix_length == 0)
380 gcov_prefix = ".";
381 prefix_length = 1;
383 /* Allocate and initialize the filename scratch space plus one. */
384 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
385 if (prefix_length)
386 memcpy (gi_filename, gcov_prefix, prefix_length);
387 gi_filename_up = gi_filename + prefix_length;
389 /* Now merge each file. */
390 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
392 unsigned n_counts;
393 struct gcov_summary prg; /* summary for this object over all
394 program. */
395 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
396 int error = 0;
397 gcov_unsigned_t tag, length;
398 gcov_position_t summary_pos = 0;
399 gcov_position_t eof_pos = 0;
400 const char *fname, *s;
401 struct gcov_fn_buffer *fn_buffer = 0;
402 struct gcov_fn_buffer **fn_tail = &fn_buffer;
404 fname = gi_ptr->filename;
406 /* Avoid to add multiple drive letters into combined path. */
407 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
408 fname += 2;
410 /* Build relocated filename, stripping off leading
411 directories from the initial filename if requested. */
412 if (gcov_prefix_strip > 0)
414 int level = 0;
415 s = fname;
416 if (IS_DIR_SEPARATOR(*s))
417 ++s;
419 /* Skip selected directory levels. */
420 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
421 if (IS_DIR_SEPARATOR(*s))
423 fname = s;
424 level++;
428 /* Update complete filename with stripped original. */
429 if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
431 /* If prefix is given, add directory separator. */
432 strcpy (gi_filename_up, "/");
433 strcpy (gi_filename_up + 1, fname);
435 else
436 strcpy (gi_filename_up, fname);
438 if (!gcov_open (gi_filename))
440 /* Open failed likely due to missed directory.
441 Create directory and retry to open file. */
442 if (create_file_directory (gi_filename))
444 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
445 continue;
447 if (!gcov_open (gi_filename))
449 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
450 continue;
454 tag = gcov_read_unsigned ();
455 if (tag)
457 /* Merge data from file. */
458 if (tag != GCOV_DATA_MAGIC)
460 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
461 gi_filename);
462 goto read_fatal;
464 length = gcov_read_unsigned ();
465 if (!gcov_version (gi_ptr, length, gi_filename))
466 goto read_fatal;
468 length = gcov_read_unsigned ();
469 if (length != gi_ptr->stamp)
470 /* Read from a different compilation. Overwrite the file. */
471 goto rewrite;
473 /* Look for program summary. */
474 for (f_ix = 0;;)
476 struct gcov_summary tmp;
478 eof_pos = gcov_position ();
479 tag = gcov_read_unsigned ();
480 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
481 break;
483 f_ix--;
484 length = gcov_read_unsigned ();
485 if (length != GCOV_TAG_SUMMARY_LENGTH)
486 goto read_mismatch;
487 gcov_read_summary (&tmp);
488 if ((error = gcov_is_error ()))
489 goto read_error;
490 if (summary_pos || tmp.checksum != crc32)
491 goto next_summary;
493 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
494 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
495 goto next_summary;
496 prg = tmp;
497 summary_pos = eof_pos;
499 next_summary:;
502 /* Merge execution counts for each function. */
503 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
504 f_ix++, tag = gcov_read_unsigned ())
506 gfi_ptr = gi_ptr->functions[f_ix];
508 if (tag != GCOV_TAG_FUNCTION)
509 goto read_mismatch;
511 length = gcov_read_unsigned ();
512 if (!length)
513 /* This function did not appear in the other program.
514 We have nothing to merge. */
515 continue;
517 if (length != GCOV_TAG_FUNCTION_LENGTH)
518 goto read_mismatch;
520 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
522 /* This function appears in the other program. We
523 need to buffer the information in order to write
524 it back out -- we'll be inserting data before
525 this point, so cannot simply keep the data in the
526 file. */
527 fn_tail = buffer_fn_data (gi_filename,
528 gi_ptr, fn_tail, f_ix);
529 if (!fn_tail)
530 goto read_mismatch;
531 continue;
534 length = gcov_read_unsigned ();
535 if (length != gfi_ptr->ident)
536 goto read_mismatch;
538 length = gcov_read_unsigned ();
539 if (length != gfi_ptr->lineno_checksum)
540 goto read_mismatch;
542 length = gcov_read_unsigned ();
543 if (length != gfi_ptr->cfg_checksum)
544 goto read_mismatch;
546 ci_ptr = gfi_ptr->ctrs;
547 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
549 gcov_merge_fn merge = gi_ptr->merge[t_ix];
551 if (!merge)
552 continue;
554 tag = gcov_read_unsigned ();
555 length = gcov_read_unsigned ();
556 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
557 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
558 goto read_mismatch;
559 (*merge) (ci_ptr->values, ci_ptr->num);
560 ci_ptr++;
562 if ((error = gcov_is_error ()))
563 goto read_error;
566 if (tag)
568 read_mismatch:;
569 fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n",
570 gi_filename, f_ix >= 0 ? "function" : "summary",
571 f_ix < 0 ? -1 - f_ix : f_ix);
572 goto read_fatal;
575 goto rewrite;
577 read_error:;
578 fprintf (stderr, "profiling:%s:%s merging\n", gi_filename,
579 error < 0 ? "Overflow": "Error");
581 goto read_fatal;
583 rewrite:;
584 gcov_rewrite ();
585 if (!summary_pos)
587 memset (&prg, 0, sizeof (prg));
588 summary_pos = eof_pos;
591 /* Merge the summaries. */
592 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
594 cs_prg = &prg.ctrs[t_ix];
595 cs_tprg = &this_prg.ctrs[t_ix];
596 cs_all = &all_prg.ctrs[t_ix];
598 if (gi_ptr->merge[t_ix])
600 if (!cs_prg->runs++)
601 cs_prg->num = cs_tprg->num;
602 cs_prg->sum_all += cs_tprg->sum_all;
603 if (cs_prg->run_max < cs_tprg->run_max)
604 cs_prg->run_max = cs_tprg->run_max;
605 cs_prg->sum_max += cs_tprg->run_max;
607 else if (cs_prg->runs)
608 goto read_mismatch;
610 if (!cs_all->runs && cs_prg->runs)
611 memcpy (cs_all, cs_prg, sizeof (*cs_all));
612 else if (!all_prg.checksum
613 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
614 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
616 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
617 gi_filename, GCOV_LOCKED
618 ? "" : " or concurrently updated without locking support");
619 all_prg.checksum = ~0u;
623 prg.checksum = crc32;
625 /* Write out the data. */
626 if (!eof_pos)
628 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
629 gcov_write_unsigned (gi_ptr->stamp);
632 if (summary_pos)
633 gcov_seek (summary_pos);
635 /* Generate whole program statistics. */
636 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg);
638 if (summary_pos < eof_pos)
639 gcov_seek (eof_pos);
641 /* Write execution counts for each function. */
642 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
644 unsigned buffered = 0;
646 if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix)
648 /* Buffered data from another program. */
649 buffered = 1;
650 gfi_ptr = &fn_buffer->info;
651 length = GCOV_TAG_FUNCTION_LENGTH;
653 else
655 gfi_ptr = gi_ptr->functions[f_ix];
656 if (gfi_ptr && gfi_ptr->key == gi_ptr)
657 length = GCOV_TAG_FUNCTION_LENGTH;
658 else
659 length = 0;
662 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
663 if (!length)
664 continue;
666 gcov_write_unsigned (gfi_ptr->ident);
667 gcov_write_unsigned (gfi_ptr->lineno_checksum);
668 gcov_write_unsigned (gfi_ptr->cfg_checksum);
670 ci_ptr = gfi_ptr->ctrs;
671 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
673 if (!gi_ptr->merge[t_ix])
674 continue;
676 n_counts = ci_ptr->num;
677 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
678 GCOV_TAG_COUNTER_LENGTH (n_counts));
679 gcov_type *c_ptr = ci_ptr->values;
680 while (n_counts--)
681 gcov_write_counter (*c_ptr++);
682 ci_ptr++;
684 if (buffered)
685 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
688 gcov_write_unsigned (0);
690 read_fatal:;
691 while (fn_buffer)
692 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
694 if ((error = gcov_close ()))
695 fprintf (stderr, error < 0 ?
696 "profiling:%s:Overflow writing\n" :
697 "profiling:%s:Error writing\n",
698 gi_filename);
702 /* Reset all counters to zero. */
704 void
705 gcov_clear (void)
707 const struct gcov_info *gi_ptr;
709 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
711 unsigned f_ix;
713 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
715 unsigned t_ix;
716 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
718 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
719 continue;
720 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
721 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
723 if (!gi_ptr->merge[t_ix])
724 continue;
726 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
727 ci_ptr++;
733 /* Add a new object file onto the bb chain. Invoked automatically
734 when running an object file's global ctors. */
736 void
737 __gcov_init (struct gcov_info *info)
739 if (!info->version || !info->n_functions)
740 return;
741 if (gcov_version (info, info->version, 0))
743 size_t filename_length = strlen(info->filename);
745 /* Refresh the longest file name information */
746 if (filename_length > gcov_max_filename)
747 gcov_max_filename = filename_length;
749 if (!gcov_list)
750 atexit (gcov_exit);
752 info->next = gcov_list;
753 gcov_list = info;
755 info->version = 0;
758 #ifdef __GTHREAD_MUTEX_INIT
759 ATTRIBUTE_HIDDEN __gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
760 #define init_mx_once()
761 #else
762 __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
764 static void
765 init_mx (void)
767 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
769 static void
770 init_mx_once (void)
772 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
773 __gthread_once (&once, init_mx);
775 #endif
777 /* Called before fork or exec - write out profile information gathered so
778 far and reset it to zero. This avoids duplication or loss of the
779 profile information gathered so far. */
781 void
782 __gcov_flush (void)
784 init_mx_once ();
785 __gthread_mutex_lock (&__gcov_flush_mx);
787 gcov_exit ();
788 gcov_clear ();
790 __gthread_mutex_unlock (&__gcov_flush_mx);
793 #endif /* L_gcov */
795 #ifdef L_gcov_reset
797 /* Function that can be called from application to reset counters to zero,
798 in order to collect profile in region of interest. */
800 void
801 __gcov_reset (void)
803 gcov_clear ();
804 /* Re-enable dumping to support collecting profile in multiple regions
805 of interest. */
806 gcov_dump_complete = 0;
809 #endif /* L_gcov_reset */
811 #ifdef L_gcov_dump
813 /* Function that can be called from application to write profile collected
814 so far, in order to collect profile in region of interest. */
816 void
817 __gcov_dump (void)
819 gcov_exit ();
820 /* Prevent profile from being dumped a second time on application exit. */
821 gcov_dump_complete = 1;
824 #endif /* L_gcov_dump */
826 #ifdef L_gcov_merge_add
827 /* The profile merging function that just adds the counters. It is given
828 an array COUNTERS of N_COUNTERS old counters and it reads the same number
829 of counters from the gcov file. */
830 void
831 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
833 for (; n_counters; counters++, n_counters--)
834 *counters += gcov_read_counter ();
836 #endif /* L_gcov_merge_add */
838 #ifdef L_gcov_merge_ior
839 /* The profile merging function that just adds the counters. It is given
840 an array COUNTERS of N_COUNTERS old counters and it reads the same number
841 of counters from the gcov file. */
842 void
843 __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
845 for (; n_counters; counters++, n_counters--)
846 *counters |= gcov_read_counter ();
848 #endif
850 #ifdef L_gcov_merge_single
851 /* The profile merging function for choosing the most common value.
852 It is given an array COUNTERS of N_COUNTERS old counters and it
853 reads the same number of counters from the gcov file. The counters
854 are split into 3-tuples where the members of the tuple have
855 meanings:
857 -- the stored candidate on the most common value of the measured entity
858 -- counter
859 -- total number of evaluations of the value */
860 void
861 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
863 unsigned i, n_measures;
864 gcov_type value, counter, all;
866 gcc_assert (!(n_counters % 3));
867 n_measures = n_counters / 3;
868 for (i = 0; i < n_measures; i++, counters += 3)
870 value = gcov_read_counter ();
871 counter = gcov_read_counter ();
872 all = gcov_read_counter ();
874 if (counters[0] == value)
875 counters[1] += counter;
876 else if (counter > counters[1])
878 counters[0] = value;
879 counters[1] = counter - counters[1];
881 else
882 counters[1] -= counter;
883 counters[2] += all;
886 #endif /* L_gcov_merge_single */
888 #ifdef L_gcov_merge_delta
889 /* The profile merging function for choosing the most common
890 difference between two consecutive evaluations of the value. It is
891 given an array COUNTERS of N_COUNTERS old counters and it reads the
892 same number of counters from the gcov file. The counters are split
893 into 4-tuples where the members of the tuple have meanings:
895 -- the last value of the measured entity
896 -- the stored candidate on the most common difference
897 -- counter
898 -- total number of evaluations of the value */
899 void
900 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
902 unsigned i, n_measures;
903 gcov_type value, counter, all;
905 gcc_assert (!(n_counters % 4));
906 n_measures = n_counters / 4;
907 for (i = 0; i < n_measures; i++, counters += 4)
909 /* last = */ gcov_read_counter ();
910 value = gcov_read_counter ();
911 counter = gcov_read_counter ();
912 all = gcov_read_counter ();
914 if (counters[1] == value)
915 counters[2] += counter;
916 else if (counter > counters[2])
918 counters[1] = value;
919 counters[2] = counter - counters[2];
921 else
922 counters[2] -= counter;
923 counters[3] += all;
926 #endif /* L_gcov_merge_delta */
928 #ifdef L_gcov_interval_profiler
929 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
930 corresponding counter in COUNTERS. If the VALUE is above or below
931 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
932 instead. */
934 void
935 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
936 int start, unsigned steps)
938 gcov_type delta = value - start;
939 if (delta < 0)
940 counters[steps + 1]++;
941 else if (delta >= steps)
942 counters[steps]++;
943 else
944 counters[delta]++;
946 #endif
948 #ifdef L_gcov_pow2_profiler
949 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
950 COUNTERS[0] is incremented. */
952 void
953 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
955 if (value & (value - 1))
956 counters[0]++;
957 else
958 counters[1]++;
960 #endif
962 /* Tries to determine the most common value among its inputs. Checks if the
963 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
964 is incremented. If this is not the case and COUNTERS[1] is not zero,
965 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
966 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
967 function is called more than 50% of the time with one value, this value
968 will be in COUNTERS[0] in the end.
970 In any case, COUNTERS[2] is incremented. */
972 static inline void
973 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
975 if (value == counters[0])
976 counters[1]++;
977 else if (counters[1] == 0)
979 counters[1] = 1;
980 counters[0] = value;
982 else
983 counters[1]--;
984 counters[2]++;
987 #ifdef L_gcov_one_value_profiler
988 void
989 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
991 __gcov_one_value_profiler_body (counters, value);
993 #endif
995 #ifdef L_gcov_indirect_call_profiler
997 /* By default, the C++ compiler will use function addresses in the
998 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
999 tells the compiler to use function descriptors instead. The value
1000 of this macro says how many words wide the descriptor is (normally 2),
1001 but it may be dependent on target flags. Since we do not have access
1002 to the target flags here we just check to see if it is set and use
1003 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
1005 It is assumed that the address of a function descriptor may be treated
1006 as a pointer to a function. */
1008 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
1009 #define VTABLE_USES_DESCRIPTORS 1
1010 #else
1011 #define VTABLE_USES_DESCRIPTORS 0
1012 #endif
1014 /* Tries to determine the most common value among its inputs. */
1015 void
1016 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
1017 void* cur_func, void* callee_func)
1019 /* If the C++ virtual tables contain function descriptors then one
1020 function may have multiple descriptors and we need to dereference
1021 the descriptors to see if they point to the same function. */
1022 if (cur_func == callee_func
1023 || (VTABLE_USES_DESCRIPTORS && callee_func
1024 && *(void **) cur_func == *(void **) callee_func))
1025 __gcov_one_value_profiler_body (counter, value);
1027 #endif
1030 #ifdef L_gcov_average_profiler
1031 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1032 to saturate up. */
1034 void
1035 __gcov_average_profiler (gcov_type *counters, gcov_type value)
1037 counters[0] += value;
1038 counters[1] ++;
1040 #endif
1042 #ifdef L_gcov_ior_profiler
1043 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1044 to saturate up. */
1046 void
1047 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
1049 *counters |= value;
1051 #endif
1053 #ifdef L_gcov_fork
1054 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1055 that they are not counted twice. */
1057 pid_t
1058 __gcov_fork (void)
1060 pid_t pid;
1061 extern __gthread_mutex_t __gcov_flush_mx;
1062 __gcov_flush ();
1063 pid = fork ();
1064 if (pid == 0)
1065 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
1066 return pid;
1068 #endif
1070 #ifdef L_gcov_execl
1071 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1072 that they are not lost. */
1075 __gcov_execl (const char *path, char *arg, ...)
1077 va_list ap, aq;
1078 unsigned i, length;
1079 char **args;
1081 __gcov_flush ();
1083 va_start (ap, arg);
1084 va_copy (aq, ap);
1086 length = 2;
1087 while (va_arg (ap, char *))
1088 length++;
1089 va_end (ap);
1091 args = (char **) alloca (length * sizeof (void *));
1092 args[0] = arg;
1093 for (i = 1; i < length; i++)
1094 args[i] = va_arg (aq, char *);
1095 va_end (aq);
1097 return execv (path, args);
1099 #endif
1101 #ifdef L_gcov_execlp
1102 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1103 that they are not lost. */
1106 __gcov_execlp (const char *path, char *arg, ...)
1108 va_list ap, aq;
1109 unsigned i, length;
1110 char **args;
1112 __gcov_flush ();
1114 va_start (ap, arg);
1115 va_copy (aq, ap);
1117 length = 2;
1118 while (va_arg (ap, char *))
1119 length++;
1120 va_end (ap);
1122 args = (char **) alloca (length * sizeof (void *));
1123 args[0] = arg;
1124 for (i = 1; i < length; i++)
1125 args[i] = va_arg (aq, char *);
1126 va_end (aq);
1128 return execvp (path, args);
1130 #endif
1132 #ifdef L_gcov_execle
1133 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
1134 that they are not lost. */
1137 __gcov_execle (const char *path, char *arg, ...)
1139 va_list ap, aq;
1140 unsigned i, length;
1141 char **args;
1142 char **envp;
1144 __gcov_flush ();
1146 va_start (ap, arg);
1147 va_copy (aq, ap);
1149 length = 2;
1150 while (va_arg (ap, char *))
1151 length++;
1152 va_end (ap);
1154 args = (char **) alloca (length * sizeof (void *));
1155 args[0] = arg;
1156 for (i = 1; i < length; i++)
1157 args[i] = va_arg (aq, char *);
1158 envp = va_arg (aq, char **);
1159 va_end (aq);
1161 return execve (path, args, envp);
1163 #endif
1165 #ifdef L_gcov_execv
1166 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1167 that they are not lost. */
1170 __gcov_execv (const char *path, char *const argv[])
1172 __gcov_flush ();
1173 return execv (path, argv);
1175 #endif
1177 #ifdef L_gcov_execvp
1178 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1179 that they are not lost. */
1182 __gcov_execvp (const char *path, char *const argv[])
1184 __gcov_flush ();
1185 return execvp (path, argv);
1187 #endif
1189 #ifdef L_gcov_execve
1190 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
1191 that they are not lost. */
1194 __gcov_execve (const char *path, char *const argv[], char *const envp[])
1196 __gcov_flush ();
1197 return execve (path, argv, envp);
1199 #endif
1200 #endif /* inhibit_libc */