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. */
46 #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
)
110 struct gcov_summary object
;
111 struct gcov_summary local_prg
;
114 const struct function_info
*fn_info
;
115 gcov_type
*count_ptr
;
116 gcov_type object_max_one
= 0;
122 for (ix
= ptr
->n_arc_counts
, count_ptr
= ptr
->arc_counts
; ix
--;)
124 gcov_type count
= *count_ptr
++;
126 if (count
> object_max_one
)
127 object_max_one
= count
;
129 if (object_max_one
> program_max_one
)
130 program_max_one
= object_max_one
;
132 memset (&local_prg
, 0, sizeof (local_prg
));
133 memset (&object
, 0, sizeof (object
));
135 /* Open for modification */
136 if ((da_file
= fopen (ptr
->filename
, "r+b")))
138 else if ((da_file
= fopen (ptr
->filename
, "w+b")))
142 fprintf (stderr
, "profiling:%s:Cannot open\n", ptr
->filename
);
147 #if defined (TARGET_HAS_F_SETLKW)
148 /* After a fork, another process might try to read and/or write
149 the same file simultaneously. So if we can, lock the file to
150 avoid race conditions. */
151 while (fcntl (fileno (da_file
), F_SETLKW
, &s_flock
)
157 /* Merge data from file. */
158 unsigned tag
, length
;
160 if (gcov_read_unsigned (da_file
, &tag
) || tag
!= GCOV_DATA_MAGIC
)
162 fprintf (stderr
, "profiling:%s:Not a gcov data file\n",
169 if (gcov_read_unsigned (da_file
, &length
) || length
!= GCOV_VERSION
)
171 gcov_version_mismatch (ptr
, length
);
175 /* Merge execution counts for each function. */
176 count_ptr
= ptr
->arc_counts
;
177 for (ix
= ptr
->n_functions
, fn_info
= ptr
->functions
;
180 if (gcov_read_unsigned (da_file
, &tag
)
181 || gcov_read_unsigned (da_file
, &length
))
184 fprintf (stderr
, "profiling:%s:Error merging\n",
190 if (tag
!= GCOV_TAG_FUNCTION
)
193 fprintf (stderr
, "profiling:%s:Merge mismatch at %s\n",
194 ptr
->filename
, fn_info
->name
);
198 unsigned flength
, checksum
;
200 if (gcov_read_unsigned (da_file
, &flength
)
201 || gcov_skip_string (da_file
, flength
)
202 || gcov_read_unsigned (da_file
, &checksum
))
204 if (flength
!= strlen (fn_info
->name
)
205 || checksum
!= fn_info
->checksum
)
208 /* Check arc counts */
209 if (gcov_read_unsigned (da_file
, &tag
)
210 || gcov_read_unsigned (da_file
, &length
))
212 if (tag
!= GCOV_TAG_ARC_COUNTS
213 || length
/ 8 != fn_info
->n_arc_counts
)
218 for (jx
= fn_info
->n_arc_counts
; jx
--; count_ptr
++)
219 if (gcov_read_counter (da_file
, &count
))
226 /* Check object summary */
227 if (gcov_read_unsigned (da_file
, &tag
)
228 || gcov_read_unsigned (da_file
, &length
))
230 if (tag
!= GCOV_TAG_OBJECT_SUMMARY
)
232 if (gcov_read_summary (da_file
, &object
))
235 /* Check program summary */
238 long base
= ftell (da_file
);
240 if (gcov_read_unsigned (da_file
, &tag
)
241 || gcov_read_unsigned (da_file
, &length
))
247 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
248 && tag
!= GCOV_TAG_PLACEHOLDER_SUMMARY
249 && tag
!= GCOV_TAG_INCORRECT_SUMMARY
)
251 if (gcov_read_summary (da_file
, &local_prg
))
253 if (local_prg
.checksum
!= program
.checksum
)
255 if (tag
== GCOV_TAG_PLACEHOLDER_SUMMARY
)
258 "profiling:%s:Concurrent race detected\n",
263 if (tag
!= GCOV_TAG_PROGRAM_SUMMARY
)
267 && memcmp (&program
, &local_prg
, sizeof (program
)))
269 fprintf (stderr
, "profiling:%s:Invocation mismatch\n",
274 memcpy (&program
, &local_prg
, sizeof (program
));
278 fseek (da_file
, 0, SEEK_SET
);
282 object
.arcs
= ptr
->n_arc_counts
;
284 if (object
.arc_max_one
< object_max_one
)
285 object
.arc_max_one
= object_max_one
;
286 object
.arc_sum_max
+= object_max_one
;
288 /* Write out the data. */
290 gcov_write_unsigned (da_file
, GCOV_DATA_MAGIC
)
292 || gcov_write_unsigned (da_file
, GCOV_VERSION
))
296 fprintf (stderr
, "profiling:%s:Error writing\n", ptr
->filename
);
301 /* Write execution counts for each function. */
302 count_ptr
= ptr
->arc_counts
;
303 for (ix
= ptr
->n_functions
, fn_info
= ptr
->functions
; ix
--; fn_info
++)
305 /* Announce function. */
306 if (gcov_write_unsigned (da_file
, GCOV_TAG_FUNCTION
)
307 || !(base
= gcov_reserve_length (da_file
))
309 || gcov_write_string (da_file
, fn_info
->name
,
310 strlen (fn_info
->name
))
311 /* function checksum */
312 || gcov_write_unsigned (da_file
, fn_info
->checksum
)
313 || gcov_write_length (da_file
, base
))
317 if (gcov_write_unsigned (da_file
, GCOV_TAG_ARC_COUNTS
)
318 || !(base
= gcov_reserve_length (da_file
)))
321 for (jx
= fn_info
->n_arc_counts
; jx
--;)
323 gcov_type count
= *count_ptr
++;
325 object
.arc_sum
+= count
;
326 if (object
.arc_max_sum
< count
)
327 object
.arc_max_sum
= count
;
328 if (gcov_write_counter (da_file
, count
))
329 goto write_error
; /* RIP Edsger Dijkstra */
331 if (gcov_write_length (da_file
, base
))
335 /* Object file summary. */
336 if (gcov_write_summary (da_file
, GCOV_TAG_OBJECT_SUMMARY
, &object
))
341 if (fseek (da_file
, 0, SEEK_END
))
343 ptr
->wkspc
= ftell (da_file
);
344 if (gcov_write_summary (da_file
, GCOV_TAG_PLACEHOLDER_SUMMARY
,
350 /* Zap trailing program summary */
351 if (fseek (da_file
, ptr
->wkspc
, SEEK_SET
))
355 if (gcov_write_unsigned (da_file
,
356 local_prg
.runs
? GCOV_TAG_PLACEHOLDER_SUMMARY
357 : GCOV_TAG_INCORRECT_SUMMARY
))
360 if (fflush (da_file
))
363 if (fclose (da_file
))
365 fprintf (stderr
, "profiling:%s:Error closing\n", ptr
->filename
);
370 program_arcs
+= ptr
->n_arc_counts
;
371 program_sum
+= object
.arc_sum
;
372 if (program_max_sum
< object
.arc_max_sum
)
373 program_max_sum
= object
.arc_max_sum
;
377 /* Generate whole program statistics. */
379 program
.arcs
= program_arcs
;
380 program
.arc_sum
= program_sum
;
381 if (program
.arc_max_one
< program_max_one
)
382 program
.arc_max_one
= program_max_one
;
383 if (program
.arc_max_sum
< program_max_sum
)
384 program
.arc_max_sum
= program_max_sum
;
385 program
.arc_sum_max
+= program_max_one
;
387 /* Upate whole program statistics. */
388 for (ptr
= gcov_list
; ptr
; ptr
= ptr
->next
)
389 if (ptr
->filename
&& ptr
->wkspc
)
393 da_file
= fopen (ptr
->filename
, "r+b");
396 fprintf (stderr
, "profiling:%s:Cannot open\n", ptr
->filename
);
400 #if defined (TARGET_HAS_F_SETLKW)
401 while (fcntl (fileno (da_file
), F_SETLKW
, &s_flock
)
405 if (fseek (da_file
, ptr
->wkspc
, SEEK_SET
)
406 || gcov_write_summary (da_file
, GCOV_TAG_PROGRAM_SUMMARY
, &program
)
408 fprintf (stderr
, "profiling:%s:Error writing\n", ptr
->filename
);
409 if (fclose (da_file
))
410 fprintf (stderr
, "profiling:%s:Error closing\n", ptr
->filename
);
414 /* Add a new object file onto the bb chain. Invoked automatically
415 when running an object file's global ctors. */
418 __gcov_init (struct gcov_info
*info
)
422 if (info
->version
!= GCOV_VERSION
)
423 gcov_version_mismatch (info
, info
->version
);
426 const char *ptr
= info
->filename
;
427 unsigned crc32
= gcov_crc32
;
432 unsigned value
= *ptr
<< 24;
434 for (ix
= 8; ix
--; value
<<= 1)
438 feedback
= (value
^ crc32
) & 0x80000000 ? 0x04c11db7 : 0;
450 info
->next
= gcov_list
;
456 /* Called before fork or exec - write out profile information gathered so
457 far and reset it to zero. This avoids duplication or loss of the
458 profile information gathered so far. */
463 struct gcov_info
*ptr
;
466 for (ptr
= gcov_list
; ptr
; ptr
= ptr
->next
)
470 for (i
= ptr
->n_arc_counts
; i
--;)
471 ptr
->arc_counts
[i
] = 0;