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 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, 59 Temple Place - Suite 330, Boston, MA
32 /* It is incorrect to include config.h here, because this file is being
33 compiled for the target, and hence definitions concerning only the host
38 #include "coretypes.h"
41 #if defined(inhibit_libc)
42 #define IN_LIBGCOV (-1)
44 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
48 #define GCOV_LINKAGE /* nothing */
53 #if defined(inhibit_libc)
54 /* If libc and its header files are not available, provide dummy functions. */
57 void __gcov_init (struct gcov_info
*p
__attribute__ ((unused
))) {}
58 void __gcov_flush (void) {}
61 #ifdef L_gcov_merge_add
62 void __gcov_merge_add (gcov_type
*counters
__attribute__ ((unused
)),
63 unsigned n_counters
__attribute__ ((unused
))) {}
66 #ifdef L_gcov_merge_single
67 void __gcov_merge_single (gcov_type
*counters
__attribute__ ((unused
)),
68 unsigned n_counters
__attribute__ ((unused
))) {}
71 #ifdef L_gcov_merge_delta
72 void __gcov_merge_delta (gcov_type
*counters
__attribute__ ((unused
)),
73 unsigned n_counters
__attribute__ ((unused
))) {}
87 /* Chain of per-object gcov structures. */
88 static struct gcov_info
*gcov_list
;
90 /* A program checksum allows us to distinguish program data for an
91 object file included in multiple programs. */
92 static gcov_unsigned_t gcov_crc32
;
95 gcov_version (struct gcov_info
*ptr
, gcov_unsigned_t version
)
97 if (version
!= GCOV_VERSION
)
101 GCOV_UNSIGNED2STRING (v
, version
);
102 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
105 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
106 ptr
->filename
, e
, v
);
112 /* Dump the coverage counts. We merge with existing counts when
113 possible, to avoid growing the .da files ad infinitum. We use this
114 program's checksum to make sure we only accumulate whole program
115 statistics to the correct summary. An object file might be embedded
116 in two separate programs, and we must keep the two program
117 summaries separate. */
122 struct gcov_info
*gi_ptr
;
123 struct gcov_summary this_program
;
124 struct gcov_summary all
;
125 struct gcov_ctr_summary
*cs_ptr
;
126 const struct gcov_ctr_info
*ci_ptr
;
128 gcov_unsigned_t c_num
;
130 memset (&all
, 0, sizeof (all
));
131 /* Find the totals for this execution. */
132 memset (&this_program
, 0, sizeof (this_program
));
133 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
135 ci_ptr
= gi_ptr
->counts
;
136 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
138 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
141 cs_ptr
= &this_program
.ctrs
[t_ix
];
142 cs_ptr
->num
+= ci_ptr
->num
;
143 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
145 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
146 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
147 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
153 /* Now merge each file. */
154 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
156 struct gcov_summary this_object
;
157 struct gcov_summary object
, program
;
158 gcov_type
*values
[GCOV_COUNTERS
];
159 const struct gcov_fn_info
*fi_ptr
;
161 unsigned c_ix
, f_ix
, n_counts
;
162 struct gcov_ctr_summary
*cs_obj
, *cs_tobj
, *cs_prg
, *cs_tprg
, *cs_all
;
164 gcov_unsigned_t tag
, length
;
165 gcov_position_t summary_pos
= 0;
167 memset (&this_object
, 0, sizeof (this_object
));
168 memset (&object
, 0, sizeof (object
));
170 /* Totals for this object file. */
171 ci_ptr
= gi_ptr
->counts
;
172 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
174 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
177 cs_ptr
= &this_object
.ctrs
[t_ix
];
178 cs_ptr
->num
+= ci_ptr
->num
;
179 for (c_num
= 0; c_num
< ci_ptr
->num
; c_num
++)
181 cs_ptr
->sum_all
+= ci_ptr
->values
[c_num
];
182 if (cs_ptr
->run_max
< ci_ptr
->values
[c_num
])
183 cs_ptr
->run_max
= ci_ptr
->values
[c_num
];
190 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
191 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
193 values
[c_ix
] = gi_ptr
->counts
[c_ix
].values
;
197 /* Calculate the function_info stride. This depends on the
198 number of counter types being measured. */
199 fi_stride
= sizeof (struct gcov_fn_info
) + c_ix
* sizeof (unsigned);
200 if (__alignof__ (struct gcov_fn_info
) > sizeof (unsigned))
202 fi_stride
+= __alignof__ (struct gcov_fn_info
) - 1;
203 fi_stride
&= ~(__alignof__ (struct gcov_fn_info
) - 1);
206 if (!gcov_open (gi_ptr
->filename
))
208 fprintf (stderr
, "profiling:%s:Cannot open\n", gi_ptr
->filename
);
212 tag
= gcov_read_unsigned ();
215 /* Merge data from file. */
216 if (tag
!= GCOV_DATA_MAGIC
)
218 fprintf (stderr
, "profiling:%s:Not a gcov data file\n",
224 length
= gcov_read_unsigned ();
225 if (!gcov_version (gi_ptr
, length
))
228 length
= gcov_read_unsigned ();
229 if (length
!= gi_ptr
->stamp
)
231 /* Read from a different compilation. Overwrite the
237 /* Merge execution counts for each function. */
238 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
240 fi_ptr
= (const struct gcov_fn_info
*)
241 ((const char *) gi_ptr
->functions
+ f_ix
* fi_stride
);
242 tag
= gcov_read_unsigned ();
243 length
= gcov_read_unsigned ();
245 /* Check function. */
246 if (tag
!= GCOV_TAG_FUNCTION
247 || length
!= GCOV_TAG_FUNCTION_LENGTH
248 || gcov_read_unsigned () != fi_ptr
->ident
249 || gcov_read_unsigned () != fi_ptr
->checksum
)
252 fprintf (stderr
, "profiling:%s:Merge mismatch for %s\n",
254 f_ix
+ 1 ? "function" : "summaries");
259 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
263 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
266 n_counts
= fi_ptr
->n_ctrs
[c_ix
];
267 merge
= gi_ptr
->counts
[c_ix
].merge
;
269 tag
= gcov_read_unsigned ();
270 length
= gcov_read_unsigned ();
271 if (tag
!= GCOV_TAG_FOR_COUNTER (t_ix
)
272 || length
!= GCOV_TAG_COUNTER_LENGTH (n_counts
))
274 (*merge
) (values
[c_ix
], n_counts
);
275 values
[c_ix
] += n_counts
;
278 if ((error
= gcov_is_error ()))
283 /* Check program & object summary */
286 gcov_position_t base
= gcov_position ();
289 tag
= gcov_read_unsigned ();
292 length
= gcov_read_unsigned ();
293 is_program
= tag
== GCOV_TAG_PROGRAM_SUMMARY
;
294 if (length
!= GCOV_TAG_SUMMARY_LENGTH
295 || (!is_program
&& tag
!= GCOV_TAG_OBJECT_SUMMARY
))
297 gcov_read_summary (is_program
? &program
: &object
);
298 if ((error
= gcov_is_error ()))
300 if (is_program
&& program
.checksum
== gcov_crc32
)
311 fprintf (stderr
, error
< 0 ? "profiling:%s:Overflow merging\n"
312 : "profiling:%s:Error merging\n", gi_ptr
->filename
);
318 memset (&program
, 0, sizeof (program
));
320 /* Merge the summaries. */
322 for (t_ix
= 0; t_ix
< GCOV_COUNTERS_SUMMABLE
; t_ix
++)
324 cs_obj
= &object
.ctrs
[t_ix
];
325 cs_tobj
= &this_object
.ctrs
[t_ix
];
326 cs_prg
= &program
.ctrs
[t_ix
];
327 cs_tprg
= &this_program
.ctrs
[t_ix
];
328 cs_all
= &all
.ctrs
[t_ix
];
330 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
333 cs_obj
->num
= cs_tobj
->num
;
334 else if (cs_obj
->num
!= cs_tobj
->num
)
336 cs_obj
->sum_all
+= cs_tobj
->sum_all
;
337 if (cs_obj
->run_max
< cs_tobj
->run_max
)
338 cs_obj
->run_max
= cs_tobj
->run_max
;
339 cs_obj
->sum_max
+= cs_tobj
->run_max
;
342 cs_prg
->num
= cs_tprg
->num
;
343 else if (cs_prg
->num
!= cs_tprg
->num
)
345 cs_prg
->sum_all
+= cs_tprg
->sum_all
;
346 if (cs_prg
->run_max
< cs_tprg
->run_max
)
347 cs_prg
->run_max
= cs_tprg
->run_max
;
348 cs_prg
->sum_max
+= cs_tprg
->run_max
;
350 else if (cs_obj
->num
|| cs_prg
->num
)
353 if (!cs_all
->runs
&& cs_prg
->runs
)
354 memcpy (cs_all
, cs_prg
, sizeof (*cs_all
));
355 else if (!all
.checksum
356 && (!GCOV_LOCKED
|| cs_all
->runs
== cs_prg
->runs
)
357 && memcmp (cs_all
, cs_prg
, sizeof (*cs_all
)))
359 fprintf (stderr
, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
360 gi_ptr
->filename
, GCOV_LOCKED
361 ? "" : " or concurrent update without locking support");
367 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
368 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
370 values
[c_ix
] = gi_ptr
->counts
[c_ix
].values
;
374 program
.checksum
= gcov_crc32
;
376 /* Write out the data. */
377 gcov_write_tag_length (GCOV_DATA_MAGIC
, GCOV_VERSION
);
378 gcov_write_unsigned (gi_ptr
->stamp
);
380 /* Write execution counts for each function. */
381 for (f_ix
= 0; f_ix
< gi_ptr
->n_functions
; f_ix
++)
383 fi_ptr
= (const struct gcov_fn_info
*)
384 ((const char *) gi_ptr
->functions
+ f_ix
* fi_stride
);
386 /* Announce function. */
387 gcov_write_tag_length (GCOV_TAG_FUNCTION
, GCOV_TAG_FUNCTION_LENGTH
);
388 gcov_write_unsigned (fi_ptr
->ident
);
389 gcov_write_unsigned (fi_ptr
->checksum
);
392 for (t_ix
= 0; t_ix
< GCOV_COUNTERS
; t_ix
++)
396 if (!((1 << t_ix
) & gi_ptr
->ctr_mask
))
399 n_counts
= fi_ptr
->n_ctrs
[c_ix
];
401 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix
),
402 GCOV_TAG_COUNTER_LENGTH (n_counts
));
403 c_ptr
= values
[c_ix
];
405 gcov_write_counter (*c_ptr
++);
407 values
[c_ix
] = c_ptr
;
412 /* Object file summary. */
413 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY
, &object
);
415 /* Generate whole program statistics. */
416 gcov_seek (summary_pos
);
417 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY
, &program
);
418 if ((error
= gcov_close ()))
419 fprintf (stderr
, error
< 0 ?
420 "profiling:%s:Overflow writing\n" :
421 "profiling:%s:Error writing\n",
426 /* Add a new object file onto the bb chain. Invoked automatically
427 when running an object file's global ctors. */
430 __gcov_init (struct gcov_info
*info
)
434 if (gcov_version (info
, info
->version
))
436 const char *ptr
= info
->filename
;
437 gcov_unsigned_t crc32
= gcov_crc32
;
442 gcov_unsigned_t value
= *ptr
<< 24;
444 for (ix
= 8; ix
--; value
<<= 1)
446 gcov_unsigned_t feedback
;
448 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
460 info
->next
= gcov_list
;
466 /* Called before fork or exec - write out profile information gathered so
467 far and reset it to zero. This avoids duplication or loss of the
468 profile information gathered so far. */
473 const struct gcov_info
*gi_ptr
;
476 for (gi_ptr
= gcov_list
; gi_ptr
; gi_ptr
= gi_ptr
->next
)
479 const struct gcov_ctr_info
*ci_ptr
;
481 for (t_ix
= 0, ci_ptr
= gi_ptr
->counts
; t_ix
!= GCOV_COUNTERS
; t_ix
++)
482 if ((1 << t_ix
) & gi_ptr
->ctr_mask
)
484 memset (ci_ptr
->values
, 0, sizeof (gcov_type
) * ci_ptr
->num
);
492 #ifdef L_gcov_merge_add
493 /* The profile merging function that just adds the counters. It is given
494 an array COUNTERS of N_COUNTERS old counters and it reads the same number
495 of counters from the gcov file. */
497 __gcov_merge_add (gcov_type
*counters
, unsigned n_counters
)
499 for (; n_counters
; counters
++, n_counters
--)
500 *counters
+= gcov_read_counter ();
502 #endif /* L_gcov_merge_add */
504 #ifdef L_gcov_merge_single
505 /* The profile merging function for choosing the most common value.
506 It is given an array COUNTERS of N_COUNTERS old counters and it
507 reads the same number of counters from the gcov file. The counters
508 are split into 3-tuples where the members of the tuple have
511 -- the stored candidate on the most common value of the measured entity
513 -- total number of evaluations of the value */
515 __gcov_merge_single (gcov_type
*counters
, unsigned n_counters
)
517 unsigned i
, n_measures
;
518 gcov_type value
, counter
, all
;
520 GCOV_CHECK (!(n_counters
% 3));
521 n_measures
= n_counters
/ 3;
522 for (i
= 0; i
< n_measures
; i
++, counters
+= 3)
524 value
= gcov_read_counter ();
525 counter
= gcov_read_counter ();
526 all
= gcov_read_counter ();
528 if (counters
[0] == value
)
529 counters
[1] += counter
;
530 else if (counter
> counters
[1])
533 counters
[1] = counter
- counters
[1];
536 counters
[1] -= counter
;
540 #endif /* L_gcov_merge_single */
542 #ifdef L_gcov_merge_delta
543 /* The profile merging function for choosing the most common
544 difference between two consecutive evaluations of the value. It is
545 given an array COUNTERS of N_COUNTERS old counters and it reads the
546 same number of counters from the gcov file. The counters are split
547 into 4-tuples where the members of the tuple have meanings:
549 -- the last value of the measured entity
550 -- the stored candidate on the most common difference
552 -- total number of evaluations of the value */
554 __gcov_merge_delta (gcov_type
*counters
, unsigned n_counters
)
556 unsigned i
, n_measures
;
557 gcov_type last
, value
, counter
, all
;
559 GCOV_CHECK (!(n_counters
% 4));
560 n_measures
= n_counters
/ 4;
561 for (i
= 0; i
< n_measures
; i
++, counters
+= 4)
563 last
= gcov_read_counter ();
564 value
= gcov_read_counter ();
565 counter
= gcov_read_counter ();
566 all
= gcov_read_counter ();
568 if (counters
[1] == value
)
569 counters
[2] += counter
;
570 else if (counter
> counters
[2])
573 counters
[2] = counter
- counters
[2];
576 counters
[2] -= counter
;
580 #endif /* L_gcov_merge_delta */
582 #endif /* inhibit_libc */