summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/dynlink.c25
-rw-r--r--src/env/__init_tls.c16
-rw-r--r--src/env/__reset_tls.c9
-rw-r--r--src/internal/pthread_impl.h5
-rw-r--r--src/thread/__tls_get_addr.c4
5 files changed, 28 insertions, 31 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index c2892b90..a3ca3cdf 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -72,7 +72,7 @@ struct dso {
struct tls_module tls;
size_t tls_id;
size_t relro_start, relro_end;
- void **new_dtv;
+ uintptr_t *new_dtv;
unsigned char *new_tls;
volatile int new_dtv_idx, new_tls_idx;
struct td_index *td_index;
@@ -445,7 +445,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
new->next = dso->td_index;
dso->td_index = new;
new->args[0] = def.dso->tls_id;
- new->args[1] = tls_val + addend;
+ new->args[1] = tls_val + addend - DTP_OFFSET;
reloc_addr[0] = (size_t)__tlsdesc_dynamic;
reloc_addr[1] = (size_t)new;
} else {
@@ -1345,9 +1345,9 @@ hidden void *__tls_get_new(tls_mod_off_t *v)
/* Block signals to make accessing new TLS async-signal-safe */
sigset_t set;
__block_all_sigs(&set);
- if (v[0]<=(size_t)self->dtv[0]) {
+ if (v[0] <= self->dtv[0]) {
__restore_sigs(&set);
- return (char *)self->dtv[v[0]]+v[1]+DTP_OFFSET;
+ return (void *)(self->dtv[v[0]] + v[1]);
}
/* This is safe without any locks held because, if the caller
@@ -1357,15 +1357,12 @@ hidden void *__tls_get_new(tls_mod_off_t *v)
struct dso *p;
for (p=head; p->tls_id != v[0]; p=p->next);
- /* Get new DTV space from new DSO if needed */
- if (v[0] > (size_t)self->dtv[0]) {
- void **newdtv = p->new_dtv +
- (v[0]+1)*a_fetch_add(&p->new_dtv_idx,1);
- memcpy(newdtv, self->dtv,
- ((size_t)self->dtv[0]+1) * sizeof(void *));
- newdtv[0] = (void *)v[0];
- self->dtv = self->dtv_copy = newdtv;
- }
+ /* Get new DTV space from new DSO */
+ uintptr_t *newdtv = p->new_dtv +
+ (v[0]+1)*a_fetch_add(&p->new_dtv_idx,1);
+ memcpy(newdtv, self->dtv, (self->dtv[0]+1) * sizeof(uintptr_t));
+ newdtv[0] = v[0];
+ self->dtv = self->dtv_copy = newdtv;
/* Get new TLS memory from all new DSOs up to the requested one */
unsigned char *mem;
@@ -1375,7 +1372,7 @@ hidden void *__tls_get_new(tls_mod_off_t *v)
* a_fetch_add(&p->new_tls_idx,1);
mem += ((uintptr_t)p->tls.image - (uintptr_t)mem)
& (p->tls.align-1);
- self->dtv[p->tls_id] = mem;
+ self->dtv[p->tls_id] = (uintptr_t)mem + DTP_OFFSET;
memcpy(mem, p->tls.image, p->tls.len);
if (p->tls_id == v[0]) break;
}
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index 96d0e284..842886f6 100644
--- a/src/env/__init_tls.c
+++ b/src/env/__init_tls.c
@@ -36,32 +36,32 @@ void *__copy_tls(unsigned char *mem)
pthread_t td;
struct tls_module *p;
size_t i;
- void **dtv;
+ uintptr_t *dtv;
#ifdef TLS_ABOVE_TP
- dtv = (void **)(mem + libc.tls_size) - (libc.tls_cnt + 1);
+ dtv = (uintptr_t*)(mem + libc.tls_size) - (libc.tls_cnt + 1);
mem += -((uintptr_t)mem + sizeof(struct pthread)) & (libc.tls_align-1);
td = (pthread_t)mem;
mem += sizeof(struct pthread);
for (i=1, p=libc.tls_head; p; i++, p=p->next) {
- dtv[i] = mem + p->offset;
- memcpy(dtv[i], p->image, p->len);
+ dtv[i] = (uintptr_t)(mem + p->offset) + DTP_OFFSET;
+ memcpy(mem + p->offset, p->image, p->len);
}
#else
- dtv = (void **)mem;
+ dtv = (uintptr_t *)mem;
mem += libc.tls_size - sizeof(struct pthread);
mem -= (uintptr_t)mem & (libc.tls_align-1);
td = (pthread_t)mem;
for (i=1, p=libc.tls_head; p; i++, p=p->next) {
- dtv[i] = mem - p->offset;
- memcpy(dtv[i], p->image, p->len);
+ dtv[i] = (uintptr_t)(mem - p->offset) + DTP_OFFSET;
+ memcpy(mem - p->offset, p->image, p->len);
}
#endif
- dtv[0] = (void *)libc.tls_cnt;
+ dtv[0] = libc.tls_cnt;
td->dtv = td->dtv_copy = dtv;
return td;
}
diff --git a/src/env/__reset_tls.c b/src/env/__reset_tls.c
index 677e57f5..15685bc6 100644
--- a/src/env/__reset_tls.c
+++ b/src/env/__reset_tls.c
@@ -6,11 +6,10 @@ void __reset_tls()
{
pthread_t self = __pthread_self();
struct tls_module *p;
- size_t i, n = (size_t)self->dtv[0];
+ size_t i, n = self->dtv[0];
if (n) for (p=libc.tls_head, i=1; i<=n; i++, p=p->next) {
- if (!self->dtv[i]) continue;
- memcpy(self->dtv[i], p->image, p->len);
- memset((char *)self->dtv[i]+p->len, 0,
- p->size - p->len);
+ char *mem = (char *)(self->dtv[i] - DTP_OFFSET);
+ memcpy(mem, p->image, p->len);
+ memset(mem+p->len, 0, p->size - p->len);
}
}
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index d491f975..7a25b88e 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -17,7 +17,8 @@ struct pthread {
/* Part 1 -- these fields may be external or
* internal (accessed via asm) ABI. Do not change. */
struct pthread *self;
- void **dtv, *unused1, *unused2;
+ uintptr_t *dtv;
+ void *unused1, *unused2;
uintptr_t sysinfo;
uintptr_t canary, canary2;
@@ -54,7 +55,7 @@ struct pthread {
/* Part 3 -- the positions of these fields relative to
* the end of the structure is external and internal ABI. */
uintptr_t canary_at_end;
- void **dtv_copy;
+ uintptr_t *dtv_copy;
};
struct start_sched_args {
diff --git a/src/thread/__tls_get_addr.c b/src/thread/__tls_get_addr.c
index 34fbc46c..d7afdabd 100644
--- a/src/thread/__tls_get_addr.c
+++ b/src/thread/__tls_get_addr.c
@@ -4,8 +4,8 @@
void *__tls_get_addr(tls_mod_off_t *v)
{
pthread_t self = __pthread_self();
- if (v[0]<=(size_t)self->dtv[0])
- return (char *)self->dtv[v[0]]+v[1]+DTP_OFFSET;
+ if (v[0] <= self->dtv[0])
+ return (void *)(self->dtv[v[0]] + v[1]);
return __tls_get_new(v);
}