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 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
45 #if defined (TARGET_HAS_F_SETLKW)
51 /* Chain of per-object gcov structures. */
52 static struct gcov_info *gcov_list;
54 /* A program checksum allows us to distinguish program data for an
55 object file included in multiple programs. */
56 static unsigned gcov_crc32;
59 gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
61 unsigned expected = GCOV_VERSION;
65 for (ix = 4; ix--; expected >>= 8, version >>= 8)
72 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
76 /* Dump the coverage counts. We merge with existing counts when
77 possible, to avoid growing the .da files ad infinitum. We use this
78 program's checksum to make sure we only accumulate whole program
79 statistics to the correct summary. An object file might be embedded
80 in two separate programs, and we must keep the two program
81 summaries separate. */
86 struct gcov_info *ptr;
88 struct gcov_summary program;
89 gcov_type program_max_one = 0;
90 gcov_type program_max_sum = 0;
91 gcov_type program_sum = 0;
92 unsigned program_arcs = 0;
94 #if defined (TARGET_HAS_F_SETLKW)
97 s_flock.l_type = F_WRLCK;
98 s_flock.l_whence = SEEK_SET;
100 s_flock.l_len = 0; /* Until EOF. */
101 s_flock.l_pid = getpid ();
104 memset (&program, 0, sizeof (program));
105 program.checksum = gcov_crc32;
107 for (ptr = gcov_list; ptr; ptr = ptr->next)
109 struct gcov_summary object;
110 struct gcov_summary local_prg;
113 const struct function_info *fn_info;
114 gcov_type **counters;
115 gcov_type *count_ptr;
116 gcov_type object_max_one = 0;
118 unsigned tag, length, flength, checksum;
119 unsigned arc_data_index, f_sect_index, sect_index;
125 counters = malloc (sizeof (gcov_type *) * ptr->n_counter_sections);
126 for (ix = 0; ix < ptr->n_counter_sections; ix++)
127 counters[ix] = ptr->counter_sections[ix].counters;
129 for (arc_data_index = 0;
130 arc_data_index < ptr->n_counter_sections
131 && ptr->counter_sections[arc_data_index].tag != GCOV_TAG_ARC_COUNTS;
135 if (arc_data_index == ptr->n_counter_sections)
137 /* For now; later we may want to just measure other profiles,
138 but now I am lazy to check for all consequences. */
141 for (ix = ptr->counter_sections[arc_data_index].n_counters,
142 count_ptr = ptr->counter_sections[arc_data_index].counters; ix--;)
144 gcov_type count = *count_ptr++;
146 if (count > object_max_one)
147 object_max_one = count;
149 if (object_max_one > program_max_one)
150 program_max_one = object_max_one;
152 memset (&local_prg, 0, sizeof (local_prg));
153 memset (&object, 0, sizeof (object));
155 /* Open for modification */
156 if (!da_file_open (ptr->filename, &merging))
158 fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
165 /* Merge data from file. */
167 if (gcov_read_unsigned (0, &tag) || tag != GCOV_DATA_MAGIC)
169 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
176 if (gcov_read_unsigned (0, &length) || length != GCOV_VERSION)
178 gcov_version_mismatch (ptr, length);
182 /* Merge execution counts for each function. */
183 for (ix = ptr->n_functions, fn_info = ptr->functions;
186 if (gcov_read_unsigned (0, &tag)
187 || gcov_read_unsigned (0, &length))
190 fprintf (stderr, "profiling:%s:Error merging\n",
196 if (tag != GCOV_TAG_FUNCTION)
199 fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
200 ptr->filename, fn_info->name);
204 if (gcov_read_unsigned (0, &flength)
205 || gcov_skip_string (0, flength)
206 || gcov_read_unsigned (0, &checksum))
208 if (flength != strlen (fn_info->name)
209 || checksum != fn_info->checksum)
213 for (f_sect_index = 0;
214 f_sect_index < fn_info->n_counter_sections;
219 if (gcov_read_unsigned (0, &tag)
220 || gcov_read_unsigned (0, &length))
223 sect_index < ptr->n_counter_sections;
225 if (ptr->counter_sections[sect_index].tag == tag)
227 if (sect_index == ptr->n_counter_sections
228 || fn_info->counter_sections[f_sect_index].tag != tag)
231 n_counters = fn_info->counter_sections[f_sect_index].n_counters;
232 if (n_counters != length / 8)
235 for (jx = 0; jx < n_counters; jx++)
236 if (gcov_read_counter (0, &count))
239 counters[sect_index][jx] += count;
240 counters[sect_index] += n_counters;
244 /* Check object summary */
245 if (gcov_read_unsigned (0, &tag)
246 || gcov_read_unsigned (0, &length))
248 if (tag != GCOV_TAG_OBJECT_SUMMARY)
250 if (gcov_read_summary (0, &object))
253 /* Check program summary */
256 long base = da_file_position (0);
258 if (gcov_read_unsigned (0, &tag)
259 || gcov_read_unsigned (0, &length))
265 if (tag != GCOV_TAG_PROGRAM_SUMMARY
266 && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
267 && tag != GCOV_TAG_INCORRECT_SUMMARY)
269 if (gcov_read_summary (0, &local_prg))
271 if (local_prg.checksum != program.checksum)
273 if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
276 "profiling:%s:Concurrent race detected\n",
281 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
285 && memcmp (&program, &local_prg, sizeof (program)))
287 fprintf (stderr, "profiling:%s:Invocation mismatch\n",
292 memcpy (&program, &local_prg, sizeof (program));
296 da_file_seek (0, 0, SEEK_SET);
300 object.arcs = ptr->counter_sections[arc_data_index].n_counters;
302 if (object.arc_max_one < object_max_one)
303 object.arc_max_one = object_max_one;
304 object.arc_sum_max += object_max_one;
306 /* Write out the data. */
308 gcov_write_unsigned (0, GCOV_DATA_MAGIC)
310 || gcov_write_unsigned (0, GCOV_VERSION))
314 fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
319 /* Write execution counts for each function. */
320 for (ix = 0; ix < ptr->n_counter_sections; ix++)
321 counters[ix] = ptr->counter_sections[ix].counters;
322 for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
324 /* Announce function. */
325 if (gcov_write_unsigned (0, GCOV_TAG_FUNCTION)
326 || !(base = gcov_reserve_length (0))
328 || gcov_write_string (0, fn_info->name,
329 strlen (fn_info->name))
330 /* function checksum */
331 || gcov_write_unsigned (0, fn_info->checksum)
332 || gcov_write_length (0, base))
336 for (f_sect_index = 0;
337 f_sect_index < fn_info->n_counter_sections;
340 tag = fn_info->counter_sections[f_sect_index].tag;
342 sect_index < ptr->n_counter_sections;
344 if (ptr->counter_sections[sect_index].tag == tag)
346 if (sect_index == ptr->n_counter_sections)
349 if (gcov_write_unsigned (0, tag)
350 || !(base = gcov_reserve_length (0)))
353 for (jx = fn_info->counter_sections[f_sect_index].n_counters; jx--;)
355 gcov_type count = *counters[sect_index]++;
357 if (tag == GCOV_TAG_ARC_COUNTS)
359 object.arc_sum += count;
360 if (object.arc_max_sum < count)
361 object.arc_max_sum = count;
363 if (gcov_write_counter (0, count))
364 goto write_error; /* RIP Edsger Dijkstra */
366 if (gcov_write_length (0, base))
371 /* Object file summary. */
372 if (gcov_write_summary (0, GCOV_TAG_OBJECT_SUMMARY, &object))
377 if (da_file_seek (0, 0, SEEK_END))
379 ptr->wkspc = da_file_position (0);
380 if (gcov_write_summary (0, GCOV_TAG_PLACEHOLDER_SUMMARY,
386 /* Zap trailing program summary */
387 if (da_file_seek (0, ptr->wkspc, SEEK_SET))
391 if (gcov_write_unsigned (0, local_prg.runs
392 ? GCOV_TAG_PLACEHOLDER_SUMMARY
393 : GCOV_TAG_INCORRECT_SUMMARY))
397 if (da_file_close ())
399 fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
404 program_arcs += ptr->counter_sections[arc_data_index].n_counters;
405 program_sum += object.arc_sum;
406 if (program_max_sum < object.arc_max_sum)
407 program_max_sum = object.arc_max_sum;
412 /* Generate whole program statistics. */
414 program.arcs = program_arcs;
415 program.arc_sum = program_sum;
416 if (program.arc_max_one < program_max_one)
417 program.arc_max_one = program_max_one;
418 if (program.arc_max_sum < program_max_sum)
419 program.arc_max_sum = program_max_sum;
420 program.arc_sum_max += program_max_one;
422 /* Upate whole program statistics. */
423 for (ptr = gcov_list; ptr; ptr = ptr->next)
424 if (ptr->filename && ptr->wkspc)
428 da_file = fopen (ptr->filename, "r+b");
431 fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
435 #if defined (TARGET_HAS_F_SETLKW)
436 while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
440 if (fseek (da_file, ptr->wkspc, SEEK_SET)
441 || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
443 fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
444 if (fclose (da_file))
445 fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
449 /* Add a new object file onto the bb chain. Invoked automatically
450 when running an object file's global ctors. */
453 __gcov_init (struct gcov_info *info)
457 if (info->version != GCOV_VERSION)
458 gcov_version_mismatch (info, info->version);
461 const char *ptr = info->filename;
462 unsigned crc32 = gcov_crc32;
467 unsigned value = *ptr << 24;
469 for (ix = 8; ix--; value <<= 1)
473 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
485 info->next = gcov_list;
491 /* Called before fork or exec - write out profile information gathered so
492 far and reset it to zero. This avoids duplication or loss of the
493 profile information gathered so far. */
498 struct gcov_info *ptr;
501 for (ptr = gcov_list; ptr; ptr = ptr->next)
505 for (j = 0; j < ptr->n_counter_sections; j++)
506 for (i = ptr->counter_sections[j].n_counters; i--;)
507 ptr->counter_sections[j].counters[i] = 0;