[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