I am creating a shared library and I noticed that by using __attribute__((visibility("default"))) (together with -fvisibility=hidden) my library exports also _init and _fini symbols. If I use a an exported_symbols list (together with -Wl,--version-script=<file_list>) the lib only exports my functions, which is perfect.
Is it a way to use the first solution and only export my functions, without _init and _fini? thanks
First of all, the issue is not limited to _init and _fini - GNU toolchain exports other useless symbols by default e.g. _edata, etc. These symbols are indeed completely unnecessary (dynamic linker obtains pointers to ctors/dtors by different means).
I've recently reported the issue to gcc-help and Binutils lists. Reply in Bintools list was that although these symbols are indeed not used on Linux systems, removing them must be very careful and require a lot of testing and performance gains would be negligible. I didn't get answer in gcc-help (maybe makes sense to re-post in gcc developers list).
As a workaround, you can explicitly hide unwanted symbols via version script:
$ cat myapp.version
{
  global: XML_*; _INTERNAL_*;
  local: *;
};
$ cat Makefile
...
LDFLAGS += -Wl,--version-script=myapp.version
An example of this for Expat project can be found here. One issue with this approach (apart from adding boilerplate to all projects instead of fixing it once in Binutils/GCC) is that it's hard to get it right with Autoconf.
Note that even if you use version script, you still need to compile with -fvisibility=hidden (it allows compiler to perform more aggressive optimizations on hidden symbols, whereas in version script's case compiler is unaware of what ends up being hidden).
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