* gcov-io.h: Add a local time stamp.
[official-gcc.git] / gcc / libgcov.c
blob72126466f66c40235836dad14d0dccd83ff4ecf9
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
11 version.
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
20 executable.)
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
25 for more details.
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
30 02111-1307, USA. */
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
34 do not apply. */
36 #include "tconfig.h"
37 #include "tsystem.h"
38 #include "coretypes.h"
39 #include "tm.h"
41 #if defined(inhibit_libc)
42 #define IN_LIBGCOV (-1)
43 #else
44 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
45 #include <stdio.h>
46 #define IN_LIBGCOV 1
47 #if defined(L_gcov)
48 #define GCOV_LINKAGE /* nothing */
49 #endif
50 #endif
51 #include "gcov-io.h"
53 #if defined(inhibit_libc)
54 /* If libc and its header files are not available, provide dummy functions. */
56 #ifdef L_gcov
57 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
58 void __gcov_flush (void) {}
59 #endif
61 #ifdef L_gcov_merge_add
62 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
63 unsigned n_counters __attribute__ ((unused))) {}
64 #endif
66 #ifdef L_gcov_merge_single
67 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
68 unsigned n_counters __attribute__ ((unused))) {}
69 #endif
71 #ifdef L_gcov_merge_delta
72 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
73 unsigned n_counters __attribute__ ((unused))) {}
74 #endif
76 #else
78 #include <string.h>
79 #if GCOV_LOCKED
80 #include <fcntl.h>
81 #include <errno.h>
82 #endif
84 #ifdef L_gcov
85 #include "gcov-io.c"
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;
94 static void
95 gcov_version_mismatch (struct gcov_info *ptr, gcov_unsigned_t version)
97 gcov_unsigned_t expected = GCOV_VERSION;
98 unsigned ix;
99 char e[4], v[4];
101 for (ix = 4; ix--; expected >>= 8, version >>= 8)
103 e[ix] = expected;
104 v[ix] = version;
107 fprintf (stderr,
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. */
119 static void
120 gcov_exit (void)
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;
133 unsigned t_ix;
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;
149 ci_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;
160 unsigned fi_stride;
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;
165 int error = 0;
166 int merging;
167 gcov_unsigned_t tag, length;
168 gcov_position_t summary_pos = 0;
170 memset (&this_object, 0, sizeof (this_object));
171 memset (&object, 0, sizeof (object));
173 /* Totals for this object file. */
174 for (t_ix = c_ix = 0,
175 ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
176 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
177 if ((1 << t_ix) & gi_ptr->ctr_mask)
179 const gcov_type *c_ptr;
180 gcov_unsigned_t c_num;
182 cs_ptr->num += ci_ptr->num;
183 values[c_ix] = ci_ptr->values;
184 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
186 cs_ptr->sum_all += *c_ptr;
187 if (cs_ptr->run_max < *c_ptr)
188 cs_ptr->run_max = *c_ptr;
190 c_ix++;
191 ci_ptr++;
194 /* Calculate the function_info stride. This depends on the
195 number of counter types being measured. */
196 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
197 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
199 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
200 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
203 /* Open for modification, if possible */
204 merging = gcov_open (gi_ptr->filename, 0);
205 if (!merging)
207 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
208 continue;
211 if (merging > 0)
213 /* Merge data from file. */
214 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
216 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
217 gi_ptr->filename);
218 read_fatal:;
219 gcov_close ();
220 continue;
222 length = gcov_read_unsigned ();
223 if (length != GCOV_VERSION)
225 gcov_version_mismatch (gi_ptr, length);
226 goto read_fatal;
229 length = gcov_read_unsigned ();
230 if (length != gi_ptr->stamp)
232 /* Read from a different compilation. Overwrite the
233 file. */
234 gcov_truncate ();
235 goto rewrite;
238 /* Merge execution counts for each function. */
239 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
240 f_ix--;
241 fi_ptr = (const struct gcov_fn_info *)
242 ((const char *) fi_ptr + fi_stride))
244 tag = gcov_read_unsigned ();
245 length = gcov_read_unsigned ();
247 /* Check function. */
248 if (tag != GCOV_TAG_FUNCTION
249 || length != GCOV_TAG_FUNCTION_LENGTH
250 || gcov_read_unsigned () != fi_ptr->ident
251 || gcov_read_unsigned () != fi_ptr->checksum)
253 read_mismatch:;
254 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
255 gi_ptr->filename,
256 f_ix + 1 ? "function" : "summaries");
257 goto read_fatal;
260 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
261 if ((1 << t_ix) & gi_ptr->ctr_mask)
263 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
264 gcov_merge_fn merge = gi_ptr->counts[c_ix].merge;
266 tag = gcov_read_unsigned ();
267 length = gcov_read_unsigned ();
268 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
269 || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
270 goto read_mismatch;
271 (*merge) (values[c_ix], n_counts);
272 values[c_ix] += n_counts;
273 c_ix++;
275 if ((error = gcov_is_error ()))
276 goto read_error;
279 /* Check program & object summary */
280 while (1)
282 gcov_position_t base = gcov_position ();
283 int is_program;
285 tag = gcov_read_unsigned ();
286 if (!tag)
287 break;
288 length = gcov_read_unsigned ();
289 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
290 if (length != GCOV_TAG_SUMMARY_LENGTH
291 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
292 goto read_mismatch;
293 gcov_read_summary (is_program ? &program : &object);
294 if ((error = gcov_is_error ()))
295 goto read_error;
296 if (is_program && program.checksum == gcov_crc32)
298 summary_pos = base;
299 goto rewrite;
302 if (!gcov_is_eof ())
304 read_error:;
305 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
306 : "profiling:%s:Error merging\n", gi_ptr->filename);
307 goto read_fatal;
309 rewrite:;
310 gcov_rewrite ();
312 if (!summary_pos)
313 memset (&program, 0, sizeof (program));
315 /* Merge the summaries. */
316 f_ix = ~0u;
317 for (t_ix = c_ix = 0,
318 cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
319 cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
320 cs_all = all.ctrs;
321 t_ix != GCOV_COUNTERS_SUMMABLE;
322 t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
324 if ((1 << t_ix) & gi_ptr->ctr_mask)
326 if (!cs_obj->runs++)
327 cs_obj->num = cs_tobj->num;
328 else if (cs_obj->num != cs_tobj->num)
329 goto read_mismatch;
330 cs_obj->sum_all += cs_tobj->sum_all;
331 if (cs_obj->run_max < cs_tobj->run_max)
332 cs_obj->run_max = cs_tobj->run_max;
333 cs_obj->sum_max += cs_tobj->run_max;
335 if (!cs_prg->runs++)
336 cs_prg->num = cs_tprg->num;
337 else if (cs_prg->num != cs_tprg->num)
338 goto read_mismatch;
339 cs_prg->sum_all += cs_tprg->sum_all;
340 if (cs_prg->run_max < cs_tprg->run_max)
341 cs_prg->run_max = cs_tprg->run_max;
342 cs_prg->sum_max += cs_tprg->run_max;
344 values[c_ix] = gi_ptr->counts[c_ix].values;
345 c_ix++;
347 else if (cs_obj->num || cs_prg->num)
348 goto read_mismatch;
350 if (!cs_all->runs && cs_prg->runs)
351 memcpy (cs_all, cs_prg, sizeof (*cs_all));
352 else if (!all.checksum
353 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
354 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
356 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
357 gi_ptr->filename, GCOV_LOCKED
358 ? "" : " or concurrent update without locking support");
359 all.checksum = ~0u;
363 program.checksum = gcov_crc32;
365 /* Write out the data. */
366 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
367 gcov_write_unsigned (gi_ptr->stamp);
369 /* Write execution counts for each function. */
370 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
371 fi_ptr = (const struct gcov_fn_info *)
372 ((const char *) fi_ptr + fi_stride))
374 /* Announce function. */
375 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
376 gcov_write_unsigned (fi_ptr->ident);
377 gcov_write_unsigned (fi_ptr->checksum);
379 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
380 if ((1 << t_ix) & gi_ptr->ctr_mask)
382 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
383 gcov_type *c_ptr;
385 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
386 GCOV_TAG_COUNTER_LENGTH (n_counts));
387 c_ptr = values[c_ix];
388 while (n_counts--)
389 gcov_write_counter (*c_ptr++);
390 values[c_ix] = c_ptr;
391 c_ix++;
395 /* Object file summary. */
396 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
398 /* Generate whole program statistics. */
399 gcov_seek (summary_pos);
400 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
401 if ((error = gcov_close ()))
402 fprintf (stderr, error < 0 ?
403 "profiling:%s:Overflow writing\n" :
404 "profiling:%s:Error writing\n",
405 gi_ptr->filename);
409 /* Add a new object file onto the bb chain. Invoked automatically
410 when running an object file's global ctors. */
412 void
413 __gcov_init (struct gcov_info *info)
415 if (!info->version)
416 return;
417 if (info->version != GCOV_VERSION)
418 gcov_version_mismatch (info, info->version);
419 else
421 const char *ptr = info->filename;
422 gcov_unsigned_t crc32 = gcov_crc32;
426 unsigned ix;
427 gcov_unsigned_t value = *ptr << 24;
429 for (ix = 8; ix--; value <<= 1)
431 gcov_unsigned_t feedback;
433 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
434 crc32 <<= 1;
435 crc32 ^= feedback;
438 while (*ptr++);
440 gcov_crc32 = crc32;
442 if (!gcov_list)
443 atexit (gcov_exit);
445 info->next = gcov_list;
446 gcov_list = info;
448 info->version = 0;
451 /* Called before fork or exec - write out profile information gathered so
452 far and reset it to zero. This avoids duplication or loss of the
453 profile information gathered so far. */
455 void
456 __gcov_flush (void)
458 const struct gcov_info *gi_ptr;
460 gcov_exit ();
461 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
463 unsigned t_ix;
464 const struct gcov_ctr_info *ci_ptr;
466 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
467 if ((1 << t_ix) & gi_ptr->ctr_mask)
469 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
470 ci_ptr++;
475 #endif /* L_gcov */
477 #ifdef L_gcov_merge_add
478 /* The profile merging function that just adds the counters. It is given
479 an array COUNTERS of N_COUNTERS old counters and it reads the same number
480 of counters from the gcov file. */
481 void
482 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
484 for (; n_counters; counters++, n_counters--)
485 *counters += gcov_read_counter ();
487 #endif /* L_gcov_merge_add */
489 #ifdef L_gcov_merge_single
490 /* The profile merging function for choosing the most common value. It is given
491 an array COUNTERS of N_COUNTERS old counters and it reads the same number
492 of counters from the gcov file. The counters are split into 3-tuples
493 where the members of the tuple have meanings:
494 -- the stored candidate on the most common value of the measured entity
495 -- counter
496 -- total number of evaluations of the value */
497 void
498 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
500 unsigned i, n_measures;
501 gcov_type value, counter, all;
503 if (n_counters % 3)
504 abort ();
506 n_measures = n_counters / 3;
507 for (i = 0; i < n_measures; i++, counters += 3)
509 value = gcov_read_counter ();
510 counter = gcov_read_counter ();
511 all = gcov_read_counter ();
513 if (counters[0] == value)
514 counters[1] += counter;
515 else if (counter > counters[1])
517 counters[0] = value;
518 counters[1] = counter - counters[1];
520 else
521 counters[1] -= counter;
522 counters[2] += all;
525 #endif /* L_gcov_merge_single */
527 #ifdef L_gcov_merge_delta
528 /* The profile merging function for choosing the most common difference between
529 two consecutive evaluations of the value. It is given an array COUNTERS of
530 N_COUNTERS old counters and it reads the same number of counters from the
531 gcov file. The counters are split into 4-tuples where the members of the
532 tuple have meanings:
533 -- the last value of the measured entity
534 -- the stored candidate on the most common difference
535 -- counter
536 -- total number of evaluations of the value */
537 void
538 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
540 unsigned i, n_measures;
541 gcov_type last, value, counter, all;
543 if (n_counters % 4)
544 abort ();
546 n_measures = n_counters / 4;
547 for (i = 0; i < n_measures; i++, counters += 4)
549 last = gcov_read_counter ();
550 value = gcov_read_counter ();
551 counter = gcov_read_counter ();
552 all = gcov_read_counter ();
554 if (counters[1] == value)
555 counters[2] += counter;
556 else if (counter > counters[2])
558 counters[1] = value;
559 counters[2] = counter - counters[2];
561 else
562 counters[2] -= counter;
563 counters[3] += all;
566 #endif /* L_gcov_merge_delta */
568 #endif /* inhibit_libc */