I am trying to get code coverage for an arm based embedded system. Using x86 for cross compilation.So basically, I have a cross profiling question.
For the application I want to generate code coverage data, I have defined a signal handler inside which I call __gcov_flush()
to flush code coverage data to .gcda files. I am sending SIGUSR1 to the application. The application uses multiple .so files where bulk of the code and logic is implemented.
When I send the signal to the process, the .gcda files for just the application get created/updated. The .gcda files for the .so's are not created/updated at all.
Is there a way to make __gcov_flush()
flush all the coverage data for the .so's that the application is using?
I dont want to force the application to exit()
because that would defeat the purpose of what I am trying to do. I need to be able to dump coverage data for the application and the .so it uses at runtime.
Please help!!
Using ARM GCC v4.5.1.
This is what I have done so far to generate code coverage data:
I have defined the following options for GCC in the Master makefile:
CFLAGS += -fprofile-arcs -ftest-coverage
LDFLAGS += -fprofile-arcs -ftest-coverage
I am also exporting GCOV_PREFIX
and GCOV_PREFIX_STRIP
as global environment variables on the target system to force the .gcda files to be created in a specific path. This is working.
My only problem is the .gcda files for the .so's not getting created/update when __gcov_flush()
is called from the application.
This question got answered on GCC mailing list. TLDR: One needs to add a handler inside every shared library used, that will dump the coverage data. Then these handlers need to be called.
Detailed answer from the mailing list follows.
On Fri, 19 Jun 2015, Utpal Patel wrote:
I am trying to get code coverage for an arm based embedded system. Using x86 for cross compilation.So basically, I have a cross profiling question.
For the application I want to generate code coverage data, I have defined a signal handler inside which I call __gcov_flush() to flush code coverage data to .gcda files. I am sending SIGUSR1 to the application. The application uses multiple .so files where bulk of the code and logic is implemented.
When I send the signal to the process, the .gcda files for just the application get created/updated. The .gcda files for the .so's are not created/updated at all.
Is there a way to make __gcov_flush() flush all the coverage data for the .so's that the application is using?
I dont want to force the application to exit() because that would defeat the purpose of what I am trying to do. I need to be able to dump coverage data for the application and the .so it uses at runtime. Please help!!
When you compiled your application with
-fprofile-arcs -ftest-coverage
only the application was instrumented (conceptually a 64bit counters in each basic block of the apps minimum spaning tree) and those counters are what__gcov_flush()
is dumping.So if you want profiling infos from libraries you need to compile the library for profiling as gcov is a static instrumentation and there is no way to get infos from a
.so
without that it was compiled for profiling just like your application. If the application is compiled for profiling then its data will be dumped when you call__gcov_flush()
but since you can not send signals to a library to call some handler you would need to install some other mechanism in the library e.g. brute force put aint libdump(void) { __gcov_flush(); }
into the library and call that from your application signal handler just like you called
__gcov_flush();
now.This is from a trivial library that just provides an open call that is a wrapper to libc open and the libdump function
2: 77:int libdump(void) { 2: 78: __gcov_flush(); 1: 79: return 0; -: 80:} -: 81:/* we now can get code coverage of the library */ 145: 82:int open(const char *pathname, int flags, mode_t mode) { 145: 83: return __open(pathname, flags, mode); -: 84:}
the library is compiled with
gcc -fPIC -Wall -g -O2 -fprofile-arcs -ftest-coverage -shared -o libgctest.so.0 libgc.c
the application has the
libdump()
in the signal handlerint libdump(void); void gc_handler(int signum) { printf("received signal\n"); __gcov_flush(); /* dump coverage data on receiving SIGUSR1 */ libdump(); /* and dump library converage data */ }
and is compiled with
gcc -O2 -fprofile-arcs -ftest-coverage hello.c -o hello -lgctest `kill -10 <PIDOF application>` will now dump the gcda of both application and library.
HTH hofrat
ps: I have no clue why the count of the return 0 line in the libhandler does not have a count of 2 as well....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With