aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile2
-rw-r--r--elf/rtld.c3
-rw-r--r--elf/tst-tls1.c81
3 files changed, 83 insertions, 3 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 476341902d..4235a594e8 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -117,7 +117,7 @@ tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
reldep reldep2 reldep3 reldep4 $(tests-nodelete-$(have-z-nodelete)) \
$(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \
neededtest3 neededtest4 unload2 lateglobal initfirst global \
- restest2 next dblload dblunload reldep5 reldep6
+ restest2 next dblload dblunload reldep5 reldep6 tst-tls1
test-srcs = tst-pathopt
tests-vis-yes = vismain
tests-nodelete-yes = nodelete
diff --git a/elf/rtld.c b/elf/rtld.c
index 2ebde4530a..f87462eda8 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -730,8 +730,7 @@ of this helper program; chances are you did not intend to run this program.\n\
GL(dl_loaded)->l_tls_blocksize = ph->p_memsz;
GL(dl_loaded)->l_tls_align = ph->p_align;
GL(dl_loaded)->l_tls_initimage_size = ph->p_filesz;
- GL(dl_loaded)->l_tls_initimage = (void *) (GL(dl_loaded)->l_addr
- + ph->p_offset);
+ GL(dl_loaded)->l_tls_initimage = (void *) ph->p_vaddr;
/* This is the first element of the initialization image list.
We create the list as circular since we have to append at
the end. */
diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c
new file mode 100644
index 0000000000..4d0913890c
--- /dev/null
+++ b/elf/tst-tls1.c
@@ -0,0 +1,81 @@
+/* glibc test for TLS in ld.so. */
+#include <stdio.h>
+
+#include <tls.h>
+
+
+/* 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");
+
+
+int
+main (void)
+{
+#ifdef USE_TLS
+ int result = 0;
+ int a, b;
+
+ /* 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)");
+
+#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
+
+ 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;
+
+# else
+# error "No support for this architecture so far."
+# endif
+
+ return result;
+#else
+ return 0;
+#endif
+}