diff options
-rw-r--r-- | ldso/dynlink.c | 25 | ||||
-rw-r--r-- | src/env/__init_tls.c | 16 | ||||
-rw-r--r-- | src/env/__reset_tls.c | 9 | ||||
-rw-r--r-- | src/internal/pthread_impl.h | 5 | ||||
-rw-r--r-- | src/thread/__tls_get_addr.c | 4 |
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); } |