This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH] PR target/65612: Multiversioning doesn't work with DSO nor PIE
- From: Szabolcs Nagy <nsz at port70 dot net>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: Jakub Jelinek <jakub at redhat dot com>, Uros Bizjak <ubizjak at gmail dot com>, Mike Stump <mikestump at comcast dot net>, Jack Howarth <howarth dot at dot gcc at gmail dot com>, Ian Lance Taylor <ian at airs dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>, Iain Sandoe <iain at codesourcery dot com>, Rainer Orth <ro at cebitec dot uni-bielefeld dot de>, Rich Felker <dalias at libc dot org>
- Date: Sat, 9 May 2015 16:31:04 +0200
- Subject: Re: PATCH] PR target/65612: Multiversioning doesn't work with DSO nor PIE
- Authentication-results: sourceware.org; auth=none
- References: <CAJMcOU9hcqopdDfpYbP5d=JLVVLUMnvqZWPQt14kH3T6DgVB8w at mail dot gmail dot com> <CAMe9rOpj-nx=eYzLD9gjy4tVuUbbii8nx0pzM8ynWEvK+WLPLA at mail dot gmail dot com> <B1F30D20-7B2F-477E-87AB-82BAA7039767 at comcast dot net> <CAFULd4aTcfyDVpMQVyZ2Po=BCG5ZQxV1Qq5TD5xsZ3LeGNwOFw at mail dot gmail dot com> <CAMe9rOpim6FhVk=ts3Zd4jfNU+oAXmtpy2aWy+ZP7qJ75E9H8g at mail dot gmail dot com> <CAFULd4bDmOcJ4bm8GpGvNL6-TCZYpZuC79RHGw_+BKD08ZF73A at mail dot gmail dot com> <20150417113731 dot GL1725 at tucnak dot redhat dot com> <CAMe9rOpGbB=UuSg3s437FaedD_mugzYKffdrJJfZEHVQQEBODQ at mail dot gmail dot com> <20150417115950 dot GM1725 at tucnak dot redhat dot com> <CAMe9rOp_Eck1MEOV6btcHLOsd5u0=dtEQDq3iy0QY0RvXwuVDQ at mail dot gmail dot com>
* H.J. Lu <hjl.tools@gmail.com> [2015-04-17 05:36:30 -0700]:
> On Fri, Apr 17, 2015 at 4:59 AM, Jakub Jelinek <jakub@redhat.com> 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.