sdm845: Select VBOOT_MIGRATE_WORKING_DATA, now required
[coreboot.git] / src / lib / libgcov.c
blob887351aa5750d6c9d8783da1f2e1a52e80f78c74
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
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
24 #define __COREBOOT__
25 #ifdef __COREBOOT__
26 #include <stdlib.h>
27 #include <string.h>
28 #include <console/console.h>
29 #include <assert.h>
30 typedef s32 pid_t;
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. */
37 # define L_gcov
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__
48 # define IN_LIBGCOV 1
49 # define IN_GCOV 0
50 #else /* __COREBOOT__ */
51 #include "tconfig.h"
52 #include "tsystem.h"
53 #include "coretypes.h"
54 #include "tm.h"
55 #include "libgcc_tm.h"
56 #endif /* __COREBOOT__ */
58 #ifndef __COREBOOT__
59 #if defined(inhibit_libc)
60 #define IN_LIBGCOV (-1)
61 #else
62 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
63 #include <stdio.h>
64 #define IN_LIBGCOV 1
65 #if defined(L_gcov)
66 #define GCOV_LINKAGE /* nothing */
67 #endif
68 #endif
69 #endif /* __COREBOOT__ */
70 #include "gcov-io.h"
72 #if defined(inhibit_libc)
73 /* If libc and its header files are not available, provide dummy functions. */
75 #ifdef L_gcov
76 void __gcov_init(struct gcov_info *p __attribute__((unused))) {}
77 void __gcov_flush(void) {}
78 #endif
80 #ifdef L_gcov_merge_add
81 void __gcov_merge_add(gcov_type *counters __attribute__((unused)),
82 unsigned int n_counters __attribute__((unused))) {}
83 #endif
85 #ifdef L_gcov_merge_single
86 void __gcov_merge_single(gcov_type *counters __attribute__((unused)),
87 unsigned int n_counters __attribute__((unused))) {}
88 #endif
90 #ifdef L_gcov_merge_delta
91 void __gcov_merge_delta(gcov_type *counters __attribute__((unused)),
92 unsigned int n_counters __attribute__((unused))) {}
93 #endif
95 #else
97 #ifndef __COREBOOT__
98 #include <string.h>
99 #if GCOV_LOCKED
100 #include <fcntl.h>
101 #include <errno.h>
102 #include <sys/stat.h>
103 #endif
104 #else
105 void __gcov_merge_add(gcov_type *counters __attribute__((unused)),
106 unsigned int n_counters __attribute__((unused))) {}
107 #endif /* __COREBOOT__ */
109 #ifdef L_gcov
110 #include "gcov-io.c"
112 struct gcov_fn_buffer {
113 struct gcov_fn_buffer *next;
114 unsigned int fn_ix;
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. */
129 static int
130 create_file_directory(char *filename)
132 #ifdef __COREBOOT__
133 (void) filename;
134 return 0;
135 #else
136 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
137 (void) filename;
138 return -1;
139 #else
140 char *s;
142 s = filename;
144 if (HAS_DRIVE_SPEC(s))
145 s += 2;
146 if (IS_DIR_SEPARATOR(*s))
147 ++s;
148 for (; *s != '\0'; s++)
149 if (IS_DIR_SEPARATOR(*s)) {
150 char sep = *s;
151 *s = '\0';
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
157 #else
158 && mkdir(filename) == -1
159 #endif
160 /* The directory might have been made by another
161 * process.
163 && errno != EEXIST) {
164 fprintf(stderr,
165 "profiling:%s:Cannot create directory\n",
166 filename);
167 *s = sep;
168 return -1;
171 *s = sep;
173 return 0;
174 #endif
175 #endif
178 static struct gcov_fn_buffer *
179 free_fn_data(const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
180 unsigned int limit)
182 struct gcov_fn_buffer *next;
183 unsigned int ix, n_ctr = 0;
185 if (!buffer)
186 return 0;
187 next = buffer->next;
189 for (ix = 0; ix != limit; ix++)
190 if (gi_ptr->merge[ix])
191 free(buffer->info.ctrs[n_ctr++].values);
192 free(buffer);
193 return next;
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;
202 unsigned int len;
204 for (ix = GCOV_COUNTERS; ix--;)
205 if (gi_ptr->merge[ix])
206 n_ctrs++;
208 len = sizeof(*fn_buffer) + sizeof(fn_buffer->info.ctrs[0]) * n_ctrs;
209 fn_buffer = (struct gcov_fn_buffer *)malloc(len);
211 if (!fn_buffer)
212 goto fail;
214 fn_buffer->next = 0;
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;
222 gcov_type *values;
224 if (!gi_ptr->merge[ix])
225 continue;
227 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix)) {
228 len = 0;
229 goto fail;
232 length = GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
233 len = length * sizeof(gcov_type);
234 values = (gcov_type *)malloc(len);
235 if (!values)
236 goto fail;
238 fn_buffer->info.ctrs[n_ctrs].num = length;
239 fn_buffer->info.ctrs[n_ctrs].values = values;
241 while (length--)
242 *values++ = gcov_read_counter();
243 n_ctrs++;
246 *end_ptr = fn_buffer;
247 return &fn_buffer->next;
249 fail:
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)
261 unsigned int ix;
263 for (ix = 32; ix--; value <<= 1) {
264 unsigned int feedback;
266 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
267 crc32 <<= 1;
268 crc32 ^= feedback;
271 return crc32;
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. */
279 static int
280 gcov_version(struct gcov_info *ptr, gcov_unsigned_t version,
281 const char *filename)
283 if (version != GCOV_VERSION) {
284 char v[4], e[4];
286 GCOV_UNSIGNED2STRING(v, version);
287 GCOV_UNSIGNED2STRING(e, GCOV_VERSION);
289 fprintf(stderr,
290 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
291 filename ? filename : ptr->filename, e, v);
292 return 0;
294 return 1;
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. */
304 static void
305 gcov_exit(void)
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;
313 unsigned int t_ix;
314 int f_ix = 0;
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;
330 f_ix++) {
331 gfi_ptr = gi_ptr->functions[f_ix];
333 if (gfi_ptr && gfi_ptr->key != gi_ptr)
334 gfi_ptr = 0;
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);
340 if (!gfi_ptr)
341 continue;
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])
346 continue;
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++) {
353 cs_ptr->sum_all +=
354 ci_ptr->values[c_num];
355 if (cs_ptr->run_max
356 < ci_ptr->values[c_num])
357 cs_ptr->run_max =
358 ci_ptr->values[c_num];
360 ci_ptr++;
365 #ifndef __COREBOOT__
367 /* Check if the level of dirs to strip off specified. */
368 char *tmp = getenv("GCOV_PREFIX_STRIP");
369 if (tmp) {
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");
379 if (gcov_prefix) {
380 prefix_length = strlen(gcov_prefix);
382 /* Remove an unnecessary trailing '/' */
383 if (IS_DIR_SEPARATOR(gcov_prefix[prefix_length - 1]))
384 prefix_length--;
385 } else
386 #endif
387 prefix_length = 0;
389 /* If no prefix was specified and a prefix strip, then we assume
390 relative. */
391 if (gcov_prefix_strip != 0 && prefix_length == 0) {
392 gcov_prefix = ".";
393 prefix_length = 1;
395 /* Allocate and initialize the filename scratch space plus one. */
396 gi_filename = (char *) alloca(prefix_length + gcov_max_filename + 2);
397 if (prefix_length)
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
405 program. */
406 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
407 int error = 0;
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))
419 fname += 2;
421 /* Build relocated filename, stripping off leading
422 * directories from the initial filename if requested.
424 if (gcov_prefix_strip > 0) {
425 int level = 0;
427 s = fname;
428 if (IS_DIR_SEPARATOR(*s))
429 ++s;
431 /* Skip selected directory levels. */
432 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
433 if (IS_DIR_SEPARATOR(*s)) {
434 fname = s;
435 level++;
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);
445 } else
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",
454 gi_filename);
455 continue;
457 if (!gcov_open(gi_filename)) {
458 fprintf(stderr,
459 "profiling:%s:Cannot open\n",
460 gi_filename);
461 continue;
465 tag = gcov_read_unsigned();
466 if (tag) {
467 /* Merge data from file. */
468 if (tag != GCOV_DATA_MAGIC) {
469 fprintf(stderr,
470 "profiling:%s:Not a gcov data file\n",
471 gi_filename);
472 goto read_fatal;
474 length = gcov_read_unsigned();
475 if (!gcov_version(gi_ptr, length, gi_filename))
476 goto read_fatal;
478 length = gcov_read_unsigned();
479 if (length != gi_ptr->stamp)
480 /* Read from a different compilation.
481 * Overwrite the file.
483 goto rewrite;
485 /* Look for program summary. */
486 for (f_ix = 0;;) {
487 struct gcov_summary tmp;
489 eof_pos = gcov_position();
490 tag = gcov_read_unsigned();
491 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
492 break;
494 f_ix--;
495 length = gcov_read_unsigned();
496 if (length != GCOV_TAG_SUMMARY_LENGTH)
497 goto read_mismatch;
498 gcov_read_summary(&tmp);
499 error = gcov_is_error();
500 if (error)
501 goto read_error;
502 if (summary_pos
503 || tmp.checksum != crc32)
504 goto next_summary;
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)
510 goto next_summary;
511 prg = tmp;
512 summary_pos = eof_pos;
514 next_summary:;
517 /* Merge execution counts for each function. */
518 for (f_ix = 0; (unsigned int)f_ix !=
519 gi_ptr->n_functions;
520 f_ix++, tag = gcov_read_unsigned()) {
521 gfi_ptr = gi_ptr->functions[f_ix];
523 if (tag != GCOV_TAG_FUNCTION)
524 goto read_mismatch;
526 length = gcov_read_unsigned();
527 if (!length)
528 /* This function did not appear
529 * in the other program. We
530 * have nothing to merge.
532 continue;
534 if (length != GCOV_TAG_FUNCTION_LENGTH)
535 goto read_mismatch;
537 if (!gfi_ptr || gfi_ptr->key !=
538 gi_ptr) {
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
546 * file.
548 fn_tail = buffer_fn_data(
549 gi_filename, gi_ptr,
550 fn_tail, f_ix);
551 if (!fn_tail)
552 goto read_mismatch;
553 continue;
556 length = gcov_read_unsigned();
557 if (length != gfi_ptr->ident)
558 goto read_mismatch;
560 length = gcov_read_unsigned();
561 if (length != gfi_ptr->lineno_checksum)
562 goto read_mismatch;
564 length = gcov_read_unsigned();
565 if (length != gfi_ptr->cfg_checksum)
566 goto read_mismatch;
568 ci_ptr = gfi_ptr->ctrs;
569 for (t_ix = 0; t_ix < GCOV_COUNTERS;
570 t_ix++) {
571 gcov_merge_fn merge =
572 gi_ptr->merge[t_ix];
574 if (!merge)
575 continue;
577 tag = gcov_read_unsigned();
578 length = gcov_read_unsigned();
579 if (tag != GCOV_TAG_FOR_COUNTER(
580 t_ix) || length !=
581 GCOV_TAG_COUNTER_LENGTH(
582 ci_ptr->num))
583 goto read_mismatch;
584 (*merge)(ci_ptr->values,
585 ci_ptr->num);
586 ci_ptr++;
588 error = gcov_is_error();
589 if (error)
590 goto read_error;
593 if (tag) {
594 read_mismatch:;
595 fprintf(stderr,
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);
600 goto read_fatal;
603 goto rewrite;
605 read_error:;
606 fprintf(stderr, "profiling:%s:%s merging\n", gi_filename,
607 error < 0 ? "Overflow" : "Error");
609 goto read_fatal;
611 rewrite:;
612 gcov_rewrite();
613 if (!summary_pos) {
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]) {
625 if (!cs_prg->runs++)
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)
632 goto read_mismatch;
634 if (!cs_all->runs && cs_prg->runs)
635 memcpy(cs_all, cs_prg, sizeof(*cs_all));
636 else if (!all_prg.checksum
637 && (!GCOV_LOCKED
638 || cs_all->runs == cs_prg->runs)
639 && memcmp(cs_all, cs_prg, sizeof(*cs_all))) {
640 fprintf(stderr,
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. */
651 if (!eof_pos) {
652 gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
653 gcov_write_unsigned(gi_ptr->stamp);
656 if (summary_pos)
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)
663 gcov_seek(eof_pos);
665 /* Write execution counts for each function. */
666 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
667 f_ix++) {
668 unsigned int buffered = 0;
670 if (fn_buffer && fn_buffer->fn_ix
671 == (unsigned int)f_ix) {
672 /* Buffered data from another program. */
673 buffered = 1;
674 gfi_ptr = &fn_buffer->info;
675 length = GCOV_TAG_FUNCTION_LENGTH;
676 } else {
677 gfi_ptr = gi_ptr->functions[f_ix];
678 if (gfi_ptr && gfi_ptr->key == gi_ptr)
679 length = GCOV_TAG_FUNCTION_LENGTH;
680 else
681 length = 0;
684 gcov_write_tag_length(GCOV_TAG_FUNCTION, length);
685 if (!length)
686 continue;
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])
695 continue;
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;
702 while (n_counts--)
703 gcov_write_counter(*c_ptr++);
704 ci_ptr++;
706 if (buffered)
707 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
708 GCOV_COUNTERS);
711 gcov_write_unsigned(0);
713 read_fatal:;
714 while (fn_buffer)
715 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
716 GCOV_COUNTERS);
718 error = gcov_close();
719 if (error)
720 fprintf(stderr, error < 0 ?
721 "profiling:%s:Overflow writing\n" :
722 "profiling:%s:Error writing\n",
723 gi_filename);
727 /* Add a new object file onto the bb chain. Invoked automatically
728 when running an object file's global ctors. */
730 void
731 __gcov_init(struct gcov_info *info)
733 if (!info->version || !info->n_functions)
734 return;
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;
742 #ifndef __COREBOOT__
743 if (!gcov_list)
744 atexit(gcov_exit);
745 #endif
747 info->next = gcov_list;
748 gcov_list = info;
750 info->version = 0;
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. */
757 void
758 __gcov_flush(void)
760 const struct gcov_info *gi_ptr;
762 gcov_exit();
763 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) {
764 unsigned int f_ix;
766 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) {
767 unsigned int t_ix;
768 const struct gcov_fn_info *gfi_ptr =
769 gi_ptr->functions[f_ix];
771 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
772 continue;
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])
776 continue;
778 memset(ci_ptr->values, 0,
779 sizeof(gcov_type) * ci_ptr->num);
780 ci_ptr++;
786 #endif /* L_gcov */
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. */
792 void
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. */
804 void
805 __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
807 for (; n_counters; counters++, n_counters--)
808 *counters |= gcov_read_counter();
810 #endif
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
817 * meanings:
819 * -- the stored candidate on the most common value of the measured entity
820 * -- counter
821 * -- total number of evaluations of the value
823 void
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]) {
839 counters[0] = value;
840 counters[1] = counter - counters[1];
841 } else
842 counters[1] -= counter;
843 counters[2] += all;
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
857 * -- counter
858 * -- total number of evaluations of the value
860 void
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) {
869 /* last = */
870 gcov_read_counter();
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]) {
878 counters[1] = value;
879 counters[2] = counter - counters[2];
880 } else
881 counters[2] -= counter;
882 counters[3] += all;
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
891 instead. */
893 void
894 __gcov_interval_profiler(gcov_type *counters, gcov_type value,
895 int start, unsigned int steps)
897 gcov_type delta = value - start;
898 if (delta < 0)
899 counters[steps + 1]++;
900 else if (delta >= steps)
901 counters[steps]++;
902 else
903 counters[delta]++;
905 #endif
907 #ifdef L_gcov_pow2_profiler
908 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
909 COUNTERS[0] is incremented. */
911 void
912 __gcov_pow2_profiler(gcov_type *counters, gcov_type value)
914 if (value & (value - 1))
915 counters[0]++;
916 else
917 counters[1]++;
919 #endif
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. */
931 static inline void
932 __gcov_one_value_profiler_body(gcov_type *counters, gcov_type value)
934 if (value == counters[0])
935 counters[1]++;
936 else if (counters[1] == 0) {
937 counters[1] = 1;
938 counters[0] = value;
939 } else
940 counters[1]--;
941 counters[2]++;
944 #ifdef L_gcov_one_value_profiler
945 void
946 __gcov_one_value_profiler(gcov_type *counters, gcov_type value)
948 __gcov_one_value_profiler_body(counters, value);
950 #endif
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
967 #else
968 #define VTABLE_USES_DESCRIPTORS 0
969 #endif
971 /* Tries to determine the most common value among its inputs. */
972 void
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);
985 #endif
988 #ifdef L_gcov_average_profiler
989 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
990 to saturate up. */
992 void
993 __gcov_average_profiler(gcov_type *counters, gcov_type value)
995 counters[0] += value;
996 counters[1]++;
998 #endif
1000 #ifdef L_gcov_ior_profiler
1001 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1002 to saturate up. */
1004 void
1005 __gcov_ior_profiler(gcov_type *counters, gcov_type value)
1007 *counters |= value;
1009 #endif
1011 #ifdef L_gcov_fork
1012 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1013 that they are not counted twice. */
1015 pid_t
1016 __gcov_fork(void)
1018 __gcov_flush();
1019 return fork();
1021 #endif
1023 #ifdef L_gcov_execl
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, ...)
1030 va_list ap, aq;
1031 unsigned int i, length;
1032 char **args;
1034 __gcov_flush();
1036 va_start(ap, arg);
1037 va_copy(aq, ap);
1039 length = 2;
1040 while (va_arg(ap, char *))
1041 length++;
1042 va_end(ap);
1044 args = (char **) alloca(length * sizeof(void *));
1045 args[0] = arg;
1046 for (i = 1; i < length; i++)
1047 args[i] = va_arg(aq, char *);
1048 va_end(aq);
1050 return execv(path, args);
1052 #endif
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, ...)
1062 va_list ap, aq;
1063 unsigned int i, length;
1064 char **args;
1066 __gcov_flush();
1068 va_start(ap, arg);
1069 va_copy(aq, ap);
1071 length = 2;
1072 while (va_arg(ap, char *))
1073 length++;
1074 va_end(ap);
1076 args = (char **) alloca(length * sizeof(void *));
1077 args[0] = arg;
1078 for (i = 1; i < length; i++)
1079 args[i] = va_arg(aq, char *);
1080 va_end(aq);
1082 return execvp(path, args);
1084 #endif
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, ...)
1094 va_list ap, aq;
1095 unsigned int i, length;
1096 char **args;
1097 char **envp;
1099 __gcov_flush();
1101 va_start(ap, arg);
1102 va_copy(aq, ap);
1104 length = 2;
1105 while (va_arg(ap, char *))
1106 length++;
1107 va_end(ap);
1109 args = (char **) alloca(length * sizeof(void *));
1110 args[0] = arg;
1111 for (i = 1; i < length; i++)
1112 args[i] = va_arg(aq, char *);
1113 envp = va_arg(aq, char **);
1114 va_end(aq);
1116 return execve(path, args, envp);
1118 #endif
1120 #ifdef L_gcov_execv
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[])
1127 __gcov_flush();
1128 return execv(path, argv);
1130 #endif
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[])
1140 __gcov_flush();
1141 return execvp(path, argv);
1143 #endif
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[])
1153 __gcov_flush();
1154 return execve(path, argv, envp);
1156 #endif
1157 #endif /* inhibit_libc */