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.
30 #include <commonlib/helpers.h>
31 #include <console/console.h>
34 #define gcc_assert(x) ASSERT(x)
35 #define fprintf(file, x...) printk(BIOS_ERR, x)
36 #include "gcov-glue.c"
38 /* Define MACROs to be used by coreboot compilation. */
40 # define L_gcov_interval_profiler
41 # define L_gcov_pow2_profiler
42 # define L_gcov_one_value_profiler
43 # define L_gcov_indirect_call_profiler
44 # define L_gcov_average_profiler
45 # define L_gcov_ior_profiler
47 # define HAVE_CC_TLS 0
48 # define __GCOV_KERNEL__
52 #else /* __COREBOOT__ */
55 #include "coretypes.h"
57 #include "libgcc_tm.h"
58 #endif /* __COREBOOT__ */
61 #if defined(inhibit_libc)
62 #define IN_LIBGCOV (-1)
64 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
68 #define GCOV_LINKAGE /* nothing */
71 #endif /* __COREBOOT__ */
74 #if defined(inhibit_libc)
75 /* If libc and its header files are not available, provide dummy functions. */
78 void __gcov_init(struct gcov_info
*p
__attribute__((unused
))) {}
79 void __gcov_flush(void) {}
82 #ifdef L_gcov_merge_add
83 void __gcov_merge_add(gcov_type
*counters
__attribute__((unused
)),
84 unsigned int n_counters
__attribute__((unused
))) {}
87 #ifdef L_gcov_merge_single
88 void __gcov_merge_single(gcov_type
*counters
__attribute__((unused
)),
89 unsigned int n_counters
__attribute__((unused
))) {}
92 #ifdef L_gcov_merge_delta
93 void __gcov_merge_delta(gcov_type
*counters
__attribute__((unused
)),
94 unsigned int n_counters
__attribute__((unused
))) {}
104 #include <sys/stat.h>
107 void __gcov_merge_add(gcov_type
*counters
__attribute__((unused
)),
108 unsigned int n_counters
__attribute__((unused
))) {}
109 #endif /* __COREBOOT__ */
114 struct gcov_fn_buffer
{
115 struct gcov_fn_buffer
*next
;
117 struct gcov_fn_info info
;
118 /* note gcov_fn_info ends in a trailing array. */
121 /* Chain of per-object gcov structures. */
122 static struct gcov_info
*gcov_list
;
124 /* Size of the longest file name. */
125 static size_t gcov_max_filename
= 0;
127 /* Make sure path component of the given FILENAME exists, create
128 missing directories. FILENAME must be writable.
129 Returns zero on success, or -1 if an error occurred. */
132 create_file_directory(char *filename
)
138 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
146 if (HAS_DRIVE_SPEC(s
))
148 if (IS_DIR_SEPARATOR(*s
))
150 for (; *s
!= '\0'; s
++)
151 if (IS_DIR_SEPARATOR(*s
)) {
155 /* Try to make directory if it doesn't already exist. */
156 if (access(filename
, F_OK
) == -1
157 #ifdef TARGET_POSIX_IO
158 && mkdir(filename
, 0755) == -1
160 && mkdir(filename
) == -1
162 /* The directory might have been made by another
165 && errno
!= EEXIST
) {
167 "profiling:%s:Cannot create directory\n",
180 static struct gcov_fn_buffer
*
181 free_fn_data(const struct gcov_info
*gi_ptr
, struct gcov_fn_buffer
*buffer
,
184 struct gcov_fn_buffer
*next
;
185 unsigned int ix
, n_ctr
= 0;
191 for (ix
= 0; ix
!= limit
; ix
++)
192 if (gi_ptr
->merge
[ix
])
193 free(buffer
->info
.ctrs
[n_ctr
++].values
);
198 static struct gcov_fn_buffer
**
199 buffer_fn_data(const char *filename
, const struct gcov_info
*gi_ptr
,
200 struct gcov_fn_buffer
**end_ptr
, unsigned int fn_ix
)
202 unsigned int n_ctrs
= 0, ix
= 0;
203 struct gcov_fn_buffer
*fn_buffer
;
206 for (ix
= GCOV_COUNTERS
; ix
--;)
207 if (gi_ptr
->merge
[ix
])
210 len
= sizeof(*fn_buffer
) + sizeof(fn_buffer
->info
.ctrs
[0]) * n_ctrs
;
211 fn_buffer
= (struct gcov_fn_buffer
*)malloc(len
);
217 fn_buffer
->fn_ix
= fn_ix
;
218 fn_buffer
->info
.ident
= gcov_read_unsigned();
219 fn_buffer
->info
.lineno_checksum
= gcov_read_unsigned();
220 fn_buffer
->info
.cfg_checksum
= gcov_read_unsigned();
222 for (n_ctrs
= ix
= 0; ix
!= GCOV_COUNTERS
; ix
++) {
223 gcov_unsigned_t length
;
226 if (!gi_ptr
->merge
[ix
])
229 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix
)) {
234 length
= GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
235 len
= length
* sizeof(gcov_type
);
236 values
= (gcov_type
*)malloc(len
);
240 fn_buffer
->info
.ctrs
[n_ctrs
].num
= length
;
241 fn_buffer
->info
.ctrs
[n_ctrs
].values
= values
;
244 *values
++ = gcov_read_counter();
248 *end_ptr
= fn_buffer
;
249 return &fn_buffer
->next
;
252 fprintf(stderr
, "profiling:%s:Function %u %s %u\n", filename
, fn_ix
,
253 len
? "cannot allocate" : "counter mismatch", len
? len
: ix
);
255 return (struct gcov_fn_buffer
**)free_fn_data(gi_ptr
, fn_buffer
, ix
);
258 /* Add an unsigned value to the current crc */
260 static gcov_unsigned_t
261 crc32_unsigned(gcov_unsigned_t crc32
, gcov_unsigned_t value
)
265 for (ix
= 32; ix
--; value
<<= 1) {
266 unsigned int feedback
;
268 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
276 /* Check if VERSION of the info block PTR matches libgcov one.
277 Return 1 on success, or zero in case of versions mismatch.
278 If FILENAME is not NULL, its value used for reporting purposes
279 instead of value from the info block. */
282 gcov_version(struct gcov_info
*ptr
, gcov_unsigned_t version
,
283 const char *filename
)
285 if (version
!= GCOV_VERSION
) {
288 GCOV_UNSIGNED2STRING(v
, version
);
289 GCOV_UNSIGNED2STRING(e
, GCOV_VERSION
);
292 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
293 filename
? filename
: ptr
->filename
, e
, v
);
299 /* Dump the coverage counts. We merge with existing counts when
300 possible, to avoid growing the .da files ad infinitum. We use this
301 program's checksum to make sure we only accumulate whole program
302 statistics to the correct summary. An object file might be embedded
303 in two separate programs, and we must keep the two program
304 summaries separate. */
309 struct gcov_info
*gi_ptr
;
310 const struct gcov_fn_info
*gfi_ptr
;
311 struct gcov_summary this_prg
; /* summary for program. */
312 struct gcov_summary all_prg
; /* summary for all instances of program. */
313 struct gcov_ctr_summary
*cs_ptr
;
314 const struct gcov_ctr_info
*ci_ptr
;
317 gcov_unsigned_t c_num
;
318 const char *gcov_prefix
;
319 int gcov_prefix_strip
= 0;
320 size_t prefix_length
;
321 char *gi_filename
, *gi_filename_up
;
322 gcov_unsigned_t crc32
= 0;
324 memset(&all_prg
, 0, sizeof(all_prg
));
325 /* Find the totals for this execution. */
326 memset(&this_prg
, 0, sizeof(this_prg
));
327 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
328 crc32
= crc32_unsigned(crc32
, gi_ptr
->stamp
);
329 crc32
= crc32_unsigned(crc32
, gi_ptr
->n_functions
);
331 for (f_ix
= 0; (unsigned int)f_ix
!= gi_ptr
->n_functions
;
333 gfi_ptr
= gi_ptr
->functions
[f_ix
];
335 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
338 crc32
= crc32_unsigned(crc32
, gfi_ptr
339 ? gfi_ptr
->cfg_checksum
: 0);
340 crc32
= crc32_unsigned(crc32
,
341 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
345 ci_ptr
= gfi_ptr
->ctrs
;
346 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++) {
347 if (!gi_ptr
->merge
[t_ix
])
350 cs_ptr
= &this_prg
.ctrs
[t_ix
];
351 cs_ptr
->num
+= ci_ptr
->num
;
352 crc32
= crc32_unsigned(crc32
, ci_ptr
->num
);
354 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++) {
356 ci_ptr
->values
[c_num
];
358 < ci_ptr
->values
[c_num
])
360 ci_ptr
->values
[c_num
];
369 /* Check if the level of dirs to strip off specified. */
370 char *tmp
= getenv("GCOV_PREFIX_STRIP");
372 gcov_prefix_strip
= atoi(tmp
);
373 /* Do not consider negative values. */
374 if (gcov_prefix_strip
< 0)
375 gcov_prefix_strip
= 0;
379 /* Get file name relocation prefix. Non-absolute values are ignored. */
380 gcov_prefix
= getenv("GCOV_PREFIX");
382 prefix_length
= strlen(gcov_prefix
);
384 /* Remove an unnecessary trailing '/' */
385 if (IS_DIR_SEPARATOR(gcov_prefix
[prefix_length
- 1]))
391 /* If no prefix was specified and a prefix strip, then we assume
393 if (gcov_prefix_strip
!= 0 && prefix_length
== 0) {
397 /* Allocate and initialize the filename scratch space plus one. */
398 gi_filename
= (char *) alloca(prefix_length
+ gcov_max_filename
+ 2);
400 memcpy(gi_filename
, gcov_prefix
, prefix_length
);
401 gi_filename_up
= gi_filename
+ prefix_length
;
403 /* Now merge each file. */
404 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
405 unsigned int n_counts
;
406 struct gcov_summary prg
; /* summary for this object over all
408 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
, *cs_all
;
410 gcov_unsigned_t tag
, length
;
411 gcov_position_t summary_pos
= 0;
412 gcov_position_t eof_pos
= 0;
413 const char *fname
, *s
;
414 struct gcov_fn_buffer
*fn_buffer
= NULL
;
415 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
417 fname
= gi_ptr
->filename
;
419 /* Avoid to add multiple drive letters into combined path. */
420 if (prefix_length
!= 0 && HAS_DRIVE_SPEC(fname
))
423 /* Build relocated filename, stripping off leading
424 * directories from the initial filename if requested.
426 if (gcov_prefix_strip
> 0) {
430 if (IS_DIR_SEPARATOR(*s
))
433 /* Skip selected directory levels. */
434 for (; (*s
!= '\0') && (level
< gcov_prefix_strip
); s
++)
435 if (IS_DIR_SEPARATOR(*s
)) {
441 /* Update complete filename with stripped original. */
442 if (prefix_length
!= 0 && !IS_DIR_SEPARATOR(*fname
)) {
443 /* If prefix is given, add directory separator.
445 strcpy(gi_filename_up
, "/");
446 strcpy(gi_filename_up
+ 1, fname
);
448 strcpy(gi_filename_up
, fname
);
450 if (!gcov_open(gi_filename
)) {
451 /* Open failed likely due to missed directory.
452 * Create directory and retry to open file.
454 if (create_file_directory(gi_filename
)) {
455 fprintf(stderr
, "profiling:%s:Skip\n",
459 if (!gcov_open(gi_filename
)) {
461 "profiling:%s:Cannot open\n",
467 tag
= gcov_read_unsigned();
469 /* Merge data from file. */
470 if (tag
!= GCOV_DATA_MAGIC
) {
472 "profiling:%s:Not a gcov data file\n",
476 length
= gcov_read_unsigned();
477 if (!gcov_version(gi_ptr
, length
, gi_filename
))
480 length
= gcov_read_unsigned();
481 if (length
!= gi_ptr
->stamp
)
482 /* Read from a different compilation.
483 * Overwrite the file.
487 /* Look for program summary. */
489 struct gcov_summary tmp
;
491 eof_pos
= gcov_position();
492 tag
= gcov_read_unsigned();
493 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
497 length
= gcov_read_unsigned();
498 if (length
!= GCOV_TAG_SUMMARY_LENGTH
)
500 gcov_read_summary(&tmp
);
501 error
= gcov_is_error();
505 || tmp
.checksum
!= crc32
)
508 for (t_ix
= 0; t_ix
!=
509 GCOV_COUNTERS_SUMMABLE
; t_ix
++)
510 if (tmp
.ctrs
[t_ix
].num
!=
511 this_prg
.ctrs
[t_ix
].num
)
514 summary_pos
= eof_pos
;
519 /* Merge execution counts for each function. */
520 for (f_ix
= 0; (unsigned int)f_ix
!=
522 f_ix
++, tag
= gcov_read_unsigned()) {
523 gfi_ptr
= gi_ptr
->functions
[f_ix
];
525 if (tag
!= GCOV_TAG_FUNCTION
)
528 length
= gcov_read_unsigned();
530 /* This function did not appear
531 * in the other program. We
532 * have nothing to merge.
536 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
539 if (!gfi_ptr
|| gfi_ptr
->key
!=
541 /* This function appears in the
542 * other program. We need to
543 * buffer the information in
544 * order to write it back out --
545 * we'll be inserting data
546 * before this point, so cannot
547 * simply keep the data in the
550 fn_tail
= buffer_fn_data(
558 length
= gcov_read_unsigned();
559 if (length
!= gfi_ptr
->ident
)
562 length
= gcov_read_unsigned();
563 if (length
!= gfi_ptr
->lineno_checksum
)
566 length
= gcov_read_unsigned();
567 if (length
!= gfi_ptr
->cfg_checksum
)
570 ci_ptr
= gfi_ptr
->ctrs
;
571 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
;
573 gcov_merge_fn merge
=
579 tag
= gcov_read_unsigned();
580 length
= gcov_read_unsigned();
581 if (tag
!= GCOV_TAG_FOR_COUNTER(
583 GCOV_TAG_COUNTER_LENGTH(
586 (*merge
)(ci_ptr
->values
,
590 error
= gcov_is_error();
598 "profiling:%s:Merge mismatch for %s %u\n",
599 gi_filename
, f_ix
>= 0 ?
600 "function" : "summary",
601 f_ix
< 0 ? -1 - f_ix
: f_ix
);
608 fprintf(stderr
, "profiling:%s:%s merging\n", gi_filename
,
609 error
< 0 ? "Overflow" : "Error");
616 memset(&prg
, 0, sizeof(prg
));
617 summary_pos
= eof_pos
;
620 /* Merge the summaries. */
621 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++) {
622 cs_prg
= &prg
.ctrs
[t_ix
];
623 cs_tprg
= &this_prg
.ctrs
[t_ix
];
624 cs_all
= &all_prg
.ctrs
[t_ix
];
626 if (gi_ptr
->merge
[t_ix
]) {
628 cs_prg
->num
= cs_tprg
->num
;
629 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
630 if (cs_prg
->run_max
< cs_tprg
->run_max
)
631 cs_prg
->run_max
= cs_tprg
->run_max
;
632 cs_prg
->sum_max
+= cs_tprg
->run_max
;
633 } else if (cs_prg
->runs
)
636 if (!cs_all
->runs
&& cs_prg
->runs
)
637 memcpy(cs_all
, cs_prg
, sizeof(*cs_all
));
638 else if (!all_prg
.checksum
640 || cs_all
->runs
== cs_prg
->runs
)
641 && memcmp(cs_all
, cs_prg
, sizeof(*cs_all
))) {
643 "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
644 gi_filename
, GCOV_LOCKED
? "" :
645 " or concurrently updated without locking support");
646 all_prg
.checksum
= ~0u;
650 prg
.checksum
= crc32
;
652 /* Write out the data. */
654 gcov_write_tag_length(GCOV_DATA_MAGIC
, GCOV_VERSION
);
655 gcov_write_unsigned(gi_ptr
->stamp
);
659 gcov_seek(summary_pos
);
661 /* Generate whole program statistics. */
662 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY
, &prg
);
664 if (summary_pos
< eof_pos
)
667 /* Write execution counts for each function. */
668 for (f_ix
= 0; (unsigned int)f_ix
!= gi_ptr
->n_functions
;
670 unsigned int buffered
= 0;
672 if (fn_buffer
&& fn_buffer
->fn_ix
673 == (unsigned int)f_ix
) {
674 /* Buffered data from another program. */
676 gfi_ptr
= &fn_buffer
->info
;
677 length
= GCOV_TAG_FUNCTION_LENGTH
;
679 gfi_ptr
= gi_ptr
->functions
[f_ix
];
680 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
681 length
= GCOV_TAG_FUNCTION_LENGTH
;
686 gcov_write_tag_length(GCOV_TAG_FUNCTION
, length
);
690 gcov_write_unsigned(gfi_ptr
->ident
);
691 gcov_write_unsigned(gfi_ptr
->lineno_checksum
);
692 gcov_write_unsigned(gfi_ptr
->cfg_checksum
);
694 ci_ptr
= gfi_ptr
->ctrs
;
695 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++) {
696 if (!gi_ptr
->merge
[t_ix
])
699 n_counts
= ci_ptr
->num
;
700 gcov_write_tag_length(
701 GCOV_TAG_FOR_COUNTER(t_ix
),
702 GCOV_TAG_COUNTER_LENGTH(n_counts
));
703 gcov_type
*c_ptr
= ci_ptr
->values
;
705 gcov_write_counter(*c_ptr
++);
709 fn_buffer
= free_fn_data(gi_ptr
, fn_buffer
,
713 gcov_write_unsigned(0);
717 fn_buffer
= free_fn_data(gi_ptr
, fn_buffer
,
720 error
= gcov_close();
722 fprintf(stderr
, error
< 0 ?
723 "profiling:%s:Overflow writing\n" :
724 "profiling:%s:Error writing\n",
729 /* Add a new object file onto the bb chain. Invoked automatically
730 when running an object file's global ctors. */
733 __gcov_init(struct gcov_info
*info
)
735 if (!info
->version
|| !info
->n_functions
)
737 if (gcov_version(info
, info
->version
, 0)) {
738 size_t filename_length
= strlen(info
->filename
);
740 /* Refresh the longest file name information */
741 if (filename_length
> gcov_max_filename
)
742 gcov_max_filename
= filename_length
;
749 info
->next
= gcov_list
;
755 /* Called before fork or exec - write out profile information gathered so
756 far and reset it to zero. This avoids duplication or loss of the
757 profile information gathered so far. */
762 const struct gcov_info
*gi_ptr
;
765 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
) {
768 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++) {
770 const struct gcov_fn_info
*gfi_ptr
=
771 gi_ptr
->functions
[f_ix
];
773 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
775 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
776 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++) {
777 if (!gi_ptr
->merge
[t_ix
])
780 memset(ci_ptr
->values
, 0,
781 sizeof(gcov_type
) * ci_ptr
->num
);
790 #ifdef L_gcov_merge_add
791 /* The profile merging function that just adds the counters. It is given
792 an array COUNTERS of N_COUNTERS old counters and it reads the same number
793 of counters from the gcov file. */
795 __gcov_merge_add(gcov_type
*counters
, unsigned int n_counters
)
797 for (; n_counters
; counters
++, n_counters
--)
798 *counters
+= gcov_read_counter();
800 #endif /* L_gcov_merge_add */
802 #ifdef L_gcov_merge_ior
803 /* The profile merging function that just adds the counters. It is given
804 an array COUNTERS of N_COUNTERS old counters and it reads the same number
805 of counters from the gcov file. */
807 __gcov_merge_ior(gcov_type
*counters
, unsigned int n_counters
)
809 for (; n_counters
; counters
++, n_counters
--)
810 *counters
|= gcov_read_counter();
814 #ifdef L_gcov_merge_single
815 /* The profile merging function for choosing the most common value.
816 * It is given an array COUNTERS of N_COUNTERS old counters and it
817 * reads the same number of counters from the gcov file. The counters
818 * are split into 3-tuples where the members of the tuple have
821 * -- the stored candidate on the most common value of the measured entity
823 * -- total number of evaluations of the value
826 __gcov_merge_single(gcov_type
*counters
, unsigned int n_counters
)
828 unsigned int i
, n_measures
;
829 gcov_type value
, counter
, all
;
831 gcc_assert(!(n_counters
% 3));
832 n_measures
= n_counters
/ 3;
833 for (i
= 0; i
< n_measures
; i
++, counters
+= 3) {
834 value
= gcov_read_counter();
835 counter
= gcov_read_counter();
836 all
= gcov_read_counter();
838 if (counters
[0] == value
)
839 counters
[1] += counter
;
840 else if (counter
> counters
[1]) {
842 counters
[1] = counter
- counters
[1];
844 counters
[1] -= counter
;
848 #endif /* L_gcov_merge_single */
850 #ifdef L_gcov_merge_delta
851 /* The profile merging function for choosing the most common
852 * difference between two consecutive evaluations of the value. It is
853 * given an array COUNTERS of N_COUNTERS old counters and it reads the
854 * same number of counters from the gcov file. The counters are split
855 * into 4-tuples where the members of the tuple have meanings:
857 * -- the last value of the measured entity
858 * -- the stored candidate on the most common difference
860 * -- total number of evaluations of the value
863 __gcov_merge_delta(gcov_type
*counters
, unsigned int n_counters
)
865 unsigned int i
, n_measures
;
866 gcov_type value
, counter
, all
;
868 gcc_assert(!(n_counters
% 4));
869 n_measures
= n_counters
/ 4;
870 for (i
= 0; i
< n_measures
; i
++, counters
+= 4) {
873 value
= gcov_read_counter();
874 counter
= gcov_read_counter();
875 all
= gcov_read_counter();
877 if (counters
[1] == value
)
878 counters
[2] += counter
;
879 else if (counter
> counters
[2]) {
881 counters
[2] = counter
- counters
[2];
883 counters
[2] -= counter
;
887 #endif /* L_gcov_merge_delta */
889 #ifdef L_gcov_interval_profiler
890 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
891 corresponding counter in COUNTERS. If the VALUE is above or below
892 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
896 __gcov_interval_profiler(gcov_type
*counters
, gcov_type value
,
897 int start
, unsigned int steps
)
899 gcov_type delta
= value
- start
;
901 counters
[steps
+ 1]++;
902 else if (delta
>= steps
)
909 #ifdef L_gcov_pow2_profiler
910 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
911 COUNTERS[0] is incremented. */
914 __gcov_pow2_profiler(gcov_type
*counters
, gcov_type value
)
916 if (value
& (value
- 1))
923 /* Tries to determine the most common value among its inputs. Checks if the
924 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
925 is incremented. If this is not the case and COUNTERS[1] is not zero,
926 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
927 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
928 function is called more than 50% of the time with one value, this value
929 will be in COUNTERS[0] in the end.
931 In any case, COUNTERS[2] is incremented. */
934 __gcov_one_value_profiler_body(gcov_type
*counters
, gcov_type value
)
936 if (value
== counters
[0])
938 else if (counters
[1] == 0) {
946 #ifdef L_gcov_one_value_profiler
948 __gcov_one_value_profiler(gcov_type
*counters
, gcov_type value
)
950 __gcov_one_value_profiler_body(counters
, value
);
954 #ifdef L_gcov_indirect_call_profiler
956 /* By default, the C++ compiler will use function addresses in the
957 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
958 tells the compiler to use function descriptors instead. The value
959 of this macro says how many words wide the descriptor is (normally 2),
960 but it may be dependent on target flags. Since we do not have access
961 to the target flags here we just check to see if it is set and use
962 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
964 It is assumed that the address of a function descriptor may be treated
965 as a pointer to a function. */
967 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
968 #define VTABLE_USES_DESCRIPTORS 1
970 #define VTABLE_USES_DESCRIPTORS 0
973 /* Tries to determine the most common value among its inputs. */
975 __gcov_indirect_call_profiler(gcov_type
*counter
, gcov_type value
,
976 void *cur_func
, void *callee_func
)
978 /* If the C++ virtual tables contain function descriptors then one
979 * function may have multiple descriptors and we need to dereference
980 * the descriptors to see if they point to the same function.
982 if (cur_func
== callee_func
983 || (VTABLE_USES_DESCRIPTORS
&& callee_func
984 && *(void **) cur_func
== *(void **) callee_func
))
985 __gcov_one_value_profiler_body(counter
, value
);
990 #ifdef L_gcov_average_profiler
991 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
995 __gcov_average_profiler(gcov_type
*counters
, gcov_type value
)
997 counters
[0] += value
;
1002 #ifdef L_gcov_ior_profiler
1003 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1007 __gcov_ior_profiler(gcov_type
*counters
, gcov_type value
)
1014 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1015 that they are not counted twice. */
1026 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1027 that they are not lost. */
1030 __gcov_execl(const char *path
, char *arg
, ...)
1033 unsigned int i
, length
;
1042 while (va_arg(ap
, char *))
1046 args
= (char **) alloca(length
* sizeof(void *));
1048 for (i
= 1; i
< length
; i
++)
1049 args
[i
] = va_arg(aq
, char *);
1052 return execv(path
, args
);
1056 #ifdef L_gcov_execlp
1057 /* A wrapper for the execlp function. Flushes the accumulated profiling data,
1058 * so that they are not lost.
1062 __gcov_execlp(const char *path
, char *arg
, ...)
1065 unsigned int i
, length
;
1074 while (va_arg(ap
, char *))
1078 args
= (char **) alloca(length
* sizeof(void *));
1080 for (i
= 1; i
< length
; i
++)
1081 args
[i
] = va_arg(aq
, char *);
1084 return execvp(path
, args
);
1088 #ifdef L_gcov_execle
1089 /* A wrapper for the execle function. Flushes the accumulated profiling data,
1090 * so that they are not lost.
1094 __gcov_execle(const char *path
, char *arg
, ...)
1097 unsigned int i
, length
;
1107 while (va_arg(ap
, char *))
1111 args
= (char **) alloca(length
* sizeof(void *));
1113 for (i
= 1; i
< length
; i
++)
1114 args
[i
] = va_arg(aq
, char *);
1115 envp
= va_arg(aq
, char **);
1118 return execve(path
, args
, envp
);
1123 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1124 that they are not lost. */
1127 __gcov_execv(const char *path
, char *const argv
[])
1130 return execv(path
, argv
);
1134 #ifdef L_gcov_execvp
1135 /* A wrapper for the execvp function. Flushes the accumulated profiling data,
1136 * so that they are not lost.
1140 __gcov_execvp(const char *path
, char *const argv
[])
1143 return execvp(path
, argv
);
1147 #ifdef L_gcov_execve
1148 /* A wrapper for the execve function. Flushes the accumulated profiling data,
1149 * so that they are not lost.
1153 __gcov_execve(const char *path
, char *const argv
[], char *const envp
[])
1156 return execve(path
, argv
, envp
);
1159 #endif /* inhibit_libc */