From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1062) id 7D951385B238; Mon, 11 Apr 2022 01:30:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7D951385B238 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alan Modra To: glibc-cvs@sourceware.org Subject: [glibc] powerpc64: Set up thread register for _dl_relocate_static_pie X-Act-Checkin: glibc X-Git-Author: Alan Modra X-Git-Refname: refs/heads/master X-Git-Oldrev: d6efcc118e406a1cfeb309f835d7118df53419bb X-Git-Newrev: 31a9bc8c55adc2a8d6f8f795a577ba5d5eca7506 Message-Id: <20220411013035.7D951385B238@sourceware.org> Date: Mon, 11 Apr 2022 01:30:35 +0000 (GMT) X-BeenThere: glibc-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Glibc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Apr 2022 01:30:35 -0000 https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=31a9bc8c55adc2a8d6f8f795a577ba5d5eca7506 commit 31a9bc8c55adc2a8d6f8f795a577ba5d5eca7506 Author: Alan Modra Date: Mon Jan 24 07:58:18 2022 +1030 powerpc64: Set up thread register for _dl_relocate_static_pie libgcc ifunc resolvers that access hwcap via a field in the tcb can't be called until the thread pointer is set up. Other ifunc resolvers might need access to at_platform. This patch sets up a fake thread pointer early to a copy of tcbhead_t. hwcapinfo.c already had local variables for hwcap and at_platform, replace them with an entire tcbhead_t. It's not that large and this way we easily ensure hwcap and at_platform are at the same relative offsets as they are in the real thread block. The patch also conditionally disables part of tst-tlsifunc-static, "bar address read from IFUNC resolver is incorrect". We can't get a proper address for a thread variable before glibc initialises tls. Reviewed-by: Tulio Magno Quites Machado Filho Diff: --- sysdeps/powerpc/hwcapinfo.c | 8 +++----- sysdeps/powerpc/hwcapinfo.h | 3 +-- sysdeps/powerpc/nptl/tls.h | 8 ++++---- sysdeps/powerpc/powerpc64/dl-machine.h | 21 +++++++++++++++++++++ sysdeps/powerpc/tst-tlsifunc-static.c | 1 + sysdeps/powerpc/tst-tlsifunc.c | 3 +++ 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/sysdeps/powerpc/hwcapinfo.c b/sysdeps/powerpc/hwcapinfo.c index e030e322bd..afde05f863 100644 --- a/sysdeps/powerpc/hwcapinfo.c +++ b/sysdeps/powerpc/hwcapinfo.c @@ -20,8 +20,7 @@ #include #include -uint64_t __tcb_hwcap __attribute__ ((visibility ("hidden"))); -uint32_t __tcb_platform __attribute__ ((visibility ("hidden"))); +tcbhead_t __tcb __attribute__ ((visibility ("hidden"))); /* This function parses the HWCAP/HWCAP2 fields, adding the previous supported ISA bits, as well as converting the AT_PLATFORM string to a number. This @@ -34,7 +33,7 @@ __tcb_parse_hwcap_and_convert_at_platform (void) uint64_t h1, h2; /* Read AT_PLATFORM string from auxv and convert it to a number. */ - __tcb_platform = _dl_string_platform (GLRO (dl_platform)); + __tcb.at_platform = _dl_string_platform (GLRO (dl_platform)); /* Read HWCAP and HWCAP2 from auxv. */ h1 = GLRO (dl_hwcap); @@ -66,8 +65,7 @@ __tcb_parse_hwcap_and_convert_at_platform (void) /* Consolidate both HWCAP and HWCAP2 into a single doubleword so that we can read both in a single load later. */ - __tcb_hwcap = h2; - __tcb_hwcap = (h1 << 32) | __tcb_hwcap; + __tcb.hwcap = (h1 << 32) | (h2 & 0xffffffff); } #if IS_IN (rtld) diff --git a/sysdeps/powerpc/hwcapinfo.h b/sysdeps/powerpc/hwcapinfo.h index ac462835ce..1f5e0bcb51 100644 --- a/sysdeps/powerpc/hwcapinfo.h +++ b/sysdeps/powerpc/hwcapinfo.h @@ -21,8 +21,7 @@ #ifndef HWCAPINFO_H # define HWCAPINFO_H -extern uint64_t __tcb_hwcap attribute_hidden; -extern uint32_t __tcb_platform attribute_hidden; +extern tcbhead_t __tcb attribute_hidden; extern void __tcb_parse_hwcap_and_convert_at_platform (void); diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h index b80d39ad41..22b0075235 100644 --- a/sysdeps/powerpc/nptl/tls.h +++ b/sysdeps/powerpc/nptl/tls.h @@ -45,8 +45,6 @@ #ifndef __ASSEMBLER__ -# include - /* Get system call information. */ # include @@ -100,6 +98,8 @@ typedef struct dtv_t *dtv; } tcbhead_t; +# include + /* This is the size of the initial TCB. */ # define TLS_INIT_TCB_SIZE 0 @@ -137,8 +137,8 @@ typedef struct # define TLS_INIT_TP(tcbp) \ ({ \ __thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \ - THREAD_SET_HWCAP (__tcb_hwcap); \ - THREAD_SET_AT_PLATFORM (__tcb_platform); \ + THREAD_SET_HWCAP (__tcb.hwcap); \ + THREAD_SET_AT_PLATFORM (__tcb.at_platform); \ NULL; \ }) diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index 6fab5cbe81..bb0ccd0811 100644 --- a/sysdeps/powerpc/powerpc64/dl-machine.h +++ b/sysdeps/powerpc/powerpc64/dl-machine.h @@ -559,6 +559,27 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, #define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit #endif +#if ENABLE_STATIC_PIE && !defined SHARED && !IS_IN (rtld) +#include +#include + +/* Set up r13 for _dl_relocate_static_pie so that libgcc ifuncs that + normally access the tcb copy of hwcap will see __tcb.hwcap. */ + +static inline void __attribute__ ((always_inline)) +ppc_init_fake_thread_pointer (void) +{ + DIAG_PUSH_NEEDS_COMMENT; + /* We are playing pointer tricks. Silence gcc warning. */ + DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Warray-bounds"); + __thread_register = (char *) &__tcb.hwcap - TCB_HWCAP; + DIAG_POP_NEEDS_COMMENT; +} + +#define ELF_MACHINE_BEFORE_RTLD_RELOC(map, dynamic_info) \ + ppc_init_fake_thread_pointer (); +#endif /* ENABLE_STATIC_PIE && !defined SHARED && !IS_IN (rtld) */ + #endif /* dl_machine_h */ #ifdef RESOLVE_MAP diff --git a/sysdeps/powerpc/tst-tlsifunc-static.c b/sysdeps/powerpc/tst-tlsifunc-static.c index c0ff8972a9..438b27c0ec 100644 --- a/sysdeps/powerpc/tst-tlsifunc-static.c +++ b/sysdeps/powerpc/tst-tlsifunc-static.c @@ -16,4 +16,5 @@ License along with the GNU C Library; if not, see . */ +#define TST_TLSIFUNC_STATIC 1 #include "tst-tlsifunc.c" diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c index 92313e68f4..6b256c6229 100644 --- a/sysdeps/powerpc/tst-tlsifunc.c +++ b/sysdeps/powerpc/tst-tlsifunc.c @@ -101,11 +101,14 @@ do_test (void) if (&bar == bar_ptr) printf ("PASS: bar address read from IFUNC resolver is correct.\n"); +#if !defined TST_TLSIFUNC_STATIC || !defined PIC \ + || !defined PI_STATIC_AND_HIDDEN else { printf ("FAIL: bar address read from IFUNC resolver is incorrect.\n"); ret = 1; } +#endif if (tcb_test ()) printf ("PASS: tcb_test IFUNC resolver called once.\n");