2011-01-15 Tobias Burnus <burnus@net-b.de>
[official-gcc.git] / gcc / libgcov.c
blob6f32e85dc55e031d099d74d4c97447ed39971084
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
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"
33 #if defined(inhibit_libc)
34 #define IN_LIBGCOV (-1)
35 #else
36 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
37 #include <stdio.h>
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_merge_add
54 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
55 unsigned n_counters __attribute__ ((unused))) {}
56 #endif
58 #ifdef L_gcov_merge_single
59 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
60 unsigned n_counters __attribute__ ((unused))) {}
61 #endif
63 #ifdef L_gcov_merge_delta
64 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
65 unsigned n_counters __attribute__ ((unused))) {}
66 #endif
68 #else
70 #include <string.h>
71 #if GCOV_LOCKED
72 #include <fcntl.h>
73 #include <errno.h>
74 #include <sys/stat.h>
75 #endif
77 #ifdef L_gcov
78 #include "gcov-io.c"
80 /* Chain of per-object gcov structures. */
81 static struct gcov_info *gcov_list;
83 /* A program checksum allows us to distinguish program data for an
84 object file included in multiple programs. */
85 static gcov_unsigned_t gcov_crc32;
87 /* Size of the longest file name. */
88 static size_t gcov_max_filename = 0;
90 /* Make sure path component of the given FILENAME exists, create
91 missing directories. FILENAME must be writable.
92 Returns zero on success, or -1 if an error occurred. */
94 static int
95 create_file_directory (char *filename)
97 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
98 (void) filename;
99 return -1;
100 #else
101 char *s;
103 s = filename;
105 if (HAS_DRIVE_SPEC(s))
106 s += 2;
107 if (IS_DIR_SEPARATOR(*s))
108 ++s;
109 for (; *s != '\0'; s++)
110 if (IS_DIR_SEPARATOR(*s))
112 char sep = *s;
113 *s = '\0';
115 /* Try to make directory if it doesn't already exist. */
116 if (access (filename, F_OK) == -1
117 #ifdef TARGET_POSIX_IO
118 && mkdir (filename, 0755) == -1
119 #else
120 && mkdir (filename) == -1
121 #endif
122 /* The directory might have been made by another process. */
123 && errno != EEXIST)
125 fprintf (stderr, "profiling:%s:Cannot create directory\n",
126 filename);
127 *s = sep;
128 return -1;
131 *s = sep;
133 return 0;
134 #endif
137 /* Check if VERSION of the info block PTR matches libgcov one.
138 Return 1 on success, or zero in case of versions mismatch.
139 If FILENAME is not NULL, its value used for reporting purposes
140 instead of value from the info block. */
142 static int
143 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
144 const char *filename)
146 if (version != GCOV_VERSION)
148 char v[4], e[4];
150 GCOV_UNSIGNED2STRING (v, version);
151 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
153 fprintf (stderr,
154 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
155 filename? filename : ptr->filename, e, v);
156 return 0;
158 return 1;
161 /* Dump the coverage counts. We merge with existing counts when
162 possible, to avoid growing the .da files ad infinitum. We use this
163 program's checksum to make sure we only accumulate whole program
164 statistics to the correct summary. An object file might be embedded
165 in two separate programs, and we must keep the two program
166 summaries separate. */
168 static void
169 gcov_exit (void)
171 struct gcov_info *gi_ptr;
172 struct gcov_summary this_program;
173 struct gcov_summary all;
174 struct gcov_ctr_summary *cs_ptr;
175 const struct gcov_ctr_info *ci_ptr;
176 unsigned t_ix;
177 gcov_unsigned_t c_num;
178 const char *gcov_prefix;
179 int gcov_prefix_strip = 0;
180 size_t prefix_length;
181 char *gi_filename, *gi_filename_up;
183 memset (&all, 0, sizeof (all));
184 /* Find the totals for this execution. */
185 memset (&this_program, 0, sizeof (this_program));
186 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
188 ci_ptr = gi_ptr->counts;
189 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
191 if (!((1 << t_ix) & gi_ptr->ctr_mask))
192 continue;
194 cs_ptr = &this_program.ctrs[t_ix];
195 cs_ptr->num += ci_ptr->num;
196 for (c_num = 0; c_num < ci_ptr->num; c_num++)
198 cs_ptr->sum_all += ci_ptr->values[c_num];
199 if (cs_ptr->run_max < ci_ptr->values[c_num])
200 cs_ptr->run_max = ci_ptr->values[c_num];
202 ci_ptr++;
207 /* Check if the level of dirs to strip off specified. */
208 char *tmp = getenv("GCOV_PREFIX_STRIP");
209 if (tmp)
211 gcov_prefix_strip = atoi (tmp);
212 /* Do not consider negative values. */
213 if (gcov_prefix_strip < 0)
214 gcov_prefix_strip = 0;
217 /* Get file name relocation prefix. Non-absolute values are ignored. */
218 gcov_prefix = getenv("GCOV_PREFIX");
219 if (gcov_prefix)
221 prefix_length = strlen(gcov_prefix);
223 /* Remove an unnecessary trailing '/' */
224 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
225 prefix_length--;
227 else
228 prefix_length = 0;
230 /* If no prefix was specified and a prefix stip, then we assume
231 relative. */
232 if (gcov_prefix_strip != 0 && prefix_length == 0)
234 gcov_prefix = ".";
235 prefix_length = 1;
237 /* Allocate and initialize the filename scratch space plus one. */
238 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
239 if (prefix_length)
240 memcpy (gi_filename, gcov_prefix, prefix_length);
241 gi_filename_up = gi_filename + prefix_length;
243 /* Now merge each file. */
244 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
246 struct gcov_summary this_object;
247 struct gcov_summary object, program;
248 gcov_type *values[GCOV_COUNTERS];
249 const struct gcov_fn_info *fi_ptr;
250 unsigned fi_stride;
251 unsigned c_ix, f_ix, n_counts;
252 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
253 int error = 0;
254 gcov_unsigned_t tag, length;
255 gcov_position_t summary_pos = 0;
256 gcov_position_t eof_pos = 0;
257 const char *fname, *s;
259 fname = gi_ptr->filename;
261 memset (&this_object, 0, sizeof (this_object));
262 memset (&object, 0, sizeof (object));
264 /* Avoid to add multiple drive letters into combined path. */
265 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
266 fname += 2;
268 /* Build relocated filename, stripping off leading
269 directories from the initial filename if requested. */
270 if (gcov_prefix_strip > 0)
272 int level = 0;
273 s = fname;
274 if (IS_DIR_SEPARATOR(*s))
275 ++s;
277 /* Skip selected directory levels. */
278 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
279 if (IS_DIR_SEPARATOR(*s))
281 fname = s;
282 level++;
285 /* Update complete filename with stripped original. */
286 if (!IS_DIR_SEPARATOR (*fname) && !HAS_DRIVE_SPEC(fname))
288 strcpy (gi_filename_up, "/");
289 strcpy (gi_filename_up + 1, fname);
291 else
292 strcpy (gi_filename_up, fname);
294 /* Totals for this object file. */
295 ci_ptr = gi_ptr->counts;
296 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
298 if (!((1 << t_ix) & gi_ptr->ctr_mask))
299 continue;
301 cs_ptr = &this_object.ctrs[t_ix];
302 cs_ptr->num += ci_ptr->num;
303 for (c_num = 0; c_num < ci_ptr->num; c_num++)
305 cs_ptr->sum_all += ci_ptr->values[c_num];
306 if (cs_ptr->run_max < ci_ptr->values[c_num])
307 cs_ptr->run_max = ci_ptr->values[c_num];
310 ci_ptr++;
313 c_ix = 0;
314 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
315 if ((1 << t_ix) & gi_ptr->ctr_mask)
317 values[c_ix] = gi_ptr->counts[c_ix].values;
318 c_ix++;
321 /* Calculate the function_info stride. This depends on the
322 number of counter types being measured. */
323 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
324 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
326 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
327 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
330 if (!gcov_open (gi_filename))
332 /* Open failed likely due to missed directory.
333 Create directory and retry to open file. */
334 if (create_file_directory (gi_filename))
336 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
337 continue;
339 if (!gcov_open (gi_filename))
341 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
342 continue;
346 tag = gcov_read_unsigned ();
347 if (tag)
349 /* Merge data from file. */
350 if (tag != GCOV_DATA_MAGIC)
352 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
353 gi_filename);
354 goto read_fatal;
356 length = gcov_read_unsigned ();
357 if (!gcov_version (gi_ptr, length, gi_filename))
358 goto read_fatal;
360 length = gcov_read_unsigned ();
361 if (length != gi_ptr->stamp)
362 /* Read from a different compilation. Overwrite the file. */
363 goto rewrite;
365 /* Merge execution counts for each function. */
366 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
368 fi_ptr = (const struct gcov_fn_info *)
369 ((const char *) gi_ptr->functions + f_ix * fi_stride);
370 tag = gcov_read_unsigned ();
371 length = gcov_read_unsigned ();
373 /* Check function. */
374 if (tag != GCOV_TAG_FUNCTION
375 || length != GCOV_TAG_FUNCTION_LENGTH
376 || gcov_read_unsigned () != fi_ptr->ident
377 || gcov_read_unsigned () != fi_ptr->checksum)
379 read_mismatch:;
380 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
381 gi_filename,
382 f_ix + 1 ? "function" : "summaries");
383 goto read_fatal;
386 c_ix = 0;
387 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
389 gcov_merge_fn merge;
391 if (!((1 << t_ix) & gi_ptr->ctr_mask))
392 continue;
394 n_counts = fi_ptr->n_ctrs[c_ix];
395 merge = gi_ptr->counts[c_ix].merge;
397 tag = gcov_read_unsigned ();
398 length = gcov_read_unsigned ();
399 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
400 || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
401 goto read_mismatch;
402 (*merge) (values[c_ix], n_counts);
403 values[c_ix] += n_counts;
404 c_ix++;
406 if ((error = gcov_is_error ()))
407 goto read_error;
410 f_ix = ~0u;
411 /* Check program & object summary */
412 while (1)
414 int is_program;
416 eof_pos = gcov_position ();
417 tag = gcov_read_unsigned ();
418 if (!tag)
419 break;
421 length = gcov_read_unsigned ();
422 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
423 if (length != GCOV_TAG_SUMMARY_LENGTH
424 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
425 goto read_mismatch;
426 gcov_read_summary (is_program ? &program : &object);
427 if ((error = gcov_is_error ()))
428 goto read_error;
429 if (is_program && program.checksum == gcov_crc32)
431 summary_pos = eof_pos;
432 goto rewrite;
436 goto rewrite;
438 read_error:;
439 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
440 : "profiling:%s:Error merging\n", gi_filename);
442 read_fatal:;
443 gcov_close ();
444 continue;
446 rewrite:;
447 gcov_rewrite ();
448 if (!summary_pos)
449 memset (&program, 0, sizeof (program));
451 /* Merge the summaries. */
452 f_ix = ~0u;
453 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
455 cs_obj = &object.ctrs[t_ix];
456 cs_tobj = &this_object.ctrs[t_ix];
457 cs_prg = &program.ctrs[t_ix];
458 cs_tprg = &this_program.ctrs[t_ix];
459 cs_all = &all.ctrs[t_ix];
461 if ((1 << t_ix) & gi_ptr->ctr_mask)
463 if (!cs_obj->runs++)
464 cs_obj->num = cs_tobj->num;
465 else if (cs_obj->num != cs_tobj->num)
466 goto read_mismatch;
467 cs_obj->sum_all += cs_tobj->sum_all;
468 if (cs_obj->run_max < cs_tobj->run_max)
469 cs_obj->run_max = cs_tobj->run_max;
470 cs_obj->sum_max += cs_tobj->run_max;
472 if (!cs_prg->runs++)
473 cs_prg->num = cs_tprg->num;
474 else if (cs_prg->num != cs_tprg->num)
475 goto read_mismatch;
476 cs_prg->sum_all += cs_tprg->sum_all;
477 if (cs_prg->run_max < cs_tprg->run_max)
478 cs_prg->run_max = cs_tprg->run_max;
479 cs_prg->sum_max += cs_tprg->run_max;
481 else if (cs_obj->num || cs_prg->num)
482 goto read_mismatch;
484 if (!cs_all->runs && cs_prg->runs)
485 memcpy (cs_all, cs_prg, sizeof (*cs_all));
486 else if (!all.checksum
487 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
488 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
490 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
491 gi_filename, GCOV_LOCKED
492 ? "" : " or concurrent update without locking support");
493 all.checksum = ~0u;
497 c_ix = 0;
498 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
499 if ((1 << t_ix) & gi_ptr->ctr_mask)
501 values[c_ix] = gi_ptr->counts[c_ix].values;
502 c_ix++;
505 program.checksum = gcov_crc32;
507 /* Write out the data. */
508 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
509 gcov_write_unsigned (gi_ptr->stamp);
511 /* Write execution counts for each function. */
512 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
514 fi_ptr = (const struct gcov_fn_info *)
515 ((const char *) gi_ptr->functions + f_ix * fi_stride);
517 /* Announce function. */
518 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
519 gcov_write_unsigned (fi_ptr->ident);
520 gcov_write_unsigned (fi_ptr->checksum);
522 c_ix = 0;
523 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
525 gcov_type *c_ptr;
527 if (!((1 << t_ix) & gi_ptr->ctr_mask))
528 continue;
530 n_counts = fi_ptr->n_ctrs[c_ix];
532 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
533 GCOV_TAG_COUNTER_LENGTH (n_counts));
534 c_ptr = values[c_ix];
535 while (n_counts--)
536 gcov_write_counter (*c_ptr++);
538 values[c_ix] = c_ptr;
539 c_ix++;
543 /* Object file summary. */
544 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
546 /* Generate whole program statistics. */
547 if (eof_pos)
548 gcov_seek (eof_pos);
549 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
550 if (!summary_pos)
551 gcov_write_unsigned (0);
552 if ((error = gcov_close ()))
553 fprintf (stderr, error < 0 ?
554 "profiling:%s:Overflow writing\n" :
555 "profiling:%s:Error writing\n",
556 gi_filename);
560 /* Add a new object file onto the bb chain. Invoked automatically
561 when running an object file's global ctors. */
563 void
564 __gcov_init (struct gcov_info *info)
566 if (!info->version)
567 return;
568 if (gcov_version (info, info->version, 0))
570 const char *ptr = info->filename;
571 gcov_unsigned_t crc32 = gcov_crc32;
572 size_t filename_length = strlen(info->filename);
574 /* Refresh the longest file name information */
575 if (filename_length > gcov_max_filename)
576 gcov_max_filename = filename_length;
580 unsigned ix;
581 gcov_unsigned_t value = *ptr << 24;
583 for (ix = 8; ix--; value <<= 1)
585 gcov_unsigned_t feedback;
587 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
588 crc32 <<= 1;
589 crc32 ^= feedback;
592 while (*ptr++);
594 gcov_crc32 = crc32;
596 if (!gcov_list)
597 atexit (gcov_exit);
599 info->next = gcov_list;
600 gcov_list = info;
602 info->version = 0;
605 /* Called before fork or exec - write out profile information gathered so
606 far and reset it to zero. This avoids duplication or loss of the
607 profile information gathered so far. */
609 void
610 __gcov_flush (void)
612 const struct gcov_info *gi_ptr;
614 gcov_exit ();
615 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
617 unsigned t_ix;
618 const struct gcov_ctr_info *ci_ptr;
620 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
621 if ((1 << t_ix) & gi_ptr->ctr_mask)
623 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
624 ci_ptr++;
629 #endif /* L_gcov */
631 #ifdef L_gcov_merge_add
632 /* The profile merging function that just adds the counters. It is given
633 an array COUNTERS of N_COUNTERS old counters and it reads the same number
634 of counters from the gcov file. */
635 void
636 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
638 for (; n_counters; counters++, n_counters--)
639 *counters += gcov_read_counter ();
641 #endif /* L_gcov_merge_add */
643 #ifdef L_gcov_merge_ior
644 /* The profile merging function that just adds the counters. It is given
645 an array COUNTERS of N_COUNTERS old counters and it reads the same number
646 of counters from the gcov file. */
647 void
648 __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
650 for (; n_counters; counters++, n_counters--)
651 *counters |= gcov_read_counter ();
653 #endif
655 #ifdef L_gcov_merge_single
656 /* The profile merging function for choosing the most common value.
657 It is given an array COUNTERS of N_COUNTERS old counters and it
658 reads the same number of counters from the gcov file. The counters
659 are split into 3-tuples where the members of the tuple have
660 meanings:
662 -- the stored candidate on the most common value of the measured entity
663 -- counter
664 -- total number of evaluations of the value */
665 void
666 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
668 unsigned i, n_measures;
669 gcov_type value, counter, all;
671 gcc_assert (!(n_counters % 3));
672 n_measures = n_counters / 3;
673 for (i = 0; i < n_measures; i++, counters += 3)
675 value = gcov_read_counter ();
676 counter = gcov_read_counter ();
677 all = gcov_read_counter ();
679 if (counters[0] == value)
680 counters[1] += counter;
681 else if (counter > counters[1])
683 counters[0] = value;
684 counters[1] = counter - counters[1];
686 else
687 counters[1] -= counter;
688 counters[2] += all;
691 #endif /* L_gcov_merge_single */
693 #ifdef L_gcov_merge_delta
694 /* The profile merging function for choosing the most common
695 difference between two consecutive evaluations of the value. It is
696 given an array COUNTERS of N_COUNTERS old counters and it reads the
697 same number of counters from the gcov file. The counters are split
698 into 4-tuples where the members of the tuple have meanings:
700 -- the last value of the measured entity
701 -- the stored candidate on the most common difference
702 -- counter
703 -- total number of evaluations of the value */
704 void
705 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
707 unsigned i, n_measures;
708 gcov_type value, counter, all;
710 gcc_assert (!(n_counters % 4));
711 n_measures = n_counters / 4;
712 for (i = 0; i < n_measures; i++, counters += 4)
714 /* last = */ gcov_read_counter ();
715 value = gcov_read_counter ();
716 counter = gcov_read_counter ();
717 all = gcov_read_counter ();
719 if (counters[1] == value)
720 counters[2] += counter;
721 else if (counter > counters[2])
723 counters[1] = value;
724 counters[2] = counter - counters[2];
726 else
727 counters[2] -= counter;
728 counters[3] += all;
731 #endif /* L_gcov_merge_delta */
733 #ifdef L_gcov_interval_profiler
734 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
735 corresponding counter in COUNTERS. If the VALUE is above or below
736 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
737 instead. */
739 void
740 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
741 int start, unsigned steps)
743 gcov_type delta = value - start;
744 if (delta < 0)
745 counters[steps + 1]++;
746 else if (delta >= steps)
747 counters[steps]++;
748 else
749 counters[delta]++;
751 #endif
753 #ifdef L_gcov_pow2_profiler
754 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
755 COUNTERS[0] is incremented. */
757 void
758 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
760 if (value & (value - 1))
761 counters[0]++;
762 else
763 counters[1]++;
765 #endif
767 /* Tries to determine the most common value among its inputs. Checks if the
768 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
769 is incremented. If this is not the case and COUNTERS[1] is not zero,
770 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
771 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
772 function is called more than 50% of the time with one value, this value
773 will be in COUNTERS[0] in the end.
775 In any case, COUNTERS[2] is incremented. */
777 static inline void
778 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
780 if (value == counters[0])
781 counters[1]++;
782 else if (counters[1] == 0)
784 counters[1] = 1;
785 counters[0] = value;
787 else
788 counters[1]--;
789 counters[2]++;
792 #ifdef L_gcov_one_value_profiler
793 void
794 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
796 __gcov_one_value_profiler_body (counters, value);
798 #endif
800 #ifdef L_gcov_indirect_call_profiler
802 /* By default, the C++ compiler will use function addresses in the
803 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
804 tells the compiler to use function descriptors instead. The value
805 of this macro says how many words wide the descriptor is (normally 2),
806 but it may be dependent on target flags. Since we do not have access
807 to the target flags here we just check to see if it is set and use
808 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
810 It is assumed that the address of a function descriptor may be treated
811 as a pointer to a function. */
813 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
814 #define VTABLE_USES_DESCRIPTORS 1
815 #else
816 #define VTABLE_USES_DESCRIPTORS 0
817 #endif
819 /* Tries to determine the most common value among its inputs. */
820 void
821 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
822 void* cur_func, void* callee_func)
824 /* If the C++ virtual tables contain function descriptors then one
825 function may have multiple descriptors and we need to dereference
826 the descriptors to see if they point to the same function. */
827 if (cur_func == callee_func
828 || (VTABLE_USES_DESCRIPTORS && callee_func
829 && *(void **) cur_func == *(void **) callee_func))
830 __gcov_one_value_profiler_body (counter, value);
832 #endif
835 #ifdef L_gcov_average_profiler
836 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
837 to saturate up. */
839 void
840 __gcov_average_profiler (gcov_type *counters, gcov_type value)
842 counters[0] += value;
843 counters[1] ++;
845 #endif
847 #ifdef L_gcov_ior_profiler
848 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
849 to saturate up. */
851 void
852 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
854 *counters |= value;
856 #endif
858 #ifdef L_gcov_fork
859 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
860 that they are not counted twice. */
862 pid_t
863 __gcov_fork (void)
865 __gcov_flush ();
866 return fork ();
868 #endif
870 #ifdef L_gcov_execl
871 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
872 that they are not lost. */
875 __gcov_execl (const char *path, char *arg, ...)
877 va_list ap, aq;
878 unsigned i, length;
879 char **args;
881 __gcov_flush ();
883 va_start (ap, arg);
884 va_copy (aq, ap);
886 length = 2;
887 while (va_arg (ap, char *))
888 length++;
889 va_end (ap);
891 args = (char **) alloca (length * sizeof (void *));
892 args[0] = arg;
893 for (i = 1; i < length; i++)
894 args[i] = va_arg (aq, char *);
895 va_end (aq);
897 return execv (path, args);
899 #endif
901 #ifdef L_gcov_execlp
902 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
903 that they are not lost. */
906 __gcov_execlp (const char *path, char *arg, ...)
908 va_list ap, aq;
909 unsigned i, length;
910 char **args;
912 __gcov_flush ();
914 va_start (ap, arg);
915 va_copy (aq, ap);
917 length = 2;
918 while (va_arg (ap, char *))
919 length++;
920 va_end (ap);
922 args = (char **) alloca (length * sizeof (void *));
923 args[0] = arg;
924 for (i = 1; i < length; i++)
925 args[i] = va_arg (aq, char *);
926 va_end (aq);
928 return execvp (path, args);
930 #endif
932 #ifdef L_gcov_execle
933 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
934 that they are not lost. */
937 __gcov_execle (const char *path, char *arg, ...)
939 va_list ap, aq;
940 unsigned i, length;
941 char **args;
942 char **envp;
944 __gcov_flush ();
946 va_start (ap, arg);
947 va_copy (aq, ap);
949 length = 2;
950 while (va_arg (ap, char *))
951 length++;
952 va_end (ap);
954 args = (char **) alloca (length * sizeof (void *));
955 args[0] = arg;
956 for (i = 1; i < length; i++)
957 args[i] = va_arg (aq, char *);
958 envp = va_arg (aq, char **);
959 va_end (aq);
961 return execve (path, args, envp);
963 #endif
965 #ifdef L_gcov_execv
966 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
967 that they are not lost. */
970 __gcov_execv (const char *path, char *const argv[])
972 __gcov_flush ();
973 return execv (path, argv);
975 #endif
977 #ifdef L_gcov_execvp
978 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
979 that they are not lost. */
982 __gcov_execvp (const char *path, char *const argv[])
984 __gcov_flush ();
985 return execvp (path, argv);
987 #endif
989 #ifdef L_gcov_execve
990 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
991 that they are not lost. */
994 __gcov_execve (const char *path, char *const argv[], char *const envp[])
996 __gcov_flush ();
997 return execve (path, argv, envp);
999 #endif
1000 #endif /* inhibit_libc */