From d1da011118ad8e35002034128458355a2de570ef Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 9 Jan 2025 19:30:44 +0100 Subject: [PATCH] elf: Always define TLS_TP_OFFSET This will be needed to compute __rseq_offset outside of the TLS relocation machinery. Reviewed-by: Michael Jeanson --- elf/Makefile | 1 + elf/tst-tls_tp_offset.c | 57 +++++++++++++++++++++++++++++++++++++ sysdeps/generic/dl-tls.h | 3 ++ sysdeps/i386/dl-tls.h | 3 ++ sysdeps/s390/dl-tls.h | 3 ++ sysdeps/x86_64/x32/dl-tls.h | 3 ++ 6 files changed, 70 insertions(+) create mode 100644 elf/tst-tls_tp_offset.c diff --git a/elf/Makefile b/elf/Makefile index 048878d602..4b1d0d8741 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -322,6 +322,7 @@ tests := \ tests-internal := \ $(tests-static-internal) \ tst-tls1 \ + tst-tls_tp_offset \ # tests-internal tests-static := $(tests-static-normal) $(tests-static-internal) diff --git a/elf/tst-tls_tp_offset.c b/elf/tst-tls_tp_offset.c new file mode 100644 index 0000000000..e7c50663aa --- /dev/null +++ b/elf/tst-tls_tp_offset.c @@ -0,0 +1,57 @@ +/* Check compile-time definition of TLS_TP_OFFSET against run-time value. + Copyright (C) 2025 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 + . */ + +#include + +#include +#include +#include +#include +#include +#include + +static __thread char thread_var __attribute__ ((tls_model ("initial-exec"))); + +static int +do_test (void) +{ + printf ("thread variable address: %p\n", &thread_var); + printf ("thread pointer address: %p\n", __thread_pointer ()); + printf ("pthread_self address: %p\n", (void *) pthread_self ()); + ptrdiff_t block_offset = ((struct link_map *) _r_debug.r_map)->l_tls_offset; + printf ("main program TLS block offset: %td\n", block_offset); + + if ((uintptr_t) &thread_var < (uintptr_t) pthread_self ()) + { + puts("TLS variables are located before struct pthread."); + TEST_COMPARE (((intptr_t) __thread_pointer () - block_offset) + - (intptr_t) &thread_var, + TLS_TP_OFFSET); + } + else + { + puts("TLS variables are located after struct pthread."); + TEST_COMPARE (((intptr_t) __thread_pointer () + block_offset) + - (intptr_t) &thread_var, + TLS_TP_OFFSET); + } + return 0; +} + +#include diff --git a/sysdeps/generic/dl-tls.h b/sysdeps/generic/dl-tls.h index 8aff4b6ca6..e9480f17a2 100644 --- a/sysdeps/generic/dl-tls.h +++ b/sysdeps/generic/dl-tls.h @@ -33,4 +33,7 @@ extern void *__tls_get_addr (tls_index *ti); TLS block. */ #define TLS_DTV_OFFSET 0 +/* Static TLS offsets are relative to the unadjusted thread pointer. */ +#define TLS_TP_OFFSET 0 + #endif /* _DL_TLS_H */ diff --git a/sysdeps/i386/dl-tls.h b/sysdeps/i386/dl-tls.h index eed183293c..2dac81bbd2 100644 --- a/sysdeps/i386/dl-tls.h +++ b/sysdeps/i386/dl-tls.h @@ -28,6 +28,9 @@ typedef struct dl_tls_index TLS block. */ #define TLS_DTV_OFFSET 0 +/* Static TLS offsets are relative to the unadjusted thread pointer. */ +#define TLS_TP_OFFSET 0 + #ifdef SHARED /* This is the prototype for the GNU version. */ extern void *___tls_get_addr (tls_index *ti) diff --git a/sysdeps/s390/dl-tls.h b/sysdeps/s390/dl-tls.h index 74756ddf05..53fd362475 100644 --- a/sysdeps/s390/dl-tls.h +++ b/sysdeps/s390/dl-tls.h @@ -28,6 +28,9 @@ typedef struct TP-relative addresses. */ #define TLS_DTV_OFFSET (-(unsigned long int) __builtin_thread_pointer ()) +/* Static TLS offsets are relative to the unadjusted thread pointer. */ +#define TLS_TP_OFFSET 0 + #ifdef SHARED extern unsigned long __tls_get_offset (unsigned long got_offset); diff --git a/sysdeps/x86_64/x32/dl-tls.h b/sysdeps/x86_64/x32/dl-tls.h index 4b736a4f30..04ac0fe0d0 100644 --- a/sysdeps/x86_64/x32/dl-tls.h +++ b/sysdeps/x86_64/x32/dl-tls.h @@ -35,4 +35,7 @@ extern void *__tls_get_addr (tls_index *ti); TLS block. */ #define TLS_DTV_OFFSET 0 +/* Static TLS offsets are relative to the unadjusted thread pointer. */ +#define TLS_TP_OFFSET 0 + #endif /* _X86_64_DL_TLS_H */