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