diff options
| -rw-r--r-- | src/ldso/dynlink.c | 22 | 
1 files changed, 14 insertions, 8 deletions
| diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 66bca506..2b6f0c94 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1034,13 +1034,13 @@ void *__copy_tls(unsigned char *mem)  void *__tls_get_addr(size_t *v)  {  	pthread_t self = __pthread_self(); -	if (v[0]<=(size_t)self->dtv[0] && self->dtv[v[0]]) +	if (v[0]<=(size_t)self->dtv[0])  		return (char *)self->dtv[v[0]]+v[1];  	/* Block signals to make accessing new TLS async-signal-safe */  	sigset_t set;  	pthread_sigmask(SIG_BLOCK, SIGALL_SET, &set); -	if (v[0]<=(size_t)self->dtv[0] && self->dtv[v[0]]) { +	if (v[0]<=(size_t)self->dtv[0]) {  		pthread_sigmask(SIG_SETMASK, &set, 0);  		return (char *)self->dtv[v[0]]+v[1];  	} @@ -1062,12 +1062,18 @@ void *__tls_get_addr(size_t *v)  		self->dtv = newdtv;  	} -	/* Get new TLS memory from new DSO */ -	unsigned char *mem = p->new_tls + -		(p->tls_size + p->tls_align) * a_fetch_add(&p->new_tls_idx,1); -	mem += ((uintptr_t)p->tls_image - (uintptr_t)mem) & (p->tls_align-1); -	self->dtv[v[0]] = mem; -	memcpy(mem, p->tls_image, p->tls_len); +	/* Get new TLS memory from all new DSOs up to the requested one */ +	unsigned char *mem; +	for (p=head; ; p=p->next) { +		if (!p->tls_id || self->dtv[p->tls_id]) continue; +		mem = p->new_tls + (p->tls_size + p->tls_align) +			* 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; +		memcpy(mem, p->tls_image, p->tls_len); +		if (p->tls_id == v[0]) break; +	}  	pthread_sigmask(SIG_SETMASK, &set, 0);  	return mem + v[1];  } | 
