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