Missed one in last change.
[official-gcc.git] / gcc / libgcov.c
blob74d830dc1b04eeeda698d80dedbbdce1c7f3778c
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 /* 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;
188 c_ix++;
189 ci_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);
203 if (!merging)
205 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
206 continue;
209 if (merging > 0)
211 /* Merge data from file. */
212 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
214 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
215 gi_ptr->filename);
216 read_fatal:;
217 gcov_close ();
218 continue;
220 length = gcov_read_unsigned ();
221 if (length != GCOV_VERSION)
223 gcov_version_mismatch (gi_ptr, length);
224 goto read_fatal;
227 /* Merge execution counts for each function. */
228 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
229 f_ix--;
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 ();
236 /* Check function. */
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)
242 read_mismatch:;
243 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
244 gi_ptr->filename,
245 f_ix + 1 ? "function" : "summaries");
246 goto read_fatal;
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))
259 goto read_mismatch;
260 (*merge) (values[c_ix], n_counts);
261 values[c_ix] += n_counts;
262 c_ix++;
264 if ((error = gcov_is_error ()))
265 goto read_error;
268 /* Check program & object summary */
269 while (1)
271 gcov_position_t base = gcov_position ();
272 int is_program;
274 tag = gcov_read_unsigned ();
275 if (!tag)
276 break;
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))
281 goto read_mismatch;
282 gcov_read_summary (is_program ? &program : &object);
283 if ((error = gcov_is_error ()))
284 goto read_error;
285 if (is_program && program.checksum == gcov_crc32)
287 summary_pos = base;
288 goto rewrite;
291 if (!gcov_is_eof ())
293 read_error:;
294 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
295 : "profiling:%s:Error merging\n", gi_ptr->filename);
296 goto read_fatal;
298 rewrite:;
299 gcov_rewrite ();
301 else
302 memset (&object, 0, sizeof (object));
303 if (!summary_pos)
304 memset (&program, 0, sizeof (program));
306 /* Merge the summaries. */
307 f_ix = ~0u;
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,
311 cs_all = all.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)
317 if (!cs_obj->runs++)
318 cs_obj->num = cs_tobj->num;
319 else if (cs_obj->num != cs_tobj->num)
320 goto read_mismatch;
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;
326 if (!cs_prg->runs++)
327 cs_prg->num = cs_tprg->num;
328 else if (cs_prg->num != cs_tprg->num)
329 goto read_mismatch;
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;
336 c_ix++;
338 else if (cs_obj->num || cs_prg->num)
339 goto read_mismatch;
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");
350 all.checksum = ~0u;
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];
373 gcov_type *c_ptr;
375 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
376 GCOV_TAG_COUNTER_LENGTH (n_counts));
377 c_ptr = values[c_ix];
378 while (n_counts--)
379 gcov_write_counter (*c_ptr++);
380 values[c_ix] = c_ptr;
381 c_ix++;
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",
395 gi_ptr->filename);
399 /* Add a new object file onto the bb chain. Invoked automatically
400 when running an object file's global ctors. */
402 void
403 __gcov_init (struct gcov_info *info)
405 if (!info->version)
406 return;
407 if (info->version != GCOV_VERSION)
408 gcov_version_mismatch (info, info->version);
409 else
411 const char *ptr = info->filename;
412 gcov_unsigned_t crc32 = gcov_crc32;
416 unsigned ix;
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;
424 crc32 <<= 1;
425 crc32 ^= feedback;
428 while (*ptr++);
430 gcov_crc32 = crc32;
432 if (!gcov_list)
433 atexit (gcov_exit);
435 info->next = gcov_list;
436 gcov_list = info;
438 info->version = 0;
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. */
445 void
446 __gcov_flush (void)
448 const struct gcov_info *gi_ptr;
450 gcov_exit ();
451 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
453 unsigned t_ix;
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);
460 ci_ptr++;
465 #endif /* L_gcov */
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. */
471 void
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
485 -- counter
486 -- total number of evaluations of the value */
487 void
488 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
490 unsigned i, n_measures;
491 gcov_type value, counter, all;
493 if (n_counters % 3)
494 abort ();
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])
507 counters[0] = value;
508 counters[1] = counter - counters[1];
510 else
511 counters[1] -= counter;
512 counters[2] += all;
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
522 tuple have meanings:
523 -- the last value of the measured entity
524 -- the stored candidate on the most common difference
525 -- counter
526 -- total number of evaluations of the value */
527 void
528 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
530 unsigned i, n_measures;
531 gcov_type last, value, counter, all;
533 if (n_counters % 4)
534 abort ();
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])
548 counters[1] = value;
549 counters[2] = counter - counters[2];
551 else
552 counters[2] -= counter;
553 counters[3] += all;
556 #endif /* L_gcov_merge_delta */
558 #endif /* inhibit_libc */