Home | History | Annotate | Download | only in gcov-src
      1 /* Routines required for instrumenting a program.  */
      2 /* Compile this one with gcc.  */
      3 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
      4 
      5 This file is part of GCC.
      6 
      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
     10 version.
     11 
     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
     15 for more details.
     16 
     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.
     20 
     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/>.  */
     25 
     26 
     27 /* A utility function for outputing errors.  */
     28 
     29 static int __attribute__((format(printf, 1, 2)))
     30 gcov_error (const char *fmt, ...)
     31 {
     32   int ret;
     33   va_list argp;
     34   va_start (argp, fmt);
     35   ret = vprintk (fmt, argp);
     36   va_end (argp);
     37   return ret;
     38 }
     39 
     40 static void
     41 allocate_filename_struct (struct gcov_filename_aux *gf)
     42 {
     43   const char *gcov_prefix;
     44   int gcov_prefix_strip = 0;
     45   size_t prefix_length = 0;
     46   char *gi_filename_up;
     47 
     48   /* Allocate and initialize the filename scratch space plus one.  */
     49   gi_filename = (char *) xmalloc (prefix_length + gcov_max_filename + 2);
     50   if (prefix_length)
     51     memcpy (gi_filename, gcov_prefix, prefix_length);
     52   gi_filename_up = gi_filename + prefix_length;
     53 
     54   gf->gi_filename_up = gi_filename_up;
     55   gf->prefix_length = prefix_length;
     56   gf->gcov_prefix_strip = gcov_prefix_strip;
     57 }
     58 
     59 static int
     60 gcov_open_by_filename (char *gi_filename)
     61 {
     62   gcov_open (gi_filename);
     63   return 0;
     64 }
     65 
     66 
     67 /* Strip GCOV_PREFIX_STRIP levels of leading '/' from FILENAME and
     68    put the result into GI_FILENAME_UP.  */
     69 
     70 static void
     71 gcov_strip_leading_dirs (int prefix_length, int gcov_prefix_strip,
     72       			 const char *filename, char *gi_filename_up)
     73 {
     74   strcpy (gi_filename_up, filename);
     75 }
     76 
     77 /* Current virual gcda file. This is for kernel use only.  */
     78 gcov_kernel_vfile *gcov_current_file;
     79 
     80 /* Set current virutal gcda file. It needs to be set before dumping
     81    profile data.  */
     82 
     83 void
     84 gcov_set_vfile (gcov_kernel_vfile *file)
     85 {
     86   gcov_current_file = file;
     87 }
     88 
     89 /* File fclose operation in kernel mode.  */
     90 
     91 int
     92 kernel_file_fclose (gcov_kernel_vfile *fp)
     93 {
     94   return 0;
     95 }
     96 
     97 /* File ftell operation in kernel mode. It currently should not
     98    be called.  */
     99 
    100 long
    101 kernel_file_ftell (gcov_kernel_vfile *fp)
    102 {
    103   return 0;
    104 }
    105 
    106 /* File fseek operation in kernel mode. It should only be called
    107    with OFFSET==0 and WHENCE==0 to a freshly opened file.  */
    108 
    109 int
    110 kernel_file_fseek (gcov_kernel_vfile *fp, long offset, int whence)
    111 {
    112   gcc_assert (offset == 0 && whence == 0 && fp->count == 0);
    113   return 0;
    114 }
    115 
    116 /* File ftruncate operation in kernel mode. It currently should not
    117    be called.  */
    118 
    119 int
    120 kernel_file_ftruncate (gcov_kernel_vfile *fp, off_t value)
    121 {
    122   gcc_assert (0);  /* should not reach here */
    123   return 0;
    124 }
    125 
    126 /* File fread operation in kernel mode. It currently should not
    127    be called.  */
    128 
    129 int
    130 kernel_file_fread (void *ptr, size_t size, size_t nitems,
    131                   gcov_kernel_vfile *fp)
    132 {
    133   gcc_assert (0);  /* should not reach here */
    134   return 0;
    135 }
    136 
    137 /* File fwrite operation in kernel mode. It outputs the data
    138    to a buffer in the virual file.  */
    139 
    140 int
    141 kernel_file_fwrite (const void *ptr, size_t size,
    142                    size_t nitems, gcov_kernel_vfile *fp)
    143 {
    144   char *vbuf;
    145   unsigned vsize, vpos;
    146   unsigned len;
    147 
    148   if (!fp) return 0;
    149 
    150   vbuf = fp->buf;
    151   vsize = fp->size;
    152   vpos = fp->count;
    153 
    154 
    155   if (vsize < vpos)
    156     {
    157       printk (KERN_ERR
    158          "GCOV_KERNEL: something wrong in file %s: vbuf=%p vsize=%u"
    159          " vpos=%u\n",
    160           fp->info->filename, vbuf, vsize, vpos);
    161       return 0;
    162     }
    163 
    164   len = vsize - vpos;
    165   len /= size;
    166 
    167   /* Increase the virtual file size if it is not suffcient. */
    168   while (len < nitems)
    169     {
    170       vsize *= 2;
    171       len = vsize - vpos;
    172       len /= size;
    173     }
    174 
    175   if (vsize != fp->size)
    176     {
    177       vbuf = fp->buf = (char *) gcov_realloc_file_buf(vsize, vpos);
    178       fp->size = vsize;
    179     }
    180 
    181   if (len > nitems)
    182 	  len = nitems;
    183 
    184   memcpy (vbuf+vpos, ptr, size*len);
    185   fp->count += len*size;
    186 
    187   if (len != nitems)
    188     printk (KERN_ERR
    189         "GCOV_KERNEL: something wrong in file %s: size=%lu nitems=%lu"
    190         " len=%d vsize=%u vpos=%u \n",
    191         fp->info->filename, size, nitems, len, vsize, vpos);
    192   return len;
    193 }
    194 
    195 /* File fileno operation in kernel mode. It currently should not
    196    be called.  */
    197 
    198 int
    199 kernel_file_fileno (gcov_kernel_vfile *fp)
    200 {
    201   gcc_assert (0);  /* should not reach here */
    202   return 0;
    203 }
    204