Hi,
starting with GCC 4.7 the visibility of template instantiations also
depends on the visibility of the template arguments. So if I am building
a shared library with -fvisibility=hidden and a template class like
std::vector<A>
then std::vector and class A both need to have explicitly declared
default visibility to make std::vector<A> also visible and usable for
library users.
However the upshot is that all calls to std::vector functions that can
not be inlined will be resolved through the PLT. This can introduce
slowdown in hot code paths. I do not need to have the ability to replace
a function through e.g. LD_PRELOAD, so this mechanism is overhead for
me. To workaround it I have tried several solutions:
1) At first it seems like protected visibility is the correct solution.
However, I encountered two problems:
- Mixing protected with default visibility is causing problems quickly
- Replacing default with protected visibility will quickly lead to
strange linker errors. It looks like there are a couple of known bugs
here, and nobody is fixing them because nobody really is using protected
visibility.
2) The -Bsymbolic ld flag also looks very promising:
"When creating a shared library, bind references to global symbols to
the
definition within the shared library, if any."
When building my codebase with this I encountered some strange crashes.
I guess I could debug those but the codebase is rather large...
3) Finally I tried tagging all methods in the class (std::vector in the
example above) with hidden visibility. Thus no more PLT calls are
generated and the code becomes faster.
However this solution is rather cumbersome. #pragma GCC visibility
doesn't work here either.
Are there some best practices how to solve this problem in general?
Is there a way to make solution 3) easier?
Or should I rather try to get solution 2) working?
Thanks and best regards,
Martin