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 gcov_unsigned_t expected = GCOV_VERSION;
99 if (version != GCOV_VERSION)
102 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
103 ptr->filename, (const char *)&expected, (const char *)&version);
109 /* Dump the coverage counts. We merge with existing counts when
110 possible, to avoid growing the .da files ad infinitum. We use this
111 program's checksum to make sure we only accumulate whole program
112 statistics to the correct summary. An object file might be embedded
113 in two separate programs, and we must keep the two program
114 summaries separate. */
119 struct gcov_info *gi_ptr;
120 struct gcov_summary this_program;
121 struct gcov_summary all;
123 memset (&all, 0, sizeof (all));
124 /* Find the totals for this execution. */
125 memset (&this_program, 0, sizeof (this_program));
126 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
128 const struct gcov_ctr_info *ci_ptr;
129 struct gcov_ctr_summary *cs_ptr;
132 for (t_ix = 0, ci_ptr = gi_ptr->counts, cs_ptr = this_program.ctrs;
133 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
134 if ((1 << t_ix) & gi_ptr->ctr_mask)
136 const gcov_type *c_ptr;
137 gcov_unsigned_t c_num;
139 cs_ptr->num += ci_ptr->num;
140 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
142 cs_ptr->sum_all += *c_ptr;
143 if (cs_ptr->run_max < *c_ptr)
144 cs_ptr->run_max = *c_ptr;
150 /* Now merge each file. */
151 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
153 struct gcov_summary this_object;
154 struct gcov_summary object, program;
155 gcov_type *values[GCOV_COUNTERS];
156 const struct gcov_fn_info *fi_ptr;
158 unsigned c_ix, t_ix, f_ix;
159 const struct gcov_ctr_info *ci_ptr;
160 struct gcov_ctr_summary *cs_ptr;
161 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
163 gcov_unsigned_t tag, length;
164 gcov_position_t summary_pos = 0;
166 memset (&this_object, 0, sizeof (this_object));
167 memset (&object, 0, sizeof (object));
169 /* Totals for this object file. */
170 for (t_ix = c_ix = 0,
171 ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
172 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
173 if ((1 << t_ix) & gi_ptr->ctr_mask)
175 const gcov_type *c_ptr;
176 gcov_unsigned_t c_num;
178 cs_ptr->num += ci_ptr->num;
179 values[c_ix] = ci_ptr->values;
180 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
182 cs_ptr->sum_all += *c_ptr;
183 if (cs_ptr->run_max < *c_ptr)
184 cs_ptr->run_max = *c_ptr;
190 /* Calculate the function_info stride. This depends on the
191 number of counter types being measured. */
192 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
193 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
195 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
196 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
199 if (!gcov_open (gi_ptr->filename))
201 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
205 tag = gcov_read_unsigned ();
208 /* Merge data from file. */
209 if (tag != GCOV_DATA_MAGIC)
211 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
217 length = gcov_read_unsigned ();
218 if (!gcov_version (gi_ptr, length))
221 length = gcov_read_unsigned ();
222 if (length != gi_ptr->stamp)
224 /* Read from a different compilation. Overwrite the
230 /* Merge execution counts for each function. */
231 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
233 fi_ptr = (const struct gcov_fn_info *)
234 ((const char *) fi_ptr + fi_stride))
236 tag = gcov_read_unsigned ();
237 length = gcov_read_unsigned ();
239 /* Check function. */
240 if (tag != GCOV_TAG_FUNCTION
241 || length != GCOV_TAG_FUNCTION_LENGTH
242 || gcov_read_unsigned () != fi_ptr->ident
243 || gcov_read_unsigned () != fi_ptr->checksum)
246 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
248 f_ix + 1 ? "function" : "summaries");
252 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
253 if ((1 << t_ix) & gi_ptr->ctr_mask)
255 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
256 gcov_merge_fn merge = gi_ptr->counts[c_ix].merge;
258 tag = gcov_read_unsigned ();
259 length = gcov_read_unsigned ();
260 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
261 || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
263 (*merge) (values[c_ix], n_counts);
264 values[c_ix] += n_counts;
267 if ((error = gcov_is_error ()))
271 /* Check program & object summary */
274 gcov_position_t base = gcov_position ();
277 tag = gcov_read_unsigned ();
280 length = gcov_read_unsigned ();
281 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
282 if (length != GCOV_TAG_SUMMARY_LENGTH
283 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
285 gcov_read_summary (is_program ? &program : &object);
286 if ((error = gcov_is_error ()))
288 if (is_program && program.checksum == gcov_crc32)
299 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
300 : "profiling:%s:Error merging\n", gi_ptr->filename);
306 memset (&program, 0, sizeof (program));
308 /* Merge the summaries. */
310 for (t_ix = c_ix = 0,
311 cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
312 cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
314 t_ix != GCOV_COUNTERS_SUMMABLE;
315 t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
317 if ((1 << t_ix) & gi_ptr->ctr_mask)
320 cs_obj->num = cs_tobj->num;
321 else if (cs_obj->num != cs_tobj->num)
323 cs_obj->sum_all += cs_tobj->sum_all;
324 if (cs_obj->run_max < cs_tobj->run_max)
325 cs_obj->run_max = cs_tobj->run_max;
326 cs_obj->sum_max += cs_tobj->run_max;
329 cs_prg->num = cs_tprg->num;
330 else if (cs_prg->num != cs_tprg->num)
332 cs_prg->sum_all += cs_tprg->sum_all;
333 if (cs_prg->run_max < cs_tprg->run_max)
334 cs_prg->run_max = cs_tprg->run_max;
335 cs_prg->sum_max += cs_tprg->run_max;
337 values[c_ix] = gi_ptr->counts[c_ix].values;
340 else if (cs_obj->num || cs_prg->num)
343 if (!cs_all->runs && cs_prg->runs)
344 memcpy (cs_all, cs_prg, sizeof (*cs_all));
345 else if (!all.checksum
346 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
347 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
349 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
350 gi_ptr->filename, GCOV_LOCKED
351 ? "" : " or concurrent update without locking support");
356 program.checksum = gcov_crc32;
358 /* Write out the data. */
359 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
360 gcov_write_unsigned (gi_ptr->stamp);
362 /* Write execution counts for each function. */
363 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
364 fi_ptr = (const struct gcov_fn_info *)
365 ((const char *) fi_ptr + fi_stride))
367 /* Announce function. */
368 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
369 gcov_write_unsigned (fi_ptr->ident);
370 gcov_write_unsigned (fi_ptr->checksum);
372 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
373 if ((1 << t_ix) & gi_ptr->ctr_mask)
375 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
378 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
379 GCOV_TAG_COUNTER_LENGTH (n_counts));
380 c_ptr = values[c_ix];
382 gcov_write_counter (*c_ptr++);
383 values[c_ix] = c_ptr;
388 /* Object file summary. */
389 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
391 /* Generate whole program statistics. */
392 gcov_seek (summary_pos);
393 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
394 if ((error = gcov_close ()))
395 fprintf (stderr, error < 0 ?
396 "profiling:%s:Overflow writing\n" :
397 "profiling:%s:Error writing\n",
402 /* Add a new object file onto the bb chain. Invoked automatically
403 when running an object file's global ctors. */
406 __gcov_init (struct gcov_info *info)
410 if (gcov_version (info, info->version))
412 const char *ptr = info->filename;
413 gcov_unsigned_t crc32 = gcov_crc32;
418 gcov_unsigned_t value = *ptr << 24;
420 for (ix = 8; ix--; value <<= 1)
422 gcov_unsigned_t feedback;
424 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
436 info->next = gcov_list;
442 /* Called before fork or exec - write out profile information gathered so
443 far and reset it to zero. This avoids duplication or loss of the
444 profile information gathered so far. */
449 const struct gcov_info *gi_ptr;
452 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
455 const struct gcov_ctr_info *ci_ptr;
457 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
458 if ((1 << t_ix) & gi_ptr->ctr_mask)
460 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
468 #ifdef L_gcov_merge_add
469 /* The profile merging function that just adds the counters. It is given
470 an array COUNTERS of N_COUNTERS old counters and it reads the same number
471 of counters from the gcov file. */
473 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
475 for (; n_counters; counters++, n_counters--)
476 *counters += gcov_read_counter ();
478 #endif /* L_gcov_merge_add */
480 #ifdef L_gcov_merge_single
481 /* The profile merging function for choosing the most common value. It is given
482 an array COUNTERS of N_COUNTERS old counters and it reads the same number
483 of counters from the gcov file. The counters are split into 3-tuples
484 where the members of the tuple have meanings:
485 -- the stored candidate on the most common value of the measured entity
487 -- total number of evaluations of the value */
489 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
491 unsigned i, n_measures;
492 gcov_type value, counter, all;
497 n_measures = n_counters / 3;
498 for (i = 0; i < n_measures; i++, counters += 3)
500 value = gcov_read_counter ();
501 counter = gcov_read_counter ();
502 all = gcov_read_counter ();
504 if (counters[0] == value)
505 counters[1] += counter;
506 else if (counter > counters[1])
509 counters[1] = counter - counters[1];
512 counters[1] -= counter;
516 #endif /* L_gcov_merge_single */
518 #ifdef L_gcov_merge_delta
519 /* The profile merging function for choosing the most common difference between
520 two consecutive evaluations of the value. It is given an array COUNTERS of
521 N_COUNTERS old counters and it reads the same number of counters from the
522 gcov file. The counters are split into 4-tuples where the members of the
524 -- the last value of the measured entity
525 -- the stored candidate on the most common difference
527 -- total number of evaluations of the value */
529 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
531 unsigned i, n_measures;
532 gcov_type last, value, counter, all;
537 n_measures = n_counters / 4;
538 for (i = 0; i < n_measures; i++, counters += 4)
540 last = gcov_read_counter ();
541 value = gcov_read_counter ();
542 counter = gcov_read_counter ();
543 all = gcov_read_counter ();
545 if (counters[1] == value)
546 counters[2] += counter;
547 else if (counter > counters[2])
550 counters[2] = counter - counters[2];
553 counters[2] -= counter;
557 #endif /* L_gcov_merge_delta */
559 #endif /* inhibit_libc */