diff mbox

PATCH] PR target/65612: Multiversioning doesn't work with DSO nor PIE

Message ID CAMe9rOrGCRJhWpNT0hMJwKCG2+vaDsaRou7JV0tdjiANnmRm=g@mail.gmail.com
State New
Headers show

Commit Message

H.J. Lu March 30, 2015, 10:25 p.m. UTC
On Sun, Mar 29, 2015 at 7:40 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sun, Mar 29, 2015 at 7:34 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Sun, Mar 29, 2015 at 7:25 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> We shouldn't call external function, __cpu_indicator_init, while an object
>>> is being relocated since its .got.plt section hasn't been updated.  It
>>> works for non-PIE since no update on .got.plt section is required.  This
>>> patch hides __cpu_indicator_init/__cpu_model from linker to force linker
>>> to resolve __cpu_indicator_init/__cpu_model to their hidden definitions
>>> in libgcc.a while providing backward binary compatibility.
>>>
>>> OK for trunk, 4.9 and 4.9 branches?
>>>
>>> Thanks.
>>>
>>>
>>> H.J.
>>> ---
>>> libgcc/
>>>
>>>         PR target/65612
>>>         * config/i386/cpuinfo.c (__cpu_model): Initialize.
>>>         (__cpu_indicator_init@GCC_4.8.0): New.
>>>         (__cpu_model@GCC_4.8.0): Likewise.
>>>
>>> gcc/testsuite/
>>>
>>>         PR target/65612
>>>         * g++.dg/ext/mv18.C: New test.
>>>         * g++.dg/ext/mv19.C: Likewise.
>>>         * g++.dg/ext/mv20.C: Likewise.
>>
>> It doesn' work for shared C++ library:
>>
>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/g++ -O2    -c
>> -o main.o main.cc
>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/g++ -shared
>> -fPIC -O2  -o libmv20.so mv20.cc
>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/g++ -O2  -o x
>> main.o libmv20.so -Wl,-R,.
>> /usr/local/bin/ld: x: hidden symbol `__cpu_model' in
>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.0.0/libgcc.a(cpuinfo.o)
>> is referenced by DSO
>> /usr/local/bin/ld: final link failed: Bad value
>> collect2: error: ld returned 1 exit status
>> Makefile:12: recipe for target 'x' failed
>> make: *** [x] Error 1
>> [hjl@gnu-tools-1 pr65612]$
>>
>> --
>> H.J.
>
> We need something like libgcc_nonshared.a, which contains cpuinfo.o, and
> link together with -lgcc_s when creating executable or DSO.
>

I am testing it on Linux/x86-64.  OK for master if regression test
passes?

Comments

Jack Howarth March 31, 2015, 12:53 a.m. UTC | #1
HJ,
     This patch breaks the bootstrap on targets like darwin which
don't build libgcc_nonshared.a...

if test -z "$objects"; then \
  echo 'int __libgcc_eh_dummy;' > eh_dummy.c; \
  /sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir/./gcc/xgcc
-B/sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir/./gcc/
-B/sw/lib/gcc5/x86_64-apple-darwin14.3.0/bin/
-B/sw/lib/gcc5/x86_64-apple-darwin14.3.0/lib/ -isystem
/sw/lib/gcc5/x86_64-apple-darwin14.3.0/include -isystem
/sw/lib/gcc5/x86_64-apple-darwin14.3.0/sys-include    -g -O2 -m32 -O2
-g -O2 -DIN_GCC    -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual
-Wno-format -Wstrict-prototypes -Wmissing-prototypes
-Wold-style-definition  -isystem ./include   -pipe -fno-common -g
-DIN_LIBGCC2 -fbuilding-libgcc -fno-stack-protector   -pipe
-fno-common -I. -I. -I../../.././gcc
-I../../../../gcc-5-20150330/libgcc
-I../../../../gcc-5-20150330/libgcc/.
-I../../../../gcc-5-20150330/libgcc/../gcc
-I../../../../gcc-5-20150330/libgcc/../include  -DHAVE_CC_TLS
-DUSE_EMUTLS -fvisibility=hidden -DHIDE_EXPORTS -c eh_dummy.c \
     -o eh_dummy.o; \
  objects=eh_dummy.o; \
fi; \
ar  rc libgcc_nonshared.a $objects
ar: cpuinfo.o: No such file or directory
Makefile:905: recipe for target 'libgcc_nonshared.a' failed
make[5]: *** [libgcc_nonshared.a] Error 1
make[5]: Leaving directory
'/sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir/x86_64-apple-darwin14.3.0/i386/libgcc'
Makefile:1168: recipe for target 'multi-do' failed
make[4]: *** [multi-do] Error 1
make[4]: Leaving directory
'/sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir/x86_64-apple-darwin14.3.0/libgcc'
Makefile:117: recipe for target 'all-multi' failed
make[3]: *** [all-multi] Error 2
make[3]: Leaving directory
'/sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir/x86_64-apple-darwin14.3.0/libgcc'
Makefile:14820: recipe for target 'all-stage1-target-libgcc' failed
make[2]: *** [all-stage1-target-libgcc] Error 2
make[2]: Leaving directory '/sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir'
Makefile:20760: recipe for target 'stage1-bubble' failed
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory '/sw/src/fink.build/gcc5-5.0.0-1/darwin_objdir'
Makefile:21064: recipe for target 'bootstrap' failed
make: *** [bootstrap] Error 2

          Jack

On Mon, Mar 30, 2015 at 6:25 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sun, Mar 29, 2015 at 7:40 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Sun, Mar 29, 2015 at 7:34 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Sun, Mar 29, 2015 at 7:25 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> We shouldn't call external function, __cpu_indicator_init, while an object
>>>> is being relocated since its .got.plt section hasn't been updated.  It
>>>> works for non-PIE since no update on .got.plt section is required.  This
>>>> patch hides __cpu_indicator_init/__cpu_model from linker to force linker
>>>> to resolve __cpu_indicator_init/__cpu_model to their hidden definitions
>>>> in libgcc.a while providing backward binary compatibility.
>>>>
>>>> OK for trunk, 4.9 and 4.9 branches?
>>>>
>>>> Thanks.
>>>>
>>>>
>>>> H.J.
>>>> ---
>>>> libgcc/
>>>>
>>>>         PR target/65612
>>>>         * config/i386/cpuinfo.c (__cpu_model): Initialize.
>>>>         (__cpu_indicator_init@GCC_4.8.0): New.
>>>>         (__cpu_model@GCC_4.8.0): Likewise.
>>>>
>>>> gcc/testsuite/
>>>>
>>>>         PR target/65612
>>>>         * g++.dg/ext/mv18.C: New test.
>>>>         * g++.dg/ext/mv19.C: Likewise.
>>>>         * g++.dg/ext/mv20.C: Likewise.
>>>
>>> It doesn' work for shared C++ library:
>>>
>>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/g++ -O2    -c
>>> -o main.o main.cc
>>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/g++ -shared
>>> -fPIC -O2  -o libmv20.so mv20.cc
>>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/g++ -O2  -o x
>>> main.o libmv20.so -Wl,-R,.
>>> /usr/local/bin/ld: x: hidden symbol `__cpu_model' in
>>> /export/build/gnu/gcc-x32/release/usr/gcc-5.0.0-x32/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.0.0/libgcc.a(cpuinfo.o)
>>> is referenced by DSO
>>> /usr/local/bin/ld: final link failed: Bad value
>>> collect2: error: ld returned 1 exit status
>>> Makefile:12: recipe for target 'x' failed
>>> make: *** [x] Error 1
>>> [hjl@gnu-tools-1 pr65612]$
>>>
>>> --
>>> H.J.
>>
>> We need something like libgcc_nonshared.a, which contains cpuinfo.o, and
>> link together with -lgcc_s when creating executable or DSO.
>>
>
> I am testing it on Linux/x86-64.  OK for master if regression test
> passes?
>
> --
> H.J.
> --
> We shouldn't call external function, __cpu_indicator_init, while an object
> is being relocated since its .got.plt section hasn't been updated.  It
> works for non-PIE since no update on .got.plt section is required.  This
> patch hides __cpu_indicator_init/__cpu_model from linker to force linker
> to resolve __cpu_indicator_init/__cpu_model to their hidden definitions
> in libgcc_nonshared.a while providing backward binary compatibility.  The
> new libgcc_nonshared.a is always linked togther with -lgcc_s and -lgcc.
>
> gcc/
>
> PR target/65612
> * gcc.c (init_spec): Add -lgcc_nonshared/libgcc_nonshared.a%s
> to -lgcc_s/-lgcc/libgcc.a%s.
>
> gcc/testsuite/
>
> PR target/65612
> * g++.dg/ext/mv18.C: New test.
> * g++.dg/ext/mv19.C: Likewise.
> * g++.dg/ext/mv20.C: Likewise.
>
> libgcc/
>
> PR target/65612
> * Makefile.in (LIB2ADDSHARED): New.
> (LIB2ADDNONSHARED): Likewise.
> (libgcc-nonshared-objects): Likewise.
> (libgcc_nonshared.a): Likewise.
> (libgcc-s-objects): Add $(LIB2ADDSHARED).
> (all): Depend on libgcc_nonshared.a.
> ($(libgcc-nonshared-objects)): Depend on libgcc_tm.h.
> (install-leaf): Install libgcc_nonshared.a.
> * 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-cpuinfo (LIB2ADD): Renamed to ...
> (LIB2ADDSHARED): This.
diff mbox

Patch

From 2dc6879c0c33069a02ae52d494f05603de9fe317 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 29 Mar 2015 18:03:49 -0700
Subject: [PATCH] Hide __cpu_indicator_init/__cpu_model from linker

We shouldn't call external function, __cpu_indicator_init, while an object
is being relocated since its .got.plt section hasn't been updated.  It
works for non-PIE since no update on .got.plt section is required.  This
patch hides __cpu_indicator_init/__cpu_model from linker to force linker
to resolve __cpu_indicator_init/__cpu_model to their hidden definitions
in libgcc_nonshared.a while providing backward binary compatibility.  The
new libgcc_nonshared.a is always linked togther with -lgcc_s and -lgcc.

gcc/

	PR target/65612
	* gcc.c (init_spec): Add -lgcc_nonshared/libgcc_nonshared.a%s
	to -lgcc_s/-lgcc/libgcc.a%s.

gcc/testsuite/

	PR target/65612
	* g++.dg/ext/mv18.C: New test.
	* g++.dg/ext/mv19.C: Likewise.
	* g++.dg/ext/mv20.C: Likewise.

libgcc/

	PR target/65612
	* Makefile.in (LIB2ADDSHARED): New.
	(LIB2ADDNONSHARED): Likewise.
	(libgcc-nonshared-objects): Likewise.
	(libgcc_nonshared.a): Likewise.
	(libgcc-s-objects): Add $(LIB2ADDSHARED).
	(all): Depend on libgcc_nonshared.a.
	($(libgcc-nonshared-objects)): Depend on libgcc_tm.h.
	(install-leaf): Install libgcc_nonshared.a.
	* 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-cpuinfo (LIB2ADD): Renamed to ...
	(LIB2ADDSHARED): This.
	(LIB2ADDNONSHARED): New.
---
 gcc/gcc.c                       |  4 ++++
 gcc/testsuite/g++.dg/ext/mv18.C |  7 +++++++
 gcc/testsuite/g++.dg/ext/mv19.C |  7 +++++++
 gcc/testsuite/g++.dg/ext/mv20.C |  7 +++++++
 libgcc/Makefile.in              | 20 +++++++++++++++++---
 libgcc/config/i386/cpuinfo.c    |  7 ++++++-
 libgcc/config/i386/t-cpuinfo    |  3 ++-
 7 files changed, 50 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/mv18.C
 create mode 100644 gcc/testsuite/g++.dg/ext/mv19.C
 create mode 100644 gcc/testsuite/g++.dg/ext/mv20.C

diff --git a/gcc/gcc.c b/gcc/gcc.c
index d956c36..88a8dac 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1566,11 +1566,13 @@  init_spec (void)
 	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
 	  {
 	    init_gcc_specs (&obstack,
+			    "-lgcc_nonshared "
 			    "-lgcc_s"
 #ifdef USE_LIBUNWIND_EXCEPTIONS
 			    " -lunwind"
 #endif
 			    ,
+			    "-lgcc_nonshared "
 			    "-lgcc",
 			    "-lgcc_eh"
 #ifdef USE_LIBUNWIND_EXCEPTIONS
@@ -1591,7 +1593,9 @@  init_spec (void)
 	    /* Ug.  We don't know shared library extensions.  Hope that
 	       systems that use this form don't do shared libraries.  */
 	    init_gcc_specs (&obstack,
+			    "libgcc_nonshared.a%s "
 			    "-lgcc_s",
+			    "libgcc_nonshared.a%s "
 			    "libgcc.a%s",
 			    "libgcc_eh.a%s"
 #ifdef USE_LIBUNWIND_EXCEPTIONS
diff --git a/gcc/testsuite/g++.dg/ext/mv18.C b/gcc/testsuite/g++.dg/ext/mv18.C
new file mode 100644
index 0000000..1f024de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/mv18.C
@@ -0,0 +1,7 @@ 
+/* Test case to check if Multiversioning works.  */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fPIE -pie" } */
+
+#include "mv1.C"
diff --git a/gcc/testsuite/g++.dg/ext/mv19.C b/gcc/testsuite/g++.dg/ext/mv19.C
new file mode 100644
index 0000000..d1ea788
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/mv19.C
@@ -0,0 +1,7 @@ 
+/* Test case to check if Multiversioning works.  */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fPIE -pie -march=x86-64" } */
+
+#include "mv14.C"
diff --git a/gcc/testsuite/g++.dg/ext/mv20.C b/gcc/testsuite/g++.dg/ext/mv20.C
new file mode 100644
index 0000000..98f7408
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/mv20.C
@@ -0,0 +1,7 @@ 
+/* Test case to check if Multiversioning works.  */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fPIE -pie -march=x86-64" } */
+
+#include "mv15.C"
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 88ddfea..cec4ae0 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -261,6 +261,14 @@  LIB2ADD =
 # Assembler files should have names ending in `.S'.
 LIB2ADD_ST =
 
+# List of extra C and assembler files to add to shared libgcc2.
+# Assembler files should have names ending in `.S'.
+LIB2ADDSHARED =
+
+# List of extra C and assembler files to add to libgcc_nonshared.a.
+# Assembler files should have names ending in `.S'.
+LIB2ADDNONSHARED =
+
 # Specify the directories to be searched for header files.
 # Both . and srcdir are used, in that order,
 # so that *config.h will be found in the compilation
@@ -806,13 +814,14 @@  endif
 
 libgcc-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADD))))
 libgcc-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADD_ST))))
+libgcc-nonshared-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADDNONSHARED))))
 
 c_flags :=
 iter-items := $(LIB2ADD) $(LIB2ADD_ST)
 include $(iterator)
 
 ifeq ($(enable_shared),yes)
-libgcc-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIB2ADD))))
+libgcc-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIB2ADD) $(LIB2ADDSHARED))))
 endif
 
 # Build LIB2ADDEH, LIB2ADDEHSTATIC, and LIB2ADDEHSHARED.  If we don't have
@@ -890,8 +899,9 @@  libgcc.a: $(libgcc-objects)
 libgcov.a: $(libgcov-objects)
 libunwind.a: $(libunwind-objects)
 libgcc_eh.a: $(libgcc-eh-objects)
+libgcc_nonshared.a: $(libgcc-nonshared-objects)
 
-libgcc.a libgcov.a libunwind.a libgcc_eh.a:
+libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_nonshared.a:
 	-rm -f $@
 
 	objects="$(objects)";					\
@@ -905,7 +915,7 @@  libgcc.a libgcov.a libunwind.a libgcc_eh.a:
 
 	$(RANLIB) $@
 
-all: libgcc.a libgcov.a
+all: libgcc.a libgcc_nonshared.a libgcov.a
 
 ifneq ($(LIBUNWIND),)
 all: libunwind.a
@@ -1051,6 +1061,7 @@  libgcc-extra-parts: $(EXTRA_PARTS)
 all: $(extra-parts)
 
 $(libgcc-objects) $(libgcc-s-objects) $(libgcc-eh-objects) \
+	$(libgcc-nonshared-objects) \
 	$(libgcov-objects) \
 	$(libunwind-objects) $(libunwind-s-objects) \
 	$(EXTRA_PARTS): libgcc_tm.h
@@ -1118,6 +1129,9 @@  install-leaf: $(install-shared) $(install-libunwind)
 	$(INSTALL_DATA) libgcc.a $(DESTDIR)$(inst_libdir)/
 	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc.a
 	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc.a
+	$(INSTALL_DATA) libgcc_nonshared.a $(DESTDIR)$(inst_libdir)/
+	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_nonshared.a
+	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_nonshared.a
 	$(INSTALL_DATA) libgcov.a $(DESTDIR)$(inst_libdir)/
 	chmod 644 $(DESTDIR)$(inst_libdir)/libgcov.a
 	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcov.a
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index eaf2f10..9639c8d 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -109,7 +109,7 @@  struct __processor_model
   unsigned int __cpu_type;
   unsigned int __cpu_subtype;
   unsigned int __cpu_features[1];
-} __cpu_model;
+} __cpu_model = { };
 
 
 /* Get the specific type of AMD CPU.  */
@@ -424,3 +424,8 @@  __cpu_indicator_init (void)
 
   return 0;
 }
+
+#if defined SHARED && !defined _WIN32
+__asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
+__asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
+#endif
diff --git a/libgcc/config/i386/t-cpuinfo b/libgcc/config/i386/t-cpuinfo
index 31c8db9..8dbe9e6 100644
--- a/libgcc/config/i386/t-cpuinfo
+++ b/libgcc/config/i386/t-cpuinfo
@@ -1 +1,2 @@ 
-LIB2ADD += $(srcdir)/config/i386/cpuinfo.c
+LIB2ADDSHARED += $(srcdir)/config/i386/cpuinfo.c
+LIB2ADDNONSHARED += $(srcdir)/config/i386/cpuinfo.c
-- 
1.9.3