libgcov.c revision 132718
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. 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13In addition to the permissions in the GNU General Public License, the 14Free Software Foundation gives you unlimited permission to link the 15compiled version of this file into combinations with other programs, 16and to distribute those combinations without any restriction coming 17from the use of this file. (The General Public License restrictions 18do apply in other respects; for example, they cover modification of 19the file, and distribution when not linked into a combine 20executable.) 21 22GCC is distributed in the hope that it will be useful, but WITHOUT ANY 23WARRANTY; without even the implied warranty of MERCHANTABILITY or 24FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25for more details. 26 27You should have received a copy of the GNU General Public License 28along with GCC; see the file COPYING. If not, write to the Free 29Software Foundation, 59 Temple Place - Suite 330, Boston, MA 3002111-1307, USA. */ 31 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. */ 35 36#include "tconfig.h" 37#include "tsystem.h" 38#include "coretypes.h" 39#include "tm.h" 40 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" 52 53#if defined(inhibit_libc) 54/* If libc and its header files are not available, provide dummy functions. */ 55 56#ifdef L_gcov 57void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} 58void __gcov_flush (void) {} 59#endif 60 61#ifdef L_gcov_merge_add 62void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), 63 unsigned n_counters __attribute__ ((unused))) {} 64#endif 65 66#ifdef L_gcov_merge_single 67void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), 68 unsigned n_counters __attribute__ ((unused))) {} 69#endif 70 71#ifdef L_gcov_merge_delta 72void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), 73 unsigned n_counters __attribute__ ((unused))) {} 74#endif 75 76#else 77 78#include <string.h> 79#if GCOV_LOCKED 80#include <fcntl.h> 81#include <errno.h> 82#include <sys/stat.h> 83#endif 84 85#ifdef L_gcov 86#include "gcov-io.c" 87 88/* Chain of per-object gcov structures. */ 89static struct gcov_info *gcov_list; 90 91/* A program checksum allows us to distinguish program data for an 92 object file included in multiple programs. */ 93static gcov_unsigned_t gcov_crc32; 94 95static int 96gcov_version (struct gcov_info *ptr, gcov_unsigned_t version) 97{ 98 if (version != GCOV_VERSION) 99 { 100 char v[4], e[4]; 101 102 GCOV_UNSIGNED2STRING (v, version); 103 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); 104 105 fprintf (stderr, 106 "profiling:%s:Version mismatch - expected %.4s got %.4s\n", 107 ptr->filename, e, v); 108 return 0; 109 } 110 return 1; 111} 112 113/* Dump the coverage counts. We merge with existing counts when 114 possible, to avoid growing the .da files ad infinitum. We use this 115 program's checksum to make sure we only accumulate whole program 116 statistics to the correct summary. An object file might be embedded 117 in two separate programs, and we must keep the two program 118 summaries separate. */ 119 120static void 121gcov_exit (void) 122{ 123 struct gcov_info *gi_ptr; 124 struct gcov_summary this_program; 125 struct gcov_summary all; 126 struct gcov_ctr_summary *cs_ptr; 127 const struct gcov_ctr_info *ci_ptr; 128 unsigned t_ix; 129 gcov_unsigned_t c_num; 130 131 memset (&all, 0, sizeof (all)); 132 /* Find the totals for this execution. */ 133 memset (&this_program, 0, sizeof (this_program)); 134 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 135 { 136 ci_ptr = gi_ptr->counts; 137 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) 138 { 139 if (!((1 << t_ix) & gi_ptr->ctr_mask)) 140 continue; 141 142 cs_ptr = &this_program.ctrs[t_ix]; 143 cs_ptr->num += ci_ptr->num; 144 for (c_num = 0; c_num < ci_ptr->num; c_num++) 145 { 146 cs_ptr->sum_all += ci_ptr->values[c_num]; 147 if (cs_ptr->run_max < ci_ptr->values[c_num]) 148 cs_ptr->run_max = ci_ptr->values[c_num]; 149 } 150 ci_ptr++; 151 } 152 } 153 154 /* Now merge each file. */ 155 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 156 { 157 struct gcov_summary this_object; 158 struct gcov_summary object, program; 159 gcov_type *values[GCOV_COUNTERS]; 160 const struct gcov_fn_info *fi_ptr; 161 unsigned fi_stride; 162 unsigned c_ix, f_ix, n_counts; 163 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all; 164 int error = 0; 165 gcov_unsigned_t tag, length; 166 gcov_position_t summary_pos = 0; 167 168 memset (&this_object, 0, sizeof (this_object)); 169 memset (&object, 0, sizeof (object)); 170 171 /* Totals for this object file. */ 172 ci_ptr = gi_ptr->counts; 173 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) 174 { 175 if (!((1 << t_ix) & gi_ptr->ctr_mask)) 176 continue; 177 178 cs_ptr = &this_object.ctrs[t_ix]; 179 cs_ptr->num += ci_ptr->num; 180 for (c_num = 0; c_num < ci_ptr->num; c_num++) 181 { 182 cs_ptr->sum_all += ci_ptr->values[c_num]; 183 if (cs_ptr->run_max < ci_ptr->values[c_num]) 184 cs_ptr->run_max = ci_ptr->values[c_num]; 185 } 186 187 ci_ptr++; 188 } 189 190 c_ix = 0; 191 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 192 if ((1 << t_ix) & gi_ptr->ctr_mask) 193 { 194 values[c_ix] = gi_ptr->counts[c_ix].values; 195 c_ix++; 196 } 197 198 /* Calculate the function_info stride. This depends on the 199 number of counter types being measured. */ 200 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned); 201 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned)) 202 { 203 fi_stride += __alignof__ (struct gcov_fn_info) - 1; 204 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); 205 } 206 207 if (!gcov_open (gi_ptr->filename)) 208 { 209 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename); 210 continue; 211 } 212 213 tag = gcov_read_unsigned (); 214 if (tag) 215 { 216 /* Merge data from file. */ 217 if (tag != GCOV_DATA_MAGIC) 218 { 219 fprintf (stderr, "profiling:%s:Not a gcov data file\n", 220 gi_ptr->filename); 221 read_fatal:; 222 gcov_close (); 223 continue; 224 } 225 length = gcov_read_unsigned (); 226 if (!gcov_version (gi_ptr, length)) 227 goto read_fatal; 228 229 length = gcov_read_unsigned (); 230 if (length != gi_ptr->stamp) 231 { 232 /* Read from a different compilation. Overwrite the 233 file. */ 234 gcov_truncate (); 235 goto rewrite; 236 } 237 238 /* Merge execution counts for each function. */ 239 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) 240 { 241 fi_ptr = (const struct gcov_fn_info *) 242 ((const char *) gi_ptr->functions + f_ix * fi_stride); 243 tag = gcov_read_unsigned (); 244 length = gcov_read_unsigned (); 245 246 /* Check function. */ 247 if (tag != GCOV_TAG_FUNCTION 248 || length != GCOV_TAG_FUNCTION_LENGTH 249 || gcov_read_unsigned () != fi_ptr->ident 250 || gcov_read_unsigned () != fi_ptr->checksum) 251 { 252 read_mismatch:; 253 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n", 254 gi_ptr->filename, 255 f_ix + 1 ? "function" : "summaries"); 256 goto read_fatal; 257 } 258 259 c_ix = 0; 260 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 261 { 262 gcov_merge_fn merge; 263 264 if (!((1 << t_ix) & gi_ptr->ctr_mask)) 265 continue; 266 267 n_counts = fi_ptr->n_ctrs[c_ix]; 268 merge = gi_ptr->counts[c_ix].merge; 269 270 tag = gcov_read_unsigned (); 271 length = gcov_read_unsigned (); 272 if (tag != GCOV_TAG_FOR_COUNTER (t_ix) 273 || length != GCOV_TAG_COUNTER_LENGTH (n_counts)) 274 goto read_mismatch; 275 (*merge) (values[c_ix], n_counts); 276 values[c_ix] += n_counts; 277 c_ix++; 278 } 279 if ((error = gcov_is_error ())) 280 goto read_error; 281 } 282 283 f_ix = ~0u; 284 /* Check program & object summary */ 285 while (1) 286 { 287 gcov_position_t base = gcov_position (); 288 int is_program; 289 290 tag = gcov_read_unsigned (); 291 if (!tag) 292 break; 293 length = gcov_read_unsigned (); 294 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY; 295 if (length != GCOV_TAG_SUMMARY_LENGTH 296 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY)) 297 goto read_mismatch; 298 gcov_read_summary (is_program ? &program : &object); 299 if ((error = gcov_is_error ())) 300 goto read_error; 301 if (is_program && program.checksum == gcov_crc32) 302 { 303 summary_pos = base; 304 goto rewrite; 305 } 306 } 307 } 308 309 if (!gcov_is_eof ()) 310 { 311 read_error:; 312 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n" 313 : "profiling:%s:Error merging\n", gi_ptr->filename); 314 goto read_fatal; 315 } 316 rewrite:; 317 gcov_rewrite (); 318 if (!summary_pos) 319 memset (&program, 0, sizeof (program)); 320 321 /* Merge the summaries. */ 322 f_ix = ~0u; 323 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) 324 { 325 cs_obj = &object.ctrs[t_ix]; 326 cs_tobj = &this_object.ctrs[t_ix]; 327 cs_prg = &program.ctrs[t_ix]; 328 cs_tprg = &this_program.ctrs[t_ix]; 329 cs_all = &all.ctrs[t_ix]; 330 331 if ((1 << t_ix) & gi_ptr->ctr_mask) 332 { 333 if (!cs_obj->runs++) 334 cs_obj->num = cs_tobj->num; 335 else if (cs_obj->num != cs_tobj->num) 336 goto read_mismatch; 337 cs_obj->sum_all += cs_tobj->sum_all; 338 if (cs_obj->run_max < cs_tobj->run_max) 339 cs_obj->run_max = cs_tobj->run_max; 340 cs_obj->sum_max += cs_tobj->run_max; 341 342 if (!cs_prg->runs++) 343 cs_prg->num = cs_tprg->num; 344 else if (cs_prg->num != cs_tprg->num) 345 goto read_mismatch; 346 cs_prg->sum_all += cs_tprg->sum_all; 347 if (cs_prg->run_max < cs_tprg->run_max) 348 cs_prg->run_max = cs_tprg->run_max; 349 cs_prg->sum_max += cs_tprg->run_max; 350 } 351 else if (cs_obj->num || cs_prg->num) 352 goto read_mismatch; 353 354 if (!cs_all->runs && cs_prg->runs) 355 memcpy (cs_all, cs_prg, sizeof (*cs_all)); 356 else if (!all.checksum 357 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) 358 && memcmp (cs_all, cs_prg, sizeof (*cs_all))) 359 { 360 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s", 361 gi_ptr->filename, GCOV_LOCKED 362 ? "" : " or concurrent update without locking support"); 363 all.checksum = ~0u; 364 } 365 } 366 367 c_ix = 0; 368 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 369 if ((1 << t_ix) & gi_ptr->ctr_mask) 370 { 371 values[c_ix] = gi_ptr->counts[c_ix].values; 372 c_ix++; 373 } 374 375 program.checksum = gcov_crc32; 376 377 /* Write out the data. */ 378 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); 379 gcov_write_unsigned (gi_ptr->stamp); 380 381 /* Write execution counts for each function. */ 382 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) 383 { 384 fi_ptr = (const struct gcov_fn_info *) 385 ((const char *) gi_ptr->functions + f_ix * fi_stride); 386 387 /* Announce function. */ 388 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH); 389 gcov_write_unsigned (fi_ptr->ident); 390 gcov_write_unsigned (fi_ptr->checksum); 391 392 c_ix = 0; 393 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 394 { 395 gcov_type *c_ptr; 396 397 if (!((1 << t_ix) & gi_ptr->ctr_mask)) 398 continue; 399 400 n_counts = fi_ptr->n_ctrs[c_ix]; 401 402 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), 403 GCOV_TAG_COUNTER_LENGTH (n_counts)); 404 c_ptr = values[c_ix]; 405 while (n_counts--) 406 gcov_write_counter (*c_ptr++); 407 408 values[c_ix] = c_ptr; 409 c_ix++; 410 } 411 } 412 413 /* Object file summary. */ 414 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object); 415 416 /* Generate whole program statistics. */ 417 gcov_seek (summary_pos); 418 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program); 419 if ((error = gcov_close ())) 420 fprintf (stderr, error < 0 ? 421 "profiling:%s:Overflow writing\n" : 422 "profiling:%s:Error writing\n", 423 gi_ptr->filename); 424 } 425} 426 427/* Add a new object file onto the bb chain. Invoked automatically 428 when running an object file's global ctors. */ 429 430void 431__gcov_init (struct gcov_info *info) 432{ 433 if (!info->version) 434 return; 435 if (gcov_version (info, info->version)) 436 { 437 const char *ptr = info->filename; 438 gcov_unsigned_t crc32 = gcov_crc32; 439 440 do 441 { 442 unsigned ix; 443 gcov_unsigned_t value = *ptr << 24; 444 445 for (ix = 8; ix--; value <<= 1) 446 { 447 gcov_unsigned_t feedback; 448 449 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; 450 crc32 <<= 1; 451 crc32 ^= feedback; 452 } 453 } 454 while (*ptr++); 455 456 gcov_crc32 = crc32; 457 458 if (!gcov_list) 459 atexit (gcov_exit); 460 461 info->next = gcov_list; 462 gcov_list = info; 463 } 464 info->version = 0; 465} 466 467/* Called before fork or exec - write out profile information gathered so 468 far and reset it to zero. This avoids duplication or loss of the 469 profile information gathered so far. */ 470 471void 472__gcov_flush (void) 473{ 474 const struct gcov_info *gi_ptr; 475 476 gcov_exit (); 477 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 478 { 479 unsigned t_ix; 480 const struct gcov_ctr_info *ci_ptr; 481 482 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++) 483 if ((1 << t_ix) & gi_ptr->ctr_mask) 484 { 485 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); 486 ci_ptr++; 487 } 488 } 489} 490 491#endif /* L_gcov */ 492 493#ifdef L_gcov_merge_add 494/* The profile merging function that just adds the counters. It is given 495 an array COUNTERS of N_COUNTERS old counters and it reads the same number 496 of counters from the gcov file. */ 497void 498__gcov_merge_add (gcov_type *counters, unsigned n_counters) 499{ 500 for (; n_counters; counters++, n_counters--) 501 *counters += gcov_read_counter (); 502} 503#endif /* L_gcov_merge_add */ 504 505#ifdef L_gcov_merge_single 506/* The profile merging function for choosing the most common value. 507 It is given an array COUNTERS of N_COUNTERS old counters and it 508 reads the same number of counters from the gcov file. The counters 509 are split into 3-tuples where the members of the tuple have 510 meanings: 511 512 -- the stored candidate on the most common value of the measured entity 513 -- counter 514 -- total number of evaluations of the value */ 515void 516__gcov_merge_single (gcov_type *counters, unsigned n_counters) 517{ 518 unsigned i, n_measures; 519 gcov_type value, counter, all; 520 521 GCOV_CHECK (!(n_counters % 3)); 522 n_measures = n_counters / 3; 523 for (i = 0; i < n_measures; i++, counters += 3) 524 { 525 value = gcov_read_counter (); 526 counter = gcov_read_counter (); 527 all = gcov_read_counter (); 528 529 if (counters[0] == value) 530 counters[1] += counter; 531 else if (counter > counters[1]) 532 { 533 counters[0] = value; 534 counters[1] = counter - counters[1]; 535 } 536 else 537 counters[1] -= counter; 538 counters[2] += all; 539 } 540} 541#endif /* L_gcov_merge_single */ 542 543#ifdef L_gcov_merge_delta 544/* The profile merging function for choosing the most common 545 difference between two consecutive evaluations of the value. It is 546 given an array COUNTERS of N_COUNTERS old counters and it reads the 547 same number of counters from the gcov file. The counters are split 548 into 4-tuples where the members of the tuple have meanings: 549 550 -- the last value of the measured entity 551 -- the stored candidate on the most common difference 552 -- counter 553 -- total number of evaluations of the value */ 554void 555__gcov_merge_delta (gcov_type *counters, unsigned n_counters) 556{ 557 unsigned i, n_measures; 558 gcov_type last, value, counter, all; 559 560 GCOV_CHECK (!(n_counters % 4)); 561 n_measures = n_counters / 4; 562 for (i = 0; i < n_measures; i++, counters += 4) 563 { 564 last = gcov_read_counter (); 565 value = gcov_read_counter (); 566 counter = gcov_read_counter (); 567 all = gcov_read_counter (); 568 569 if (counters[1] == value) 570 counters[2] += counter; 571 else if (counter > counters[2]) 572 { 573 counters[1] = value; 574 counters[2] = counter - counters[2]; 575 } 576 else 577 counters[2] -= counter; 578 counters[3] += all; 579 } 580} 581#endif /* L_gcov_merge_delta */ 582 583#endif /* inhibit_libc */ 584