OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [gcov-io.c] - Blame information for rev 728

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 684 jeremybenn
/* File format for coverage information
2
   Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007,
3
   2008  Free Software Foundation, Inc.
4
   Contributed by Bob Manson <manson@cygnus.com>.
5
   Completely remangled by Nathan Sidwell <nathan@codesourcery.com>.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 3, or (at your option) any later
12
version.
13
 
14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15
WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
for more details.
18
 
19
Under Section 7 of GPL version 3, you are granted additional
20
permissions described in the GCC Runtime Library Exception, version
21
3.1, as published by the Free Software Foundation.
22
 
23
You should have received a copy of the GNU General Public License and
24
a copy of the GCC Runtime Library Exception along with this program;
25
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
26
<http://www.gnu.org/licenses/>.  */
27
 
28
/* Routines declared in gcov-io.h.  This file should be #included by
29
   another source file, after having #included gcov-io.h.  */
30
 
31
#if !IN_GCOV
32
static void gcov_write_block (unsigned);
33
static gcov_unsigned_t *gcov_write_words (unsigned);
34
#endif
35
static const gcov_unsigned_t *gcov_read_words (unsigned);
36
#if !IN_LIBGCOV
37
static void gcov_allocate (unsigned);
38
#endif
39
 
40
static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
41
{
42
#if !IN_LIBGCOV
43
  if (gcov_var.endian)
44
    {
45
      value = (value >> 16) | (value << 16);
46
      value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff);
47
    }
48
#endif
49
  return value;
50
}
51
 
52
/* Open a gcov file. NAME is the name of the file to open and MODE
53
   indicates whether a new file should be created, or an existing file
54
   opened. If MODE is >= 0 an existing file will be opened, if
55
   possible, and if MODE is <= 0, a new file will be created. Use
56
   MODE=0 to attempt to reopen an existing file and then fall back on
57
   creating a new one.  If MODE < 0, the file will be opened in
58
   read-only mode.  Otherwise it will be opened for modification.
59
   Return zero on failure, >0 on opening an existing file and <0 on
60
   creating a new one.  */
61
 
62
GCOV_LINKAGE int
63
#if IN_LIBGCOV
64
gcov_open (const char *name)
65
#else
66
gcov_open (const char *name, int mode)
67
#endif
68
{
69
#if IN_LIBGCOV
70
  const int mode = 0;
71
#endif
72
#if GCOV_LOCKED
73
  struct flock s_flock;
74
  int fd;
75
 
76
  s_flock.l_whence = SEEK_SET;
77
  s_flock.l_start = 0;
78
  s_flock.l_len = 0; /* Until EOF.  */
79
  s_flock.l_pid = getpid ();
80
#endif
81
 
82
  gcc_assert (!gcov_var.file);
83
  gcov_var.start = 0;
84
  gcov_var.offset = gcov_var.length = 0;
85
  gcov_var.overread = -1u;
86
  gcov_var.error = 0;
87
#if !IN_LIBGCOV
88
  gcov_var.endian = 0;
89
#endif
90
#if GCOV_LOCKED
91
  if (mode > 0)
92
    {
93
      /* Read-only mode - acquire a read-lock.  */
94
      s_flock.l_type = F_RDLCK;
95
      fd = open (name, O_RDONLY);
96
    }
97
  else
98
    {
99
      /* Write mode - acquire a write-lock.  */
100
      s_flock.l_type = F_WRLCK;
101
      fd = open (name, O_RDWR | O_CREAT, 0666);
102
    }
103
  if (fd < 0)
104
    return 0;
105
 
106
  while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR)
107
    continue;
108
 
109
  gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b");
110
 
111
  if (!gcov_var.file)
112
    {
113
      close (fd);
114
      return 0;
115
    }
116
 
117
  if (mode > 0)
118
    gcov_var.mode = 1;
119
  else if (mode == 0)
120
    {
121
      struct stat st;
122
 
123
      if (fstat (fd, &st) < 0)
124
        {
125
          fclose (gcov_var.file);
126
          gcov_var.file = 0;
127
          return 0;
128
        }
129
      if (st.st_size != 0)
130
        gcov_var.mode = 1;
131
      else
132
        gcov_var.mode = mode * 2 + 1;
133
    }
134
  else
135
    gcov_var.mode = mode * 2 + 1;
136
#else
137
  if (mode >= 0)
138
    gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b");
139
 
140
  if (gcov_var.file)
141
    gcov_var.mode = 1;
142
  else if (mode <= 0)
143
    {
144
      gcov_var.file = fopen (name, "w+b");
145
      if (gcov_var.file)
146
        gcov_var.mode = mode * 2 + 1;
147
    }
148
  if (!gcov_var.file)
149
    return 0;
150
#endif
151
 
152
  setbuf (gcov_var.file, (char *)0);
153
 
154
  return 1;
155
}
156
 
157
/* Close the current gcov file. Flushes data to disk. Returns nonzero
158
   on failure or error flag set.  */
159
 
160
GCOV_LINKAGE int
161
gcov_close (void)
162
{
163
  if (gcov_var.file)
164
    {
165
#if !IN_GCOV
166
      if (gcov_var.offset && gcov_var.mode < 0)
167
        gcov_write_block (gcov_var.offset);
168
#endif
169
      fclose (gcov_var.file);
170
      gcov_var.file = 0;
171
      gcov_var.length = 0;
172
    }
173
#if !IN_LIBGCOV
174
  free (gcov_var.buffer);
175
  gcov_var.alloc = 0;
176
  gcov_var.buffer = 0;
177
#endif
178
  gcov_var.mode = 0;
179
  return gcov_var.error;
180
}
181
 
182
#if !IN_LIBGCOV
183
/* Check if MAGIC is EXPECTED. Use it to determine endianness of the
184
   file. Returns +1 for same endian, -1 for other endian and zero for
185
   not EXPECTED.  */
186
 
187
GCOV_LINKAGE int
188
gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected)
189
{
190
  if (magic == expected)
191
    return 1;
192
  magic = (magic >> 16) | (magic << 16);
193
  magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff);
194
  if (magic == expected)
195
    {
196
      gcov_var.endian = 1;
197
      return -1;
198
    }
199
  return 0;
200
}
201
#endif
202
 
203
#if !IN_LIBGCOV
204
static void
205
gcov_allocate (unsigned length)
206
{
207
  size_t new_size = gcov_var.alloc;
208
 
209
  if (!new_size)
210
    new_size = GCOV_BLOCK_SIZE;
211
  new_size += length;
212
  new_size *= 2;
213
 
214
  gcov_var.alloc = new_size;
215
  gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2);
216
}
217
#endif
218
 
219
#if !IN_GCOV
220
/* Write out the current block, if needs be.  */
221
 
222
static void
223
gcov_write_block (unsigned size)
224
{
225
  if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
226
    gcov_var.error = 1;
227
  gcov_var.start += size;
228
  gcov_var.offset -= size;
229
}
230
 
231
/* Allocate space to write BYTES bytes to the gcov file. Return a
232
   pointer to those bytes, or NULL on failure.  */
233
 
234
static gcov_unsigned_t *
235
gcov_write_words (unsigned words)
236
{
237
  gcov_unsigned_t *result;
238
 
239
  gcc_assert (gcov_var.mode < 0);
240
#if IN_LIBGCOV
241
  if (gcov_var.offset >= GCOV_BLOCK_SIZE)
242
    {
243
      gcov_write_block (GCOV_BLOCK_SIZE);
244
      if (gcov_var.offset)
245
        {
246
          gcc_assert (gcov_var.offset == 1);
247
          memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
248
        }
249
    }
250
#else
251
  if (gcov_var.offset + words > gcov_var.alloc)
252
    gcov_allocate (gcov_var.offset + words);
253
#endif
254
  result = &gcov_var.buffer[gcov_var.offset];
255
  gcov_var.offset += words;
256
 
257
  return result;
258
}
259
 
260
/* Write unsigned VALUE to coverage file.  Sets error flag
261
   appropriately.  */
262
 
263
GCOV_LINKAGE void
264
gcov_write_unsigned (gcov_unsigned_t value)
265
{
266
  gcov_unsigned_t *buffer = gcov_write_words (1);
267
 
268
  buffer[0] = value;
269
}
270
 
271
/* Write counter VALUE to coverage file.  Sets error flag
272
   appropriately.  */
273
 
274
#if IN_LIBGCOV
275
GCOV_LINKAGE void
276
gcov_write_counter (gcov_type value)
277
{
278
  gcov_unsigned_t *buffer = gcov_write_words (2);
279
 
280
  buffer[0] = (gcov_unsigned_t) value;
281
  if (sizeof (value) > sizeof (gcov_unsigned_t))
282
    buffer[1] = (gcov_unsigned_t) (value >> 32);
283
  else
284
    buffer[1] = 0;
285
}
286
#endif /* IN_LIBGCOV */
287
 
288
#if !IN_LIBGCOV
289
/* Write STRING to coverage file.  Sets error flag on file
290
   error, overflow flag on overflow */
291
 
292
GCOV_LINKAGE void
293
gcov_write_string (const char *string)
294
{
295
  unsigned length = 0;
296
  unsigned alloc = 0;
297
  gcov_unsigned_t *buffer;
298
 
299
  if (string)
300
    {
301
      length = strlen (string);
302
      alloc = (length + 4) >> 2;
303
    }
304
 
305
  buffer = gcov_write_words (1 + alloc);
306
 
307
  buffer[0] = alloc;
308
  buffer[alloc] = 0;
309
  memcpy (&buffer[1], string, length);
310
}
311
#endif
312
 
313
#if !IN_LIBGCOV
314
/* Write a tag TAG and reserve space for the record length. Return a
315
   value to be used for gcov_write_length.  */
316
 
317
GCOV_LINKAGE gcov_position_t
318
gcov_write_tag (gcov_unsigned_t tag)
319
{
320
  gcov_position_t result = gcov_var.start + gcov_var.offset;
321
  gcov_unsigned_t *buffer = gcov_write_words (2);
322
 
323
  buffer[0] = tag;
324
  buffer[1] = 0;
325
 
326
  return result;
327
}
328
 
329
/* Write a record length using POSITION, which was returned by
330
   gcov_write_tag.  The current file position is the end of the
331
   record, and is restored before returning.  Returns nonzero on
332
   overflow.  */
333
 
334
GCOV_LINKAGE void
335
gcov_write_length (gcov_position_t position)
336
{
337
  unsigned offset;
338
  gcov_unsigned_t length;
339
  gcov_unsigned_t *buffer;
340
 
341
  gcc_assert (gcov_var.mode < 0);
342
  gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset);
343
  gcc_assert (position >= gcov_var.start);
344
  offset = position - gcov_var.start;
345
  length = gcov_var.offset - offset - 2;
346
  buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset];
347
  buffer[1] = length;
348
  if (gcov_var.offset >= GCOV_BLOCK_SIZE)
349
    gcov_write_block (gcov_var.offset);
350
}
351
 
352
#else /* IN_LIBGCOV */
353
 
354
/* Write a tag TAG and length LENGTH.  */
355
 
356
GCOV_LINKAGE void
357
gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
358
{
359
  gcov_unsigned_t *buffer = gcov_write_words (2);
360
 
361
  buffer[0] = tag;
362
  buffer[1] = length;
363
}
364
 
365
/* Write a summary structure to the gcov file.  Return nonzero on
366
   overflow.  */
367
 
368
GCOV_LINKAGE void
369
gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
370
{
371
  unsigned ix;
372
  const struct gcov_ctr_summary *csum;
373
 
374
  gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
375
  gcov_write_unsigned (summary->checksum);
376
  for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
377
    {
378
      gcov_write_unsigned (csum->num);
379
      gcov_write_unsigned (csum->runs);
380
      gcov_write_counter (csum->sum_all);
381
      gcov_write_counter (csum->run_max);
382
      gcov_write_counter (csum->sum_max);
383
    }
384
}
385
#endif /* IN_LIBGCOV */
386
 
387
#endif /*!IN_GCOV */
388
 
389
/* Return a pointer to read BYTES bytes from the gcov file. Returns
390
   NULL on failure (read past EOF).  */
391
 
392
static const gcov_unsigned_t *
393
gcov_read_words (unsigned words)
394
{
395
  const gcov_unsigned_t *result;
396
  unsigned excess = gcov_var.length - gcov_var.offset;
397
 
398
  gcc_assert (gcov_var.mode > 0);
399
  if (excess < words)
400
    {
401
      gcov_var.start += gcov_var.offset;
402
#if IN_LIBGCOV
403
      if (excess)
404
        {
405
          gcc_assert (excess == 1);
406
          memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
407
        }
408
#else
409
      memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4);
410
#endif
411
      gcov_var.offset = 0;
412
      gcov_var.length = excess;
413
#if IN_LIBGCOV
414
      gcc_assert (!gcov_var.length || gcov_var.length == 1);
415
      excess = GCOV_BLOCK_SIZE;
416
#else
417
      if (gcov_var.length + words > gcov_var.alloc)
418
        gcov_allocate (gcov_var.length + words);
419
      excess = gcov_var.alloc - gcov_var.length;
420
#endif
421
      excess = fread (gcov_var.buffer + gcov_var.length,
422
                      1, excess << 2, gcov_var.file) >> 2;
423
      gcov_var.length += excess;
424
      if (gcov_var.length < words)
425
        {
426
          gcov_var.overread += words - gcov_var.length;
427
          gcov_var.length = 0;
428
          return 0;
429
        }
430
    }
431
  result = &gcov_var.buffer[gcov_var.offset];
432
  gcov_var.offset += words;
433
  return result;
434
}
435
 
436
/* Read unsigned value from a coverage file. Sets error flag on file
437
   error, overflow flag on overflow */
438
 
439
GCOV_LINKAGE gcov_unsigned_t
440
gcov_read_unsigned (void)
441
{
442
  gcov_unsigned_t value;
443
  const gcov_unsigned_t *buffer = gcov_read_words (1);
444
 
445
  if (!buffer)
446
    return 0;
447
  value = from_file (buffer[0]);
448
  return value;
449
}
450
 
451
/* Read counter value from a coverage file. Sets error flag on file
452
   error, overflow flag on overflow */
453
 
454
GCOV_LINKAGE gcov_type
455
gcov_read_counter (void)
456
{
457
  gcov_type value;
458
  const gcov_unsigned_t *buffer = gcov_read_words (2);
459
 
460
  if (!buffer)
461
    return 0;
462
  value = from_file (buffer[0]);
463
  if (sizeof (value) > sizeof (gcov_unsigned_t))
464
    value |= ((gcov_type) from_file (buffer[1])) << 32;
465
  else if (buffer[1])
466
    gcov_var.error = -1;
467
 
468
  return value;
469
}
470
 
471
/* Read string from coverage file. Returns a pointer to a static
472
   buffer, or NULL on empty string. You must copy the string before
473
   calling another gcov function.  */
474
 
475
#if !IN_LIBGCOV
476
GCOV_LINKAGE const char *
477
gcov_read_string (void)
478
{
479
  unsigned length = gcov_read_unsigned ();
480
 
481
  if (!length)
482
    return 0;
483
 
484
  return (const char *) gcov_read_words (length);
485
}
486
#endif
487
 
488
GCOV_LINKAGE void
489
gcov_read_summary (struct gcov_summary *summary)
490
{
491
  unsigned ix;
492
  struct gcov_ctr_summary *csum;
493
 
494
  summary->checksum = gcov_read_unsigned ();
495
  for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
496
    {
497
      csum->num = gcov_read_unsigned ();
498
      csum->runs = gcov_read_unsigned ();
499
      csum->sum_all = gcov_read_counter ();
500
      csum->run_max = gcov_read_counter ();
501
      csum->sum_max = gcov_read_counter ();
502
    }
503
}
504
 
505
#if !IN_LIBGCOV
506
/* Reset to a known position.  BASE should have been obtained from
507
   gcov_position, LENGTH should be a record length.  */
508
 
509
GCOV_LINKAGE void
510
gcov_sync (gcov_position_t base, gcov_unsigned_t length)
511
{
512
  gcc_assert (gcov_var.mode > 0);
513
  base += length;
514
  if (base - gcov_var.start <= gcov_var.length)
515
    gcov_var.offset = base - gcov_var.start;
516
  else
517
    {
518
      gcov_var.offset = gcov_var.length = 0;
519
      fseek (gcov_var.file, base << 2, SEEK_SET);
520
      gcov_var.start = ftell (gcov_var.file) >> 2;
521
    }
522
}
523
#endif
524
 
525
#if IN_LIBGCOV
526
/* Move to a given position in a gcov file.  */
527
 
528
GCOV_LINKAGE void
529
gcov_seek (gcov_position_t base)
530
{
531
  gcc_assert (gcov_var.mode < 0);
532
  if (gcov_var.offset)
533
    gcov_write_block (gcov_var.offset);
534
  fseek (gcov_var.file, base << 2, SEEK_SET);
535
  gcov_var.start = ftell (gcov_var.file) >> 2;
536
}
537
#endif
538
 
539
#if IN_GCOV > 0
540
/* Return the modification time of the current gcov file.  */
541
 
542
GCOV_LINKAGE time_t
543
gcov_time (void)
544
{
545
  struct stat status;
546
 
547
  if (fstat (fileno (gcov_var.file), &status))
548
    return 0;
549
  else
550
    return status.st_mtime;
551
}
552
#endif /* IN_GCOV */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.