/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/include/usr/gcov.h $ */ /* */ /* IBM CONFIDENTIAL */ /* */ /* COPYRIGHT International Business Machines Corp. 2012,2013 */ /* */ /* p1 */ /* */ /* Object Code Only (OCO) source materials */ /* Licensed Internal Code Source Materials */ /* IBM HostBoot Licensed Internal Code */ /* */ /* The source code for this program is not published or otherwise */ /* divested of its trade secrets, irrespective of what has been */ /* deposited with the U.S. Copyright Office. */ /* */ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ #ifndef __USR_GCOV_H #define __USR_GCOV_H /** @file gcov.h * @brief Header file to generate gcov_info chain for each module. * * Each gcov-instrumented module needs to have its own gcov_info chain * and associated linking function. Each .o file will have its own * gcov_info object which is added to the chain when the module is loaded * (static initializers) by calling the __gcov_init function. * * We make the gcov_info chain unique per-module, instead of a single * global chain, so that we don't have bad pointers if a module was * loaded and then unloaded. */ #include #include #include /** @struct gcov_info * @brief Structure generated by gcc. Do not use. * * This structure is automatically generated and instances of it created by * gcc when the --coverage compile option is used. We don't need to * manipulate this structure from code except: * 1) To fix up the chains as objects are added to the chain. * 2) To copy the gcov_info and counters into the base-chain when we * unload a module. * * The rest of this structure is parsed by the Gcov.pm debug tool. * * Most of the items in here are used as uint32_t's by gcov but are still * aligned on a 64-bit boundary. The unusedN fields are to ensure proper * alignment. */ struct gcov_info { uint32_t version; uint32_t unused0; gcov_info* next; uint32_t timestamp; uint32_t unused1; char* filename; uint32_t n_functions; uint32_t unused2; void* functions; uint32_t counter_mask; uint32_t unused3; uint32_t n_counters; uint32_t unused4; uint64_t* counters; } PACKED; // Preprocessor magic to create a variable name based off the module name. // GCOV_INFO_OBJ() will create a post-processed name like // 'foobar_gcov_info_head' or 'core_gcov_info_head'. #ifdef __HOSTBOOT_MODULE #define __GCOV_PREFIX __HOSTBOOT_MODULE #define ___GCOV_STRINGIFY(X) #X #define __GCOV_STRINGIFY(X) ___GCOV_STRINGIFY(X) #define __GCOV_PREFIX_NAME __GCOV_STRINGIFY(__HOSTBOOT_MODULE) #else #define __GCOV_PREFIX core #define __GCOV_PREFIX_NAME "core" #endif #define __GCOV_INFO_OBJ(X,Y) X ## Y #define _GCOV_INFO_OBJ(X,Y) __GCOV_INFO_OBJ(X,Y) #define GCOV_INFO_OBJ() _GCOV_INFO_OBJ(__GCOV_PREFIX, _gcov_info_head) /** Pointer to the beginning of the gcov_info chain for this module. */ gcov_info* GCOV_INFO_OBJ() = NULL; /** Function called by module loading to add the object gcov_info instance * to the chain. */ extern "C" void __gcov_init(gcov_info* i_info) { // Atomically push i_info onto the gcov_info_head stack. do { i_info->next = GCOV_INFO_OBJ(); } while (!__sync_bool_compare_and_swap(&GCOV_INFO_OBJ(), i_info->next, i_info)); } // This ifdef has two pieces of code which are used in module unloading. // // In the modules themselves we have a function that is registered via atexit // to call to copy the contents of their own gcov_info chain into the base // gcov_info chain. This is required because the module's memory is going // away as it is unloaded. // // In the base code (non-modules) we have a single implementation of the // code for actually doing a copy of the gcov_info chain into the base code's // own chain. This is kept in just the base code for space savings. // #ifdef __HOSTBOOT_MODULE // Forward declaration of __gcov_module_copychain for modules. extern "C" void __gcov_module_copychain(gcov_info* chain); /** Function called by module unloading to move the module's gcov_info * instances to the global chain. */ extern "C" void __gcov_module_unload(void* unused) { __gcov_module_copychain(GCOV_INFO_OBJ()); } // Register __gcov_module_unload with __cxa_atexit. extern void* __dso_handle; extern "C" int __cxa_atexit(void(*)(void*),void*,void*); int __unused_gcov_cxa_register = __cxa_atexit(&__gcov_module_unload, NULL, __dso_handle); #else /** Function called by a module being unloaded (via __gcov_module_unload) to * copy the module's gcov_info chain into the base gcov_info chain. */ extern "C" void __gcov_module_copychain(gcov_info* chain) { while(chain != NULL) { // Copy old info. gcov_info* new_info = new gcov_info(); memcpy(new_info, chain, sizeof(gcov_info)); // Copy old counters. uint64_t* new_counters = new uint64_t[chain->n_counters](); memcpy(new_counters, chain->counters, chain->n_counters*sizeof(uint64_t)); new_info->counters = new_counters; // Atomically push new_info onto the core_gcov_info_head stack. do { new_info->next = GCOV_INFO_OBJ(); } while (!__sync_bool_compare_and_swap(&GCOV_INFO_OBJ(), new_info->next, new_info)); // Advance to next info in this modules chain. chain = chain->next; } } #endif /** Unneeded function but must be defined to compile. * * This function appears to be typically used by libgcov.so when instrumented * on a real linux-based system. It can be used to merge counters across * multiple runs or when a 'fork' occurs. It doesn't appear that this * function ever gets called for us but the unresolved symbol is added to * the module (by gcc) so we've created a stub here to pass compile. */ extern "C" void __gcov_merge_add() { while(1); } #endif