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, 2004, 2005, 2008, 2009, 2010 5 Free Software Foundation, Inc. 6 7This file is part of GCC. 8 9GCC is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 3, or (at your option) any later 12version. 13 14GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17for more details. 18 19Under Section 7 of GPL version 3, you are granted additional 20permissions described in the GCC Runtime Library Exception, version 213.1, as published by the Free Software Foundation. 22 23You should have received a copy of the GNU General Public License and 24a copy of the GCC Runtime Library Exception along with this program; 25see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 26<http://www.gnu.org/licenses/>. */ 27 28/* Assume compiling for Linux Kernel if __KERNEL__ is defined. */ 29#ifdef __KERNEL__ 30 /* Define MACROs to be used by kernel compilation. */ 31# define L_gcov 32# define L_gcov_interval_profiler 33# define L_gcov_pow2_profiler 34# define L_gcov_one_value_profiler 35# define L_gcov_indirect_call_profiler 36# define L_gcov_average_profiler 37# define L_gcov_ior_profiler 38 39# define HAVE_CC_TLS 0 40# define __GCOV_KERNEL__ 41 42# define IN_LIBGCOV 1 43# define IN_GCOV 0 44#else /* __KERNEL__ */ 45#include "tconfig.h" 46#include "tsystem.h" 47#include "coretypes.h" 48#include "tm.h" 49#endif /* __KERNEL__ */ 50 51#if 1 52#define THREAD_PREFIX __thread 53#else 54#define THREAD_PREFIX 55#endif 56 57#ifndef __GCOV_KERNEL__ 58#if defined(inhibit_libc) 59#define IN_LIBGCOV (-1) 60#else 61#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ 62#include <stdio.h> 63#define IN_LIBGCOV 1 64#if defined(L_gcov) 65#define GCOV_LINKAGE /* nothing */ 66#endif 67#endif 68#endif /* __GCOV_KERNEL__ */ 69 70#include "gcov-io.h" 71 72#if defined(inhibit_libc) 73/* If libc and its header files are not available, provide dummy functions. */ 74 75#ifdef L_gcov 76void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} 77void __gcov_flush (void) {} 78#endif 79 80#ifdef L_gcov_merge_add 81void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), 82 unsigned n_counters __attribute__ ((unused))) {} 83#endif 84 85#ifdef L_gcov_merge_single 86void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), 87 unsigned n_counters __attribute__ ((unused))) {} 88#endif 89 90#ifdef L_gcov_merge_delta 91void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), 92 unsigned n_counters __attribute__ ((unused))) {} 93#endif 94 95#else 96 97#ifndef __GCOV_KERNEL__ 98#include <string.h> 99#if GCOV_LOCKED 100#include <fcntl.h> 101#include <errno.h> 102#include <sys/stat.h> 103#endif 104#endif /* __GCOV_KERNEL__ */ 105 106#ifdef L_gcov 107#include "gcov-io.c" 108 109/* Utility function for outputing errors. */ 110static int 111gcov_error (const char *fmt, ...) 112{ 113 int ret; 114 va_list argp; 115 va_start (argp, fmt); 116#ifdef __GCOV_KERNEL__ 117 ret = vprintk (fmt, argp); 118#else 119 ret = vfprintf (stderr, fmt, argp); 120#endif 121 va_end (argp); 122 return ret; 123} 124 125#ifndef __GCOV_KERNEL__ 126/* Emitted in coverage.c. */ 127extern char * __gcov_pmu_profile_filename; 128extern char * __gcov_pmu_profile_options; 129extern gcov_unsigned_t __gcov_pmu_top_n_address; 130 131/* Sampling rate. */ 132extern gcov_unsigned_t __gcov_sampling_rate; 133static int gcov_sampling_rate_initialized = 0; 134void __gcov_set_sampling_rate (unsigned int rate); 135 136/* Set sampling rate to RATE. */ 137 138void __gcov_set_sampling_rate (unsigned int rate) 139{ 140 __gcov_sampling_rate = rate; 141} 142 143/* Per thread sample counter. */ 144THREAD_PREFIX gcov_unsigned_t __gcov_sample_counter = 0; 145 146/* Chain of per-object gcov structures. */ 147extern struct gcov_info *__gcov_list; 148 149/* Size of the longest file name. */ 150static size_t gcov_max_filename = 0; 151#endif /* __GCOV_KERNEL__ */ 152 153/* Unique identifier assigned to each module (object file). */ 154static gcov_unsigned_t gcov_cur_module_id = 0; 155 156/* Pointer to the direct-call counters (per call-site counters). 157 Initialized by the caller. */ 158THREAD_PREFIX gcov_type *__gcov_direct_call_counters ATTRIBUTE_HIDDEN; 159 160/* Direct call callee address. */ 161THREAD_PREFIX void *__gcov_direct_call_callee ATTRIBUTE_HIDDEN; 162 163/* Pointer to the indirect-call counters (per call-site counters). 164 Initialized by the caller. */ 165THREAD_PREFIX gcov_type *__gcov_indirect_call_topn_counters ATTRIBUTE_HIDDEN; 166 167/* Indirect call callee address. */ 168THREAD_PREFIX void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN; 169 170/* A program checksum allows us to distinguish program data for an 171 object file included in multiple programs. */ 172static gcov_unsigned_t gcov_crc32; 173 174/* Dynamic call graph build and form module groups. */ 175void __gcov_compute_module_groups (void) ATTRIBUTE_HIDDEN; 176void __gcov_finalize_dyn_callgraph (void) ATTRIBUTE_HIDDEN; 177 178/* Profile summary for the gdca file, used in sanity check? */ 179static struct gcov_summary all; 180 181/* Profile summary for this program in current exeuction. */ 182static struct gcov_summary this_program; 183 184/* Profile summary for this object in current execuction. */ 185static struct gcov_summary this_object; 186 187/* Merged profile summary for this program. */ 188static struct gcov_summary program; 189 190/* Merged profile summary for this object. */ 191static struct gcov_summary object; 192 193/* Record the position of summary info. */ 194static gcov_position_t summary_pos = 0; 195 196/* Record the postion of eof. */ 197static gcov_position_t eof_pos = 0; 198 199/* Number of chars in prefix to be stripped. */ 200static int gcov_prefix_strip = 0; 201 202/* The length of path prefix. */ 203static size_t prefix_length = 0; 204 205/* gi_filename is current object filename. 206 gi_filename_up points to the stripped filename. */ 207static char *gi_filename, *gi_filename_up; 208 209static int gcov_open_by_filename (char * gi_filename); 210static int gcov_exit_init (void); 211static void gcov_dump_one_gcov (struct gcov_info *gi_ptr); 212 213/* Make sure path component of the given FILENAME exists, create 214 missing directories. FILENAME must be writable. 215 Returns zero on success, or -1 if an error occurred. */ 216 217static int 218create_file_directory (char *filename) 219{ 220#if !defined(TARGET_POSIX_IO) && !defined(_WIN32) 221 (void) filename; 222 return -1; 223#else 224 char *s; 225 226 s = filename; 227 228 if (HAS_DRIVE_SPEC(s)) 229 s += 2; 230 if (IS_DIR_SEPARATOR(*s)) 231 ++s; 232 for (; *s != '\0'; s++) 233 if (IS_DIR_SEPARATOR(*s)) 234 { 235 char sep = *s; 236 *s = '\0'; 237 238 /* Try to make directory if it doesn't already exist. */ 239 if (access (filename, F_OK) == -1 240#ifdef TARGET_POSIX_IO 241 && mkdir (filename, 0755) == -1 242#else 243 && mkdir (filename) == -1 244#endif 245 /* The directory might have been made by another process. */ 246 && errno != EEXIST) 247 { 248 fprintf (stderr, "profiling:%s:Cannot create directory\n", 249 filename); 250 *s = sep; 251 return -1; 252 }; 253 254 *s = sep; 255 }; 256 return 0; 257#endif 258} 259 260/* Open a file with the specified name. */ 261 262static int 263gcov_open_by_filename (char * gi_filename) 264{ 265 if (!gcov_open (gi_filename)) 266 { 267 /* Open failed likely due to missed directory. 268 Create directory and retry to open file. */ 269 if (create_file_directory (gi_filename)) 270 { 271 gcov_error ("profiling:%s:Skip\n", gi_filename); 272 return -1; 273 } 274 if (!gcov_open (gi_filename)) 275 { 276 gcov_error ("profiling:%s:Cannot open\n", gi_filename); 277 return -1; 278 } 279 } 280 return 0; 281} 282 283 284/* Determine whether a counter is active. */ 285 286static inline int 287gcov_counter_active (const struct gcov_info *info, unsigned int type) 288{ 289 return (1 << type) & info->ctr_mask; 290} 291 292#ifndef __GCOV_KERNEL__ 293/* Check if VERSION of the info block PTR matches libgcov one. 294 Return 1 on success, or zero in case of versions mismatch. 295 If FILENAME is not NULL, its value used for reporting purposes 296 instead of value from the info block. */ 297 298static int 299gcov_version (struct gcov_info *ptr __attribute__ ((unused)), 300 gcov_unsigned_t version, const char *filename) 301{ 302 if (version != GCOV_VERSION) 303 { 304 char v[4], e[4]; 305 306 GCOV_UNSIGNED2STRING (v, version); 307 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); 308 309 if (filename) 310 gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n", 311 filename, e, v); 312 else 313 gcov_error ("profiling:Version mismatch - expected %.4s got %.4s\n", e, v); 314 return 0; 315 } 316 return 1; 317} 318 319#define GCOV_GET_FILENAME gcov_strip_leading_dirs 320 321/* Strip GCOV_PREFIX_STRIP levels of leading '/' from FILENAME and 322 put the result into GI_FILENAME_UP. */ 323 324static void 325gcov_strip_leading_dirs (int prefix_length, int gcov_prefix_strip, 326 const char *filename, char *gi_filename_up) 327{ 328 /* Avoid to add multiple drive letters into combined path. */ 329 if (prefix_length != 0 && HAS_DRIVE_SPEC(filename)) 330 filename += 2; 331 332 /* Build relocated filename, stripping off leading 333 directories from the initial filename if requested. */ 334 if (gcov_prefix_strip > 0) 335 { 336 int level = 0; 337 const char *s = filename; 338 if (IS_DIR_SEPARATOR(*s)) 339 ++s; 340 341 /* Skip selected directory levels. */ 342 for (; (*s != '\0') && (level < gcov_prefix_strip); s++) 343 if (IS_DIR_SEPARATOR(*s)) 344 { 345 filename = s; 346 level++; 347 } 348 } 349 /* Update complete filename with stripped original. */ 350 if (prefix_length != 0 && !IS_DIR_SEPARATOR (*filename)) 351 { 352 /* If prefix is given, add directory separator. */ 353 strcpy (gi_filename_up, "/"); 354 strcpy (gi_filename_up + 1, filename); 355 } 356 else 357 strcpy (gi_filename_up, filename); 358} 359 360/* This function allocates the space to store current file name. */ 361 362static void 363gcov_alloc_filename (void) 364{ 365 /* Get file name relocation prefix. Non-absolute values are ignored. */ 366 char *gcov_prefix = 0; 367 368 prefix_length = 0; 369 gcov_prefix_strip = 0; 370 371 { 372 /* Check if the level of dirs to strip off specified. */ 373 char *tmp = getenv ("GCOV_PREFIX_STRIP"); 374 if (tmp) 375 { 376 gcov_prefix_strip = atoi (tmp); 377 /* Do not consider negative values. */ 378 if (gcov_prefix_strip < 0) 379 gcov_prefix_strip = 0; 380 } 381 } 382 /* Get file name relocation prefix. Non-absolute values are ignored. */ 383 gcov_prefix = getenv ("GCOV_PREFIX"); 384 if (gcov_prefix) 385 { 386 prefix_length = strlen(gcov_prefix); 387 388 /* Remove an unnecessary trailing '/' */ 389 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) 390 prefix_length--; 391 } 392 else 393 prefix_length = 0; 394 395 /* If no prefix was specified and a prefix stip, then we assume 396 relative. */ 397 if (gcov_prefix_strip != 0 && prefix_length == 0) 398 { 399 gcov_prefix = "."; 400 prefix_length = 1; 401 } 402 403 /* Allocate and initialize the filename scratch space. */ 404 gi_filename = (char *) malloc (prefix_length + gcov_max_filename + 2); 405 if (prefix_length) 406 memcpy (gi_filename, gcov_prefix, prefix_length); 407 408 gi_filename_up = gi_filename + prefix_length; 409} 410 411/* Stop the pmu profiler and dump pmu profile info into the global file. */ 412 413static void 414pmu_profile_stop (void) 415{ 416 const char *pmu_profile_filename = __gcov_pmu_profile_filename; 417 const char *pmu_options = __gcov_pmu_profile_options; 418 size_t filename_length; 419 int gcda_error; 420 421 if (!pmu_profile_filename || !pmu_options) 422 return; 423 424 __gcov_stop_pmu_profiler (); 425 426 filename_length = strlen (pmu_profile_filename); 427 if (filename_length > gcov_max_filename) 428 gcov_max_filename = filename_length; 429 /* Allocate and initialize the filename scratch space. */ 430 gcov_alloc_filename (); 431 GCOV_GET_FILENAME (prefix_length, gcov_prefix_strip, pmu_profile_filename, 432 gi_filename_up); 433 /* Open the gcda file for writing. We don't support merge yet. */ 434 gcda_error = gcov_open_by_filename (gi_filename); 435 __gcov_end_pmu_profiler (gcda_error); 436 if ((gcda_error = gcov_close ())) 437 gcov_error (gcda_error < 0 ? "pmu_profile_stop:%s:Overflow writing\n" : 438 "pmu_profile_stop:%s:Error writing\n", 439 gi_filename); 440} 441 442/* Sort N entries in VALUE_ARRAY in descending order. 443 Each entry in VALUE_ARRAY has two values. The sorting 444 is based on the second value. */ 445 446GCOV_LINKAGE void 447gcov_sort_n_vals (gcov_type *value_array, int n) 448{ 449 int j, k; 450 for (j = 2; j < n; j += 2) 451 { 452 gcov_type cur_ent[2]; 453 cur_ent[0] = value_array[j]; 454 cur_ent[1] = value_array[j + 1]; 455 k = j - 2; 456 while (k >= 0 && value_array[k + 1] < cur_ent[1]) 457 { 458 value_array[k + 2] = value_array[k]; 459 value_array[k + 3] = value_array[k+1]; 460 k -= 2; 461 } 462 value_array[k + 2] = cur_ent[0]; 463 value_array[k + 3] = cur_ent[1]; 464 } 465} 466 467/* Sort the profile counters for all indirect call sites. Counters 468 for each call site are allocated in array COUNTERS. */ 469 470static void 471gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters) 472{ 473 int i; 474 gcov_type *values; 475 int n = counters->num; 476 gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS)); 477 478 values = counters->values; 479 480 for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS) 481 { 482 gcov_type *value_array = &values[i + 1]; 483 gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1); 484 } 485} 486 487/* Write imported files (auxiliary modules) for primary module GI_PTR 488 into file GI_FILENAME. */ 489 490static void 491gcov_write_import_file (char *gi_filename, struct gcov_info *gi_ptr) 492{ 493 char *gi_imports_filename; 494 const char *gcov_suffix; 495 FILE *imports_file; 496 size_t prefix_length, suffix_length; 497 498 gcov_suffix = getenv ("GCOV_IMPORTS_SUFFIX"); 499 if (!gcov_suffix || !strlen (gcov_suffix)) 500 gcov_suffix = ".imports"; 501 suffix_length = strlen (gcov_suffix); 502 prefix_length = strlen (gi_filename); 503 gi_imports_filename = (char *) alloca (prefix_length + suffix_length + 1); 504 memset (gi_imports_filename, 0, prefix_length + suffix_length + 1); 505 memcpy (gi_imports_filename, gi_filename, prefix_length); 506 memcpy (gi_imports_filename + prefix_length, gcov_suffix, suffix_length); 507 imports_file = fopen (gi_imports_filename, "w"); 508 if (imports_file) 509 { 510 const struct dyn_imp_mod **imp_mods; 511 unsigned i, imp_len; 512 imp_mods = gcov_get_sorted_import_module_array (gi_ptr, &imp_len); 513 if (imp_mods) 514 { 515 for (i = 0; i < imp_len; i++) 516 { 517 fprintf (imports_file, "%s\n", 518 imp_mods[i]->imp_mod->mod_info->source_filename); 519 fprintf (imports_file, "%s%s\n", 520 imp_mods[i]->imp_mod->mod_info->da_filename, GCOV_DATA_SUFFIX); 521 } 522 free (imp_mods); 523 } 524 fclose (imports_file); 525 } 526} 527 528static void 529gcov_dump_module_info (void) 530{ 531 struct gcov_info *gi_ptr; 532 533 __gcov_compute_module_groups (); 534 535 /* Now write out module group info. */ 536 for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 537 { 538 int error; 539 540 GCOV_GET_FILENAME (prefix_length, gcov_prefix_strip, gi_ptr->filename, 541 gi_filename_up); 542 error = gcov_open_by_filename (gi_filename); 543 if (error != 0) 544 continue; 545 546 /* Overwrite the zero word at the of the file. */ 547 gcov_rewrite (); 548 gcov_seek (gi_ptr->eof_pos); 549 550 gcov_write_module_infos (gi_ptr); 551 gcov_truncate (); 552 553 if ((error = gcov_close ())) 554 gcov_error (error < 0 ? "profiling:%s:Overflow writing\n" : 555 "profiling:%s:Error writing\n", 556 gi_filename); 557 gcov_write_import_file (gi_filename, gi_ptr); 558 } 559 __gcov_finalize_dyn_callgraph (); 560} 561 562/* Dump the coverage counts. We merge with existing counts when 563 possible, to avoid growing the .da files ad infinitum. We use this 564 program's checksum to make sure we only accumulate whole program 565 statistics to the correct summary. An object file might be embedded 566 in two separate programs, and we must keep the two program 567 summaries separate. */ 568 569static void 570gcov_exit (void) 571{ 572 struct gcov_info *gi_ptr; 573 int dump_module_info; 574 575 /* Stop and write the PMU profile data into the global file. */ 576 pmu_profile_stop (); 577 578 dump_module_info = gcov_exit_init (); 579 580 for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 581 gcov_dump_one_gcov (gi_ptr); 582 583 if (dump_module_info) 584 gcov_dump_module_info (); 585 586 free (gi_filename); 587} 588 589/* Add a new object file onto the bb chain. Invoked automatically 590 when running an object file's global ctors. */ 591 592void 593__gcov_init (struct gcov_info *info) 594{ 595 if (!gcov_sampling_rate_initialized) 596 { 597 const char* env_value_str = getenv ("GCOV_SAMPLING_RATE"); 598 if (env_value_str) 599 { 600 int env_value_int = atoi(env_value_str); 601 if (env_value_int >= 1) 602 __gcov_sampling_rate = env_value_int; 603 } 604 gcov_sampling_rate_initialized = 1; 605 } 606 607 if (!info->version) 608 return; 609 610 if (gcov_version (info, info->version, 0)) 611 { 612 const char *ptr = info->filename; 613 gcov_unsigned_t crc32 = gcov_crc32; 614 size_t filename_length = strlen (info->filename); 615 struct gcov_pmu_info pmu_info; 616 617 /* Refresh the longest file name information. */ 618 if (filename_length > gcov_max_filename) 619 gcov_max_filename = filename_length; 620 621 /* Initialize the pmu profiler. */ 622 pmu_info.pmu_profile_filename = __gcov_pmu_profile_filename; 623 pmu_info.pmu_tool = __gcov_pmu_profile_options; 624 pmu_info.pmu_top_n_address = __gcov_pmu_top_n_address; 625 __gcov_init_pmu_profiler (&pmu_info); 626 if (pmu_info.pmu_profile_filename) 627 { 628 /* Refresh the longest file name information. */ 629 filename_length = strlen (pmu_info.pmu_profile_filename); 630 if (filename_length > gcov_max_filename) 631 gcov_max_filename = filename_length; 632 } 633 634 /* Assign the module ID (starting at 1). */ 635 info->mod_info->ident = (++gcov_cur_module_id); 636 gcc_assert (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (GEN_FUNC_GLOBAL_ID ( 637 info->mod_info->ident, 0)) 638 == info->mod_info->ident); 639 640 do 641 { 642 unsigned ix; 643 gcov_unsigned_t value = *ptr << 24; 644 645 for (ix = 8; ix--; value <<= 1) 646 { 647 gcov_unsigned_t feedback; 648 649 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; 650 crc32 <<= 1; 651 crc32 ^= feedback; 652 } 653 } while (*ptr++); 654 655 gcov_crc32 = crc32; 656 657 if (!__gcov_list) 658 { 659 atexit (gcov_exit); 660 /* Start pmu profiler. */ 661 __gcov_start_pmu_profiler (); 662 } 663 664 info->next = __gcov_list; 665 __gcov_list = info; 666 } 667 info->version = 0; 668} 669 670/* Called before fork or exec - write out profile information gathered so 671 far and reset it to zero. This avoids duplication or loss of the 672 profile information gathered so far. */ 673 674void 675__gcov_flush (void) 676{ 677 const struct gcov_info *gi_ptr; 678 679 __gcov_stop_pmu_profiler (); 680 gcov_exit (); 681 for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 682 { 683 unsigned t_ix; 684 const struct gcov_ctr_info *ci_ptr; 685 686 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++) 687 if (gcov_counter_active (gi_ptr, t_ix)) 688 { 689 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); 690 ci_ptr++; 691 } 692 } 693 __gcov_start_pmu_profiler (); 694} 695 696#else /* __GCOV_KERNEL__ */ 697 698#define GCOV_GET_FILENAME gcov_get_filename 699 700/* Copy the filename to the buffer. */ 701 702static inline void 703gcov_get_filename (int prefix_length __attribute__ ((unused)), 704 int gcov_prefix_strip __attribute__ ((unused)), 705 const char *filename, char *gi_filename_up) 706{ 707 strcpy (gi_filename_up, filename); 708} 709 710/* Sort the profile counters for all indirect call sites. Counters 711 for each call site are allocated in array COUNTERS. */ 712 713static void 714gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters) 715{ 716 /* Empty */ 717} 718 719/* Reserves a buffer to store the name of the file being processed. */ 720static char _kernel_gi_filename[520]; 721 722/* This function allocates the space to store current file name. */ 723 724static void 725gcov_alloc_filename (void) 726{ 727 prefix_length = 0; 728 gcov_prefix_strip = 0; 729 gi_filename = _kernel_gi_filename; 730 gi_filename_up = _kernel_gi_filename; 731} 732 733#endif /* __GCOV_KERNEL__ */ 734 735/* Determine number of active counters in gcov_info INFO, 736 the counter arrays are stored in VALUES if the coming 737 value of VALUES !=0. If FLAG_SORT_ICALL_TOPN_COUNTER !=0, 738 the icall_topn_counter in INFO will be sorted. 739 Return: the number of active counter types. */ 740 741static unsigned int 742gcov_counter_array (const struct gcov_info *info, 743 gcov_type *values[GCOV_COUNTERS], 744 int flag_sort_icall_topn_counter) 745{ 746 unsigned int i; 747 unsigned int result = 0; 748 749 for (i = 0; i < GCOV_COUNTERS; i++) { 750 if (gcov_counter_active (info, i)) 751 { 752 if (values) 753 values[result] = info->counts[result].values; 754 if (flag_sort_icall_topn_counter && 755 (i == GCOV_COUNTER_ICALL_TOPNV)) 756 gcov_sort_icall_topn_counter (&info->counts[result]); 757 result++; 758 } 759 } 760 return result; 761} 762 763/* Compute object summary recored in gcov_info INFO. The result is 764 stored in OBJ_SUM. Note that the caller is responsible for 765 zeroing out OBJ_SUM, otherwise the summary is accumulated. */ 766 767static void 768gcov_object_summary (struct gcov_info *info, 769 struct gcov_summary *obj_sum) 770{ 771 const struct gcov_ctr_info *ci_ptr; 772 struct gcov_ctr_summary *cs_ptr; 773 gcov_unsigned_t c_num; 774 unsigned t_ix; 775 776 /* Totals for this object file. */ 777 ci_ptr = info->counts; 778 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) 779 { 780 if (!gcov_counter_active (info, t_ix)) 781 continue; 782 783 cs_ptr = &(obj_sum->ctrs[t_ix]); 784 cs_ptr->num += ci_ptr->num; 785 for (c_num = 0; c_num < ci_ptr->num; c_num++) 786 { 787 cs_ptr->sum_all += ci_ptr->values[c_num]; 788 if (cs_ptr->run_max < ci_ptr->values[c_num]) 789 cs_ptr->run_max = ci_ptr->values[c_num]; 790 } 791 ci_ptr++; 792 } 793} 794 795/* Merge with existing gcda file in the same directory to avoid 796 excessive growthe of the files. */ 797 798static int 799gcov_merge_gcda_file (struct gcov_info *info, 800 gcov_type *values[GCOV_COUNTERS], 801 unsigned fi_stride) 802{ 803 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all; 804 unsigned t_ix, f_ix; 805 806#ifndef __GCOV_KERNEL__ 807 const struct gcov_fn_info *fi_ptr; 808 unsigned c_ix, n_counts; 809 int error = 0; 810 gcov_unsigned_t tag, length; 811 812 eof_pos = 0; 813 summary_pos = 0; 814 815 tag = gcov_read_unsigned (); 816 if (tag) 817 { 818 /* Merge data from file. */ 819 if (tag != GCOV_DATA_MAGIC) 820 { 821 gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename); 822 goto read_fatal; 823 } 824 length = gcov_read_unsigned (); 825 if (!gcov_version (info, length, gi_filename)) 826 goto read_fatal; 827 828 length = gcov_read_unsigned (); 829 if (length != info->stamp) 830 /* Read from a different compilation. Overwrite the file. */ 831 goto rewrite; 832 833 /* Merge execution counts for each function. */ 834 for (f_ix = 0; f_ix < info->n_functions; f_ix++) 835 { 836 fi_ptr = (const struct gcov_fn_info *) 837 ((const char *) info->functions + f_ix * fi_stride); 838 tag = gcov_read_unsigned (); 839 length = gcov_read_unsigned (); 840 841 /* Check function. */ 842 if (tag != GCOV_TAG_FUNCTION 843 || length != GCOV_TAG_FUNCTION_LENGTH 844 || gcov_read_unsigned () != fi_ptr->ident 845 || gcov_read_unsigned () != fi_ptr->lineno_checksum 846 || gcov_read_unsigned () != fi_ptr->cfg_checksum) 847 goto read_mismatch; 848 849 c_ix = 0; 850 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 851 { 852 gcov_merge_fn merge; 853 854 if (!((1 << t_ix) & info->ctr_mask)) 855 continue; 856 857 n_counts = fi_ptr->n_ctrs[c_ix]; 858 merge = info->counts[c_ix].merge; 859 860 tag = gcov_read_unsigned (); 861 length = gcov_read_unsigned (); 862 if (tag != GCOV_TAG_FOR_COUNTER (t_ix) 863 || length != GCOV_TAG_COUNTER_LENGTH (n_counts)) 864 goto read_mismatch; 865 (*merge) (values[c_ix], n_counts); 866 values[c_ix] += n_counts; 867 c_ix++; 868 } 869 if ((error = gcov_is_error ())) 870 goto read_error; 871 } 872 873 f_ix = ~0u; 874 /* Check program & object summary. */ 875 while (1) 876 { 877 int is_program; 878 879 eof_pos = gcov_position (); 880 tag = gcov_read_unsigned (); 881 if (!tag) 882 break; 883 884 length = gcov_read_unsigned (); 885 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY; 886 if (length != GCOV_TAG_SUMMARY_LENGTH 887 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY)) 888 goto read_mismatch; 889 gcov_read_summary (is_program ? &program : &object); 890 if ((error = gcov_is_error ())) 891 goto read_error; 892 if (is_program && program.checksum == gcov_crc32) 893 { 894 summary_pos = eof_pos; 895 goto rewrite; 896 } 897 } 898 } 899 900 goto rewrite; 901 902read_error:; 903 gcov_error (error < 0 ? "profiling:%s:Overflow merging\n" 904 : "profiling:%s:Error merging\n", gi_filename); 905 goto read_fatal; 906 907#endif /* __GCOV_KERNEL__ */ 908 909 goto rewrite; 910 911read_mismatch:; 912 gcov_error ("profiling:%s:Merge mismatch for %s\n", gi_filename, 913 f_ix + 1 ? "function" : "summaries"); 914 goto read_fatal; /* work-around the compiler warning */ 915 916read_fatal:; 917 gcov_close (); 918 return 1; 919 920rewrite:; 921 gcov_rewrite (); 922 if (!summary_pos) 923 memset (&program, 0, sizeof (program)); 924 925 /* Merge the summaries. */ 926 f_ix = ~0u; 927 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) 928 { 929 cs_obj = &object.ctrs[t_ix]; 930 cs_tobj = &this_object.ctrs[t_ix]; 931 cs_prg = &program.ctrs[t_ix]; 932 cs_tprg = &this_program.ctrs[t_ix]; 933 cs_all = &all.ctrs[t_ix]; 934 935 if ((1 << t_ix) & info->ctr_mask) 936 { 937 if (!cs_obj->runs++) 938 cs_obj->num = cs_tobj->num; 939 else if (cs_obj->num != cs_tobj->num) 940 goto read_mismatch; 941 cs_obj->sum_all += cs_tobj->sum_all; 942 if (cs_obj->run_max < cs_tobj->run_max) 943 cs_obj->run_max = cs_tobj->run_max; 944 cs_obj->sum_max += cs_tobj->run_max; 945 946 if (!cs_prg->runs++) 947 cs_prg->num = cs_tprg->num; 948 else if (cs_prg->num != cs_tprg->num) 949 goto read_mismatch; 950 cs_prg->sum_all += cs_tprg->sum_all; 951 if (cs_prg->run_max < cs_tprg->run_max) 952 cs_prg->run_max = cs_tprg->run_max; 953 cs_prg->sum_max += cs_tprg->run_max; 954 } 955 else if (cs_obj->num || cs_prg->num) 956 goto read_mismatch; 957 958 if (!cs_all->runs && cs_prg->runs) 959 memcpy (cs_all, cs_prg, sizeof (*cs_all)); 960 else if (!all.checksum 961 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) 962 && memcmp (cs_all, cs_prg, sizeof (*cs_all))) 963 { 964 gcov_error ("profiling:%s:Invocation mismatch - " 965 "some data files may have been removed%s", 966 gi_filename, GCOV_LOCKED 967 ? "" : " or concurrent update without locking support"); 968 all.checksum = ~0u; 969 } 970 } 971 972 return 0; 973} 974 975/* Calculate the function_info stride. This depends on the 976 number of counter types being measured. 977 NUM_COUNTER_TYPES is number of counter types recorded. 978 Return: the number of bytes for accessing next fn_info 979 (aligned to gcov_fn_info). */ 980 981static unsigned 982gcov_compute_fi_stride (unsigned num_counter_types) 983{ 984 unsigned fi_stride; 985 986 fi_stride = offsetof (struct gcov_fn_info, n_ctrs) + 987 num_counter_types * sizeof (unsigned); 988 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned)) 989 { 990 fi_stride += __alignof__ (struct gcov_fn_info) - 1; 991 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); 992 } 993 return fi_stride; 994} 995 996/* This function returns the size of gcda file to be written. Note 997 the size is in units of gcov_type. */ 998 999GCOV_LINKAGE unsigned 1000gcov_gcda_file_size (struct gcov_info *gi_ptr) 1001{ 1002 unsigned size; 1003 const struct gcov_fn_info *fi_ptr; 1004 unsigned f_ix, t_ix, c_ix; 1005 unsigned n_counts; 1006 unsigned fi_stride; 1007 gcov_type *values[GCOV_COUNTERS]; 1008 1009 c_ix = gcov_counter_array (gi_ptr, values, 0); 1010 fi_stride = gcov_compute_fi_stride (c_ix); 1011 1012 /* GCOV_DATA_MAGIC, GCOV_VERSION and time_stamp. */ 1013 size = 3; 1014 1015 /* size for each function. */ 1016 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) 1017 { 1018 fi_ptr = (const struct gcov_fn_info *) 1019 ((const char *) gi_ptr->functions + f_ix * fi_stride); 1020 1021 size += 2 /* tag_length itself */ 1022 + GCOV_TAG_FUNCTION_LENGTH; /* ident, lineno_cksum, cfg_cksm */ 1023 1024 c_ix = 0; 1025 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 1026 { 1027 if (!((1 << t_ix) & gi_ptr->ctr_mask)) 1028 continue; 1029 1030 n_counts = fi_ptr->n_ctrs[c_ix]; 1031 size += 2 + GCOV_TAG_COUNTER_LENGTH (n_counts); 1032 c_ix++; 1033 } 1034 } 1035 1036 /* Object summary. */ 1037 size += 2 + GCOV_TAG_SUMMARY_LENGTH; 1038 1039 /* Program summary. */ 1040 size += 2 + GCOV_TAG_SUMMARY_LENGTH; 1041 1042 size += 1; 1043 1044 return size*4; 1045} 1046 1047/* Write profile data (including summary and module grouping information, 1048 if available, to file. */ 1049 1050static void 1051gcov_write_gcda_file (struct gcov_info *gi_ptr, 1052 unsigned fi_stride) 1053{ 1054 const struct gcov_fn_info *fi_ptr; 1055 gcov_type *values[GCOV_COUNTERS]; 1056 unsigned t_ix, c_ix, f_ix, n_counts; 1057 int error = 0; 1058 1059 /* Write out the data. */ 1060 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); 1061 gcov_write_unsigned (gi_ptr->stamp); 1062 1063 gcov_counter_array (gi_ptr, values, 0); 1064 1065 /* Write execution counts for each function. */ 1066 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) 1067 { 1068 fi_ptr = (const struct gcov_fn_info *) 1069 ((const char *) gi_ptr->functions + f_ix * fi_stride); 1070 1071 /* Announce function. */ 1072 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH); 1073 gcov_write_unsigned (fi_ptr->ident); 1074 gcov_write_unsigned (fi_ptr->lineno_checksum); 1075 gcov_write_unsigned (fi_ptr->cfg_checksum); 1076 1077 c_ix = 0; 1078 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) 1079 { 1080 gcov_type *c_ptr; 1081 1082 if (!((1 << t_ix) & gi_ptr->ctr_mask)) 1083 continue; 1084 1085 n_counts = fi_ptr->n_ctrs[c_ix]; 1086 1087 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), 1088 GCOV_TAG_COUNTER_LENGTH (n_counts)); 1089 c_ptr = values[c_ix]; 1090 while (n_counts--) 1091 gcov_write_counter (*c_ptr++); 1092 1093 values[c_ix] = c_ptr; 1094 c_ix++; 1095 } 1096 } 1097 1098 /* Object file summary. */ 1099 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object); 1100 1101 /* Generate whole program statistics. */ 1102 program.checksum = gcov_crc32; 1103 if (eof_pos) 1104 gcov_seek (eof_pos); 1105 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program); 1106 if (!summary_pos) 1107 gcov_write_unsigned (0); 1108 1109 /* TODO: there is a problem here -- if there are other program 1110 summary data after the matching one, setting eof_pos to this 1111 position means that the module info table will overwrite the 1112 those other program summary. It also means a mismatch error 1113 may occur at the next merge if no matching program summary is 1114 found before the module info data. */ 1115 if (!summary_pos) 1116 gi_ptr->eof_pos = gcov_position () - 1; 1117 else 1118 gi_ptr->eof_pos = gcov_position (); 1119 1120 if ((error = gcov_close ())) 1121 gcov_error (error < 0 ? 1122 "profiling:%s:Overflow writing\n" : 1123 "profiling:%s:Error writing\n", 1124 gi_filename); 1125} 1126 1127/* Do some preparation work before calling the actual dumping 1128 routine. 1129 Return: 1 when module grouping info needs to be dumped, 1130 0 otherwise. */ 1131 1132static int 1133gcov_exit_init (void) 1134{ 1135 struct gcov_info *gi_ptr; 1136 int dump_module_info = 0; 1137 1138 dump_module_info = 0; 1139 gcov_prefix_strip = 0; 1140 1141 memset (&all, 0, sizeof (all)); 1142 1143 /* Find the totals for this execution. */ 1144 memset (&this_program, 0, sizeof (this_program)); 1145 for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next) 1146 { 1147 gcov_object_summary (gi_ptr, &this_program); 1148 1149 /* The IS_PRIMARY field is overloaded to indicate if this module 1150 is FDO/LIPO. */ 1151 dump_module_info |= gi_ptr->mod_info->is_primary; 1152 } 1153 1154 gcov_alloc_filename (); 1155 1156 return dump_module_info; 1157} 1158 1159/* Dump one entry in the gcov_info list (for one object). */ 1160 1161static void 1162gcov_dump_one_gcov (struct gcov_info *gi_ptr) 1163{ 1164 gcov_type *values[GCOV_COUNTERS]; 1165 unsigned fi_stride; 1166 unsigned c_ix; 1167 int ret; 1168 1169 memset (&this_object, 0, sizeof (this_object)); 1170 memset (&object, 0, sizeof (object)); 1171 1172 gcov_object_summary (gi_ptr, &this_object); 1173 1174 c_ix = gcov_counter_array (gi_ptr, values, 1); 1175 1176 fi_stride = gcov_compute_fi_stride (c_ix); 1177 1178 GCOV_GET_FILENAME (prefix_length, gcov_prefix_strip, gi_ptr->filename, 1179 gi_filename_up); 1180 1181 if (gcov_open_by_filename (gi_filename) == -1) 1182 return; 1183 1184 /* Now merge this file. */ 1185 ret = gcov_merge_gcda_file (gi_ptr, values, fi_stride); 1186 if (ret != 0 ) return; 1187 1188 gcov_write_gcda_file (gi_ptr, fi_stride); 1189} 1190 1191#endif /* L_gcov */ 1192 1193#ifdef L_gcov_merge_add 1194/* The profile merging function that just adds the counters. It is given 1195 an array COUNTERS of N_COUNTERS old counters and it reads the same number 1196 of counters from the gcov file. */ 1197void 1198__gcov_merge_add (gcov_type *counters, unsigned n_counters) 1199{ 1200 for (; n_counters; counters++, n_counters--) 1201 *counters += gcov_read_counter (); 1202} 1203#endif /* L_gcov_merge_add */ 1204 1205#ifdef L_gcov_merge_ior 1206/* The profile merging function that just adds the counters. It is given 1207 an array COUNTERS of N_COUNTERS old counters and it reads the same number 1208 of counters from the gcov file. */ 1209void 1210__gcov_merge_ior (gcov_type *counters, unsigned n_counters) 1211{ 1212 for (; n_counters; counters++, n_counters--) 1213 *counters |= gcov_read_counter (); 1214} 1215#endif 1216 1217#ifdef L_gcov_merge_reusedist 1218 1219/* Return the weighted arithmetic mean of two values. */ 1220 1221static gcov_type 1222__gcov_weighted_mean2 (gcov_type value1, gcov_type count1, 1223 gcov_type value2, gcov_type count2) 1224{ 1225 if (count1 + count2 == 0) 1226 return 0; 1227 else 1228 return (value1 * count1 + value2 * count2) / (count1 + count2); 1229} 1230 1231void 1232__gcov_merge_reusedist (gcov_type *counters, unsigned n_counters) 1233{ 1234 unsigned i; 1235 1236 gcc_assert(!(n_counters % 4)); 1237 1238 for (i = 0; i < n_counters; i += 4) 1239 { 1240 /* Decode current values. */ 1241 gcov_type c_mean_dist = counters[i]; 1242 gcov_type c_mean_size = counters[i+1]; 1243 gcov_type c_count = counters[i+2]; 1244 gcov_type c_dist_x_size = counters[i+3]; 1245 1246 /* Read and decode values in file. */ 1247 gcov_type f_mean_dist = __gcov_read_counter (); 1248 gcov_type f_mean_size = __gcov_read_counter (); 1249 gcov_type f_count = __gcov_read_counter (); 1250 gcov_type f_dist_x_size = __gcov_read_counter (); 1251 1252 /* Compute aggregates. */ 1253 gcov_type a_mean_dist = __gcov_weighted_mean2 ( 1254 f_mean_dist, f_count, c_mean_dist, c_count); 1255 gcov_type a_mean_size = __gcov_weighted_mean2 ( 1256 f_mean_size, f_count, c_mean_size, c_count); 1257 gcov_type a_count = f_count + c_count; 1258 gcov_type a_dist_x_size = f_dist_x_size + c_dist_x_size; 1259 1260 /* Encode back into counters. */ 1261 counters[i] = a_mean_dist; 1262 counters[i+1] = a_mean_size; 1263 counters[i+2] = a_count; 1264 counters[i+3] = a_dist_x_size; 1265 } 1266} 1267 1268#endif 1269 1270#ifdef L_gcov_merge_dc 1271 1272/* Returns 1 if the function global id GID is not valid. */ 1273 1274static int 1275__gcov_is_gid_insane (gcov_type gid) 1276{ 1277 if (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (gid) == 0 1278 || EXTRACT_FUNC_ID_FROM_GLOBAL_ID (gid) == 0) 1279 return 1; 1280 return 0; 1281} 1282 1283/* The profile merging function used for merging direct call counts 1284 This function is given array COUNTERS of N_COUNTERS old counters and it 1285 reads the same number of counters from the gcov file. */ 1286 1287void 1288__gcov_merge_dc (gcov_type *counters, unsigned n_counters) 1289{ 1290 unsigned i; 1291 1292 gcc_assert (!(n_counters % 2)); 1293 for (i = 0; i < n_counters; i += 2) 1294 { 1295 gcov_type global_id = gcov_read_counter (); 1296 gcov_type call_count = gcov_read_counter (); 1297 1298 /* Note that global id counter may never have been set if no calls were 1299 made from this call-site. */ 1300 if (counters[i] && global_id) 1301 { 1302 /* TODO race condition requires us do the following correction. */ 1303 if (__gcov_is_gid_insane (counters[i])) 1304 counters[i] = global_id; 1305 else if (__gcov_is_gid_insane (global_id)) 1306 global_id = counters[i]; 1307 1308 gcc_assert (counters[i] == global_id); 1309 } 1310 else if (global_id) 1311 counters[i] = global_id; 1312 1313 counters[i + 1] += call_count; 1314 1315 /* Reset. */ 1316 if (__gcov_is_gid_insane (counters[i])) 1317 counters[i] = counters[i + 1] = 0; 1318 1319 /* Assert that the invariant (global_id == 0) <==> (call_count == 0) 1320 holds true after merging. */ 1321 if (counters[i] == 0) 1322 counters[i+1] = 0; 1323 if (counters[i + 1] == 0) 1324 counters[i] = 0; 1325 } 1326} 1327#endif 1328 1329#ifdef L_gcov_merge_icall_topn 1330/* The profile merging function used for merging indirect call counts 1331 This function is given array COUNTERS of N_COUNTERS old counters and it 1332 reads the same number of counters from the gcov file. */ 1333 1334void 1335__gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters) 1336{ 1337 unsigned i, j, k, m; 1338 1339 gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS)); 1340 for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS) 1341 { 1342 gcov_type *value_array = &counters[i + 1]; 1343 unsigned tmp_size = 2 * (GCOV_ICALL_TOPN_NCOUNTS - 1); 1344 gcov_type *tmp_array 1345 = (gcov_type *) alloca (tmp_size * sizeof (gcov_type)); 1346 1347 for (j = 0; j < tmp_size; j++) 1348 tmp_array[j] = 0; 1349 1350 for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2) 1351 { 1352 tmp_array[j] = value_array[j]; 1353 tmp_array[j + 1] = value_array [j + 1]; 1354 } 1355 1356 /* Skip the number_of_eviction entry. */ 1357 gcov_read_counter (); 1358 for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2) 1359 { 1360 int found = 0; 1361 gcov_type global_id = gcov_read_counter (); 1362 gcov_type call_count = gcov_read_counter (); 1363 for (m = 0; m < j; m += 2) 1364 { 1365 if (tmp_array[m] == global_id) 1366 { 1367 found = 1; 1368 tmp_array[m + 1] += call_count; 1369 break; 1370 } 1371 } 1372 if (!found) 1373 { 1374 tmp_array[j] = global_id; 1375 tmp_array[j + 1] = call_count; 1376 j += 2; 1377 } 1378 } 1379 /* Now sort the temp array */ 1380 gcov_sort_n_vals (tmp_array, j); 1381 1382 /* Now copy back the top half of the temp array */ 1383 for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2) 1384 { 1385 value_array[k] = tmp_array[k]; 1386 value_array[k + 1] = tmp_array[k + 1]; 1387 } 1388 } 1389} 1390#endif 1391 1392 1393#ifdef L_gcov_merge_single 1394/* The profile merging function for choosing the most common value. 1395 It is given an array COUNTERS of N_COUNTERS old counters and it 1396 reads the same number of counters from the gcov file. The counters 1397 are split into 3-tuples where the members of the tuple have 1398 meanings: 1399 1400 -- the stored candidate on the most common value of the measured entity 1401 -- counter 1402 -- total number of evaluations of the value */ 1403void 1404__gcov_merge_single (gcov_type *counters, unsigned n_counters) 1405{ 1406 unsigned i, n_measures; 1407 gcov_type value, counter, all; 1408 1409 gcc_assert (!(n_counters % 3)); 1410 n_measures = n_counters / 3; 1411 for (i = 0; i < n_measures; i++, counters += 3) 1412 { 1413 value = gcov_read_counter (); 1414 counter = gcov_read_counter (); 1415 all = gcov_read_counter (); 1416 1417 if (counters[0] == value) 1418 counters[1] += counter; 1419 else if (counter > counters[1]) 1420 { 1421 counters[0] = value; 1422 counters[1] = counter - counters[1]; 1423 } 1424 else 1425 counters[1] -= counter; 1426 counters[2] += all; 1427 } 1428} 1429#endif /* L_gcov_merge_single */ 1430 1431#ifdef L_gcov_merge_delta 1432/* The profile merging function for choosing the most common 1433 difference between two consecutive evaluations of the value. It is 1434 given an array COUNTERS of N_COUNTERS old counters and it reads the 1435 same number of counters from the gcov file. The counters are split 1436 into 4-tuples where the members of the tuple have meanings: 1437 1438 -- the last value of the measured entity 1439 -- the stored candidate on the most common difference 1440 -- counter 1441 -- total number of evaluations of the value */ 1442void 1443__gcov_merge_delta (gcov_type *counters, unsigned n_counters) 1444{ 1445 unsigned i, n_measures; 1446 gcov_type value, counter, all; 1447 1448 gcc_assert (!(n_counters % 4)); 1449 n_measures = n_counters / 4; 1450 for (i = 0; i < n_measures; i++, counters += 4) 1451 { 1452 /* last = */ gcov_read_counter (); 1453 value = gcov_read_counter (); 1454 counter = gcov_read_counter (); 1455 all = gcov_read_counter (); 1456 1457 if (counters[1] == value) 1458 counters[2] += counter; 1459 else if (counter > counters[2]) 1460 { 1461 counters[1] = value; 1462 counters[2] = counter - counters[2]; 1463 } 1464 else 1465 counters[2] -= counter; 1466 counters[3] += all; 1467 } 1468} 1469#endif /* L_gcov_merge_delta */ 1470 1471#ifdef L_gcov_interval_profiler 1472/* If VALUE is in interval <START, START + STEPS - 1>, then increases the 1473 corresponding counter in COUNTERS. If the VALUE is above or below 1474 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased 1475 instead. */ 1476 1477void 1478__gcov_interval_profiler (gcov_type *counters, gcov_type value, 1479 int start, unsigned steps) 1480{ 1481 gcov_type delta = value - start; 1482 if (delta < 0) 1483 counters[steps + 1]++; 1484 else if (delta >= steps) 1485 counters[steps]++; 1486 else 1487 counters[delta]++; 1488} 1489#endif 1490 1491#ifdef L_gcov_pow2_profiler 1492/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise 1493 COUNTERS[0] is incremented. */ 1494 1495void 1496__gcov_pow2_profiler (gcov_type *counters, gcov_type value) 1497{ 1498 if (value & (value - 1)) 1499 counters[0]++; 1500 else 1501 counters[1]++; 1502} 1503#endif 1504 1505/* Tries to determine the most common value among its inputs. Checks if the 1506 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] 1507 is incremented. If this is not the case and COUNTERS[1] is not zero, 1508 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and 1509 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this 1510 function is called more than 50% of the time with one value, this value 1511 will be in COUNTERS[0] in the end. 1512 1513 In any case, COUNTERS[2] is incremented. */ 1514 1515static inline void 1516__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) 1517{ 1518 if (value == counters[0]) 1519 counters[1]++; 1520 else if (counters[1] == 0) 1521 { 1522 counters[1] = 1; 1523 counters[0] = value; 1524 } 1525 else 1526 counters[1]--; 1527 counters[2]++; 1528} 1529 1530#ifdef L_gcov_indirect_call_topn_profiler 1531/* Tries to keep track the most frequent N values in the counters where 1532 N is specified by parameter TOPN_VAL. To track top N values, 2*N counter 1533 entries are used. 1534 counter[0] --- the accumative count of the number of times one entry in 1535 in the counters gets evicted/replaced due to limited capacity. 1536 When this value reaches a threshold, the bottom N values are 1537 cleared. 1538 counter[1] through counter[2*N] records the top 2*N values collected so far. 1539 Each value is represented by two entries: count[2*i+1] is the ith value, and 1540 count[2*i+2] is the number of times the value is seen. */ 1541 1542static void 1543__gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value, 1544 gcov_unsigned_t topn_val) 1545{ 1546 unsigned i, found = 0, have_zero_count = 0; 1547 1548 gcov_type *entry; 1549 gcov_type *lfu_entry = &counters[1]; 1550 gcov_type *value_array = &counters[1]; 1551 gcov_type *num_eviction = &counters[0]; 1552 1553 /* There are 2*topn_val values tracked, each value takes two slots in the 1554 counter array */ 1555 for ( i = 0; i < (topn_val << 2); i += 2) 1556 { 1557 entry = &value_array[i]; 1558 if ( entry[0] == value) 1559 { 1560 entry[1]++ ; 1561 found = 1; 1562 break; 1563 } 1564 else if (entry[1] == 0) 1565 { 1566 lfu_entry = entry; 1567 have_zero_count = 1; 1568 } 1569 else if (entry[1] < lfu_entry[1]) 1570 lfu_entry = entry; 1571 } 1572 1573 if (found) 1574 return; 1575 1576 /* lfu_entry is either an empty entry or an entry 1577 with lowest count, which will be evicted. */ 1578 lfu_entry[0] = value; 1579 lfu_entry[1] = 1; 1580 1581#define GCOV_ICALL_COUNTER_CLEAR_THRESHOLD 3000 1582 1583 /* Too many evictions -- time to clear bottom entries to 1584 avoid hot values bumping each other out. */ 1585 if ( !have_zero_count 1586 && ++*num_eviction >= GCOV_ICALL_COUNTER_CLEAR_THRESHOLD) 1587 { 1588 unsigned i, j; 1589 gcov_type *p, minv; 1590 gcov_type* tmp_cnts 1591 = (gcov_type *)alloca (topn_val * sizeof(gcov_type)); 1592 1593 *num_eviction = 0; 1594 1595 for ( i = 0; i < topn_val; i++ ) 1596 tmp_cnts[i] = 0; 1597 1598 /* Find the largest topn_val values from the group of 1599 2*topn_val values and put them into tmp_cnts. */ 1600 1601 for ( i = 0; i < 2 * topn_val; i += 2 ) 1602 { 1603 p = 0; 1604 for ( j = 0; j < topn_val; j++ ) 1605 { 1606 if ( !p || tmp_cnts[j] < *p ) 1607 p = &tmp_cnts[j]; 1608 } 1609 if ( value_array[i + 1] > *p ) 1610 *p = value_array[i + 1]; 1611 } 1612 1613 minv = tmp_cnts[0]; 1614 for ( j = 1; j < topn_val; j++ ) 1615 { 1616 if (tmp_cnts[j] < minv) 1617 minv = tmp_cnts[j]; 1618 } 1619 /* Zero out low value entries */ 1620 for ( i = 0; i < 2 * topn_val; i += 2 ) 1621 { 1622 if (value_array[i + 1] < minv) 1623 { 1624 value_array[i] = 0; 1625 value_array[i + 1] = 0; 1626 } 1627 } 1628 } 1629} 1630#endif 1631 1632#ifdef L_gcov_one_value_profiler 1633void 1634__gcov_one_value_profiler (gcov_type *counters, gcov_type value) 1635{ 1636 __gcov_one_value_profiler_body (counters, value); 1637} 1638#endif 1639 1640#ifdef L_gcov_indirect_call_profiler 1641 1642/* By default, the C++ compiler will use function addresses in the 1643 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero 1644 tells the compiler to use function descriptors instead. The value 1645 of this macro says how many words wide the descriptor is (normally 2), 1646 but it may be dependent on target flags. Since we do not have access 1647 to the target flags here we just check to see if it is set and use 1648 that to set VTABLE_USES_DESCRIPTORS to 0 or 1. 1649 1650 It is assumed that the address of a function descriptor may be treated 1651 as a pointer to a function. */ 1652 1653#ifdef TARGET_VTABLE_USES_DESCRIPTORS 1654#define VTABLE_USES_DESCRIPTORS 1 1655#else 1656#define VTABLE_USES_DESCRIPTORS 0 1657#endif 1658 1659/* Tries to determine the most common value among its inputs. */ 1660void 1661__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, 1662 void* cur_func, void* callee_func) 1663{ 1664 /* If the C++ virtual tables contain function descriptors then one 1665 function may have multiple descriptors and we need to dereference 1666 the descriptors to see if they point to the same function. */ 1667 if (cur_func == callee_func 1668 || (VTABLE_USES_DESCRIPTORS && callee_func 1669 && *(void **) cur_func == *(void **) callee_func)) 1670 __gcov_one_value_profiler_body (counter, value); 1671} 1672#endif 1673 1674 1675#ifdef L_gcov_indirect_call_topn_profiler 1676extern THREAD_PREFIX gcov_type *__gcov_indirect_call_topn_counters ATTRIBUTE_HIDDEN; 1677extern THREAD_PREFIX void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN; 1678#ifdef TARGET_VTABLE_USES_DESCRIPTORS 1679#define VTABLE_USES_DESCRIPTORS 1 1680#else 1681#define VTABLE_USES_DESCRIPTORS 0 1682#endif 1683void 1684__gcov_indirect_call_topn_profiler (void *cur_func, 1685 void *cur_module_gcov_info, 1686 gcov_unsigned_t cur_func_id) 1687{ 1688 void *callee_func = __gcov_indirect_call_topn_callee; 1689 gcov_type *counter = __gcov_indirect_call_topn_counters; 1690 /* If the C++ virtual tables contain function descriptors then one 1691 function may have multiple descriptors and we need to dereference 1692 the descriptors to see if they point to the same function. */ 1693 if (cur_func == callee_func 1694 || (VTABLE_USES_DESCRIPTORS && callee_func 1695 && *(void **) cur_func == *(void **) callee_func)) 1696 { 1697 gcov_type global_id 1698 = ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident; 1699 global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id); 1700 __gcov_topn_value_profiler_body (counter, global_id, GCOV_ICALL_TOPN_VAL); 1701 __gcov_indirect_call_topn_callee = 0; 1702 } 1703} 1704 1705#endif 1706 1707#ifdef L_gcov_direct_call_profiler 1708extern THREAD_PREFIX gcov_type *__gcov_direct_call_counters ATTRIBUTE_HIDDEN; 1709extern THREAD_PREFIX void *__gcov_direct_call_callee ATTRIBUTE_HIDDEN; 1710/* Direct call profiler. */ 1711void 1712__gcov_direct_call_profiler (void *cur_func, 1713 void *cur_module_gcov_info, 1714 gcov_unsigned_t cur_func_id) 1715{ 1716 if (cur_func == __gcov_direct_call_callee) 1717 { 1718 gcov_type global_id 1719 = ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident; 1720 global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id); 1721 __gcov_direct_call_counters[0] = global_id; 1722 __gcov_direct_call_counters[1]++; 1723 __gcov_direct_call_callee = 0; 1724 } 1725} 1726#endif 1727 1728 1729#ifdef L_gcov_average_profiler 1730/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want 1731 to saturate up. */ 1732 1733void 1734__gcov_average_profiler (gcov_type *counters, gcov_type value) 1735{ 1736 counters[0] += value; 1737 counters[1] ++; 1738} 1739#endif 1740 1741#ifdef L_gcov_ior_profiler 1742/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want 1743 to saturate up. */ 1744 1745void 1746__gcov_ior_profiler (gcov_type *counters, gcov_type value) 1747{ 1748 *counters |= value; 1749} 1750#endif 1751 1752#ifdef L_gcov_fork 1753/* A wrapper for the fork function. Flushes the accumulated profiling data, so 1754 that they are not counted twice. */ 1755 1756pid_t 1757__gcov_fork (void) 1758{ 1759 __gcov_flush (); 1760 return fork (); 1761} 1762#endif 1763 1764#ifdef L_gcov_execl 1765/* A wrapper for the execl function. Flushes the accumulated profiling data, so 1766 that they are not lost. */ 1767 1768int 1769__gcov_execl (const char *path, char *arg, ...) 1770{ 1771 va_list ap, aq; 1772 unsigned i, length; 1773 char **args; 1774 1775 __gcov_flush (); 1776 1777 va_start (ap, arg); 1778 va_copy (aq, ap); 1779 1780 length = 2; 1781 while (va_arg (ap, char *)) 1782 length++; 1783 va_end (ap); 1784 1785 args = (char **) alloca (length * sizeof (void *)); 1786 args[0] = arg; 1787 for (i = 1; i < length; i++) 1788 args[i] = va_arg (aq, char *); 1789 va_end (aq); 1790 1791 return execv (path, args); 1792} 1793#endif 1794 1795#ifdef L_gcov_execlp 1796/* A wrapper for the execlp function. Flushes the accumulated profiling data, so 1797 that they are not lost. */ 1798 1799int 1800__gcov_execlp (const char *path, char *arg, ...) 1801{ 1802 va_list ap, aq; 1803 unsigned i, length; 1804 char **args; 1805 1806 __gcov_flush (); 1807 1808 va_start (ap, arg); 1809 va_copy (aq, ap); 1810 1811 length = 2; 1812 while (va_arg (ap, char *)) 1813 length++; 1814 va_end (ap); 1815 1816 args = (char **) alloca (length * sizeof (void *)); 1817 args[0] = arg; 1818 for (i = 1; i < length; i++) 1819 args[i] = va_arg (aq, char *); 1820 va_end (aq); 1821 1822 return execvp (path, args); 1823} 1824#endif 1825 1826#ifdef L_gcov_execle 1827/* A wrapper for the execle function. Flushes the accumulated profiling data, so 1828 that they are not lost. */ 1829 1830int 1831__gcov_execle (const char *path, char *arg, ...) 1832{ 1833 va_list ap, aq; 1834 unsigned i, length; 1835 char **args; 1836 char **envp; 1837 1838 __gcov_flush (); 1839 1840 va_start (ap, arg); 1841 va_copy (aq, ap); 1842 1843 length = 2; 1844 while (va_arg (ap, char *)) 1845 length++; 1846 va_end (ap); 1847 1848 args = (char **) alloca (length * sizeof (void *)); 1849 args[0] = arg; 1850 for (i = 1; i < length; i++) 1851 args[i] = va_arg (aq, char *); 1852 envp = va_arg (aq, char **); 1853 va_end (aq); 1854 1855 return execve (path, args, envp); 1856} 1857#endif 1858 1859#ifdef L_gcov_execv 1860/* A wrapper for the execv function. Flushes the accumulated profiling data, so 1861 that they are not lost. */ 1862 1863int 1864__gcov_execv (const char *path, char *const argv[]) 1865{ 1866 __gcov_flush (); 1867 return execv (path, argv); 1868} 1869#endif 1870 1871#ifdef L_gcov_execvp 1872/* A wrapper for the execvp function. Flushes the accumulated profiling data, so 1873 that they are not lost. */ 1874 1875int 1876__gcov_execvp (const char *path, char *const argv[]) 1877{ 1878 __gcov_flush (); 1879 return execvp (path, argv); 1880} 1881#endif 1882 1883#ifdef L_gcov_execve 1884/* A wrapper for the execve function. Flushes the accumulated profiling data, so 1885 that they are not lost. */ 1886 1887int 1888__gcov_execve (const char *path, char *const argv[], char *const envp[]) 1889{ 1890 __gcov_flush (); 1891 return execve (path, argv, envp); 1892} 1893#endif 1894 1895#ifdef __GCOV_KERNEL__ 1896/* 1897 * Provide different implementation for the following functions: 1898 * __gcov_init 1899 * __gcov_exit 1900 * 1901 * Provide the following dummy merge functions: 1902 * __gcov_merge_add 1903 * __gcov_merge_single 1904 * __gcov_merge_delta 1905 * __gcov_merge_ior 1906 * __gcov_merge_icall_topn 1907 * __gcov_merge_dc 1908 * __gcov_merge_reusedist 1909 * 1910 * Reuse the following functions: 1911 * __gcov_interval_profiler() 1912 * __gcov_pow2_profiler() 1913 * __gcov_average_profiler() 1914 * __gcov_ior_profiler() 1915 * __gcov_one_value_profiler() 1916 * __gcov_indirect_call_profiler() 1917 * |-> __gcov_one_value_profiler_body() 1918 * 1919 * For LIPO: (TBD) 1920 * Change slightly for the following functions: 1921 * __gcov_merge_icall_topn 1922 * __gcov_merge_dc 1923 * 1924 * Reuse the following functions: 1925 * __gcov_direct_call_profiler() 1926 * __gcov_indirect_call_topn_profiler() 1927 * |-> __gcov_topn_value_profiler_body() 1928 * 1929 */ 1930 1931/* Current virual gcda file. This is for kernel use only. */ 1932gcov_kernel_vfile *gcov_current_file; 1933 1934/* Set current virutal gcda file. It needs to be set before dumping 1935 profile data. */ 1936 1937void 1938gcov_set_vfile (gcov_kernel_vfile *file) 1939{ 1940 gcov_current_file = file; 1941} 1942 1943/* Dump one entry in the gcov_info list (for one object) in kernel. */ 1944 1945void 1946gcov_kernel_dump_one_gcov (struct gcov_info *info) 1947{ 1948 gcc_assert (gcov_current_file); 1949 1950 gcov_exit_init (); 1951 1952 gcov_dump_one_gcov (info); 1953} 1954 1955#define DUMMY_FUNC(func) \ 1956void func (gcov_type *counters __attribute__ ((unused)), \ 1957 unsigned n_counters __attribute__ ((unused))) {} 1958 1959DUMMY_FUNC (__gcov_merge_add) 1960EXPORT_SYMBOL (__gcov_merge_add); 1961 1962DUMMY_FUNC (__gcov_merge_single) 1963EXPORT_SYMBOL (__gcov_merge_single); 1964 1965DUMMY_FUNC (__gcov_merge_delta) 1966EXPORT_SYMBOL (__gcov_merge_delta); 1967 1968DUMMY_FUNC(__gcov_merge_ior) 1969EXPORT_SYMBOL (__gcov_merge_ior); 1970 1971DUMMY_FUNC (__gcov_merge_icall_topn) 1972EXPORT_SYMBOL (__gcov_merge_icall_topn); 1973 1974DUMMY_FUNC (__gcov_merge_dc) 1975EXPORT_SYMBOL (__gcov_merge_dc); 1976 1977DUMMY_FUNC (__gcov_merge_reusedist) 1978EXPORT_SYMBOL (__gcov_merge_reusedist); 1979 1980EXPORT_SYMBOL (__gcov_average_profiler); 1981EXPORT_SYMBOL (__gcov_indirect_call_profiler); 1982EXPORT_SYMBOL (__gcov_interval_profiler); 1983EXPORT_SYMBOL (__gcov_ior_profiler); 1984EXPORT_SYMBOL (__gcov_one_value_profiler); 1985EXPORT_SYMBOL (__gcov_pow2_profiler); 1986 1987#endif /* __GCOV_KERNEL__ */ 1988 1989#endif /* inhibit_libc */ 1990