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.
7 This file is part of GCC.
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
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
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.
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/>. */
30 #include "coretypes.h"
32 #include "libgcc_tm.h"
34 #if defined(inhibit_libc)
35 #define IN_LIBGCOV (-1)
37 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
41 #define GCOV_LINKAGE /* nothing */
46 #if defined(inhibit_libc)
47 /* If libc and its header files are not available, provide dummy functions. */
50 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
51 void __gcov_flush (void) {}
54 #ifdef L_gcov_merge_add
55 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
56 unsigned n_counters __attribute__ ((unused))) {}
59 #ifdef L_gcov_merge_single
60 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
61 unsigned n_counters __attribute__ ((unused))) {}
64 #ifdef L_gcov_merge_delta
65 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
66 unsigned n_counters __attribute__ ((unused))) {}
83 struct gcov_fn_buffer *next;
85 struct gcov_fn_info info;
86 /* note gcov_fn_info ends in a trailing array. */
89 /* Chain of per-object gcov structures. */
90 static struct gcov_info *gcov_list;
92 /* Size of the longest file name. */
93 static size_t gcov_max_filename = 0;
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. */
100 create_file_directory (char *filename)
102 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
110 if (HAS_DRIVE_SPEC(s))
112 if (IS_DIR_SEPARATOR(*s))
114 for (; *s != '\0'; s++)
115 if (IS_DIR_SEPARATOR(*s))
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
125 && mkdir (filename) == -1
127 /* The directory might have been made by another process. */
130 fprintf (stderr, "profiling:%s:Cannot create directory\n",
142 static struct gcov_fn_buffer *
143 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
146 struct gcov_fn_buffer *next;
147 unsigned ix, n_ctr = 0;
153 for (ix = 0; ix != limit; ix++)
154 if (gi_ptr->merge[ix])
155 free (buffer->info.ctrs[n_ctr++].values);
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)
164 unsigned n_ctrs = 0, ix = 0;
165 struct gcov_fn_buffer *fn_buffer;
168 for (ix = GCOV_COUNTERS; ix--;)
169 if (gi_ptr->merge[ix])
172 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
173 fn_buffer = (struct gcov_fn_buffer *)malloc (len);
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 ();
184 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
186 gcov_unsigned_t length;
189 if (!gi_ptr->merge[ix])
192 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
198 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
199 len = length * sizeof (gcov_type);
200 values = (gcov_type *)malloc (len);
204 fn_buffer->info.ctrs[n_ctrs].num = length;
205 fn_buffer->info.ctrs[n_ctrs].values = values;
208 *values++ = gcov_read_counter ();
212 *end_ptr = fn_buffer;
213 return &fn_buffer->next;
216 fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
217 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
219 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
222 /* Add an unsigned value to the current crc */
224 static gcov_unsigned_t
225 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
229 for (ix = 32; ix--; value <<= 1)
233 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
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. */
247 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
248 const char *filename)
250 if (version != GCOV_VERSION)
254 GCOV_UNSIGNED2STRING (v, version);
255 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
258 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
259 filename? filename : ptr->filename, e, v);
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. */
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;
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;
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)
295 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
296 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
298 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
300 gfi_ptr = gi_ptr->functions[f_ix];
302 if (gfi_ptr && gfi_ptr->key != gi_ptr)
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);
311 ci_ptr = gfi_ptr->ctrs;
312 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
314 if (!gi_ptr->merge[t_ix])
317 cs_ptr = &this_prg.ctrs[t_ix];
318 cs_ptr->num += ci_ptr->num;
319 crc32 = crc32_unsigned (crc32, ci_ptr->num);
321 for (c_num = 0; c_num < ci_ptr->num; c_num++)
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];
333 /* Check if the level of dirs to strip off specified. */
334 char *tmp = getenv("GCOV_PREFIX_STRIP");
337 gcov_prefix_strip = atoi (tmp);
338 /* Do not consider negative values. */
339 if (gcov_prefix_strip < 0)
340 gcov_prefix_strip = 0;
344 /* Get file name relocation prefix. Non-absolute values are ignored. */
345 gcov_prefix = getenv("GCOV_PREFIX");
348 prefix_length = strlen(gcov_prefix);
350 /* Remove an unnecessary trailing '/' */
351 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
357 /* If no prefix was specified and a prefix stip, then we assume
359 if (gcov_prefix_strip != 0 && prefix_length == 0)
364 /* Allocate and initialize the filename scratch space plus one. */
365 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
367 memcpy (gi_filename, gcov_prefix, prefix_length);
368 gi_filename_up = gi_filename + prefix_length;
370 /* Now merge each file. */
371 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
374 struct gcov_summary prg; /* summary for this object over all
376 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
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;
385 fname = gi_ptr->filename;
387 /* Avoid to add multiple drive letters into combined path. */
388 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
391 /* Build relocated filename, stripping off leading
392 directories from the initial filename if requested. */
393 if (gcov_prefix_strip > 0)
397 if (IS_DIR_SEPARATOR(*s))
400 /* Skip selected directory levels. */
401 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
402 if (IS_DIR_SEPARATOR(*s))
409 /* Update complete filename with stripped original. */
410 if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
412 /* If prefix is given, add directory separator. */
413 strcpy (gi_filename_up, "/");
414 strcpy (gi_filename_up + 1, fname);
417 strcpy (gi_filename_up, fname);
419 if (!gcov_open (gi_filename))
421 /* Open failed likely due to missed directory.
422 Create directory and retry to open file. */
423 if (create_file_directory (gi_filename))
425 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
428 if (!gcov_open (gi_filename))
430 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
435 tag = gcov_read_unsigned ();
438 /* Merge data from file. */
439 if (tag != GCOV_DATA_MAGIC)
441 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
445 length = gcov_read_unsigned ();
446 if (!gcov_version (gi_ptr, length, gi_filename))
449 length = gcov_read_unsigned ();
450 if (length != gi_ptr->stamp)
451 /* Read from a different compilation. Overwrite the file. */
454 /* Look for program summary. */
457 struct gcov_summary tmp;
459 eof_pos = gcov_position ();
460 tag = gcov_read_unsigned ();
461 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
465 length = gcov_read_unsigned ();
466 if (length != GCOV_TAG_SUMMARY_LENGTH)
468 gcov_read_summary (&tmp);
469 if ((error = gcov_is_error ()))
471 if (summary_pos || tmp.checksum != crc32)
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)
478 summary_pos = eof_pos;
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 ())
487 gfi_ptr = gi_ptr->functions[f_ix];
489 if (tag != GCOV_TAG_FUNCTION)
492 length = gcov_read_unsigned ();
494 /* This function did not appear in the other program.
495 We have nothing to merge. */
498 if (length != GCOV_TAG_FUNCTION_LENGTH)
501 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
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
508 fn_tail = buffer_fn_data (gi_filename,
509 gi_ptr, fn_tail, f_ix);
515 length = gcov_read_unsigned ();
516 if (length != gfi_ptr->ident)
519 length = gcov_read_unsigned ();
520 if (length != gfi_ptr->lineno_checksum)
523 length = gcov_read_unsigned ();
524 if (length != gfi_ptr->cfg_checksum)
527 ci_ptr = gfi_ptr->ctrs;
528 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
530 gcov_merge_fn merge = gi_ptr->merge[t_ix];
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))
540 (*merge) (ci_ptr->values, ci_ptr->num);
543 if ((error = gcov_is_error ()))
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);
559 fprintf (stderr, "profiling:%s:%s merging\n", gi_filename,
560 error < 0 ? "Overflow": "Error");
568 memset (&prg, 0, sizeof (prg));
569 summary_pos = eof_pos;
572 /* Merge the summaries. */
573 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
575 cs_prg = &prg.ctrs[t_ix];
576 cs_tprg = &this_prg.ctrs[t_ix];
577 cs_all = &all_prg.ctrs[t_ix];
579 if (gi_ptr->merge[t_ix])
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;
588 else if (cs_prg->runs)
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)))
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;
604 prg.checksum = crc32;
606 /* Write out the data. */
609 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
610 gcov_write_unsigned (gi_ptr->stamp);
614 gcov_seek (summary_pos);
616 /* Generate whole program statistics. */
617 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg);
619 if (summary_pos < eof_pos)
622 /* Write execution counts for each function. */
623 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
625 unsigned buffered = 0;
627 if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix)
629 /* Buffered data from another program. */
631 gfi_ptr = &fn_buffer->info;
632 length = GCOV_TAG_FUNCTION_LENGTH;
636 gfi_ptr = gi_ptr->functions[f_ix];
637 if (gfi_ptr && gfi_ptr->key == gi_ptr)
638 length = GCOV_TAG_FUNCTION_LENGTH;
643 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
647 gcov_write_unsigned (gfi_ptr->ident);
648 gcov_write_unsigned (gfi_ptr->lineno_checksum);
649 gcov_write_unsigned (gfi_ptr->cfg_checksum);
651 ci_ptr = gfi_ptr->ctrs;
652 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
654 if (!gi_ptr->merge[t_ix])
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;
662 gcov_write_counter (*c_ptr++);
666 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
669 gcov_write_unsigned (0);
673 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
675 if ((error = gcov_close ()))
676 fprintf (stderr, error < 0 ?
677 "profiling:%s:Overflow writing\n" :
678 "profiling:%s:Error writing\n",
683 /* Add a new object file onto the bb chain. Invoked automatically
684 when running an object file's global ctors. */
687 __gcov_init (struct gcov_info *info)
689 if (!info->version || !info->n_functions)
691 if (gcov_version (info, info->version, 0))
693 size_t filename_length = strlen(info->filename);
695 /* Refresh the longest file name information */
696 if (filename_length > gcov_max_filename)
697 gcov_max_filename = filename_length;
702 info->next = gcov_list;
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. */
715 const struct gcov_info *gi_ptr;
718 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
722 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
725 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
727 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
729 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
730 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
732 if (!gi_ptr->merge[t_ix])
735 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
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. */
749 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
751 for (; n_counters; counters++, n_counters--)
752 *counters += gcov_read_counter ();
754 #endif /* L_gcov_merge_add */
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. */
761 __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
763 for (; n_counters; counters++, n_counters--)
764 *counters |= gcov_read_counter ();
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
775 -- the stored candidate on the most common value of the measured entity
777 -- total number of evaluations of the value */
779 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
781 unsigned i, n_measures;
782 gcov_type value, counter, all;
784 gcc_assert (!(n_counters % 3));
785 n_measures = n_counters / 3;
786 for (i = 0; i < n_measures; i++, counters += 3)
788 value = gcov_read_counter ();
789 counter = gcov_read_counter ();
790 all = gcov_read_counter ();
792 if (counters[0] == value)
793 counters[1] += counter;
794 else if (counter > counters[1])
797 counters[1] = counter - counters[1];
800 counters[1] -= counter;
804 #endif /* L_gcov_merge_single */
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:
813 -- the last value of the measured entity
814 -- the stored candidate on the most common difference
816 -- total number of evaluations of the value */
818 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
820 unsigned i, n_measures;
821 gcov_type value, counter, all;
823 gcc_assert (!(n_counters % 4));
824 n_measures = n_counters / 4;
825 for (i = 0; i < n_measures; i++, counters += 4)
827 /* last = */ gcov_read_counter ();
828 value = gcov_read_counter ();
829 counter = gcov_read_counter ();
830 all = gcov_read_counter ();
832 if (counters[1] == value)
833 counters[2] += counter;
834 else if (counter > counters[2])
837 counters[2] = counter - counters[2];
840 counters[2] -= counter;
844 #endif /* L_gcov_merge_delta */
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
853 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
854 int start, unsigned steps)
856 gcov_type delta = value - start;
858 counters[steps + 1]++;
859 else if (delta >= steps)
866 #ifdef L_gcov_pow2_profiler
867 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
868 COUNTERS[0] is incremented. */
871 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
873 if (value & (value - 1))
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.
888 In any case, COUNTERS[2] is incremented. */
891 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
893 if (value == counters[0])
895 else if (counters[1] == 0)
905 #ifdef L_gcov_one_value_profiler
907 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
909 __gcov_one_value_profiler_body (counters, value);
913 #ifdef L_gcov_indirect_call_profiler
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.
923 It is assumed that the address of a function descriptor may be treated
924 as a pointer to a function. */
926 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
927 #define VTABLE_USES_DESCRIPTORS 1
929 #define VTABLE_USES_DESCRIPTORS 0
932 /* Tries to determine the most common value among its inputs. */
934 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
935 void* cur_func, void* callee_func)
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);
948 #ifdef L_gcov_average_profiler
949 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
953 __gcov_average_profiler (gcov_type *counters, gcov_type value)
955 counters[0] += value;
960 #ifdef L_gcov_ior_profiler
961 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
965 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
972 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
973 that they are not counted twice. */
984 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
985 that they are not lost. */
988 __gcov_execl (const char *path, char *arg, ...)
1000 while (va_arg (ap, char *))
1004 args = (char **) alloca (length * sizeof (void *));
1006 for (i = 1; i < length; i++)
1007 args[i] = va_arg (aq, char *);
1010 return execv (path, args);
1014 #ifdef L_gcov_execlp
1015 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1016 that they are not lost. */
1019 __gcov_execlp (const char *path, char *arg, ...)
1031 while (va_arg (ap, char *))
1035 args = (char **) alloca (length * sizeof (void *));
1037 for (i = 1; i < length; i++)
1038 args[i] = va_arg (aq, char *);
1041 return execvp (path, args);
1045 #ifdef L_gcov_execle
1046 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
1047 that they are not lost. */
1050 __gcov_execle (const char *path, char *arg, ...)
1063 while (va_arg (ap, char *))
1067 args = (char **) alloca (length * sizeof (void *));
1069 for (i = 1; i < length; i++)
1070 args[i] = va_arg (aq, char *);
1071 envp = va_arg (aq, char **);
1074 return execve (path, args, envp);
1079 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1080 that they are not lost. */
1083 __gcov_execv (const char *path, char *const argv[])
1086 return execv (path, argv);
1090 #ifdef L_gcov_execvp
1091 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1092 that they are not lost. */
1095 __gcov_execvp (const char *path, char *const argv[])
1098 return execvp (path, argv);
1102 #ifdef L_gcov_execve
1103 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
1104 that they are not lost. */
1107 __gcov_execve (const char *path, char *const argv[], char *const envp[])
1110 return execve (path, argv, envp);
1113 #endif /* inhibit_libc */