blob: 024b2c38ba41ce4cfbd2911b99bc54edc42ecdcc [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{
114 struct gcov_fn_buffer *next;
Lee Leahy75b85992017-03-08 16:34:12 -0800115 unsigned int fn_ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800116 struct gcov_fn_info info;
117 /* note gcov_fn_info ends in a trailing array. */
118};
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__
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 {
152 char sep = *s;
153 *s = '\0';
154
155 /* Try to make directory if it doesn't already exist. */
Lee Leahy38768c32017-03-09 14:07:18 -0800156 if (access(filename, F_OK) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800157#ifdef TARGET_POSIX_IO
Lee Leahy38768c32017-03-09 14:07:18 -0800158 && mkdir(filename, 0755) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800159#else
Lee Leahy38768c32017-03-09 14:07:18 -0800160 && mkdir(filename) == -1
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800161#endif
162 /* The directory might have been made by another process. */
163 && errno != EEXIST)
164 {
Lee Leahy38768c32017-03-09 14:07:18 -0800165 fprintf(stderr, "profiling:%s:Cannot create directory\n",
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800166 filename);
167 *s = sep;
168 return -1;
169 };
170
171 *s = sep;
172 };
173 return 0;
174#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{
182 struct gcov_fn_buffer *next;
Lee Leahy75b85992017-03-08 16:34:12 -0800183 unsigned int ix, n_ctr = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800184
185 if (!buffer)
186 return 0;
187 next = buffer->next;
188
189 for (ix = 0; ix != limit; ix++)
190 if (gi_ptr->merge[ix])
Lee Leahy38768c32017-03-09 14:07:18 -0800191 free(buffer->info.ctrs[n_ctr++].values);
192 free(buffer);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800193 return next;
194}
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 Leahy75b85992017-03-08 16:34:12 -0800200 unsigned int n_ctrs = 0, ix = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800201 struct gcov_fn_buffer *fn_buffer;
Lee Leahy75b85992017-03-08 16:34:12 -0800202 unsigned int len;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800203
204 for (ix = GCOV_COUNTERS; ix--;)
205 if (gi_ptr->merge[ix])
206 n_ctrs++;
207
Lee Leahy38768c32017-03-09 14:07:18 -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
211 if (!fn_buffer)
212 goto fail;
213
214 fn_buffer->next = 0;
215 fn_buffer->fn_ix = fn_ix;
Lee Leahy38768c32017-03-09 14:07:18 -0800216 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
220 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
221 {
222 gcov_unsigned_t length;
223 gcov_type *values;
224
225 if (!gi_ptr->merge[ix])
226 continue;
227
Lee Leahy38768c32017-03-09 14:07:18 -0800228 if (gcov_read_unsigned() != GCOV_TAG_FOR_COUNTER(ix))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800229 {
230 len = 0;
231 goto fail;
232 }
233
Lee Leahy38768c32017-03-09 14:07:18 -0800234 length = GCOV_TAG_COUNTER_NUM(gcov_read_unsigned());
235 len = length * sizeof(gcov_type);
236 values = (gcov_type *)malloc(len);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800237 if (!values)
238 goto fail;
239
240 fn_buffer->info.ctrs[n_ctrs].num = length;
241 fn_buffer->info.ctrs[n_ctrs].values = values;
242
243 while (length--)
Lee Leahy38768c32017-03-09 14:07:18 -0800244 *values++ = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800245 n_ctrs++;
246 }
247
248 *end_ptr = fn_buffer;
249 return &fn_buffer->next;
250
251fail:
Lee Leahy38768c32017-03-09 14:07:18 -0800252 fprintf(stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800253 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
254
Lee Leahy38768c32017-03-09 14:07:18 -0800255 return (struct gcov_fn_buffer **)free_fn_data(gi_ptr, fn_buffer, ix);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800256}
257
258/* Add an unsigned value to the current crc */
259
260static gcov_unsigned_t
Lee Leahy38768c32017-03-09 14:07:18 -0800261crc32_unsigned(gcov_unsigned_t crc32, gcov_unsigned_t value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800262{
Lee Leahy75b85992017-03-08 16:34:12 -0800263 unsigned int ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800264
265 for (ix = 32; ix--; value <<= 1)
266 {
Lee Leahy75b85992017-03-08 16:34:12 -0800267 unsigned int feedback;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800268
269 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
270 crc32 <<= 1;
271 crc32 ^= feedback;
272 }
273
274 return crc32;
275}
276
277/* Check if VERSION of the info block PTR matches libgcov one.
278 Return 1 on success, or zero in case of versions mismatch.
279 If FILENAME is not NULL, its value used for reporting purposes
280 instead of value from the info block. */
281
282static int
Lee Leahy38768c32017-03-09 14:07:18 -0800283gcov_version(struct gcov_info *ptr, gcov_unsigned_t version,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800284 const char *filename)
285{
286 if (version != GCOV_VERSION)
287 {
288 char v[4], e[4];
289
Lee Leahy38768c32017-03-09 14:07:18 -0800290 GCOV_UNSIGNED2STRING(v, version);
291 GCOV_UNSIGNED2STRING(e, GCOV_VERSION);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800292
Lee Leahy38768c32017-03-09 14:07:18 -0800293 fprintf(stderr,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800294 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
295 filename? filename : ptr->filename, e, v);
296 return 0;
297 }
298 return 1;
299}
300
301/* Dump the coverage counts. We merge with existing counts when
302 possible, to avoid growing the .da files ad infinitum. We use this
303 program's checksum to make sure we only accumulate whole program
304 statistics to the correct summary. An object file might be embedded
305 in two separate programs, and we must keep the two program
306 summaries separate. */
307
308static void
Lee Leahy38768c32017-03-09 14:07:18 -0800309gcov_exit(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800310{
311 struct gcov_info *gi_ptr;
312 const struct gcov_fn_info *gfi_ptr;
313 struct gcov_summary this_prg; /* summary for program. */
314 struct gcov_summary all_prg; /* summary for all instances of program. */
315 struct gcov_ctr_summary *cs_ptr;
316 const struct gcov_ctr_info *ci_ptr;
Lee Leahy75b85992017-03-08 16:34:12 -0800317 unsigned int t_ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800318 int f_ix = 0;
319 gcov_unsigned_t c_num;
320 const char *gcov_prefix;
321 int gcov_prefix_strip = 0;
322 size_t prefix_length;
323 char *gi_filename, *gi_filename_up;
324 gcov_unsigned_t crc32 = 0;
325
Lee Leahy38768c32017-03-09 14:07:18 -0800326 memset(&all_prg, 0, sizeof(all_prg));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800327 /* Find the totals for this execution. */
Lee Leahy38768c32017-03-09 14:07:18 -0800328 memset(&this_prg, 0, sizeof(this_prg));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800329 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
330 {
Lee Leahy38768c32017-03-09 14:07:18 -0800331 crc32 = crc32_unsigned(crc32, gi_ptr->stamp);
332 crc32 = crc32_unsigned(crc32, gi_ptr->n_functions);
Kyösti Mälkkiecd84242013-09-13 07:57:49 +0300333
Lee Leahy75b85992017-03-08 16:34:12 -0800334 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions; f_ix++)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800335 {
336 gfi_ptr = gi_ptr->functions[f_ix];
337
338 if (gfi_ptr && gfi_ptr->key != gi_ptr)
339 gfi_ptr = 0;
340
Lee Leahy38768c32017-03-09 14:07:18 -0800341 crc32 = crc32_unsigned(crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
342 crc32 = crc32_unsigned(crc32,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800343 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
344 if (!gfi_ptr)
345 continue;
346
347 ci_ptr = gfi_ptr->ctrs;
348 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
349 {
350 if (!gi_ptr->merge[t_ix])
351 continue;
352
353 cs_ptr = &this_prg.ctrs[t_ix];
354 cs_ptr->num += ci_ptr->num;
Lee Leahy38768c32017-03-09 14:07:18 -0800355 crc32 = crc32_unsigned(crc32, ci_ptr->num);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800356
357 for (c_num = 0; c_num < ci_ptr->num; c_num++)
358 {
359 cs_ptr->sum_all += ci_ptr->values[c_num];
360 if (cs_ptr->run_max < ci_ptr->values[c_num])
361 cs_ptr->run_max = ci_ptr->values[c_num];
362 }
363 ci_ptr++;
364 }
365 }
366 }
367
368#ifndef __COREBOOT__
369 {
370 /* Check if the level of dirs to strip off specified. */
371 char *tmp = getenv("GCOV_PREFIX_STRIP");
372 if (tmp)
373 {
Lee Leahy38768c32017-03-09 14:07:18 -0800374 gcov_prefix_strip = atoi(tmp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800375 /* Do not consider negative values. */
376 if (gcov_prefix_strip < 0)
377 gcov_prefix_strip = 0;
378 }
379 }
380
381 /* Get file name relocation prefix. Non-absolute values are ignored. */
382 gcov_prefix = getenv("GCOV_PREFIX");
383 if (gcov_prefix)
384 {
385 prefix_length = strlen(gcov_prefix);
386
387 /* Remove an unnecessary trailing '/' */
Lee Leahy38768c32017-03-09 14:07:18 -0800388 if (IS_DIR_SEPARATOR(gcov_prefix[prefix_length - 1]))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800389 prefix_length--;
390 }
391 else
392#endif
393 prefix_length = 0;
394
Martin Rothcbf2bd72013-07-09 21:51:14 -0600395 /* If no prefix was specified and a prefix strip, then we assume
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800396 relative. */
397 if (gcov_prefix_strip != 0 && prefix_length == 0)
398 {
399 gcov_prefix = ".";
400 prefix_length = 1;
401 }
402 /* Allocate and initialize the filename scratch space plus one. */
Lee Leahy38768c32017-03-09 14:07:18 -0800403 gi_filename = (char *) alloca(prefix_length + gcov_max_filename + 2);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800404 if (prefix_length)
Lee Leahy38768c32017-03-09 14:07:18 -0800405 memcpy(gi_filename, gcov_prefix, prefix_length);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800406 gi_filename_up = gi_filename + prefix_length;
407
408 /* Now merge each file. */
409 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
410 {
Lee Leahy75b85992017-03-08 16:34:12 -0800411 unsigned int n_counts;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800412 struct gcov_summary prg; /* summary for this object over all
413 program. */
414 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
415 int error = 0;
416 gcov_unsigned_t tag, length;
417 gcov_position_t summary_pos = 0;
418 gcov_position_t eof_pos = 0;
419 const char *fname, *s;
420 struct gcov_fn_buffer *fn_buffer = 0;
421 struct gcov_fn_buffer **fn_tail = &fn_buffer;
422
423 fname = gi_ptr->filename;
424
425 /* Avoid to add multiple drive letters into combined path. */
426 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
427 fname += 2;
428
429 /* Build relocated filename, stripping off leading
430 directories from the initial filename if requested. */
431 if (gcov_prefix_strip > 0)
432 {
433 int level = 0;
434 s = fname;
435 if (IS_DIR_SEPARATOR(*s))
436 ++s;
437
438 /* Skip selected directory levels. */
439 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
440 if (IS_DIR_SEPARATOR(*s))
441 {
442 fname = s;
443 level++;
444 }
445 }
446
447 /* Update complete filename with stripped original. */
Lee Leahy38768c32017-03-09 14:07:18 -0800448 if (prefix_length != 0 && !IS_DIR_SEPARATOR(*fname))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800449 {
450 /* If prefix is given, add directory separator. */
Lee Leahy38768c32017-03-09 14:07:18 -0800451 strcpy(gi_filename_up, "/");
452 strcpy(gi_filename_up + 1, fname);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800453 }
454 else
Lee Leahy38768c32017-03-09 14:07:18 -0800455 strcpy(gi_filename_up, fname);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800456
Lee Leahy38768c32017-03-09 14:07:18 -0800457 if (!gcov_open(gi_filename))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800458 {
459 /* Open failed likely due to missed directory.
460 Create directory and retry to open file. */
Lee Leahy38768c32017-03-09 14:07:18 -0800461 if (create_file_directory(gi_filename))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800462 {
Lee Leahy38768c32017-03-09 14:07:18 -0800463 fprintf(stderr, "profiling:%s:Skip\n", gi_filename);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800464 continue;
465 }
Lee Leahy38768c32017-03-09 14:07:18 -0800466 if (!gcov_open(gi_filename))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800467 {
Lee Leahy38768c32017-03-09 14:07:18 -0800468 fprintf(stderr, "profiling:%s:Cannot open\n", gi_filename);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800469 continue;
470 }
471 }
472
Lee Leahy38768c32017-03-09 14:07:18 -0800473 tag = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800474 if (tag)
475 {
476 /* Merge data from file. */
477 if (tag != GCOV_DATA_MAGIC)
478 {
Lee Leahy38768c32017-03-09 14:07:18 -0800479 fprintf(stderr, "profiling:%s:Not a gcov data file\n",
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800480 gi_filename);
481 goto read_fatal;
482 }
Lee Leahy38768c32017-03-09 14:07:18 -0800483 length = gcov_read_unsigned();
484 if (!gcov_version(gi_ptr, length, gi_filename))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800485 goto read_fatal;
486
Lee Leahy38768c32017-03-09 14:07:18 -0800487 length = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800488 if (length != gi_ptr->stamp)
489 /* Read from a different compilation. Overwrite the file. */
490 goto rewrite;
491
492 /* Look for program summary. */
493 for (f_ix = 0;;)
494 {
495 struct gcov_summary tmp;
496
Lee Leahy38768c32017-03-09 14:07:18 -0800497 eof_pos = gcov_position();
498 tag = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800499 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
500 break;
501
502 f_ix--;
Lee Leahy38768c32017-03-09 14:07:18 -0800503 length = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800504 if (length != GCOV_TAG_SUMMARY_LENGTH)
505 goto read_mismatch;
Lee Leahy38768c32017-03-09 14:07:18 -0800506 gcov_read_summary(&tmp);
507 if ((error = gcov_is_error()))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800508 goto read_error;
509 if (summary_pos || tmp.checksum != crc32)
510 goto next_summary;
511
512 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
513 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
514 goto next_summary;
515 prg = tmp;
516 summary_pos = eof_pos;
517
518 next_summary:;
519 }
520
521 /* Merge execution counts for each function. */
Lee Leahy75b85992017-03-08 16:34:12 -0800522 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions;
Lee Leahy38768c32017-03-09 14:07:18 -0800523 f_ix++, tag = gcov_read_unsigned())
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800524 {
525 gfi_ptr = gi_ptr->functions[f_ix];
526
527 if (tag != GCOV_TAG_FUNCTION)
528 goto read_mismatch;
529
Lee Leahy38768c32017-03-09 14:07:18 -0800530 length = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800531 if (!length)
532 /* This function did not appear in the other program.
533 We have nothing to merge. */
534 continue;
535
536 if (length != GCOV_TAG_FUNCTION_LENGTH)
537 goto read_mismatch;
538
539 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
540 {
541 /* This function appears in the other program. We
542 need to buffer the information in order to write
543 it back out -- we'll be inserting data before
544 this point, so cannot simply keep the data in the
545 file. */
Lee Leahy38768c32017-03-09 14:07:18 -0800546 fn_tail = buffer_fn_data(gi_filename,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800547 gi_ptr, fn_tail, f_ix);
548 if (!fn_tail)
549 goto read_mismatch;
550 continue;
551 }
552
Lee Leahy38768c32017-03-09 14:07:18 -0800553 length = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800554 if (length != gfi_ptr->ident)
555 goto read_mismatch;
556
Lee Leahy38768c32017-03-09 14:07:18 -0800557 length = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800558 if (length != gfi_ptr->lineno_checksum)
559 goto read_mismatch;
560
Lee Leahy38768c32017-03-09 14:07:18 -0800561 length = gcov_read_unsigned();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800562 if (length != gfi_ptr->cfg_checksum)
563 goto read_mismatch;
564
565 ci_ptr = gfi_ptr->ctrs;
566 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
567 {
568 gcov_merge_fn merge = gi_ptr->merge[t_ix];
569
570 if (!merge)
571 continue;
572
Lee Leahy38768c32017-03-09 14:07:18 -0800573 tag = gcov_read_unsigned();
574 length = gcov_read_unsigned();
575 if (tag != GCOV_TAG_FOR_COUNTER(t_ix)
576 || length != GCOV_TAG_COUNTER_LENGTH(ci_ptr->num))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800577 goto read_mismatch;
Lee Leahy38768c32017-03-09 14:07:18 -0800578 (*merge)(ci_ptr->values, ci_ptr->num);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800579 ci_ptr++;
580 }
Lee Leahy38768c32017-03-09 14:07:18 -0800581 if ((error = gcov_is_error()))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800582 goto read_error;
583 }
584
585 if (tag)
586 {
587 read_mismatch:;
Lee Leahy38768c32017-03-09 14:07:18 -0800588 fprintf(stderr, "profiling:%s:Merge mismatch for %s %u\n",
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800589 gi_filename, f_ix >= 0 ? "function" : "summary",
590 f_ix < 0 ? -1 - f_ix : f_ix);
591 goto read_fatal;
592 }
593 }
594 goto rewrite;
595
596 read_error:;
Lee Leahy38768c32017-03-09 14:07:18 -0800597 fprintf(stderr, "profiling:%s:%s merging\n", gi_filename,
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800598 error < 0 ? "Overflow": "Error");
599
600 goto read_fatal;
601
602 rewrite:;
Lee Leahy38768c32017-03-09 14:07:18 -0800603 gcov_rewrite();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800604 if (!summary_pos)
605 {
Lee Leahy38768c32017-03-09 14:07:18 -0800606 memset(&prg, 0, sizeof(prg));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800607 summary_pos = eof_pos;
608 }
609
610 /* Merge the summaries. */
611 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
612 {
613 cs_prg = &prg.ctrs[t_ix];
614 cs_tprg = &this_prg.ctrs[t_ix];
615 cs_all = &all_prg.ctrs[t_ix];
616
617 if (gi_ptr->merge[t_ix])
618 {
619 if (!cs_prg->runs++)
620 cs_prg->num = cs_tprg->num;
621 cs_prg->sum_all += cs_tprg->sum_all;
622 if (cs_prg->run_max < cs_tprg->run_max)
623 cs_prg->run_max = cs_tprg->run_max;
624 cs_prg->sum_max += cs_tprg->run_max;
625 }
626 else if (cs_prg->runs)
627 goto read_mismatch;
628
629 if (!cs_all->runs && cs_prg->runs)
Lee Leahy38768c32017-03-09 14:07:18 -0800630 memcpy(cs_all, cs_prg, sizeof(*cs_all));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800631 else if (!all_prg.checksum
632 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
Lee Leahy38768c32017-03-09 14:07:18 -0800633 && memcmp(cs_all, cs_prg, sizeof(*cs_all)))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800634 {
Lee Leahy38768c32017-03-09 14:07:18 -0800635 fprintf(stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800636 gi_filename, GCOV_LOCKED
637 ? "" : " or concurrently updated without locking support");
638 all_prg.checksum = ~0u;
639 }
640 }
641
642 prg.checksum = crc32;
643
644 /* Write out the data. */
645 if (!eof_pos)
646 {
Lee Leahy38768c32017-03-09 14:07:18 -0800647 gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
648 gcov_write_unsigned(gi_ptr->stamp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800649 }
650
651 if (summary_pos)
Lee Leahy38768c32017-03-09 14:07:18 -0800652 gcov_seek(summary_pos);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800653
654 /* Generate whole program statistics. */
Lee Leahy38768c32017-03-09 14:07:18 -0800655 gcov_write_summary(GCOV_TAG_PROGRAM_SUMMARY, &prg);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800656
657 if (summary_pos < eof_pos)
Lee Leahy38768c32017-03-09 14:07:18 -0800658 gcov_seek(eof_pos);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800659
660 /* Write execution counts for each function. */
Lee Leahy75b85992017-03-08 16:34:12 -0800661 for (f_ix = 0; (unsigned int)f_ix != gi_ptr->n_functions; f_ix++)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800662 {
Lee Leahy75b85992017-03-08 16:34:12 -0800663 unsigned int buffered = 0;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800664
Lee Leahy75b85992017-03-08 16:34:12 -0800665 if (fn_buffer && fn_buffer->fn_ix == (unsigned int)f_ix)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800666 {
667 /* Buffered data from another program. */
668 buffered = 1;
669 gfi_ptr = &fn_buffer->info;
670 length = GCOV_TAG_FUNCTION_LENGTH;
671 }
672 else
673 {
674 gfi_ptr = gi_ptr->functions[f_ix];
675 if (gfi_ptr && gfi_ptr->key == gi_ptr)
676 length = GCOV_TAG_FUNCTION_LENGTH;
677 else
678 length = 0;
679 }
680
Lee Leahy38768c32017-03-09 14:07:18 -0800681 gcov_write_tag_length(GCOV_TAG_FUNCTION, length);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800682 if (!length)
683 continue;
684
Lee Leahy38768c32017-03-09 14:07:18 -0800685 gcov_write_unsigned(gfi_ptr->ident);
686 gcov_write_unsigned(gfi_ptr->lineno_checksum);
687 gcov_write_unsigned(gfi_ptr->cfg_checksum);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800688
689 ci_ptr = gfi_ptr->ctrs;
690 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
691 {
692 if (!gi_ptr->merge[t_ix])
693 continue;
694
695 n_counts = ci_ptr->num;
Lee Leahy38768c32017-03-09 14:07:18 -0800696 gcov_write_tag_length(GCOV_TAG_FOR_COUNTER(t_ix),
697 GCOV_TAG_COUNTER_LENGTH(n_counts));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800698 gcov_type *c_ptr = ci_ptr->values;
699 while (n_counts--)
Lee Leahy38768c32017-03-09 14:07:18 -0800700 gcov_write_counter(*c_ptr++);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800701 ci_ptr++;
702 }
703 if (buffered)
Lee Leahy38768c32017-03-09 14:07:18 -0800704 fn_buffer = free_fn_data(gi_ptr, fn_buffer, GCOV_COUNTERS);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800705 }
706
Lee Leahy38768c32017-03-09 14:07:18 -0800707 gcov_write_unsigned(0);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800708
709 read_fatal:;
710 while (fn_buffer)
Lee Leahy38768c32017-03-09 14:07:18 -0800711 fn_buffer = free_fn_data(gi_ptr, fn_buffer, GCOV_COUNTERS);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800712
Lee Leahy38768c32017-03-09 14:07:18 -0800713 if ((error = gcov_close()))
714 fprintf(stderr, error < 0 ?
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800715 "profiling:%s:Overflow writing\n" :
716 "profiling:%s:Error writing\n",
717 gi_filename);
718 }
719}
720
721/* Add a new object file onto the bb chain. Invoked automatically
722 when running an object file's global ctors. */
723
724void
Lee Leahy38768c32017-03-09 14:07:18 -0800725__gcov_init(struct gcov_info *info)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800726{
727 if (!info->version || !info->n_functions)
728 return;
Lee Leahy38768c32017-03-09 14:07:18 -0800729 if (gcov_version(info, info->version, 0))
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800730 {
731 size_t filename_length = strlen(info->filename);
732
733 /* Refresh the longest file name information */
734 if (filename_length > gcov_max_filename)
735 gcov_max_filename = filename_length;
736
737#ifndef __COREBOOT__
738 if (!gcov_list)
Lee Leahy38768c32017-03-09 14:07:18 -0800739 atexit(gcov_exit);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800740#endif
741
742 info->next = gcov_list;
743 gcov_list = info;
744 }
745 info->version = 0;
746}
747
748/* Called before fork or exec - write out profile information gathered so
749 far and reset it to zero. This avoids duplication or loss of the
750 profile information gathered so far. */
751
752void
Lee Leahy38768c32017-03-09 14:07:18 -0800753__gcov_flush(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800754{
755 const struct gcov_info *gi_ptr;
756
Lee Leahy38768c32017-03-09 14:07:18 -0800757 gcov_exit();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800758 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
759 {
Lee Leahy75b85992017-03-08 16:34:12 -0800760 unsigned int f_ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800761
762 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
763 {
Lee Leahy75b85992017-03-08 16:34:12 -0800764 unsigned int t_ix;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800765 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
766
767 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
768 continue;
769 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
770 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
771 {
772 if (!gi_ptr->merge[t_ix])
773 continue;
774
Lee Leahy38768c32017-03-09 14:07:18 -0800775 memset(ci_ptr->values, 0, sizeof(gcov_type) * ci_ptr->num);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800776 ci_ptr++;
777 }
778 }
779 }
780}
781
782#endif /* L_gcov */
783
784#ifdef L_gcov_merge_add
785/* The profile merging function that just adds the counters. It is given
786 an array COUNTERS of N_COUNTERS old counters and it reads the same number
787 of counters from the gcov file. */
788void
Lee Leahy38768c32017-03-09 14:07:18 -0800789__gcov_merge_add(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800790{
791 for (; n_counters; counters++, n_counters--)
Lee Leahy38768c32017-03-09 14:07:18 -0800792 *counters += gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800793}
794#endif /* L_gcov_merge_add */
795
796#ifdef L_gcov_merge_ior
797/* The profile merging function that just adds the counters. It is given
798 an array COUNTERS of N_COUNTERS old counters and it reads the same number
799 of counters from the gcov file. */
800void
Lee Leahy38768c32017-03-09 14:07:18 -0800801__gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800802{
803 for (; n_counters; counters++, n_counters--)
Lee Leahy38768c32017-03-09 14:07:18 -0800804 *counters |= gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800805}
806#endif
807
808#ifdef L_gcov_merge_single
809/* The profile merging function for choosing the most common value.
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600810 * It is given an array COUNTERS of N_COUNTERS old counters and it
811 * reads the same number of counters from the gcov file. The counters
812 * are split into 3-tuples where the members of the tuple have
813 * meanings:
814 *
815 * -- the stored candidate on the most common value of the measured entity
816 * -- counter
Stefan Reinauerf572e1e2013-01-16 09:47:54 -0800817 * -- total number of evaluations of the value
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600818 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800819void
Lee Leahy38768c32017-03-09 14:07:18 -0800820__gcov_merge_single(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800821{
Lee Leahy75b85992017-03-08 16:34:12 -0800822 unsigned int i, n_measures;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800823 gcov_type value, counter, all;
824
Lee Leahy38768c32017-03-09 14:07:18 -0800825 gcc_assert(!(n_counters % 3));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800826 n_measures = n_counters / 3;
827 for (i = 0; i < n_measures; i++, counters += 3)
828 {
Lee Leahy38768c32017-03-09 14:07:18 -0800829 value = gcov_read_counter();
830 counter = gcov_read_counter();
831 all = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800832
833 if (counters[0] == value)
834 counters[1] += counter;
835 else if (counter > counters[1])
836 {
837 counters[0] = value;
838 counters[1] = counter - counters[1];
839 }
840 else
841 counters[1] -= counter;
842 counters[2] += all;
843 }
844}
845#endif /* L_gcov_merge_single */
846
847#ifdef L_gcov_merge_delta
848/* The profile merging function for choosing the most common
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600849 * difference between two consecutive evaluations of the value. It is
850 * given an array COUNTERS of N_COUNTERS old counters and it reads the
851 * same number of counters from the gcov file. The counters are split
852 * into 4-tuples where the members of the tuple have meanings:
853 *
854 * -- the last value of the measured entity
855 * -- the stored candidate on the most common difference
856 * -- counter
Stefan Reinauerf572e1e2013-01-16 09:47:54 -0800857 * -- total number of evaluations of the value
Ronald G. Minnich850793f2013-01-13 17:22:42 -0600858 */
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800859void
Lee Leahy38768c32017-03-09 14:07:18 -0800860__gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800861{
Lee Leahy75b85992017-03-08 16:34:12 -0800862 unsigned int i, n_measures;
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800863 gcov_type value, counter, all;
864
Lee Leahy38768c32017-03-09 14:07:18 -0800865 gcc_assert(!(n_counters % 4));
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800866 n_measures = n_counters / 4;
867 for (i = 0; i < n_measures; i++, counters += 4)
868 {
Lee Leahy38768c32017-03-09 14:07:18 -0800869 /* last = */ gcov_read_counter();
870 value = gcov_read_counter();
871 counter = gcov_read_counter();
872 all = gcov_read_counter();
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800873
874 if (counters[1] == value)
875 counters[2] += counter;
876 else if (counter > counters[2])
877 {
878 counters[1] = value;
879 counters[2] = counter - counters[2];
880 }
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
894void
Lee Leahy38768c32017-03-09 14:07:18 -0800895__gcov_interval_profiler(gcov_type *counters, gcov_type value,
Lee Leahy75b85992017-03-08 16:34:12 -0800896 int start, unsigned int steps)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800897{
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
912void
Lee Leahy38768c32017-03-09 14:07:18 -0800913__gcov_pow2_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800914{
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
932static inline void
Lee Leahy38768c32017-03-09 14:07:18 -0800933__gcov_one_value_profiler_body(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800934{
935 if (value == counters[0])
936 counters[1]++;
937 else if (counters[1] == 0)
938 {
939 counters[1] = 1;
940 counters[0] = value;
941 }
942 else
943 counters[1]--;
944 counters[2]++;
945}
946
947#ifdef L_gcov_one_value_profiler
948void
Lee Leahy38768c32017-03-09 14:07:18 -0800949__gcov_one_value_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800950{
Lee Leahy38768c32017-03-09 14:07:18 -0800951 __gcov_one_value_profiler_body(counters, value);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800952}
953#endif
954
955#ifdef L_gcov_indirect_call_profiler
956
957/* By default, the C++ compiler will use function addresses in the
958 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
959 tells the compiler to use function descriptors instead. The value
960 of this macro says how many words wide the descriptor is (normally 2),
961 but it may be dependent on target flags. Since we do not have access
962 to the target flags here we just check to see if it is set and use
963 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
964
965 It is assumed that the address of a function descriptor may be treated
966 as a pointer to a function. */
967
968#ifdef TARGET_VTABLE_USES_DESCRIPTORS
969#define VTABLE_USES_DESCRIPTORS 1
970#else
971#define VTABLE_USES_DESCRIPTORS 0
972#endif
973
974/* Tries to determine the most common value among its inputs. */
975void
Lee Leahy38768c32017-03-09 14:07:18 -0800976__gcov_indirect_call_profiler(gcov_type *counter, gcov_type value,
Lee Leahyb2d834a2017-03-08 16:52:22 -0800977 void *cur_func, void *callee_func)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800978{
979 /* If the C++ virtual tables contain function descriptors then one
980 function may have multiple descriptors and we need to dereference
981 the descriptors to see if they point to the same function. */
982 if (cur_func == callee_func
983 || (VTABLE_USES_DESCRIPTORS && callee_func
984 && *(void **) cur_func == *(void **) callee_func))
Lee Leahy38768c32017-03-09 14:07:18 -0800985 __gcov_one_value_profiler_body(counter, value);
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800986}
987#endif
988
989
990#ifdef L_gcov_average_profiler
991/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
992 to saturate up. */
993
994void
Lee Leahy38768c32017-03-09 14:07:18 -0800995__gcov_average_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -0800996{
997 counters[0] += value;
998 counters[1] ++;
999}
1000#endif
1001
1002#ifdef L_gcov_ior_profiler
1003/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1004 to saturate up. */
1005
1006void
Lee Leahy38768c32017-03-09 14:07:18 -08001007__gcov_ior_profiler(gcov_type *counters, gcov_type value)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001008{
1009 *counters |= value;
1010}
1011#endif
1012
1013#ifdef L_gcov_fork
1014/* A wrapper for the fork function. Flushes the accumulated profiling data, so
1015 that they are not counted twice. */
1016
1017pid_t
Lee Leahy38768c32017-03-09 14:07:18 -08001018__gcov_fork(void)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001019{
Lee Leahy38768c32017-03-09 14:07:18 -08001020 __gcov_flush();
1021 return fork();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001022}
1023#endif
1024
1025#ifdef L_gcov_execl
1026/* A wrapper for the execl function. Flushes the accumulated profiling data, so
1027 that they are not lost. */
1028
1029int
Lee Leahy38768c32017-03-09 14:07:18 -08001030__gcov_execl(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001031{
1032 va_list ap, aq;
Lee Leahy75b85992017-03-08 16:34:12 -08001033 unsigned int i, length;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001034 char **args;
1035
Lee Leahy38768c32017-03-09 14:07:18 -08001036 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001037
Lee Leahy38768c32017-03-09 14:07:18 -08001038 va_start(ap, arg);
1039 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001040
1041 length = 2;
Lee Leahy38768c32017-03-09 14:07:18 -08001042 while (va_arg(ap, char *))
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001043 length++;
Lee Leahy38768c32017-03-09 14:07:18 -08001044 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001045
Lee Leahy38768c32017-03-09 14:07:18 -08001046 args = (char **) alloca(length * sizeof(void *));
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001047 args[0] = arg;
1048 for (i = 1; i < length; i++)
Lee Leahy38768c32017-03-09 14:07:18 -08001049 args[i] = va_arg(aq, char *);
1050 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001051
Lee Leahy38768c32017-03-09 14:07:18 -08001052 return execv(path, args);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001053}
1054#endif
1055
1056#ifdef L_gcov_execlp
1057/* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1058 that they are not lost. */
1059
1060int
Lee Leahy38768c32017-03-09 14:07:18 -08001061__gcov_execlp(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001062{
1063 va_list ap, aq;
Lee Leahy75b85992017-03-08 16:34:12 -08001064 unsigned int i, length;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001065 char **args;
1066
Lee Leahy38768c32017-03-09 14:07:18 -08001067 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001068
Lee Leahy38768c32017-03-09 14:07:18 -08001069 va_start(ap, arg);
1070 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001071
1072 length = 2;
Lee Leahy38768c32017-03-09 14:07:18 -08001073 while (va_arg(ap, char *))
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001074 length++;
Lee Leahy38768c32017-03-09 14:07:18 -08001075 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001076
Lee Leahy38768c32017-03-09 14:07:18 -08001077 args = (char **) alloca(length * sizeof(void *));
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001078 args[0] = arg;
1079 for (i = 1; i < length; i++)
Lee Leahy38768c32017-03-09 14:07:18 -08001080 args[i] = va_arg(aq, char *);
1081 va_end(aq);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001082
Lee Leahy38768c32017-03-09 14:07:18 -08001083 return execvp(path, args);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001084}
1085#endif
1086
1087#ifdef L_gcov_execle
1088/* A wrapper for the execle function. Flushes the accumulated profiling data, so
1089 that they are not lost. */
1090
1091int
Lee Leahy38768c32017-03-09 14:07:18 -08001092__gcov_execle(const char *path, char *arg, ...)
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001093{
1094 va_list ap, aq;
Lee Leahy75b85992017-03-08 16:34:12 -08001095 unsigned int i, length;
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001096 char **args;
1097 char **envp;
1098
Lee Leahy38768c32017-03-09 14:07:18 -08001099 __gcov_flush();
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001100
Lee Leahy38768c32017-03-09 14:07:18 -08001101 va_start(ap, arg);
1102 va_copy(aq, ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001103
1104 length = 2;
Lee Leahy38768c32017-03-09 14:07:18 -08001105 while (va_arg(ap, char *))
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001106 length++;
Lee Leahy38768c32017-03-09 14:07:18 -08001107 va_end(ap);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001108
Lee Leahy38768c32017-03-09 14:07:18 -08001109 args = (char **) alloca(length * sizeof(void *));
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001110 args[0] = arg;
1111 for (i = 1; i < length; i++)
Lee Leahy38768c32017-03-09 14:07:18 -08001112 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 Leahy38768c32017-03-09 14:07:18 -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 Leahy38768c32017-03-09 14:07:18 -08001127 __gcov_flush();
1128 return execv(path, argv);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001129}
1130#endif
1131
1132#ifdef L_gcov_execvp
1133/* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1134 that they are not lost. */
1135
1136int
Lee Leahy38768c32017-03-09 14:07:18 -08001137__gcov_execvp(const char *path, char *const argv[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001138{
Lee Leahy38768c32017-03-09 14:07:18 -08001139 __gcov_flush();
1140 return execvp(path, argv);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001141}
1142#endif
1143
1144#ifdef L_gcov_execve
1145/* A wrapper for the execve function. Flushes the accumulated profiling data, so
1146 that they are not lost. */
1147
1148int
Lee Leahy38768c32017-03-09 14:07:18 -08001149__gcov_execve(const char *path, char *const argv[], char *const envp[])
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001150{
Lee Leahy38768c32017-03-09 14:07:18 -08001151 __gcov_flush();
1152 return execve(path, argv, envp);
Stefan Reinauerd37ab452012-12-18 16:23:28 -08001153}
1154#endif
1155#endif /* inhibit_libc */