[Bug gcov-profile/44779] The gcov library does not adequately handle functions with constructor/destructor attributes
marxin at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Tue Aug 9 12:02:00 GMT 2016
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44779
Martin Liška <marxin at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|WAITING |RESOLVED
CC| |marxin at gcc dot gnu.org
Resolution|--- |INVALID
--- Comment #6 from Martin Liška <marxin at gcc dot gnu.org> ---
(In reply to Jay Vaughan from comment #0)
> I am developing a software system which has the requirement (as it is
> safety-critical), that we report full coverage of our modules as part of the
> validation process.
>
> One aspect of this software system is the inclusion of a library - lets call
> it libguardian - which is wrapped around all applications being run on our
> custom system, using LD_PRELOAD. The purpose of libguardian is to obtain
> valid conditions for continued launch prior to the execution of main() by
> the runtime in the wrapped application. To this end, libguardian defines a
> constructor and destructor pair of functions that obtain the valid
> conditions required for continued launch, and clean up/report on exit of the
> application.
>
> This libguardian, and associated applications, works perfectly fine.
> However, it is not possible to capture coverage information for these
> functions due to limits in gcov.
>
> The constructor/destructor methods are defined thus:
>
>
> #define GUARDIAN_CONSTRUCTOR_DESTRUCTOR_PRIORITY 65535
> /* NOTE: this priority can also be 101! */
>
> void guardian_constructor(void) __attribute__
> ((constructor(GUARDIAN_CONSTRUCTOR_DESTRUCTOR_PRIORITY)));
>
> void guardian_destructor(void) __attribute__
> ((destructor(GUARDIAN_CONSTRUCTOR_DESTRUCTOR_PRIORITY)));
>
>
> If the guardian_constructor() finds conditions unsavory for continued
> execution in our environment, it exit()'s immediately. In this circumstance,
> coverage is lost (or not provided) by gcov's atexit/destructor methods, as
> it appears that *priority* of known constructors is not accounted for in the
> gcov library, nor is there an atexit() handler that can adequately sort
> these priorities.
Well, there are two scenarios that happen for your test-case:
1) guardian_constructor exits: as the function is called via LD_PRELOAD,
libgcov is not yet registered and cannot produce any *.gcda files. It's
unrelated to priorities of dtors/atexit handlers
2) _SHOULD_CONSTRUCTOR_DIE_ is undefined: all works fine except
guardian_exiter:
LD_PRELOAD=./testlib.so ./testapp
++++++ GUARDIAN CONSTRUCTOR STAGE: [15226]
This is a number between 1 and 10: 1
This is a number between 1 and 10: 2
This is a number between 1 and 10: 3
This is a number between 1 and 10: 4
This is a number between 1 and 10: 5
This is a number between 1 and 10: 6
This is a number between 1 and 10: 7
This is a number between 1 and 10: 8
This is a number between 1 and 10: 9
This is a number between 1 and 10: 10
**********************************
gcov init is called
gcov init is called
^^ That was the constructor ^^
This is main() in the testapp()
By now, the testlib should have reported
its own progress in counting 1 to 10.
Next comes the destructor :::
gcov_exit is called
------ GUARDIAN DESTRUCTOR STAGE:
**********************************
gcov_exit is called
!!!!!! GUARDIAN EXIT HANDLER REACHED !!!!!!
gcov testlib.c
File 'testlib.c'
Lines executed:78.57% of 14
Creating 'testlib.c.gcov'
gcov testapp.c
File 'testapp.c'
Lines executed:100.00% of 3
Creating 'testapp.c.gcov'
As you can see, I added dumping of gcov_init/gcov_exit. The only functions
which is not seen by coverage is:
#####: 16:static void guardian_exiter(void)
-: 17:{
#####: 18: fprintf(stderr, "!!!!!! GUARDIAN EXIT HANDLER REACHED
!!!!!!\n");
#####: 19:}
That's kind of expected behavior because atexit handlers are executed in
reverse order to how they were registered.
I would recommend to not utilize atexit handler and do the necessary work in
guardian_destructor.
Due to aforementioned explanation, I'm closing the PR as invalid.
More information about the Gcc-bugs
mailing list