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 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file. (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
22 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING. If not, write to the Free
29 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "coretypes.h"
37 #if defined(inhibit_libc)
38 #define IN_LIBGCOV (-1)
40 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
44 #define GCOV_LINKAGE /* nothing */
49 #if defined(inhibit_libc)
50 /* If libc and its header files are not available, provide dummy functions. */
53 void __gcov_init (struct gcov_info
*p
__attribute__ ((unused
))) {}
54 void __gcov_flush (void) {}
57 #ifdef L_gcov_merge_add
58 void __gcov_merge_add (gcov_type
*counters
__attribute__ ((unused
)),
59 unsigned n_counters
__attribute__ ((unused
))) {}
62 #ifdef L_gcov_merge_single
63 void __gcov_merge_single (gcov_type
*counters
__attribute__ ((unused
)),
64 unsigned n_counters
__attribute__ ((unused
))) {}
67 #ifdef L_gcov_merge_delta
68 void __gcov_merge_delta (gcov_type
*counters
__attribute__ ((unused
)),
69 unsigned n_counters
__attribute__ ((unused
))) {}
84 /* Chain of per-object gcov structures. */
85 static struct gcov_info
*gcov_list
;
87 /* A program checksum allows us to distinguish program data for an
88 object file included in multiple programs. */
89 static gcov_unsigned_t gcov_crc32
;
91 /* Size of the longest file name. */
92 static size_t gcov_max_filename
= 0;
94 #ifdef TARGET_POSIX_IO
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
)
104 for (s
= filename
+ 1; *s
!= '\0'; s
++)
105 if (IS_DIR_SEPARATOR(*s
))
110 /* Try to make directory if it doesn't already exist. */
111 if (access (filename
, F_OK
) == -1
112 && mkdir (filename
, 0755) == -1
113 /* The directory might have been made by another process. */
116 fprintf (stderr
, "profiling:%s:Cannot create directory\n",
128 /* Check if VERSION of the info block PTR matches libgcov one.
129 Return 1 on success, or zero in case of versions mismatch.
130 If FILENAME is not NULL, its value used for reporting purposes
131 instead of value from the info block. */
134 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
,
135 const char *filename
)
137 if (version
!= GCOV_VERSION
)
141 GCOV_UNSIGNED2STRING (v
, version
);
142 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
145 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
146 filename
? filename
: ptr
->filename
, e
, v
);
152 /* Dump the coverage counts. We merge with existing counts when
153 possible, to avoid growing the .da files ad infinitum. We use this
154 program's checksum to make sure we only accumulate whole program
155 statistics to the correct summary. An object file might be embedded
156 in two separate programs, and we must keep the two program
157 summaries separate. */
162 struct gcov_info
*gi_ptr
;
163 struct gcov_summary this_program
;
164 struct gcov_summary all
;
165 struct gcov_ctr_summary
*cs_ptr
;
166 const struct gcov_ctr_info
*ci_ptr
;
168 gcov_unsigned_t c_num
;
169 const char *gcov_prefix
;
170 int gcov_prefix_strip
= 0;
171 size_t prefix_length
;
172 char *gi_filename
, *gi_filename_up
;
174 memset (&all
, 0, sizeof (all
));
175 /* Find the totals for this execution. */
176 memset (&this_program
, 0, sizeof (this_program
));
177 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
179 ci_ptr
= gi_ptr
->counts
;
180 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
182 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
185 cs_ptr
= &this_program
.ctrs
[t_ix
];
186 cs_ptr
->num
+= ci_ptr
->num
;
187 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
189 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
190 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
191 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
197 /* Get file name relocation prefix. Non-absolute values are ignored. */
198 gcov_prefix
= getenv("GCOV_PREFIX");
199 if (gcov_prefix
&& IS_ABSOLUTE_PATH (gcov_prefix
))
201 /* Check if the level of dirs to strip off specified. */
202 char *tmp
= getenv("GCOV_PREFIX_STRIP");
205 gcov_prefix_strip
= atoi (tmp
);
206 /* Do not consider negative values. */
207 if (gcov_prefix_strip
< 0)
208 gcov_prefix_strip
= 0;
211 prefix_length
= strlen(gcov_prefix
);
213 /* Remove an unnecessary trailing '/' */
214 if (IS_DIR_SEPARATOR (gcov_prefix
[prefix_length
- 1]))
220 /* Allocate and initialize the filename scratch space. */
221 gi_filename
= (char *) alloca (prefix_length
+ gcov_max_filename
+ 1);
223 memcpy (gi_filename
, gcov_prefix
, prefix_length
);
224 gi_filename_up
= gi_filename
+ prefix_length
;
226 /* Now merge each file. */
227 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
229 struct gcov_summary this_object
;
230 struct gcov_summary object
, program
;
231 gcov_type
*values
[GCOV_COUNTERS
];
232 const struct gcov_fn_info
*fi_ptr
;
234 unsigned c_ix
, f_ix
, n_counts
;
235 struct gcov_ctr_summary
*cs_obj
, *cs_tobj
, *cs_prg
, *cs_tprg
, *cs_all
;
237 gcov_unsigned_t tag
, length
;
238 gcov_position_t summary_pos
= 0;
239 gcov_position_t eof_pos
= 0;
241 memset (&this_object
, 0, sizeof (this_object
));
242 memset (&object
, 0, sizeof (object
));
244 /* Build relocated filename, stripping off leading
245 directories from the initial filename if requested. */
246 if (gcov_prefix_strip
> 0)
249 const char *fname
= gi_ptr
->filename
;
252 /* Skip selected directory levels. */
253 for (s
= fname
+ 1; (*s
!= '\0') && (level
< gcov_prefix_strip
); s
++)
254 if (IS_DIR_SEPARATOR(*s
))
260 /* Update complete filename with stripped original. */
261 strcpy (gi_filename_up
, fname
);
264 strcpy (gi_filename_up
, gi_ptr
->filename
);
266 /* Totals for this object file. */
267 ci_ptr
= gi_ptr
->counts
;
268 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
270 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
273 cs_ptr
= &this_object
.ctrs
[t_ix
];
274 cs_ptr
->num
+= ci_ptr
->num
;
275 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
277 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
278 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
279 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
286 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
287 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
289 values
[c_ix
] = gi_ptr
->counts
[c_ix
].values
;
293 /* Calculate the function_info stride. This depends on the
294 number of counter types being measured. */
295 fi_stride
= sizeof (struct gcov_fn_info
) + c_ix
* sizeof (unsigned);
296 if (__alignof__ (struct gcov_fn_info
) > sizeof (unsigned))
298 fi_stride
+= __alignof__ (struct gcov_fn_info
) - 1;
299 fi_stride
&= ~(__alignof__ (struct gcov_fn_info
) - 1);
302 if (!gcov_open (gi_filename
))
304 #ifdef TARGET_POSIX_IO
305 /* Open failed likely due to missed directory.
306 Create directory and retry to open file. */
307 if (create_file_directory (gi_filename
))
309 fprintf (stderr
, "profiling:%s:Skip\n", gi_filename
);
313 if (!gcov_open (gi_filename
))
315 fprintf (stderr
, "profiling:%s:Cannot open\n", gi_filename
);
320 tag
= gcov_read_unsigned ();
323 /* Merge data from file. */
324 if (tag
!= GCOV_DATA_MAGIC
)
326 fprintf (stderr
, "profiling:%s:Not a gcov data file\n",
330 length
= gcov_read_unsigned ();
331 if (!gcov_version (gi_ptr
, length
, gi_filename
))
334 length
= gcov_read_unsigned ();
335 if (length
!= gi_ptr
->stamp
)
336 /* Read from a different compilation. Overwrite the file. */
339 /* Merge execution counts for each function. */
340 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
342 fi_ptr
= (const struct gcov_fn_info
*)
343 ((const char *) gi_ptr
->functions
+ f_ix
* fi_stride
);
344 tag
= gcov_read_unsigned ();
345 length
= gcov_read_unsigned ();
347 /* Check function. */
348 if (tag
!= GCOV_TAG_FUNCTION
349 || length
!= GCOV_TAG_FUNCTION_LENGTH
350 || gcov_read_unsigned () != fi_ptr
->ident
351 || gcov_read_unsigned () != fi_ptr
->checksum
)
354 fprintf (stderr
, "profiling:%s:Merge mismatch for %s\n",
356 f_ix
+ 1 ? "function" : "summaries");
361 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
365 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
368 n_counts
= fi_ptr
->n_ctrs
[c_ix
];
369 merge
= gi_ptr
->counts
[c_ix
].merge
;
371 tag
= gcov_read_unsigned ();
372 length
= gcov_read_unsigned ();
373 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
374 || length
!= GCOV_TAG_COUNTER_LENGTH (n_counts
))
376 (*merge
) (values
[c_ix
], n_counts
);
377 values
[c_ix
] += n_counts
;
380 if ((error
= gcov_is_error ()))
385 /* Check program & object summary */
390 eof_pos
= gcov_position ();
391 tag
= gcov_read_unsigned ();
395 length
= gcov_read_unsigned ();
396 is_program
= tag
== GCOV_TAG_PROGRAM_SUMMARY
;
397 if (length
!= GCOV_TAG_SUMMARY_LENGTH
398 || (!is_program
&& tag
!= GCOV_TAG_OBJECT_SUMMARY
))
400 gcov_read_summary (is_program
? &program
: &object
);
401 if ((error
= gcov_is_error ()))
403 if (is_program
&& program
.checksum
== gcov_crc32
)
405 summary_pos
= eof_pos
;
413 fprintf (stderr
, error
< 0 ? "profiling:%s:Overflow merging\n"
414 : "profiling:%s:Error merging\n", gi_filename
);
423 memset (&program
, 0, sizeof (program
));
425 /* Merge the summaries. */
427 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
429 cs_obj
= &object
.ctrs
[t_ix
];
430 cs_tobj
= &this_object
.ctrs
[t_ix
];
431 cs_prg
= &program
.ctrs
[t_ix
];
432 cs_tprg
= &this_program
.ctrs
[t_ix
];
433 cs_all
= &all
.ctrs
[t_ix
];
435 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
438 cs_obj
->num
= cs_tobj
->num
;
439 else if (cs_obj
->num
!= cs_tobj
->num
)
441 cs_obj
->sum_all
+= cs_tobj
->sum_all
;
442 if (cs_obj
->run_max
< cs_tobj
->run_max
)
443 cs_obj
->run_max
= cs_tobj
->run_max
;
444 cs_obj
->sum_max
+= cs_tobj
->run_max
;
447 cs_prg
->num
= cs_tprg
->num
;
448 else if (cs_prg
->num
!= cs_tprg
->num
)
450 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
451 if (cs_prg
->run_max
< cs_tprg
->run_max
)
452 cs_prg
->run_max
= cs_tprg
->run_max
;
453 cs_prg
->sum_max
+= cs_tprg
->run_max
;
455 else if (cs_obj
->num
|| cs_prg
->num
)
458 if (!cs_all
->runs
&& cs_prg
->runs
)
459 memcpy (cs_all
, cs_prg
, sizeof (*cs_all
));
460 else if (!all
.checksum
461 && (!GCOV_LOCKED
|| cs_all
->runs
== cs_prg
->runs
)
462 && memcmp (cs_all
, cs_prg
, sizeof (*cs_all
)))
464 fprintf (stderr
, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
465 gi_filename
, GCOV_LOCKED
466 ? "" : " or concurrent update without locking support");
472 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
473 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
475 values
[c_ix
] = gi_ptr
->counts
[c_ix
].values
;
479 program
.checksum
= gcov_crc32
;
481 /* Write out the data. */
482 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
483 gcov_write_unsigned (gi_ptr
->stamp
);
485 /* Write execution counts for each function. */
486 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
488 fi_ptr
= (const struct gcov_fn_info
*)
489 ((const char *) gi_ptr
->functions
+ f_ix
* fi_stride
);
491 /* Announce function. */
492 gcov_write_tag_length (GCOV_TAG_FUNCTION
, GCOV_TAG_FUNCTION_LENGTH
);
493 gcov_write_unsigned (fi_ptr
->ident
);
494 gcov_write_unsigned (fi_ptr
->checksum
);
497 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
501 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
504 n_counts
= fi_ptr
->n_ctrs
[c_ix
];
506 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
507 GCOV_TAG_COUNTER_LENGTH (n_counts
));
508 c_ptr
= values
[c_ix
];
510 gcov_write_counter (*c_ptr
++);
512 values
[c_ix
] = c_ptr
;
517 /* Object file summary. */
518 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY
, &object
);
520 /* Generate whole program statistics. */
523 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &program
);
525 gcov_write_unsigned (0);
526 if ((error
= gcov_close ()))
527 fprintf (stderr
, error
< 0 ?
528 "profiling:%s:Overflow writing\n" :
529 "profiling:%s:Error writing\n",
534 /* Add a new object file onto the bb chain. Invoked automatically
535 when running an object file's global ctors. */
538 __gcov_init (struct gcov_info
*info
)
542 if (gcov_version (info
, info
->version
, 0))
544 const char *ptr
= info
->filename
;
545 gcov_unsigned_t crc32
= gcov_crc32
;
546 size_t filename_length
= strlen(info
->filename
);
548 /* Refresh the longest file name information */
549 if (filename_length
> gcov_max_filename
)
550 gcov_max_filename
= filename_length
;
555 gcov_unsigned_t value
= *ptr
<< 24;
557 for (ix
= 8; ix
--; value
<<= 1)
559 gcov_unsigned_t feedback
;
561 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
573 info
->next
= gcov_list
;
579 /* Called before fork or exec - write out profile information gathered so
580 far and reset it to zero. This avoids duplication or loss of the
581 profile information gathered so far. */
586 const struct gcov_info
*gi_ptr
;
589 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
592 const struct gcov_ctr_info
*ci_ptr
;
594 for (t_ix
= 0, ci_ptr
= gi_ptr
->counts
; t_ix
!= GCOV_COUNTERS
; t_ix
++)
595 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
597 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
605 #ifdef L_gcov_merge_add
606 /* The profile merging function that just adds the counters. It is given
607 an array COUNTERS of N_COUNTERS old counters and it reads the same number
608 of counters from the gcov file. */
610 __gcov_merge_add (gcov_type
*counters
, unsigned n_counters
)
612 for (; n_counters
; counters
++, n_counters
--)
613 *counters
+= gcov_read_counter ();
615 #endif /* L_gcov_merge_add */
617 #ifdef L_gcov_merge_ior
618 /* The profile merging function that just adds the counters. It is given
619 an array COUNTERS of N_COUNTERS old counters and it reads the same number
620 of counters from the gcov file. */
622 __gcov_merge_ior (gcov_type
*counters
, unsigned n_counters
)
624 for (; n_counters
; counters
++, n_counters
--)
625 *counters
|= gcov_read_counter ();
629 #ifdef L_gcov_merge_single
630 /* The profile merging function for choosing the most common value.
631 It is given an array COUNTERS of N_COUNTERS old counters and it
632 reads the same number of counters from the gcov file. The counters
633 are split into 3-tuples where the members of the tuple have
636 -- the stored candidate on the most common value of the measured entity
638 -- total number of evaluations of the value */
640 __gcov_merge_single (gcov_type
*counters
, unsigned n_counters
)
642 unsigned i
, n_measures
;
643 gcov_type value
, counter
, all
;
645 gcc_assert (!(n_counters
% 3));
646 n_measures
= n_counters
/ 3;
647 for (i
= 0; i
< n_measures
; i
++, counters
+= 3)
649 value
= gcov_read_counter ();
650 counter
= gcov_read_counter ();
651 all
= gcov_read_counter ();
653 if (counters
[0] == value
)
654 counters
[1] += counter
;
655 else if (counter
> counters
[1])
658 counters
[1] = counter
- counters
[1];
661 counters
[1] -= counter
;
665 #endif /* L_gcov_merge_single */
667 #ifdef L_gcov_merge_delta
668 /* The profile merging function for choosing the most common
669 difference between two consecutive evaluations of the value. It is
670 given an array COUNTERS of N_COUNTERS old counters and it reads the
671 same number of counters from the gcov file. The counters are split
672 into 4-tuples where the members of the tuple have meanings:
674 -- the last value of the measured entity
675 -- the stored candidate on the most common difference
677 -- total number of evaluations of the value */
679 __gcov_merge_delta (gcov_type
*counters
, unsigned n_counters
)
681 unsigned i
, n_measures
;
682 gcov_type last
, value
, counter
, all
;
684 gcc_assert (!(n_counters
% 4));
685 n_measures
= n_counters
/ 4;
686 for (i
= 0; i
< n_measures
; i
++, counters
+= 4)
688 last
= gcov_read_counter ();
689 value
= gcov_read_counter ();
690 counter
= gcov_read_counter ();
691 all
= gcov_read_counter ();
693 if (counters
[1] == value
)
694 counters
[2] += counter
;
695 else if (counter
> counters
[2])
698 counters
[2] = counter
- counters
[2];
701 counters
[2] -= counter
;
705 #endif /* L_gcov_merge_delta */
707 #ifdef L_gcov_interval_profiler
708 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
709 corresponding counter in COUNTERS. If the VALUE is above or below
710 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
714 __gcov_interval_profiler (gcov_type
*counters
, gcov_type value
,
715 int start
, unsigned steps
)
717 gcov_type delta
= value
- start
;
719 counters
[steps
+ 1]++;
720 else if (delta
>= steps
)
727 #ifdef L_gcov_pow2_profiler
728 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
729 COUNTERS[0] is incremented. */
732 __gcov_pow2_profiler (gcov_type
*counters
, gcov_type value
)
734 if (value
& (value
- 1))
741 /* Tries to determine the most common value among its inputs. Checks if the
742 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
743 is incremented. If this is not the case and COUNTERS[1] is not zero,
744 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
745 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
746 function is called more than 50% of the time with one value, this value
747 will be in COUNTERS[0] in the end.
749 In any case, COUNTERS[2] is incremented. */
752 __gcov_one_value_profiler_body (gcov_type
*counters
, gcov_type value
)
754 if (value
== counters
[0])
756 else if (counters
[1] == 0)
766 #ifdef L_gcov_one_value_profiler
768 __gcov_one_value_profiler (gcov_type
*counters
, gcov_type value
)
770 __gcov_one_value_profiler_body (counters
, value
);
774 #ifdef L_gcov_indirect_call_profiler
775 /* Tries to determine the most common value among its inputs. */
777 __gcov_indirect_call_profiler (gcov_type
* counter
, gcov_type value
,
778 void* cur_func
, void* callee_func
)
780 if (cur_func
== callee_func
)
781 __gcov_one_value_profiler_body (counter
, value
);
786 #ifdef L_gcov_average_profiler
787 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
791 __gcov_average_profiler (gcov_type
*counters
, gcov_type value
)
793 counters
[0] += value
;
798 #ifdef L_gcov_ior_profiler
799 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
803 __gcov_ior_profiler (gcov_type
*counters
, gcov_type value
)
810 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
811 that they are not counted twice. */
822 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
823 that they are not lost. */
826 __gcov_execl (const char *path
, const char *arg
, ...)
838 while (va_arg (ap
, char *))
842 args
= (char **) alloca (length
* sizeof (void *));
843 args
[0] = (char *) arg
;
844 for (i
= 1; i
< length
; i
++)
845 args
[i
] = va_arg (aq
, char *);
848 return execv (path
, args
);
853 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
854 that they are not lost. */
857 __gcov_execlp (const char *path
, const char *arg
, ...)
869 while (va_arg (ap
, char *))
873 args
= (char **) alloca (length
* sizeof (void *));
874 args
[0] = (char *) arg
;
875 for (i
= 1; i
< length
; i
++)
876 args
[i
] = va_arg (aq
, char *);
879 return execvp (path
, args
);
884 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
885 that they are not lost. */
888 __gcov_execle (const char *path
, const char *arg
, ...)
901 while (va_arg (ap
, char *))
905 args
= (char **) alloca (length
* sizeof (void *));
906 args
[0] = (char *) arg
;
907 for (i
= 1; i
< length
; i
++)
908 args
[i
] = va_arg (aq
, char *);
909 envp
= va_arg (aq
, char **);
912 return execve (path
, args
, envp
);
917 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
918 that they are not lost. */
921 __gcov_execv (const char *path
, char *const argv
[])
924 return execv (path
, argv
);
929 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
930 that they are not lost. */
933 __gcov_execvp (const char *path
, char *const argv
[])
936 return execvp (path
, argv
);
941 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
942 that they are not lost. */
945 __gcov_execve (const char *path
, char *const argv
[], char *const envp
[])
948 return execve (path
, argv
, envp
);
951 #endif /* inhibit_libc */