Home | History | Annotate | Line # | Download | only in libgcc
libgcov-interface.c revision 1.1.1.1.4.2
      1          1.1     mrg /* Routines required for instrumenting a program.  */
      2          1.1     mrg /* Compile this one with gcc.  */
      3  1.1.1.1.4.2  martin /* Copyright (C) 1989-2017 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