https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83074

--- Comment #6 from Stefan Vargyas <stvar at yahoo dot com> ---
> 
> Don't use --export-dynamic.  This causes __libc_csu_{init,fini} to be shared
> between the objects instead of having a private copy in each object.
> 

Thank you very much Andreas for your deep inside knowledge!

Indeed, as I'll show below, '__libc_csu_{init,fini}' are
the culprits for 'foo.so' blocking at exit after being
loaded in by 'bar':

(1) Build 'foo.so' exactly as before:

  $ make allclean

  $ make GCC=gcc-7.2.0 COVERAGE=yes foo.so

(2) The ELF file obtained has its dynamic symbol table
containing '__libc_csu_{init,fini}', with both symbols
having their binding set to 'STB_GLOBAL' and visibility
to 'STV_DEFAULT':

  $ readelf --dyn-syms foo.so|grep -E 'libc_csu_(init|fini)'
      46: 0000000000003540   137 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
      49: 0000000000003530     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini

(3) Do some manual patching of the ELF file for to set
binding to 'STB_LOCAL' and visibility to 'STV_HIDDEN':

  $ ghex2 foo.so

  $ readelf --dyn-syms foo.so|grep -E 'libc_csu_(init|fini)'
      46: 0000000000003540   137 FUNC    LOCAL  HIDDEN    14 __libc_csu_init
      49: 0000000000003530     2 FUNC    LOCAL  HIDDEN    14 __libc_csu_fini

Note that I couldn't avoid manually patching 'foo.so'
since none of the linker options seems to be able to
help (neither `--dynamic-list' nor `--version-script').
Couldn't find help using 'objcopy' either: this tool
doesn't want to touch the dynamic symbol table at all!

(4) Now build 'bar' using the patched 'foo.so':

  $ make GCC=gcc-7.2.0 COVERAGE=yes bar

(5) Both 'foo.so' and 'bar' work nicely (not hanging
anymore):

  $ ./foo.so 
  foo.so: version: 0.1

  $ ./bar
  bar: foo.so: version: 0.1

Only one final remark: `-pie' without `--export-dynamic'
still causes '__libc_csu_{init,fini}' to be added to the
dynamic symbol table:

  $ gcc-7.2.0 -I. -fPIC -fvisibility=hidden -c foo.c -o foo.o

  $ gcc-7.2.0 -Wl,-L. -pie foo.o -o foo.so

  $ readelf --dyn-syms foo.so|grep -P 'libc_csu_(init|fini)'
      40: 00000000000033f0   137 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
      42: 00000000000033e0     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini

Reply via email to