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_mismatch (struct gcov_info *ptr, gcov_unsigned_t version)
97 gcov_unsigned_t expected = GCOV_VERSION;
101 for (ix = 4; ix--; expected >>= 8, version >>= 8)
108 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
109 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;
126 memset (&all, 0, sizeof (all));
127 /* Find the totals for this execution. */
128 memset (&this_program, 0, sizeof (this_program));
129 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
131 const struct gcov_ctr_info *ci_ptr;
132 struct gcov_ctr_summary *cs_ptr;
135 for (t_ix = 0, ci_ptr = gi_ptr->counts, cs_ptr = this_program.ctrs;
136 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
137 if ((1 << t_ix) & gi_ptr->ctr_mask)
139 const gcov_type *c_ptr;
140 gcov_unsigned_t c_num;
142 cs_ptr->num += ci_ptr->num;
143 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
145 cs_ptr->sum_all += *c_ptr;
146 if (cs_ptr->run_max < *c_ptr)
147 cs_ptr->run_max = *c_ptr;
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, t_ix, f_ix;
162 const struct gcov_ctr_info *ci_ptr;
163 struct gcov_ctr_summary *cs_ptr;
164 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
167 gcov_unsigned_t tag, length;
168 gcov_position_t summary_pos = 0;
170 /* Totals for this object file. */
171 memset (&this_object, 0, sizeof (this_object));
172 for (t_ix = c_ix = 0,
173 ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
174 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
175 if ((1 << t_ix) & gi_ptr->ctr_mask)
177 const gcov_type *c_ptr;
178 gcov_unsigned_t c_num;
180 cs_ptr->num += ci_ptr->num;
181 values[c_ix] = ci_ptr->values;
182 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
184 cs_ptr->sum_all += *c_ptr;
185 if (cs_ptr->run_max < *c_ptr)
186 cs_ptr->run_max = *c_ptr;
192 /* Calculate the function_info stride. This depends on the
193 number of counter types being measured. */
194 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
195 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
197 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
198 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
201 /* Open for modification, if possible */
202 merging = gcov_open (gi_ptr->filename, 0);
205 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
211 /* Merge data from file. */
212 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
214 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
220 length = gcov_read_unsigned ();
221 if (length != GCOV_VERSION)
223 gcov_version_mismatch (gi_ptr, length);
227 /* Merge execution counts for each function. */
228 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
230 fi_ptr = (const struct gcov_fn_info *)
231 ((const char *) fi_ptr + fi_stride))
233 tag = gcov_read_unsigned ();
234 length = gcov_read_unsigned ();
237 if (tag != GCOV_TAG_FUNCTION
238 || length != GCOV_TAG_FUNCTION_LENGTH
239 || gcov_read_unsigned () != fi_ptr->ident
240 || gcov_read_unsigned () != fi_ptr->checksum)
243 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
245 f_ix + 1 ? "function" : "summaries");
249 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
250 if ((1 << t_ix) & gi_ptr->ctr_mask)
252 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
253 gcov_merge_fn merge = gi_ptr->counts[c_ix].merge;
255 tag = gcov_read_unsigned ();
256 length = gcov_read_unsigned ();
257 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
258 || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
260 (*merge) (values[c_ix], n_counts);
261 values[c_ix] += n_counts;
264 if ((error = gcov_is_error ()))
268 /* Check program & object summary */
271 gcov_position_t base = gcov_position ();
274 tag = gcov_read_unsigned ();
277 length = gcov_read_unsigned ();
278 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
279 if (length != GCOV_TAG_SUMMARY_LENGTH
280 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
282 gcov_read_summary (is_program ? &program : &object);
283 if ((error = gcov_is_error ()))
285 if (is_program && program.checksum == gcov_crc32)
294 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
295 : "profiling:%s:Error merging\n", gi_ptr->filename);
302 memset (&object, 0, sizeof (object));
304 memset (&program, 0, sizeof (program));
306 /* Merge the summaries. */
308 for (t_ix = c_ix = 0,
309 cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
310 cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
312 t_ix != GCOV_COUNTERS_SUMMABLE;
313 t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
315 if ((1 << t_ix) & gi_ptr->ctr_mask)
318 cs_obj->num = cs_tobj->num;
319 else if (cs_obj->num != cs_tobj->num)
321 cs_obj->sum_all += cs_tobj->sum_all;
322 if (cs_obj->run_max < cs_tobj->run_max)
323 cs_obj->run_max = cs_tobj->run_max;
324 cs_obj->sum_max += cs_tobj->run_max;
327 cs_prg->num = cs_tprg->num;
328 else if (cs_prg->num != cs_tprg->num)
330 cs_prg->sum_all += cs_tprg->sum_all;
331 if (cs_prg->run_max < cs_tprg->run_max)
332 cs_prg->run_max = cs_tprg->run_max;
333 cs_prg->sum_max += cs_tprg->run_max;
335 values[c_ix] = gi_ptr->counts[c_ix].values;
338 else if (cs_obj->num || cs_prg->num)
341 if (!cs_all->runs && cs_prg->runs)
342 memcpy (cs_all, cs_prg, sizeof (*cs_all));
343 else if (!all.checksum
344 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
345 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
347 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
348 gi_ptr->filename, GCOV_LOCKED
349 ? "" : " or concurrent update without locking support");
354 program.checksum = gcov_crc32;
356 /* Write out the data. */
357 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
359 /* Write execution counts for each function. */
360 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
361 fi_ptr = (const struct gcov_fn_info *)
362 ((const char *) fi_ptr + fi_stride))
364 /* Announce function. */
365 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
366 gcov_write_unsigned (fi_ptr->ident);
367 gcov_write_unsigned (fi_ptr->checksum);
369 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
370 if ((1 << t_ix) & gi_ptr->ctr_mask)
372 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
375 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
376 GCOV_TAG_COUNTER_LENGTH (n_counts));
377 c_ptr = values[c_ix];
379 gcov_write_counter (*c_ptr++);
380 values[c_ix] = c_ptr;
385 /* Object file summary. */
386 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
388 /* Generate whole program statistics. */
389 gcov_seek (summary_pos);
390 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
391 if ((error = gcov_close ()))
392 fprintf (stderr, error < 0 ?
393 "profiling:%s:Overflow writing\n" :
394 "profiling:%s:Error writing\n",
399 /* Add a new object file onto the bb chain. Invoked automatically
400 when running an object file's global ctors. */
403 __gcov_init (struct gcov_info *info)
407 if (info->version != GCOV_VERSION)
408 gcov_version_mismatch (info, info->version);
411 const char *ptr = info->filename;
412 gcov_unsigned_t crc32 = gcov_crc32;
417 gcov_unsigned_t value = *ptr << 24;
419 for (ix = 8; ix--; value <<= 1)
421 gcov_unsigned_t feedback;
423 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
435 info->next = gcov_list;
441 /* Called before fork or exec - write out profile information gathered so
442 far and reset it to zero. This avoids duplication or loss of the
443 profile information gathered so far. */
448 const struct gcov_info *gi_ptr;
451 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
454 const struct gcov_ctr_info *ci_ptr;
456 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
457 if ((1 << t_ix) & gi_ptr->ctr_mask)
459 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
467 #ifdef L_gcov_merge_add
468 /* The profile merging function that just adds the counters. It is given
469 an array COUNTERS of N_COUNTERS old counters and it reads the same number
470 of counters from the gcov file. */
472 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
474 for (; n_counters; counters++, n_counters--)
475 *counters += gcov_read_counter ();
477 #endif /* L_gcov_merge_add */
479 #ifdef L_gcov_merge_single
480 /* The profile merging function for choosing the most common value. It is given
481 an array COUNTERS of N_COUNTERS old counters and it reads the same number
482 of counters from the gcov file. The counters are split into 3-tuples
483 where the members of the tuple have meanings:
484 -- the stored candidate on the most common value of the measured entity
486 -- total number of evaluations of the value */
488 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
490 unsigned i, n_measures;
491 gcov_type value, counter, all;
496 n_measures = n_counters / 3;
497 for (i = 0; i < n_measures; i++, counters += 3)
499 value = gcov_read_counter ();
500 counter = gcov_read_counter ();
501 all = gcov_read_counter ();
503 if (counters[0] == value)
504 counters[1] += counter;
505 else if (counter > counters[1])
508 counters[1] = counter - counters[1];
511 counters[1] -= counter;
515 #endif /* L_gcov_merge_single */
517 #ifdef L_gcov_merge_delta
518 /* The profile merging function for choosing the most common difference between
519 two consecutive evaluations of the value. It is given an array COUNTERS of
520 N_COUNTERS old counters and it reads the same number of counters from the
521 gcov file. The counters are split into 4-tuples where the members of the
523 -- the last value of the measured entity
524 -- the stored candidate on the most common difference
526 -- total number of evaluations of the value */
528 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
530 unsigned i, n_measures;
531 gcov_type last, value, counter, all;
536 n_measures = n_counters / 4;
537 for (i = 0; i < n_measures; i++, counters += 4)
539 last = gcov_read_counter ();
540 value = gcov_read_counter ();
541 counter = gcov_read_counter ();
542 all = gcov_read_counter ();
544 if (counters[1] == value)
545 counters[2] += counter;
546 else if (counter > counters[2])
549 counters[2] = counter - counters[2];
552 counters[2] -= counter;
556 #endif /* L_gcov_merge_delta */
558 #endif /* inhibit_libc */