Fuwei
Fuwei

Reputation: 11

Using __gcov_flush within a library doesn't force the other modules to yield .gcda files

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

Answers (1)

Sergey
Sergey

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.

  1. 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.

  2. 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

Related Questions