+void *__copy_tls(unsigned char *mem, size_t cnt)
+{
+ struct dso *p;
+ void **dtv = (void *)mem;
+ dtv[0] = (void *)cnt;
+ mem = (void *)(dtv + cnt + 1);
+ for (p=tail; p; p=p->prev) {
+ if (p->tls_id-1 >= cnt) continue;
+ mem += -p->tls_len & (4*sizeof(size_t)-1);
+ mem += ((uintptr_t)p->tls_image - (uintptr_t)mem)
+ & (p->tls_align-1);
+ dtv[p->tls_id] = mem;
+ memcpy(mem, p->tls_image, p->tls_len);
+ mem += p->tls_size;
+ }
+ ((pthread_t)mem)->dtv = dtv;
+ 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];
+}
+