blob: 3e94664cf3566668353b2eadde93163de7391bac [file] [log] [blame]
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001/* 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.
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 3, or (at your option) any later
12version.
13
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
18
19Under Section 7 of GPL version 3, you are granted additional
20permissions described in the GCC Runtime Library Exception, version
213.1, as published by the Free Software Foundation.
Patrick Georgia73b9312015-10-31 11:55:10 +010022*/
Stefan Reinauerd37ab452012-12-18 16:23:28 -080023
24#define __COREBOOT__
25#ifdef __COREBOOT__
26#include <stdlib.h>
27#include <string.h>
28#include <console/console.h>
29#include <assert.h>
30typedef s32 pid_t;
31#define gcc_assert(x) ASSERT(x)
32#define fprintf(file, x...) printk(BIOS_ERR, x)
Lee Leahy38768c32017-03-09 14:07:18 -080033#define alloca(size) __builtin_alloca(size)
Stefan Reinauerd37ab452012-12-18 16:23:28 -080034#include "gcov-glue.c"
35
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
44
45# define HAVE_CC_TLS 0
46# define __GCOV_KERNEL__
47
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__ */
57
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"
71
72#if defined(inhibit_libc)
73/* If libc and its header files are not available, provide dummy functions. */
74
75#ifdef L_gcov
Lee Leahy38768c32017-03-09 14:07:18 -080076void __gcov_init(struct gcov_info *p __attribute__ ((unused))) {}
77void __gcov_flush(void) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080078#endif
79
80#ifdef L_gcov_merge_add
Lee Leahy38768c32017-03-09 14:07:18 -080081void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)),
Lee Leahy75b85992017-03-08 16:34:12 -080082 unsigned int n_counters __attribute__ ((unused))) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080083#endif
84
85#ifdef L_gcov_merge_single
Lee Leahy38768c32017-03-09 14:07:18 -080086void __gcov_merge_single(gcov_type *counters __attribute__ ((unused)),
Lee Leahy75b85992017-03-08 16:34:12 -080087 unsigned int n_counters __attribute__ ((unused))) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080088#endif
89
90#ifdef L_gcov_merge_delta
Lee Leahy38768c32017-03-09 14:07:18 -080091void __gcov_merge_delta(gcov_type *counters __attribute__ ((unused)),
Lee Leahy75b85992017-03-08 16:34:12 -080092 unsigned int n_counters __attribute__ ((unused))) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080093#endif
94
95#else
96
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
105void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)),
Lee Leahy75b85992017-03-08 16:34:12 -0800106 unsigned int n_counters __attribute__ ((unused))) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800107#endif /* __COREBOOT__ */
108
109#ifdef L_gcov
110#include "gcov-io.c"
111
112struct gcov_fn_buffer
113{
Lee Leahye20a3192017-03-09 16:21:34 -0800114 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. */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800118};
119
120/* Chain of per-object gcov structures. */
121static struct gcov_info *gcov_list;
122
123/* Size of the longest file name. */
124static 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
130static int
Lee Leahy38768c32017-03-09 14:07:18 -0800131create_file_directory(char *filename)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800132{
133#ifdef __COREBOOT__
Lee Leahye20a3192017-03-09 16:21:34 -0800134 (void) filename;
135 return 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800136#else
137#if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
Lee Leahye20a3192017-03-09 16:21:34 -0800138 (void) filename;
139 return -1;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800140#else
Lee Leahye20a3192017-03-09 16:21:34 -0800141 char *s;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800142
Lee Leahye20a3192017-03-09 16:21:34 -0800143 s = filename;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800144
Lee Leahye20a3192017-03-09 16:21:34 -0800145 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';
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800153
Lee Leahye20a3192017-03-09 16:21:34 -0800154 /* Try to make directory if it doesn't already exist. */
155 if (access(filename, F_OK) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800156#ifdef TARGET_POSIX_IO
Lee Leahye20a3192017-03-09 16:21:34 -0800157 && mkdir(filename, 0755) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800158#else
Lee Leahye20a3192017-03-09 16:21:34 -0800159 && mkdir(filename) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800160#endif
Lee Leahye20a3192017-03-09 16:21:34 -0800161 /* 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 };
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800171
Lee Leahye20a3192017-03-09 16:21:34 -0800172 *s = sep;
173 };
174 return 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800175#endif
176#endif
177}
178
179static struct gcov_fn_buffer *
Lee Leahy38768c32017-03-09 14:07:18 -0800180free_fn_data(const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
Lee Leahy75b85992017-03-08 16:34:12 -0800181 unsigned int limit)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800182{
Lee Leahye20a3192017-03-09 16:21:34 -0800183 struct gcov_fn_buffer *next;
184 unsigned int ix, n_ctr = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800185
Lee Leahye20a3192017-03-09 16:21:34 -0800186 if (!buffer)
187 return 0;
188 next = buffer->next;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800189
Lee Leahye20a3192017-03-09 16:21:34 -0800190 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800195}
196
197static struct gcov_fn_buffer **
Lee Leahy38768c32017-03-09 14:07:18 -0800198buffer_fn_data(const char *filename, const struct gcov_info *gi_ptr,
Lee Leahy75b85992017-03-08 16:34:12 -0800199 struct gcov_fn_buffer **end_ptr, unsigned int fn_ix)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800200{
Lee Leahye20a3192017-03-09 16:21:34 -0800201 unsigned int n_ctrs = 0, ix = 0;
202 struct gcov_fn_buffer *fn_buffer;
203 unsigned int len;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800204
Lee Leahye20a3192017-03-09 16:21:34 -0800205 for (ix = GCOV_COUNTERS; ix--;)
206 if (gi_ptr->merge[ix])
207 n_ctrs++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800208
Lee Leahye20a3192017-03-09 16:21:34 -0800209 len = sizeof(*fn_buffer) + sizeof(fn_buffer->info.ctrs[0]) * n_ctrs;
210 fn_buffer = (struct gcov_fn_buffer *)malloc(len);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800211
Lee Leahye20a3192017-03-09 16:21:34 -0800212 if (!fn_buffer)
213 goto fail;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800214
Lee Leahye20a3192017-03-09 16:21:34 -0800215 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();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800220
Lee Leahye20a3192017-03-09 16:21:34 -0800221 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) {
222 gcov_unsigned_t length;
223 gcov_type *values;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800224
Lee Leahye20a3192017-03-09 16:21:34 -0800225 if (!gi_ptr->merge[ix])
226 continue;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800227
Lee Leahye20a3192017-03-09 16:21:34 -0800228 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++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800245 }
246
Lee Leahye20a3192017-03-09 16:21:34 -0800247 *end_ptr = fn_buffer;
248 return &fn_buffer->next;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800249
250fail:
Lee Leahy35af5c42017-03-09 17:35:28 -0800251 fprintf(stderr, "profiling:%s:Function %u %s %u\n", filename, fn_ix,
Lee Leahye20a3192017-03-09 16:21:34 -0800252 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800253
Lee Leahye20a3192017-03-09 16:21:34 -0800254 return (struct gcov_fn_buffer **)free_fn_data(gi_ptr, fn_buffer, ix);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800255}
256
257/* Add an unsigned value to the current crc */
258
259static gcov_unsigned_t
Lee Leahy38768c32017-03-09 14:07:18 -0800260crc32_unsigned(gcov_unsigned_t crc32, gcov_unsigned_t value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800261{
Lee Leahye20a3192017-03-09 16:21:34 -0800262 unsigned int ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800263
Lee Leahye20a3192017-03-09 16:21:34 -0800264 for (ix = 32; ix--; value <<= 1) {
265 unsigned int feedback;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800266
Lee Leahye20a3192017-03-09 16:21:34 -0800267 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
268 crc32 <<= 1;
269 crc32 ^= feedback;
270 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800271
Lee Leahye20a3192017-03-09 16:21:34 -0800272 return crc32;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800273}
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
280static int
Lee Leahy38768c32017-03-09 14:07:18 -0800281gcov_version(struct gcov_info *ptr, gcov_unsigned_t version,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800282 const char *filename)
283{
Lee Leahye20a3192017-03-09 16:21:34 -0800284 if (version != GCOV_VERSION) {
285 char v[4], e[4];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800286
Lee Leahye20a3192017-03-09 16:21:34 -0800287 GCOV_UNSIGNED2STRING(v, version);
288 GCOV_UNSIGNED2STRING(e, GCOV_VERSION);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800289
Lee Leahye20a3192017-03-09 16:21:34 -0800290 fprintf(stderr,
291 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
Lee Leahy35af5c42017-03-09 17:35:28 -0800292 filename ? filename : ptr->filename, e, v);
Lee Leahye20a3192017-03-09 16:21:34 -0800293 return 0;
294 }
295 return 1;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800296}
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
305static void
Lee Leahy38768c32017-03-09 14:07:18 -0800306gcov_exit(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800307{
Lee Leahye20a3192017-03-09 16:21:34 -0800308 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800322
Lee Leahye20a3192017-03-09 16:21:34 -0800323 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);
Kyösti Mälkkiecd84242013-09-13 07:57:49 +0300329
Lee Leahye20a3192017-03-09 16:21:34 -0800330 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
331 f_ix++) {
332 gfi_ptr = gi_ptr->functions[f_ix];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800333
Lee Leahye20a3192017-03-09 16:21:34 -0800334 if (gfi_ptr && gfi_ptr->key != gi_ptr)
335 gfi_ptr = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800336
Lee Leahye20a3192017-03-09 16:21:34 -0800337 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800343
Lee Leahye20a3192017-03-09 16:21:34 -0800344 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800348
Lee Leahye20a3192017-03-09 16:21:34 -0800349 cs_ptr = &this_prg.ctrs[t_ix];
350 cs_ptr->num += ci_ptr->num;
351 crc32 = crc32_unsigned(crc32, ci_ptr->num);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800352
Lee Leahye20a3192017-03-09 16:21:34 -0800353 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 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800363 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800364 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800365
366#ifndef __COREBOOT__
Lee Leahye20a3192017-03-09 16:21:34 -0800367 {
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 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800377
Lee Leahye20a3192017-03-09 16:21:34 -0800378 /* 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);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800382
Lee Leahye20a3192017-03-09 16:21:34 -0800383 /* Remove an unnecessary trailing '/' */
384 if (IS_DIR_SEPARATOR(gcov_prefix[prefix_length - 1]))
385 prefix_length--;
386 } else
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800387#endif
Lee Leahye20a3192017-03-09 16:21:34 -0800388 prefix_length = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800389
Lee Leahye20a3192017-03-09 16:21:34 -0800390 /* 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800395 }
Lee Leahye20a3192017-03-09 16:21:34 -0800396 /* 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800401
Lee Leahye20a3192017-03-09 16:21:34 -0800402 /* 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 = 0;
414 struct gcov_fn_buffer **fn_tail = &fn_buffer;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800415
Lee Leahye20a3192017-03-09 16:21:34 -0800416 fname = gi_ptr->filename;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800417
Lee Leahye20a3192017-03-09 16:21:34 -0800418 /* Avoid to add multiple drive letters into combined path. */
419 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
420 fname += 2;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800421
Lee Leahye20a3192017-03-09 16:21:34 -0800422 /* 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800427
Lee Leahye20a3192017-03-09 16:21:34 -0800428 s = fname;
429 if (IS_DIR_SEPARATOR(*s))
430 ++s;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800431
Lee Leahye20a3192017-03-09 16:21:34 -0800432 /* 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 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800439
Lee Leahye20a3192017-03-09 16:21:34 -0800440 /* 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);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800448
Lee Leahye20a3192017-03-09 16:21:34 -0800449 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 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800465
Lee Leahye20a3192017-03-09 16:21:34 -0800466 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;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800478
Lee Leahye20a3192017-03-09 16:21:34 -0800479 length = gcov_read_unsigned();
480 if (length != gi_ptr->stamp)
481 /* Read from a different compilation.
482 * Overwrite the file.
483 */
484 goto rewrite;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800485
Lee Leahye20a3192017-03-09 16:21:34 -0800486 /* Look for program summary. */
487 for (f_ix = 0;;) {
488 struct gcov_summary tmp;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800489
Lee Leahye20a3192017-03-09 16:21:34 -0800490 eof_pos = gcov_position();
491 tag = gcov_read_unsigned();
492 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
493 break;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800494
Lee Leahye20a3192017-03-09 16:21:34 -0800495 f_ix--;
496 length = gcov_read_unsigned();
497 if (length != GCOV_TAG_SUMMARY_LENGTH)
498 goto read_mismatch;
499 gcov_read_summary(&tmp);
500 if ((error = gcov_is_error()))
501 goto read_error;
502 if (summary_pos
503 || tmp.checksum != crc32)
504 goto next_summary;
505
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;
513
514 next_summary:;
515 }
516
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];
522
523 if (tag != GCOV_TAG_FUNCTION)
524 goto read_mismatch;
525
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.
531 */
532 continue;
533
534 if (length != GCOV_TAG_FUNCTION_LENGTH)
535 goto read_mismatch;
536
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.
547 */
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;
554 }
555
556 length = gcov_read_unsigned();
557 if (length != gfi_ptr->ident)
558 goto read_mismatch;
559
560 length = gcov_read_unsigned();
561 if (length != gfi_ptr->lineno_checksum)
562 goto read_mismatch;
563
564 length = gcov_read_unsigned();
565 if (length != gfi_ptr->cfg_checksum)
566 goto read_mismatch;
567
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];
573
574 if (!merge)
575 continue;
576
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++;
587 }
588 if ((error = gcov_is_error()))
589 goto read_error;
590 }
591
592 if (tag) {
593 read_mismatch:;
594 fprintf(stderr,
595 "profiling:%s:Merge mismatch for %s %u\n",
596 gi_filename, f_ix >= 0 ?
597 "function" : "summary",
598 f_ix < 0 ? -1 - f_ix : f_ix);
599 goto read_fatal;
600 }
601 }
602 goto rewrite;
603
604read_error:;
605 fprintf(stderr, "profiling:%s:%s merging\n", gi_filename,
Lee Leahy35af5c42017-03-09 17:35:28 -0800606 error < 0 ? "Overflow" : "Error");
Lee Leahye20a3192017-03-09 16:21:34 -0800607
608 goto read_fatal;
609
610rewrite:;
611 gcov_rewrite();
612 if (!summary_pos) {
613 memset(&prg, 0, sizeof(prg));
614 summary_pos = eof_pos;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800615 }
616
Lee Leahye20a3192017-03-09 16:21:34 -0800617 /* Merge the summaries. */
618 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) {
619 cs_prg = &prg.ctrs[t_ix];
620 cs_tprg = &this_prg.ctrs[t_ix];
621 cs_all = &all_prg.ctrs[t_ix];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800622
Lee Leahye20a3192017-03-09 16:21:34 -0800623 if (gi_ptr->merge[t_ix]) {
624 if (!cs_prg->runs++)
625 cs_prg->num = cs_tprg->num;
626 cs_prg->sum_all += cs_tprg->sum_all;
627 if (cs_prg->run_max < cs_tprg->run_max)
628 cs_prg->run_max = cs_tprg->run_max;
629 cs_prg->sum_max += cs_tprg->run_max;
630 } else if (cs_prg->runs)
631 goto read_mismatch;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800632
Lee Leahye20a3192017-03-09 16:21:34 -0800633 if (!cs_all->runs && cs_prg->runs)
634 memcpy(cs_all, cs_prg, sizeof(*cs_all));
635 else if (!all_prg.checksum
636 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
637 && memcmp(cs_all, cs_prg, sizeof(*cs_all))) {
638 fprintf(stderr,
639 "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
640 gi_filename, GCOV_LOCKED ? "" :
641 " or concurrently updated without locking support");
642 all_prg.checksum = ~0u;
643 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800644 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800645
Lee Leahye20a3192017-03-09 16:21:34 -0800646 prg.checksum = crc32;
647
648 /* Write out the data. */
649 if (!eof_pos) {
650 gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
651 gcov_write_unsigned(gi_ptr->stamp);
652 }
653
654 if (summary_pos)
655 gcov_seek(summary_pos);
656
657 /* Generate whole program statistics. */
658 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY, &prg);
659
660 if (summary_pos < eof_pos)
661 gcov_seek(eof_pos);
662
663 /* Write execution counts for each function. */
664 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions; f_ix++) {
665 unsigned int buffered = 0;
666
667 if (fn_buffer && fn_buffer->fn_ix == (unsigned int)f_ix) {
668 /* Buffered data from another program. */
669 buffered = 1;
670 gfi_ptr = &fn_buffer->info;
671 length = GCOV_TAG_FUNCTION_LENGTH;
672 } else {
673 gfi_ptr = gi_ptr->functions[f_ix];
674 if (gfi_ptr && gfi_ptr->key == gi_ptr)
675 length = GCOV_TAG_FUNCTION_LENGTH;
676 else
677 length = 0;
678 }
679
680 gcov_write_tag_length(GCOV_TAG_FUNCTION, length);
681 if (!length)
682 continue;
683
684 gcov_write_unsigned(gfi_ptr->ident);
685 gcov_write_unsigned(gfi_ptr->lineno_checksum);
686 gcov_write_unsigned(gfi_ptr->cfg_checksum);
687
688 ci_ptr = gfi_ptr->ctrs;
689 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) {
690 if (!gi_ptr->merge[t_ix])
691 continue;
692
693 n_counts = ci_ptr->num;
694 gcov_write_tag_length(GCOV_TAG_FOR_COUNTER(t_ix),
695 GCOV_TAG_COUNTER_LENGTH(n_counts));
696 gcov_type *c_ptr = ci_ptr->values;
697 while (n_counts--)
698 gcov_write_counter(*c_ptr++);
699 ci_ptr++;
700 }
701 if (buffered)
702 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
703 GCOV_COUNTERS);
704 }
705
706 gcov_write_unsigned(0);
707
708read_fatal:;
709 while (fn_buffer)
710 fn_buffer = free_fn_data(gi_ptr, fn_buffer, GCOV_COUNTERS);
711
712 if ((error = gcov_close()))
713 fprintf(stderr, error < 0 ?
714 "profiling:%s:Overflow writing\n" :
715 "profiling:%s:Error writing\n",
716 gi_filename);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800717 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800718}
719
720/* Add a new object file onto the bb chain. Invoked automatically
721 when running an object file's global ctors. */
722
723void
Lee Leahy38768c32017-03-09 14:07:18 -0800724__gcov_init(struct gcov_info *info)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800725{
Lee Leahye20a3192017-03-09 16:21:34 -0800726 if (!info->version || !info->n_functions)
727 return;
728 if (gcov_version(info, info->version, 0)) {
729 size_t filename_length = strlen(info->filename);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800730
Lee Leahye20a3192017-03-09 16:21:34 -0800731 /* Refresh the longest file name information */
732 if (filename_length > gcov_max_filename)
733 gcov_max_filename = filename_length;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800734
735#ifndef __COREBOOT__
Lee Leahye20a3192017-03-09 16:21:34 -0800736 if (!gcov_list)
737 atexit(gcov_exit);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800738#endif
739
Lee Leahye20a3192017-03-09 16:21:34 -0800740 info->next = gcov_list;
741 gcov_list = info;
742 }
743 info->version = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800744}
745
746/* Called before fork or exec - write out profile information gathered so
747 far and reset it to zero. This avoids duplication or loss of the
748 profile information gathered so far. */
749
750void
Lee Leahy38768c32017-03-09 14:07:18 -0800751__gcov_flush(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800752{
Lee Leahye20a3192017-03-09 16:21:34 -0800753 const struct gcov_info *gi_ptr;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800754
Lee Leahye20a3192017-03-09 16:21:34 -0800755 gcov_exit();
756 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) {
757 unsigned int f_ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800758
Lee Leahye20a3192017-03-09 16:21:34 -0800759 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) {
760 unsigned int t_ix;
761 const struct gcov_fn_info *gfi_ptr =
762 gi_ptr->functions[f_ix];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800763
Lee Leahye20a3192017-03-09 16:21:34 -0800764 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
765 continue;
766 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
767 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) {
768 if (!gi_ptr->merge[t_ix])
769 continue;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800770
Lee Leahye20a3192017-03-09 16:21:34 -0800771 memset(ci_ptr->values, 0,
772 sizeof(gcov_type) * ci_ptr->num);
773 ci_ptr++;
774 }
775 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800776 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800777}
778
779#endif /* L_gcov */
780
781#ifdef L_gcov_merge_add
782/* The profile merging function that just adds the counters. It is given
783 an array COUNTERS of N_COUNTERS old counters and it reads the same number
784 of counters from the gcov file. */
785void
Lee Leahy38768c32017-03-09 14:07:18 -0800786__gcov_merge_add(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800787{
Lee Leahye20a3192017-03-09 16:21:34 -0800788 for (; n_counters; counters++, n_counters--)
789 *counters += gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800790}
791#endif /* L_gcov_merge_add */
792
793#ifdef L_gcov_merge_ior
794/* The profile merging function that just adds the counters. It is given
795 an array COUNTERS of N_COUNTERS old counters and it reads the same number
796 of counters from the gcov file. */
797void
Lee Leahy38768c32017-03-09 14:07:18 -0800798__gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800799{
Lee Leahye20a3192017-03-09 16:21:34 -0800800 for (; n_counters; counters++, n_counters--)
801 *counters |= gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800802}
803#endif
804
805#ifdef L_gcov_merge_single
806/* The profile merging function for choosing the most common value.
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600807 * It is given an array COUNTERS of N_COUNTERS old counters and it
808 * reads the same number of counters from the gcov file. The counters
809 * are split into 3-tuples where the members of the tuple have
810 * meanings:
811 *
812 * -- the stored candidate on the most common value of the measured entity
813 * -- counter
Stefan Reinauerf572e1e2013-01-16 09:47:54 -0800814 * -- total number of evaluations of the value
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600815 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800816void
Lee Leahy38768c32017-03-09 14:07:18 -0800817__gcov_merge_single(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800818{
Lee Leahye20a3192017-03-09 16:21:34 -0800819 unsigned int i, n_measures;
820 gcov_type value, counter, all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800821
Lee Leahye20a3192017-03-09 16:21:34 -0800822 gcc_assert(!(n_counters % 3));
823 n_measures = n_counters / 3;
824 for (i = 0; i < n_measures; i++, counters += 3) {
825 value = gcov_read_counter();
826 counter = gcov_read_counter();
827 all = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800828
Lee Leahye20a3192017-03-09 16:21:34 -0800829 if (counters[0] == value)
830 counters[1] += counter;
831 else if (counter > counters[1]) {
832 counters[0] = value;
833 counters[1] = counter - counters[1];
834 } else
835 counters[1] -= counter;
836 counters[2] += all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800837 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800838}
839#endif /* L_gcov_merge_single */
840
841#ifdef L_gcov_merge_delta
842/* The profile merging function for choosing the most common
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600843 * difference between two consecutive evaluations of the value. It is
844 * given an array COUNTERS of N_COUNTERS old counters and it reads the
845 * same number of counters from the gcov file. The counters are split
846 * into 4-tuples where the members of the tuple have meanings:
847 *
848 * -- the last value of the measured entity
849 * -- the stored candidate on the most common difference
850 * -- counter
Stefan Reinauerf572e1e2013-01-16 09:47:54 -0800851 * -- total number of evaluations of the value
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600852 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800853void
Lee Leahy38768c32017-03-09 14:07:18 -0800854__gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800855{
Lee Leahye20a3192017-03-09 16:21:34 -0800856 unsigned int i, n_measures;
857 gcov_type value, counter, all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800858
Lee Leahye20a3192017-03-09 16:21:34 -0800859 gcc_assert(!(n_counters % 4));
860 n_measures = n_counters / 4;
861 for (i = 0; i < n_measures; i++, counters += 4) {
862 /* last = */
863 gcov_read_counter();
864 value = gcov_read_counter();
865 counter = gcov_read_counter();
866 all = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800867
Lee Leahye20a3192017-03-09 16:21:34 -0800868 if (counters[1] == value)
869 counters[2] += counter;
870 else if (counter > counters[2]) {
871 counters[1] = value;
872 counters[2] = counter - counters[2];
873 } else
874 counters[2] -= counter;
875 counters[3] += all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800876 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800877}
878#endif /* L_gcov_merge_delta */
879
880#ifdef L_gcov_interval_profiler
881/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
882 corresponding counter in COUNTERS. If the VALUE is above or below
883 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
884 instead. */
885
886void
Lee Leahy38768c32017-03-09 14:07:18 -0800887__gcov_interval_profiler(gcov_type *counters, gcov_type value,
Lee Leahy75b85992017-03-08 16:34:12 -0800888 int start, unsigned int steps)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800889{
Lee Leahye20a3192017-03-09 16:21:34 -0800890 gcov_type delta = value - start;
891 if (delta < 0)
892 counters[steps + 1]++;
893 else if (delta >= steps)
894 counters[steps]++;
895 else
896 counters[delta]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800897}
898#endif
899
900#ifdef L_gcov_pow2_profiler
901/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
902 COUNTERS[0] is incremented. */
903
904void
Lee Leahy38768c32017-03-09 14:07:18 -0800905__gcov_pow2_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800906{
Lee Leahye20a3192017-03-09 16:21:34 -0800907 if (value & (value - 1))
908 counters[0]++;
909 else
910 counters[1]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800911}
912#endif
913
914/* Tries to determine the most common value among its inputs. Checks if the
915 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
916 is incremented. If this is not the case and COUNTERS[1] is not zero,
917 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
918 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
919 function is called more than 50% of the time with one value, this value
920 will be in COUNTERS[0] in the end.
921
922 In any case, COUNTERS[2] is incremented. */
923
924static inline void
Lee Leahy38768c32017-03-09 14:07:18 -0800925__gcov_one_value_profiler_body(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800926{
Lee Leahye20a3192017-03-09 16:21:34 -0800927 if (value == counters[0])
928 counters[1]++;
929 else if (counters[1] == 0) {
930 counters[1] = 1;
931 counters[0] = value;
932 } else
933 counters[1]--;
934 counters[2]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800935}
936
937#ifdef L_gcov_one_value_profiler
938void
Lee Leahy38768c32017-03-09 14:07:18 -0800939__gcov_one_value_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800940{
Lee Leahye20a3192017-03-09 16:21:34 -0800941 __gcov_one_value_profiler_body(counters, value);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800942}
943#endif
944
945#ifdef L_gcov_indirect_call_profiler
946
947/* By default, the C++ compiler will use function addresses in the
948 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
949 tells the compiler to use function descriptors instead. The value
950 of this macro says how many words wide the descriptor is (normally 2),
951 but it may be dependent on target flags. Since we do not have access
952 to the target flags here we just check to see if it is set and use
953 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
954
955 It is assumed that the address of a function descriptor may be treated
956 as a pointer to a function. */
957
958#ifdef TARGET_VTABLE_USES_DESCRIPTORS
959#define VTABLE_USES_DESCRIPTORS 1
960#else
961#define VTABLE_USES_DESCRIPTORS 0
962#endif
963
964/* Tries to determine the most common value among its inputs. */
965void
Lee Leahy38768c32017-03-09 14:07:18 -0800966__gcov_indirect_call_profiler(gcov_type *counter, gcov_type value,
Lee Leahyb2d834a2017-03-08 16:52:22 -0800967 void *cur_func, void *callee_func)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800968{
Lee Leahye20a3192017-03-09 16:21:34 -0800969 /* If the C++ virtual tables contain function descriptors then one
970 * function may have multiple descriptors and we need to dereference
971 * the descriptors to see if they point to the same function.
972 */
973 if (cur_func == callee_func
974 || (VTABLE_USES_DESCRIPTORS && callee_func
975 && *(void **) cur_func == *(void **) callee_func))
976 __gcov_one_value_profiler_body(counter, value);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800977}
978#endif
979
980
981#ifdef L_gcov_average_profiler
982/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
983 to saturate up. */
984
985void
Lee Leahy38768c32017-03-09 14:07:18 -0800986__gcov_average_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800987{
Lee Leahye20a3192017-03-09 16:21:34 -0800988 counters[0] += value;
Lee Leahy35af5c42017-03-09 17:35:28 -0800989 counters[1]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800990}
991#endif
992
993#ifdef L_gcov_ior_profiler
994/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
995 to saturate up. */
996
997void
Lee Leahy38768c32017-03-09 14:07:18 -0800998__gcov_ior_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800999{
Lee Leahye20a3192017-03-09 16:21:34 -08001000 *counters |= value;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001001}
1002#endif
1003
1004#ifdef L_gcov_fork
1005/* A wrapper for the fork function. Flushes the accumulated profiling data, so
1006 that they are not counted twice. */
1007
1008pid_t
Lee Leahy38768c32017-03-09 14:07:18 -08001009__gcov_fork(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001010{
Lee Leahye20a3192017-03-09 16:21:34 -08001011 __gcov_flush();
1012 return fork();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001013}
1014#endif
1015
1016#ifdef L_gcov_execl
1017/* A wrapper for the execl function. Flushes the accumulated profiling data, so
1018 that they are not lost. */
1019
1020int
Lee Leahy38768c32017-03-09 14:07:18 -08001021__gcov_execl(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001022{
Lee Leahye20a3192017-03-09 16:21:34 -08001023 va_list ap, aq;
1024 unsigned int i, length;
1025 char **args;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001026
Lee Leahye20a3192017-03-09 16:21:34 -08001027 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001028
Lee Leahye20a3192017-03-09 16:21:34 -08001029 va_start(ap, arg);
1030 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001031
Lee Leahye20a3192017-03-09 16:21:34 -08001032 length = 2;
1033 while (va_arg(ap, char *))
1034 length++;
1035 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001036
Lee Leahye20a3192017-03-09 16:21:34 -08001037 args = (char **) alloca(length * sizeof(void *));
1038 args[0] = arg;
1039 for (i = 1; i < length; i++)
1040 args[i] = va_arg(aq, char *);
1041 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001042
Lee Leahye20a3192017-03-09 16:21:34 -08001043 return execv(path, args);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001044}
1045#endif
1046
1047#ifdef L_gcov_execlp
1048/* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1049 that they are not lost. */
1050
1051int
Lee Leahy38768c32017-03-09 14:07:18 -08001052__gcov_execlp(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001053{
Lee Leahye20a3192017-03-09 16:21:34 -08001054 va_list ap, aq;
1055 unsigned int i, length;
1056 char **args;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001057
Lee Leahye20a3192017-03-09 16:21:34 -08001058 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001059
Lee Leahye20a3192017-03-09 16:21:34 -08001060 va_start(ap, arg);
1061 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001062
Lee Leahye20a3192017-03-09 16:21:34 -08001063 length = 2;
1064 while (va_arg(ap, char *))
1065 length++;
1066 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001067
Lee Leahye20a3192017-03-09 16:21:34 -08001068 args = (char **) alloca(length * sizeof(void *));
1069 args[0] = arg;
1070 for (i = 1; i < length; i++)
1071 args[i] = va_arg(aq, char *);
1072 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001073
Lee Leahye20a3192017-03-09 16:21:34 -08001074 return execvp(path, args);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001075}
1076#endif
1077
1078#ifdef L_gcov_execle
1079/* A wrapper for the execle function. Flushes the accumulated profiling data, so
1080 that they are not lost. */
1081
1082int
Lee Leahy38768c32017-03-09 14:07:18 -08001083__gcov_execle(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001084{
Lee Leahye20a3192017-03-09 16:21:34 -08001085 va_list ap, aq;
1086 unsigned int i, length;
1087 char **args;
1088 char **envp;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001089
Lee Leahye20a3192017-03-09 16:21:34 -08001090 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001091
Lee Leahye20a3192017-03-09 16:21:34 -08001092 va_start(ap, arg);
1093 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001094
Lee Leahye20a3192017-03-09 16:21:34 -08001095 length = 2;
1096 while (va_arg(ap, char *))
1097 length++;
1098 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001099
Lee Leahye20a3192017-03-09 16:21:34 -08001100 args = (char **) alloca(length * sizeof(void *));
1101 args[0] = arg;
1102 for (i = 1; i < length; i++)
1103 args[i] = va_arg(aq, char *);
1104 envp = va_arg(aq, char **);
1105 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001106
Lee Leahye20a3192017-03-09 16:21:34 -08001107 return execve(path, args, envp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001108}
1109#endif
1110
1111#ifdef L_gcov_execv
1112/* A wrapper for the execv function. Flushes the accumulated profiling data, so
1113 that they are not lost. */
1114
1115int
Lee Leahy38768c32017-03-09 14:07:18 -08001116__gcov_execv(const char *path, char *const argv[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001117{
Lee Leahye20a3192017-03-09 16:21:34 -08001118 __gcov_flush();
1119 return execv(path, argv);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001120}
1121#endif
1122
1123#ifdef L_gcov_execvp
1124/* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1125 that they are not lost. */
1126
1127int
Lee Leahy38768c32017-03-09 14:07:18 -08001128__gcov_execvp(const char *path, char *const argv[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001129{
Lee Leahye20a3192017-03-09 16:21:34 -08001130 __gcov_flush();
1131 return execvp(path, argv);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001132}
1133#endif
1134
1135#ifdef L_gcov_execve
1136/* A wrapper for the execve function. Flushes the accumulated profiling data, so
1137 that they are not lost. */
1138
1139int
Lee Leahy38768c32017-03-09 14:07:18 -08001140__gcov_execve(const char *path, char *const argv[], char *const envp[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001141{
Lee Leahye20a3192017-03-09 16:21:34 -08001142 __gcov_flush();
1143 return execve(path, argv, envp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001144}
1145#endif
1146#endif /* inhibit_libc */