Reputation: 11
Lately I have been trying to use gcc/gcov to undertake code-coverage testing for a C++ project. The project consists of its main module and several .so libraries, which should all be taken into measurement.
I have compiled all the modules with --coverage parameter each with gcc and kept them where they were generated, together with corresponding .gcno tag files. After a normal execution and graceful exit the .gcda files could be properly generated. The problem is, the program is supposed to be a services without interruption or termination, and it's not allowed to insert any customized code (like a signal handler) into the main module. As the solutions from the web suggest, I wrote a signal handler function in a standalone .so library, which invokes __gcov_flush on receiving SIGUSR1 signal to flush the runtime coverage counters to files.
However, it was observed that, while the __gcov_flush function is guaranteed to be properly invoked, only the .gcda file of the .so library is generated during runtime. It seems to me that __gcov_flush is in charge of flushing the data of the wrapper module but not the others. I wonder if this is how it is supposed to work, or is there some tricks I need to take care of to generate complete results?
Upvotes: 1
Views: 2341
Reputation: 31
I see two problems here.
If your executable loads several shared libraries it is quite hard
to get the functionality needed. The linker adds profiling code from
libgcov.a
for every shared library and it is hard to call every
library's __gcov_flush()
from one central place like signal handler
defined in yet another shared library.
The function __gcov_flush()
function from libgcov.a
is declared
with __attribute__ ((__visibility__ ("hidden")))
If you extract _gcov.o from the archive and run
objdump -t _gcov.o
you see something like
_gcov.o: file format elf32-littlearm
SYMBOL TABLE:
000014b4 g F .text 00000016 .hidden __gcov_flush
Linker doesn't export hidden symbols even if you ask it to do that as it mentioned here or here
So I see two solutions for the second problem.
You may try to edit symbol table for _gcov.o
in libgcov.a
and
set visibility to "default"
instead of "hidden"
. I didn't take
that way because I didn't find any good elf editor.
If you managed to do that make sure to update your link command so
it links this patched _gcov.o
instead of default one from
libgcov.a
. Basically, you need to remove --coverage
option from
your linker flags for that.
You may create a wrapper for __gcov_flush()
declare and export it
as it suggested in the links above. Call this wrapper from your
signal handler in the shared library.
I suggest you not to add profiling for the small signal handler library - it is really unnecessary.
Upvotes: 0