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