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
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
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.
28 #include <commonlib/helpers.h>
29 #include <console/console.h>
32 #define gcc_assert(x) ASSERT(x)
33 #define fprintf(file, x...) printk(BIOS_ERR, x)
34 #include "gcov-glue.c"
36 /* Define MACROs to be used by coreboot compilation. */
38 # define L_gcov_interval_profiler
39 # define L_gcov_pow2_profiler
40 # define L_gcov_one_value_profiler
41 # define L_gcov_indirect_call_profiler
42 # define L_gcov_average_profiler
43 # define L_gcov_ior_profiler
45 # define HAVE_CC_TLS 0
46 # define __GCOV_KERNEL__
50 #else /* __COREBOOT__ */
53 #include "coretypes.h"
55 #include "libgcc_tm.h"
56 #endif /* __COREBOOT__ */
59 #if defined(inhibit_libc)
60 #define IN_LIBGCOV (-1)
62 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
66 #define GCOV_LINKAGE /* nothing */
69 #endif /* __COREBOOT__ */
72 #if defined(inhibit_libc)
73 /* If libc and its header files are not available, provide dummy functions. */
76 void __gcov_init(struct gcov_info
*p
__attribute__((unused
))) {}
77 void __gcov_flush(void) {}
80 #ifdef L_gcov_merge_add
81 void __gcov_merge_add(gcov_type
*counters
__attribute__((unused
)),
82 unsigned int n_counters
__attribute__((unused
))) {}
85 #ifdef L_gcov_merge_single
86 void __gcov_merge_single(gcov_type
*counters
__attribute__((unused
)),
87 unsigned int n_counters
__attribute__((unused
))) {}
90 #ifdef L_gcov_merge_delta
91 void __gcov_merge_delta(gcov_type
*counters
__attribute__((unused
)),
92 unsigned int n_counters
__attribute__((unused
))) {}
102 #include <sys/stat.h>
105 void __gcov_merge_add(gcov_type
*counters
__attribute__((unused
)),
106 unsigned int n_counters
__attribute__((unused
))) {}
107 #endif /* __COREBOOT__ */
112 struct gcov_fn_buffer
{
113 struct gcov_fn_buffer
*next
;
115 struct gcov_fn_info info
;
116 /* note gcov_fn_info ends in a trailing array. */
119 /* Chain of per-object gcov structures. */
120 static struct gcov_info
*gcov_list
;
122 /* Size of the longest file name. */
123 static size_t gcov_max_filename
= 0;
125 /* Make sure path component of the given FILENAME exists, create
126 missing directories. FILENAME must be writable.
127 Returns zero on success, or -1 if an error occurred. */
130 create_file_directory(char *filename
)
136 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
144 if (HAS_DRIVE_SPEC(s
))
146 if (IS_DIR_SEPARATOR(*s
))
148 for (; *s
!= '\0'; s
++)
149 if (IS_DIR_SEPARATOR(*s
)) {
153 /* Try to make directory if it doesn't already exist. */
154 if (access(filename
, F_OK
) == -1
155 #ifdef TARGET_POSIX_IO
156 && mkdir(filename
, 0755) == -1
158 && mkdir(filename
) == -1
160 /* The directory might have been made by another
163 && errno
!= EEXIST
) {
165 "profiling:%s:Cannot create directory\n",
178 static struct gcov_fn_buffer
*
179 free_fn_data(const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
182 struct gcov_fn_buffer
*next
;
183 unsigned int ix
, n_ctr
= 0;
189 for (ix
= 0; ix
!= limit
; ix
++)
190 if (gi_ptr
->merge
[ix
])
191 free(buffer
->info
.ctrs
[n_ctr
++].values
);
196 static struct gcov_fn_buffer
**
197 buffer_fn_data(const char *filename
, const struct gcov_info
*gi_ptr
,
198 struct gcov_fn_buffer
**end_ptr
, unsigned int fn_ix
)
200 unsigned int n_ctrs
= 0, ix
= 0;
201 struct gcov_fn_buffer
*fn_buffer
;
204 for (ix
= GCOV_COUNTERS
; ix
--;)
205 if (gi_ptr
->merge
[ix
])
208 len
= sizeof(*fn_buffer
) + sizeof(fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
209 fn_buffer
= (struct gcov_fn_buffer
*)malloc(len
);
215 fn_buffer
->fn_ix
= fn_ix
;
216 fn_buffer
->info
.ident
= gcov_read_unsigned();
217 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned();
218 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned();
220 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++) {
221 gcov_unsigned_t length
;
224 if (!gi_ptr
->merge
[ix
])
227 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix
)) {
232 length
= GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
233 len
= length
* sizeof(gcov_type
);
234 values
= (gcov_type
*)malloc(len
);
238 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
239 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
242 *values
++ = gcov_read_counter();
246 *end_ptr
= fn_buffer
;
247 return &fn_buffer
->next
;
250 fprintf(stderr
, "profiling:%s:Function %u %s %u\n", filename
, fn_ix
,
251 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
253 return (struct gcov_fn_buffer
**)free_fn_data(gi_ptr
, fn_buffer
, ix
);
256 /* Add an unsigned value to the current crc */
258 static gcov_unsigned_t
259 crc32_unsigned(gcov_unsigned_t crc32
, gcov_unsigned_t value
)
263 for (ix
= 32; ix
--; value
<<= 1) {
264 unsigned int feedback
;
266 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
274 /* Check if VERSION of the info block PTR matches libgcov one.
275 Return 1 on success, or zero in case of versions mismatch.
276 If FILENAME is not NULL, its value used for reporting purposes
277 instead of value from the info block. */
280 gcov_version(struct gcov_info
*ptr
, gcov_unsigned_t version
,
281 const char *filename
)
283 if (version
!= GCOV_VERSION
) {
286 GCOV_UNSIGNED2STRING(v
, version
);
287 GCOV_UNSIGNED2STRING(e
, GCOV_VERSION
);
290 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
291 filename
? filename
: ptr
->filename
, e
, v
);
297 /* Dump the coverage counts. We merge with existing counts when
298 possible, to avoid growing the .da files ad infinitum. We use this
299 program's checksum to make sure we only accumulate whole program
300 statistics to the correct summary. An object file might be embedded
301 in two separate programs, and we must keep the two program
302 summaries separate. */
307 struct gcov_info
*gi_ptr
;
308 const struct gcov_fn_info
*gfi_ptr
;
309 struct gcov_summary this_prg
; /* summary for program. */
310 struct gcov_summary all_prg
; /* summary for all instances of program. */
311 struct gcov_ctr_summary
*cs_ptr
;
312 const struct gcov_ctr_info
*ci_ptr
;
315 gcov_unsigned_t c_num
;
316 const char *gcov_prefix
;
317 int gcov_prefix_strip
= 0;
318 size_t prefix_length
;
319 char *gi_filename
, *gi_filename_up
;
320 gcov_unsigned_t crc32
= 0;
322 memset(&all_prg
, 0, sizeof(all_prg
));
323 /* Find the totals for this execution. */
324 memset(&this_prg
, 0, sizeof(this_prg
));
325 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
326 crc32
= crc32_unsigned(crc32
, gi_ptr
->stamp
);
327 crc32
= crc32_unsigned(crc32
, gi_ptr
->n_functions
);
329 for (f_ix
= 0; (unsigned int)f_ix
!= gi_ptr
->n_functions
;
331 gfi_ptr
= gi_ptr
->functions
[f_ix
];
333 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
336 crc32
= crc32_unsigned(crc32
, gfi_ptr
337 ? gfi_ptr
->cfg_checksum
: 0);
338 crc32
= crc32_unsigned(crc32
,
339 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
343 ci_ptr
= gfi_ptr
->ctrs
;
344 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++) {
345 if (!gi_ptr
->merge
[t_ix
])
348 cs_ptr
= &this_prg
.ctrs
[t_ix
];
349 cs_ptr
->num
+= ci_ptr
->num
;
350 crc32
= crc32_unsigned(crc32
, ci_ptr
->num
);
352 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++) {
354 ci_ptr
->values
[c_num
];
356 < ci_ptr
->values
[c_num
])
358 ci_ptr
->values
[c_num
];
367 /* Check if the level of dirs to strip off specified. */
368 char *tmp
= getenv("GCOV_PREFIX_STRIP");
370 gcov_prefix_strip
= atoi(tmp
);
371 /* Do not consider negative values. */
372 if (gcov_prefix_strip
< 0)
373 gcov_prefix_strip
= 0;
377 /* Get file name relocation prefix. Non-absolute values are ignored. */
378 gcov_prefix
= getenv("GCOV_PREFIX");
380 prefix_length
= strlen(gcov_prefix
);
382 /* Remove an unnecessary trailing '/' */
383 if (IS_DIR_SEPARATOR(gcov_prefix
[prefix_length
- 1]))
389 /* If no prefix was specified and a prefix strip, then we assume
391 if (gcov_prefix_strip
!= 0 && prefix_length
== 0) {
395 /* Allocate and initialize the filename scratch space plus one. */
396 gi_filename
= (char *) alloca(prefix_length
+ gcov_max_filename
+ 2);
398 memcpy(gi_filename
, gcov_prefix
, prefix_length
);
399 gi_filename_up
= gi_filename
+ prefix_length
;
401 /* Now merge each file. */
402 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
403 unsigned int n_counts
;
404 struct gcov_summary prg
; /* summary for this object over all
406 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
, *cs_all
;
408 gcov_unsigned_t tag
, length
;
409 gcov_position_t summary_pos
= 0;
410 gcov_position_t eof_pos
= 0;
411 const char *fname
, *s
;
412 struct gcov_fn_buffer
*fn_buffer
= NULL
;
413 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
415 fname
= gi_ptr
->filename
;
417 /* Avoid to add multiple drive letters into combined path. */
418 if (prefix_length
!= 0 && HAS_DRIVE_SPEC(fname
))
421 /* Build relocated filename, stripping off leading
422 * directories from the initial filename if requested.
424 if (gcov_prefix_strip
> 0) {
428 if (IS_DIR_SEPARATOR(*s
))
431 /* Skip selected directory levels. */
432 for (; (*s
!= '\0') && (level
< gcov_prefix_strip
); s
++)
433 if (IS_DIR_SEPARATOR(*s
)) {
439 /* Update complete filename with stripped original. */
440 if (prefix_length
!= 0 && !IS_DIR_SEPARATOR(*fname
)) {
441 /* If prefix is given, add directory separator.
443 strcpy(gi_filename_up
, "/");
444 strcpy(gi_filename_up
+ 1, fname
);
446 strcpy(gi_filename_up
, fname
);
448 if (!gcov_open(gi_filename
)) {
449 /* Open failed likely due to missed directory.
450 * Create directory and retry to open file.
452 if (create_file_directory(gi_filename
)) {
453 fprintf(stderr
, "profiling:%s:Skip\n",
457 if (!gcov_open(gi_filename
)) {
459 "profiling:%s:Cannot open\n",
465 tag
= gcov_read_unsigned();
467 /* Merge data from file. */
468 if (tag
!= GCOV_DATA_MAGIC
) {
470 "profiling:%s:Not a gcov data file\n",
474 length
= gcov_read_unsigned();
475 if (!gcov_version(gi_ptr
, length
, gi_filename
))
478 length
= gcov_read_unsigned();
479 if (length
!= gi_ptr
->stamp
)
480 /* Read from a different compilation.
481 * Overwrite the file.
485 /* Look for program summary. */
487 struct gcov_summary tmp
;
489 eof_pos
= gcov_position();
490 tag
= gcov_read_unsigned();
491 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
495 length
= gcov_read_unsigned();
496 if (length
!= GCOV_TAG_SUMMARY_LENGTH
)
498 gcov_read_summary(&tmp
);
499 error
= gcov_is_error();
503 || tmp
.checksum
!= crc32
)
506 for (t_ix
= 0; t_ix
!=
507 GCOV_COUNTERS_SUMMABLE
; t_ix
++)
508 if (tmp
.ctrs
[t_ix
].num
!=
509 this_prg
.ctrs
[t_ix
].num
)
512 summary_pos
= eof_pos
;
517 /* Merge execution counts for each function. */
518 for (f_ix
= 0; (unsigned int)f_ix
!=
520 f_ix
++, tag
= gcov_read_unsigned()) {
521 gfi_ptr
= gi_ptr
->functions
[f_ix
];
523 if (tag
!= GCOV_TAG_FUNCTION
)
526 length
= gcov_read_unsigned();
528 /* This function did not appear
529 * in the other program. We
530 * have nothing to merge.
534 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
537 if (!gfi_ptr
|| gfi_ptr
->key
!=
539 /* This function appears in the
540 * other program. We need to
541 * buffer the information in
542 * order to write it back out --
543 * we'll be inserting data
544 * before this point, so cannot
545 * simply keep the data in the
548 fn_tail
= buffer_fn_data(
556 length
= gcov_read_unsigned();
557 if (length
!= gfi_ptr
->ident
)
560 length
= gcov_read_unsigned();
561 if (length
!= gfi_ptr
->lineno_checksum
)
564 length
= gcov_read_unsigned();
565 if (length
!= gfi_ptr
->cfg_checksum
)
568 ci_ptr
= gfi_ptr
->ctrs
;
569 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
;
571 gcov_merge_fn merge
=
577 tag
= gcov_read_unsigned();
578 length
= gcov_read_unsigned();
579 if (tag
!= GCOV_TAG_FOR_COUNTER(
581 GCOV_TAG_COUNTER_LENGTH(
584 (*merge
)(ci_ptr
->values
,
588 error
= gcov_is_error();
596 "profiling:%s:Merge mismatch for %s %u\n",
597 gi_filename
, f_ix
>= 0 ?
598 "function" : "summary",
599 f_ix
< 0 ? -1 - f_ix
: f_ix
);
606 fprintf(stderr
, "profiling:%s:%s merging\n", gi_filename
,
607 error
< 0 ? "Overflow" : "Error");
614 memset(&prg
, 0, sizeof(prg
));
615 summary_pos
= eof_pos
;
618 /* Merge the summaries. */
619 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++) {
620 cs_prg
= &prg
.ctrs
[t_ix
];
621 cs_tprg
= &this_prg
.ctrs
[t_ix
];
622 cs_all
= &all_prg
.ctrs
[t_ix
];
624 if (gi_ptr
->merge
[t_ix
]) {
626 cs_prg
->num
= cs_tprg
->num
;
627 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
628 if (cs_prg
->run_max
< cs_tprg
->run_max
)
629 cs_prg
->run_max
= cs_tprg
->run_max
;
630 cs_prg
->sum_max
+= cs_tprg
->run_max
;
631 } else if (cs_prg
->runs
)
634 if (!cs_all
->runs
&& cs_prg
->runs
)
635 memcpy(cs_all
, cs_prg
, sizeof(*cs_all
));
636 else if (!all_prg
.checksum
638 || cs_all
->runs
== cs_prg
->runs
)
639 && memcmp(cs_all
, cs_prg
, sizeof(*cs_all
))) {
641 "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
642 gi_filename
, GCOV_LOCKED
? "" :
643 " or concurrently updated without locking support");
644 all_prg
.checksum
= ~0u;
648 prg
.checksum
= crc32
;
650 /* Write out the data. */
652 gcov_write_tag_length(GCOV_DATA_MAGIC
, GCOV_VERSION
);
653 gcov_write_unsigned(gi_ptr
->stamp
);
657 gcov_seek(summary_pos
);
659 /* Generate whole program statistics. */
660 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY
, &prg
);
662 if (summary_pos
< eof_pos
)
665 /* Write execution counts for each function. */
666 for (f_ix
= 0; (unsigned int)f_ix
!= gi_ptr
->n_functions
;
668 unsigned int buffered
= 0;
670 if (fn_buffer
&& fn_buffer
->fn_ix
671 == (unsigned int)f_ix
) {
672 /* Buffered data from another program. */
674 gfi_ptr
= &fn_buffer
->info
;
675 length
= GCOV_TAG_FUNCTION_LENGTH
;
677 gfi_ptr
= gi_ptr
->functions
[f_ix
];
678 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
679 length
= GCOV_TAG_FUNCTION_LENGTH
;
684 gcov_write_tag_length(GCOV_TAG_FUNCTION
, length
);
688 gcov_write_unsigned(gfi_ptr
->ident
);
689 gcov_write_unsigned(gfi_ptr
->lineno_checksum
);
690 gcov_write_unsigned(gfi_ptr
->cfg_checksum
);
692 ci_ptr
= gfi_ptr
->ctrs
;
693 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++) {
694 if (!gi_ptr
->merge
[t_ix
])
697 n_counts
= ci_ptr
->num
;
698 gcov_write_tag_length(
699 GCOV_TAG_FOR_COUNTER(t_ix
),
700 GCOV_TAG_COUNTER_LENGTH(n_counts
));
701 gcov_type
*c_ptr
= ci_ptr
->values
;
703 gcov_write_counter(*c_ptr
++);
707 fn_buffer
= free_fn_data(gi_ptr
, fn_buffer
,
711 gcov_write_unsigned(0);
715 fn_buffer
= free_fn_data(gi_ptr
, fn_buffer
,
718 error
= gcov_close();
720 fprintf(stderr
, error
< 0 ?
721 "profiling:%s:Overflow writing\n" :
722 "profiling:%s:Error writing\n",
727 /* Add a new object file onto the bb chain. Invoked automatically
728 when running an object file's global ctors. */
731 __gcov_init(struct gcov_info
*info
)
733 if (!info
->version
|| !info
->n_functions
)
735 if (gcov_version(info
, info
->version
, 0)) {
736 size_t filename_length
= strlen(info
->filename
);
738 /* Refresh the longest file name information */
739 if (filename_length
> gcov_max_filename
)
740 gcov_max_filename
= filename_length
;
747 info
->next
= gcov_list
;
753 /* Called before fork or exec - write out profile information gathered so
754 far and reset it to zero. This avoids duplication or loss of the
755 profile information gathered so far. */
760 const struct gcov_info
*gi_ptr
;
763 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
766 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++) {
768 const struct gcov_fn_info
*gfi_ptr
=
769 gi_ptr
->functions
[f_ix
];
771 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
773 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
774 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++) {
775 if (!gi_ptr
->merge
[t_ix
])
778 memset(ci_ptr
->values
, 0,
779 sizeof(gcov_type
) * ci_ptr
->num
);
788 #ifdef L_gcov_merge_add
789 /* The profile merging function that just adds the counters. It is given
790 an array COUNTERS of N_COUNTERS old counters and it reads the same number
791 of counters from the gcov file. */
793 __gcov_merge_add(gcov_type
*counters
, unsigned int n_counters
)
795 for (; n_counters
; counters
++, n_counters
--)
796 *counters
+= gcov_read_counter();
798 #endif /* L_gcov_merge_add */
800 #ifdef L_gcov_merge_ior
801 /* The profile merging function that just adds the counters. It is given
802 an array COUNTERS of N_COUNTERS old counters and it reads the same number
803 of counters from the gcov file. */
805 __gcov_merge_ior(gcov_type
*counters
, unsigned int n_counters
)
807 for (; n_counters
; counters
++, n_counters
--)
808 *counters
|= gcov_read_counter();
812 #ifdef L_gcov_merge_single
813 /* The profile merging function for choosing the most common value.
814 * It is given an array COUNTERS of N_COUNTERS old counters and it
815 * reads the same number of counters from the gcov file. The counters
816 * are split into 3-tuples where the members of the tuple have
819 * -- the stored candidate on the most common value of the measured entity
821 * -- total number of evaluations of the value
824 __gcov_merge_single(gcov_type
*counters
, unsigned int n_counters
)
826 unsigned int i
, n_measures
;
827 gcov_type value
, counter
, all
;
829 gcc_assert(!(n_counters
% 3));
830 n_measures
= n_counters
/ 3;
831 for (i
= 0; i
< n_measures
; i
++, counters
+= 3) {
832 value
= gcov_read_counter();
833 counter
= gcov_read_counter();
834 all
= gcov_read_counter();
836 if (counters
[0] == value
)
837 counters
[1] += counter
;
838 else if (counter
> counters
[1]) {
840 counters
[1] = counter
- counters
[1];
842 counters
[1] -= counter
;
846 #endif /* L_gcov_merge_single */
848 #ifdef L_gcov_merge_delta
849 /* The profile merging function for choosing the most common
850 * difference between two consecutive evaluations of the value. It is
851 * given an array COUNTERS of N_COUNTERS old counters and it reads the
852 * same number of counters from the gcov file. The counters are split
853 * into 4-tuples where the members of the tuple have meanings:
855 * -- the last value of the measured entity
856 * -- the stored candidate on the most common difference
858 * -- total number of evaluations of the value
861 __gcov_merge_delta(gcov_type
*counters
, unsigned int n_counters
)
863 unsigned int i
, n_measures
;
864 gcov_type value
, counter
, all
;
866 gcc_assert(!(n_counters
% 4));
867 n_measures
= n_counters
/ 4;
868 for (i
= 0; i
< n_measures
; i
++, counters
+= 4) {
871 value
= gcov_read_counter();
872 counter
= gcov_read_counter();
873 all
= gcov_read_counter();
875 if (counters
[1] == value
)
876 counters
[2] += counter
;
877 else if (counter
> counters
[2]) {
879 counters
[2] = counter
- counters
[2];
881 counters
[2] -= counter
;
885 #endif /* L_gcov_merge_delta */
887 #ifdef L_gcov_interval_profiler
888 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
889 corresponding counter in COUNTERS. If the VALUE is above or below
890 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
894 __gcov_interval_profiler(gcov_type
*counters
, gcov_type value
,
895 int start
, unsigned int steps
)
897 gcov_type delta
= value
- start
;
899 counters
[steps
+ 1]++;
900 else if (delta
>= steps
)
907 #ifdef L_gcov_pow2_profiler
908 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
909 COUNTERS[0] is incremented. */
912 __gcov_pow2_profiler(gcov_type
*counters
, gcov_type value
)
914 if (value
& (value
- 1))
921 /* Tries to determine the most common value among its inputs. Checks if the
922 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
923 is incremented. If this is not the case and COUNTERS[1] is not zero,
924 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
925 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
926 function is called more than 50% of the time with one value, this value
927 will be in COUNTERS[0] in the end.
929 In any case, COUNTERS[2] is incremented. */
932 __gcov_one_value_profiler_body(gcov_type
*counters
, gcov_type value
)
934 if (value
== counters
[0])
936 else if (counters
[1] == 0) {
944 #ifdef L_gcov_one_value_profiler
946 __gcov_one_value_profiler(gcov_type
*counters
, gcov_type value
)
948 __gcov_one_value_profiler_body(counters
, value
);
952 #ifdef L_gcov_indirect_call_profiler
954 /* By default, the C++ compiler will use function addresses in the
955 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
956 tells the compiler to use function descriptors instead. The value
957 of this macro says how many words wide the descriptor is (normally 2),
958 but it may be dependent on target flags. Since we do not have access
959 to the target flags here we just check to see if it is set and use
960 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
962 It is assumed that the address of a function descriptor may be treated
963 as a pointer to a function. */
965 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
966 #define VTABLE_USES_DESCRIPTORS 1
968 #define VTABLE_USES_DESCRIPTORS 0
971 /* Tries to determine the most common value among its inputs. */
973 __gcov_indirect_call_profiler(gcov_type
*counter
, gcov_type value
,
974 void *cur_func
, void *callee_func
)
976 /* If the C++ virtual tables contain function descriptors then one
977 * function may have multiple descriptors and we need to dereference
978 * the descriptors to see if they point to the same function.
980 if (cur_func
== callee_func
981 || (VTABLE_USES_DESCRIPTORS
&& callee_func
982 && *(void **) cur_func
== *(void **) callee_func
))
983 __gcov_one_value_profiler_body(counter
, value
);
988 #ifdef L_gcov_average_profiler
989 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
993 __gcov_average_profiler(gcov_type
*counters
, gcov_type value
)
995 counters
[0] += value
;
1000 #ifdef L_gcov_ior_profiler
1001 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1005 __gcov_ior_profiler(gcov_type
*counters
, gcov_type value
)
1012 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1013 that they are not counted twice. */
1024 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1025 that they are not lost. */
1028 __gcov_execl(const char *path
, char *arg
, ...)
1031 unsigned int i
, length
;
1040 while (va_arg(ap
, char *))
1044 args
= (char **) alloca(length
* sizeof(void *));
1046 for (i
= 1; i
< length
; i
++)
1047 args
[i
] = va_arg(aq
, char *);
1050 return execv(path
, args
);
1054 #ifdef L_gcov_execlp
1055 /* A wrapper for the execlp function. Flushes the accumulated profiling data,
1056 * so that they are not lost.
1060 __gcov_execlp(const char *path
, char *arg
, ...)
1063 unsigned int i
, length
;
1072 while (va_arg(ap
, char *))
1076 args
= (char **) alloca(length
* sizeof(void *));
1078 for (i
= 1; i
< length
; i
++)
1079 args
[i
] = va_arg(aq
, char *);
1082 return execvp(path
, args
);
1086 #ifdef L_gcov_execle
1087 /* A wrapper for the execle function. Flushes the accumulated profiling data,
1088 * so that they are not lost.
1092 __gcov_execle(const char *path
, char *arg
, ...)
1095 unsigned int i
, length
;
1105 while (va_arg(ap
, char *))
1109 args
= (char **) alloca(length
* sizeof(void *));
1111 for (i
= 1; i
< length
; i
++)
1112 args
[i
] = va_arg(aq
, char *);
1113 envp
= va_arg(aq
, char **);
1116 return execve(path
, args
, envp
);
1121 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1122 that they are not lost. */
1125 __gcov_execv(const char *path
, char *const argv
[])
1128 return execv(path
, argv
);
1132 #ifdef L_gcov_execvp
1133 /* A wrapper for the execvp function. Flushes the accumulated profiling data,
1134 * so that they are not lost.
1138 __gcov_execvp(const char *path
, char *const argv
[])
1141 return execvp(path
, argv
);
1145 #ifdef L_gcov_execve
1146 /* A wrapper for the execve function. Flushes the accumulated profiling data,
1147 * so that they are not lost.
1151 __gcov_execve(const char *path
, char *const argv
[], char *const envp
[])
1154 return execve(path
, argv
, envp
);
1157 #endif /* inhibit_libc */