diff options
Diffstat (limited to 'sysdeps')
-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 |
6 files changed, 226 insertions, 1 deletions
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 */ |