about summary refs log tree commit diff
path: root/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-12-31 21:59:07 -0500
committerRich Felker <dalias@aerifal.cx>2019-12-31 21:59:07 -0500
commitb82cd6c78d812d38c31febba5a9e57dbaa7919c4 (patch)
treee28a39dc038a3ae1ecdf8ecc2c50512b25d8b69f /ldso
parentb529ec9b52ff4b94e455f0e6cb1f3ef3994560d5 (diff)
downloadmusl-b82cd6c78d812d38c31febba5a9e57dbaa7919c4.tar.gz
musl-b82cd6c78d812d38c31febba5a9e57dbaa7919c4.tar.xz
musl-b82cd6c78d812d38c31febba5a9e57dbaa7919c4.zip
fix crashing ldso on archs where __set_thread_area examines auxv
commit 1c84c99913bf1cd47b866ed31e665848a0da84a2 moved the call to
__init_tp above the initialization of libc.auxv, inadvertently
breaking archs where __set_thread_area examines auxv for the sake of
determining the TLS/atomic model needed at runtime. this broke armv6
and sh2.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/dynlink.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 59176812..acd2b20a 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -107,7 +107,7 @@ struct symdef {
 	struct dso *dso;
 };
 
-typedef void (*stage3_func)(size_t *);
+typedef void (*stage3_func)(size_t *, size_t *);
 
 static struct builtin_tls {
 	char c;
@@ -1596,13 +1596,14 @@ static void install_new_tls(void)
 
 hidden void __dls2(unsigned char *base, size_t *sp)
 {
+	size_t *auxv;
+	for (auxv=sp+1+*sp+1; *auxv; auxv++);
+	auxv++;
 	if (DL_FDPIC) {
 		void *p1 = (void *)sp[-2];
 		void *p2 = (void *)sp[-1];
 		if (!p1) {
-			size_t *auxv, aux[AUX_CNT];
-			for (auxv=sp+1+*sp+1; *auxv; auxv++);
-			auxv++;
+			size_t aux[AUX_CNT];
 			decode_vec(auxv, aux, AUX_CNT);
 			if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE];
 			else ldso.base = (void *)(aux[AT_PHDR] & -4096);
@@ -1648,8 +1649,8 @@ hidden void __dls2(unsigned char *base, size_t *sp)
 	 * symbolically as a barrier against moving the address
 	 * load across the above relocation processing. */
 	struct symdef dls2b_def = find_sym(&ldso, "__dls2b", 0);
-	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls2b_def.sym-ldso.syms])(sp);
-	else ((stage3_func)laddr(&ldso, dls2b_def.sym->st_value))(sp);
+	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls2b_def.sym-ldso.syms])(sp, auxv);
+	else ((stage3_func)laddr(&ldso, dls2b_def.sym->st_value))(sp, auxv);
 }
 
 /* Stage 2b sets up a valid thread pointer, which requires relocations
@@ -1658,11 +1659,12 @@ hidden void __dls2(unsigned char *base, size_t *sp)
  * so that loads of the thread pointer and &errno can be pure/const and
  * thereby hoistable. */
 
-void __dls2b(size_t *sp)
+void __dls2b(size_t *sp, size_t *auxv)
 {
 	/* 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.auxv = auxv;
 	libc.tls_size = sizeof builtin_tls;
 	libc.tls_align = tls_align;
 	if (__init_tp(__copy_tls((void *)builtin_tls)) < 0) {
@@ -1670,8 +1672,8 @@ void __dls2b(size_t *sp)
 	}
 
 	struct symdef dls3_def = find_sym(&ldso, "__dls3", 0);
-	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls3_def.sym-ldso.syms])(sp);
-	else ((stage3_func)laddr(&ldso, dls3_def.sym->st_value))(sp);
+	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls3_def.sym-ldso.syms])(sp, auxv);
+	else ((stage3_func)laddr(&ldso, dls3_def.sym->st_value))(sp, auxv);
 }
 
 /* Stage 3 of the dynamic linker is called with the dynamic linker/libc
@@ -1679,10 +1681,10 @@ void __dls2b(size_t *sp)
  * process dependencies and relocations for the main application and
  * transfer control to its entry point. */
 
-void __dls3(size_t *sp)
+void __dls3(size_t *sp, size_t *auxv)
 {
 	static struct dso app, vdso;
-	size_t aux[AUX_CNT], *auxv;
+	size_t aux[AUX_CNT];
 	size_t i;
 	char *env_preload=0;
 	char *replace_argv0=0;
@@ -1695,8 +1697,6 @@ void __dls3(size_t *sp)
 	/* Find aux vector just past environ[] and use it to initialize
 	 * global data that may be needed before we can make syscalls. */
 	__environ = envp;
-	for (i=argc+1; argv[i]; i++);
-	libc.auxv = auxv = (void *)(argv+i+1);
 	decode_vec(auxv, aux, AUX_CNT);
 	__hwcap = aux[AT_HWCAP];
 	search_vec(auxv, &__sysinfo, AT_SYSINFO);