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