From b82cd6c78d812d38c31febba5a9e57dbaa7919c4 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 31 Dec 2019 21:59:07 -0500 Subject: [PATCH] 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. --- ldso/dynlink.c | 26 +++++++++++++------------- 1 file 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);