1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2017 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
29 #if defined(inhibit_libc)
32 void __gcov_flush (void) {}
36 void __gcov_reset (void) {}
40 void __gcov_dump (void) {}
45 /* Some functions we want to bind in this dynamic object, but have an
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.*/
50 #define ALIAS_void_fn(src,dst) \
54 extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN
;
55 extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN
;
58 #ifdef __GTHREAD_MUTEX_INIT
59 __gthread_mutex_t __gcov_flush_mx
= __GTHREAD_MUTEX_INIT
;
60 #define init_mx_once()
62 __gthread_mutex_t __gcov_flush_mx
;
67 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx
);
73 static __gthread_once_t once
= __GTHREAD_ONCE_INIT
;
74 __gthread_once (&once
, init_mx
);
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. */
86 __gthread_mutex_lock (&__gcov_flush_mx
);
91 __gthread_mutex_unlock (&__gcov_flush_mx
);
94 #endif /* L_gcov_flush */
98 /* Reset all counters to zero. */
101 gcov_clear (const struct gcov_info
*list
)
103 const struct gcov_info
*gi_ptr
;
105 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
109 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
112 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
114 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
116 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
117 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++)
119 if (!gi_ptr
->merge
[t_ix
])
122 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
129 /* Function that can be called from application to reset counters to zero,
130 in order to collect profile in region of interest. */
133 __gcov_reset_int (void)
135 struct gcov_root
*root
;
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
)
142 gcov_clear (root
->list
);
147 ALIAS_void_fn (__gcov_reset_int
, __gcov_reset
);
149 #endif /* L_gcov_reset */
152 /* Function that can be called from application to write profile collected
153 so far, in order to collect profile in region of interest. */
156 __gcov_dump_int (void)
158 struct gcov_root
*root
;
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
);
167 ALIAS_void_fn (__gcov_dump_int
, __gcov_dump
);
169 #endif /* L_gcov_dump */
172 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
173 that they are not counted twice. */
182 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx
);
188 /* A wrapper for the execl function. Flushes the accumulated
189 profiling data, so that they are not lost. */
192 __gcov_execl (const char *path
, char *arg
, ...)
204 while (va_arg (ap
, char *))
208 args
= (char **) alloca (length
* sizeof (void *));
210 for (i
= 1; i
< length
; i
++)
211 args
[i
] = va_arg (aq
, char *);
214 return execv (path
, args
);
219 /* A wrapper for the execlp function. Flushes the accumulated
220 profiling data, so that they are not lost. */
223 __gcov_execlp (const char *path
, char *arg
, ...)
235 while (va_arg (ap
, char *))
239 args
= (char **) alloca (length
* sizeof (void *));
241 for (i
= 1; i
< length
; i
++)
242 args
[i
] = va_arg (aq
, char *);
245 return execvp (path
, args
);
250 /* A wrapper for the execle function. Flushes the accumulated
251 profiling data, so that they are not lost. */
254 __gcov_execle (const char *path
, char *arg
, ...)
267 while (va_arg (ap
, char *))
271 args
= (char **) alloca (length
* sizeof (void *));
273 for (i
= 1; i
< length
; i
++)
274 args
[i
] = va_arg (aq
, char *);
275 envp
= va_arg (aq
, char **);
278 return execve (path
, args
, envp
);
283 /* A wrapper for the execv function. Flushes the accumulated
284 profiling data, so that they are not lost. */
287 __gcov_execv (const char *path
, char *const argv
[])
290 return execv (path
, argv
);
295 /* A wrapper for the execvp function. Flushes the accumulated
296 profiling data, so that they are not lost. */
299 __gcov_execvp (const char *path
, char *const argv
[])
302 return execvp (path
, argv
);
307 /* A wrapper for the execve function. Flushes the accumulated
308 profiling data, so that they are not lost. */
311 __gcov_execve (const char *path
, char *const argv
[], char *const envp
[])
314 return execve (path
, argv
, envp
);
317 #endif /* inhibit_libc */