Code coverage of libraries
Code coverage of static/shared libraries and DLL
During the linking operation, CoverageScanner includes all instrumentations of the shared libraries if these are compiled with CoverageScanner. CoverageBrowser displays the code coverage of the complete application (executable and its libraries) in one view.
Note: To get an analysis of the code coverage of a library only, it is necessary to compile the main application and exclude its sources from the code coverage by adding in the command line --cs-exclude-file-abs-regex=.*
, for example.
Code coverage of plugins/manually loaded shared libraries
Libraries loaded dynamically can also be instrumented, but it is necessary to handle the generation of the execution report in the main application or in the plugin code itself.
Generating code coverage information directly from the main application
Handling the plugins in the main application can be done using the register/unregister mechanism of the CoverageScanner API. Call __coveragescanner_register_library()
after loading a library and __coveragescanner_unregister_library()
just before unloading it.
Example:
* #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main(int argc, char **argv) { void *handle; double (*cosine)(double); char *error; handle = dlopen("libm.so", RTLD_LAZY); #ifdef __COVERAGESCANNER__ __coveragescanner_register_library("libm.so"); #endif if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } dlerror(); /* Clear any existing error */ /* Writing: cosine = (double (*)(double)) dlsym(handle, "cos"); would seem more natural, but the C99 standard leaves casting from "void *" to a function pointer undefined. The assignment used below is the POSIX.1-2003 (Technical Corrigendum 1) workaround; see the Rationale for the POSIX specification of dlsym(). */ *(void **) (&cosine) = dlsym(handle, "cos"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } printf("%f\n", (*cosine)(2.0)); #ifdef __COVERAGESCANNER__ __coveragescanner_unregister_library("libm.so"); #endif dlclose(handle); exit(EXIT_SUCCESS); }
Note: Calling __coveragescanner_register_library()
or __coveragescanner_unregister_library()
on an non-instrumented library is allowed.
Generating code coverage information directly from the plugin
CoverageScanner cannot handle the instrumentation of plugins (i.e. shared libraries loaded manually) during the linking phase. In this case, the library must initialize and store the executions itself. Therefore, the shared library needs to call __coveragescanner_filename()
to set the name of the execution file during its initialization and __coveragescanner_save()
to save the instrumentations when it becomes unloaded.
Code coverage of plugins generated with Microsoft Visual Studio
The function DllMain()
is called on the initialization and the termination of the DLL generated using Microsoft® Visual Studio®. When the reason
field is equal to DLL_PROCESS_ATTACH
, the function __coveragescanner_filename()
should be called. To save the measures on exit, the function __coveragescanner_save()
shall be called when reason
is DLL_PROCESS_DETACH
.
Example:
* extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { switch( dwReason ) { case DLL_PROCESS_ATTACH: #ifdef __COVERAGESCANNER__ /* Initialization of the CoverageScanner library. */ /* Replace "mylib" with your filename without extension */ __coveragescanner_filename("mylib"); #endif ... break; case DLL_PROCESS_DETACH: ... #ifdef __COVERAGESCANNER__ /* Saves the execution report */ __coveragescanner_save(); #endif break; } return TRUE; }
Code coverage of plugins generated with GNU gcc
The GNU compiler offers two attributes that let you execute a function when a library becomes loaded or unloaded:
__attribute__ ((constructor)) my_init(void);
: This attribute specifies a function to be called when the library is loaded. Call the function__coveragescanner_filename()
in the custom initialization function of the library.__attribute__ ((destructor)) my_fini(void);
: This attribute specifies a function to be called when the library is unloaded. Call the function__coveragescanner_save()
on the termination of the library.
Example:
* static void plugin_load(void) __attribute__ ((constructor)) ; static void plugin_unload(void) __attribute__ ((destructor)) ; static void plugin_load(void) { #ifdef __COVERAGESCANNER__ /* Initialization of the CoverageScanner library. */ /* Replace "mylib" with your filename without extension */ __coveragescanner_filename("mylib"); #endif ... } static void plugin_unload(void) { ... #ifdef __COVERAGESCANNER__ /* Saves the execution report */ __coveragescanner_save(); #endif }
Coco v7.2.1 ©2024 The Qt Company Ltd.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property
of their respective owners.