1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2023 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_reset (void) {}
36 void __gcov_dump (void) {}
41 extern __gthread_mutex_t __gcov_mx ATTRIBUTE_HIDDEN
;
43 #ifdef L_gcov_lock_unlock
44 #ifdef __GTHREAD_MUTEX_INIT
45 __gthread_mutex_t __gcov_mx
= __GTHREAD_MUTEX_INIT
;
46 #define init_mx_once()
48 __gthread_mutex_t __gcov_mx
;
53 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx
);
59 static __gthread_once_t once
= __GTHREAD_ONCE_INIT
;
60 __gthread_once (&once
, init_mx
);
64 /* Lock critical section for __gcov_dump and __gcov_reset functions. */
70 __gthread_mutex_lock (&__gcov_mx
);
73 /* Unlock critical section for __gcov_dump and __gcov_reset functions. */
78 __gthread_mutex_unlock (&__gcov_mx
);
84 /* Reset all counters to zero. */
87 gcov_clear (const struct gcov_info
*list
)
89 const struct gcov_info
*gi_ptr
;
91 for (gi_ptr
= list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
95 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
98 const struct gcov_fn_info
*gfi_ptr
= gi_ptr
->functions
[f_ix
];
100 if (!gfi_ptr
|| gfi_ptr
->key
!= gi_ptr
)
102 const struct gcov_ctr_info
*ci_ptr
= gfi_ptr
->ctrs
;
103 for (t_ix
= 0; t_ix
!= GCOV_COUNTERS
; t_ix
++)
105 if (!gi_ptr
->merge
[t_ix
])
108 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
115 /* Function that can be called from application to reset counters to zero,
116 in order to collect profile in region of interest. */
119 __gcov_reset_int (void)
121 struct gcov_root
*root
;
123 /* If we're compatible with the master, iterate over everything,
124 otherise just do us. */
125 for (root
= __gcov_master
.version
== GCOV_VERSION
126 ? __gcov_master
.root
: &__gcov_root
; root
; root
= root
->next
)
128 gcov_clear (root
->list
);
133 /* Exported function __gcov_reset. */
145 #endif /* L_gcov_reset */
148 /* Function that can be called from application to write profile collected
149 so far, in order to collect profile in region of interest. */
152 __gcov_dump_int (void)
154 struct gcov_root
*root
;
156 /* If we're compatible with the master, iterate over everything,
157 otherise just do us. */
158 for (root
= __gcov_master
.version
== GCOV_VERSION
159 ? __gcov_master
.root
: &__gcov_root
; root
; root
= root
->next
)
160 __gcov_dump_one (root
);
163 /* Exported function __gcov_dump. */
175 #endif /* L_gcov_dump */
178 /* A wrapper for the fork function. We reset counters in the child
179 so that they are not counted twice. */
188 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx
);
189 /* We do not need locking as we are the only thread in the child. */
197 /* A wrapper for the execl function. Flushes the accumulated
198 profiling data, so that they are not lost. */
201 __gcov_execl (const char *path
, char *arg
, ...)
207 /* Dump counters only, they will be lost after exec. */
214 while (va_arg (ap
, char *))
218 args
= (char **) alloca (length
* sizeof (void *));
220 for (i
= 1; i
< length
; i
++)
221 args
[i
] = va_arg (aq
, char *);
224 int ret
= execv (path
, args
);
225 /* We reach this code only when execv fails, reset counter then here. */
232 /* A wrapper for the execlp function. Flushes the accumulated
233 profiling data, so that they are not lost. */
236 __gcov_execlp (const char *path
, char *arg
, ...)
242 /* Dump counters only, they will be lost after exec. */
249 while (va_arg (ap
, char *))
253 args
= (char **) alloca (length
* sizeof (void *));
255 for (i
= 1; i
< length
; i
++)
256 args
[i
] = va_arg (aq
, char *);
259 int ret
= execvp (path
, args
);
260 /* We reach this code only when execv fails, reset counter then here. */
267 /* A wrapper for the execle function. Flushes the accumulated
268 profiling data, so that they are not lost. */
271 __gcov_execle (const char *path
, char *arg
, ...)
278 /* Dump counters only, they will be lost after exec. */
285 while (va_arg (ap
, char *))
289 args
= (char **) alloca (length
* sizeof (void *));
291 for (i
= 1; i
< length
; i
++)
292 args
[i
] = va_arg (aq
, char *);
293 envp
= va_arg (aq
, char **);
296 int ret
= execve (path
, args
, envp
);
297 /* We reach this code only when execv fails, reset counter then here. */
304 /* A wrapper for the execv function. Flushes the accumulated
305 profiling data, so that they are not lost. */
308 __gcov_execv (const char *path
, char *const argv
[])
310 /* Dump counters only, they will be lost after exec. */
312 int ret
= execv (path
, argv
);
313 /* We reach this code only when execv fails, reset counter then here. */
320 /* A wrapper for the execvp function. Flushes the accumulated
321 profiling data, so that they are not lost. */
324 __gcov_execvp (const char *path
, char *const argv
[])
326 /* Dump counters only, they will be lost after exec. */
328 int ret
= execvp (path
, argv
);
329 /* We reach this code only when execv fails, reset counter then here. */
336 /* A wrapper for the execve function. Flushes the accumulated
337 profiling data, so that they are not lost. */
340 __gcov_execve (const char *path
, char *const argv
[], char *const envp
[])
342 /* Dump counters only, they will be lost after exec. */
344 int ret
= execve (path
, argv
, envp
);
345 /* We reach this code only when execv fails, reset counter then here. */
350 #endif /* inhibit_libc */