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