blob: 887351aa5750d6c9d8783da1f2e1a52e80f78c74 [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
Stefan Reinauer6a001132017-07-13 02:20:27 +020076void __gcov_init(struct gcov_info *p __attribute__((unused))) {}
Lee Leahy38768c32017-03-09 14:07:18 -080077void __gcov_flush(void) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080078#endif
79
80#ifdef L_gcov_merge_add
Stefan Reinauer6a001132017-07-13 02:20:27 +020081void __gcov_merge_add(gcov_type *counters __attribute__((unused)),
82 unsigned int n_counters __attribute__((unused))) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080083#endif
84
85#ifdef L_gcov_merge_single
Stefan Reinauer6a001132017-07-13 02:20:27 +020086void __gcov_merge_single(gcov_type *counters __attribute__((unused)),
87 unsigned int n_counters __attribute__((unused))) {}
Stefan Reinauerd37ab452012-12-18 16:23:28 -080088#endif
89
90#ifdef L_gcov_merge_delta
Stefan Reinauer6a001132017-07-13 02:20:27 +020091void __gcov_merge_delta(gcov_type *counters __attribute__((unused)),
92 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
Stefan Reinauer6a001132017-07-13 02:20:27 +0200105void __gcov_merge_add(gcov_type *counters __attribute__((unused)),
106 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
Lee Leahy342f8d62017-03-10 15:31:56 -0800112struct gcov_fn_buffer {
Lee Leahye20a3192017-03-09 16:21:34 -0800113 struct gcov_fn_buffer *next;
114 unsigned int fn_ix;
115 struct gcov_fn_info info;
116 /* note gcov_fn_info ends in a trailing array. */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800117};
118
119/* Chain of per-object gcov structures. */
120static struct gcov_info *gcov_list;
121
122/* Size of the longest file name. */
123static size_t gcov_max_filename = 0;
124
125/* Make sure path component of the given FILENAME exists, create
126 missing directories. FILENAME must be writable.
127 Returns zero on success, or -1 if an error occurred. */
128
129static int
Lee Leahy38768c32017-03-09 14:07:18 -0800130create_file_directory(char *filename)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800131{
132#ifdef __COREBOOT__
Lee Leahye20a3192017-03-09 16:21:34 -0800133 (void) filename;
134 return 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800135#else
136#if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
Lee Leahye20a3192017-03-09 16:21:34 -0800137 (void) filename;
138 return -1;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800139#else
Lee Leahye20a3192017-03-09 16:21:34 -0800140 char *s;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800141
Lee Leahye20a3192017-03-09 16:21:34 -0800142 s = filename;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800143
Lee Leahye20a3192017-03-09 16:21:34 -0800144 if (HAS_DRIVE_SPEC(s))
145 s += 2;
146 if (IS_DIR_SEPARATOR(*s))
147 ++s;
148 for (; *s != '\0'; s++)
149 if (IS_DIR_SEPARATOR(*s)) {
150 char sep = *s;
151 *s = '\0';
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800152
Lee Leahye20a3192017-03-09 16:21:34 -0800153 /* Try to make directory if it doesn't already exist. */
154 if (access(filename, F_OK) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800155#ifdef TARGET_POSIX_IO
Lee Leahye20a3192017-03-09 16:21:34 -0800156 && mkdir(filename, 0755) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800157#else
Lee Leahye20a3192017-03-09 16:21:34 -0800158 && mkdir(filename) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800159#endif
Lee Leahye20a3192017-03-09 16:21:34 -0800160 /* The directory might have been made by another
161 * process.
162 */
163 && errno != EEXIST) {
164 fprintf(stderr,
165 "profiling:%s:Cannot create directory\n",
166 filename);
167 *s = sep;
168 return -1;
169 };
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800170
Lee Leahye20a3192017-03-09 16:21:34 -0800171 *s = sep;
172 };
173 return 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800174#endif
175#endif
176}
177
178static struct gcov_fn_buffer *
Lee Leahy38768c32017-03-09 14:07:18 -0800179free_fn_data(const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
Lee Leahy75b85992017-03-08 16:34:12 -0800180 unsigned int limit)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800181{
Lee Leahye20a3192017-03-09 16:21:34 -0800182 struct gcov_fn_buffer *next;
183 unsigned int ix, n_ctr = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800184
Lee Leahye20a3192017-03-09 16:21:34 -0800185 if (!buffer)
186 return 0;
187 next = buffer->next;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800188
Lee Leahye20a3192017-03-09 16:21:34 -0800189 for (ix = 0; ix != limit; ix++)
190 if (gi_ptr->merge[ix])
191 free(buffer->info.ctrs[n_ctr++].values);
192 free(buffer);
193 return next;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800194}
195
196static struct gcov_fn_buffer **
Lee Leahy38768c32017-03-09 14:07:18 -0800197buffer_fn_data(const char *filename, const struct gcov_info *gi_ptr,
Lee Leahy75b85992017-03-08 16:34:12 -0800198 struct gcov_fn_buffer **end_ptr, unsigned int fn_ix)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800199{
Lee Leahye20a3192017-03-09 16:21:34 -0800200 unsigned int n_ctrs = 0, ix = 0;
201 struct gcov_fn_buffer *fn_buffer;
202 unsigned int len;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800203
Lee Leahye20a3192017-03-09 16:21:34 -0800204 for (ix = GCOV_COUNTERS; ix--;)
205 if (gi_ptr->merge[ix])
206 n_ctrs++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800207
Lee Leahye20a3192017-03-09 16:21:34 -0800208 len = sizeof(*fn_buffer) + sizeof(fn_buffer->info.ctrs[0]) * n_ctrs;
209 fn_buffer = (struct gcov_fn_buffer *)malloc(len);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800210
Lee Leahye20a3192017-03-09 16:21:34 -0800211 if (!fn_buffer)
212 goto fail;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800213
Lee Leahye20a3192017-03-09 16:21:34 -0800214 fn_buffer->next = 0;
215 fn_buffer->fn_ix = fn_ix;
216 fn_buffer->info.ident = gcov_read_unsigned();
217 fn_buffer->info.lineno_checksum = gcov_read_unsigned();
218 fn_buffer->info.cfg_checksum = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800219
Lee Leahye20a3192017-03-09 16:21:34 -0800220 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) {
221 gcov_unsigned_t length;
222 gcov_type *values;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800223
Lee Leahye20a3192017-03-09 16:21:34 -0800224 if (!gi_ptr->merge[ix])
225 continue;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800226
Lee Leahye20a3192017-03-09 16:21:34 -0800227 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix)) {
228 len = 0;
229 goto fail;
230 }
231
232 length = GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
233 len = length * sizeof(gcov_type);
234 values = (gcov_type *)malloc(len);
235 if (!values)
236 goto fail;
237
238 fn_buffer->info.ctrs[n_ctrs].num = length;
239 fn_buffer->info.ctrs[n_ctrs].values = values;
240
241 while (length--)
242 *values++ = gcov_read_counter();
243 n_ctrs++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800244 }
245
Lee Leahye20a3192017-03-09 16:21:34 -0800246 *end_ptr = fn_buffer;
247 return &fn_buffer->next;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800248
249fail:
Lee Leahy35af5c42017-03-09 17:35:28 -0800250 fprintf(stderr, "profiling:%s:Function %u %s %u\n", filename, fn_ix,
Lee Leahye20a3192017-03-09 16:21:34 -0800251 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800252
Lee Leahye20a3192017-03-09 16:21:34 -0800253 return (struct gcov_fn_buffer **)free_fn_data(gi_ptr, fn_buffer, ix);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800254}
255
256/* Add an unsigned value to the current crc */
257
258static gcov_unsigned_t
Lee Leahy38768c32017-03-09 14:07:18 -0800259crc32_unsigned(gcov_unsigned_t crc32, gcov_unsigned_t value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800260{
Lee Leahye20a3192017-03-09 16:21:34 -0800261 unsigned int ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800262
Lee Leahye20a3192017-03-09 16:21:34 -0800263 for (ix = 32; ix--; value <<= 1) {
264 unsigned int feedback;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800265
Lee Leahye20a3192017-03-09 16:21:34 -0800266 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
267 crc32 <<= 1;
268 crc32 ^= feedback;
269 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800270
Lee Leahye20a3192017-03-09 16:21:34 -0800271 return crc32;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800272}
273
274/* Check if VERSION of the info block PTR matches libgcov one.
275 Return 1 on success, or zero in case of versions mismatch.
276 If FILENAME is not NULL, its value used for reporting purposes
277 instead of value from the info block. */
278
279static int
Lee Leahy38768c32017-03-09 14:07:18 -0800280gcov_version(struct gcov_info *ptr, gcov_unsigned_t version,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800281 const char *filename)
282{
Lee Leahye20a3192017-03-09 16:21:34 -0800283 if (version != GCOV_VERSION) {
284 char v[4], e[4];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800285
Lee Leahye20a3192017-03-09 16:21:34 -0800286 GCOV_UNSIGNED2STRING(v, version);
287 GCOV_UNSIGNED2STRING(e, GCOV_VERSION);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800288
Lee Leahye20a3192017-03-09 16:21:34 -0800289 fprintf(stderr,
290 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
Lee Leahy35af5c42017-03-09 17:35:28 -0800291 filename ? filename : ptr->filename, e, v);
Lee Leahye20a3192017-03-09 16:21:34 -0800292 return 0;
293 }
294 return 1;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800295}
296
297/* Dump the coverage counts. We merge with existing counts when
298 possible, to avoid growing the .da files ad infinitum. We use this
299 program's checksum to make sure we only accumulate whole program
300 statistics to the correct summary. An object file might be embedded
301 in two separate programs, and we must keep the two program
302 summaries separate. */
303
304static void
Lee Leahy38768c32017-03-09 14:07:18 -0800305gcov_exit(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800306{
Lee Leahye20a3192017-03-09 16:21:34 -0800307 struct gcov_info *gi_ptr;
308 const struct gcov_fn_info *gfi_ptr;
309 struct gcov_summary this_prg; /* summary for program. */
310 struct gcov_summary all_prg; /* summary for all instances of program. */
311 struct gcov_ctr_summary *cs_ptr;
312 const struct gcov_ctr_info *ci_ptr;
313 unsigned int t_ix;
314 int f_ix = 0;
315 gcov_unsigned_t c_num;
316 const char *gcov_prefix;
317 int gcov_prefix_strip = 0;
318 size_t prefix_length;
319 char *gi_filename, *gi_filename_up;
320 gcov_unsigned_t crc32 = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800321
Lee Leahye20a3192017-03-09 16:21:34 -0800322 memset(&all_prg, 0, sizeof(all_prg));
323 /* Find the totals for this execution. */
324 memset(&this_prg, 0, sizeof(this_prg));
325 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) {
326 crc32 = crc32_unsigned(crc32, gi_ptr->stamp);
327 crc32 = crc32_unsigned(crc32, gi_ptr->n_functions);
Kyösti Mälkkiecd84242013-09-13 07:57:49 +0300328
Lee Leahye20a3192017-03-09 16:21:34 -0800329 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
330 f_ix++) {
331 gfi_ptr = gi_ptr->functions[f_ix];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800332
Lee Leahye20a3192017-03-09 16:21:34 -0800333 if (gfi_ptr && gfi_ptr->key != gi_ptr)
334 gfi_ptr = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800335
Lee Leahye20a3192017-03-09 16:21:34 -0800336 crc32 = crc32_unsigned(crc32, gfi_ptr
337 ? gfi_ptr->cfg_checksum : 0);
338 crc32 = crc32_unsigned(crc32,
339 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
340 if (!gfi_ptr)
341 continue;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800342
Lee Leahye20a3192017-03-09 16:21:34 -0800343 ci_ptr = gfi_ptr->ctrs;
344 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) {
345 if (!gi_ptr->merge[t_ix])
346 continue;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800347
Lee Leahye20a3192017-03-09 16:21:34 -0800348 cs_ptr = &this_prg.ctrs[t_ix];
349 cs_ptr->num += ci_ptr->num;
350 crc32 = crc32_unsigned(crc32, ci_ptr->num);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800351
Lee Leahye20a3192017-03-09 16:21:34 -0800352 for (c_num = 0; c_num < ci_ptr->num; c_num++) {
353 cs_ptr->sum_all +=
354 ci_ptr->values[c_num];
355 if (cs_ptr->run_max
356 < ci_ptr->values[c_num])
357 cs_ptr->run_max =
358 ci_ptr->values[c_num];
359 }
360 ci_ptr++;
361 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800362 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800363 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800364
365#ifndef __COREBOOT__
Lee Leahye20a3192017-03-09 16:21:34 -0800366 {
367 /* Check if the level of dirs to strip off specified. */
368 char *tmp = getenv("GCOV_PREFIX_STRIP");
369 if (tmp) {
370 gcov_prefix_strip = atoi(tmp);
371 /* Do not consider negative values. */
372 if (gcov_prefix_strip < 0)
373 gcov_prefix_strip = 0;
374 }
375 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800376
Lee Leahye20a3192017-03-09 16:21:34 -0800377 /* Get file name relocation prefix. Non-absolute values are ignored. */
378 gcov_prefix = getenv("GCOV_PREFIX");
379 if (gcov_prefix) {
380 prefix_length = strlen(gcov_prefix);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800381
Lee Leahye20a3192017-03-09 16:21:34 -0800382 /* Remove an unnecessary trailing '/' */
383 if (IS_DIR_SEPARATOR(gcov_prefix[prefix_length - 1]))
384 prefix_length--;
385 } else
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800386#endif
Lee Leahye20a3192017-03-09 16:21:34 -0800387 prefix_length = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800388
Lee Leahye20a3192017-03-09 16:21:34 -0800389 /* If no prefix was specified and a prefix strip, then we assume
390 relative. */
391 if (gcov_prefix_strip != 0 && prefix_length == 0) {
392 gcov_prefix = ".";
393 prefix_length = 1;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800394 }
Lee Leahye20a3192017-03-09 16:21:34 -0800395 /* Allocate and initialize the filename scratch space plus one. */
396 gi_filename = (char *) alloca(prefix_length + gcov_max_filename + 2);
397 if (prefix_length)
398 memcpy(gi_filename, gcov_prefix, prefix_length);
399 gi_filename_up = gi_filename + prefix_length;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800400
Lee Leahye20a3192017-03-09 16:21:34 -0800401 /* Now merge each file. */
402 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) {
403 unsigned int n_counts;
404 struct gcov_summary prg; /* summary for this object over all
405 program. */
406 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
407 int error = 0;
408 gcov_unsigned_t tag, length;
409 gcov_position_t summary_pos = 0;
410 gcov_position_t eof_pos = 0;
411 const char *fname, *s;
Elyes HAOUAS1d3fde42018-06-05 08:41:29 +0200412 struct gcov_fn_buffer *fn_buffer = NULL;
Lee Leahye20a3192017-03-09 16:21:34 -0800413 struct gcov_fn_buffer **fn_tail = &fn_buffer;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800414
Lee Leahye20a3192017-03-09 16:21:34 -0800415 fname = gi_ptr->filename;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800416
Lee Leahye20a3192017-03-09 16:21:34 -0800417 /* Avoid to add multiple drive letters into combined path. */
418 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
419 fname += 2;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800420
Lee Leahye20a3192017-03-09 16:21:34 -0800421 /* Build relocated filename, stripping off leading
422 * directories from the initial filename if requested.
423 */
424 if (gcov_prefix_strip > 0) {
425 int level = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800426
Lee Leahye20a3192017-03-09 16:21:34 -0800427 s = fname;
428 if (IS_DIR_SEPARATOR(*s))
429 ++s;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800430
Lee Leahye20a3192017-03-09 16:21:34 -0800431 /* Skip selected directory levels. */
432 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
433 if (IS_DIR_SEPARATOR(*s)) {
434 fname = s;
435 level++;
436 }
437 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800438
Lee Leahye20a3192017-03-09 16:21:34 -0800439 /* Update complete filename with stripped original. */
440 if (prefix_length != 0 && !IS_DIR_SEPARATOR(*fname)) {
441 /* If prefix is given, add directory separator.
442 */
443 strcpy(gi_filename_up, "/");
444 strcpy(gi_filename_up + 1, fname);
445 } else
446 strcpy(gi_filename_up, fname);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800447
Lee Leahye20a3192017-03-09 16:21:34 -0800448 if (!gcov_open(gi_filename)) {
449 /* Open failed likely due to missed directory.
450 * Create directory and retry to open file.
451 */
452 if (create_file_directory(gi_filename)) {
453 fprintf(stderr, "profiling:%s:Skip\n",
454 gi_filename);
455 continue;
456 }
457 if (!gcov_open(gi_filename)) {
458 fprintf(stderr,
459 "profiling:%s:Cannot open\n",
460 gi_filename);
461 continue;
462 }
463 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800464
Lee Leahye20a3192017-03-09 16:21:34 -0800465 tag = gcov_read_unsigned();
466 if (tag) {
467 /* Merge data from file. */
468 if (tag != GCOV_DATA_MAGIC) {
469 fprintf(stderr,
470 "profiling:%s:Not a gcov data file\n",
471 gi_filename);
472 goto read_fatal;
473 }
474 length = gcov_read_unsigned();
475 if (!gcov_version(gi_ptr, length, gi_filename))
476 goto read_fatal;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800477
Lee Leahye20a3192017-03-09 16:21:34 -0800478 length = gcov_read_unsigned();
479 if (length != gi_ptr->stamp)
480 /* Read from a different compilation.
481 * Overwrite the file.
482 */
483 goto rewrite;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800484
Lee Leahye20a3192017-03-09 16:21:34 -0800485 /* Look for program summary. */
486 for (f_ix = 0;;) {
487 struct gcov_summary tmp;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800488
Lee Leahye20a3192017-03-09 16:21:34 -0800489 eof_pos = gcov_position();
490 tag = gcov_read_unsigned();
491 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
492 break;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800493
Lee Leahye20a3192017-03-09 16:21:34 -0800494 f_ix--;
495 length = gcov_read_unsigned();
496 if (length != GCOV_TAG_SUMMARY_LENGTH)
497 goto read_mismatch;
498 gcov_read_summary(&tmp);
Lee Leahy491c5b62017-03-10 15:51:04 -0800499 error = gcov_is_error();
500 if (error)
Lee Leahye20a3192017-03-09 16:21:34 -0800501 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 }
Lee Leahy491c5b62017-03-10 15:51:04 -0800588 error = gcov_is_error();
589 if (error)
Lee Leahye20a3192017-03-09 16:21:34 -0800590 goto read_error;
591 }
592
593 if (tag) {
594 read_mismatch:;
595 fprintf(stderr,
596 "profiling:%s:Merge mismatch for %s %u\n",
597 gi_filename, f_ix >= 0 ?
598 "function" : "summary",
599 f_ix < 0 ? -1 - f_ix : f_ix);
600 goto read_fatal;
601 }
602 }
603 goto rewrite;
604
605read_error:;
606 fprintf(stderr, "profiling:%s:%s merging\n", gi_filename,
Lee Leahy35af5c42017-03-09 17:35:28 -0800607 error < 0 ? "Overflow" : "Error");
Lee Leahye20a3192017-03-09 16:21:34 -0800608
609 goto read_fatal;
610
611rewrite:;
612 gcov_rewrite();
613 if (!summary_pos) {
614 memset(&prg, 0, sizeof(prg));
615 summary_pos = eof_pos;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800616 }
617
Lee Leahye20a3192017-03-09 16:21:34 -0800618 /* Merge the summaries. */
619 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) {
620 cs_prg = &prg.ctrs[t_ix];
621 cs_tprg = &this_prg.ctrs[t_ix];
622 cs_all = &all_prg.ctrs[t_ix];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800623
Lee Leahye20a3192017-03-09 16:21:34 -0800624 if (gi_ptr->merge[t_ix]) {
625 if (!cs_prg->runs++)
626 cs_prg->num = cs_tprg->num;
627 cs_prg->sum_all += cs_tprg->sum_all;
628 if (cs_prg->run_max < cs_tprg->run_max)
629 cs_prg->run_max = cs_tprg->run_max;
630 cs_prg->sum_max += cs_tprg->run_max;
631 } else if (cs_prg->runs)
632 goto read_mismatch;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800633
Lee Leahye20a3192017-03-09 16:21:34 -0800634 if (!cs_all->runs && cs_prg->runs)
635 memcpy(cs_all, cs_prg, sizeof(*cs_all));
636 else if (!all_prg.checksum
Lee Leahy73402172017-03-10 15:23:24 -0800637 && (!GCOV_LOCKED
638 || cs_all->runs == cs_prg->runs)
Lee Leahye20a3192017-03-09 16:21:34 -0800639 && memcmp(cs_all, cs_prg, sizeof(*cs_all))) {
640 fprintf(stderr,
641 "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
642 gi_filename, GCOV_LOCKED ? "" :
643 " or concurrently updated without locking support");
644 all_prg.checksum = ~0u;
645 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800646 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800647
Lee Leahye20a3192017-03-09 16:21:34 -0800648 prg.checksum = crc32;
649
650 /* Write out the data. */
651 if (!eof_pos) {
652 gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
653 gcov_write_unsigned(gi_ptr->stamp);
654 }
655
656 if (summary_pos)
657 gcov_seek(summary_pos);
658
659 /* Generate whole program statistics. */
660 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY, &prg);
661
662 if (summary_pos < eof_pos)
663 gcov_seek(eof_pos);
664
665 /* Write execution counts for each function. */
Lee Leahy73402172017-03-10 15:23:24 -0800666 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
667 f_ix++) {
Lee Leahye20a3192017-03-09 16:21:34 -0800668 unsigned int buffered = 0;
669
Lee Leahy73402172017-03-10 15:23:24 -0800670 if (fn_buffer && fn_buffer->fn_ix
671 == (unsigned int)f_ix) {
Lee Leahye20a3192017-03-09 16:21:34 -0800672 /* Buffered data from another program. */
673 buffered = 1;
674 gfi_ptr = &fn_buffer->info;
675 length = GCOV_TAG_FUNCTION_LENGTH;
676 } else {
677 gfi_ptr = gi_ptr->functions[f_ix];
678 if (gfi_ptr && gfi_ptr->key == gi_ptr)
679 length = GCOV_TAG_FUNCTION_LENGTH;
680 else
681 length = 0;
682 }
683
684 gcov_write_tag_length(GCOV_TAG_FUNCTION, length);
685 if (!length)
686 continue;
687
688 gcov_write_unsigned(gfi_ptr->ident);
689 gcov_write_unsigned(gfi_ptr->lineno_checksum);
690 gcov_write_unsigned(gfi_ptr->cfg_checksum);
691
692 ci_ptr = gfi_ptr->ctrs;
693 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) {
694 if (!gi_ptr->merge[t_ix])
695 continue;
696
697 n_counts = ci_ptr->num;
Lee Leahy73402172017-03-10 15:23:24 -0800698 gcov_write_tag_length(
699 GCOV_TAG_FOR_COUNTER(t_ix),
Lee Leahye20a3192017-03-09 16:21:34 -0800700 GCOV_TAG_COUNTER_LENGTH(n_counts));
701 gcov_type *c_ptr = ci_ptr->values;
702 while (n_counts--)
703 gcov_write_counter(*c_ptr++);
704 ci_ptr++;
705 }
706 if (buffered)
707 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
708 GCOV_COUNTERS);
709 }
710
711 gcov_write_unsigned(0);
712
713read_fatal:;
714 while (fn_buffer)
Lee Leahy73402172017-03-10 15:23:24 -0800715 fn_buffer = free_fn_data(gi_ptr, fn_buffer,
716 GCOV_COUNTERS);
Lee Leahye20a3192017-03-09 16:21:34 -0800717
Lee Leahy491c5b62017-03-10 15:51:04 -0800718 error = gcov_close();
719 if (error)
Lee Leahye20a3192017-03-09 16:21:34 -0800720 fprintf(stderr, error < 0 ?
721 "profiling:%s:Overflow writing\n" :
722 "profiling:%s:Error writing\n",
723 gi_filename);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800724 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800725}
726
727/* Add a new object file onto the bb chain. Invoked automatically
728 when running an object file's global ctors. */
729
730void
Lee Leahy38768c32017-03-09 14:07:18 -0800731__gcov_init(struct gcov_info *info)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800732{
Lee Leahye20a3192017-03-09 16:21:34 -0800733 if (!info->version || !info->n_functions)
734 return;
735 if (gcov_version(info, info->version, 0)) {
736 size_t filename_length = strlen(info->filename);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800737
Lee Leahye20a3192017-03-09 16:21:34 -0800738 /* Refresh the longest file name information */
739 if (filename_length > gcov_max_filename)
740 gcov_max_filename = filename_length;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800741
742#ifndef __COREBOOT__
Lee Leahye20a3192017-03-09 16:21:34 -0800743 if (!gcov_list)
744 atexit(gcov_exit);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800745#endif
746
Lee Leahye20a3192017-03-09 16:21:34 -0800747 info->next = gcov_list;
748 gcov_list = info;
749 }
750 info->version = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800751}
752
753/* Called before fork or exec - write out profile information gathered so
754 far and reset it to zero. This avoids duplication or loss of the
755 profile information gathered so far. */
756
757void
Lee Leahy38768c32017-03-09 14:07:18 -0800758__gcov_flush(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800759{
Lee Leahye20a3192017-03-09 16:21:34 -0800760 const struct gcov_info *gi_ptr;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800761
Lee Leahye20a3192017-03-09 16:21:34 -0800762 gcov_exit();
763 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) {
764 unsigned int f_ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800765
Lee Leahye20a3192017-03-09 16:21:34 -0800766 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) {
767 unsigned int t_ix;
768 const struct gcov_fn_info *gfi_ptr =
769 gi_ptr->functions[f_ix];
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800770
Lee Leahye20a3192017-03-09 16:21:34 -0800771 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
772 continue;
773 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
774 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) {
775 if (!gi_ptr->merge[t_ix])
776 continue;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800777
Lee Leahye20a3192017-03-09 16:21:34 -0800778 memset(ci_ptr->values, 0,
779 sizeof(gcov_type) * ci_ptr->num);
780 ci_ptr++;
781 }
782 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800783 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800784}
785
786#endif /* L_gcov */
787
788#ifdef L_gcov_merge_add
789/* The profile merging function that just adds the counters. It is given
790 an array COUNTERS of N_COUNTERS old counters and it reads the same number
791 of counters from the gcov file. */
792void
Lee Leahy38768c32017-03-09 14:07:18 -0800793__gcov_merge_add(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800794{
Lee Leahye20a3192017-03-09 16:21:34 -0800795 for (; n_counters; counters++, n_counters--)
796 *counters += gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800797}
798#endif /* L_gcov_merge_add */
799
800#ifdef L_gcov_merge_ior
801/* The profile merging function that just adds the counters. It is given
802 an array COUNTERS of N_COUNTERS old counters and it reads the same number
803 of counters from the gcov file. */
804void
Lee Leahy38768c32017-03-09 14:07:18 -0800805__gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800806{
Lee Leahye20a3192017-03-09 16:21:34 -0800807 for (; n_counters; counters++, n_counters--)
808 *counters |= gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800809}
810#endif
811
812#ifdef L_gcov_merge_single
813/* The profile merging function for choosing the most common value.
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600814 * It is given an array COUNTERS of N_COUNTERS old counters and it
815 * reads the same number of counters from the gcov file. The counters
816 * are split into 3-tuples where the members of the tuple have
817 * meanings:
818 *
819 * -- the stored candidate on the most common value of the measured entity
820 * -- counter
Stefan Reinauerf572e1e2013-01-16 09:47:54 -0800821 * -- total number of evaluations of the value
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600822 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800823void
Lee Leahy38768c32017-03-09 14:07:18 -0800824__gcov_merge_single(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800825{
Lee Leahye20a3192017-03-09 16:21:34 -0800826 unsigned int i, n_measures;
827 gcov_type value, counter, all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800828
Lee Leahye20a3192017-03-09 16:21:34 -0800829 gcc_assert(!(n_counters % 3));
830 n_measures = n_counters / 3;
831 for (i = 0; i < n_measures; i++, counters += 3) {
832 value = gcov_read_counter();
833 counter = gcov_read_counter();
834 all = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800835
Lee Leahye20a3192017-03-09 16:21:34 -0800836 if (counters[0] == value)
837 counters[1] += counter;
838 else if (counter > counters[1]) {
839 counters[0] = value;
840 counters[1] = counter - counters[1];
841 } else
842 counters[1] -= counter;
843 counters[2] += all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800844 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800845}
846#endif /* L_gcov_merge_single */
847
848#ifdef L_gcov_merge_delta
849/* The profile merging function for choosing the most common
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600850 * difference between two consecutive evaluations of the value. It is
851 * given an array COUNTERS of N_COUNTERS old counters and it reads the
852 * same number of counters from the gcov file. The counters are split
853 * into 4-tuples where the members of the tuple have meanings:
854 *
855 * -- the last value of the measured entity
856 * -- the stored candidate on the most common difference
857 * -- counter
Stefan Reinauerf572e1e2013-01-16 09:47:54 -0800858 * -- total number of evaluations of the value
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600859 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800860void
Lee Leahy38768c32017-03-09 14:07:18 -0800861__gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800862{
Lee Leahye20a3192017-03-09 16:21:34 -0800863 unsigned int i, n_measures;
864 gcov_type value, counter, all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800865
Lee Leahye20a3192017-03-09 16:21:34 -0800866 gcc_assert(!(n_counters % 4));
867 n_measures = n_counters / 4;
868 for (i = 0; i < n_measures; i++, counters += 4) {
869 /* last = */
870 gcov_read_counter();
871 value = gcov_read_counter();
872 counter = gcov_read_counter();
873 all = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800874
Lee Leahye20a3192017-03-09 16:21:34 -0800875 if (counters[1] == value)
876 counters[2] += counter;
877 else if (counter > counters[2]) {
878 counters[1] = value;
879 counters[2] = counter - counters[2];
880 } else
881 counters[2] -= counter;
882 counters[3] += all;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800883 }
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800884}
885#endif /* L_gcov_merge_delta */
886
887#ifdef L_gcov_interval_profiler
888/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
889 corresponding counter in COUNTERS. If the VALUE is above or below
890 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
891 instead. */
892
893void
Lee Leahy38768c32017-03-09 14:07:18 -0800894__gcov_interval_profiler(gcov_type *counters, gcov_type value,
Lee Leahy75b85992017-03-08 16:34:12 -0800895 int start, unsigned int steps)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800896{
Lee Leahye20a3192017-03-09 16:21:34 -0800897 gcov_type delta = value - start;
898 if (delta < 0)
899 counters[steps + 1]++;
900 else if (delta >= steps)
901 counters[steps]++;
902 else
903 counters[delta]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800904}
905#endif
906
907#ifdef L_gcov_pow2_profiler
908/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
909 COUNTERS[0] is incremented. */
910
911void
Lee Leahy38768c32017-03-09 14:07:18 -0800912__gcov_pow2_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800913{
Lee Leahye20a3192017-03-09 16:21:34 -0800914 if (value & (value - 1))
915 counters[0]++;
916 else
917 counters[1]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800918}
919#endif
920
921/* Tries to determine the most common value among its inputs. Checks if the
922 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
923 is incremented. If this is not the case and COUNTERS[1] is not zero,
924 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
925 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
926 function is called more than 50% of the time with one value, this value
927 will be in COUNTERS[0] in the end.
928
929 In any case, COUNTERS[2] is incremented. */
930
931static inline void
Lee Leahy38768c32017-03-09 14:07:18 -0800932__gcov_one_value_profiler_body(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800933{
Lee Leahye20a3192017-03-09 16:21:34 -0800934 if (value == counters[0])
935 counters[1]++;
936 else if (counters[1] == 0) {
937 counters[1] = 1;
938 counters[0] = value;
939 } else
940 counters[1]--;
941 counters[2]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800942}
943
944#ifdef L_gcov_one_value_profiler
945void
Lee Leahy38768c32017-03-09 14:07:18 -0800946__gcov_one_value_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800947{
Lee Leahye20a3192017-03-09 16:21:34 -0800948 __gcov_one_value_profiler_body(counters, value);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800949}
950#endif
951
952#ifdef L_gcov_indirect_call_profiler
953
954/* By default, the C++ compiler will use function addresses in the
955 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
956 tells the compiler to use function descriptors instead. The value
957 of this macro says how many words wide the descriptor is (normally 2),
958 but it may be dependent on target flags. Since we do not have access
959 to the target flags here we just check to see if it is set and use
960 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
961
962 It is assumed that the address of a function descriptor may be treated
963 as a pointer to a function. */
964
965#ifdef TARGET_VTABLE_USES_DESCRIPTORS
966#define VTABLE_USES_DESCRIPTORS 1
967#else
968#define VTABLE_USES_DESCRIPTORS 0
969#endif
970
971/* Tries to determine the most common value among its inputs. */
972void
Lee Leahy38768c32017-03-09 14:07:18 -0800973__gcov_indirect_call_profiler(gcov_type *counter, gcov_type value,
Lee Leahyb2d834a2017-03-08 16:52:22 -0800974 void *cur_func, void *callee_func)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800975{
Lee Leahye20a3192017-03-09 16:21:34 -0800976 /* If the C++ virtual tables contain function descriptors then one
977 * function may have multiple descriptors and we need to dereference
978 * the descriptors to see if they point to the same function.
979 */
980 if (cur_func == callee_func
981 || (VTABLE_USES_DESCRIPTORS && callee_func
982 && *(void **) cur_func == *(void **) callee_func))
983 __gcov_one_value_profiler_body(counter, value);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800984}
985#endif
986
987
988#ifdef L_gcov_average_profiler
989/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
990 to saturate up. */
991
992void
Lee Leahy38768c32017-03-09 14:07:18 -0800993__gcov_average_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800994{
Lee Leahye20a3192017-03-09 16:21:34 -0800995 counters[0] += value;
Lee Leahy35af5c42017-03-09 17:35:28 -0800996 counters[1]++;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800997}
998#endif
999
1000#ifdef L_gcov_ior_profiler
1001/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1002 to saturate up. */
1003
1004void
Lee Leahy38768c32017-03-09 14:07:18 -08001005__gcov_ior_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001006{
Lee Leahye20a3192017-03-09 16:21:34 -08001007 *counters |= value;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001008}
1009#endif
1010
1011#ifdef L_gcov_fork
1012/* A wrapper for the fork function. Flushes the accumulated profiling data, so
1013 that they are not counted twice. */
1014
1015pid_t
Lee Leahy38768c32017-03-09 14:07:18 -08001016__gcov_fork(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001017{
Lee Leahye20a3192017-03-09 16:21:34 -08001018 __gcov_flush();
1019 return fork();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001020}
1021#endif
1022
1023#ifdef L_gcov_execl
1024/* A wrapper for the execl function. Flushes the accumulated profiling data, so
1025 that they are not lost. */
1026
1027int
Lee Leahy38768c32017-03-09 14:07:18 -08001028__gcov_execl(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001029{
Lee Leahye20a3192017-03-09 16:21:34 -08001030 va_list ap, aq;
1031 unsigned int i, length;
1032 char **args;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001033
Lee Leahye20a3192017-03-09 16:21:34 -08001034 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001035
Lee Leahye20a3192017-03-09 16:21:34 -08001036 va_start(ap, arg);
1037 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001038
Lee Leahye20a3192017-03-09 16:21:34 -08001039 length = 2;
1040 while (va_arg(ap, char *))
1041 length++;
1042 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001043
Lee Leahye20a3192017-03-09 16:21:34 -08001044 args = (char **) alloca(length * sizeof(void *));
1045 args[0] = arg;
1046 for (i = 1; i < length; i++)
1047 args[i] = va_arg(aq, char *);
1048 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001049
Lee Leahye20a3192017-03-09 16:21:34 -08001050 return execv(path, args);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001051}
1052#endif
1053
1054#ifdef L_gcov_execlp
Lee Leahy73402172017-03-10 15:23:24 -08001055/* A wrapper for the execlp function. Flushes the accumulated profiling data,
1056 * so that they are not lost.
1057 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001058
1059int
Lee Leahy38768c32017-03-09 14:07:18 -08001060__gcov_execlp(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001061{
Lee Leahye20a3192017-03-09 16:21:34 -08001062 va_list ap, aq;
1063 unsigned int i, length;
1064 char **args;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001065
Lee Leahye20a3192017-03-09 16:21:34 -08001066 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001067
Lee Leahye20a3192017-03-09 16:21:34 -08001068 va_start(ap, arg);
1069 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001070
Lee Leahye20a3192017-03-09 16:21:34 -08001071 length = 2;
1072 while (va_arg(ap, char *))
1073 length++;
1074 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001075
Lee Leahye20a3192017-03-09 16:21:34 -08001076 args = (char **) alloca(length * sizeof(void *));
1077 args[0] = arg;
1078 for (i = 1; i < length; i++)
1079 args[i] = va_arg(aq, char *);
1080 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001081
Lee Leahye20a3192017-03-09 16:21:34 -08001082 return execvp(path, args);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001083}
1084#endif
1085
1086#ifdef L_gcov_execle
Lee Leahy73402172017-03-10 15:23:24 -08001087/* A wrapper for the execle function. Flushes the accumulated profiling data,
1088 * so that they are not lost.
1089 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001090
1091int
Lee Leahy38768c32017-03-09 14:07:18 -08001092__gcov_execle(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001093{
Lee Leahye20a3192017-03-09 16:21:34 -08001094 va_list ap, aq;
1095 unsigned int i, length;
1096 char **args;
1097 char **envp;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001098
Lee Leahye20a3192017-03-09 16:21:34 -08001099 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001100
Lee Leahye20a3192017-03-09 16:21:34 -08001101 va_start(ap, arg);
1102 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001103
Lee Leahye20a3192017-03-09 16:21:34 -08001104 length = 2;
1105 while (va_arg(ap, char *))
1106 length++;
1107 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001108
Lee Leahye20a3192017-03-09 16:21:34 -08001109 args = (char **) alloca(length * sizeof(void *));
1110 args[0] = arg;
1111 for (i = 1; i < length; i++)
1112 args[i] = va_arg(aq, char *);
1113 envp = va_arg(aq, char **);
1114 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001115
Lee Leahye20a3192017-03-09 16:21:34 -08001116 return execve(path, args, envp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001117}
1118#endif
1119
1120#ifdef L_gcov_execv
1121/* A wrapper for the execv function. Flushes the accumulated profiling data, so
1122 that they are not lost. */
1123
1124int
Lee Leahy38768c32017-03-09 14:07:18 -08001125__gcov_execv(const char *path, char *const argv[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001126{
Lee Leahye20a3192017-03-09 16:21:34 -08001127 __gcov_flush();
1128 return execv(path, argv);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001129}
1130#endif
1131
1132#ifdef L_gcov_execvp
Lee Leahy73402172017-03-10 15:23:24 -08001133/* A wrapper for the execvp function. Flushes the accumulated profiling data,
1134 * so that they are not lost.
1135 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001136
1137int
Lee Leahy38768c32017-03-09 14:07:18 -08001138__gcov_execvp(const char *path, char *const argv[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001139{
Lee Leahye20a3192017-03-09 16:21:34 -08001140 __gcov_flush();
1141 return execvp(path, argv);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001142}
1143#endif
1144
1145#ifdef L_gcov_execve
Lee Leahy73402172017-03-10 15:23:24 -08001146/* A wrapper for the execve function. Flushes the accumulated profiling data,
1147 * so that they are not lost.
1148 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001149
1150int
Lee Leahy38768c32017-03-09 14:07:18 -08001151__gcov_execve(const char *path, char *const argv[], char *const envp[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001152{
Lee Leahye20a3192017-03-09 16:21:34 -08001153 __gcov_flush();
1154 return execve(path, argv, envp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001155}
1156#endif
1157#endif /* inhibit_libc */