How to prevent GLIBC symbols from being exported from an .so?

Viewed 80

I am linking GLIBC statically into my .so:

g++ -shared -o morpher.so -static-libstdc++ -static-libgcc -Wl,-L. -Wl,--whole-archive -l:hello.o -l:libmorpher.a -Wl,--no-whole-archive

I do this to make my binary (.so) portable across different Linux distributions and versions.

However, this has an undesirable side effect: all GLIBC symbols, including e.g. malloc() and free(), are exported from my shared library:

$ nm morpher.so | grep free
00000000000ef520 t _ZN12_GLOBAL__N_14pool4freeEPv.constprop.0
000000000008b08c t _ZN12_GLOBAL__N_14pool4freeEPv.constprop.0.cold
00000000000ef710 T _ZN9__gnu_cxx9__freeresEv
00000000000ef860 T __cxa_free_dependent_exception
00000000000ef7b0 T __cxa_free_exception
                 U __freelocale@@GLIBC_2.2.5
                 U free@@GLIBC_2.2.5

Adding -fvisibility=hidden has no effect: it only works on source files at compile time.

Is there a way to prevent GLIBC and libstdc++ symbols from being exported?

1 Answers

nm (without the -D option) shows the static symbol table (.symtab), not the dynamic symbol table (.dynsym). Only the dynamic symbol table is relevant to dynamic linking.

In your case, it appears that the symbols are not actually defined in the shared object. Rather, __freelocale and free are undefined (U) or imported. If you build your shared object on the oldest distribution you want to support, such imports do not impact cross-distribution compatibility because glibc has a compatible ABI across distributions, and later versions support symbols from older versions.

-static-libgcc is about libgcc (not glibc). A lot of libgcc is always statically linked. The shared-by-default part is mostly about the unwinder, and linking that dynamically is recommended, so that the system unwinder is used.

Related