xref: /aosp_15_r20/external/coreboot/src/lib/libgcov.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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