diff options
| author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-10-30 04:33:48 +0000 |
|---|---|---|
| committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-10-30 04:33:48 +0000 |
| commit | 4fc0cd60dfa59fbd89f9f6737db69d3794701dfc (patch) | |
| tree | 53b0181c20035ed05aa5a9def6dad0e7a50dcc7f | |
| parent | c82f7be400838c99fdbf7635610f799a1154ccdd (diff) | |
| download | uClibc-alpine-4fc0cd60dfa59fbd89f9f6737db69d3794701dfc.tar.bz2 uClibc-alpine-4fc0cd60dfa59fbd89f9f6737db69d3794701dfc.tar.xz | |
Add TLS test suite for testing TLS relocation functionality in the dynamic loader. Make sure your read the README file before asking any questions, and then read it again.
41 files changed, 2800 insertions, 0 deletions
diff --git a/test/tls/Makefile b/test/tls/Makefile new file mode 100644 index 000000000..06da470c9 --- /dev/null +++ b/test/tls/Makefile @@ -0,0 +1,252 @@ +# Makefile for TLS testsuite in uClibc +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program 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 Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +TOPDIR = ../../ +PTDIR = $(TOPDIR)libpthread/nptl +include ../Rules.mak + +INCLUDES := -I. -I$(TOPDIR)include \ + -I$(PTDIR) \ + -I$(PTDIR)/compat \ + -I$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(PTDIR)/sysdeps/pthread \ + -I$(PTDIR)/sysdeps/pthread/bits \ + -I$(PTDIR)/sysdeps/generic \ + -include $(PTDIR)/compat/libc-symbols.h \ + -I$(TOPDIR)ldso/include + +CFLAGS = -D_LIBC -D_GNU_SOURCE $(INCLUDES) -std=gnu99 \ + -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -Os + +LDFLAGS += + +# +# Targets and defines to build DSO modules +# +SO_CFLAGS = $(CFLAGS) -fPIC -DSHARED -shared + +SO_LDFLAGS = $(LDFLAGS) -shared -static-libgcc -L$(TOPDIR)lib +SO_LDFLAGS-tst-tlsmod3.os = tst-tlsmod2.so +SO_LDFLAGS-tst-tlsmod8.os = tst-tlsmod7.so +SO_LDFLAGS-tst-tlsmod10.os = tst-tlsmod9.so +SO_LDFLAGS-tst-tlsmod12.os = tst-tlsmod11.so +SO_LDFLAGS-tst-tlsmod13a.os = tst-tlsmod13.so + +OS_OBJS = $(patsubst %.c, %.os, $(wildcard tst-tlsmod*.c)) +SO_OBJS = $(patsubst %.c, %.so, $(wildcard tst-tlsmod*.c)) + +# +# Test applications +# +APPS = 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-tls1-static tst-tls2-static tst-tls9-static + +all: $(APPS) + +$(OS_OBJS): %.os : %.c + $(CC) $(SO_CFLAGS) -c $< -o $@ + +$(SO_OBJS): %.so : %.os + $(CC) $(SO_LDFLAGS) $(SO_LDFLAGS-$<) $< -o $@ + +tst-tls1: tst-tls1.c + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls2: tst-tls2.c + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls3: tst-tls3.c tst-tlsmod1.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) $@.o tst-tlsmod1.so -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls4: tst-tls4.c tst-tlsmod2.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls5: tst-tls5.c tst-tlsmod2.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls6: tst-tls6.c tst-tlsmod2.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls7: tst-tls7.c tst-tlsmod2.so tst-tlsmod3.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls8: tst-tls8.c tst-tlsmod3.so tst-tlsmod4.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls9: tst-tls9.c tst-tlsmod5.so tst-tlsmod6.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls10: tst-tls10.c tst-tlsmod7.so tst-tlsmod8.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -Wl,-rpath-link=. tst-tlsmod8.so $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls11: tst-tls11.c tst-tlsmod9.so tst-tlsmod10.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -Wl,-rpath-link=. tst-tlsmod10.so $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls12: tst-tls12.c tst-tlsmod11.so tst-tlsmod12.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -Wl,-rpath-link=. tst-tlsmod12.so $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls13: tst-tls13.c tst-tlsmod13.so tst-tlsmod13a.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl -Wl,-rpath-link=. $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls14: tst-tls14.c tst-tlsmod14a.so tst-tlsmod14b.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl -Wl,-rpath-link=. tst-tlsmod14a.so $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls15: tst-tls15.c tst-tlsmod15a.so tst-tlsmod15b.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) $(LDFLAGS) -ldl -Wl,-rpath-link=. $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls1-static: tst-tls1-static.c + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) -static $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls2-static: tst-tls2-static.c + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) -static $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +tst-tls9-static: tst-tls9-static.c tst-tlsmod5.so tst-tlsmod6.so + -@ echo "-------" + -@ echo " " + -@ echo "Compiling $@ vs uClibc: " + -@ echo " " + $(CC) $(CFLAGS) -c $< -o $@.o + $(CC) -ldl -static $@.o -o $@ + $(STRIPTOOL) -x -R .note -R .comment $@ + -@ echo " " + +clean: + $(RM) *.o *.os *.so *~ core $(APPS) diff --git a/test/tls/README b/test/tls/README new file mode 100644 index 000000000..06c9eb743 --- /dev/null +++ b/test/tls/README @@ -0,0 +1,8 @@ +These tests were imported from 'glibc/elf' and are responsible for testing +the TLS functionality of the dynamic loader. The file 'tls-macros-mips.h' +is a copy of 'glibc/sysdeps/mips/tls-macros.h'. Dependency and link orders +are critical and should NOT be changed. Even if you think you know what +you are doing, do not touch the Makefile without posting to the uClibc +development mailing list. + +-Steve <sjhill@uclibc.org> diff --git a/test/tls/tls-macros-mips.h b/test/tls/tls-macros-mips.h new file mode 100644 index 000000000..2d0516b3e --- /dev/null +++ b/test/tls/tls-macros-mips.h @@ -0,0 +1,88 @@ +/* Macros to support TLS testing in times of missing compiler support. */ + +#if _MIPS_SIM != _ABI64 + +/* These versions are for o32 and n32. */ + +# define TLS_GD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + asm ("addiu %0, $28, %%tlsgd(" #x ")" \ + : "=r" (__result)); \ + (int *)__tls_get_addr (__result); }) +#else +# define TLS_GD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + asm ("daddiu %0, $28, %%tlsgd(" #x ")" \ + : "=r" (__result)); \ + (int *)__tls_get_addr (__result); }) +#endif + +#if _MIPS_SIM != _ABI64 +# define TLS_LD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + asm ("addiu %0, $28, %%tlsldm(" #x ")" \ + : "=r" (__result)); \ + __result = __tls_get_addr (__result); \ + asm ("lui $3,%%dtprel_hi(" #x ")\n\t" \ + "addiu $3,$3,%%dtprel_lo(" #x ")\n\t" \ + "addu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_IE(x) \ + ({ void *__result; \ + asm (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + asm ("lw $3,%%gottprel(" #x ")($28)\n\t" \ + "addu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_LE(x) \ + ({ void *__result; \ + asm (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + asm ("lui $3,%%tprel_hi(" #x ")\n\t" \ + "addiu $3,$3,%%tprel_lo(" #x ")\n\t" \ + "addu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) + +#else + +/* These versions are for n64. */ + +# define TLS_LD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + asm ("daddiu %0, $28, %%tlsldm(" #x ")" \ + : "=r" (__result)); \ + __result = __tls_get_addr (__result); \ + asm ("lui $3,%%dtprel_hi(" #x ")\n\t" \ + "daddiu $3,$3,%%dtprel_lo(" #x ")\n\t" \ + "daddu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_IE(x) \ + ({ void *__result; \ + asm (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + asm ("ld $3,%%gottprel(" #x ")($28)\n\t" \ + "daddu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_LE(x) \ + ({ void *__result; \ + asm (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + asm ("lui $3,%%tprel_hi(" #x ")\n\t" \ + "daddiu $3,$3,%%tprel_lo(" #x ")\n\t" \ + "daddu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +#endif diff --git a/test/tls/tls-macros.h b/test/tls/tls-macros.h new file mode 100644 index 000000000..9552d10d7 --- /dev/null +++ b/test/tls/tls-macros.h @@ -0,0 +1,853 @@ +/* Macros to support TLS testing in times of missing compiler support. */ + +#define COMMON_INT_DEF(x) \ + asm (".tls_common " #x ",4,4") +/* XXX Until we get compiler support we don't need declarations. */ +#define COMMON_INT_DECL(x) + +/* XXX This definition will probably be machine specific, too. */ +#define VAR_INT_DEF(x) \ + asm (".section .tdata\n\t" \ + ".globl " #x "\n" \ + ".balign 4\n" \ + #x ":\t.long 0\n\t" \ + ".size " #x ",4\n\t" \ + ".previous") +/* XXX Until we get compiler support we don't need declarations. */ +#define VAR_INT_DECL(x) + +#ifdef __mips__ +#include <tls-macros-mips.h> +#endif + + /* XXX Each architecture must have its own asm for now. */ +#ifdef __i386__ +# define TLS_LE(x) \ + ({ int *__l; \ + asm ("movl %%gs:0,%0\n\t" \ + "subl $" #x "@tpoff,%0" \ + : "=r" (__l)); \ + __l; }) + +# ifdef PIC +# define TLS_IE(x) \ + ({ int *__l; \ + asm ("movl %%gs:0,%0\n\t" \ + "subl " #x "@gottpoff(%%ebx),%0" \ + : "=r" (__l)); \ + __l; }) +# else +# define TLS_IE(x) \ + ({ int *__l, __b; \ + asm ("call 1f\n\t" \ + ".subsection 1\n" \ + "1:\tmovl (%%esp), %%ebx\n\t" \ + "ret\n\t" \ + ".previous\n\t" \ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ + "movl %%gs:0,%0\n\t" \ + "subl " #x "@gottpoff(%%ebx),%0" \ + : "=r" (__l), "=&b" (__b)); \ + __l; }) +# endif + +# ifdef PIC +# define TLS_LD(x) \ + ({ int *__l, __c, __d; \ + asm ("leal " #x "@tlsldm(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "leal " #x "@dtpoff(%%eax), %%eax" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# else +# define TLS_LD(x) \ + ({ int *__l, __b, __c, __d; \ + asm ("call 1f\n\t" \ + ".subsection 1\n" \ + "1:\tmovl (%%esp), %%ebx\n\t" \ + "ret\n\t" \ + ".previous\n\t" \ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ + "leal " #x "@tlsldm(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "leal " #x "@dtpoff(%%eax), %%eax" \ + : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# endif + +# ifdef PIC +# define TLS_GD(x) \ + ({ int *__l, __c, __d; \ + asm ("leal " #x "@tlsgd(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "nop" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# else +# define TLS_GD(x) \ + ({ int *__l, __b, __c, __d; \ + asm ("call 1f\n\t" \ + ".subsection 1\n" \ + "1:\tmovl (%%esp), %%ebx\n\t" \ + "ret\n\t" \ + ".previous\n\t" \ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ + "leal " #x "@tlsgd(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "nop" \ + : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# endif + +#elif defined __x86_64__ + +# define TLS_LE(x) \ + ({ int *__l; \ + asm ("movq %%fs:0,%0\n\t" \ + "leaq " #x "@tpoff(%0), %0" \ + : "=r" (__l)); \ + __l; }) + +# define TLS_IE(x) \ + ({ int *__l; \ + asm ("movq %%fs:0,%0\n\t" \ + "addq " #x "@gottpoff(%%rip),%0" \ + : "=r" (__l)); \ + __l; }) + +# define TLS_LD(x) \ + ({ int *__l, __c, __d; \ + asm ("leaq " #x "@tlsld(%%rip),%%rdi\n\t" \ + "call __tls_get_addr@plt\n\t" \ + "leaq " #x "@dtpoff(%%rax), %%rax" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d) \ + : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ + __l; }) + +# define TLS_GD(x) \ + ({ int *__l, __c, __d; \ + asm (".byte 0x66\n\t" \ + "leaq " #x "@tlsgd(%%rip),%%rdi\n\t" \ + ".word 0x6666\n\t" \ + "rex64\n\t" \ + "call __tls_get_addr@plt" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d) \ + : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ + __l; }) + +#elif defined __sh__ + +# define TLS_LE(x) \ + ({ int *__l; void *__tp; \ + asm ("stc gbr,%1\n\t" \ + "mov.l 1f,%0\n\t" \ + "bra 2f\n\t" \ + " add %1,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tpoff\n\t" \ + "2:" \ + : "=r" (__l), "=r" (__tp)); \ + __l; }) + +# ifdef PIC +# define TLS_IE(x) \ + ({ int *__l; void *__tp; \ + register void *__gp __asm__("r12"); \ + asm ("mov.l 1f,r0\n\t" \ + "stc gbr,%1\n\t" \ + "mov.l @(r0,r12),%0\n\t" \ + "bra 2f\n\t" \ + " add %1,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@gottpoff\n\t" \ + "2:" \ + : "=r" (__l), "=r" (__tp) : "r" (__gp) : "r0"); \ + __l; }) +# else +# define TLS_IE(x) \ + ({ int *__l; void *__tp; \ + asm ("mov.l r12,@-r15\n\t" \ + "mova 0f,r0\n\t" \ + "mov.l 0f,r12\n\t" \ + "add r0,r12\n\t" \ + "mov.l 1f,r0\n\t" \ + "stc gbr,%1\n\t" \ + "mov.l @(r0,r12),%0\n\t" \ + "bra 2f\n\t" \ + " add %1,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@gottpoff\n\t" \ + "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ + "2: mov.l @r15+,r12" \ + : "=r" (__l), "=r" (__tp) : : "r0"); \ + __l; }) +#endif + +# ifdef PIC +# define TLS_LD(x) \ + ({ int *__l; \ + register void *__gp __asm__("r12"); \ + asm ("mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 4f\n\t" \ + " nop\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsldm\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "4: mov.l 3f,%0\n\t" \ + "bra 5f\n\t" \ + " add r0,%0\n\t" \ + ".align 2\n\t" \ + "3: .long " #x "@dtpoff\n\t" \ + "5:" \ + : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "pr", "t"); \ + __l; }) +# else +# define TLS_LD(x) \ + ({ int *__l; \ + asm ("mov.l r12,@-r15\n\t" \ + "mova 0f,r0\n\t" \ + "mov.l 0f,r12\n\t" \ + "add r0,r12\n\t" \ + "mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 4f\n\t" \ + " nop\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsldm\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ + "4: mov.l 3f,%0\n\t" \ + "bra 5f\n\t" \ + " add r0,%0\n\t" \ + ".align 2\n\t" \ + "3: .long " #x "@dtpoff\n\t" \ + "5: mov.l @r15+,r12" \ + : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "pr", "t"); \ + __l; }) +#endif + +# ifdef PIC +# define TLS_GD(x) \ + ({ int *__l; \ + register void *__gp __asm__("r12"); \ + asm ("mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 3f\n\t" \ + " mov r0,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsgd\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "3:" \ + : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "pr", "t"); \ + __l; }) +# else +# define TLS_GD(x) \ + ({ int *__l; \ + asm ("mov.l r12,@-r15\n\t" \ + "mova 0f,r0\n\t" \ + "mov.l 0f,r12\n\t" \ + "add r0,r12\n\t" \ + "mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 3f\n\t" \ + " mov r0,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsgd\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ + "3: mov.l @r15+,r12" \ + : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "pr", "t"); \ + __l; }) +#endif + +#elif defined __alpha__ + +register void *__gp __asm__("$29"); + +# define TLS_LE(x) \ + ({ int *__l; \ + asm ("call_pal 158\n\tlda $0," #x "($0)\t\t!tprel" : "=v"(__l)); \ + __l; }) + +# define TLS_IE(x) \ + ({ char *__tp; unsigned long __o; \ + asm ("call_pal 158\n\tldq %1," #x "($gp)\t\t!gottprel" \ + : "=v"(__tp), "=r"(__o) : "r"(__gp)); \ + (int *)(__tp + __o); }) + +# define TLS_LD(x) \ + ({ extern void *__tls_get_addr(void *); int *__l; void *__i; \ + asm ("lda %0," #x "($gp)\t\t!tlsldm" : "=r" (__i) : "r"(__gp)); \ + __i = __tls_get_addr(__i); \ + asm ("lda %0, " #x "(%1)\t\t!dtprel" : "=r"(__l) : "r"(__i)); \ + __l; }) + +# define TLS_GD(x) \ + ({ extern void *__tls_get_addr(void *); void *__i; \ + asm ("lda %0," #x "($gp)\t\t!tlsgd" : "=r" (__i) : "r"(__gp)); \ + (int *) __tls_get_addr(__i); }) + + +#elif defined __ia64__ + +# define TLS_LE(x) \ + ({ void *__l; \ + asm ("mov r2=r13\n\t" \ + ";;\n\t" \ + "addl %0=@tprel(" #x "),r2\n\t" \ + : "=r" (__l) : : "r2" ); __l; }) + +# define TLS_IE(x) \ + ({ void *__l; \ + register long __gp asm ("gp"); \ + asm (";;\n\t" \ + "addl r16=@ltoff(@tprel(" #x ")),gp\n\t" \ + ";;\n\t" \ + "ld8 r17=[r16]\n\t" \ + ";;\n\t" \ + "add %0=r13,r17\n\t" \ + ";;\n\t" \ + : "=r" (__l) : "r" (__gp) : "r16", "r17" ); __l; }) + +# define __TLS_CALL_CLOBBERS \ + "r2", "r3", "r8", "r9", "r10", "r11", "r14", "r15", "r16", "r17", \ + "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", \ + "r27", "r28", "r29", "r30", "r31", \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + "b6", "b7", \ + "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" + +# define TLS_LD(x) \ + ({ void *__l; \ + register long __gp asm ("gp"); \ + asm (";;\n\t" \ + "mov loc0=gp\n\t" \ + "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ + "addl out1=@dtprel(" #x "),r0\n\t" \ + ";;\n\t" \ + "ld8 out0=[r16]\n\t" \ + "br.call.sptk.many b0=__tls_get_addr" \ + ";;\n\t" \ + "mov gp=loc0\n\t" \ + "mov %0=r8\n\t" \ + ";;\n\t" \ + : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \ + __l; }) + +# define TLS_GD(x) \ + ({ void *__l; \ + register long __gp asm ("gp"); \ + asm (";;\n\t" \ + "mov loc0=gp\n\t" \ + "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ + "addl r17=@ltoff(@dtprel(" #x ")),gp\n\t" \ + ";;\n\t" \ + "ld8 out0=[r16]\n\t" \ + "ld8 out1=[r17]\n\t" \ + "br.call.sptk.many b0=__tls_get_addr" \ + ";;\n\t" \ + "mov gp=loc0\n\t" \ + "mov %0=r8\n\t" \ + ";;\n\t" \ + : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \ + __l; }) + +#elif defined __sparc__ && !defined __arch64__ + +# define TLS_LE(x) \ + ({ int *__l; \ + asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \ + asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# ifdef __PIC__ +# define TLS_LOAD_PIC \ + ({ register long pc __asm__ ("%o7"); \ + long got; \ + asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "call .+8\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ + "add %1, %0, %1\n\t" \ + : "=r" (pc), "=r" (got)); \ + got; }) +# else +# define TLS_LOAD_PIC \ + ({ long got; \ + asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \ + "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \ + "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \ + : "=r" (got)); \ + got; }) +# endif + +# define TLS_IE(x) \ + ({ int *__l; \ + asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \ + asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("ld [%1 + %2], %0, %%tie_ld(" #x ")" \ + : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# define TLS_LD(x) \ + ({ int *__l; register void *__o0 asm ("%o0"); \ + long __o; \ + asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \ + asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("add %1, %2, %0, %%tldm_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \ + asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \ + asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \ + : "r" (__o0), "r" (__o)); \ + __l; }) + +# define TLS_GD(x) \ + ({ int *__l; register void *__o0 asm ("%o0"); \ + asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \ + asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("add %1, %2, %0, %%tgd_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + __o0; }) + +#elif defined __sparc__ && defined __arch64__ + +# define TLS_LE(x) \ + ({ int *__l; \ + asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \ + asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# ifdef __PIC__ +# define TLS_LOAD_PIC \ + ({ long pc, got; \ + asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "rd %%pc, %0\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ + "add %1, %0, %1\n\t" \ + : "=r" (pc), "=r" (got)); \ + got; }) +# else +# define TLS_LOAD_PIC \ + ({ long got; \ + asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \ + "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \ + "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \ + : "=r" (got)); \ + got; }) +# endif + +# define TLS_IE(x) \ + ({ int *__l; \ + asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \ + asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("ldx [%1 + %2], %0, %%tie_ldx(" #x ")" \ + : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# define TLS_LD(x) \ + ({ int *__l; register void *__o0 asm ("%o0"); \ + long __o; \ + asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \ + asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("add %1, %2, %0, %%tldm_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \ + asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \ + asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \ + : "r" (__o0), "r" (__o)); \ + __l; }) + +# define TLS_GD(x) \ + ({ int *__l; register void *__o0 asm ("%o0"); \ + asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \ + asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + asm ("add %1, %2, %0, %%tgd_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + __o0; }) + +#elif defined __s390x__ + +# define TLS_LE(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@ntpoff\n" \ + "1:\tlg %0,0(%0)" \ + : "=a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + +# ifdef PIC +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@gotntpoff\n" \ + "1:\tlg %0,0(%0)\n\t" \ + "lg %0,0(%0,%%r12):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@indntpoff\n" \ + "1:\t lg %0,0(%0)\n\t" \ + "lg %0,0(%0):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef PIC +# define TLS_LD(x) \ + ({ unsigned long __offset, __save12; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsldm\n\t" \ + ".quad " #x "@dtpoff\n" \ + "1:\tlgr %1,%%r12\n\t" \ + "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ + "lg %0,8(%0)\n\t" \ + "algr %0,%%r2\n\t" \ + "lgr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_LD(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsldm\n\t" \ + ".quad " #x "@dtpoff\n" \ + "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ + "lg %0,8(%0)\n\t" \ + "algr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef PIC +# define TLS_GD(x) \ + ({ unsigned long __offset, __save12; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsgd\n" \ + "1:\tlgr %1,%%r12\n\t" \ + "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ + "lgr %0,%%r2\n\t" \ + "lgr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_GD(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsgd\n" \ + "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ + "lgr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +#elif defined __s390__ + +# define TLS_LE(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.long " #x "@ntpoff\n" \ + "1:\tl %0,0(%0)" \ + : "=a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + +# ifdef PIC +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.long " #x "@gotntpoff\n" \ + "1:\tl %0,0(%0)\n\t" \ + "l %0,0(%0,%%r12):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.long " #x "@indntpoff\n" \ + "1:\t l %0,0(%0)\n\t" \ + "l %0,0(%0):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef PIC +# define TLS_LD(x) \ + ({ unsigned long __offset, __save12; \ + asm ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long __tls_get_offset@plt-0b\n\t" \ + ".long " #x "@tlsldm\n\t" \ + ".long " #x "@dtpoff\n" \ + "1:\tlr %1,%%r12\n\t" \ + "l %%r12,0(%0)\n\t" \ + "la %%r12,0(%%r12,%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t" \ + "l %0,12(%0)\n\t" \ + "alr %0,%%r2\n\t" \ + "lr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_LD(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ + ".long __tls_get_offset@plt\n\t" \ + ".long " #x "@tlsldm\n\t" \ + ".long " #x "@dtpoff\n" \ + "1:\tl %%r12,0(%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t" \ + "l %0,12(%0)\n\t" \ + "alr %0,%%r2" \ + : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef PIC +# define TLS_GD(x) \ + ({ unsigned long __offset, __save12; \ + asm ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long __tls_get_offset@plt-0b\n\t" \ + ".long " #x "@tlsgd\n" \ + "1:\tlr %1,%%r12\n\t" \ + "l %%r12,0(%0)\n\t" \ + "la %%r12,0(%%r12,%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t" \ + "lr %0,%%r2\n\t" \ + "lr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_GD(x) \ + ({ unsigned long __offset; \ + asm ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ + ".long __tls_get_offset@plt\n\t" \ + ".long " #x "@tlsgd\n" \ + "1:\tl %%r12,0(%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t" \ + "lr %0,%%r2" \ + : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +#elif defined __powerpc__ && !defined __powerpc64__ + +#include "config.h" + +# define __TLS_CALL_CLOBBERS \ + "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", \ + "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7" + +/* PowerPC32 Local Exec TLS access. */ +# define TLS_LE(x) \ + ({ int *__result; \ + asm ("addi %0,2," #x "@tprel" \ + : "=r" (__result)); \ + __result; }) + +/* PowerPC32 Initial Exec TLS access. */ +# ifdef HAVE_ASM_PPC_REL16 +# define TLS_IE(x) \ + ({ int *__result; \ + asm ("bcl 20,31,1f\n1:\t" \ + "mflr %0\n\t" \ + "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ + "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ + "lwz %0," #x "@got@tprel(%0)\n\t" \ + "add %0,%0," #x "@tls" \ + : "=b" (__result) : \ + : "lr"); \ + __result; }) +# else +# define TLS_IE(x) \ + ({ int *__result; \ + asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \ + "mflr %0\n\t" \ + "lwz %0," #x "@got@tprel(%0)\n\t" \ + "add %0,%0," #x "@tls" \ + : "=b" (__result) : \ + : "lr"); \ + __result; }) +# endif + +/* PowerPC32 Local Dynamic TLS access. */ +# ifdef HAVE_ASM_PPC_REL16 +# define TLS_LD(x) \ + ({ int *__result; \ + asm ("bcl 20,31,1f\n1:\t" \ + "mflr 3\n\t" \ + "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ + "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ + "addi 3,3," #x "@got@tlsld\n\t" \ + "bl __tls_get_addr@plt\n\t" \ + "addi %0,3," #x "@dtprel" \ + : "=r" (__result) : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# else +# define TLS_LD(x) \ + ({ int *__result; \ + asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \ + "mflr 3\n\t" \ + "addi 3,3," #x "@got@tlsld\n\t" \ + "bl __tls_get_addr@plt\n\t" \ + "addi %0,3," #x "@dtprel" \ + : "=r" (__result) : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# endif + +/* PowerPC32 General Dynamic TLS access. */ +# ifdef HAVE_ASM_PPC_REL16 +# define TLS_GD(x) \ + ({ register int *__result __asm__ ("r3"); \ + asm ("bcl 20,31,1f\n1:\t" \ + "mflr 3\n\t" \ + "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ + "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ + "addi 3,3," #x "@got@tlsgd\n\t" \ + "bl __tls_get_addr@plt" \ + : : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# else +# define TLS_GD(x) \ + ({ register int *__result __asm__ ("r3"); \ + asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \ + "mflr 3\n\t" \ + "addi 3,3," #x "@got@tlsgd\n\t" \ + "bl __tls_get_addr@plt" \ + : : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# endif + +#elif defined __powerpc__ && defined __powerpc64__ + +/* PowerPC64 Local Exec TLS access. */ +# define TLS_LE(x) \ + ({ int * __result; \ + asm ( \ + " addis %0,13," #x "@tprel@ha\n" \ + " addi %0,%0," #x "@tprel@l\n" \ + : "=b" (__result) ); \ + __result; \ + }) +/* PowerPC64 Initial Exec TLS access. */ +# define TLS_IE(x) \ + ({ int * __result; \ + asm ( \ + " ld %0," #x "@got@tprel(2)\n" \ + " add %0,%0," #x "@tls\n" \ + : "=b" (__result) ); \ + __result; \ + }) +/* PowerPC64 Local Dynamic TLS access. */ +# define TLS_LD(x) \ + ({ int * __result; \ + asm ( \ + " addi 3,2," #x "@got@tlsld\n" \ + " bl .__tls_get_addr\n" \ + " nop \n" \ + " addis %0,3," #x "@dtprel@ha\n" \ + " addi %0,%0," #x "@dtprel@l\n" \ + : "=b" (__result) : \ + : "0", "3", "4", "5", "6", "7", \ + "8", "9", "10", "11", "12", \ + "lr", "ctr", \ + "cr0", "cr1", "cr5", "cr6", "cr7"); \ + __result; \ + }) +/* PowerPC64 General Dynamic TLS access. */ +# define TLS_GD(x) \ + ({ int * __result; \ + asm ( \ + " addi 3,2," #x "@got@tlsgd\n" \ + " bl .__tls_get_addr\n" \ + " nop \n" \ + " mr %0,3\n" \ + : "=b" (__result) : \ + : "0", "3", "4", "5", "6", "7", \ + "8", "9", "10", "11", "12", \ + "lr", "ctr", \ + "cr0", "cr1", "cr5", "cr6", "cr7"); \ + __result; \ + }) + +#elif !defined TLS_LE || !defined TLS_IE \ + || !defined TLS_LD || !defined TLS_GD +# error "No support for this architecture so far." +#endif diff --git a/test/tls/tst-tls1-static.c b/test/tls/tst-tls1-static.c new file mode 100644 index 000000000..a01008073 --- /dev/null +++ b/test/tls/tst-tls1-static.c @@ -0,0 +1 @@ +#include "tst-tls1.c" diff --git a/test/tls/tst-tls1.c b/test/tls/tst-tls1.c new file mode 100644 index 000000000..478f5bbdc --- /dev/null +++ b/test/tls/tst-tls1.c @@ -0,0 +1,91 @@ +/* glibc test for TLS in ld.so. */ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +# include "tls-macros.h" + + +/* Two common 'int' variables in TLS. */ +COMMON_INT_DEF(foo); +COMMON_INT_DEF(bar); +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + int result = 0; + int *ap, *bp; + + + /* Set the variable using the local exec model. */ + puts ("set bar to 1 (LE)"); + ap = TLS_LE (bar); + *ap = 1; + + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + ap = TLS_IE (foo); + bp = TLS_IE (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo and bar (LD)", stdout); + ap = TLS_LD (foo); + bp = TLS_LD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using generic dynamic model. */ + fputs ("get sum of foo and bar (GD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls10.c b/test/tls/tst-tls10.c new file mode 100644 index 000000000..fc0677072 --- /dev/null +++ b/test/tls/tst-tls10.c @@ -0,0 +1,40 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A local = { 1, 2, 3 }; +#endif + +#define CHECK(N, S) \ + p = f##N##a (); \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int +main (void) +{ + struct A *p; + if (local.a != 1 || local.b != 2 || local.c != 3) + abort (); +#ifdef USE_TLS__THREAD + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + check1 (); + check2 (); + if (f1a () != &a1 || f2a () != &a2 || f3a () != &a3 || f4a () != &a4) + abort (); + CHECK (5, 16); + CHECK (6, 19); + if (f7a () != &a2 || f8a () != &a4) + abort (); + CHECK (9, 28); + CHECK (10, 31); +#endif + exit (0); +} diff --git a/test/tls/tst-tls10.h b/test/tls/tst-tls10.h new file mode 100644 index 000000000..1be6adc29 --- /dev/null +++ b/test/tls/tst-tls10.h @@ -0,0 +1,38 @@ +#include <tls.h> +#include <stdlib.h> + +#if defined USE_TLS && defined HAVE___THREAD \ + && defined HAVE_TLS_MODEL_ATTRIBUTE +# define USE_TLS__THREAD + +struct A +{ + char a; + int b; + long long c; +}; + +extern __thread struct A a1, a2, a3, a4; +extern struct A *f1a (void); +extern struct A *f2a (void); +extern struct A *f3a (void); +extern struct A *f4a (void); +extern struct A *f5a (void); +extern struct A *f6a (void); +extern struct A *f7a (void); +extern struct A *f8a (void); +extern struct A *f9a (void); +extern struct A *f10a (void); +extern int f1b (void); +extern int f2b (void); +extern int f3b (void); +extern int f4b (void); +extern int f5b (void); +extern int f6b (void); +extern int f7b (void); +extern int f8b (void); +extern int f9b (void); +extern int f10b (void); +extern void check1 (void); +extern void check2 (void); +#endif diff --git a/test/tls/tst-tls11.c b/test/tls/tst-tls11.c new file mode 100644 index 000000000..816cf5cc2 --- /dev/null +++ b/test/tls/tst-tls11.c @@ -0,0 +1,27 @@ +#include "tst-tls10.h" + +#define CHECK(N, S) \ + p = f##N##a (); \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int +main (void) +{ +#ifdef USE_TLS__THREAD + struct A *p; + check1 (); + check2 (); + CHECK (1, 4); + CHECK (2, 22); + CHECK (3, 10); + CHECK (4, 25); + CHECK (5, 16); + CHECK (6, 19); + CHECK (7, 22); + CHECK (8, 25); + CHECK (9, 28); + CHECK (10, 31); +#endif + exit (0); +} diff --git a/test/tls/tst-tls12.c b/test/tls/tst-tls12.c new file mode 100644 index 000000000..84aa7d35c --- /dev/null +++ b/test/tls/tst-tls12.c @@ -0,0 +1,18 @@ +#include "tst-tls10.h" + +#define CHECK(N, S) \ + p = &a##N; \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int +main (void) +{ +#ifdef USE_TLS__THREAD + struct A *p; + check1 (); + CHECK (1, 4); + CHECK (2, 7); +#endif + exit (0); +} diff --git a/test/tls/tst-tls13.c b/test/tls/tst-tls13.c new file mode 100644 index 000000000..55fb62e54 --- /dev/null +++ b/test/tls/tst-tls13.c @@ -0,0 +1,30 @@ +/* Check unloading modules with data in static TLS block. */ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + + +static int +do_test (void) +{ + int i; + for (i = 0; i < 1000;) + { + printf ("round %d\n",++i); + + void *h = dlopen ("tst-tlsmod13a.so", RTLD_LAZY); + if (h == NULL) + { + printf ("cannot load: %s\n", dlerror ()); + exit (1); + } + + dlclose (h); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#define TIMEOUT 3 +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls14.c b/test/tls/tst-tls14.c new file mode 100644 index 000000000..428fd5293 --- /dev/null +++ b/test/tls/tst-tls14.c @@ -0,0 +1,66 @@ +/* Check alignment of TLS variable. */ +#include <dlfcn.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include <tls.h> + +#if USE_TLS && HAVE___THREAD + +#define AL 4096 +struct foo +{ + int i; +} __attribute ((aligned (AL))); + +static __thread struct foo f; +static struct foo g; + + +extern int in_dso1 (void); + + +static int +do_test (void) +{ + int result = 0; + + int fail = (((uintptr_t) &f) & (AL - 1)) != 0; + printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK"); + result |= fail; + + fail = (((uintptr_t) &g) & (AL - 1)) != 0; + printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK"); + result |= fail; + + result |= in_dso1 (); + + void *h = dlopen ("tst-tlsmod14b.so", RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open tst-tlsmod14b.so: %m\n"); + exit (1); + } + + int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso2"); + if (fp == NULL) + { + puts ("cannot find in_dso2"); + exit (1); + } + + result |= fp (); + + return result; +} + +#define TEST_FUNCTION do_test () + +#else + +#define TEST_FUNCTION 0 + +#endif + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls15.c b/test/tls/tst-tls15.c new file mode 100644 index 000000000..7ac963aa2 --- /dev/null +++ b/test/tls/tst-tls15.c @@ -0,0 +1,32 @@ +#include <dlfcn.h> +#include <stdio.h> + +static int +do_test (void) +{ + void *h = dlopen ("tst-tlsmod15a.so", RTLD_NOW); + if (h != NULL) + { + puts ("unexpectedly succeeded to open tst-tlsmod15a.so"); + exit (1); + } + + h = dlopen ("tst-tlsmod15b.so", RTLD_NOW); + if (h == NULL) + { + puts ("failed to open tst-tlsmod15b.so"); + exit (1); + } + + int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso"); + if (fp == NULL) + { + puts ("cannot find in_dso"); + exit (1); + } + + return fp (); +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls2-static.c b/test/tls/tst-tls2-static.c new file mode 100644 index 000000000..55ffa5744 --- /dev/null +++ b/test/tls/tst-tls2-static.c @@ -0,0 +1 @@ +#include "tst-tls2.c" diff --git a/test/tls/tst-tls2.c b/test/tls/tst-tls2.c new file mode 100644 index 000000000..417489968 --- /dev/null +++ b/test/tls/tst-tls2.c @@ -0,0 +1,91 @@ +/* glibc test for TLS in ld.so. */ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +# include "tls-macros.h" + + +/* Two 'int' variables in TLS. */ +VAR_INT_DEF(foo); +VAR_INT_DEF(bar); +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + int result = 0; + int *ap, *bp; + + + /* Set the variable using the local exec model. */ + puts ("set bar to 1 (LE)"); + ap = TLS_LE (bar); + *ap = 1; + + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + ap = TLS_IE (foo); + bp = TLS_IE (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo and bar (LD)", stdout); + ap = TLS_LD (foo); + bp = TLS_LD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using generic dynamic model. */ + fputs ("get sum of foo and bar (GD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls3.c b/test/tls/tst-tls3.c new file mode 100644 index 000000000..84be43575 --- /dev/null +++ b/test/tls/tst-tls3.c @@ -0,0 +1,76 @@ +/* glibc test for TLS in ld.so. */ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +# include "tls-macros.h" + + +/* One define int variable, two externs. */ +COMMON_INT_DECL(foo); +VAR_INT_DECL(bar); +VAR_INT_DEF(baz); +#endif + + +extern int in_dso (void); + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + int result = 0; + int *ap, *bp, *cp; + + + /* Set the variable using the local exec model. */ + puts ("set baz to 3 (LE)"); + ap = TLS_LE (baz); + *ap = 3; + + + /* Get variables using initial exec model. */ + puts ("set variables foo and bar (IE)"); + ap = TLS_IE (foo); + *ap = 1; + bp = TLS_IE (bar); + *bp = 2; + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo, bar (GD) and baz (LD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + cp = TLS_LD (baz); + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 2) + { + printf ("bar = %d\n", *bp); + result = 1; + } + if (*cp != 3) + { + printf ("baz = %d\n", *cp); + result = 1; + } + + + result |= in_dso (); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls4.c b/test/tls/tst-tls4.c new file mode 100644 index 000000000..f92ee53ce --- /dev/null +++ b/test/tls/tst-tls4.c @@ -0,0 +1,56 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include <tls.h> + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod2.so"; + int result = 0; + int *foop; + int (*fp) (int, int *); + void *h; + + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + result |= fp (0, NULL); + + foop = dlsym (h, "foo"); + if (foop == NULL) + { + printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); + exit (1); + } + if (*foop != 16) + { + puts ("foo != 16"); + result = 1; + } + + dlclose (h); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls5.c b/test/tls/tst-tls5.c new file mode 100644 index 000000000..a571d2cd3 --- /dev/null +++ b/test/tls/tst-tls5.c @@ -0,0 +1,72 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include <tls.h> + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod2.so"; + int result = 0; + int *foop; + int *foop2; + int (*fp) (int, int *); + void *h; + + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + foop = dlsym (h, "foo"); + if (foop == NULL) + { + printf ("cannot get symbol 'foo': %s\n", dlerror ()); + exit (1); + } + + *foop = 42; + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + result |= fp (42, foop); + + foop2 = dlsym (h, "foo"); + if (foop2 == NULL) + { + printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); + exit (1); + } + + if (foop != foop2) + { + puts ("address of 'foo' different the second time"); + result = 1; + } + else if (*foop != 16) + { + puts ("foo != 16"); + result = 1; + } + + dlclose (h); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls6.c b/test/tls/tst-tls6.c new file mode 100644 index 000000000..68d706538 --- /dev/null +++ b/test/tls/tst-tls6.c @@ -0,0 +1,90 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include <link.h> +#include <tls.h> + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod2.so"; + int result = 0; + int *foop; + int *foop2; + int (*fp) (int, int *); + void *h; + int i; + int modid = -1; + + for (i = 0; i < 10; ++i) + { + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + 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. */ + 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; + } + + foop = dlsym (h, "foo"); + if (foop == NULL) + { + printf ("cannot get symbol 'foo': %s\n", dlerror ()); + exit (1); + } + + *foop = 42 + i; + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + result |= fp (42 + i, foop); + + foop2 = dlsym (h, "foo"); + if (foop2 == NULL) + { + printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); + exit (1); + } + + if (foop != foop2) + { + puts ("address of 'foo' different the second time"); + result = 1; + } + else if (*foop != 16) + { + puts ("foo != 16"); + result = 1; + } + + dlclose (h); + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls7.c b/test/tls/tst-tls7.c new file mode 100644 index 000000000..37f1a63e1 --- /dev/null +++ b/test/tls/tst-tls7.c @@ -0,0 +1,61 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include <link.h> +#include <tls.h> + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod3.so"; + int result = 0; + int (*fp) (void); + void *h; + int i; + int modid = -1; + + for (i = 0; i < 10; ++i) + { + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + 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. */ + 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; + } + + fp = dlsym (h, "in_dso2"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso2': %s\n", dlerror ()); + exit (1); + } + + result |= fp (); + + dlclose (h); + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls8.c b/test/tls/tst-tls8.c new file mode 100644 index 000000000..dd896c493 --- /dev/null +++ b/test/tls/tst-tls8.c @@ -0,0 +1,174 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include <link.h> +#include <tls.h> + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname1[] = "tst-tlsmod3.so"; + static const char modname2[] = "tst-tlsmod4.so"; + int result = 0; + int (*fp1) (void); + int (*fp2) (int, int *); + void *h1; + void *h2; + int i; + size_t modid1 = (size_t) -1; + size_t modid2 = (size_t) -1; + int *bazp; + + for (i = 0; i < 10; ++i) + { + h1 = dlopen (modname1, RTLD_LAZY); + if (h1 == NULL) + { + printf ("cannot open '%s': %s\n", modname1, dlerror ()); + 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. */ + 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; + } + + fp1 = dlsym (h1, "in_dso2"); + if (fp1 == NULL) + { + printf ("cannot get symbol 'in_dso2' in %s\n", modname1); + exit (1); + } + + result |= fp1 (); + + + + h2 = dlopen (modname2, RTLD_LAZY); + if (h2 == NULL) + { + printf ("cannot open '%s': %s\n", modname2, dlerror ()); + 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. */ + if (modid2 == (size_t) -1) + modid2 = ((struct link_map *) h1)->l_tls_modid; + else if (((struct link_map *) h1)->l_tls_modid != modid2) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, ((struct link_map *) h1)->l_tls_modid, modid2); + result = 1; + } + + bazp = dlsym (h2, "baz"); + if (bazp == NULL) + { + printf ("cannot get symbol 'baz' in %s\n", modname2); + exit (1); + } + + *bazp = 42 + i; + + fp2 = dlsym (h2, "in_dso"); + if (fp2 == NULL) + { + printf ("cannot get symbol 'in_dso' in %s\n", modname2); + exit (1); + } + + result |= fp2 (42 + i, bazp); + + dlclose (h1); + dlclose (h2); + + + h1 = dlopen (modname1, RTLD_LAZY); + if (h1 == NULL) + { + printf ("cannot open '%s': %s\n", modname1, dlerror ()); + 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. */ + 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; + } + + fp1 = dlsym (h1, "in_dso2"); + if (fp1 == NULL) + { + printf ("cannot get symbol 'in_dso2' in %s\n", modname1); + exit (1); + } + + result |= fp1 (); + + + + h2 = dlopen (modname2, RTLD_LAZY); + if (h2 == NULL) + { + printf ("cannot open '%s': %s\n", modname2, dlerror ()); + 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. */ + if (((struct link_map *) h1)->l_tls_modid != modid2) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, ((struct link_map *) h1)->l_tls_modid, modid2); + result = 1; + } + + bazp = dlsym (h2, "baz"); + if (bazp == NULL) + { + printf ("cannot get symbol 'baz' in %s\n", modname2); + exit (1); + } + + *bazp = 62 + i; + + fp2 = dlsym (h2, "in_dso"); + if (fp2 == NULL) + { + printf ("cannot get symbol 'in_dso' in %s\n", modname2); + exit (1); + } + + result |= fp2 (62 + i, bazp); + + /* This time the dlclose calls are in reverse order. */ + dlclose (h2); + dlclose (h1); + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tls9-static.c b/test/tls/tst-tls9-static.c new file mode 100644 index 000000000..51812ccc7 --- /dev/null +++ b/test/tls/tst-tls9-static.c @@ -0,0 +1 @@ +#include "tst-tls9.c" diff --git a/test/tls/tst-tls9.c b/test/tls/tst-tls9.c new file mode 100644 index 000000000..e317696df --- /dev/null +++ b/test/tls/tst-tls9.c @@ -0,0 +1,42 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include <link.h> +#include <tls.h> + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname1[] = "tst-tlsmod5.so"; + static const char modname2[] = "tst-tlsmod6.so"; + int result = 0; + + void *h1 = dlopen (modname1, RTLD_LAZY); + if (h1 == NULL) + { + printf ("cannot open '%s': %s\n", modname1, dlerror ()); + result = 1; + } + void *h2 = dlopen (modname2, RTLD_LAZY); + if (h2 == NULL) + { + printf ("cannot open '%s': %s\n", modname2, dlerror ()); + result = 1; + } + + if (h1 != NULL) + dlclose (h1); + if (h2 != NULL) + dlclose (h2); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/test/tls/tst-tlsmod1.c b/test/tls/tst-tlsmod1.c new file mode 100644 index 000000000..c74a617b7 --- /dev/null +++ b/test/tls/tst-tlsmod1.c @@ -0,0 +1,68 @@ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +#include "tls-macros.h" + + +/* One define int variable, two externs. */ +COMMON_INT_DEF(foo); +VAR_INT_DEF(bar); +VAR_INT_DECL(baz); +#endif + +extern int in_dso (void); + +int +in_dso (void) +{ + int result = 0; +#ifdef USE_TLS + int *ap, *bp, *cp; + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + asm ("" ::: "memory"); + ap = TLS_IE (foo); + bp = TLS_IE (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 3; + if (*ap != 1) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 2) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using generic dynamic model. */ + fputs ("get sum of foo and bar and baz (GD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + cp = TLS_GD (baz); + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 2) + { + printf ("bar = %d\n", *bp); + result = 1; + } + if (*cp != 3) + { + printf ("baz = %d\n", *cp); + result = 1; + } +#endif + + return result; +} diff --git a/test/tls/tst-tlsmod10.c b/test/tls/tst-tlsmod10.c new file mode 100644 index 000000000..32e54f3c0 --- /dev/null +++ b/test/tls/tst-tlsmod10.c @@ -0,0 +1 @@ +#include "tst-tlsmod8.c" diff --git a/test/tls/tst-tlsmod11.c b/test/tls/tst-tlsmod11.c new file mode 100644 index 000000000..9938b5753 --- /dev/null +++ b/test/tls/tst-tlsmod11.c @@ -0,0 +1,6 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; +#endif diff --git a/test/tls/tst-tlsmod12.c b/test/tls/tst-tlsmod12.c new file mode 100644 index 000000000..4602709a1 --- /dev/null +++ b/test/tls/tst-tlsmod12.c @@ -0,0 +1,14 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +extern __thread struct A a2 __attribute__((tls_model("initial-exec"))); + +void +check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 7 || a2.b != 8 || a2.c != 9) + abort (); +} +#endif diff --git a/test/tls/tst-tlsmod13.c b/test/tls/tst-tlsmod13.c new file mode 100644 index 000000000..beca89f6f --- /dev/null +++ b/test/tls/tst-tlsmod13.c @@ -0,0 +1,14 @@ +#include <tls.h> + +#if defined USE_TLS && defined HAVE___THREAD \ + && defined HAVE_TLS_MODEL_ATTRIBUTE +__thread int a[2] __attribute__ ((tls_model ("initial-exec"))); +#else +int a[2]; +#endif + +int +foo (void) +{ + return a[0]; +} diff --git a/test/tls/tst-tlsmod13a.c b/test/tls/tst-tlsmod13a.c new file mode 100644 index 000000000..14b12b032 --- /dev/null +++ b/test/tls/tst-tlsmod13a.c @@ -0,0 +1,16 @@ +#include <tls.h> + +#if defined USE_TLS && defined HAVE___THREAD \ + && defined HAVE_TLS_MODEL_ATTRIBUTE +__thread int b[2] __attribute__ ((tls_model ("initial-exec"))); +#else +int b[2]; +#endif + +extern int foo (void); + +int +bar (void) +{ + return foo () + b[0]; +} diff --git a/test/tls/tst-tlsmod14a.c b/test/tls/tst-tlsmod14a.c new file mode 100644 index 000000000..0bb393d9c --- /dev/null +++ b/test/tls/tst-tlsmod14a.c @@ -0,0 +1,41 @@ +#include <stdint.h> +#include <stdio.h> + +#include <tls.h> + +#if USE_TLS && HAVE___THREAD + +#define AL 4096 +struct foo +{ + int i; +} __attribute ((aligned (AL))); + +static __thread struct foo f; +static struct foo g; + + +#ifndef FCT +# define FCT in_dso1 +#endif + + +int +FCT (void) +{ + puts (__func__); + + int result = 0; + + int fail = (((uintptr_t) &f) & (AL - 1)) != 0; + printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK"); + result |= fail; + + fail = (((uintptr_t) &g) & (AL - 1)) != 0; + printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK"); + result |= fail; + + return result; +} + +#endif diff --git a/test/tls/tst-tlsmod14b.c b/test/tls/tst-tlsmod14b.c new file mode 100644 index 000000000..24d9ceaf7 --- /dev/null +++ b/test/tls/tst-tlsmod14b.c @@ -0,0 +1,2 @@ +#define FCT in_dso2 +#include "tst-tlsmod14a.c" diff --git a/test/tls/tst-tlsmod15a.c b/test/tls/tst-tlsmod15a.c new file mode 100644 index 000000000..66c707129 --- /dev/null +++ b/test/tls/tst-tlsmod15a.c @@ -0,0 +1,6 @@ +extern int nonexistent_dummy_var; +int * +foo (void) +{ + return &nonexistent_dummy_var; +} diff --git a/test/tls/tst-tlsmod15b.c b/test/tls/tst-tlsmod15b.c new file mode 100644 index 000000000..4f63eab14 --- /dev/null +++ b/test/tls/tst-tlsmod15b.c @@ -0,0 +1,17 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int mod15b_var __attribute__((tls_model("initial-exec"))); + +int +in_dso (void) +{ + return mod15b_var; +} +#else +int +in_dso (void) +{ + return 0; +} +#endif diff --git a/test/tls/tst-tlsmod2.c b/test/tls/tst-tlsmod2.c new file mode 100644 index 000000000..98d9d3e51 --- /dev/null +++ b/test/tls/tst-tlsmod2.c @@ -0,0 +1,38 @@ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +#include "tls-macros.h" + + +COMMON_INT_DEF(foo); + + +int +in_dso (int n, int *caller_foop) +{ + int *foop; + int result = 0; + + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + + foop = TLS_GD (foo); + + if (caller_foop != NULL && foop != caller_foop) + { + printf ("callers address of foo differs: %p vs %p\n", caller_foop, foop); + result = 1; + } + else if (*foop != n) + { + printf ("foo != %d\n", n); + result = 1; + } + + *foop = 16; + + return result; +} +#endif diff --git a/test/tls/tst-tlsmod3.c b/test/tls/tst-tlsmod3.c new file mode 100644 index 000000000..4a8aad659 --- /dev/null +++ b/test/tls/tst-tlsmod3.c @@ -0,0 +1,41 @@ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +# include "tls-macros.h" + +extern int in_dso (int n, int *caller_foop); + +COMMON_INT_DEF(comm_n); + + + + +int +in_dso2 (void) +{ + int *foop; + int result = 0; + static int n; + int *np; + + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + + foop = TLS_GD (foo); + np = TLS_GD (comm_n); + + if (n != *np) + { + printf ("n = %d != comm_n = %d\n", n, *np); + result = 1; + } + + result |= in_dso (*foop = 42 + n++, foop); + + *foop = 16; + + return result; +} +#endif diff --git a/test/tls/tst-tlsmod4.c b/test/tls/tst-tlsmod4.c new file mode 100644 index 000000000..5285e821b --- /dev/null +++ b/test/tls/tst-tlsmod4.c @@ -0,0 +1,38 @@ +#include <stdio.h> + +#include <tls.h> + +#ifdef USE_TLS +# include "tls-macros.h" + + +COMMON_INT_DEF(baz); + + +int +in_dso (int n, int *caller_bazp) +{ + int *bazp; + int result = 0; + + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + + bazp = TLS_GD (baz); + + if (caller_bazp != NULL && bazp != caller_bazp) + { + printf ("callers address of baz differs: %p vs %p\n", caller_bazp, bazp); + result = 1; + } + else if (*bazp != n) + { + printf ("baz != %d\n", n); + result = 1; + } + + *bazp = 16; + + return result; +} +#endif diff --git a/test/tls/tst-tlsmod5.c b/test/tls/tst-tlsmod5.c new file mode 100644 index 000000000..2ec69e13b --- /dev/null +++ b/test/tls/tst-tlsmod5.c @@ -0,0 +1,7 @@ +#include <tls.h> + +#ifdef USE_TLS +#include "tls-macros.h" + +COMMON_INT_DEF(foo); +#endif diff --git a/test/tls/tst-tlsmod6.c b/test/tls/tst-tlsmod6.c new file mode 100644 index 000000000..0fda51b22 --- /dev/null +++ b/test/tls/tst-tlsmod6.c @@ -0,0 +1,7 @@ +#include <tls.h> + +#ifdef USE_TLS +#include "tls-macros.h" + +COMMON_INT_DEF(bar); +#endif diff --git a/test/tls/tst-tlsmod7.c b/test/tls/tst-tlsmod7.c new file mode 100644 index 000000000..944b97f9c --- /dev/null +++ b/test/tls/tst-tlsmod7.c @@ -0,0 +1,103 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 13, 14, 15 }; +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; + +void +check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); +} + +struct A * +f1a (void) +{ + return &a1; +} + +struct A * +f2a (void) +{ + return &a2; +} + +struct A * +f3a (void) +{ + return &a3; +} + +struct A * +f4a (void) +{ + return &a4; +} + +struct A * +f5a (void) +{ + return &local1; +} + +struct A * +f6a (void) +{ + return &local2; +} + +int +f1b (void) +{ + return a1.a; +} + +int +f2b (void) +{ + return a2.b; +} + +int +f3b (void) +{ + return a3.c; +} + +int +f4b (void) +{ + return a4.a; +} + +int +f5b (void) +{ + return local1.b; +} + +int +f6b (void) +{ + return local2.c; +} +#endif diff --git a/test/tls/tst-tlsmod8.c b/test/tls/tst-tlsmod8.c new file mode 100644 index 000000000..c1822fc0c --- /dev/null +++ b/test/tls/tst-tlsmod8.c @@ -0,0 +1,72 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread long long dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A a2 = { 22, 23, 24 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 25, 26, 27 }; +static __thread struct A local1 = { 28, 29, 30 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 31, 32, 33 }; + +void +check2 (void) +{ + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 28 || local1.b != 29 || local1.c != 30) + abort (); + if (local2.a != 31 || local2.b != 32 || local2.c != 33) + abort (); +} + +struct A * +f7a (void) +{ + return &a2; +} + +struct A * +f8a (void) +{ + return &a4; +} + +struct A * +f9a (void) +{ + return &local1; +} + +struct A * +f10a (void) +{ + return &local2; +} + +int +f7b (void) +{ + return a2.b; +} + +int +f8b (void) +{ + return a4.a; +} + +int +f9b (void) +{ + return local1.b; +} + +int +f10b (void) +{ + return local2.c; +} +#endif diff --git a/test/tls/tst-tlsmod9.c b/test/tls/tst-tlsmod9.c new file mode 100644 index 000000000..e124144e4 --- /dev/null +++ b/test/tls/tst-tlsmod9.c @@ -0,0 +1,101 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +extern __thread struct A a4 __attribute__((tls_model("initial-exec"))); +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; + +void +check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); +} + +struct A * +f1a (void) +{ + return &a1; +} + +struct A * +f2a (void) +{ + return &a2; +} + +struct A * +f3a (void) +{ + return &a3; +} + +struct A * +f4a (void) +{ + return &a4; +} + +struct A * +f5a (void) +{ + return &local1; +} + +struct A * +f6a (void) +{ + return &local2; +} + +int +f1b (void) +{ + return a1.a; +} + +int +f2b (void) +{ + return a2.b; +} + +int +f3b (void) +{ + return a3.c; +} + +int +f4b (void) +{ + return a4.a; +} + +int +f5b (void) +{ + return local1.b; +} + +int +f6b (void) +{ + return local2.c; +} +#endif |
