about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/internal/pthread_impl.h2
-rw-r--r--src/ldso/dynlink.c10
-rw-r--r--src/thread/i386/tls.s8
-rw-r--r--src/thread/tls.c0
4 files changed, 19 insertions, 1 deletions
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 56b92b22..f7facba3 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -22,7 +22,7 @@
 
 struct pthread {
 	struct pthread *self;
-	void *dtv, *unused1, *unused2;
+	void **dtv, *unused1, *unused2;
 	uintptr_t sysinfo;
 	uintptr_t canary;
 	pid_t tid, pid;
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 4e0b9f4e..774ab849 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -654,6 +654,16 @@ void *__copy_tls(unsigned char *mem, size_t cnt)
 	return mem;
 }
 
+void *__tls_get_addr(size_t *p)
+{
+	pthread_t self = __pthread_self();
+	if ((size_t)self->dtv[0] < p[0]) {
+		// FIXME: obtain new DTV and TLS from the DSO
+		a_crash();
+	}
+	return (char *)self->dtv[p[0]] + p[1];
+}
+
 void *__dynlink(int argc, char **argv)
 {
 	size_t aux[AUX_CNT] = {0};
diff --git a/src/thread/i386/tls.s b/src/thread/i386/tls.s
new file mode 100644
index 00000000..e1f22629
--- /dev/null
+++ b/src/thread/i386/tls.s
@@ -0,0 +1,8 @@
+.text
+.global ___tls_get_addr
+.type ___tls_get_addr,@function
+___tls_get_addr:
+	push %eax
+	call __tls_get_addr
+	pop %edx
+	ret
diff --git a/src/thread/tls.c b/src/thread/tls.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/thread/tls.c