diff options
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | csu/libc-start.c | 11 | ||||
-rw-r--r-- | elf/rtld.c | 4 | ||||
-rw-r--r-- | sysdeps/generic/libc-start.h | 30 | ||||
-rw-r--r-- | sysdeps/powerpc/Makefile | 10 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64le/Makefile | 10 | ||||
-rw-r--r-- | sysdeps/powerpc/tst-tlsifunc-static.c | 19 | ||||
-rw-r--r-- | sysdeps/powerpc/tst-tlsifunc.c | 129 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/libc-start.h | 29 |
9 files changed, 265 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog index 1195de4701..baf85432cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2017-07-17 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> + + [BZ #21707] + * csu/libc-start.c (LIBC_START_MAIN): Perform IREL{,A} + relocations before or after initializing the TCB on statically + linked executables. That's a per-architecture definition. + * elf/rtld.c (dl_main): Add a comment about thread-local + variables initialization. + * sysdeps/generic/libc-start.h: New file. Define + ARCH_APPLY_IREL and ARCH_SETUP_IREL. + * sysdeps/powerpc/Makefile: + [$(subdir) = elf && $(multi-arch) != no] (tests-static-internal): Add + tst-tlsifunc-static. + [$(subdir) = elf && $(multi-arch) != no && $(build-shared) == yes] + (tests-internal): Add tst-tlsifunc. + * sysdeps/powerpc/tst-tlsifunc.c: New file. + * sysdeps/powerpc/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 || $(subdir) = stdlib] (bug-strtod bug-strtod2) + (bug-strtod2 tst-strtod-round tst-wcstod-round tst-strtod6 tst-strrom) + (tst-strfrom-locale strfrom-skeleton): Likewise. + * sysdeps/unix/sysv/linux/powerpc/libc-start.h: New file. Define + ARCH_APPLY_IREL and ARCH_SETUP_IREL. + 2017-07-17 DJ Delorie <dj@redhat.com> * nss/nss_test.h: New. diff --git a/csu/libc-start.c b/csu/libc-start.c index c2dd1593eb..6720617188 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -108,6 +108,8 @@ apply_irel (void) # define ARCH_INIT_CPU_FEATURES() #endif +#include <libc-start.h> + STATIC int LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), int argc, @@ -189,11 +191,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), ARCH_INIT_CPU_FEATURES (); /* Perform IREL{,A} relocations. */ - apply_irel (); + ARCH_SETUP_IREL (); /* The stack guard goes into the TCB, so initialize it early. */ __libc_setup_tls (); + /* In some architectures, IREL{,A} relocations happen after TLS setup in + order to let IFUNC resolvers benefit from TCB information, e.g. powerpc's + hwcap and platform fields available in the TCB. */ + ARCH_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 +231,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __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)) diff --git a/elf/rtld.c b/elf/rtld.c index 65647fb1c8..1772f89ea8 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -2208,7 +2208,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", /* Now that we have completed relocation, the initializer data for the TLS blocks has its final values and we can copy them - into the main thread's TLS area, which we allocated above. */ + into the main thread's TLS area, which we allocated above. + Note: thread-local variables must only be accessed after completing + the next step. */ _dl_allocate_tls_init (tcbp); /* And finally install it for the main thread. */ diff --git a/sysdeps/generic/libc-start.h b/sysdeps/generic/libc-start.h new file mode 100644 index 0000000000..1bbd9628f0 --- /dev/null +++ b/sysdeps/generic/libc-start.h @@ -0,0 +1,30 @@ +/* Generic definitions for libc main startup. + 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/>. */ + +#ifndef _LIBC_START_H +#define _LIBC_START_H + +#ifndef SHARED +/* By default we perform STT_GNU_IFUNC resolution *before* TLS + initialization, and this means you cannot, without machine + knowledge, access TLS from an IFUNC resolver. */ +#define ARCH_SETUP_IREL() apply_irel () +#define ARCH_APPLY_IREL() +#endif /* ! SHARED */ + +#endif /* _LIBC_START_H */ diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile index e03a202c65..0d9206bec4 100644 --- a/sysdeps/powerpc/Makefile +++ b/sysdeps/powerpc/Makefile @@ -11,7 +11,15 @@ sysdep-rtld-routines += dl-machine hwcapinfo # Don't optimize GD tls sequence to LE. LDFLAGS-tst-tlsopt-powerpc += -Wl,--no-tls-optimize tests += tst-tlsopt-powerpc -endif + +ifneq (no,$(multi-arch)) +tests-static += tst-tlsifunc-static +tests-internal += tst-tlsifunc-static +ifeq (yes,$(build-shared)) +tests-internal += tst-tlsifunc +endif # build-shared +endif # multi-arch +endif # subdir = elf ifeq ($(subdir),setjmp) ifeq (yes,$(build-shared)) diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile index 2c34f38a83..77617b670a 100644 --- a/sysdeps/powerpc/powerpc64le/Makefile +++ b/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),%f128_r$(suf)): CFLAGS += -mfloat128 $(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 diff --git a/sysdeps/powerpc/tst-tlsifunc-static.c b/sysdeps/powerpc/tst-tlsifunc-static.c new file mode 100644 index 0000000000..e5313af579 --- /dev/null +++ b/sysdeps/powerpc/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" diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c new file mode 100644 index 0000000000..0a8bdbf0c4 --- /dev/null +++ b/sysdeps/powerpc/tst-tlsifunc.c @@ -0,0 +1,129 @@ +/* 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 <stdint.h> +#include <inttypes.h> +#include <libc-symbols.h> +#include <tls-macros.h> + +__thread int bar; +static int *bar_ptr = NULL; + +static uint32_t resolver_platform = 0; + +int foo (void); + +int tcb_test (void); + +/* Offsets copied from tcb-offsets.h. */ +#ifdef __powerpc64__ +# define __TPREG "r13" +# define __ATPLATOFF -28764 +#else +# define __TPREG "r2" +# define __ATPLATOFF -28724 +#endif + +uint32_t +get_platform (void) +{ + register unsigned long tp __asm__ (__TPREG); + uint32_t tmp; + + __asm__ ("lwz %0,%1(%2)\n" + : "=r" (tmp) + : "i" (__ATPLATOFF), "b" (tp)); + + return tmp; +} + +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); + +void +init_tcb_test (void) +{ + resolver_platform = get_platform (); +} + +int +my_tcb_test (void) +{ + printf ("resolver_platform = 0x%"PRIx32 + " and current platform = 0x%"PRIx32".\n", + resolver_platform, get_platform ()); + return resolver_platform != 0; +} + +__ifunc (tcb_test, tcb_test, my_tcb_test, void, init_tcb_test); + +static int +do_test (void) +{ + int ret = 0; + + if (foo ()) + printf ("PASS: foo IFUNC resolver called once.\n"); + else + { + printf ("FAIL: foo IFUNC resolver not called once.\n"); + ret = 1; + } + + if (&bar == bar_ptr) + printf ("PASS: bar address read from IFUNC resolver is correct.\n"); + else + { + printf ("FAIL: bar address read from IFUNC resolver is incorrect.\n"); + ret = 1; + } + + if (tcb_test ()) + printf ("PASS: tcb_test IFUNC resolver called once.\n"); + else + { + printf ("FAIL: tcb_test IFUNC resolver not called once.\n"); + ret = 1; + } + + if (resolver_platform == get_platform ()) + printf ("PASS: platform read from IFUNC resolver is correct.\n"); + else + { + printf ("FAIL: platform read from IFUNC resolver is incorrect.\n"); + ret = 1; + } + + return ret; +} + +#include <support/test-driver.c> diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.h b/sysdeps/unix/sysv/linux/powerpc/libc-start.h new file mode 100644 index 0000000000..c0635be9bc --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.h @@ -0,0 +1,29 @@ +/* PowerPC definitions for libc main startup. + 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/>. */ + +#ifndef _LIBC_START_H +#define _LIBC_START_H + +#ifndef SHARED +/* IREL{,A} must happen after TCB initialization in order to allow IFUNC + resolvers to read TCB fields, e.g. hwcap and at_platform. */ +#define ARCH_SETUP_IREL() +#define ARCH_APPLY_IREL() apply_irel () +#endif /* ! SHARED */ + +#endif /* _LIBC_START_H */ |