Discussion:
libgcov as shared library and other issues
Alexander Monakov
2018-09-24 22:21:55 UTC
Permalink
Hello,

Here's the promised "libgcov summary"; sorry about the delay.

So libgcov has a bit unusual design where:

- on the one hand, the library is static-only, has PIC code and may be linked
into shared libraries,

- almost all gcov symbols have "hidden" visibility so they don't participate
in dynamic linking

- on the other hand, the __gcov_master symbol deliberately has default
visibility, presumably with the intention that a running program has exactly
one instance of this symbol, although the exact motivation is unclear to me.

This latter point does not reliably work as intended though: there are scenarios
where a dynamically linked program will have multiple __gcov_masters anyway:

- via repeated dlopen(RTLD_LOCAL) with main executable not linked against libgcov
or not exporting libgcov symbols (as in PR 83879)
- when shared libraries have version scripts that hide their __gcov_master
- when -Bsymbolic is in effect


Additionally, indirect call profiling symbols are not hidden either, and that
leads to extra complications. Since there are multiple symbols, during dynamic
linking they may be partially interposed. PR 84107 demonstrates how this leads
to libgcov segfaulting in a fairly simple and legitimate program.

Bottom line: static linking code with default-visibility symbols
into shared libraries is problematic.

So one strategy is to ensure all gcov symbols have hidden visibility. That would
isolate gcov instances in each shared library loaded in the program, and each
library would have the responsibility to write out its counters when unloaded.
Also, __gcov_dump would dump only the counters specific to the current library.

I may be missing something here so it might be nice to unearth why exactly
__gcov_master is intended to be global.

Another strategy is to introduce libgcov.so and have it host either all libgcov
symbols or just those that by design are required to exist once in the program.

When talking to Richi at the Cauldron I got the impression he'd question if
shared libgcov is worth the cost, e.g. would it make any easier for users to
mix two libraries, one linked against older libgcov, and another with a newer
(something that doesn't work at all now, but would be nice to support if I
understood Richard correctly).

Alexander
Martin Liška
2018-09-26 09:46:56 UTC
Permalink
Post by Alexander Monakov
Hello,
Here's the promised "libgcov summary"; sorry about the delay.
Thank you Alexander, I take it as productive discussion starting point.
Post by Alexander Monakov
- on the one hand, the library is static-only, has PIC code and may be linked
into shared libraries,
- almost all gcov symbols have "hidden" visibility so they don't participate
in dynamic linking
- on the other hand, the __gcov_master symbol deliberately has default
visibility, presumably with the intention that a running program has exactly
one instance of this symbol, although the exact motivation is unclear to me.
The only usage I see right now is support of __gcov_reset, __gcov_dump function.
Which in my opinion should cover all loaded DSOs in an executable.
Post by Alexander Monakov
This latter point does not reliably work as intended though: there are scenarios
- via repeated dlopen(RTLD_LOCAL) with main executable not linked against libgcov
or not exporting libgcov symbols (as in PR 83879)
Here we have a work-around: --dynamic-list-data.
Post by Alexander Monakov
- when shared libraries have version scripts that hide their __gcov_master
- when -Bsymbolic is in effect
Additionally, indirect call profiling symbols are not hidden either, and that
leads to extra complications. Since there are multiple symbols, during dynamic
linking they may be partially interposed. PR 84107 demonstrates how this leads
to libgcov segfaulting in a fairly simple and legitimate program.
For this one, we have a working work-around: https://gcc.gnu.org/ml/gcc-patches/2018-09/msg00961.html
Post by Alexander Monakov
Bottom line: static linking code with default-visibility symbols
into shared libraries is problematic.
So one strategy is to ensure all gcov symbols have hidden visibility. That would
isolate gcov instances in each shared library loaded in the program, and each
library would have the responsibility to write out its counters when unloaded.
Also, __gcov_dump would dump only the counters specific to the current library.
I may be missing something here so it might be nice to unearth why exactly
__gcov_master is intended to be global.
Another strategy is to introduce libgcov.so and have it host either all libgcov
symbols or just those that by design are required to exist once in the program.
When talking to Richi at the Cauldron I got the impression he'd question if
shared libgcov is worth the cost, e.g. would it make any easier for users to
mix two libraries, one linked against older libgcov, and another with a newer
(something that doesn't work at all now, but would be nice to support if I
understood Richard correctly).
Alexander
Note that I'm fan of the shared library. I actually prepared working patch for that.
So my strategy would be to first install the suggested patch:
https://gcc.gnu.org/ml/gcc-patches/2018-09/msg00961.html

and then we Richi is fine, we can also add the shared library patch.

Martin
Richard Biener
2018-09-27 10:04:48 UTC
Permalink
Post by Martin Liška
Post by Alexander Monakov
Hello,
Here's the promised "libgcov summary"; sorry about the delay.
Thank you Alexander, I take it as productive discussion starting point.
Post by Alexander Monakov
- on the one hand, the library is static-only, has PIC code and may be linked
into shared libraries,
- almost all gcov symbols have "hidden" visibility so they don't participate
in dynamic linking
- on the other hand, the __gcov_master symbol deliberately has default
visibility, presumably with the intention that a running program has exactly
one instance of this symbol, although the exact motivation is unclear to me.
The only usage I see right now is support of __gcov_reset, __gcov_dump function.
Which in my opinion should cover all loaded DSOs in an executable.
I guess so. That could be still implemented some dlsym walking though.
Post by Martin Liška
Post by Alexander Monakov
This latter point does not reliably work as intended though: there are scenarios
- via repeated dlopen(RTLD_LOCAL) with main executable not linked against libgcov
or not exporting libgcov symbols (as in PR 83879)
Here we have a work-around: --dynamic-list-data.
Post by Alexander Monakov
- when shared libraries have version scripts that hide their __gcov_master
- when -Bsymbolic is in effect
Additionally, indirect call profiling symbols are not hidden either, and that
leads to extra complications. Since there are multiple symbols, during dynamic
linking they may be partially interposed. PR 84107 demonstrates how this leads
to libgcov segfaulting in a fairly simple and legitimate program.
For this one, we have a working work-around: https://gcc.gnu.org/ml/gcc-patches/2018-09/msg00961.html
Post by Alexander Monakov
Bottom line: static linking code with default-visibility symbols
into shared libraries is problematic.
So one strategy is to ensure all gcov symbols have hidden visibility. That would
isolate gcov instances in each shared library loaded in the program, and each
library would have the responsibility to write out its counters when unloaded.
Also, __gcov_dump would dump only the counters specific to the current library.
I may be missing something here so it might be nice to unearth why exactly
__gcov_master is intended to be global.
Another strategy is to introduce libgcov.so and have it host either all libgcov
symbols or just those that by design are required to exist once in the program.
When talking to Richi at the Cauldron I got the impression he'd question if
shared libgcov is worth the cost, e.g. would it make any easier for users to
mix two libraries, one linked against older libgcov, and another with a newer
(something that doesn't work at all now, but would be nice to support if I
understood Richard correctly).
Alexander
Note that I'm fan of the shared library. I actually prepared working patch for that.
https://gcc.gnu.org/ml/gcc-patches/2018-09/msg00961.html
and then we Richi is fine, we can also add the shared library patch.
I don't stand in the way of a shared libgcov I just think it may be not worth
the trouble...

Richard.
Post by Martin Liška
Martin
Loading...