about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ldso/dynlink.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index a124e704..7ac0bf75 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1889,13 +1889,25 @@ void __dls3(size_t *sp)
 	/* Initial TLS must also be allocated before final relocations
 	 * might result in calloc being a call to application code. */
 	update_tls_size();
+	void *initial_tls = builtin_tls;
 	if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) {
-		void *initial_tls = calloc(libc.tls_size, 1);
+		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);
 		}
+	}
+	static_tls_cnt = tls_cnt;
+
+	/* The main program must be relocated LAST since it may contain
+	 * copy relocations which depend on libraries' relocations. */
+	reloc_all(app.next);
+	reloc_all(&app);
+
+	/* Actual copying to new TLS needs to happen after relocations,
+	 * since the TLS images might have contained relocated addresses. */
+	if (initial_tls != builtin_tls) {
 		if (__init_tp(__copy_tls(initial_tls)) < 0) {
 			a_crash();
 		}
@@ -1909,12 +1921,6 @@ void __dls3(size_t *sp)
 		if (__copy_tls((void*)builtin_tls) != self) a_crash();
 		libc.tls_size = tmp_tls_size;
 	}
-	static_tls_cnt = tls_cnt;
-
-	/* The main program must be relocated LAST since it may contin
-	 * copy relocations which depend on libraries' relocations. */
-	reloc_all(app.next);
-	reloc_all(&app);
 
 	if (ldso_fail) _exit(127);
 	if (ldd_mode) _exit(0);