This patch serie allow TLS tests to really run some TLS testing instead of just doing "return 0;".
Some defines were missing since the split between libc and tests repositories.
It also adds some missing tls macros for or1k and ppc64.
Some dead code is removed from 3 tests, it was accessing private/internal data structures from libc which is no longer possible since repository split.
TLS tests have been run only on OpenRISC using qemu. This has been compiled for x86_64, or1k, powerpc, ppc64, mips32r6, sparc, armv7a.
Yann Sionneau (4): or1k: add missing tls macros powerpc64: add missing tls macros powerpc: update tls macros inline asm clobbers tls: make tls tests great again
test/tls/Makefile.in | 6 +++ test/tls/tls-macros-or1k.h | 75 ++++++++++++++++++++++++++ test/tls/tls-macros-powerpc.h | 2 +- test/tls/tls-macros-powerpc64.h | 43 +++++++++++++++ test/tls/tls-macros.h | 10 +++- test/tls/tst-tls6.c | 25 --------- test/tls/tst-tls7.c | 25 --------- test/tls/tst-tls8.c | 95 --------------------------------- 8 files changed, 134 insertions(+), 147 deletions(-) create mode 100644 test/tls/tls-macros-or1k.h create mode 100644 test/tls/tls-macros-powerpc64.h
Signed-off-by: Yann Sionneau yann@sionneau.net --- test/tls/tls-macros-or1k.h | 75 ++++++++++++++++++++++++++++++++++++++ test/tls/tls-macros.h | 4 ++ 2 files changed, 79 insertions(+) create mode 100644 test/tls/tls-macros-or1k.h
diff --git a/test/tls/tls-macros-or1k.h b/test/tls/tls-macros-or1k.h new file mode 100644 index 0000000..dcf78d6 --- /dev/null +++ b/test/tls/tls-macros-or1k.h @@ -0,0 +1,75 @@ +/* Macros to support TLS testing, OpenRISC version. + Copyright (C) 2019 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/. */ + +#define TLS_LOAD_GOT \ + ({ register long lr __asm__ ("r9"); \ + long got; \ + asm ("l.jal 0x8\n\t" \ + " l.movhi %0, gotpchi(_GLOBAL_OFFSET_TABLE_-4)\n\t" \ + "l.ori %0, %0, gotpclo(_GLOBAL_OFFSET_TABLE_+0)\n\t" \ + "l.add %0, %0, %1" \ + : "=r" (got), "=r" (lr)); \ + got; }) + +/* General Dynamic: + l.movhi r17, tlsgdhi(symbol) + l.ori r17, r17, tlsgdlo(symbol) + l.add r17, r17, r16 + l.or r3, r17, r17 + l.jal plt(__tls_get_addr) + l.nop */ + +#define TLS_GD(x) \ + ({ void *__tlsgd; \ + extern void *__tls_get_addr (void *); \ + asm ("l.movhi %0, tlsgdhi(" #x ")\n\t" \ + "l.ori %0, %0, tlsgdlo(" #x ")\n\t" \ + : "=r" (__tlsgd)); \ + (int *) __tls_get_addr (TLS_LOAD_GOT + __tlsgd); }) + +#define TLS_LD(x) TLS_GD(x) + +/* Initial Exec: + l.movhi r17, gottpoffhi(symbol) + l.add r17, r17, r16 + l.lwz r17, gottpofflo(symbol)(r17) + l.add r17, r17, r10 + l.lbs r17, 0(r17) */ + +#define TLS_IE(x) \ + ({ register long __tls __asm__ ("r10"); \ + void *__tlsie; \ + asm ("l.movhi %0, gottpoffhi(" #x ")\n\t" \ + "l.add %0, %0, %1\n\t" \ + "l.lwz %0, gottpofflo(" #x ")(%0)\n\t" \ + "l.add %0, %0, %2\n\t" \ + : "=&r" (__tlsie) : "r" (TLS_LOAD_GOT), \ + "r" (__tls) : "memory"); \ + __tlsie; }) + +/* Local Exec: + l.movhi r17, tpoffha(symbol) + l.add r17, r17, r10 + l.addi r17, r17, tpofflo(symbol) + l.lbs r17, 0(r17) */ + +#define TLS_LE(x) \ + ({ register long __tls __asm__ ("r10"); \ + void *__tlsle; \ + asm ("l.movhi %0, tpoffha(" #x ")\n\t" \ + "l.add %0, %0, %1\n\t" \ + "l.addi %0, %0, tpofflo(" #x ")\n\t" \ + : "=&r" (__tlsle) : "r" (__tls) : "memory"); \ + __tlsle; }) diff --git a/test/tls/tls-macros.h b/test/tls/tls-macros.h index 9053d8d..71e8ef4 100644 --- a/test/tls/tls-macros.h +++ b/test/tls/tls-macros.h @@ -76,6 +76,10 @@ #include <tls-macros-xtensa.h> #endif
+#ifdef __or1k__ +#include <tls-macros-or1k.h> +#endif + #if !defined TLS_LE || !defined TLS_IE \ || !defined TLS_LD || !defined TLS_GD # error "No support for this architecture so far."
Signed-off-by: Yann Sionneau yann@sionneau.net --- test/tls/tls-macros-powerpc64.h | 43 +++++++++++++++++++++++++++++++++ test/tls/tls-macros.h | 6 ++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/tls/tls-macros-powerpc64.h
diff --git a/test/tls/tls-macros-powerpc64.h b/test/tls/tls-macros-powerpc64.h new file mode 100644 index 0000000..6021664 --- /dev/null +++ b/test/tls/tls-macros-powerpc64.h @@ -0,0 +1,43 @@ +#define __TLS_CALL_CLOBBERS \ + "0", "4", "5", "6", "7", "8", "9", "10", "11", "12", \ + "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7" + +/* PowerPC64 Local Exec TLS access. */ +#define TLS_LE(x) \ + ({ int * __result; \ + asm ("addis %0,13," #x "@tprel@ha\n\t" \ + "addi %0,%0," #x "@tprel@l" \ + : "=b" (__result) ); \ + __result; \ + }) +/* PowerPC64 Initial Exec TLS access. */ +#define TLS_IE(x) \ + ({ int * __result; \ + asm ("ld %0," #x "@got@tprel(2)\n\t" \ + "add %0,%0," #x "@tls" \ + : "=r" (__result) ); \ + __result; \ + }) + +/* PowerPC64 Local Dynamic TLS access. */ +#define TLS_LD(x) \ + ({ int * __result; \ + asm ("addi 3,2," #x "@got@tlsld\n\t" \ + "bl __tls_get_addr\n\t" \ + "nop \n\t" \ + "addis %0,3," #x "@dtprel@ha\n\t" \ + "addi %0,%0," #x "@dtprel@l" \ + : "=b" (__result) : \ + : "3", __TLS_CALL_CLOBBERS); \ + __result; \ + }) +/* PowerPC64 General Dynamic TLS access. */ +#define TLS_GD(x) \ + ({ register int *__result __asm__ ("r3"); \ + asm ("addi 3,2," #x "@got@tlsgd\n\t" \ + "bl __tls_get_addr\n\t" \ + "nop " \ + : "=r" (__result) : \ + : __TLS_CALL_CLOBBERS); \ + __result; \ + }) diff --git a/test/tls/tls-macros.h b/test/tls/tls-macros.h index 71e8ef4..47e0b22 100644 --- a/test/tls/tls-macros.h +++ b/test/tls/tls-macros.h @@ -56,10 +56,14 @@ #include <tls-macros-mips.h> #endif
-#ifdef __powerpc__ +#if defined(__powerpc__) && !defined(__powerpc64__) #include <tls-macros-powerpc.h> #endif
+#if defined(__powerpc__) && defined(__powerpc64__) +#include <tls-macros-powerpc64.h> +#endif + #ifdef __sh__ #include <tls-macros-sh.h> #endif
This was causing a compile error for powerpc64 toolchain because r3 was both listed as clobbered and as output in inline asm.
Signed-off-by: Yann Sionneau yann@sionneau.net --- test/tls/tls-macros-powerpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/tls/tls-macros-powerpc.h b/test/tls/tls-macros-powerpc.h index ef293bb..8a368fa 100644 --- a/test/tls/tls-macros-powerpc.h +++ b/test/tls/tls-macros-powerpc.h @@ -1,5 +1,5 @@ #define __TLS_CALL_CLOBBERS \ - "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", \ + "0", "4", "5", "6", "7", "8", "9", "10", "11", "12", \ "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7"
/* PowerPC32 Local Exec TLS access. */
* TLS tests were "empty" because nothing was setting the following variables:
* USE_TLS * HAVE___THREAD * HAVE_TLS_MODEL_ATTRIBUTE
All toolchains supported by uClibc-ng today do support both NPTL threads and TLS. All ports also define HAVE_TLS_MODEL_ATTRIBUTE except alpha.
* 3 tests (tst-tls6 / tst-tls7 / tst-tls8) were peeking into internal/private data structures from libc, which is not possible anymore since libc and tests are now split into 2 git repositories.
This commit fixes those 2 issues so that TLS tests can be run again.
Signed-off-by: Yann Sionneau yann@sionneau.net --- test/tls/Makefile.in | 6 +++ test/tls/tst-tls6.c | 25 ------------ test/tls/tst-tls7.c | 25 ------------ test/tls/tst-tls8.c | 95 -------------------------------------------- 4 files changed, 6 insertions(+), 145 deletions(-)
diff --git a/test/tls/Makefile.in b/test/tls/Makefile.in index 6a6a50e..348fc1c 100644 --- a/test/tls/Makefile.in +++ b/test/tls/Makefile.in @@ -1,6 +1,12 @@ # uClibc-ng TLS tests # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+CFLAGS += -DUSE_TLS=1 -DHAVE___THREAD=1 -I. + +ifneq ($(ARCH),alpha) +CFLAGS += -DHAVE_TLS_MODEL_ATTRIBUTE=1 +endif + TESTS := tst-tls1 tst-tls2 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 \ tst-tls8 tst-tls9 tst-tls10 tst-tls11 tst-tls12 tst-tls13 \ tst-tls14 tst-tls15 tst-tls16 tst-tls17 tst-tls18 tst-tls-at-ctor \ diff --git a/test/tls/tst-tls6.c b/test/tls/tst-tls6.c index 7cc8f6b..b9a5609 100644 --- a/test/tls/tst-tls6.c +++ b/test/tls/tst-tls6.c @@ -26,31 +26,6 @@ do_test (void) exit (1); }
- /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ -#ifdef __UCLIBC__ - if (modid == -1) - modid = ((struct dyn_elf *) h)->dyn->l_tls_modid; - else if (((struct dyn_elf *)h)->dyn->l_tls_modid != (size_t) modid) - { - printf ("round %d: modid now %zu, initially %d\n", - i, - ((struct dyn_elf *)h)->dyn->l_tls_modid, - modid); - result = 1; - } -#else - if (modid == -1) - modid = ((struct link_map *) h)->l_tls_modid; - else if (((struct link_map *) h)->l_tls_modid != modid) - { - printf ("round %d: modid now %zd, initially %d\n", - i, ((struct link_map *) h)->l_tls_modid, modid); - result = 1; - } -#endif - foop = dlsym (h, "foo"); if (foop == NULL) { diff --git a/test/tls/tst-tls7.c b/test/tls/tst-tls7.c index b8bb71d..b0a6d37 100644 --- a/test/tls/tst-tls7.c +++ b/test/tls/tst-tls7.c @@ -24,31 +24,6 @@ do_test (void) exit (1); }
- /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ -#ifdef __UCLIBC__ - if (modid == -1) - modid = ((struct dyn_elf *) h)->dyn->l_tls_modid; - else if (((struct dyn_elf *)h)->dyn->l_tls_modid != (size_t) modid) - { - printf ("round %d: modid now %zu, initially %d\n", - i, - ((struct dyn_elf *)h)->dyn->l_tls_modid, - modid); - result = 1; - } -#else - if (modid == -1) - modid = ((struct link_map *) h)->l_tls_modid; - else if (((struct link_map *) h)->l_tls_modid != (size_t) modid) - { - printf ("round %d: modid now %zu, initially %d\n", - i, ((struct link_map *) h)->l_tls_modid, modid); - result = 1; - } -#endif - fp = dlsym (h, "in_dso2"); if (fp == NULL) { diff --git a/test/tls/tst-tls8.c b/test/tls/tst-tls8.c index 4635304..a723cab 100644 --- a/test/tls/tst-tls8.c +++ b/test/tls/tst-tls8.c @@ -29,31 +29,6 @@ do_test (void) exit (1); }
- /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ -#ifdef __UCLIBC__ - if (modid1 == (size_t) -1) - modid1 = ((struct dyn_elf *) h1)->dyn->l_tls_modid; - else if (((struct dyn_elf *)h1)->dyn->l_tls_modid != (size_t) modid1) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, - ((struct dyn_elf *)h1)->dyn->l_tls_modid, - modid1); - result = 1; - } -#else - if (modid1 == (size_t) -1) - modid1 = ((struct link_map *) h1)->l_tls_modid; - else if (((struct link_map *) h1)->l_tls_modid != modid1) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h1)->l_tls_modid, modid1); - result = 1; - } -#endif - fp1 = dlsym (h1, "in_dso2"); if (fp1 == NULL) { @@ -72,32 +47,6 @@ do_test (void) exit (1); }
- /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ -#ifdef __UCLIBC__ - if (modid2 == (size_t) -1) - modid2 = ((struct dyn_elf *)h2)->dyn->l_tls_modid; - else if (((struct dyn_elf *)h2)->dyn->l_tls_modid - != (size_t) modid2) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, - ((struct dyn_elf *)h2)->dyn->l_tls_modid, - modid2); - result = 1; - } -#else - if (modid2 == (size_t) -1) - modid2 = ((struct link_map *) h2)->l_tls_modid; - else if (((struct link_map *) h2)->l_tls_modid != modid2) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h2)->l_tls_modid, modid2); - result = 1; - } -#endif - bazp = dlsym (h2, "baz"); if (bazp == NULL) { @@ -127,28 +76,6 @@ do_test (void) exit (1); }
- /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ -#ifdef __UCLIBC__ - if (((struct dyn_elf *)h1)->dyn->l_tls_modid - != modid1) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, - ((struct dyn_elf *)h1)->dyn->l_tls_modid, - modid1); - result = 1; - } -#else - if (((struct link_map *) h1)->l_tls_modid != modid1) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h1)->l_tls_modid, modid1); - result = 1; - } -#endif - fp1 = dlsym (h1, "in_dso2"); if (fp1 == NULL) { @@ -167,28 +94,6 @@ do_test (void) exit (1); }
- /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ -#ifdef __UCLIBC__ - if (((struct dyn_elf *)h2)->dyn->l_tls_modid - != modid2) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, - ((struct dyn_elf *)h2)->dyn->l_tls_modid, - modid2); - result = 1; - } -#else - if (((struct link_map *) h2)->l_tls_modid != modid2) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h2)->l_tls_modid, modid2); - result = 1; - } -#endif - bazp = dlsym (h2, "baz"); if (bazp == NULL) {