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 <console/console.h>
31 #define gcc_assert(x) ASSERT(x)
32 #define fprintf(file, x...) printk(BIOS_ERR, x)
33 #define alloca(size) __builtin_alloca (size)
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 n_counters
__attribute__ ((unused
))) {}
85 #ifdef L_gcov_merge_single
86 void __gcov_merge_single (gcov_type
*counters
__attribute__ ((unused
)),
87 unsigned n_counters
__attribute__ ((unused
))) {}
90 #ifdef L_gcov_merge_delta
91 void __gcov_merge_delta (gcov_type
*counters
__attribute__ ((unused
)),
92 unsigned n_counters
__attribute__ ((unused
))) {}
102 #include <sys/stat.h>
105 void __gcov_merge_add(gcov_type
*counters
__attribute__ ((unused
)),
106 unsigned n_counters
__attribute__ ((unused
))) {}
107 #endif /* __COREBOOT__ */
112 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
))
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 process. */
165 fprintf (stderr
, "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 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 fn_ix
)
200 unsigned 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
++)
222 gcov_unsigned_t length
;
225 if (!gi_ptr
->merge
[ix
])
228 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)
269 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
277 /* Check if VERSION of the info block PTR matches libgcov one.
278 Return 1 on success, or zero in case of versions mismatch.
279 If FILENAME is not NULL, its value used for reporting purposes
280 instead of value from the info block. */
283 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
284 const char *filename
)
286 if (version
!= GCOV_VERSION
)
290 GCOV_UNSIGNED2STRING (v
, version
);
291 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
294 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
295 filename
? filename
: ptr
->filename
, e
, v
);
301 /* Dump the coverage counts. We merge with existing counts when
302 possible, to avoid growing the .da files ad infinitum. We use this
303 program's checksum to make sure we only accumulate whole program
304 statistics to the correct summary. An object file might be embedded
305 in two separate programs, and we must keep the two program
306 summaries separate. */
311 struct gcov_info
*gi_ptr
;
312 const struct gcov_fn_info
*gfi_ptr
;
313 struct gcov_summary this_prg
; /* summary for program. */
314 struct gcov_summary all_prg
; /* summary for all instances of program. */
315 struct gcov_ctr_summary
*cs_ptr
;
316 const struct gcov_ctr_info
*ci_ptr
;
319 gcov_unsigned_t c_num
;
320 const char *gcov_prefix
;
321 int gcov_prefix_strip
= 0;
322 size_t prefix_length
;
323 char *gi_filename
, *gi_filename_up
;
324 gcov_unsigned_t crc32
= 0;
326 memset (&all_prg
, 0, sizeof (all_prg
));
327 /* Find the totals for this execution. */
328 memset (&this_prg
, 0, sizeof (this_prg
));
329 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
331 crc32
= crc32_unsigned (crc32
, gi_ptr
->stamp
);
332 crc32
= crc32_unsigned (crc32
, gi_ptr
->n_functions
);
334 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
336 gfi_ptr
= gi_ptr
->functions
[f_ix
];
338 if (gfi_ptr
&& gfi_ptr
->key
!= gi_ptr
)
341 crc32
= crc32_unsigned (crc32
, gfi_ptr
? gfi_ptr
->cfg_checksum
: 0);
342 crc32
= crc32_unsigned (crc32
,
343 gfi_ptr
? gfi_ptr
->lineno_checksum
: 0);
347 ci_ptr
= gfi_ptr
->ctrs
;
348 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
350 if (!gi_ptr
->merge
[t_ix
])
353 cs_ptr
= &this_prg
.ctrs
[t_ix
];
354 cs_ptr
->num
+= ci_ptr
->num
;
355 crc32
= crc32_unsigned (crc32
, ci_ptr
->num
);
357 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
359 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
360 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
361 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
370 /* Check if the level of dirs to strip off specified. */
371 char *tmp
= getenv("GCOV_PREFIX_STRIP");
374 gcov_prefix_strip
= atoi (tmp
);
375 /* Do not consider negative values. */
376 if (gcov_prefix_strip
< 0)
377 gcov_prefix_strip
= 0;
381 /* Get file name relocation prefix. Non-absolute values are ignored. */
382 gcov_prefix
= getenv("GCOV_PREFIX");
385 prefix_length
= strlen(gcov_prefix
);
387 /* Remove an unnecessary trailing '/' */
388 if (IS_DIR_SEPARATOR (gcov_prefix
[prefix_length
- 1]))
395 /* If no prefix was specified and a prefix strip, then we assume
397 if (gcov_prefix_strip
!= 0 && prefix_length
== 0)
402 /* Allocate and initialize the filename scratch space plus one. */
403 gi_filename
= (char *) alloca (prefix_length
+ gcov_max_filename
+ 2);
405 memcpy (gi_filename
, gcov_prefix
, prefix_length
);
406 gi_filename_up
= gi_filename
+ prefix_length
;
408 /* Now merge each file. */
409 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
412 struct gcov_summary prg
; /* summary for this object over all
414 struct gcov_ctr_summary
*cs_prg
, *cs_tprg
, *cs_all
;
416 gcov_unsigned_t tag
, length
;
417 gcov_position_t summary_pos
= 0;
418 gcov_position_t eof_pos
= 0;
419 const char *fname
, *s
;
420 struct gcov_fn_buffer
*fn_buffer
= 0;
421 struct gcov_fn_buffer
**fn_tail
= &fn_buffer
;
423 fname
= gi_ptr
->filename
;
425 /* Avoid to add multiple drive letters into combined path. */
426 if (prefix_length
!= 0 && HAS_DRIVE_SPEC(fname
))
429 /* Build relocated filename, stripping off leading
430 directories from the initial filename if requested. */
431 if (gcov_prefix_strip
> 0)
435 if (IS_DIR_SEPARATOR(*s
))
438 /* Skip selected directory levels. */
439 for (; (*s
!= '\0') && (level
< gcov_prefix_strip
); s
++)
440 if (IS_DIR_SEPARATOR(*s
))
447 /* Update complete filename with stripped original. */
448 if (prefix_length
!= 0 && !IS_DIR_SEPARATOR (*fname
))
450 /* If prefix is given, add directory separator. */
451 strcpy (gi_filename_up
, "/");
452 strcpy (gi_filename_up
+ 1, fname
);
455 strcpy (gi_filename_up
, fname
);
457 if (!gcov_open (gi_filename
))
459 /* Open failed likely due to missed directory.
460 Create directory and retry to open file. */
461 if (create_file_directory (gi_filename
))
463 fprintf (stderr
, "profiling:%s:Skip\n", gi_filename
);
466 if (!gcov_open (gi_filename
))
468 fprintf (stderr
, "profiling:%s:Cannot open\n", gi_filename
);
473 tag
= gcov_read_unsigned ();
476 /* Merge data from file. */
477 if (tag
!= GCOV_DATA_MAGIC
)
479 fprintf (stderr
, "profiling:%s:Not a gcov data file\n",
483 length
= gcov_read_unsigned ();
484 if (!gcov_version (gi_ptr
, length
, gi_filename
))
487 length
= gcov_read_unsigned ();
488 if (length
!= gi_ptr
->stamp
)
489 /* Read from a different compilation. Overwrite the file. */
492 /* Look for program summary. */
495 struct gcov_summary tmp
;
497 eof_pos
= gcov_position ();
498 tag
= gcov_read_unsigned ();
499 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
503 length
= gcov_read_unsigned ();
504 if (length
!= GCOV_TAG_SUMMARY_LENGTH
)
506 gcov_read_summary (&tmp
);
507 if ((error
= gcov_is_error ()))
509 if (summary_pos
|| tmp
.checksum
!= crc32
)
512 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS_SUMMABLE
; t_ix
++)
513 if (tmp
.ctrs
[t_ix
].num
!= this_prg
.ctrs
[t_ix
].num
)
516 summary_pos
= eof_pos
;
521 /* Merge execution counts for each function. */
522 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
;
523 f_ix
++, tag
= gcov_read_unsigned ())
525 gfi_ptr
= gi_ptr
->functions
[f_ix
];
527 if (tag
!= GCOV_TAG_FUNCTION
)
530 length
= gcov_read_unsigned ();
532 /* This function did not appear in the other program.
533 We have nothing to merge. */
536 if (length
!= GCOV_TAG_FUNCTION_LENGTH
)
539 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
541 /* This function appears in the other program. We
542 need to buffer the information in order to write
543 it back out -- we'll be inserting data before
544 this point, so cannot simply keep the data in the
546 fn_tail
= buffer_fn_data (gi_filename
,
547 gi_ptr
, fn_tail
, f_ix
);
553 length
= gcov_read_unsigned ();
554 if (length
!= gfi_ptr
->ident
)
557 length
= gcov_read_unsigned ();
558 if (length
!= gfi_ptr
->lineno_checksum
)
561 length
= gcov_read_unsigned ();
562 if (length
!= gfi_ptr
->cfg_checksum
)
565 ci_ptr
= gfi_ptr
->ctrs
;
566 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
568 gcov_merge_fn merge
= gi_ptr
->merge
[t_ix
];
573 tag
= gcov_read_unsigned ();
574 length
= gcov_read_unsigned ();
575 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
576 || length
!= GCOV_TAG_COUNTER_LENGTH (ci_ptr
->num
))
578 (*merge
) (ci_ptr
->values
, ci_ptr
->num
);
581 if ((error
= gcov_is_error ()))
588 fprintf (stderr
, "profiling:%s:Merge mismatch for %s %u\n",
589 gi_filename
, f_ix
>= 0 ? "function" : "summary",
590 f_ix
< 0 ? -1 - f_ix
: f_ix
);
597 fprintf (stderr
, "profiling:%s:%s merging\n", gi_filename
,
598 error
< 0 ? "Overflow": "Error");
606 memset (&prg
, 0, sizeof (prg
));
607 summary_pos
= eof_pos
;
610 /* Merge the summaries. */
611 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
613 cs_prg
= &prg
.ctrs
[t_ix
];
614 cs_tprg
= &this_prg
.ctrs
[t_ix
];
615 cs_all
= &all_prg
.ctrs
[t_ix
];
617 if (gi_ptr
->merge
[t_ix
])
620 cs_prg
->num
= cs_tprg
->num
;
621 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
622 if (cs_prg
->run_max
< cs_tprg
->run_max
)
623 cs_prg
->run_max
= cs_tprg
->run_max
;
624 cs_prg
->sum_max
+= cs_tprg
->run_max
;
626 else if (cs_prg
->runs
)
629 if (!cs_all
->runs
&& cs_prg
->runs
)
630 memcpy (cs_all
, cs_prg
, sizeof (*cs_all
));
631 else if (!all_prg
.checksum
632 && (!GCOV_LOCKED
|| cs_all
->runs
== cs_prg
->runs
)
633 && memcmp (cs_all
, cs_prg
, sizeof (*cs_all
)))
635 fprintf (stderr
, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
636 gi_filename
, GCOV_LOCKED
637 ? "" : " or concurrently updated without locking support");
638 all_prg
.checksum
= ~0u;
642 prg
.checksum
= crc32
;
644 /* Write out the data. */
647 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
648 gcov_write_unsigned (gi_ptr
->stamp
);
652 gcov_seek (summary_pos
);
654 /* Generate whole program statistics. */
655 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &prg
);
657 if (summary_pos
< eof_pos
)
660 /* Write execution counts for each function. */
661 for (f_ix
= 0; (unsigned)f_ix
!= gi_ptr
->n_functions
; f_ix
++)
663 unsigned buffered
= 0;
665 if (fn_buffer
&& fn_buffer
->fn_ix
== (unsigned)f_ix
)
667 /* Buffered data from another program. */
669 gfi_ptr
= &fn_buffer
->info
;
670 length
= GCOV_TAG_FUNCTION_LENGTH
;
674 gfi_ptr
= gi_ptr
->functions
[f_ix
];
675 if (gfi_ptr
&& gfi_ptr
->key
== gi_ptr
)
676 length
= GCOV_TAG_FUNCTION_LENGTH
;
681 gcov_write_tag_length (GCOV_TAG_FUNCTION
, length
);
685 gcov_write_unsigned (gfi_ptr
->ident
);
686 gcov_write_unsigned (gfi_ptr
->lineno_checksum
);
687 gcov_write_unsigned (gfi_ptr
->cfg_checksum
);
689 ci_ptr
= gfi_ptr
->ctrs
;
690 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
692 if (!gi_ptr
->merge
[t_ix
])
695 n_counts
= ci_ptr
->num
;
696 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
697 GCOV_TAG_COUNTER_LENGTH (n_counts
));
698 gcov_type
*c_ptr
= ci_ptr
->values
;
700 gcov_write_counter (*c_ptr
++);
704 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
707 gcov_write_unsigned (0);
711 fn_buffer
= free_fn_data (gi_ptr
, fn_buffer
, GCOV_COUNTERS
);
713 if ((error
= gcov_close ()))
714 fprintf (stderr
, error
< 0 ?
715 "profiling:%s:Overflow writing\n" :
716 "profiling:%s:Error writing\n",
721 /* Add a new object file onto the bb chain. Invoked automatically
722 when running an object file's global ctors. */
725 __gcov_init (struct gcov_info
*info
)
727 if (!info
->version
|| !info
->n_functions
)
729 if (gcov_version (info
, info
->version
, 0))
731 size_t filename_length
= strlen(info
->filename
);
733 /* Refresh the longest file name information */
734 if (filename_length
> gcov_max_filename
)
735 gcov_max_filename
= filename_length
;
742 info
->next
= gcov_list
;
748 /* Called before fork or exec - write out profile information gathered so
749 far and reset it to zero. This avoids duplication or loss of the
750 profile information gathered so far. */
755 const struct gcov_info
*gi_ptr
;
758 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
762 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
765 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
767 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
769 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
770 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++)
772 if (!gi_ptr
->merge
[t_ix
])
775 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
784 #ifdef L_gcov_merge_add
785 /* The profile merging function that just adds the counters. It is given
786 an array COUNTERS of N_COUNTERS old counters and it reads the same number
787 of counters from the gcov file. */
789 __gcov_merge_add (gcov_type
*counters
, unsigned n_counters
)
791 for (; n_counters
; counters
++, n_counters
--)
792 *counters
+= gcov_read_counter ();
794 #endif /* L_gcov_merge_add */
796 #ifdef L_gcov_merge_ior
797 /* The profile merging function that just adds the counters. It is given
798 an array COUNTERS of N_COUNTERS old counters and it reads the same number
799 of counters from the gcov file. */
801 __gcov_merge_ior (gcov_type
*counters
, unsigned n_counters
)
803 for (; n_counters
; counters
++, n_counters
--)
804 *counters
|= gcov_read_counter ();
808 #ifdef L_gcov_merge_single
809 /* The profile merging function for choosing the most common value.
810 * It is given an array COUNTERS of N_COUNTERS old counters and it
811 * reads the same number of counters from the gcov file. The counters
812 * are split into 3-tuples where the members of the tuple have
815 * -- the stored candidate on the most common value of the measured entity
817 * -- total number of evaluations of the value
820 __gcov_merge_single (gcov_type
*counters
, unsigned n_counters
)
822 unsigned i
, n_measures
;
823 gcov_type value
, counter
, all
;
825 gcc_assert (!(n_counters
% 3));
826 n_measures
= n_counters
/ 3;
827 for (i
= 0; i
< n_measures
; i
++, counters
+= 3)
829 value
= gcov_read_counter ();
830 counter
= gcov_read_counter ();
831 all
= gcov_read_counter ();
833 if (counters
[0] == value
)
834 counters
[1] += counter
;
835 else if (counter
> counters
[1])
838 counters
[1] = counter
- counters
[1];
841 counters
[1] -= counter
;
845 #endif /* L_gcov_merge_single */
847 #ifdef L_gcov_merge_delta
848 /* The profile merging function for choosing the most common
849 * difference between two consecutive evaluations of the value. It is
850 * given an array COUNTERS of N_COUNTERS old counters and it reads the
851 * same number of counters from the gcov file. The counters are split
852 * into 4-tuples where the members of the tuple have meanings:
854 * -- the last value of the measured entity
855 * -- the stored candidate on the most common difference
857 * -- total number of evaluations of the value
860 __gcov_merge_delta (gcov_type
*counters
, unsigned n_counters
)
862 unsigned i
, n_measures
;
863 gcov_type value
, counter
, all
;
865 gcc_assert (!(n_counters
% 4));
866 n_measures
= n_counters
/ 4;
867 for (i
= 0; i
< n_measures
; i
++, counters
+= 4)
869 /* last = */ gcov_read_counter ();
870 value
= gcov_read_counter ();
871 counter
= gcov_read_counter ();
872 all
= gcov_read_counter ();
874 if (counters
[1] == value
)
875 counters
[2] += counter
;
876 else if (counter
> counters
[2])
879 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 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)
947 #ifdef L_gcov_one_value_profiler
949 __gcov_one_value_profiler (gcov_type
*counters
, gcov_type value
)
951 __gcov_one_value_profiler_body (counters
, value
);
955 #ifdef L_gcov_indirect_call_profiler
957 /* By default, the C++ compiler will use function addresses in the
958 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
959 tells the compiler to use function descriptors instead. The value
960 of this macro says how many words wide the descriptor is (normally 2),
961 but it may be dependent on target flags. Since we do not have access
962 to the target flags here we just check to see if it is set and use
963 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
965 It is assumed that the address of a function descriptor may be treated
966 as a pointer to a function. */
968 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
969 #define VTABLE_USES_DESCRIPTORS 1
971 #define VTABLE_USES_DESCRIPTORS 0
974 /* Tries to determine the most common value among its inputs. */
976 __gcov_indirect_call_profiler (gcov_type
* counter
, gcov_type value
,
977 void* cur_func
, void* callee_func
)
979 /* If the C++ virtual tables contain function descriptors then one
980 function may have multiple descriptors and we need to dereference
981 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
, ...)
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, so
1058 that they are not lost. */
1061 __gcov_execlp (const char *path
, char *arg
, ...)
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, so
1089 that they are not lost. */
1092 __gcov_execle (const char *path
, char *arg
, ...)
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, so
1134 that they are not lost. */
1137 __gcov_execvp (const char *path
, char *const argv
[])
1140 return execvp (path
, argv
);
1144 #ifdef L_gcov_execve
1145 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
1146 that they are not lost. */
1149 __gcov_execve (const char *path
, char *const argv
[], char *const envp
[])
1152 return execve (path
, argv
, envp
);
1155 #endif /* inhibit_libc */