diff options
Diffstat (limited to 'elf/tst-tls1.c')
-rw-r--r-- | elf/tst-tls1.c | 158 |
1 files changed, 107 insertions, 51 deletions
diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c index 4d0913890c..fc426b0d3c 100644 --- a/elf/tst-tls1.c +++ b/elf/tst-tls1.c @@ -6,14 +6,8 @@ /* XXX Until gcc gets told how to define and use thread-local variables we will have to resort to use asms. */ -//asm (".tls_common foo,4,4"); -asm (".section \".tdata\", \"awT\", @progbits\n\t" - ".align 4\n\t" - ".globl foo\n" - "foo:\t.long 0\n\t" - ".globl bar\n" - "bar:\t.long 0\n\t" - ".previous"); +asm (".tls_common foo,4,4"); +asm (".tls_common bar,4,4"); int @@ -21,59 +15,121 @@ main (void) { #ifdef USE_TLS int result = 0; - int a, b; + int *ap, *bp; /* XXX Each architecture must have its own asm for now. */ # ifdef __i386__ - /* Set the variable using the local exec model. */ - puts ("set bar to 1 (LE)"); - asm ("movl %gs:0,%eax\n\t" - "subl $bar@tpoff,%eax\n\t" - "movl $1,(%eax)"); +# define TLS_LE(x) \ + ({ int *__l; \ + asm ("movl %%gs:0,%0\n\t" \ + "subl $" #x "@tpoff,%0" \ + : "=r" (__l)); \ + __l; }) -#if 0 - // XXX Doesn't work yet; no runtime relocations. - fputs ("get sum of foo and bar (IE)", stdout); - 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,%%eax\n\t" - "movl %%eax,%%edx\n\t" - "addl foo@gottpoff(%%ebx),%%eax\n\t" - "addl bar@gottpoff(%%ebx),%%eax\n\t" - "movl (%%eax), %0\n\t" - "addl (%%edx), %0" - : "=a" (a), "=&b" (b)); - printf (" = %d\n", a); - result |= a != 1; -#endif +#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; }) - fputs ("get sum of foo and bar (GD)", stdout); - 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 foo@tlsgd(%%ebx),%%eax\n\t" - "call ___tls_get_addr@plt\n\t" - "nop\n\t" - "movl (%%eax), %%edx\n\t" - "leal bar@tlsgd(%%ebx),%%eax\n\t" - "call ___tls_get_addr@plt\n\t" - "nop\n\t" - "addl (%%eax), %%edx\n\t" - : "=&a" (a), "=d" (b)); - printf (" = %d\n", b); - result |= b != 1; +#define TLS_LD(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" \ + "leal " #x "@tlsldm(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "leal " #x "@dtpoff(%%eax), %%eax" \ + : "=a" (__l), "=&b" (__b)); \ + __l; }) + +#define TLS_GD(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" \ + "leal " #x "@tlsgd(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "nop" \ + : "=a" (__l), "=&b" (__b)); \ + __l; }) # else # error "No support for this architecture so far." # endif + /* 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; |