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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [libgcov.c] - Blame information for rev 734

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* Routines required for instrumenting a program.  */
2
/* Compile this one with gcc.  */
3
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4
   2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011
5
   Free Software Foundation, Inc.
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
#include "tconfig.h"
29
#include "tsystem.h"
30
#include "coretypes.h"
31
#include "tm.h"
32
#include "libgcc_tm.h"
33
 
34
#if defined(inhibit_libc)
35
#define IN_LIBGCOV (-1)
36
#else
37
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
38
#include <stdio.h>
39
#define IN_LIBGCOV 1
40
#if defined(L_gcov)
41
#define GCOV_LINKAGE /* nothing */
42
#endif
43
#endif
44
#include "gcov-io.h"
45
 
46
#if defined(inhibit_libc)
47
/* If libc and its header files are not available, provide dummy functions.  */
48
 
49
#ifdef L_gcov
50
void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
51
void __gcov_flush (void) {}
52
#endif
53
 
54
#ifdef L_gcov_merge_add
55
void __gcov_merge_add (gcov_type *counters  __attribute__ ((unused)),
56
                       unsigned n_counters __attribute__ ((unused))) {}
57
#endif
58
 
59
#ifdef L_gcov_merge_single
60
void __gcov_merge_single (gcov_type *counters  __attribute__ ((unused)),
61
                          unsigned n_counters __attribute__ ((unused))) {}
62
#endif
63
 
64
#ifdef L_gcov_merge_delta
65
void __gcov_merge_delta (gcov_type *counters  __attribute__ ((unused)),
66
                         unsigned n_counters __attribute__ ((unused))) {}
67
#endif
68
 
69
#else
70
 
71
#include <string.h>
72
#if GCOV_LOCKED
73
#include <fcntl.h>
74
#include <errno.h>
75
#include <sys/stat.h>
76
#endif
77
 
78
#ifdef L_gcov
79
#include "gcov-io.c"
80
 
81
struct gcov_fn_buffer
82
{
83
  struct gcov_fn_buffer *next;
84
  unsigned fn_ix;
85
  struct gcov_fn_info info;
86
  /* note gcov_fn_info ends in a trailing array.  */
87
};
88
 
89
/* Chain of per-object gcov structures.  */
90
static struct gcov_info *gcov_list;
91
 
92
/* Size of the longest file name. */
93
static size_t gcov_max_filename = 0;
94
 
95
/* Make sure path component of the given FILENAME exists, create
96
   missing directories. FILENAME must be writable.
97
   Returns zero on success, or -1 if an error occurred.  */
98
 
99
static int
100
create_file_directory (char *filename)
101
{
102
#if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
103
  (void) filename;
104
  return -1;
105
#else
106
  char *s;
107
 
108
  s = filename;
109
 
110
  if (HAS_DRIVE_SPEC(s))
111
    s += 2;
112
  if (IS_DIR_SEPARATOR(*s))
113
    ++s;
114
  for (; *s != '\0'; s++)
115
    if (IS_DIR_SEPARATOR(*s))
116
      {
117
        char sep = *s;
118
        *s  = '\0';
119
 
120
        /* Try to make directory if it doesn't already exist.  */
121
        if (access (filename, F_OK) == -1
122
#ifdef TARGET_POSIX_IO
123
            && mkdir (filename, 0755) == -1
124
#else
125
            && mkdir (filename) == -1
126
#endif
127
            /* The directory might have been made by another process.  */
128
            && errno != EEXIST)
129
          {
130
            fprintf (stderr, "profiling:%s:Cannot create directory\n",
131
                     filename);
132
            *s = sep;
133
            return -1;
134
          };
135
 
136
        *s = sep;
137
      };
138
  return 0;
139
#endif
140
}
141
 
142
static struct gcov_fn_buffer *
143
free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
144
              unsigned limit)
145
{
146
  struct gcov_fn_buffer *next;
147
  unsigned ix, n_ctr = 0;
148
 
149
  if (!buffer)
150
    return 0;
151
  next = buffer->next;
152
 
153
  for (ix = 0; ix != limit; ix++)
154
    if (gi_ptr->merge[ix])
155
      free (buffer->info.ctrs[n_ctr++].values);
156
  free (buffer);
157
  return next;
158
}
159
 
160
static struct gcov_fn_buffer **
161
buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
162
                struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
163
{
164
  unsigned n_ctrs = 0, ix = 0;
165
  struct gcov_fn_buffer *fn_buffer;
166
  unsigned len;
167
 
168
  for (ix = GCOV_COUNTERS; ix--;)
169
    if (gi_ptr->merge[ix])
170
      n_ctrs++;
171
 
172
  len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
173
  fn_buffer = (struct gcov_fn_buffer *)malloc (len);
174
 
175
  if (!fn_buffer)
176
    goto fail;
177
 
178
  fn_buffer->next = 0;
179
  fn_buffer->fn_ix = fn_ix;
180
  fn_buffer->info.ident = gcov_read_unsigned ();
181
  fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
182
  fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
183
 
184
  for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
185
    {
186
      gcov_unsigned_t length;
187
      gcov_type *values;
188
 
189
      if (!gi_ptr->merge[ix])
190
        continue;
191
 
192
      if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
193
        {
194
          len = 0;
195
          goto fail;
196
        }
197
 
198
      length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
199
      len = length * sizeof (gcov_type);
200
      values = (gcov_type *)malloc (len);
201
      if (!values)
202
        goto fail;
203
 
204
      fn_buffer->info.ctrs[n_ctrs].num = length;
205
      fn_buffer->info.ctrs[n_ctrs].values = values;
206
 
207
      while (length--)
208
        *values++ = gcov_read_counter ();
209
      n_ctrs++;
210
    }
211
 
212
  *end_ptr = fn_buffer;
213
  return &fn_buffer->next;
214
 
215
 fail:
216
  fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
217
           len ? "cannot allocate" : "counter mismatch", len ? len : ix);
218
 
219
  return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
220
}
221
 
222
/* Add an unsigned value to the current crc */
223
 
224
static gcov_unsigned_t
225
crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
226
{
227
  unsigned ix;
228
 
229
  for (ix = 32; ix--; value <<= 1)
230
    {
231
      unsigned feedback;
232
 
233
      feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
234
      crc32 <<= 1;
235
      crc32 ^= feedback;
236
    }
237
 
238
  return crc32;
239
}
240
 
241
/* Check if VERSION of the info block PTR matches libgcov one.
242
   Return 1 on success, or zero in case of versions mismatch.
243
   If FILENAME is not NULL, its value used for reporting purposes
244
   instead of value from the info block.  */
245
 
246
static int
247
gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
248
              const char *filename)
249
{
250
  if (version != GCOV_VERSION)
251
    {
252
      char v[4], e[4];
253
 
254
      GCOV_UNSIGNED2STRING (v, version);
255
      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
256
 
257
      fprintf (stderr,
258
               "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
259
               filename? filename : ptr->filename, e, v);
260
      return 0;
261
    }
262
  return 1;
263
}
264
 
265
/* Dump the coverage counts. We merge with existing counts when
266
   possible, to avoid growing the .da files ad infinitum. We use this
267
   program's checksum to make sure we only accumulate whole program
268
   statistics to the correct summary. An object file might be embedded
269
   in two separate programs, and we must keep the two program
270
   summaries separate.  */
271
 
272
static void
273
gcov_exit (void)
274
{
275
  struct gcov_info *gi_ptr;
276
  const struct gcov_fn_info *gfi_ptr;
277
  struct gcov_summary this_prg; /* summary for program.  */
278
  struct gcov_summary all_prg;  /* summary for all instances of program.  */
279
  struct gcov_ctr_summary *cs_ptr;
280
  const struct gcov_ctr_info *ci_ptr;
281
  unsigned t_ix;
282
  int f_ix;
283
  gcov_unsigned_t c_num;
284
  const char *gcov_prefix;
285
  int gcov_prefix_strip = 0;
286
  size_t prefix_length;
287
  char *gi_filename, *gi_filename_up;
288
  gcov_unsigned_t crc32 = 0;
289
 
290
  memset (&all_prg, 0, sizeof (all_prg));
291
  /* Find the totals for this execution.  */
292
  memset (&this_prg, 0, sizeof (this_prg));
293
  for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
294
    {
295
      crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
296
      crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
297
 
298
      for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
299
        {
300
          gfi_ptr = gi_ptr->functions[f_ix];
301
 
302
          if (gfi_ptr && gfi_ptr->key != gi_ptr)
303
            gfi_ptr = 0;
304
 
305
          crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
306
          crc32 = crc32_unsigned (crc32,
307
                                  gfi_ptr ? gfi_ptr->lineno_checksum : 0);
308
          if (!gfi_ptr)
309
            continue;
310
 
311
          ci_ptr = gfi_ptr->ctrs;
312
          for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
313
            {
314
              if (!gi_ptr->merge[t_ix])
315
                continue;
316
 
317
              cs_ptr = &this_prg.ctrs[t_ix];
318
              cs_ptr->num += ci_ptr->num;
319
              crc32 = crc32_unsigned (crc32, ci_ptr->num);
320
 
321
              for (c_num = 0; c_num < ci_ptr->num; c_num++)
322
                {
323
                  cs_ptr->sum_all += ci_ptr->values[c_num];
324
                  if (cs_ptr->run_max < ci_ptr->values[c_num])
325
                    cs_ptr->run_max = ci_ptr->values[c_num];
326
                }
327
              ci_ptr++;
328
            }
329
        }
330
    }
331
 
332
  {
333
    /* Check if the level of dirs to strip off specified. */
334
    char *tmp = getenv("GCOV_PREFIX_STRIP");
335
    if (tmp)
336
      {
337
        gcov_prefix_strip = atoi (tmp);
338
        /* Do not consider negative values. */
339
        if (gcov_prefix_strip < 0)
340
          gcov_prefix_strip = 0;
341
      }
342
  }
343
 
344
  /* Get file name relocation prefix.  Non-absolute values are ignored. */
345
  gcov_prefix = getenv("GCOV_PREFIX");
346
  if (gcov_prefix)
347
    {
348
      prefix_length = strlen(gcov_prefix);
349
 
350
      /* Remove an unnecessary trailing '/' */
351
      if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
352
        prefix_length--;
353
    }
354
  else
355
    prefix_length = 0;
356
 
357
  /* If no prefix was specified and a prefix stip, then we assume
358
     relative.  */
359
  if (gcov_prefix_strip != 0 && prefix_length == 0)
360
    {
361
      gcov_prefix = ".";
362
      prefix_length = 1;
363
    }
364
  /* Allocate and initialize the filename scratch space plus one.  */
365
  gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
366
  if (prefix_length)
367
    memcpy (gi_filename, gcov_prefix, prefix_length);
368
  gi_filename_up = gi_filename + prefix_length;
369
 
370
  /* Now merge each file.  */
371
  for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
372
    {
373
      unsigned n_counts;
374
      struct gcov_summary prg; /* summary for this object over all
375
                                  program.  */
376
      struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
377
      int error = 0;
378
      gcov_unsigned_t tag, length;
379
      gcov_position_t summary_pos = 0;
380
      gcov_position_t eof_pos = 0;
381
      const char *fname, *s;
382
      struct gcov_fn_buffer *fn_buffer = 0;
383
      struct gcov_fn_buffer **fn_tail = &fn_buffer;
384
 
385
      fname = gi_ptr->filename;
386
 
387
      /* Avoid to add multiple drive letters into combined path.  */
388
      if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
389
        fname += 2;
390
 
391
      /* Build relocated filename, stripping off leading
392
         directories from the initial filename if requested. */
393
      if (gcov_prefix_strip > 0)
394
        {
395
          int level = 0;
396
          s = fname;
397
          if (IS_DIR_SEPARATOR(*s))
398
            ++s;
399
 
400
          /* Skip selected directory levels. */
401
          for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
402
            if (IS_DIR_SEPARATOR(*s))
403
              {
404
                fname = s;
405
                level++;
406
              }
407
        }
408
 
409
      /* Update complete filename with stripped original. */
410
      if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
411
        {
412
          /* If prefix is given, add directory separator.  */
413
          strcpy (gi_filename_up, "/");
414
          strcpy (gi_filename_up + 1, fname);
415
        }
416
      else
417
        strcpy (gi_filename_up, fname);
418
 
419
      if (!gcov_open (gi_filename))
420
        {
421
          /* Open failed likely due to missed directory.
422
             Create directory and retry to open file. */
423
          if (create_file_directory (gi_filename))
424
            {
425
              fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
426
              continue;
427
            }
428
          if (!gcov_open (gi_filename))
429
            {
430
              fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
431
              continue;
432
            }
433
        }
434
 
435
      tag = gcov_read_unsigned ();
436
      if (tag)
437
        {
438
          /* Merge data from file.  */
439
          if (tag != GCOV_DATA_MAGIC)
440
            {
441
              fprintf (stderr, "profiling:%s:Not a gcov data file\n",
442
                       gi_filename);
443
              goto read_fatal;
444
            }
445
          length = gcov_read_unsigned ();
446
          if (!gcov_version (gi_ptr, length, gi_filename))
447
            goto read_fatal;
448
 
449
          length = gcov_read_unsigned ();
450
          if (length != gi_ptr->stamp)
451
            /* Read from a different compilation. Overwrite the file.  */
452
            goto rewrite;
453
 
454
          /* Look for program summary.  */
455
          for (f_ix = 0;;)
456
            {
457
              struct gcov_summary tmp;
458
 
459
              eof_pos = gcov_position ();
460
              tag = gcov_read_unsigned ();
461
              if (tag != GCOV_TAG_PROGRAM_SUMMARY)
462
                break;
463
 
464
              f_ix--;
465
              length = gcov_read_unsigned ();
466
              if (length != GCOV_TAG_SUMMARY_LENGTH)
467
                goto read_mismatch;
468
              gcov_read_summary (&tmp);
469
              if ((error = gcov_is_error ()))
470
                goto read_error;
471
              if (summary_pos || tmp.checksum != crc32)
472
                goto next_summary;
473
 
474
              for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
475
                if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
476
                  goto next_summary;
477
              prg = tmp;
478
              summary_pos = eof_pos;
479
 
480
            next_summary:;
481
            }
482
 
483
          /* Merge execution counts for each function.  */
484
          for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
485
               f_ix++, tag = gcov_read_unsigned ())
486
            {
487
              gfi_ptr = gi_ptr->functions[f_ix];
488
 
489
              if (tag != GCOV_TAG_FUNCTION)
490
                goto read_mismatch;
491
 
492
              length = gcov_read_unsigned ();
493
              if (!length)
494
                /* This function did not appear in the other program.
495
                   We have nothing to merge.  */
496
                continue;
497
 
498
              if (length != GCOV_TAG_FUNCTION_LENGTH)
499
                goto read_mismatch;
500
 
501
              if (!gfi_ptr || gfi_ptr->key != gi_ptr)
502
                {
503
                  /* This function appears in the other program.  We
504
                     need to buffer the information in order to write
505
                     it back out -- we'll be inserting data before
506
                     this point, so cannot simply keep the data in the
507
                     file.  */
508
                  fn_tail = buffer_fn_data (gi_filename,
509
                                            gi_ptr, fn_tail, f_ix);
510
                  if (!fn_tail)
511
                    goto read_mismatch;
512
                  continue;
513
                }
514
 
515
              length = gcov_read_unsigned ();
516
              if (length != gfi_ptr->ident)
517
                goto read_mismatch;
518
 
519
              length = gcov_read_unsigned ();
520
              if (length != gfi_ptr->lineno_checksum)
521
                goto read_mismatch;
522
 
523
              length = gcov_read_unsigned ();
524
              if (length != gfi_ptr->cfg_checksum)
525
                goto read_mismatch;
526
 
527
              ci_ptr = gfi_ptr->ctrs;
528
              for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
529
                {
530
                  gcov_merge_fn merge = gi_ptr->merge[t_ix];
531
 
532
                  if (!merge)
533
                    continue;
534
 
535
                  tag = gcov_read_unsigned ();
536
                  length = gcov_read_unsigned ();
537
                  if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
538
                      || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
539
                    goto read_mismatch;
540
                  (*merge) (ci_ptr->values, ci_ptr->num);
541
                  ci_ptr++;
542
                }
543
              if ((error = gcov_is_error ()))
544
                goto read_error;
545
            }
546
 
547
          if (tag)
548
            {
549
            read_mismatch:;
550
              fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n",
551
                       gi_filename, f_ix >= 0 ? "function" : "summary",
552
                       f_ix < 0 ? -1 - f_ix : f_ix);
553
              goto read_fatal;
554
            }
555
        }
556
      goto rewrite;
557
 
558
    read_error:;
559
      fprintf (stderr, "profiling:%s:%s merging\n", gi_filename,
560
               error < 0 ? "Overflow": "Error");
561
 
562
      goto read_fatal;
563
 
564
    rewrite:;
565
      gcov_rewrite ();
566
      if (!summary_pos)
567
        {
568
          memset (&prg, 0, sizeof (prg));
569
          summary_pos = eof_pos;
570
        }
571
 
572
      /* Merge the summaries.  */
573
      for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
574
        {
575
          cs_prg = &prg.ctrs[t_ix];
576
          cs_tprg = &this_prg.ctrs[t_ix];
577
          cs_all = &all_prg.ctrs[t_ix];
578
 
579
          if (gi_ptr->merge[t_ix])
580
            {
581
              if (!cs_prg->runs++)
582
                cs_prg->num = cs_tprg->num;
583
              cs_prg->sum_all += cs_tprg->sum_all;
584
              if (cs_prg->run_max < cs_tprg->run_max)
585
                cs_prg->run_max = cs_tprg->run_max;
586
              cs_prg->sum_max += cs_tprg->run_max;
587
            }
588
          else if (cs_prg->runs)
589
            goto read_mismatch;
590
 
591
          if (!cs_all->runs && cs_prg->runs)
592
            memcpy (cs_all, cs_prg, sizeof (*cs_all));
593
          else if (!all_prg.checksum
594
                   && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
595
                   && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
596
            {
597
              fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
598
                       gi_filename, GCOV_LOCKED
599
                       ? "" : " or concurrently updated without locking support");
600
              all_prg.checksum = ~0u;
601
            }
602
        }
603
 
604
      prg.checksum = crc32;
605
 
606
      /* Write out the data.  */
607
      if (!eof_pos)
608
        {
609
          gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
610
          gcov_write_unsigned (gi_ptr->stamp);
611
        }
612
 
613
      if (summary_pos)
614
        gcov_seek (summary_pos);
615
 
616
      /* Generate whole program statistics.  */
617
      gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg);
618
 
619
      if (summary_pos < eof_pos)
620
        gcov_seek (eof_pos);
621
 
622
      /* Write execution counts for each function.  */
623
      for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
624
        {
625
          unsigned buffered = 0;
626
 
627
          if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix)
628
            {
629
              /* Buffered data from another program.  */
630
              buffered = 1;
631
              gfi_ptr = &fn_buffer->info;
632
              length = GCOV_TAG_FUNCTION_LENGTH;
633
            }
634
          else
635
            {
636
              gfi_ptr = gi_ptr->functions[f_ix];
637
              if (gfi_ptr && gfi_ptr->key == gi_ptr)
638
                length = GCOV_TAG_FUNCTION_LENGTH;
639
              else
640
                length = 0;
641
            }
642
 
643
          gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
644
          if (!length)
645
            continue;
646
 
647
          gcov_write_unsigned (gfi_ptr->ident);
648
          gcov_write_unsigned (gfi_ptr->lineno_checksum);
649
          gcov_write_unsigned (gfi_ptr->cfg_checksum);
650
 
651
          ci_ptr = gfi_ptr->ctrs;
652
          for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
653
            {
654
              if (!gi_ptr->merge[t_ix])
655
                continue;
656
 
657
              n_counts = ci_ptr->num;
658
              gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
659
                                     GCOV_TAG_COUNTER_LENGTH (n_counts));
660
              gcov_type *c_ptr = ci_ptr->values;
661
              while (n_counts--)
662
                gcov_write_counter (*c_ptr++);
663
              ci_ptr++;
664
            }
665
          if (buffered)
666
            fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
667
        }
668
 
669
      gcov_write_unsigned (0);
670
 
671
    read_fatal:;
672
      while (fn_buffer)
673
        fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
674
 
675
      if ((error = gcov_close ()))
676
          fprintf (stderr, error  < 0 ?
677
                   "profiling:%s:Overflow writing\n" :
678
                   "profiling:%s:Error writing\n",
679
                   gi_filename);
680
    }
681
}
682
 
683
/* Add a new object file onto the bb chain.  Invoked automatically
684
   when running an object file's global ctors.  */
685
 
686
void
687
__gcov_init (struct gcov_info *info)
688
{
689
  if (!info->version || !info->n_functions)
690
    return;
691
  if (gcov_version (info, info->version, 0))
692
    {
693
      size_t filename_length = strlen(info->filename);
694
 
695
      /* Refresh the longest file name information */
696
      if (filename_length > gcov_max_filename)
697
        gcov_max_filename = filename_length;
698
 
699
      if (!gcov_list)
700
        atexit (gcov_exit);
701
 
702
      info->next = gcov_list;
703
      gcov_list = info;
704
    }
705
  info->version = 0;
706
}
707
 
708
/* Called before fork or exec - write out profile information gathered so
709
   far and reset it to zero.  This avoids duplication or loss of the
710
   profile information gathered so far.  */
711
 
712
void
713
__gcov_flush (void)
714
{
715
  const struct gcov_info *gi_ptr;
716
 
717
  gcov_exit ();
718
  for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
719
    {
720
      unsigned f_ix;
721
 
722
      for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
723
        {
724
          unsigned t_ix;
725
          const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
726
 
727
          if (!gfi_ptr || gfi_ptr->key != gi_ptr)
728
            continue;
729
          const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
730
          for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
731
            {
732
              if (!gi_ptr->merge[t_ix])
733
                continue;
734
 
735
              memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
736
              ci_ptr++;
737
            }
738
        }
739
    }
740
}
741
 
742
#endif /* L_gcov */
743
 
744
#ifdef L_gcov_merge_add
745
/* The profile merging function that just adds the counters.  It is given
746
   an array COUNTERS of N_COUNTERS old counters and it reads the same number
747
   of counters from the gcov file.  */
748
void
749
__gcov_merge_add (gcov_type *counters, unsigned n_counters)
750
{
751
  for (; n_counters; counters++, n_counters--)
752
    *counters += gcov_read_counter ();
753
}
754
#endif /* L_gcov_merge_add */
755
 
756
#ifdef L_gcov_merge_ior
757
/* The profile merging function that just adds the counters.  It is given
758
   an array COUNTERS of N_COUNTERS old counters and it reads the same number
759
   of counters from the gcov file.  */
760
void
761
__gcov_merge_ior (gcov_type *counters, unsigned n_counters)
762
{
763
  for (; n_counters; counters++, n_counters--)
764
    *counters |= gcov_read_counter ();
765
}
766
#endif
767
 
768
#ifdef L_gcov_merge_single
769
/* The profile merging function for choosing the most common value.
770
   It is given an array COUNTERS of N_COUNTERS old counters and it
771
   reads the same number of counters from the gcov file.  The counters
772
   are split into 3-tuples where the members of the tuple have
773
   meanings:
774
 
775
   -- the stored candidate on the most common value of the measured entity
776
   -- counter
777
   -- total number of evaluations of the value  */
778
void
779
__gcov_merge_single (gcov_type *counters, unsigned n_counters)
780
{
781
  unsigned i, n_measures;
782
  gcov_type value, counter, all;
783
 
784
  gcc_assert (!(n_counters % 3));
785
  n_measures = n_counters / 3;
786
  for (i = 0; i < n_measures; i++, counters += 3)
787
    {
788
      value = gcov_read_counter ();
789
      counter = gcov_read_counter ();
790
      all = gcov_read_counter ();
791
 
792
      if (counters[0] == value)
793
        counters[1] += counter;
794
      else if (counter > counters[1])
795
        {
796
          counters[0] = value;
797
          counters[1] = counter - counters[1];
798
        }
799
      else
800
        counters[1] -= counter;
801
      counters[2] += all;
802
    }
803
}
804
#endif /* L_gcov_merge_single */
805
 
806
#ifdef L_gcov_merge_delta
807
/* The profile merging function for choosing the most common
808
   difference between two consecutive evaluations of the value.  It is
809
   given an array COUNTERS of N_COUNTERS old counters and it reads the
810
   same number of counters from the gcov file.  The counters are split
811
   into 4-tuples where the members of the tuple have meanings:
812
 
813
   -- the last value of the measured entity
814
   -- the stored candidate on the most common difference
815
   -- counter
816
   -- total number of evaluations of the value  */
817
void
818
__gcov_merge_delta (gcov_type *counters, unsigned n_counters)
819
{
820
  unsigned i, n_measures;
821
  gcov_type value, counter, all;
822
 
823
  gcc_assert (!(n_counters % 4));
824
  n_measures = n_counters / 4;
825
  for (i = 0; i < n_measures; i++, counters += 4)
826
    {
827
      /* last = */ gcov_read_counter ();
828
      value = gcov_read_counter ();
829
      counter = gcov_read_counter ();
830
      all = gcov_read_counter ();
831
 
832
      if (counters[1] == value)
833
        counters[2] += counter;
834
      else if (counter > counters[2])
835
        {
836
          counters[1] = value;
837
          counters[2] = counter - counters[2];
838
        }
839
      else
840
        counters[2] -= counter;
841
      counters[3] += all;
842
    }
843
}
844
#endif /* L_gcov_merge_delta */
845
 
846
#ifdef L_gcov_interval_profiler
847
/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
848
   corresponding counter in COUNTERS.  If the VALUE is above or below
849
   the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
850
   instead.  */
851
 
852
void
853
__gcov_interval_profiler (gcov_type *counters, gcov_type value,
854
                          int start, unsigned steps)
855
{
856
  gcov_type delta = value - start;
857
  if (delta < 0)
858
    counters[steps + 1]++;
859
  else if (delta >= steps)
860
    counters[steps]++;
861
  else
862
    counters[delta]++;
863
}
864
#endif
865
 
866
#ifdef L_gcov_pow2_profiler
867
/* If VALUE is a power of two, COUNTERS[1] is incremented.  Otherwise
868
   COUNTERS[0] is incremented.  */
869
 
870
void
871
__gcov_pow2_profiler (gcov_type *counters, gcov_type value)
872
{
873
  if (value & (value - 1))
874
    counters[0]++;
875
  else
876
    counters[1]++;
877
}
878
#endif
879
 
880
/* Tries to determine the most common value among its inputs.  Checks if the
881
   value stored in COUNTERS[0] matches VALUE.  If this is the case, COUNTERS[1]
882
   is incremented.  If this is not the case and COUNTERS[1] is not zero,
883
   COUNTERS[1] is decremented.  Otherwise COUNTERS[1] is set to one and
884
   VALUE is stored to COUNTERS[0].  This algorithm guarantees that if this
885
   function is called more than 50% of the time with one value, this value
886
   will be in COUNTERS[0] in the end.
887
 
888
   In any case, COUNTERS[2] is incremented.  */
889
 
890
static inline void
891
__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
892
{
893
  if (value == counters[0])
894
    counters[1]++;
895
  else if (counters[1] == 0)
896
    {
897
      counters[1] = 1;
898
      counters[0] = value;
899
    }
900
  else
901
    counters[1]--;
902
  counters[2]++;
903
}
904
 
905
#ifdef L_gcov_one_value_profiler
906
void
907
__gcov_one_value_profiler (gcov_type *counters, gcov_type value)
908
{
909
  __gcov_one_value_profiler_body (counters, value);
910
}
911
#endif
912
 
913
#ifdef L_gcov_indirect_call_profiler
914
 
915
/* By default, the C++ compiler will use function addresses in the
916
   vtable entries.  Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
917
   tells the compiler to use function descriptors instead.  The value
918
   of this macro says how many words wide the descriptor is (normally 2),
919
   but it may be dependent on target flags.  Since we do not have access
920
   to the target flags here we just check to see if it is set and use
921
   that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
922
 
923
   It is assumed that the address of a function descriptor may be treated
924
   as a pointer to a function.  */
925
 
926
#ifdef TARGET_VTABLE_USES_DESCRIPTORS
927
#define VTABLE_USES_DESCRIPTORS 1
928
#else
929
#define VTABLE_USES_DESCRIPTORS 0
930
#endif
931
 
932
/* Tries to determine the most common value among its inputs. */
933
void
934
__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
935
                               void* cur_func, void* callee_func)
936
{
937
  /* If the C++ virtual tables contain function descriptors then one
938
     function may have multiple descriptors and we need to dereference
939
     the descriptors to see if they point to the same function.  */
940
  if (cur_func == callee_func
941
      || (VTABLE_USES_DESCRIPTORS && callee_func
942
          && *(void **) cur_func == *(void **) callee_func))
943
    __gcov_one_value_profiler_body (counter, value);
944
}
945
#endif
946
 
947
 
948
#ifdef L_gcov_average_profiler
949
/* Increase corresponding COUNTER by VALUE.  FIXME: Perhaps we want
950
   to saturate up.  */
951
 
952
void
953
__gcov_average_profiler (gcov_type *counters, gcov_type value)
954
{
955
  counters[0] += value;
956
  counters[1] ++;
957
}
958
#endif
959
 
960
#ifdef L_gcov_ior_profiler
961
/* Increase corresponding COUNTER by VALUE.  FIXME: Perhaps we want
962
   to saturate up.  */
963
 
964
void
965
__gcov_ior_profiler (gcov_type *counters, gcov_type value)
966
{
967
  *counters |= value;
968
}
969
#endif
970
 
971
#ifdef L_gcov_fork
972
/* A wrapper for the fork function.  Flushes the accumulated profiling data, so
973
   that they are not counted twice.  */
974
 
975
pid_t
976
__gcov_fork (void)
977
{
978
  __gcov_flush ();
979
  return fork ();
980
}
981
#endif
982
 
983
#ifdef L_gcov_execl
984
/* A wrapper for the execl function.  Flushes the accumulated profiling data, so
985
   that they are not lost.  */
986
 
987
int
988
__gcov_execl (const char *path, char *arg, ...)
989
{
990
  va_list ap, aq;
991
  unsigned i, length;
992
  char **args;
993
 
994
  __gcov_flush ();
995
 
996
  va_start (ap, arg);
997
  va_copy (aq, ap);
998
 
999
  length = 2;
1000
  while (va_arg (ap, char *))
1001
    length++;
1002
  va_end (ap);
1003
 
1004
  args = (char **) alloca (length * sizeof (void *));
1005
  args[0] = arg;
1006
  for (i = 1; i < length; i++)
1007
    args[i] = va_arg (aq, char *);
1008
  va_end (aq);
1009
 
1010
  return execv (path, args);
1011
}
1012
#endif
1013
 
1014
#ifdef L_gcov_execlp
1015
/* A wrapper for the execlp function.  Flushes the accumulated profiling data, so
1016
   that they are not lost.  */
1017
 
1018
int
1019
__gcov_execlp (const char *path, char *arg, ...)
1020
{
1021
  va_list ap, aq;
1022
  unsigned i, length;
1023
  char **args;
1024
 
1025
  __gcov_flush ();
1026
 
1027
  va_start (ap, arg);
1028
  va_copy (aq, ap);
1029
 
1030
  length = 2;
1031
  while (va_arg (ap, char *))
1032
    length++;
1033
  va_end (ap);
1034
 
1035
  args = (char **) alloca (length * sizeof (void *));
1036
  args[0] = arg;
1037
  for (i = 1; i < length; i++)
1038
    args[i] = va_arg (aq, char *);
1039
  va_end (aq);
1040
 
1041
  return execvp (path, args);
1042
}
1043
#endif
1044
 
1045
#ifdef L_gcov_execle
1046
/* A wrapper for the execle function.  Flushes the accumulated profiling data, so
1047
   that they are not lost.  */
1048
 
1049
int
1050
__gcov_execle (const char *path, char *arg, ...)
1051
{
1052
  va_list ap, aq;
1053
  unsigned i, length;
1054
  char **args;
1055
  char **envp;
1056
 
1057
  __gcov_flush ();
1058
 
1059
  va_start (ap, arg);
1060
  va_copy (aq, ap);
1061
 
1062
  length = 2;
1063
  while (va_arg (ap, char *))
1064
    length++;
1065
  va_end (ap);
1066
 
1067
  args = (char **) alloca (length * sizeof (void *));
1068
  args[0] = arg;
1069
  for (i = 1; i < length; i++)
1070
    args[i] = va_arg (aq, char *);
1071
  envp = va_arg (aq, char **);
1072
  va_end (aq);
1073
 
1074
  return execve (path, args, envp);
1075
}
1076
#endif
1077
 
1078
#ifdef L_gcov_execv
1079
/* A wrapper for the execv function.  Flushes the accumulated profiling data, so
1080
   that they are not lost.  */
1081
 
1082
int
1083
__gcov_execv (const char *path, char *const argv[])
1084
{
1085
  __gcov_flush ();
1086
  return execv (path, argv);
1087
}
1088
#endif
1089
 
1090
#ifdef L_gcov_execvp
1091
/* A wrapper for the execvp function.  Flushes the accumulated profiling data, so
1092
   that they are not lost.  */
1093
 
1094
int
1095
__gcov_execvp (const char *path, char *const argv[])
1096
{
1097
  __gcov_flush ();
1098
  return execvp (path, argv);
1099
}
1100
#endif
1101
 
1102
#ifdef L_gcov_execve
1103
/* A wrapper for the execve function.  Flushes the accumulated profiling data, so
1104
   that they are not lost.  */
1105
 
1106
int
1107
__gcov_execve (const char *path, char *const argv[], char *const envp[])
1108
{
1109
  __gcov_flush ();
1110
  return execve (path, argv, envp);
1111
}
1112
#endif
1113
#endif /* inhibit_libc */

powered by: WebSVN 2.1.0

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