1/* Routines required for instrumenting a program. */ 2/* Compile this one with gcc. */ 3/* Copyright (C) 1989-2014 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17Under Section 7 of GPL version 3, you are granted additional 18permissions described in the GCC Runtime Library Exception, version 193.1, as published by the Free Software Foundation. 20 21You should have received a copy of the GNU General Public License and 22a copy of the GCC Runtime Library Exception along with this program; 23see 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 29static int __attribute__((format(printf, 1, 2))) 30gcov_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 40static void 41allocate_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 59static int 60gcov_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 70static void 71gcov_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. */ 78gcov_kernel_vfile *gcov_current_file; 79 80/* Set current virutal gcda file. It needs to be set before dumping 81 profile data. */ 82 83void 84gcov_set_vfile (gcov_kernel_vfile *file) 85{ 86 gcov_current_file = file; 87} 88 89/* File fclose operation in kernel mode. */ 90 91int 92kernel_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 100long 101kernel_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 109int 110kernel_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 119int 120kernel_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 129int 130kernel_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 140int 141kernel_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 198int 199kernel_file_fileno (gcov_kernel_vfile *fp) 200{ 201 gcc_assert (0); /* should not reach here */ 202 return 0; 203} 204