]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/libgcov-interface.c
Fix PR63190
[thirdparty/gcc.git] / libgcc / libgcov-interface.c
CommitLineData
ded3d3f8 1/* Routines required for instrumenting a program. */
2/* Compile this one with gcc. */
f9fb6ba0 3/* Copyright (C) 1989-2014 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
46/* Some functions we want to bind in this dynamic object, but have an
47 overridable global alias. */
48#define STRONG_ALIAS(src,dst) \
49 extern __typeof (src) dst __attribute__((alias (#src)))
50
859fa1a9 51extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
cb3ea3de 52extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
ded3d3f8 53
54#ifdef L_gcov_flush
ded3d3f8 55#ifdef __GTHREAD_MUTEX_INIT
cb3ea3de 56__gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
ded3d3f8 57#define init_mx_once()
58#else
cb3ea3de 59__gthread_mutex_t __gcov_flush_mx;
ded3d3f8 60
61static void
62init_mx (void)
63{
64 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
65}
cb3ea3de 66
ded3d3f8 67static void
68init_mx_once (void)
69{
70 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
71 __gthread_once (&once, init_mx);
72}
73#endif
74
75/* Called before fork or exec - write out profile information gathered so
76 far and reset it to zero. This avoids duplication or loss of the
77 profile information gathered so far. */
78
79void
80__gcov_flush (void)
81{
82 init_mx_once ();
83 __gthread_mutex_lock (&__gcov_flush_mx);
84
859fa1a9 85 __gcov_dump_one (&__gcov_root);
b12d2330 86 __gcov_reset_int ();
ded3d3f8 87
88 __gthread_mutex_unlock (&__gcov_flush_mx);
89}
90
91#endif /* L_gcov_flush */
92
93#ifdef L_gcov_reset
94
859fa1a9 95/* Reset all counters to zero. */
96
97static void
98gcov_clear (const struct gcov_info *list)
99{
100 const struct gcov_info *gi_ptr;
101
102 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
103 {
104 unsigned f_ix;
105
106 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
107 {
108 unsigned t_ix;
109 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
110
111 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
112 continue;
113 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
114 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
115 {
116 if (!gi_ptr->merge[t_ix])
117 continue;
118
119 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
120 ci_ptr++;
121 }
122 }
123 }
124}
125
ded3d3f8 126/* Function that can be called from application to reset counters to zero,
127 in order to collect profile in region of interest. */
128
129void
b12d2330 130__gcov_reset_int (void)
ded3d3f8 131{
859fa1a9 132 gcov_clear (__gcov_root.list);
133 __gcov_root.dumped = 0;
ded3d3f8 134}
135
b12d2330 136STRONG_ALIAS (__gcov_reset_int, __gcov_reset);
137
ded3d3f8 138#endif /* L_gcov_reset */
139
140#ifdef L_gcov_dump
ded3d3f8 141/* Function that can be called from application to write profile collected
142 so far, in order to collect profile in region of interest. */
143
144void
145__gcov_dump (void)
146{
859fa1a9 147 __gcov_dump_one (&__gcov_root);
ded3d3f8 148}
149
150#endif /* L_gcov_dump */
151
ded3d3f8 152#ifdef L_gcov_fork
153/* A wrapper for the fork function. Flushes the accumulated profiling data, so
154 that they are not counted twice. */
155
156pid_t
157__gcov_fork (void)
158{
159 pid_t pid;
ded3d3f8 160 __gcov_flush ();
161 pid = fork ();
162 if (pid == 0)
163 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
164 return pid;
165}
166#endif
167
168#ifdef L_gcov_execl
169/* A wrapper for the execl function. Flushes the accumulated profiling data, so
170 that they are not lost. */
171
172int
173__gcov_execl (const char *path, char *arg, ...)
174{
175 va_list ap, aq;
176 unsigned i, length;
177 char **args;
178
179 __gcov_flush ();
180
181 va_start (ap, arg);
182 va_copy (aq, ap);
183
184 length = 2;
185 while (va_arg (ap, char *))
186 length++;
187 va_end (ap);
188
189 args = (char **) alloca (length * sizeof (void *));
190 args[0] = arg;
191 for (i = 1; i < length; i++)
192 args[i] = va_arg (aq, char *);
193 va_end (aq);
194
195 return execv (path, args);
196}
197#endif
198
199#ifdef L_gcov_execlp
cb3ea3de 200/* A wrapper for the execlp function. Flushes the accumulated
201 profiling data, so that they are not lost. */
ded3d3f8 202
203int
204__gcov_execlp (const char *path, char *arg, ...)
205{
206 va_list ap, aq;
207 unsigned i, length;
208 char **args;
209
210 __gcov_flush ();
211
212 va_start (ap, arg);
213 va_copy (aq, ap);
214
215 length = 2;
216 while (va_arg (ap, char *))
217 length++;
218 va_end (ap);
219
220 args = (char **) alloca (length * sizeof (void *));
221 args[0] = arg;
222 for (i = 1; i < length; i++)
223 args[i] = va_arg (aq, char *);
224 va_end (aq);
225
226 return execvp (path, args);
227}
228#endif
229
230#ifdef L_gcov_execle
cb3ea3de 231/* A wrapper for the execle function. Flushes the accumulated
232 profiling data, so that they are not lost. */
ded3d3f8 233
234int
235__gcov_execle (const char *path, char *arg, ...)
236{
237 va_list ap, aq;
238 unsigned i, length;
239 char **args;
240 char **envp;
241
242 __gcov_flush ();
243
244 va_start (ap, arg);
245 va_copy (aq, ap);
246
247 length = 2;
248 while (va_arg (ap, char *))
249 length++;
250 va_end (ap);
251
252 args = (char **) alloca (length * sizeof (void *));
253 args[0] = arg;
254 for (i = 1; i < length; i++)
255 args[i] = va_arg (aq, char *);
256 envp = va_arg (aq, char **);
257 va_end (aq);
258
259 return execve (path, args, envp);
260}
261#endif
262
263#ifdef L_gcov_execv
cb3ea3de 264/* A wrapper for the execv function. Flushes the accumulated
265 profiling data, so that they are not lost. */
ded3d3f8 266
267int
268__gcov_execv (const char *path, char *const argv[])
269{
270 __gcov_flush ();
271 return execv (path, argv);
272}
273#endif
274
275#ifdef L_gcov_execvp
cb3ea3de 276/* A wrapper for the execvp function. Flushes the accumulated
277 profiling data, so that they are not lost. */
ded3d3f8 278
279int
280__gcov_execvp (const char *path, char *const argv[])
281{
282 __gcov_flush ();
283 return execvp (path, argv);
284}
285#endif
286
287#ifdef L_gcov_execve
cb3ea3de 288/* A wrapper for the execve function. Flushes the accumulated
289 profiling data, so that they are not lost. */
ded3d3f8 290
291int
292__gcov_execve (const char *path, char *const argv[], char *const envp[])
293{
294 __gcov_flush ();
295 return execve (path, argv, envp);
296}
297#endif
298#endif /* inhibit_libc */