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