diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ldso/dynlink.c | 31 | 
1 files changed, 23 insertions, 8 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index b049142b..31f59392 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1159,7 +1159,15 @@ _Noreturn void __dls3(size_t *sp)  	char **argv = (void *)(sp+1);  	char **argv_orig = argv;  	char **envp = argv+argc+1; -	void *initial_tls; + +	/* Setup early thread pointer in builtin_tls for ldso/libc itself to +	 * use during dynamic linking. If possible it will also serve as the +	 * thread pointer at runtime. */ +	libc.tls_size = sizeof builtin_tls; +	if (__init_tp(__copy_tls((void *)builtin_tls)) < 0) { +		dprintf(2, "%s: Thread-local storage not supported by kernel.\n", argv[0]); +		_exit(127); +	}  	/* Find aux vector just past environ[] */  	for (i=argc+1; argv[i]; i++) @@ -1336,19 +1344,26 @@ _Noreturn void __dls3(size_t *sp)  	reloc_all(&app);  	update_tls_size(); -	if (libc.tls_size > sizeof builtin_tls) { -		initial_tls = calloc(libc.tls_size, 1); +	if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) { +		void *initial_tls = calloc(libc.tls_size, 1);  		if (!initial_tls) {  			dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",  				argv[0], libc.tls_size);  			_exit(127);  		} +		if (__init_tp(__copy_tls(initial_tls)) < 0) { +			dprintf(2, "%s: Failed to switch to new thread pointer.\n", argv[0]); +			_exit(127); +		}  	} else { -		initial_tls = builtin_tls; -	} -	if (__init_tp(__copy_tls(initial_tls)) < 0 && tls_cnt) { -		dprintf(2, "%s: Thread-local storage not supported by kernel.\n", argv[0]); -		_exit(127); +		size_t tmp_tls_size = libc.tls_size; +		pthread_t self = __pthread_self(); +		/* Temporarily set the tls size to the full size of +		 * builtin_tls so that __copy_tls will use the same layout +		 * as it did for before. Then check, just to be safe. */ +		libc.tls_size = sizeof builtin_tls; +		if (__copy_tls((void*)builtin_tls) != self) a_crash(); +		libc.tls_size = tmp_tls_size;  	}  	static_tls_cnt = tls_cnt;  | 
