1 /* SPDX-License-Identifier: GPL-3.0-only WITH GCC-exception-3.1 */
2
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.
8
9 This file is part of GCC.
10
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
14 version.
15
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
19 for more details.
20
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.
24 */
25
26 #ifdef __COREBOOT__
27 #include <stdlib.h>
28 #include <string.h>
29 #include <commonlib/helpers.h>
30 #include <console/console.h>
31 #include <assert.h>
32 typedef s32 pid_t;
33 #define gcc_assert(x) ASSERT(x)
34 #define fprintf(file, x...) printk(BIOS_ERR, x)
35 #include "gcov-glue.c"
36
37 /* Define MACROs to be used by coreboot compilation. */
38 # define L_gcov
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
45
46 # define HAVE_CC_TLS 0
47 # define __GCOV_KERNEL__
48
49 # define IN_LIBGCOV 1
50 # define IN_GCOV 0
51 #else /* __COREBOOT__ */
52 #include "tconfig.h"
53 #include "tsystem.h"
54 #include "coretypes.h"
55 #include "tm.h"
56 #include "libgcc_tm.h"
57 #endif /* __COREBOOT__ */
58
59 #ifndef __COREBOOT__
60 #if defined(inhibit_libc)
61 #define IN_LIBGCOV (-1)
62 #else
63 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
64 #include <stdio.h>
65 #define IN_LIBGCOV 1
66 #if defined(L_gcov)
67 #define GCOV_LINKAGE /* nothing */
68 #endif
69 #endif
70 #endif /* __COREBOOT__ */
71 #include "gcov-io.h"
72
73 #if defined(inhibit_libc)
74 /* If libc and its header files are not available, provide dummy functions. */
75
76 #ifdef L_gcov
__gcov_init(struct gcov_info * p)77 void __gcov_init(struct gcov_info *p __attribute__((unused))) {}
__gcov_flush(void)78 void __gcov_flush(void) {}
79 #endif
80
81 #ifdef L_gcov_merge_add
__gcov_merge_add(gcov_type * counters,unsigned int n_counters)82 void __gcov_merge_add(gcov_type *counters __attribute__((unused)),
83 unsigned int n_counters __attribute__((unused))) {}
84 #endif
85
86 #ifdef L_gcov_merge_single
__gcov_merge_single(gcov_type * counters,unsigned int n_counters)87 void __gcov_merge_single(gcov_type *counters __attribute__((unused)),
88 unsigned int n_counters __attribute__((unused))) {}
89 #endif
90
91 #ifdef L_gcov_merge_delta
__gcov_merge_delta(gcov_type * counters,unsigned int n_counters)92 void __gcov_merge_delta(gcov_type *counters __attribute__((unused)),
93 unsigned int n_counters __attribute__((unused))) {}
94 #endif
95
96 #else
97
98 #ifndef __COREBOOT__
99 #include <string.h>
100 #if GCOV_LOCKED
101 #include <fcntl.h>
102 #include <errno.h>
103 #include <sys/stat.h>
104 #endif
105 #else
__gcov_merge_add(gcov_type * counters,unsigned int n_counters)106 void __gcov_merge_add(gcov_type *counters __attribute__((unused)),
107 unsigned int n_counters __attribute__((unused))) {}
108 #endif /* __COREBOOT__ */
109
110 #ifdef L_gcov
111 #include "gcov-io.c"
112
113 struct gcov_fn_buffer {
114 struct gcov_fn_buffer *next;
115 unsigned int fn_ix;
116 struct gcov_fn_info info;
117 /* note gcov_fn_info ends in a trailing array. */
118 };
119
120 /* Chain of per-object gcov structures. */
121 static struct gcov_info *gcov_list;
122
123 /* Size of the longest file name. */
124 static size_t gcov_max_filename = 0;
125
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. */
129
130 static int
create_file_directory(char * filename)131 create_file_directory(char *filename)
132 {
133 #ifdef __COREBOOT__
134 (void) filename;
135 return 0;
136 #else
137 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
138 (void) filename;
139 return -1;
140 #else
141 char *s;
142
143 s = filename;
144
145 if (HAS_DRIVE_SPEC(s))
146 s += 2;
147 if (IS_DIR_SEPARATOR(*s))
148 ++s;
149 for (; *s != '\0'; s++)
150 if (IS_DIR_SEPARATOR(*s)) {
151 char sep = *s;
152 *s = '\0';
153
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
158 #else
159 && mkdir(filename) == -1
160 #endif
161 /* The directory might have been made by another
162 * process.
163 */
164 && errno != EEXIST) {
165 fprintf(stderr,
166 "profiling:%s:Cannot create directory\n",
167 filename);
168 *s = sep;
169 return -1;
170 };
171
172 *s = sep;
173 };
174 return 0;
175 #endif
176 #endif
177 }
178
179 static struct gcov_fn_buffer *
free_fn_data(const struct gcov_info * gi_ptr,struct gcov_fn_buffer * buffer,unsigned int limit)180 free_fn_data(const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
181 unsigned int limit)
182 {
183 struct gcov_fn_buffer *next;
184 unsigned int ix, n_ctr = 0;
185
186 if (!buffer)
187 return 0;
188 next = buffer->next;
189
190 for (ix = 0; ix != limit; ix++)
191 if (gi_ptr->merge[ix])
192 free(buffer->info.ctrs[n_ctr++].values);
193 free(buffer);
194 return next;
195 }
196
197 static struct gcov_fn_buffer **
buffer_fn_data(const char * filename,const struct gcov_info * gi_ptr,struct gcov_fn_buffer ** end_ptr,unsigned int fn_ix)198 buffer_fn_data(const char *filename, const struct gcov_info *gi_ptr,
199 struct gcov_fn_buffer **end_ptr, unsigned int fn_ix)
200 {
201 unsigned int n_ctrs = 0, ix = 0;
202 struct gcov_fn_buffer *fn_buffer;
203 unsigned int len;
204
205 for (ix = GCOV_COUNTERS; ix--;)
206 if (gi_ptr->merge[ix])
207 n_ctrs++;
208
209 len = sizeof(*fn_buffer) + sizeof(fn_buffer->info.ctrs[0]) * n_ctrs;
210 fn_buffer = (struct gcov_fn_buffer *)malloc(len);
211
212 if (!fn_buffer)
213 goto fail;
214
215 fn_buffer->next = 0;
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();
220
221 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) {
222 gcov_unsigned_t length;
223 gcov_type *values;
224
225 if (!gi_ptr->merge[ix])
226 continue;
227
228 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix)) {
229 len = 0;
230 goto fail;
231 }
232
233 length = GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
234 len = length * sizeof(gcov_type);
235 values = (gcov_type *)malloc(len);
236 if (!values)
237 goto fail;
238
239 fn_buffer->info.ctrs[n_ctrs].num = length;
240 fn_buffer->info.ctrs[n_ctrs].values = values;
241
242 while (length--)
243 *values++ = gcov_read_counter();
244 n_ctrs++;
245 }
246
247 *end_ptr = fn_buffer;
248 return &fn_buffer->next;
249
250 fail:
251 fprintf(stderr, "profiling:%s:Function %u %s %u\n", filename, fn_ix,
252 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
253
254 return (struct gcov_fn_buffer **)free_fn_data(gi_ptr, fn_buffer, ix);
255 }
256
257 /* Add an unsigned value to the current crc */
258
259 static gcov_unsigned_t
crc32_unsigned(gcov_unsigned_t crc32,gcov_unsigned_t value)260 crc32_unsigned(gcov_unsigned_t crc32, gcov_unsigned_t value)
261 {
262 unsigned int ix;
263
264 for (ix = 32; ix--; value <<= 1) {
265 unsigned int feedback;
266
267 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
268 crc32 <<= 1;
269 crc32 ^= feedback;
270 }
271
272 return crc32;
273 }
274
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. */
279
280 static int
gcov_version(struct gcov_info * ptr,gcov_unsigned_t version,const char * filename)281 gcov_version(struct gcov_info *ptr, gcov_unsigned_t version,
282 const char *filename)
283 {
284 if (version != GCOV_VERSION) {
285 char v[4], e[4];
286
287 GCOV_UNSIGNED2STRING(v, version);
288 GCOV_UNSIGNED2STRING(e, GCOV_VERSION);
289
290 fprintf(stderr,
291 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
292 filename ? filename : ptr->filename, e, v);
293 return 0;
294 }
295 return 1;
296 }
297
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. */
304
305 static void
gcov_exit(void)306 gcov_exit(void)
307 {
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;
314 unsigned int t_ix;
315 int f_ix = 0;
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;
322
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);
329
330 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
331 f_ix++) {
332 gfi_ptr = gi_ptr->functions[f_ix];
333
334 if (gfi_ptr && gfi_ptr->key != gi_ptr)
335 gfi_ptr = 0;
336
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);
341 if (!gfi_ptr)
342 continue;
343
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])
347 continue;
348
349 cs_ptr = &this_prg.ctrs[t_ix];
350 cs_ptr->num += ci_ptr->num;
351 crc32 = crc32_unsigned(crc32, ci_ptr->num);
352
353 for (c_num = 0; c_num < ci_ptr->num; c_num++) {
354 cs_ptr->sum_all +=
355 ci_ptr->values[c_num];
356 if (cs_ptr->run_max
357 < ci_ptr->values[c_num])
358 cs_ptr->run_max =
359 ci_ptr->values[c_num];
360 }
361 ci_ptr++;
362 }
363 }
364 }
365
366 #ifndef __COREBOOT__
367 {
368 /* Check if the level of dirs to strip off specified. */
369 char *tmp = getenv("GCOV_PREFIX_STRIP");
370 if (tmp) {
371 gcov_prefix_strip = atoi(tmp);
372 /* Do not consider negative values. */
373 if (gcov_prefix_strip < 0)
374 gcov_prefix_strip = 0;
375 }
376 }
377
378 /* Get file name relocation prefix. Non-absolute values are ignored. */
379 gcov_prefix = getenv("GCOV_PREFIX");
380 if (gcov_prefix) {
381 prefix_length = strlen(gcov_prefix);
382
383 /* Remove an unnecessary trailing '/' */
384 if (IS_DIR_SEPARATOR(gcov_prefix[prefix_length - 1]))
385 prefix_length--;
386 } else
387 #endif
388 prefix_length = 0;
389
390 /* If no prefix was specified and a prefix strip, then we assume
391 relative. */
392 if (gcov_prefix_strip != 0 && prefix_length == 0) {
393 gcov_prefix = ".";
394 prefix_length = 1;
395 }
396 /* Allocate and initialize the filename scratch space plus one. */
397 gi_filename = (char *) alloca(prefix_length + gcov_max_filename + 2);
398 if (prefix_length)
399 memcpy(gi_filename, gcov_prefix, prefix_length);
400 gi_filename_up = gi_filename + prefix_length;
401
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
406 program. */
407 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
408 int error = 0;
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;
415
416 fname = gi_ptr->filename;
417
418 /* Avoid to add multiple drive letters into combined path. */
419 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
420 fname += 2;
421
422 /* Build relocated filename, stripping off leading
423 * directories from the initial filename if requested.
424 */
425 if (gcov_prefix_strip > 0) {
426 int level = 0;
427
428 s = fname;
429 if (IS_DIR_SEPARATOR(*s))
430 ++s;
431
432 /* Skip selected directory levels. */
433 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
434 if (IS_DIR_SEPARATOR(*s)) {
435 fname = s;
436 level++;
437 }
438 }
439
440 /* Update complete filename with stripped original. */
441 if (prefix_length != 0 && !IS_DIR_SEPARATOR(*fname)) {
442 /* If prefix is given, add directory separator.
443 */
444 strcpy(gi_filename_up, "/");
445 strcpy(gi_filename_up + 1, fname);
446 } else
447 strcpy(gi_filename_up, fname);
448
449 if (!gcov_open(gi_filename)) {
450 /* Open failed likely due to missed directory.
451 * Create directory and retry to open file.
452 */
453 if (create_file_directory(gi_filename)) {
454 fprintf(stderr, "profiling:%s:Skip\n",
455 gi_filename);
456 continue;
457 }
458 if (!gcov_open(gi_filename)) {
459 fprintf(stderr,
460 "profiling:%s:Cannot open\n",
461 gi_filename);
462 continue;
463 }
464 }
465
466 tag = gcov_read_unsigned();
467 if (tag) {
468 /* Merge data from file. */
469 if (tag != GCOV_DATA_MAGIC) {
470 fprintf(stderr,
471 "profiling:%s:Not a gcov data file\n",
472 gi_filename);
473 goto read_fatal;
474 }
475 length = gcov_read_unsigned();
476 if (!gcov_version(gi_ptr, length, gi_filename))
477 goto read_fatal;
478
479 length = gcov_read_unsigned();
480 if (length != gi_ptr->stamp)
481 /* Read from a different compilation.
482 * Overwrite the file.
483 */
484 goto rewrite;
485
486 /* Look for program summary. */
487 for (f_ix = 0;;) {
488 struct gcov_summary tmp;
489
490 eof_pos = gcov_position();
491 tag = gcov_read_unsigned();
492 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
493 break;
494
495 f_ix--;
496 length = gcov_read_unsigned();
497 if (length != GCOV_TAG_SUMMARY_LENGTH)
498 goto read_mismatch;
499 gcov_read_summary(&tmp);
500 error = gcov_is_error();
501 if (error)
502 goto read_error;
503 if (summary_pos
504 || tmp.checksum != crc32)
505 goto next_summary;
506
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)
511 goto next_summary;
512 prg = tmp;
513 summary_pos = eof_pos;
514
515 next_summary:;
516 }
517
518 /* Merge execution counts for each function. */
519 for (f_ix = 0; (unsigned int)f_ix !=
520 gi_ptr->n_functions;
521 f_ix++, tag = gcov_read_unsigned()) {
522 gfi_ptr = gi_ptr->functions[f_ix];
523
524 if (tag != GCOV_TAG_FUNCTION)
525 goto read_mismatch;
526
527 length = gcov_read_unsigned();
528 if (!length)
529 /* This function did not appear
530 * in the other program. We
531 * have nothing to merge.
532 */
533 continue;
534
535 if (length != GCOV_TAG_FUNCTION_LENGTH)
536 goto read_mismatch;
537
538 if (!gfi_ptr || gfi_ptr->key !=
539 gi_ptr) {
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
547 * file.
548 */
549 fn_tail = buffer_fn_data(
550 gi_filename, gi_ptr,
551 fn_tail, f_ix);
552 if (!fn_tail)
553 goto read_mismatch;
554 continue;
555 }
556
557 length = gcov_read_unsigned();
558 if (length != gfi_ptr->ident)
559 goto read_mismatch;
560
561 length = gcov_read_unsigned();
562 if (length != gfi_ptr->lineno_checksum)
563 goto read_mismatch;
564
565 length = gcov_read_unsigned();
566 if (length != gfi_ptr->cfg_checksum)
567 goto read_mismatch;
568
569 ci_ptr = gfi_ptr->ctrs;
570 for (t_ix = 0; t_ix < GCOV_COUNTERS;
571 t_ix++) {
572 gcov_merge_fn merge =
573 gi_ptr->merge[t_ix];
574
575 if (!merge)
576 continue;
577
578 tag = gcov_read_unsigned();
579 length = gcov_read_unsigned();
580 if (tag != GCOV_TAG_FOR_COUNTER(
581 t_ix) || length !=
582 GCOV_TAG_COUNTER_LENGTH(
583 ci_ptr->num))
584 goto read_mismatch;
585 (*merge)(ci_ptr->values,
586 ci_ptr->num);
587 ci_ptr++;
588 }
589 error = gcov_is_error();
590 if (error)
591 goto read_error;
592 }
593
594 if (tag) {
595 read_mismatch:;
596 fprintf(stderr,
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);
601 goto read_fatal;
602 }
603 }
604 goto rewrite;
605
606 read_error:;
607 fprintf(stderr, "profiling:%s:%s merging\n", gi_filename,
608 error < 0 ? "Overflow" : "Error");
609
610 goto read_fatal;
611
612 rewrite:;
613 gcov_rewrite();
614 if (!summary_pos) {
615 memset(&prg, 0, sizeof(prg));
616 summary_pos = eof_pos;
617 }
618
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];
624
625 if (gi_ptr->merge[t_ix]) {
626 if (!cs_prg->runs++)
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)
633 goto read_mismatch;
634
635 if (!cs_all->runs && cs_prg->runs)
636 memcpy(cs_all, cs_prg, sizeof(*cs_all));
637 else if (!all_prg.checksum
638 && (!GCOV_LOCKED
639 || cs_all->runs == cs_prg->runs)
640 && memcmp(cs_all, cs_prg, sizeof(*cs_all))) {
641 fprintf(stderr,
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;
646 }
647 }
648
649 prg.checksum = crc32;
650
651 /* Write out the data. */
652 if (!eof_pos) {
653 gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
654 gcov_write_unsigned(gi_ptr->stamp);
655 }
656
657 if (summary_pos)
658 gcov_seek(summary_pos);
659
660 /* Generate whole program statistics. */
661 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY, &prg);
662
663 if (summary_pos < eof_pos)
664 gcov_seek(eof_pos);
665
666 /* Write execution counts for each function. */
667 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
668 f_ix++) {
669 unsigned int buffered = 0;
670
671 if (fn_buffer && fn_buffer->fn_ix
672 == (unsigned int)f_ix) {
673 /* Buffered data from another program. */
674 buffered = 1;
675 gfi_ptr = &fn_buffer->info;
676 length = GCOV_TAG_FUNCTION_LENGTH;
677 } else {
678 gfi_ptr = gi_ptr->functions[f_ix];
679 if (gfi_ptr && gfi_ptr->key == gi_ptr)
680 length = GCOV_TAG_FUNCTION_LENGTH;
681 else
682 length = 0;
683 }
684
685 gcov_write_tag_length(GCOV_TAG_FUNCTION, length);
686 if (!length)
687 continue;
688
689 gcov_write_unsigned(gfi_ptr->ident);
690 gcov_write_unsigned(gfi_ptr->lineno_checksum);
691 gcov_write_unsigned(gfi_ptr->cfg_checksum);
692
693 ci_ptr = gfi_ptr->ctrs;
694 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) {
695 if (!gi_ptr->merge[t_ix])
696 continue;
697
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;
703 while (n_counts--)
704 gcov_write_counter(*c_ptr++);
705 ci_ptr++;
706 }
707 if (buffered)
708 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
709 GCOV_COUNTERS);
710 }
711
712 gcov_write_unsigned(0);
713
714 read_fatal:;
715 while (fn_buffer)
716 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
717 GCOV_COUNTERS);
718
719 error = gcov_close();
720 if (error)
721 fprintf(stderr, error < 0 ?
722 "profiling:%s:Overflow writing\n" :
723 "profiling:%s:Error writing\n",
724 gi_filename);
725 }
726 }
727
728 /* Add a new object file onto the bb chain. Invoked automatically
729 when running an object file's global ctors. */
730
731 void
__gcov_init(struct gcov_info * info)732 __gcov_init(struct gcov_info *info)
733 {
734 if (!info->version || !info->n_functions)
735 return;
736 if (gcov_version(info, info->version, 0)) {
737 size_t filename_length = strlen(info->filename);
738
739 /* Refresh the longest file name information */
740 if (filename_length > gcov_max_filename)
741 gcov_max_filename = filename_length;
742
743 #ifndef __COREBOOT__
744 if (!gcov_list)
745 atexit(gcov_exit);
746 #endif
747
748 info->next = gcov_list;
749 gcov_list = info;
750 }
751 info->version = 0;
752 }
753
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. */
757
758 void
__gcov_flush(void)759 __gcov_flush(void)
760 {
761 const struct gcov_info *gi_ptr;
762
763 gcov_exit();
764 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) {
765 unsigned int f_ix;
766
767 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) {
768 unsigned int t_ix;
769 const struct gcov_fn_info *gfi_ptr =
770 gi_ptr->functions[f_ix];
771
772 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
773 continue;
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])
777 continue;
778
779 memset(ci_ptr->values, 0,
780 sizeof(gcov_type) * ci_ptr->num);
781 ci_ptr++;
782 }
783 }
784 }
785 }
786
787 #endif /* L_gcov */
788
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. */
793 void
__gcov_merge_add(gcov_type * counters,unsigned int n_counters)794 __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
795 {
796 for (; n_counters; counters++, n_counters--)
797 *counters += gcov_read_counter();
798 }
799 #endif /* L_gcov_merge_add */
800
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. */
805 void
__gcov_merge_ior(gcov_type * counters,unsigned int n_counters)806 __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
807 {
808 for (; n_counters; counters++, n_counters--)
809 *counters |= gcov_read_counter();
810 }
811 #endif
812
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
818 * meanings:
819 *
820 * -- the stored candidate on the most common value of the measured entity
821 * -- counter
822 * -- total number of evaluations of the value
823 */
824 void
__gcov_merge_single(gcov_type * counters,unsigned int n_counters)825 __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
826 {
827 unsigned int i, n_measures;
828 gcov_type value, counter, all;
829
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();
836
837 if (counters[0] == value)
838 counters[1] += counter;
839 else if (counter > counters[1]) {
840 counters[0] = value;
841 counters[1] = counter - counters[1];
842 } else
843 counters[1] -= counter;
844 counters[2] += all;
845 }
846 }
847 #endif /* L_gcov_merge_single */
848
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:
855 *
856 * -- the last value of the measured entity
857 * -- the stored candidate on the most common difference
858 * -- counter
859 * -- total number of evaluations of the value
860 */
861 void
__gcov_merge_delta(gcov_type * counters,unsigned int n_counters)862 __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
863 {
864 unsigned int i, n_measures;
865 gcov_type value, counter, all;
866
867 gcc_assert(!(n_counters % 4));
868 n_measures = n_counters / 4;
869 for (i = 0; i < n_measures; i++, counters += 4) {
870 /* last = */
871 gcov_read_counter();
872 value = gcov_read_counter();
873 counter = gcov_read_counter();
874 all = gcov_read_counter();
875
876 if (counters[1] == value)
877 counters[2] += counter;
878 else if (counter > counters[2]) {
879 counters[1] = value;
880 counters[2] = counter - counters[2];
881 } else
882 counters[2] -= counter;
883 counters[3] += all;
884 }
885 }
886 #endif /* L_gcov_merge_delta */
887
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
892 instead. */
893
894 void
__gcov_interval_profiler(gcov_type * counters,gcov_type value,int start,unsigned int steps)895 __gcov_interval_profiler(gcov_type *counters, gcov_type value,
896 int start, unsigned int steps)
897 {
898 gcov_type delta = value - start;
899 if (delta < 0)
900 counters[steps + 1]++;
901 else if (delta >= steps)
902 counters[steps]++;
903 else
904 counters[delta]++;
905 }
906 #endif
907
908 #ifdef L_gcov_pow2_profiler
909 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
910 COUNTERS[0] is incremented. */
911
912 void
__gcov_pow2_profiler(gcov_type * counters,gcov_type value)913 __gcov_pow2_profiler(gcov_type *counters, gcov_type value)
914 {
915 if (value & (value - 1))
916 counters[0]++;
917 else
918 counters[1]++;
919 }
920 #endif
921
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.
929
930 In any case, COUNTERS[2] is incremented. */
931
932 static inline void
__gcov_one_value_profiler_body(gcov_type * counters,gcov_type value)933 __gcov_one_value_profiler_body(gcov_type *counters, gcov_type value)
934 {
935 if (value == counters[0])
936 counters[1]++;
937 else if (counters[1] == 0) {
938 counters[1] = 1;
939 counters[0] = value;
940 } else
941 counters[1]--;
942 counters[2]++;
943 }
944
945 #ifdef L_gcov_one_value_profiler
946 void
__gcov_one_value_profiler(gcov_type * counters,gcov_type value)947 __gcov_one_value_profiler(gcov_type *counters, gcov_type value)
948 {
949 __gcov_one_value_profiler_body(counters, value);
950 }
951 #endif
952
953 #ifdef L_gcov_indirect_call_profiler
954
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.
962
963 It is assumed that the address of a function descriptor may be treated
964 as a pointer to a function. */
965
966 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
967 #define VTABLE_USES_DESCRIPTORS 1
968 #else
969 #define VTABLE_USES_DESCRIPTORS 0
970 #endif
971
972 /* Tries to determine the most common value among its inputs. */
973 void
__gcov_indirect_call_profiler(gcov_type * counter,gcov_type value,void * cur_func,void * callee_func)974 __gcov_indirect_call_profiler(gcov_type *counter, gcov_type value,
975 void *cur_func, void *callee_func)
976 {
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.
980 */
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);
985 }
986 #endif
987
988
989 #ifdef L_gcov_average_profiler
990 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
991 to saturate up. */
992
993 void
__gcov_average_profiler(gcov_type * counters,gcov_type value)994 __gcov_average_profiler(gcov_type *counters, gcov_type value)
995 {
996 counters[0] += value;
997 counters[1]++;
998 }
999 #endif
1000
1001 #ifdef L_gcov_ior_profiler
1002 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1003 to saturate up. */
1004
1005 void
__gcov_ior_profiler(gcov_type * counters,gcov_type value)1006 __gcov_ior_profiler(gcov_type *counters, gcov_type value)
1007 {
1008 *counters |= value;
1009 }
1010 #endif
1011
1012 #ifdef L_gcov_fork
1013 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1014 that they are not counted twice. */
1015
1016 pid_t
__gcov_fork(void)1017 __gcov_fork(void)
1018 {
1019 __gcov_flush();
1020 return fork();
1021 }
1022 #endif
1023
1024 #ifdef L_gcov_execl
1025 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1026 that they are not lost. */
1027
1028 int
__gcov_execl(const char * path,char * arg,...)1029 __gcov_execl(const char *path, char *arg, ...)
1030 {
1031 va_list ap, aq;
1032 unsigned int i, length;
1033 char **args;
1034
1035 __gcov_flush();
1036
1037 va_start(ap, arg);
1038 va_copy(aq, ap);
1039
1040 length = 2;
1041 while (va_arg(ap, char *))
1042 length++;
1043 va_end(ap);
1044
1045 args = (char **) alloca(length * sizeof(void *));
1046 args[0] = arg;
1047 for (i = 1; i < length; i++)
1048 args[i] = va_arg(aq, char *);
1049 va_end(aq);
1050
1051 return execv(path, args);
1052 }
1053 #endif
1054
1055 #ifdef L_gcov_execlp
1056 /* A wrapper for the execlp function. Flushes the accumulated profiling data,
1057 * so that they are not lost.
1058 */
1059
1060 int
__gcov_execlp(const char * path,char * arg,...)1061 __gcov_execlp(const char *path, char *arg, ...)
1062 {
1063 va_list ap, aq;
1064 unsigned int i, length;
1065 char **args;
1066
1067 __gcov_flush();
1068
1069 va_start(ap, arg);
1070 va_copy(aq, ap);
1071
1072 length = 2;
1073 while (va_arg(ap, char *))
1074 length++;
1075 va_end(ap);
1076
1077 args = (char **) alloca(length * sizeof(void *));
1078 args[0] = arg;
1079 for (i = 1; i < length; i++)
1080 args[i] = va_arg(aq, char *);
1081 va_end(aq);
1082
1083 return execvp(path, args);
1084 }
1085 #endif
1086
1087 #ifdef L_gcov_execle
1088 /* A wrapper for the execle function. Flushes the accumulated profiling data,
1089 * so that they are not lost.
1090 */
1091
1092 int
__gcov_execle(const char * path,char * arg,...)1093 __gcov_execle(const char *path, char *arg, ...)
1094 {
1095 va_list ap, aq;
1096 unsigned int i, length;
1097 char **args;
1098 char **envp;
1099
1100 __gcov_flush();
1101
1102 va_start(ap, arg);
1103 va_copy(aq, ap);
1104
1105 length = 2;
1106 while (va_arg(ap, char *))
1107 length++;
1108 va_end(ap);
1109
1110 args = (char **) alloca(length * sizeof(void *));
1111 args[0] = arg;
1112 for (i = 1; i < length; i++)
1113 args[i] = va_arg(aq, char *);
1114 envp = va_arg(aq, char **);
1115 va_end(aq);
1116
1117 return execve(path, args, envp);
1118 }
1119 #endif
1120
1121 #ifdef L_gcov_execv
1122 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1123 that they are not lost. */
1124
1125 int
__gcov_execv(const char * path,char * const argv[])1126 __gcov_execv(const char *path, char *const argv[])
1127 {
1128 __gcov_flush();
1129 return execv(path, argv);
1130 }
1131 #endif
1132
1133 #ifdef L_gcov_execvp
1134 /* A wrapper for the execvp function. Flushes the accumulated profiling data,
1135 * so that they are not lost.
1136 */
1137
1138 int
__gcov_execvp(const char * path,char * const argv[])1139 __gcov_execvp(const char *path, char *const argv[])
1140 {
1141 __gcov_flush();
1142 return execvp(path, argv);
1143 }
1144 #endif
1145
1146 #ifdef L_gcov_execve
1147 /* A wrapper for the execve function. Flushes the accumulated profiling data,
1148 * so that they are not lost.
1149 */
1150
1151 int
__gcov_execve(const char * path,char * const argv[],char * const envp[])1152 __gcov_execve(const char *path, char *const argv[], char *const envp[])
1153 {
1154 __gcov_flush();
1155 return execve(path, argv, envp);
1156 }
1157 #endif
1158 #endif /* inhibit_libc */
1159