1 /* Routines required for instrumenting a program. */ 2 /* Compile this one with gcc. */ 3 /* Copyright (C) 1989-2018 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 Under Section 7 of GPL version 3, you are granted additional 18 permissions described in the GCC Runtime Library Exception, version 19 3.1, as published by the Free Software Foundation. 20 21 You should have received a copy of the GNU General Public License and 22 a copy of the GCC Runtime Library Exception along with this program; 23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 <http://www.gnu.org/licenses/>. */ 25 26 #include "libgcov.h" 27 28 #if defined(inhibit_libc) 29 /* If libc and its header files are not available, provide dummy functions. */ 30 31 #if defined(L_gcov) 32 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} 33 #endif 34 35 #else /* inhibit_libc */ 36 37 #include <string.h> 38 #if GCOV_LOCKED 39 #include <fcntl.h> 40 #include <errno.h> 41 #include <sys/stat.h> 42 #endif 43 44 #ifdef L_gcov 45 46 /* A utility function for outputting errors. */ 47 static int gcov_error (const char *, ...); 48 49 #if !IN_GCOV_TOOL 50 static void gcov_error_exit (void); 51 #endif 52 53 #include "gcov-io.c" 54 55 struct gcov_fn_buffer 56 { 57 struct gcov_fn_buffer *next; 58 unsigned fn_ix; 59 struct gcov_fn_info info; 60 /* note gcov_fn_info ends in a trailing array. */ 61 }; 62 63 struct gcov_summary_buffer 64 { 65 struct gcov_summary_buffer *next; 66 struct gcov_summary summary; 67 }; 68 69 /* A struct that bundles all the related information about the 70 gcda filename. */ 71 72 struct gcov_filename 73 { 74 char *filename; /* filename buffer */ 75 size_t max_length; /* maximum filename length */ 76 int strip; /* leading chars to strip from filename */ 77 size_t prefix; /* chars to prepend to filename */ 78 }; 79 80 static struct gcov_fn_buffer * 81 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer, 82 unsigned limit) 83 { 84 struct gcov_fn_buffer *next; 85 unsigned ix, n_ctr = 0; 86 87 if (!buffer) 88 return 0; 89 next = buffer->next; 90 91 for (ix = 0; ix != limit; ix++) 92 if (gi_ptr->merge[ix]) 93 free (buffer->info.ctrs[n_ctr++].values); 94 free (buffer); 95 return next; 96 } 97 98 static struct gcov_fn_buffer ** 99 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr, 100 struct gcov_fn_buffer **end_ptr, unsigned fn_ix) 101 { 102 unsigned n_ctrs = 0, ix = 0; 103 struct gcov_fn_buffer *fn_buffer; 104 unsigned len; 105 106 for (ix = GCOV_COUNTERS; ix--;) 107 if (gi_ptr->merge[ix]) 108 n_ctrs++; 109 110 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs; 111 fn_buffer = (struct gcov_fn_buffer *) xmalloc (len); 112 113 if (!fn_buffer) 114 goto fail; 115 116 fn_buffer->next = 0; 117 fn_buffer->fn_ix = fn_ix; 118 fn_buffer->info.ident = gcov_read_unsigned (); 119 fn_buffer->info.lineno_checksum = gcov_read_unsigned (); 120 fn_buffer->info.cfg_checksum = gcov_read_unsigned (); 121 122 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) 123 { 124 gcov_unsigned_t length; 125 gcov_type *values; 126 127 if (!gi_ptr->merge[ix]) 128 continue; 129 130 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix)) 131 { 132 len = 0; 133 goto fail; 134 } 135 136 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ()); 137 len = length * sizeof (gcov_type); 138 values = (gcov_type *) xmalloc (len); 139 if (!values) 140 goto fail; 141 142 fn_buffer->info.ctrs[n_ctrs].num = length; 143 fn_buffer->info.ctrs[n_ctrs].values = values; 144 145 while (length--) 146 *values++ = gcov_read_counter (); 147 n_ctrs++; 148 } 149 150 *end_ptr = fn_buffer; 151 return &fn_buffer->next; 152 153 fail: 154 gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix, 155 len ? "cannot allocate" : "counter mismatch", len ? len : ix); 156 157 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); 158 } 159 160 /* Add an unsigned value to the current crc */ 161 162 static gcov_unsigned_t 163 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) 164 { 165 unsigned ix; 166 167 for (ix = 32; ix--; value <<= 1) 168 { 169 unsigned feedback; 170 171 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; 172 crc32 <<= 1; 173 crc32 ^= feedback; 174 } 175 176 return crc32; 177 } 178 179 /* Check if VERSION of the info block PTR matches libgcov one. 180 Return 1 on success, or zero in case of versions mismatch. 181 If FILENAME is not NULL, its value used for reporting purposes 182 instead of value from the info block. */ 183 184 static int 185 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, 186 const char *filename) 187 { 188 if (version != GCOV_VERSION) 189 { 190 char v[4], e[4]; 191 192 GCOV_UNSIGNED2STRING (v, version); 193 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); 194 195 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n", 196 filename? filename : ptr->filename, e, v); 197 return 0; 198 } 199 return 1; 200 } 201 202 /* Insert counter VALUE into HISTOGRAM. */ 203 204 static void 205 gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value) 206 { 207 unsigned i; 208 209 i = gcov_histo_index(value); 210 histogram[i].num_counters++; 211 histogram[i].cum_value += value; 212 if (value < histogram[i].min_value) 213 histogram[i].min_value = value; 214 } 215 216 /* Computes a histogram of the arc counters to place in the summary SUM. */ 217 218 static void 219 gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum) 220 { 221 struct gcov_info *gi_ptr; 222 const struct gcov_fn_info *gfi_ptr; 223 const struct gcov_ctr_info *ci_ptr; 224 struct gcov_ctr_summary *cs_ptr; 225 unsigned t_ix, f_ix, ctr_info_ix, ix; 226 int h_ix; 227 228 /* This currently only applies to arc counters. */ 229 t_ix = GCOV_COUNTER_ARCS; 230 231 /* First check if there are any counts recorded for this counter. */ 232 cs_ptr = &(sum->ctrs[t_ix]); 233 if (!cs_ptr->num) 234 return; 235 236 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) 237 { 238 cs_ptr->histogram[h_ix].num_counters = 0; 239 cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max; 240 cs_ptr->histogram[h_ix].cum_value = 0; 241 } 242 243 /* Walk through all the per-object structures and record each of 244 the count values in histogram. */ 245 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) 246 { 247 if (!gi_ptr->merge[t_ix]) 248 continue; 249 250 /* Find the appropriate index into the gcov_ctr_info array 251 for the counter we are currently working on based on the 252 existence of the merge function pointer for this object. */ 253 for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++) 254 { 255 if (gi_ptr->merge[ix]) 256 ctr_info_ix++; 257 } 258 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++) 259 { 260 gfi_ptr = gi_ptr->functions[f_ix]; 261 262 if (!gfi_ptr || gfi_ptr->key != gi_ptr) 263 continue; 264 265 ci_ptr = &gfi_ptr->ctrs[ctr_info_ix]; 266 for (ix = 0; ix < ci_ptr->num; ix++) 267 gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]); 268 } 269 } 270 } 271 272 /* buffer for the fn_data from another program. */ 273 static struct gcov_fn_buffer *fn_buffer; 274 /* buffer for summary from other programs to be written out. */ 275 static struct gcov_summary_buffer *sum_buffer; 276 277 /* This function computes the program level summary and the histo-gram. 278 It computes and returns CRC32 and stored summary in THIS_PRG. 279 Also determines the longest filename length of the info files. */ 280 281 #if !IN_GCOV_TOOL 282 static 283 #endif 284 gcov_unsigned_t 285 compute_summary (struct gcov_info *list, struct gcov_summary *this_prg, 286 size_t *max_length) 287 { 288 struct gcov_info *gi_ptr; 289 const struct gcov_fn_info *gfi_ptr; 290 struct gcov_ctr_summary *cs_ptr; 291 const struct gcov_ctr_info *ci_ptr; 292 int f_ix; 293 unsigned t_ix; 294 gcov_unsigned_t c_num; 295 gcov_unsigned_t crc32 = 0; 296 297 /* Find the totals for this execution. */ 298 memset (this_prg, 0, sizeof (*this_prg)); 299 *max_length = 0; 300 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) 301 { 302 size_t len = strlen (gi_ptr->filename); 303 if (len > *max_length) 304 *max_length = len; 305 306 crc32 = crc32_unsigned (crc32, gi_ptr->stamp); 307 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); 308 309 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) 310 { 311 gfi_ptr = gi_ptr->functions[f_ix]; 312 313 if (gfi_ptr && gfi_ptr->key != gi_ptr) 314 gfi_ptr = 0; 315 316 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); 317 crc32 = crc32_unsigned (crc32, 318 gfi_ptr ? gfi_ptr->lineno_checksum : 0); 319 if (!gfi_ptr) 320 continue; 321 322 ci_ptr = gfi_ptr->ctrs; 323 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) 324 { 325 if (!gi_ptr->merge[t_ix]) 326 continue; 327 328 cs_ptr = &(this_prg->ctrs[t_ix]); 329 cs_ptr->num += ci_ptr->num; 330 crc32 = crc32_unsigned (crc32, ci_ptr->num); 331 332 for (c_num = 0; c_num < ci_ptr->num; c_num++) 333 { 334 cs_ptr->sum_all += ci_ptr->values[c_num]; 335 if (cs_ptr->run_max < ci_ptr->values[c_num]) 336 cs_ptr->run_max = ci_ptr->values[c_num]; 337 } 338 ci_ptr++; 339 } 340 } 341 } 342 gcov_compute_histogram (list, this_prg); 343 return crc32; 344 } 345 346 /* Including system dependent components. */ 347 #include "libgcov-driver-system.c" 348 349 /* This function merges counters in GI_PTR to an existing gcda file. 350 Return 0 on success. 351 Return -1 on error. In this case, caller will goto read_fatal. */ 352 353 static int 354 merge_one_data (const char *filename, 355 struct gcov_info *gi_ptr, 356 struct gcov_summary *prg_p, 357 struct gcov_summary *this_prg, 358 gcov_position_t *summary_pos_p, 359 gcov_position_t *eof_pos_p, 360 gcov_unsigned_t crc32) 361 { 362 gcov_unsigned_t tag, length; 363 unsigned t_ix; 364 int f_ix; 365 int error = 0; 366 struct gcov_fn_buffer **fn_tail = &fn_buffer; 367 struct gcov_summary_buffer **sum_tail = &sum_buffer; 368 369 length = gcov_read_unsigned (); 370 if (!gcov_version (gi_ptr, length, filename)) 371 return -1; 372 373 length = gcov_read_unsigned (); 374 if (length != gi_ptr->stamp) 375 /* Read from a different compilation. Overwrite the file. */ 376 return 0; 377 378 /* Look for program summary. */ 379 for (f_ix = 0;;) 380 { 381 struct gcov_summary tmp; 382 383 *eof_pos_p = gcov_position (); 384 tag = gcov_read_unsigned (); 385 if (tag != GCOV_TAG_PROGRAM_SUMMARY) 386 break; 387 388 f_ix--; 389 length = gcov_read_unsigned (); 390 gcov_read_summary (&tmp); 391 if ((error = gcov_is_error ())) 392 goto read_error; 393 if (*summary_pos_p) 394 { 395 /* Save all summaries after the one that will be 396 merged into below. These will need to be rewritten 397 as histogram merging may change the number of non-zero 398 histogram entries that will be emitted, and thus the 399 size of the merged summary. */ 400 (*sum_tail) = (struct gcov_summary_buffer *) 401 xmalloc (sizeof(struct gcov_summary_buffer)); 402 (*sum_tail)->summary = tmp; 403 (*sum_tail)->next = 0; 404 sum_tail = &((*sum_tail)->next); 405 goto next_summary; 406 } 407 if (tmp.checksum != crc32) 408 goto next_summary; 409 410 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) 411 if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num) 412 goto next_summary; 413 *prg_p = tmp; 414 *summary_pos_p = *eof_pos_p; 415 416 next_summary:; 417 } 418 419 /* Merge execution counts for each function. */ 420 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; 421 f_ix++, tag = gcov_read_unsigned ()) 422 { 423 const struct gcov_ctr_info *ci_ptr; 424 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; 425 426 if (tag != GCOV_TAG_FUNCTION) 427 goto read_mismatch; 428 429 length = gcov_read_unsigned (); 430 if (!length) 431 /* This function did not appear in the other program. 432 We have nothing to merge. */ 433 continue; 434 435 if (length != GCOV_TAG_FUNCTION_LENGTH) 436 goto read_mismatch; 437 438 if (!gfi_ptr || gfi_ptr->key != gi_ptr) 439 { 440 /* This function appears in the other program. We 441 need to buffer the information in order to write 442 it back out -- we'll be inserting data before 443 this point, so cannot simply keep the data in the 444 file. */ 445 fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix); 446 if (!fn_tail) 447 goto read_mismatch; 448 continue; 449 } 450 451 length = gcov_read_unsigned (); 452 if (length != gfi_ptr->ident) 453 goto read_mismatch; 454 455 length = gcov_read_unsigned (); 456 if (length != gfi_ptr->lineno_checksum) 457 goto read_mismatch; 458 459 length = gcov_read_unsigned (); 460 if (length != gfi_ptr->cfg_checksum) 461 goto read_mismatch; 462 463 ci_ptr = gfi_ptr->ctrs; 464 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 465 { 466 gcov_merge_fn merge = gi_ptr->merge[t_ix]; 467 468 if (!merge) 469 continue; 470 471 tag = gcov_read_unsigned (); 472 length = gcov_read_unsigned (); 473 if (tag != GCOV_TAG_FOR_COUNTER (t_ix) 474 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) 475 goto read_mismatch; 476 (*merge) (ci_ptr->values, ci_ptr->num); 477 ci_ptr++; 478 } 479 if ((error = gcov_is_error ())) 480 goto read_error; 481 } 482 483 if (tag) 484 { 485 read_mismatch:; 486 gcov_error ("profiling:%s:Merge mismatch for %s %u\n", 487 filename, f_ix >= 0 ? "function" : "summary", 488 f_ix < 0 ? -1 - f_ix : f_ix); 489 return -1; 490 } 491 return 0; 492 493 read_error: 494 gcov_error ("profiling:%s:%s merging\n", filename, 495 error < 0 ? "Overflow": "Error"); 496 return -1; 497 } 498 499 /* Write counters in GI_PTR and the summary in PRG to a gcda file. In 500 the case of appending to an existing file, SUMMARY_POS will be non-zero. 501 We will write the file starting from SUMMAY_POS. */ 502 503 static void 504 write_one_data (const struct gcov_info *gi_ptr, 505 const struct gcov_summary *prg_p, 506 const gcov_position_t eof_pos, 507 const gcov_position_t summary_pos) 508 { 509 unsigned f_ix; 510 struct gcov_summary_buffer *next_sum_buffer; 511 512 /* Write out the data. */ 513 if (!eof_pos) 514 { 515 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); 516 gcov_write_unsigned (gi_ptr->stamp); 517 } 518 519 if (summary_pos) 520 gcov_seek (summary_pos); 521 522 /* Generate whole program statistics. */ 523 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p); 524 525 /* Rewrite all the summaries that were after the summary we merged 526 into. This is necessary as the merged summary may have a different 527 size due to the number of non-zero histogram entries changing after 528 merging. */ 529 530 while (sum_buffer) 531 { 532 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary); 533 next_sum_buffer = sum_buffer->next; 534 free (sum_buffer); 535 sum_buffer = next_sum_buffer; 536 } 537 538 /* Write execution counts for each function. */ 539 for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++) 540 { 541 unsigned buffered = 0; 542 const struct gcov_fn_info *gfi_ptr; 543 const struct gcov_ctr_info *ci_ptr; 544 gcov_unsigned_t length; 545 unsigned t_ix; 546 547 if (fn_buffer && fn_buffer->fn_ix == f_ix) 548 { 549 /* Buffered data from another program. */ 550 buffered = 1; 551 gfi_ptr = &fn_buffer->info; 552 length = GCOV_TAG_FUNCTION_LENGTH; 553 } 554 else 555 { 556 gfi_ptr = gi_ptr->functions[f_ix]; 557 if (gfi_ptr && gfi_ptr->key == gi_ptr) 558 length = GCOV_TAG_FUNCTION_LENGTH; 559 else 560 length = 0; 561 } 562 563 gcov_write_tag_length (GCOV_TAG_FUNCTION, length); 564 if (!length) 565 continue; 566 567 gcov_write_unsigned (gfi_ptr->ident); 568 gcov_write_unsigned (gfi_ptr->lineno_checksum); 569 gcov_write_unsigned (gfi_ptr->cfg_checksum); 570 571 ci_ptr = gfi_ptr->ctrs; 572 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 573 { 574 gcov_unsigned_t n_counts; 575 gcov_type *c_ptr; 576 577 if (!gi_ptr->merge[t_ix]) 578 continue; 579 580 n_counts = ci_ptr->num; 581 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), 582 GCOV_TAG_COUNTER_LENGTH (n_counts)); 583 c_ptr = ci_ptr->values; 584 while (n_counts--) 585 gcov_write_counter (*c_ptr++); 586 ci_ptr++; 587 } 588 if (buffered) 589 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); 590 } 591 592 gcov_write_unsigned (0); 593 } 594 595 /* Helper function for merging summary. 596 Return -1 on error. Return 0 on success. */ 597 598 static int 599 merge_summary (const char *filename, int run_counted, 600 const struct gcov_info *gi_ptr, struct gcov_summary *prg, 601 struct gcov_summary *this_prg, gcov_unsigned_t crc32, 602 struct gcov_summary *all_prg __attribute__ ((unused))) 603 { 604 struct gcov_ctr_summary *cs_prg, *cs_tprg; 605 unsigned t_ix; 606 #if !GCOV_LOCKED 607 /* summary for all instances of program. */ 608 struct gcov_ctr_summary *cs_all; 609 #endif 610 611 /* Merge the summaries. */ 612 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) 613 { 614 cs_prg = &(prg->ctrs[t_ix]); 615 cs_tprg = &(this_prg->ctrs[t_ix]); 616 617 if (gi_ptr->merge[t_ix]) 618 { 619 int first = !cs_prg->runs; 620 621 if (!run_counted) 622 cs_prg->runs++; 623 if (first) 624 cs_prg->num = cs_tprg->num; 625 cs_prg->sum_all += cs_tprg->sum_all; 626 if (cs_prg->run_max < cs_tprg->run_max) 627 cs_prg->run_max = cs_tprg->run_max; 628 cs_prg->sum_max += cs_tprg->run_max; 629 if (first) 630 memcpy (cs_prg->histogram, cs_tprg->histogram, 631 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); 632 else 633 gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram); 634 } 635 else if (cs_prg->runs) 636 { 637 gcov_error ("profiling:%s:Merge mismatch for summary.\n", 638 filename); 639 return -1; 640 } 641 #if !GCOV_LOCKED 642 cs_all = &all_prg->ctrs[t_ix]; 643 if (!cs_all->runs && cs_prg->runs) 644 { 645 cs_all->num = cs_prg->num; 646 cs_all->runs = cs_prg->runs; 647 cs_all->sum_all = cs_prg->sum_all; 648 cs_all->run_max = cs_prg->run_max; 649 cs_all->sum_max = cs_prg->sum_max; 650 } 651 else if (!all_prg->checksum 652 /* Don't compare the histograms, which may have slight 653 variations depending on the order they were updated 654 due to the truncating integer divides used in the 655 merge. */ 656 && (cs_all->num != cs_prg->num 657 || cs_all->runs != cs_prg->runs 658 || cs_all->sum_all != cs_prg->sum_all 659 || cs_all->run_max != cs_prg->run_max 660 || cs_all->sum_max != cs_prg->sum_max)) 661 { 662 gcov_error ("profiling:%s:Data file mismatch - some " 663 "data files may have been concurrently " 664 "updated without locking support\n", filename); 665 all_prg->checksum = ~0u; 666 } 667 #endif 668 } 669 670 prg->checksum = crc32; 671 672 return 0; 673 } 674 675 676 /* Sort N entries in VALUE_ARRAY in descending order. 677 Each entry in VALUE_ARRAY has two values. The sorting 678 is based on the second value. */ 679 680 GCOV_LINKAGE void 681 gcov_sort_n_vals (gcov_type *value_array, int n) 682 { 683 int j, k; 684 685 for (j = 2; j < n; j += 2) 686 { 687 gcov_type cur_ent[2]; 688 689 cur_ent[0] = value_array[j]; 690 cur_ent[1] = value_array[j + 1]; 691 k = j - 2; 692 while (k >= 0 && value_array[k + 1] < cur_ent[1]) 693 { 694 value_array[k + 2] = value_array[k]; 695 value_array[k + 3] = value_array[k+1]; 696 k -= 2; 697 } 698 value_array[k + 2] = cur_ent[0]; 699 value_array[k + 3] = cur_ent[1]; 700 } 701 } 702 703 /* Sort the profile counters for all indirect call sites. Counters 704 for each call site are allocated in array COUNTERS. */ 705 706 static void 707 gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters) 708 { 709 int i; 710 gcov_type *values; 711 int n = counters->num; 712 713 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS)); 714 values = counters->values; 715 716 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS) 717 { 718 gcov_type *value_array = &values[i + 1]; 719 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1); 720 } 721 } 722 723 /* Sort topn indirect_call profile counters in GI_PTR. */ 724 725 static void 726 gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr) 727 { 728 unsigned int i; 729 int f_ix; 730 const struct gcov_fn_info *gfi_ptr; 731 const struct gcov_ctr_info *ci_ptr; 732 733 if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV]) 734 return; 735 736 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) 737 { 738 gfi_ptr = gi_ptr->functions[f_ix]; 739 ci_ptr = gfi_ptr->ctrs; 740 for (i = 0; i < GCOV_COUNTERS; i++) 741 { 742 if (!gi_ptr->merge[i]) 743 continue; 744 if (i == GCOV_COUNTER_ICALL_TOPNV) 745 { 746 gcov_sort_icall_topn_counter (ci_ptr); 747 break; 748 } 749 ci_ptr++; 750 } 751 } 752 } 753 754 /* Dump the coverage counts for one gcov_info object. We merge with existing 755 counts when possible, to avoid growing the .da files ad infinitum. We use 756 this program's checksum to make sure we only accumulate whole program 757 statistics to the correct summary. An object file might be embedded 758 in two separate programs, and we must keep the two program 759 summaries separate. */ 760 761 static void 762 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, 763 unsigned run_counted, 764 gcov_unsigned_t crc32, struct gcov_summary *all_prg, 765 struct gcov_summary *this_prg) 766 { 767 struct gcov_summary prg; /* summary for this object over all program. */ 768 int error; 769 gcov_unsigned_t tag; 770 gcov_position_t summary_pos = 0; 771 gcov_position_t eof_pos = 0; 772 773 fn_buffer = 0; 774 sum_buffer = 0; 775 776 gcov_sort_topn_counter_arrays (gi_ptr); 777 778 error = gcov_exit_open_gcda_file (gi_ptr, gf); 779 if (error == -1) 780 return; 781 782 tag = gcov_read_unsigned (); 783 if (tag) 784 { 785 /* Merge data from file. */ 786 if (tag != GCOV_DATA_MAGIC) 787 { 788 gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename); 789 goto read_fatal; 790 } 791 error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg, 792 &summary_pos, &eof_pos, crc32); 793 if (error == -1) 794 goto read_fatal; 795 } 796 797 gcov_rewrite (); 798 799 if (!summary_pos) 800 { 801 memset (&prg, 0, sizeof (prg)); 802 summary_pos = eof_pos; 803 } 804 805 error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg, 806 crc32, all_prg); 807 if (error == -1) 808 goto read_fatal; 809 810 write_one_data (gi_ptr, &prg, eof_pos, summary_pos); 811 /* fall through */ 812 813 read_fatal:; 814 while (fn_buffer) 815 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); 816 817 if ((error = gcov_close ())) 818 gcov_error (error < 0 ? 819 "profiling:%s:Overflow writing\n" : 820 "profiling:%s:Error writing\n", 821 gf->filename); 822 } 823 824 825 /* Dump all the coverage counts for the program. It first computes program 826 summary and then traverses gcov_list list and dumps the gcov_info 827 objects one by one. */ 828 829 #if !IN_GCOV_TOOL 830 static 831 #endif 832 void 833 gcov_do_dump (struct gcov_info *list, int run_counted) 834 { 835 struct gcov_info *gi_ptr; 836 struct gcov_filename gf; 837 gcov_unsigned_t crc32; 838 struct gcov_summary all_prg; 839 struct gcov_summary this_prg; 840 841 crc32 = compute_summary (list, &this_prg, &gf.max_length); 842 843 allocate_filename_struct (&gf); 844 #if !GCOV_LOCKED 845 memset (&all_prg, 0, sizeof (all_prg)); 846 #endif 847 848 /* Now merge each file. */ 849 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) 850 dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg); 851 852 free (gf.filename); 853 } 854 855 #if IN_GCOV_TOOL 856 const char * 857 __attribute__ ((unused)) 858 gcov_get_filename (struct gcov_info *list) 859 { 860 return list->filename; 861 } 862 #endif 863 864 #if !IN_GCOV_TOOL 865 void 866 __gcov_dump_one (struct gcov_root *root) 867 { 868 if (root->dumped) 869 return; 870 871 gcov_do_dump (root->list, root->run_counted); 872 873 root->dumped = 1; 874 root->run_counted = 1; 875 } 876 877 /* Per-dynamic-object gcov state. */ 878 struct gcov_root __gcov_root; 879 880 /* Exactly one of these will be live in the process image. */ 881 struct gcov_master __gcov_master = 882 {GCOV_VERSION, 0}; 883 884 void 885 __gcov_exit (void) 886 { 887 __gcov_dump_one (&__gcov_root); 888 if (__gcov_root.next) 889 __gcov_root.next->prev = __gcov_root.prev; 890 if (__gcov_root.prev) 891 __gcov_root.prev->next = __gcov_root.next; 892 else 893 __gcov_master.root = __gcov_root.next; 894 895 gcov_error_exit (); 896 } 897 898 /* Add a new object file onto the bb chain. Invoked automatically 899 when running an object file's global ctors. */ 900 901 void 902 __gcov_init (struct gcov_info *info) 903 { 904 if (!info->version || !info->n_functions) 905 return; 906 if (gcov_version (info, info->version, 0)) 907 { 908 if (!__gcov_root.list) 909 { 910 /* Add to master list and at exit function. */ 911 if (gcov_version (NULL, __gcov_master.version, "<master>")) 912 { 913 __gcov_root.next = __gcov_master.root; 914 if (__gcov_master.root) 915 __gcov_master.root->prev = &__gcov_root; 916 __gcov_master.root = &__gcov_root; 917 } 918 } 919 920 info->next = __gcov_root.list; 921 __gcov_root.list = info; 922 } 923 } 924 #endif /* !IN_GCOV_TOOL */ 925 #endif /* L_gcov */ 926 #endif /* inhibit_libc */ 927