* H.J. Lu <[email protected]> [2015-04-17 05:36:30 -0700]: > On Fri, Apr 17, 2015 at 4:59 AM, Jakub Jelinek <[email protected]> wrote: > > On Fri, Apr 17, 2015 at 04:48:48AM -0700, H.J. Lu wrote: > >> > I don't like it. Nonshared libgcc is libgcc.a, period. No sense in > >> > creating yet another library for that. > >> > So, IMHO beyond making the __cpu* entrypoints compat symbols only (@ > >> > instead > >> > of @@ symbol versions) the right fix is simply tweak init_gcc_spec, so > >> > that > >> > static_name is always linked in, in the switch combinations that it isn't > >> > right now of course after shared_name rather than before that. > >> > I thought we've fixed that years ago... > >> >
I think the patch committed for this is suboptimal. (it breaks with musl libc on x86 if libgcc_s is linked into a binary) the patch: http://gcc.gnu.org/ml/gcc-patches/2015-04/msg00878.html original thread: http://gcc.gnu.org/ml/gcc-patches/2015-03/msg01520.html The symbol versioning hack for __cpu_model and __cpu_indicator_init makes them invisible to the musl dynamic linker so their relocation fails with 'symbol not found' error. (affects anything linked with -lgcc_s) I don't yet understand all the constraints, what I gathered is * x86 multi-versioning was broken with libgcc_s because ifunc resolution tried to use a libgcc_s function before it was relocated. (mv dispatch uses ifunc before relocation is finished, that calls __builtin_cpu_init that turns into a call to __cpu_indicator_init that is a constructor in libgcc_s.so to initialize __cpu_model). * old binaries that happened to work still have to work with new libgcc_s.so so __cpu_* must have a definition there. * new binaries must get their own definition of __cpu_* (ie statically linked from libgcc.a) to avoid the ifunc issue. I would rename the __cpu_* symbols and put those only in libgcc.a while keeping the old __cpu_* symbols still available in libgcc_s.so: old binaries work with new gcc, new binaries get the right definitions (so they work on old systems and new systems too, and yes -lgcc should be passed to c++ dso linking). Did i miss something? (This is not in the gcc-5 branch so I assume It is OK to work on a less intrusive fix.) PS.: It would be nice if there was a specification for the ifunc interface contract before any ifunc/multiversioned interface gets into the compiler runtime (see libatomic.so) to avoid similar bugs and incompatibilities between the dynamic linker/loader and compiler, the dynamic linker cannot guarantee arbitrary ifunc calls to work. > >> > >> We never pass -lgcc to linker when building C++ DSO: > >> > >> /usr/libexec/gcc/x86_64-redhat-linux/4.9.2/collect2 -plugin > >> /usr/libexec/gcc/x86_64-redhat-linux/4.9.2/liblto_plugin.so > >> -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper > >> -plugin-opt=-fresolution=/tmp/ccZC7iqy.res > >> -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc > >> -plugin-opt=-pass-through=-lgcc_s --build-id --no-add-needed > >> --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -shared > >> /usr/lib/gcc/x86_64-redhat-linux/4.9.2/../../../../lib64/crti.o > >> /usr/lib/gcc/x86_64-redhat-linux/4.9.2/crtbeginS.o > >> -L/usr/lib/gcc/x86_64-redhat-linux/4.9.2 > >> -L/usr/lib/gcc/x86_64-redhat-linux/4.9.2/../../../../lib64 > >> -L/lib/../lib64 -L/usr/lib/../lib64 > >> -L/usr/lib/gcc/x86_64-redhat-linux/4.9.2/../../.. x.o -lstdc++ -lm > >> -lgcc_s -lc -lgcc_s /usr/lib/gcc/x86_64-redhat-linux/4.9.2/crtendS.o > >> /usr/lib/gcc/x86_64-redhat-linux/4.9.2/../../../../lib64/crtn.o > >> [hjl@gnu-32 tmp]$ > >> > >> That is why libgcc_nonshared.a is needed. > > > > See what I wrote. I think it is a bug that we don't do that, in your case > > we should pass -lgcc_s -lgcc -lc -lgcc_s -lgcc. > > Or, if you don't want to change that, as the multi-versioning change is > > i386/x86_64 only change, just ensure that those targets have > > t-slibgcc-libgcc in libgcc/config.host and thus behave like most other linux > > targets where -lgcc is linked in always after -lgcc_s. > > > > Jakub > > This patch works for me. OK for trunk? > > gcc/testsuite/ > > PR target/65612 > * g++.dg/ext/mv18.C: New test. > * g++.dg/ext/mv19.C: Likewise. > * g++.dg/ext/mv20.C: Likewise. > * g++.dg/ext/mv21.C: Likewise. > * g++.dg/ext/mv22.C: Likewise. > * g++.dg/ext/mv23.C: Likewise. > > libgcc/ > > PR target/65612 > * config.host (tmake_file): Add t-slibgcc-libgcc for Linux/x86. > * config/i386/cpuinfo.c (__cpu_model): Initialize. > (__cpu_indicator_init@GCC_4.8.0): New. > (__cpu_model@GCC_4.8.0): Likewise. > * config/i386/t-linux (HOST_LIBGCC2_CFLAGS): Add > -DUSE_ELF_SYMVER. > > Thanks. > > -- > H.J.
