255 lines
9.5 KiB
Diff
255 lines
9.5 KiB
Diff
|
This fix is not correct and cannot be applied generally to x86_64
|
||
|
because Intel wishes to use IFUNC earlier in the dynamic loader
|
||
|
specifically to speedup TLS initialization, and as such that means
|
||
|
we cannot in glibc use TLS in IFUNC resolvers. In ppc64le though we
|
||
|
can use this patch to fix the sln (static application) problems until
|
||
|
upstream has a better solution.
|
||
|
|
||
|
https://www.sourceware.org/ml/libc-alpha/2017-07/msg00336.html
|
||
|
|
||
|
Changes since version 1:
|
||
|
|
||
|
- Added a testcase. This is now validating both statically and
|
||
|
dynamically linked executables.
|
||
|
- Fixed an issue in the $(foreach ..) in sysdeps/powerpc/powerpc64le/Makefile.
|
||
|
- Added a comment to csu/libc-start.c
|
||
|
- Added a comment to csu/libc-tls.c
|
||
|
|
||
|
-- 8< --
|
||
|
|
||
|
The patch proposed by Peter Bergner [1] to libgc in order to fix
|
||
|
[BZ #21707] adds a dependency on a symbol provided by the loader,
|
||
|
forcing the loader to be linked to tests after libgcc was linked.
|
||
|
|
||
|
It also requires to read the thread pointer during IRELA relocations.
|
||
|
|
||
|
Tested on powerpc, powerpc64, powerpc64le, s390x and x86_64.
|
||
|
|
||
|
[1] https://sourceware.org/ml/libc-alpha/2017-06/msg01383.html
|
||
|
|
||
|
2017-07-08 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||
|
|
||
|
[BZ #21707]
|
||
|
* csu/libc-start.c (LIBC_START_MAIN): Perform IREL{,A}
|
||
|
relocations after initializing the TCB on statically linked
|
||
|
executables..
|
||
|
* csu/libc-tls.c (__libc_setup_tls): Add a comment about
|
||
|
IREL{,A} relocations.
|
||
|
* elf/Makefile (tests-static-normal): Add tst-tlsifunc-static.
|
||
|
(tests): Add tst-tlsifunc.
|
||
|
* elf/tst-tlsifunc.c: New file.
|
||
|
* elf/tst-tlsifunc-static.c: Likewise.
|
||
|
* sysdeps/powerpc/powerpc64le/Makefile (f128-loader-link): New
|
||
|
variable.
|
||
|
[$(subdir) = math] (test-float128% test-ifloat128%): Force
|
||
|
linking to the loader after linking to libgcc.
|
||
|
[$(subdir) = wcsmbs stdlib] (bug-strtod bug-strtod2 bug-strtod2)
|
||
|
(tst-strtod-round tst-wcstod-round tst-strtod6 tst-strrom)
|
||
|
(tst-strfrom-locale strfrom-skeleton): Likewise.
|
||
|
---
|
||
|
csu/libc-start.c | 11 +++---
|
||
|
csu/libc-tls.c | 2 ++
|
||
|
elf/Makefile | 5 +--
|
||
|
elf/tst-tlsifunc-static.c | 19 +++++++++++
|
||
|
elf/tst-tlsifunc.c | 66 ++++++++++++++++++++++++++++++++++++
|
||
|
sysdeps/powerpc/powerpc64le/Makefile | 10 ++++++
|
||
|
6 files changed, 107 insertions(+), 6 deletions(-)
|
||
|
create mode 100644 elf/tst-tlsifunc-static.c
|
||
|
create mode 100644 elf/tst-tlsifunc.c
|
||
|
|
||
|
Index: glibc-2.25-717-g3020042/csu/libc-start.c
|
||
|
===================================================================
|
||
|
--- glibc-2.25-717-g3020042.orig/csu/libc-start.c
|
||
|
+++ glibc-2.25-717-g3020042/csu/libc-start.c
|
||
|
@@ -188,12 +188,15 @@ LIBC_START_MAIN (int (*main) (int, char
|
||
|
|
||
|
ARCH_INIT_CPU_FEATURES ();
|
||
|
|
||
|
- /* Perform IREL{,A} relocations. */
|
||
|
- apply_irel ();
|
||
|
-
|
||
|
/* The stack guard goes into the TCB, so initialize it early. */
|
||
|
__libc_setup_tls ();
|
||
|
|
||
|
+ /* Perform IREL{,A} relocations.
|
||
|
+ Note: the relocations must happen after TLS initialization so that
|
||
|
+ IFUNC resolvers can benefit from thread-local storage, e.g. powerpc's
|
||
|
+ hwcap and platform fields available in the TCB. */
|
||
|
+ apply_irel ();
|
||
|
+
|
||
|
/* Set up the stack checker's canary. */
|
||
|
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
|
||
|
# ifdef THREAD_SET_STACK_GUARD
|
||
|
@@ -224,7 +227,7 @@ LIBC_START_MAIN (int (*main) (int, char
|
||
|
__pointer_chk_guard_local = pointer_chk_guard;
|
||
|
# endif
|
||
|
|
||
|
-#endif
|
||
|
+#endif /* !SHARED */
|
||
|
|
||
|
/* Register the destructor of the dynamic linker if there is any. */
|
||
|
if (__glibc_likely (rtld_fini != NULL))
|
||
|
Index: glibc-2.25-717-g3020042/csu/libc-tls.c
|
||
|
===================================================================
|
||
|
--- glibc-2.25-717-g3020042.orig/csu/libc-tls.c
|
||
|
+++ glibc-2.25-717-g3020042/csu/libc-tls.c
|
||
|
@@ -101,6 +101,8 @@ init_static_tls (size_t memsz, size_t al
|
||
|
GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
|
||
|
}
|
||
|
|
||
|
+/* Note: IREL{,A} relocations happen after TLS setup. __libc_setup_tls has
|
||
|
+ to guarantee that it won't use STT_GNU_IFUNC. */
|
||
|
void
|
||
|
__libc_setup_tls (void)
|
||
|
{
|
||
|
Index: glibc-2.25-717-g3020042/elf/Makefile
|
||
|
===================================================================
|
||
|
--- glibc-2.25-717-g3020042.orig/elf/Makefile
|
||
|
+++ glibc-2.25-717-g3020042/elf/Makefile
|
||
|
@@ -151,12 +151,13 @@ tests-static-normal := tst-leaks1-static
|
||
|
tst-tlsalign-static tst-tlsalign-extern-static \
|
||
|
tst-linkall-static tst-env-setuid tst-env-setuid-tunables
|
||
|
tests-static-internal := tst-tls1-static tst-tls2-static \
|
||
|
- tst-ptrguard1-static tst-stackguard1-static
|
||
|
+ tst-ptrguard1-static tst-stackguard1-static \
|
||
|
+ tst-tlsifunc-static
|
||
|
|
||
|
tests := tst-tls9 tst-leaks1 \
|
||
|
tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
|
||
|
tst-auxv
|
||
|
-tests-internal := tst-tls1 tst-tls2 $(tests-static-internal)
|
||
|
+tests-internal := tst-tls1 tst-tls2 tst-tlsifunc $(tests-static-internal)
|
||
|
tests-static := $(tests-static-normal) $(tests-static-internal)
|
||
|
|
||
|
ifeq (yes,$(build-shared))
|
||
|
Index: glibc-2.25-717-g3020042/elf/tst-tlsifunc-static.c
|
||
|
===================================================================
|
||
|
--- /dev/null
|
||
|
+++ glibc-2.25-717-g3020042/elf/tst-tlsifunc-static.c
|
||
|
@@ -0,0 +1,19 @@
|
||
|
+/* Test if an executable can read from the TLS from an STT_GNU_IFUNC resolver.
|
||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
|
+ This file is part of the GNU C Library.
|
||
|
+
|
||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||
|
+ modify it under the terms of the GNU Lesser General Public
|
||
|
+ License as published by the Free Software Foundation; either
|
||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||
|
+
|
||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public
|
||
|
+ License along with the GNU C Library; if not, see
|
||
|
+ <http://www.gnu.org/licenses/>. */
|
||
|
+
|
||
|
+#include "tst-tlsifunc.c"
|
||
|
Index: glibc-2.25-717-g3020042/elf/tst-tlsifunc.c
|
||
|
===================================================================
|
||
|
--- /dev/null
|
||
|
+++ glibc-2.25-717-g3020042/elf/tst-tlsifunc.c
|
||
|
@@ -0,0 +1,66 @@
|
||
|
+/* Test if an executable can read from the TLS from an STT_GNU_IFUNC resolver.
|
||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
|
+ This file is part of the GNU C Library.
|
||
|
+
|
||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||
|
+ modify it under the terms of the GNU Lesser General Public
|
||
|
+ License as published by the Free Software Foundation; either
|
||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||
|
+
|
||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public
|
||
|
+ License along with the GNU C Library; if not, see
|
||
|
+ <http://www.gnu.org/licenses/>. */
|
||
|
+
|
||
|
+#include <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <libc-symbols.h>
|
||
|
+#include "tls-macros.h"
|
||
|
+
|
||
|
+__thread int bar;
|
||
|
+static int * bar_ptr = NULL;
|
||
|
+
|
||
|
+int foo (void);
|
||
|
+
|
||
|
+void
|
||
|
+init_foo (void)
|
||
|
+{
|
||
|
+ bar_ptr = TLS_GD (bar);
|
||
|
+}
|
||
|
+
|
||
|
+int
|
||
|
+my_foo (void)
|
||
|
+{
|
||
|
+ printf ("&bar = %p and bar_ptr = %p.\n", &bar, bar_ptr);
|
||
|
+ return bar_ptr != NULL;
|
||
|
+}
|
||
|
+
|
||
|
+__ifunc (foo, foo, my_foo, void, init_foo);
|
||
|
+
|
||
|
+static int
|
||
|
+do_test (void)
|
||
|
+{
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ if (foo ())
|
||
|
+ printf ("PASS: IFUNC resolver called once.\n");
|
||
|
+ else {
|
||
|
+ printf ("FAIL: IFUNC resolver not called once.\n");
|
||
|
+ ret = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (&bar == bar_ptr)
|
||
|
+ printf ("PASS: Address read from IFUNC resolver is correct.\n");
|
||
|
+ else {
|
||
|
+ printf ("FAIL: Address read from IFUNC resolver is incorrect.\n");
|
||
|
+ ret = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+#include <support/test-driver.c>
|
||
|
Index: glibc-2.25-717-g3020042/sysdeps/powerpc/powerpc64le/Makefile
|
||
|
===================================================================
|
||
|
--- glibc-2.25-717-g3020042.orig/sysdeps/powerpc/powerpc64le/Makefile
|
||
|
+++ glibc-2.25-717-g3020042/sysdeps/powerpc/powerpc64le/Makefile
|
||
|
@@ -1,6 +1,11 @@
|
||
|
# When building float128 we need to ensure -mfloat128 is
|
||
|
# passed to all such object files.
|
||
|
|
||
|
+# libgcc requires __tcb_parse_hwcap_and_convert_at_platform when built with
|
||
|
+# a binary128 type. That symbol is provided by the loader on dynamically
|
||
|
+# linked executables, forcing to link the loader after libgcc link.
|
||
|
+f128-loader-link = $(as-needed) $(elf-objpfx)ld.so $(no-as-needed)
|
||
|
+
|
||
|
ifeq ($(subdir),math)
|
||
|
# sqrtf128 requires emulation before POWER9.
|
||
|
CPPFLAGS += -I../soft-fp
|
||
|
@@ -11,6 +16,8 @@ $(foreach suf,$(all-object-suffixes),%f1
|
||
|
$(foreach suf,$(all-object-suffixes),$(objpfx)test-float128%$(suf)): CFLAGS += -mfloat128
|
||
|
$(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128
|
||
|
CFLAGS-libm-test-support-float128.c += -mfloat128
|
||
|
+$(objpfx)test-float128% $(objpfx)test-ifloat128%: \
|
||
|
+ gnulib-tests += $(f128-loader-link)
|
||
|
endif
|
||
|
|
||
|
# Append flags to string <-> _Float128 routines.
|
||
|
@@ -28,6 +35,9 @@ CFLAGS-tst-strtod6.c += -mfloat128
|
||
|
CFLAGS-tst-strfrom.c += -mfloat128
|
||
|
CFLAGS-tst-strfrom-locale.c += -mfloat128
|
||
|
CFLAGS-strfrom-skeleton.c += -mfloat128
|
||
|
+$(foreach test,bug-strtod bug-strtod2 bug-strtod2 tst-strtod-round \
|
||
|
+tst-wcstod-round tst-strtod6 tst-strrom tst-strfrom-locale \
|
||
|
+strfrom-skeleton,$(objpfx)$(test)): gnulib-tests += $(f128-loader-link)
|
||
|
|
||
|
# When building glibc with support for _Float128, the powers of ten tables in
|
||
|
# fpioconst.c and in the string conversion functions must be extended. Some
|