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 #if defined(inhibit_libc)
33 /* If libc and its header files are not available, provide dummy functions. */
36 void __gcov_init (void *p);
37 void __gcov_flush (void);
39 void __gcov_init (void *p) { }
40 void __gcov_flush (void) { }
43 #ifdef L_gcov_merge_add
44 void __gcov_merge_add (gcov_type *, unsigned);
46 void __gcov_merge_add (gcov_type *counters, unsigned n_counters) { }
51 /* It is incorrect to include config.h here, because this file is being
52 compiled for the target, and hence definitions concerning only the host
57 #include "coretypes.h"
60 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
64 #if defined (TARGET_HAS_F_SETLKW)
74 /* Chain of per-object gcov structures. */
75 static struct gcov_info *gcov_list;
77 /* A program checksum allows us to distinguish program data for an
78 object file included in multiple programs. */
79 static unsigned gcov_crc32;
82 gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
84 unsigned expected = GCOV_VERSION;
88 for (ix = 4; ix--; expected >>= 8, version >>= 8)
95 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
99 /* Dump the coverage counts. We merge with existing counts when
100 possible, to avoid growing the .da files ad infinitum. We use this
101 program's checksum to make sure we only accumulate whole program
102 statistics to the correct summary. An object file might be embedded
103 in two separate programs, and we must keep the two program
104 summaries separate. */
109 struct gcov_info *gi_ptr;
110 struct gcov_summary this_program;
111 struct gcov_summary all;
113 memset (&all, 0, sizeof (all));
114 /* Find the totals for this execution. */
115 memset (&this_program, 0, sizeof (this_program));
116 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
118 const struct gcov_ctr_info *ci_ptr;
119 struct gcov_ctr_summary *cs_ptr;
122 for (t_ix = 0, ci_ptr = gi_ptr->counts, cs_ptr = this_program.ctrs;
123 t_ix != GCOV_COUNTERS; t_ix++, cs_ptr++)
124 if ((1 << t_ix) & gi_ptr->ctr_mask)
126 const gcov_type *c_ptr;
129 cs_ptr->num += ci_ptr->num;
130 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
132 cs_ptr->sum_all += *c_ptr;
133 if (cs_ptr->run_max < *c_ptr)
134 cs_ptr->run_max = *c_ptr;
140 /* Now write the data */
141 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
143 struct gcov_summary this_object;
144 struct gcov_summary object, program;
145 gcov_type *values[GCOV_COUNTERS];
146 const struct gcov_fn_info *fi_ptr;
148 unsigned c_ix, t_ix, f_ix;
149 const struct gcov_ctr_info *ci_ptr;
150 struct gcov_ctr_summary *cs_ptr;
151 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
155 unsigned tag, length;
156 unsigned long summary_pos = 0;
158 /* Totals for this object file. */
159 memset (&this_object, 0, sizeof (this_object));
160 for (t_ix = c_ix = 0,
161 ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
162 t_ix != GCOV_COUNTERS; t_ix++, cs_ptr++)
163 if ((1 << t_ix) & gi_ptr->ctr_mask)
165 const gcov_type *c_ptr;
168 cs_ptr->num += ci_ptr->num;
169 values[c_ix] = ci_ptr->values;
170 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
172 cs_ptr->sum_all += *c_ptr;
173 if (cs_ptr->run_max < *c_ptr)
174 cs_ptr->run_max = *c_ptr;
180 /* Calculate the function_info stride. This depends on the
181 number of counter types being measured. */
182 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
183 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
185 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
186 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
189 /* Open for modification, if possible */
190 merging = gcov_open (gi_ptr->filename, 0);
193 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
199 /* Merge data from file. */
200 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
202 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
208 length = gcov_read_unsigned ();
209 if (length != GCOV_VERSION)
211 gcov_version_mismatch (gi_ptr, length);
215 /* Merge execution counts for each function. */
216 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
218 fi_ptr = (const struct gcov_fn_info *)
219 ((const char *) fi_ptr + fi_stride))
221 tag = gcov_read_unsigned ();
222 length = gcov_read_unsigned ();
225 if (tag != GCOV_TAG_FUNCTION
226 || gcov_read_unsigned () != fi_ptr->ident
227 || gcov_read_unsigned () != fi_ptr->checksum)
230 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
232 f_ix + 1 ? "function" : "summaries");
236 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
237 if ((1 << t_ix) & gi_ptr->ctr_mask)
242 tag = gcov_read_unsigned ();
243 length = gcov_read_unsigned ();
245 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
246 || fi_ptr->n_ctrs[c_ix] * 8 != length)
248 n_counts = fi_ptr->n_ctrs[c_ix];
249 merge = gi_ptr->counts[c_ix].merge;
250 (*merge) (values[c_ix], n_counts);
251 values[c_ix] += n_counts;
254 if ((error = gcov_is_error ()))
258 /* Check object summary */
259 if (gcov_read_unsigned () != GCOV_TAG_OBJECT_SUMMARY)
261 gcov_read_unsigned ();
262 gcov_read_summary (&object);
264 /* Check program summary */
265 while (!gcov_is_eof ())
267 base = gcov_position ();
268 tag = gcov_read_unsigned ();
269 gcov_read_unsigned ();
270 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
272 gcov_read_summary (&program);
273 if ((error = gcov_is_error ()))
276 fprintf (stderr, error < 0 ?
277 "profiling:%s:Overflow merging\n" :
278 "profiling:%s:Error merging\n",
283 if (program.checksum != gcov_crc32)
291 memset (&object, 0, sizeof (object));
293 memset (&program, 0, sizeof (program));
295 /* Merge the summaries. */
297 for (t_ix = c_ix = 0,
298 cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
299 cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
301 t_ix != GCOV_COUNTERS;
302 t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
304 if ((1 << t_ix) & gi_ptr->ctr_mask)
307 cs_obj->num = cs_tobj->num;
308 else if (cs_obj->num != cs_tobj->num)
310 cs_obj->sum_all += cs_tobj->sum_all;
311 if (cs_obj->run_max < cs_tobj->run_max)
312 cs_obj->run_max = cs_tobj->run_max;
313 cs_obj->sum_max += cs_tobj->run_max;
316 cs_prg->num = cs_tprg->num;
317 else if (cs_prg->num != cs_tprg->num)
319 cs_prg->sum_all += cs_tprg->sum_all;
320 if (cs_prg->run_max < cs_tprg->run_max)
321 cs_prg->run_max = cs_tprg->run_max;
322 cs_prg->sum_max += cs_tprg->run_max;
324 values[c_ix] = gi_ptr->counts[c_ix].values;
327 else if (cs_obj->num || cs_prg->num)
330 if (!cs_all->runs && cs_prg->runs)
331 memcpy (cs_all, cs_prg, sizeof (*cs_all));
332 else if (!all.checksum
333 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
334 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
336 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
337 gi_ptr->filename, GCOV_LOCKED
338 ? "" : " or concurrent update without locking support");
343 program.checksum = gcov_crc32;
345 /* Write out the data. */
346 gcov_write_unsigned (GCOV_DATA_MAGIC);
347 gcov_write_unsigned (GCOV_VERSION);
349 /* Write execution counts for each function. */
350 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
351 fi_ptr = (const struct gcov_fn_info *)
352 ((const char *) fi_ptr + fi_stride))
354 /* Announce function. */
355 base = gcov_write_tag (GCOV_TAG_FUNCTION);
356 gcov_write_unsigned (fi_ptr->ident);
357 gcov_write_unsigned (fi_ptr->checksum);
358 gcov_write_length (base);
360 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
361 if ((1 << t_ix) & gi_ptr->ctr_mask)
366 base = gcov_write_tag (GCOV_TAG_FOR_COUNTER (t_ix));
367 c_ptr = values[c_ix];
368 for (n_counts = fi_ptr->n_ctrs[c_ix]; n_counts--; c_ptr++)
369 gcov_write_counter (*c_ptr);
370 values[c_ix] = c_ptr;
371 gcov_write_length (base);
376 /* Object file summary. */
377 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
379 /* Generate whole program statistics. */
381 gcov_seek (summary_pos, 0);
384 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
385 if ((error = gcov_close ()))
387 fprintf (stderr, error < 0 ?
388 "profiling:%s:Overflow writing\n" :
389 "profiling:%s:Error writing\n",
391 gi_ptr->filename = 0;
396 /* Add a new object file onto the bb chain. Invoked automatically
397 when running an object file's global ctors. */
400 __gcov_init (struct gcov_info *info)
404 if (info->version != GCOV_VERSION)
405 gcov_version_mismatch (info, info->version);
408 const char *ptr = info->filename;
409 unsigned crc32 = gcov_crc32;
414 unsigned value = *ptr << 24;
416 for (ix = 8; ix--; value <<= 1)
420 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
432 info->next = gcov_list;
438 /* Called before fork or exec - write out profile information gathered so
439 far and reset it to zero. This avoids duplication or loss of the
440 profile information gathered so far. */
445 const struct gcov_info *gi_ptr;
448 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
451 const struct gcov_ctr_info *ci_ptr;
453 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
454 if ((1 << t_ix) & gi_ptr->ctr_mask)
456 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
464 #ifdef L_gcov_merge_add
465 /* The profile merging function that just adds the counters. It is given
466 an array COUNTERS of N_COUNTERS old counters and it reads the same number
467 of counters from the gcov file. */
469 __gcov_merge_add (counters, n_counters)
473 for (; n_counters; counters++, n_counters--)
474 *counters += gcov_read_counter ();
476 #endif /* L_gcov_merge_add */
478 #endif /* inhibit_libc */