1 /* SPDX-License-Identifier: GPL-3.0-only WITH GCC-exception-3.1 */
3 /* Routines required for instrumenting a program. */
4 /* Compile this one with gcc. */
5 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
6 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011
7 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 Under Section 7 of GPL version 3, you are granted additional
22 permissions described in the GCC Runtime Library Exception, version
23 3.1, as published by the Free Software Foundation.
29 #include <commonlib/helpers.h>
30 #include <console/console.h>
33 #define gcc_assert(x) ASSERT(x)
34 #define fprintf(file, x...) printk(BIOS_ERR, x)
35 #include "gcov-glue.c"
37 /* Define MACROs to be used by coreboot compilation. */
39 # define L_gcov_interval_profiler
40 # define L_gcov_pow2_profiler
41 # define L_gcov_one_value_profiler
42 # define L_gcov_indirect_call_profiler
43 # define L_gcov_average_profiler
44 # define L_gcov_ior_profiler
46 # define HAVE_CC_TLS 0
47 # define __GCOV_KERNEL__
51 #else /* __COREBOOT__ */
54 #include "coretypes.h"
56 #include "libgcc_tm.h"
57 #endif /* __COREBOOT__ */
60 #if defined(inhibit_libc)
61 #define IN_LIBGCOV (-1)
63 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
67 #define GCOV_LINKAGE /* nothing */
70 #endif /* __COREBOOT__ */
73 #if defined(inhibit_libc)
74 /* If libc and its header files are not available, provide dummy functions. */
77 void __gcov_init(struct gcov_info
*p
__attribute__((unused
))) {}
78 void __gcov_flush(void) {}
81 #ifdef L_gcov_merge_add
82 void __gcov_merge_add(gcov_type
*counters
__attribute__((unused
)),
83 unsigned int n_counters
__attribute__((unused
))) {}
86 #ifdef L_gcov_merge_single
87 void __gcov_merge_single(gcov_type
*counters
__attribute__((unused
)),
88 unsigned int n_counters
__attribute__((unused
))) {}
91 #ifdef L_gcov_merge_delta
92 void __gcov_merge_delta(gcov_type
*counters
__attribute__((unused
)),
93 unsigned int n_counters
__attribute__((unused
))) {}
103 #include <sys/stat.h>
106 void __gcov_merge_add(gcov_type
*counters
__attribute__((unused
)),
107 unsigned int n_counters
__attribute__((unused
))) {}
108 #endif /* __COREBOOT__ */
113 struct gcov_fn_buffer
{
114 struct gcov_fn_buffer
*next
;
116 struct gcov_fn_info info
;
117 /* note gcov_fn_info ends in a trailing array. */
120 /* Chain of per-object gcov structures. */
121 static struct gcov_info
*gcov_list
;
123 /* Size of the longest file name. */
124 static size_t gcov_max_filename
= 0;
126 /* Make sure path component of the given FILENAME exists, create
127 missing directories. FILENAME must be writable.
128 Returns zero on success, or -1 if an error occurred. */
131 create_file_directory(char *filename
)
137 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
145 if (HAS_DRIVE_SPEC(s
))
147 if (IS_DIR_SEPARATOR(*s
))
149 for (; *s
!= '\0'; s
++)
150 if (IS_DIR_SEPARATOR(*s
)) {
154 /* Try to make directory if it doesn't already exist. */
155 if (access(filename
, F_OK
) == -1
156 #ifdef TARGET_POSIX_IO
157 && mkdir(filename
, 0755) == -1
159 && mkdir(filename
) == -1
161 /* The directory might have been made by another
164 && errno
!= EEXIST
) {
166 "profiling:%s:Cannot create directory\n",
179 static struct gcov_fn_buffer
*
180 free_fn_data(const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
183 struct gcov_fn_buffer
*next
;
184 unsigned int ix
, n_ctr
= 0;
190 for (ix
= 0; ix
!= limit
; ix
++)
191 if (gi_ptr
->merge
[ix
])
192 free(buffer
->info
.ctrs
[n_ctr
++].values
);
197 static struct gcov_fn_buffer
**
198 buffer_fn_data(const char *filename
, const struct gcov_info
*gi_ptr
,
199 struct gcov_fn_buffer
**end_ptr
, unsigned int fn_ix
)
201 unsigned int n_ctrs
= 0, ix
= 0;
202 struct gcov_fn_buffer
*fn_buffer
;
205 for (ix
= GCOV_COUNTERS
; ix
--;)
206 if (gi_ptr
->merge
[ix
])
209 len
= sizeof(*fn_buffer
) + sizeof(fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
210 fn_buffer
= (struct gcov_fn_buffer
*)malloc(len
);
216 fn_buffer
->fn_ix
= fn_ix
;
217 fn_buffer
->info
.ident
= gcov_read_unsigned();
218 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned();
219 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned();
221 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++) {
222 gcov_unsigned_t length
;
225 if (!gi_ptr
->merge
[ix
])
228 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix
)) {
233 length
= GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
234 len
= length
* sizeof(gcov_type
);
235 values
= (gcov_type
*)malloc(len
);
239 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
240 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
243 *values
++ = gcov_read_counter();
247 *end_ptr
= fn_buffer
;
248 return &fn_buffer
->next
;
251 fprintf(stderr
, "profiling:%s:Function %u %s %u\n", filename
, fn_ix
,
252 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
254 return (struct gcov_fn_buffer
**)free_fn_data(gi_ptr
, fn_buffer
, ix
);
257 /* Add an unsigned value to the current crc */
259 static gcov_unsigned_t
260 crc32_unsigned(gcov_unsigned_t crc32
, gcov_unsigned_t value
)
264 for (ix
= 32; ix
--; value
<<= 1) {
265 unsigned int feedback
;
267 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
275 /* Check if VERSION of the info block PTR matches libgcov one.
276 Return 1 on success, or zero in case of versions mismatch.
277 If FILENAME is not NULL, its value used for reporting purposes
278 instead of value from the info block. */
281 gcov_version(struct gcov_info
*ptr
, gcov_unsigned_t version
,
282 const char *filename
)
284 if (version
!= GCOV_VERSION
) {
287 GCOV_UNSIGNED2STRING(v
, version
);
288 GCOV_UNSIGNED2STRING(e
, GCOV_VERSION
);
291 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
292 filename
? filename
: ptr
->filename
, e
, v
);
298 /* Dump the coverage counts. We merge with existing counts when
299 possible, to avoid growing the .da files ad infinitum. We use this
300 program's checksum to make sure we only accumulate whole program
301 statistics to the correct summary. An object file might be embedded
302 in two separate programs, and we must keep the two program
303 summaries separate. */
308 struct gcov_info
*gi_ptr
;
309 const struct gcov_fn_info
*gfi_ptr
;
310 struct gcov_summary this_prg
; /* summary for program. */
311 struct gcov_summary all_prg
; /* summary for all instances of program. */
312 struct gcov_ctr_summary
*cs_ptr
;
313 const struct gcov_ctr_info
*ci_ptr
;
316 gcov_unsigned_t c_num
;
317 const char *gcov_prefix
;
318 int gcov_prefix_strip
= 0;
319 size_t prefix_length
;
320 char *gi_filename
, *gi_filename_up
;
321 gcov_unsigned_t crc32
= 0;
323 memset(&all_prg
, 0, sizeof(all_prg
));
324 /* Find the totals for this execution. */
325 memset(&this_prg
, 0, sizeof(this_prg
));
326 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
327 crc32
= crc32_unsigned(crc32
, gi_ptr
->stamp
);
328 crc32
= crc32_unsigned(crc32
, gi_ptr
->n_functions
);
330 for (f_ix
= 0; (unsigned int)f_ix
!= gi_ptr
->n_functions
;
332 gfi_ptr
= gi_ptr
->functions
[f_ix
];
334 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
337 crc32
= crc32_unsigned(crc32
, gfi_ptr
338 ? gfi_ptr
->cfg_checksum
: 0);
339 crc32
= crc32_unsigned(crc32
,
340 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
344 ci_ptr
= gfi_ptr
->ctrs
;
345 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++) {
346 if (!gi_ptr
->merge
[t_ix
])
349 cs_ptr
= &this_prg
.ctrs
[t_ix
];
350 cs_ptr
->num
+= ci_ptr
->num
;
351 crc32
= crc32_unsigned(crc32
, ci_ptr
->num
);
353 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++) {
355 ci_ptr
->values
[c_num
];
357 < ci_ptr
->values
[c_num
])
359 ci_ptr
->values
[c_num
];
368 /* Check if the level of dirs to strip off specified. */
369 char *tmp
= getenv("GCOV_PREFIX_STRIP");
371 gcov_prefix_strip
= atoi(tmp
);
372 /* Do not consider negative values. */
373 if (gcov_prefix_strip
< 0)
374 gcov_prefix_strip
= 0;
378 /* Get file name relocation prefix. Non-absolute values are ignored. */
379 gcov_prefix
= getenv("GCOV_PREFIX");
381 prefix_length
= strlen(gcov_prefix
);
383 /* Remove an unnecessary trailing '/' */
384 if (IS_DIR_SEPARATOR(gcov_prefix
[prefix_length
- 1]))
390 /* If no prefix was specified and a prefix strip, then we assume
392 if (gcov_prefix_strip
!= 0 && prefix_length
== 0) {
396 /* Allocate and initialize the filename scratch space plus one. */
397 gi_filename
= (char *) alloca(prefix_length
+ gcov_max_filename
+ 2);
399 memcpy(gi_filename
, gcov_prefix
, prefix_length
);
400 gi_filename_up
= gi_filename
+ prefix_length
;
402 /* Now merge each file. */
403 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
404 unsigned int n_counts
;
405 struct gcov_summary prg
; /* summary for this object over all
407 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
, *cs_all
;
409 gcov_unsigned_t tag
, length
;
410 gcov_position_t summary_pos
= 0;
411 gcov_position_t eof_pos
= 0;
412 const char *fname
, *s
;
413 struct gcov_fn_buffer
*fn_buffer
= NULL
;
414 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
416 fname
= gi_ptr
->filename
;
418 /* Avoid to add multiple drive letters into combined path. */
419 if (prefix_length
!= 0 && HAS_DRIVE_SPEC(fname
))
422 /* Build relocated filename, stripping off leading
423 * directories from the initial filename if requested.
425 if (gcov_prefix_strip
> 0) {
429 if (IS_DIR_SEPARATOR(*s
))
432 /* Skip selected directory levels. */
433 for (; (*s
!= '\0') && (level
< gcov_prefix_strip
); s
++)
434 if (IS_DIR_SEPARATOR(*s
)) {
440 /* Update complete filename with stripped original. */
441 if (prefix_length
!= 0 && !IS_DIR_SEPARATOR(*fname
)) {
442 /* If prefix is given, add directory separator.
444 strcpy(gi_filename_up
, "/");
445 strcpy(gi_filename_up
+ 1, fname
);
447 strcpy(gi_filename_up
, fname
);
449 if (!gcov_open(gi_filename
)) {
450 /* Open failed likely due to missed directory.
451 * Create directory and retry to open file.
453 if (create_file_directory(gi_filename
)) {
454 fprintf(stderr
, "profiling:%s:Skip\n",
458 if (!gcov_open(gi_filename
)) {
460 "profiling:%s:Cannot open\n",
466 tag
= gcov_read_unsigned();
468 /* Merge data from file. */
469 if (tag
!= GCOV_DATA_MAGIC
) {
471 "profiling:%s:Not a gcov data file\n",
475 length
= gcov_read_unsigned();
476 if (!gcov_version(gi_ptr
, length
, gi_filename
))
479 length
= gcov_read_unsigned();
480 if (length
!= gi_ptr
->stamp
)
481 /* Read from a different compilation.
482 * Overwrite the file.
486 /* Look for program summary. */
488 struct gcov_summary tmp
;
490 eof_pos
= gcov_position();
491 tag
= gcov_read_unsigned();
492 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
496 length
= gcov_read_unsigned();
497 if (length
!= GCOV_TAG_SUMMARY_LENGTH
)
499 gcov_read_summary(&tmp
);
500 error
= gcov_is_error();
504 || tmp
.checksum
!= crc32
)
507 for (t_ix
= 0; t_ix
!=
508 GCOV_COUNTERS_SUMMABLE
; t_ix
++)
509 if (tmp
.ctrs
[t_ix
].num
!=
510 this_prg
.ctrs
[t_ix
].num
)
513 summary_pos
= eof_pos
;
518 /* Merge execution counts for each function. */
519 for (f_ix
= 0; (unsigned int)f_ix
!=
521 f_ix
++, tag
= gcov_read_unsigned()) {
522 gfi_ptr
= gi_ptr
->functions
[f_ix
];
524 if (tag
!= GCOV_TAG_FUNCTION
)
527 length
= gcov_read_unsigned();
529 /* This function did not appear
530 * in the other program. We
531 * have nothing to merge.
535 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
538 if (!gfi_ptr
|| gfi_ptr
->key
!=
540 /* This function appears in the
541 * other program. We need to
542 * buffer the information in
543 * order to write it back out --
544 * we'll be inserting data
545 * before this point, so cannot
546 * simply keep the data in the
549 fn_tail
= buffer_fn_data(
557 length
= gcov_read_unsigned();
558 if (length
!= gfi_ptr
->ident
)
561 length
= gcov_read_unsigned();
562 if (length
!= gfi_ptr
->lineno_checksum
)
565 length
= gcov_read_unsigned();
566 if (length
!= gfi_ptr
->cfg_checksum
)
569 ci_ptr
= gfi_ptr
->ctrs
;
570 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
;
572 gcov_merge_fn merge
=
578 tag
= gcov_read_unsigned();
579 length
= gcov_read_unsigned();
580 if (tag
!= GCOV_TAG_FOR_COUNTER(
582 GCOV_TAG_COUNTER_LENGTH(
585 (*merge
)(ci_ptr
->values
,
589 error
= gcov_is_error();
597 "profiling:%s:Merge mismatch for %s %u\n",
598 gi_filename
, f_ix
>= 0 ?
599 "function" : "summary",
600 f_ix
< 0 ? -1 - f_ix
: f_ix
);
607 fprintf(stderr
, "profiling:%s:%s merging\n", gi_filename
,
608 error
< 0 ? "Overflow" : "Error");
615 memset(&prg
, 0, sizeof(prg
));
616 summary_pos
= eof_pos
;
619 /* Merge the summaries. */
620 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++) {
621 cs_prg
= &prg
.ctrs
[t_ix
];
622 cs_tprg
= &this_prg
.ctrs
[t_ix
];
623 cs_all
= &all_prg
.ctrs
[t_ix
];
625 if (gi_ptr
->merge
[t_ix
]) {
627 cs_prg
->num
= cs_tprg
->num
;
628 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
629 if (cs_prg
->run_max
< cs_tprg
->run_max
)
630 cs_prg
->run_max
= cs_tprg
->run_max
;
631 cs_prg
->sum_max
+= cs_tprg
->run_max
;
632 } else if (cs_prg
->runs
)
635 if (!cs_all
->runs
&& cs_prg
->runs
)
636 memcpy(cs_all
, cs_prg
, sizeof(*cs_all
));
637 else if (!all_prg
.checksum
639 || cs_all
->runs
== cs_prg
->runs
)
640 && memcmp(cs_all
, cs_prg
, sizeof(*cs_all
))) {
642 "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
643 gi_filename
, GCOV_LOCKED
? "" :
644 " or concurrently updated without locking support");
645 all_prg
.checksum
= ~0u;
649 prg
.checksum
= crc32
;
651 /* Write out the data. */
653 gcov_write_tag_length(GCOV_DATA_MAGIC
, GCOV_VERSION
);
654 gcov_write_unsigned(gi_ptr
->stamp
);
658 gcov_seek(summary_pos
);
660 /* Generate whole program statistics. */
661 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY
, &prg
);
663 if (summary_pos
< eof_pos
)
666 /* Write execution counts for each function. */
667 for (f_ix
= 0; (unsigned int)f_ix
!= gi_ptr
->n_functions
;
669 unsigned int buffered
= 0;
671 if (fn_buffer
&& fn_buffer
->fn_ix
672 == (unsigned int)f_ix
) {
673 /* Buffered data from another program. */
675 gfi_ptr
= &fn_buffer
->info
;
676 length
= GCOV_TAG_FUNCTION_LENGTH
;
678 gfi_ptr
= gi_ptr
->functions
[f_ix
];
679 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
680 length
= GCOV_TAG_FUNCTION_LENGTH
;
685 gcov_write_tag_length(GCOV_TAG_FUNCTION
, length
);
689 gcov_write_unsigned(gfi_ptr
->ident
);
690 gcov_write_unsigned(gfi_ptr
->lineno_checksum
);
691 gcov_write_unsigned(gfi_ptr
->cfg_checksum
);
693 ci_ptr
= gfi_ptr
->ctrs
;
694 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++) {
695 if (!gi_ptr
->merge
[t_ix
])
698 n_counts
= ci_ptr
->num
;
699 gcov_write_tag_length(
700 GCOV_TAG_FOR_COUNTER(t_ix
),
701 GCOV_TAG_COUNTER_LENGTH(n_counts
));
702 gcov_type
*c_ptr
= ci_ptr
->values
;
704 gcov_write_counter(*c_ptr
++);
708 fn_buffer
= free_fn_data(gi_ptr
, fn_buffer
,
712 gcov_write_unsigned(0);
716 fn_buffer
= free_fn_data(gi_ptr
, fn_buffer
,
719 error
= gcov_close();
721 fprintf(stderr
, error
< 0 ?
722 "profiling:%s:Overflow writing\n" :
723 "profiling:%s:Error writing\n",
728 /* Add a new object file onto the bb chain. Invoked automatically
729 when running an object file's global ctors. */
732 __gcov_init(struct gcov_info
*info
)
734 if (!info
->version
|| !info
->n_functions
)
736 if (gcov_version(info
, info
->version
, 0)) {
737 size_t filename_length
= strlen(info
->filename
);
739 /* Refresh the longest file name information */
740 if (filename_length
> gcov_max_filename
)
741 gcov_max_filename
= filename_length
;
748 info
->next
= gcov_list
;
754 /* Called before fork or exec - write out profile information gathered so
755 far and reset it to zero. This avoids duplication or loss of the
756 profile information gathered so far. */
761 const struct gcov_info
*gi_ptr
;
764 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
767 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++) {
769 const struct gcov_fn_info
*gfi_ptr
=
770 gi_ptr
->functions
[f_ix
];
772 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
774 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
775 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++) {
776 if (!gi_ptr
->merge
[t_ix
])
779 memset(ci_ptr
->values
, 0,
780 sizeof(gcov_type
) * ci_ptr
->num
);
789 #ifdef L_gcov_merge_add
790 /* The profile merging function that just adds the counters. It is given
791 an array COUNTERS of N_COUNTERS old counters and it reads the same number
792 of counters from the gcov file. */
794 __gcov_merge_add(gcov_type
*counters
, unsigned int n_counters
)
796 for (; n_counters
; counters
++, n_counters
--)
797 *counters
+= gcov_read_counter();
799 #endif /* L_gcov_merge_add */
801 #ifdef L_gcov_merge_ior
802 /* The profile merging function that just adds the counters. It is given
803 an array COUNTERS of N_COUNTERS old counters and it reads the same number
804 of counters from the gcov file. */
806 __gcov_merge_ior(gcov_type
*counters
, unsigned int n_counters
)
808 for (; n_counters
; counters
++, n_counters
--)
809 *counters
|= gcov_read_counter();
813 #ifdef L_gcov_merge_single
814 /* The profile merging function for choosing the most common value.
815 * It is given an array COUNTERS of N_COUNTERS old counters and it
816 * reads the same number of counters from the gcov file. The counters
817 * are split into 3-tuples where the members of the tuple have
820 * -- the stored candidate on the most common value of the measured entity
822 * -- total number of evaluations of the value
825 __gcov_merge_single(gcov_type
*counters
, unsigned int n_counters
)
827 unsigned int i
, n_measures
;
828 gcov_type value
, counter
, all
;
830 gcc_assert(!(n_counters
% 3));
831 n_measures
= n_counters
/ 3;
832 for (i
= 0; i
< n_measures
; i
++, counters
+= 3) {
833 value
= gcov_read_counter();
834 counter
= gcov_read_counter();
835 all
= gcov_read_counter();
837 if (counters
[0] == value
)
838 counters
[1] += counter
;
839 else if (counter
> counters
[1]) {
841 counters
[1] = counter
- counters
[1];
843 counters
[1] -= counter
;
847 #endif /* L_gcov_merge_single */
849 #ifdef L_gcov_merge_delta
850 /* The profile merging function for choosing the most common
851 * difference between two consecutive evaluations of the value. It is
852 * given an array COUNTERS of N_COUNTERS old counters and it reads the
853 * same number of counters from the gcov file. The counters are split
854 * into 4-tuples where the members of the tuple have meanings:
856 * -- the last value of the measured entity
857 * -- the stored candidate on the most common difference
859 * -- total number of evaluations of the value
862 __gcov_merge_delta(gcov_type
*counters
, unsigned int n_counters
)
864 unsigned int i
, n_measures
;
865 gcov_type value
, counter
, all
;
867 gcc_assert(!(n_counters
% 4));
868 n_measures
= n_counters
/ 4;
869 for (i
= 0; i
< n_measures
; i
++, counters
+= 4) {
872 value
= gcov_read_counter();
873 counter
= gcov_read_counter();
874 all
= gcov_read_counter();
876 if (counters
[1] == value
)
877 counters
[2] += counter
;
878 else if (counter
> counters
[2]) {
880 counters
[2] = counter
- counters
[2];
882 counters
[2] -= counter
;
886 #endif /* L_gcov_merge_delta */
888 #ifdef L_gcov_interval_profiler
889 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
890 corresponding counter in COUNTERS. If the VALUE is above or below
891 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
895 __gcov_interval_profiler(gcov_type
*counters
, gcov_type value
,
896 int start
, unsigned int steps
)
898 gcov_type delta
= value
- start
;
900 counters
[steps
+ 1]++;
901 else if (delta
>= steps
)
908 #ifdef L_gcov_pow2_profiler
909 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
910 COUNTERS[0] is incremented. */
913 __gcov_pow2_profiler(gcov_type
*counters
, gcov_type value
)
915 if (value
& (value
- 1))
922 /* Tries to determine the most common value among its inputs. Checks if the
923 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
924 is incremented. If this is not the case and COUNTERS[1] is not zero,
925 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
926 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
927 function is called more than 50% of the time with one value, this value
928 will be in COUNTERS[0] in the end.
930 In any case, COUNTERS[2] is incremented. */
933 __gcov_one_value_profiler_body(gcov_type
*counters
, gcov_type value
)
935 if (value
== counters
[0])
937 else if (counters
[1] == 0) {
945 #ifdef L_gcov_one_value_profiler
947 __gcov_one_value_profiler(gcov_type
*counters
, gcov_type value
)
949 __gcov_one_value_profiler_body(counters
, value
);
953 #ifdef L_gcov_indirect_call_profiler
955 /* By default, the C++ compiler will use function addresses in the
956 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
957 tells the compiler to use function descriptors instead. The value
958 of this macro says how many words wide the descriptor is (normally 2),
959 but it may be dependent on target flags. Since we do not have access
960 to the target flags here we just check to see if it is set and use
961 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
963 It is assumed that the address of a function descriptor may be treated
964 as a pointer to a function. */
966 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
967 #define VTABLE_USES_DESCRIPTORS 1
969 #define VTABLE_USES_DESCRIPTORS 0
972 /* Tries to determine the most common value among its inputs. */
974 __gcov_indirect_call_profiler(gcov_type
*counter
, gcov_type value
,
975 void *cur_func
, void *callee_func
)
977 /* If the C++ virtual tables contain function descriptors then one
978 * function may have multiple descriptors and we need to dereference
979 * the descriptors to see if they point to the same function.
981 if (cur_func
== callee_func
982 || (VTABLE_USES_DESCRIPTORS
&& callee_func
983 && *(void **) cur_func
== *(void **) callee_func
))
984 __gcov_one_value_profiler_body(counter
, value
);
989 #ifdef L_gcov_average_profiler
990 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
994 __gcov_average_profiler(gcov_type
*counters
, gcov_type value
)
996 counters
[0] += value
;
1001 #ifdef L_gcov_ior_profiler
1002 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1006 __gcov_ior_profiler(gcov_type
*counters
, gcov_type value
)
1013 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1014 that they are not counted twice. */
1025 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1026 that they are not lost. */
1029 __gcov_execl(const char *path
, char *arg
, ...)
1032 unsigned int i
, length
;
1041 while (va_arg(ap
, char *))
1045 args
= (char **) alloca(length
* sizeof(void *));
1047 for (i
= 1; i
< length
; i
++)
1048 args
[i
] = va_arg(aq
, char *);
1051 return execv(path
, args
);
1055 #ifdef L_gcov_execlp
1056 /* A wrapper for the execlp function. Flushes the accumulated profiling data,
1057 * so that they are not lost.
1061 __gcov_execlp(const char *path
, char *arg
, ...)
1064 unsigned int i
, length
;
1073 while (va_arg(ap
, char *))
1077 args
= (char **) alloca(length
* sizeof(void *));
1079 for (i
= 1; i
< length
; i
++)
1080 args
[i
] = va_arg(aq
, char *);
1083 return execvp(path
, args
);
1087 #ifdef L_gcov_execle
1088 /* A wrapper for the execle function. Flushes the accumulated profiling data,
1089 * so that they are not lost.
1093 __gcov_execle(const char *path
, char *arg
, ...)
1096 unsigned int i
, length
;
1106 while (va_arg(ap
, char *))
1110 args
= (char **) alloca(length
* sizeof(void *));
1112 for (i
= 1; i
< length
; i
++)
1113 args
[i
] = va_arg(aq
, char *);
1114 envp
= va_arg(aq
, char **);
1117 return execve(path
, args
, envp
);
1122 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1123 that they are not lost. */
1126 __gcov_execv(const char *path
, char *const argv
[])
1129 return execv(path
, argv
);
1133 #ifdef L_gcov_execvp
1134 /* A wrapper for the execvp function. Flushes the accumulated profiling data,
1135 * so that they are not lost.
1139 __gcov_execvp(const char *path
, char *const argv
[])
1142 return execvp(path
, argv
);
1146 #ifdef L_gcov_execve
1147 /* A wrapper for the execve function. Flushes the accumulated profiling data,
1148 * so that they are not lost.
1152 __gcov_execve(const char *path
, char *const argv
[], char *const envp
[])
1155 return execve(path
, argv
, envp
);
1158 #endif /* inhibit_libc */