OSDN Git Service

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