]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/libgcov-interface.c
PR c++/85552 - wrong instantiation of dtor for DMI.
[thirdparty/gcc.git] / libgcc / libgcov-interface.c
CommitLineData
ded3d3f8 1/* Routines required for instrumenting a program. */
2/* Compile this one with gcc. */
fbd26352 3/* Copyright (C) 1989-2019 Free Software Foundation, Inc.
ded3d3f8 4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
67745126 26#include "libgcov.h"
ded3d3f8 27#include "gthr.h"
28
ded3d3f8 29#if defined(inhibit_libc)
30
31#ifdef L_gcov_flush
32void __gcov_flush (void) {}
33#endif
34
35#ifdef L_gcov_reset
36void __gcov_reset (void) {}
37#endif
38
39#ifdef L_gcov_dump
40void __gcov_dump (void) {}
41#endif
42
43#else
44
b12d2330 45/* Some functions we want to bind in this dynamic object, but have an
a91625a6 46 overridable global alias. Unfortunately not all targets support
47 aliases, so we just have a forwarding function. That'll be tail
48 called, so the cost is a single jump instruction.*/
49
50#define ALIAS_void_fn(src,dst) \
51 void dst (void) \
52 { src (); }
b12d2330 53
859fa1a9 54extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
cb3ea3de 55extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
ded3d3f8 56
57#ifdef L_gcov_flush
ded3d3f8 58#ifdef __GTHREAD_MUTEX_INIT
cb3ea3de 59__gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
ded3d3f8 60#define init_mx_once()
61#else
cb3ea3de 62__gthread_mutex_t __gcov_flush_mx;
ded3d3f8 63
64static void
65init_mx (void)
66{
67 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
68}
cb3ea3de 69
ded3d3f8 70static void
71init_mx_once (void)
72{
73 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
74 __gthread_once (&once, init_mx);
75}
76#endif
77
78/* Called before fork or exec - write out profile information gathered so
79 far and reset it to zero. This avoids duplication or loss of the
80 profile information gathered so far. */
81
82void
83__gcov_flush (void)
84{
85 init_mx_once ();
86 __gthread_mutex_lock (&__gcov_flush_mx);
87
bc587267 88 __gcov_dump_int ();
b12d2330 89 __gcov_reset_int ();
ded3d3f8 90
91 __gthread_mutex_unlock (&__gcov_flush_mx);
92}
93
94#endif /* L_gcov_flush */
95
96#ifdef L_gcov_reset
97
859fa1a9 98/* Reset all counters to zero. */
99
100static void
101gcov_clear (const struct gcov_info *list)
102{
103 const struct gcov_info *gi_ptr;
104
105 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
106 {
107 unsigned f_ix;
108
109 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
110 {
111 unsigned t_ix;
112 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
113
114 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
115 continue;
116 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
117 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
118 {
119 if (!gi_ptr->merge[t_ix])
120 continue;
121
122 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
123 ci_ptr++;
124 }
125 }
126 }
127}
128
ded3d3f8 129/* Function that can be called from application to reset counters to zero,
130 in order to collect profile in region of interest. */
131
132void
b12d2330 133__gcov_reset_int (void)
ded3d3f8 134{
bc587267 135 struct gcov_root *root;
136
137 /* If we're compatible with the master, iterate over everything,
138 otherise just do us. */
139 for (root = __gcov_master.version == GCOV_VERSION
140 ? __gcov_master.root : &__gcov_root; root; root = root->next)
141 {
142 gcov_clear (root->list);
143 root->dumped = 0;
144 }
ded3d3f8 145}
146
a91625a6 147ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
b12d2330 148
ded3d3f8 149#endif /* L_gcov_reset */
150
151#ifdef L_gcov_dump
ded3d3f8 152/* Function that can be called from application to write profile collected
153 so far, in order to collect profile in region of interest. */
154
155void
bc587267 156__gcov_dump_int (void)
ded3d3f8 157{
bc587267 158 struct gcov_root *root;
159
160 /* If we're compatible with the master, iterate over everything,
161 otherise just do us. */
162 for (root = __gcov_master.version == GCOV_VERSION
163 ? __gcov_master.root : &__gcov_root; root; root = root->next)
164 __gcov_dump_one (root);
ded3d3f8 165}
166
bc587267 167ALIAS_void_fn (__gcov_dump_int, __gcov_dump);
168
ded3d3f8 169#endif /* L_gcov_dump */
170
ded3d3f8 171#ifdef L_gcov_fork
172/* A wrapper for the fork function. Flushes the accumulated profiling data, so
173 that they are not counted twice. */
174
175pid_t
176__gcov_fork (void)
177{
178 pid_t pid;
ded3d3f8 179 __gcov_flush ();
180 pid = fork ();
181 if (pid == 0)
182 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
183 return pid;
184}
185#endif
186
187#ifdef L_gcov_execl
bc587267 188/* A wrapper for the execl function. Flushes the accumulated
189 profiling data, so that they are not lost. */
ded3d3f8 190
191int
192__gcov_execl (const char *path, char *arg, ...)
193{
194 va_list ap, aq;
195 unsigned i, length;
196 char **args;
197
198 __gcov_flush ();
199
200 va_start (ap, arg);
201 va_copy (aq, ap);
202
203 length = 2;
204 while (va_arg (ap, char *))
205 length++;
206 va_end (ap);
207
208 args = (char **) alloca (length * sizeof (void *));
209 args[0] = arg;
210 for (i = 1; i < length; i++)
211 args[i] = va_arg (aq, char *);
212 va_end (aq);
213
214 return execv (path, args);
215}
216#endif
217
218#ifdef L_gcov_execlp
cb3ea3de 219/* A wrapper for the execlp function. Flushes the accumulated
220 profiling data, so that they are not lost. */
ded3d3f8 221
222int
223__gcov_execlp (const char *path, char *arg, ...)
224{
225 va_list ap, aq;
226 unsigned i, length;
227 char **args;
228
229 __gcov_flush ();
230
231 va_start (ap, arg);
232 va_copy (aq, ap);
233
234 length = 2;
235 while (va_arg (ap, char *))
236 length++;
237 va_end (ap);
238
239 args = (char **) alloca (length * sizeof (void *));
240 args[0] = arg;
241 for (i = 1; i < length; i++)
242 args[i] = va_arg (aq, char *);
243 va_end (aq);
244
245 return execvp (path, args);
246}
247#endif
248
249#ifdef L_gcov_execle
cb3ea3de 250/* A wrapper for the execle function. Flushes the accumulated
251 profiling data, so that they are not lost. */
ded3d3f8 252
253int
254__gcov_execle (const char *path, char *arg, ...)
255{
256 va_list ap, aq;
257 unsigned i, length;
258 char **args;
259 char **envp;
260
261 __gcov_flush ();
262
263 va_start (ap, arg);
264 va_copy (aq, ap);
265
266 length = 2;
267 while (va_arg (ap, char *))
268 length++;
269 va_end (ap);
270
271 args = (char **) alloca (length * sizeof (void *));
272 args[0] = arg;
273 for (i = 1; i < length; i++)
274 args[i] = va_arg (aq, char *);
275 envp = va_arg (aq, char **);
276 va_end (aq);
277
278 return execve (path, args, envp);
279}
280#endif
281
282#ifdef L_gcov_execv
cb3ea3de 283/* A wrapper for the execv function. Flushes the accumulated
284 profiling data, so that they are not lost. */
ded3d3f8 285
286int
287__gcov_execv (const char *path, char *const argv[])
288{
289 __gcov_flush ();
290 return execv (path, argv);
291}
292#endif
293
294#ifdef L_gcov_execvp
cb3ea3de 295/* A wrapper for the execvp function. Flushes the accumulated
296 profiling data, so that they are not lost. */
ded3d3f8 297
298int
299__gcov_execvp (const char *path, char *const argv[])
300{
301 __gcov_flush ();
302 return execvp (path, argv);
303}
304#endif
305
306#ifdef L_gcov_execve
cb3ea3de 307/* A wrapper for the execve function. Flushes the accumulated
308 profiling data, so that they are not lost. */
ded3d3f8 309
310int
311__gcov_execve (const char *path, char *const argv[], char *const envp[])
312{
313 __gcov_flush ();
314 return execve (path, argv, envp);
315}
316#endif
317#endif /* inhibit_libc */