diff options
Diffstat (limited to 'src/ldso')
-rw-r--r-- | src/ldso/__dlsym.c | 4 | ||||
-rw-r--r-- | src/ldso/aarch64/tlsdesc.s | 23 | ||||
-rw-r--r-- | src/ldso/arm/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/arm/tlsdesc.S | 6 | ||||
-rw-r--r-- | src/ldso/dl_iterate_phdr.c | 3 | ||||
-rw-r--r-- | src/ldso/dlerror.c | 44 | ||||
-rw-r--r-- | src/ldso/i386/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/i386/tlsdesc.s | 2 | ||||
-rw-r--r-- | src/ldso/loongarch64/dlsym.s | 7 | ||||
-rw-r--r-- | src/ldso/m68k/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/microblaze/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/mips/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/mipsn32/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/or1k/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/powerpc/dlsym.s | 1 | ||||
-rw-r--r-- | src/ldso/powerpc/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/powerpc64/dlsym.s | 1 | ||||
-rw-r--r-- | src/ldso/riscv32/dlsym.s | 6 | ||||
-rw-r--r-- | src/ldso/riscv64/dlsym.s | 6 | ||||
-rw-r--r-- | src/ldso/riscv64/tlsdesc.s | 32 | ||||
-rw-r--r-- | src/ldso/sh/dlsym.s | 2 | ||||
-rw-r--r-- | src/ldso/sh/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/x86_64/tlsdesc.s | 2 |
23 files changed, 125 insertions, 41 deletions
diff --git a/src/ldso/__dlsym.c b/src/ldso/__dlsym.c index 8ac0a334..0384f97e 100644 --- a/src/ldso/__dlsym.c +++ b/src/ldso/__dlsym.c @@ -8,3 +8,7 @@ static void *stub_dlsym(void *restrict p, const char *restrict s, void *restrict } weak_alias(stub_dlsym, __dlsym); + +#if _REDIR_TIME64 +weak_alias(stub_dlsym, __dlsym_redir_time64); +#endif diff --git a/src/ldso/aarch64/tlsdesc.s b/src/ldso/aarch64/tlsdesc.s index c91baa45..c6c685b3 100644 --- a/src/ldso/aarch64/tlsdesc.s +++ b/src/ldso/aarch64/tlsdesc.s @@ -9,30 +9,23 @@ __tlsdesc_static: ldr x0,[x0,#8] ret -.hidden __tls_get_new - // size_t __tlsdesc_dynamic(size_t *a) // { // struct {size_t modidx,off;} *p = (void*)a[1]; // size_t *dtv = *(size_t**)(tp - 8); -// if (p->modidx <= dtv[0]) -// return dtv[p->modidx] + p->off - tp; -// return __tls_get_new(p) - tp; +// return dtv[p->modidx] + p->off - tp; // } .global __tlsdesc_dynamic .hidden __tlsdesc_dynamic .type __tlsdesc_dynamic,@function __tlsdesc_dynamic: - stp x1,x2,[sp,#-32]! - stp x3,x4,[sp,#16] + stp x1,x2,[sp,#-16]! mrs x1,tpidr_el0 // tp ldr x0,[x0,#8] // p - ldr x2,[x0] // p->modidx - ldr x3,[x1,#-8] // dtv - ldr x2,[x3,x2,lsl #3] // dtv[p->modidx] - ldr x0,[x0,#8] // p->off - add x0,x0,x2 - sub x0,x0,x1 - ldp x3,x4,[sp,#16] - ldp x1,x2,[sp],#32 + ldp x0,x2,[x0] // p->modidx, p->off + sub x2,x2,x1 // p->off - tp + ldr x1,[x1,#-8] // dtv + ldr x1,[x1,x0,lsl #3] // dtv[p->modidx] + add x0,x1,x2 // dtv[p->modidx] + p->off - tp + ldp x1,x2,[sp],#16 ret diff --git a/src/ldso/arm/dlsym_time64.S b/src/ldso/arm/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/arm/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/arm/tlsdesc.S b/src/ldso/arm/tlsdesc.S index 455eac1d..3ae133c9 100644 --- a/src/ldso/arm/tlsdesc.S +++ b/src/ldso/arm/tlsdesc.S @@ -8,8 +8,6 @@ __tlsdesc_static: ldr r0,[r0] bx lr -.hidden __tls_get_new - .global __tlsdesc_dynamic .hidden __tlsdesc_dynamic .type __tlsdesc_dynamic,%function @@ -30,7 +28,11 @@ __tlsdesc_dynamic: #if __ARM_ARCH >= 5 blx r0 // r0 = tp #else +#if __thumb__ + add lr,pc,#1 +#else mov lr,pc +#endif bx r0 #endif #endif diff --git a/src/ldso/dl_iterate_phdr.c b/src/ldso/dl_iterate_phdr.c index 86c87ef8..9546dd36 100644 --- a/src/ldso/dl_iterate_phdr.c +++ b/src/ldso/dl_iterate_phdr.c @@ -1,5 +1,6 @@ #include <elf.h> #include <link.h> +#include "pthread_impl.h" #include "libc.h" #define AUX_CNT 38 @@ -35,7 +36,7 @@ static int static_dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size info.dlpi_subs = 0; if (tls_phdr) { info.dlpi_tls_modid = 1; - info.dlpi_tls_data = (void *)(base + tls_phdr->p_vaddr); + info.dlpi_tls_data = __tls_get_addr((tls_mod_off_t[]){1,0}); } else { info.dlpi_tls_modid = 0; info.dlpi_tls_data = 0; diff --git a/src/ldso/dlerror.c b/src/ldso/dlerror.c index 3fcc7779..dae0f3a9 100644 --- a/src/ldso/dlerror.c +++ b/src/ldso/dlerror.c @@ -3,7 +3,12 @@ #include <stdarg.h> #include "pthread_impl.h" #include "dynlink.h" -#include "lock.h" +#include "atomic.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc __libc_realloc +#define free __libc_free char *dlerror() { @@ -17,30 +22,37 @@ char *dlerror() return s; } -static volatile int freebuf_queue_lock[1]; -static void **freebuf_queue; +/* Atomic singly-linked list, used to store list of thread-local dlerror + * buffers for deferred free. They cannot be freed at thread exit time + * because, by the time it's known they can be freed, the exiting thread + * is in a highly restrictive context where it cannot call (even the + * libc-internal) free. It also can't take locks; thus the atomic list. */ + +static void *volatile freebuf_queue; void __dl_thread_cleanup(void) { pthread_t self = __pthread_self(); - if (self->dlerror_buf && self->dlerror_buf != (void *)-1) { - LOCK(freebuf_queue_lock); - void **p = (void **)self->dlerror_buf; - *p = freebuf_queue; - freebuf_queue = p; - UNLOCK(freebuf_queue_lock); - } + if (!self->dlerror_buf || self->dlerror_buf == (void *)-1) + return; + void *h; + do { + h = freebuf_queue; + *(void **)self->dlerror_buf = h; + } while (a_cas_p(&freebuf_queue, h, self->dlerror_buf) != h); } hidden void __dl_vseterr(const char *fmt, va_list ap) { - LOCK(freebuf_queue_lock); - while (freebuf_queue) { - void **p = freebuf_queue; - freebuf_queue = *p; - free(p); + void **q; + do q = freebuf_queue; + while (q && a_cas_p(&freebuf_queue, q, 0) != q); + + while (q) { + void **p = *q; + free(q); + q = p; } - UNLOCK(freebuf_queue_lock); va_list ap2; va_copy(ap2, ap); diff --git a/src/ldso/i386/dlsym_time64.S b/src/ldso/i386/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/i386/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/i386/tlsdesc.s b/src/ldso/i386/tlsdesc.s index a5c0100c..32c81766 100644 --- a/src/ldso/i386/tlsdesc.s +++ b/src/ldso/i386/tlsdesc.s @@ -6,8 +6,6 @@ __tlsdesc_static: mov 4(%eax),%eax ret -.hidden __tls_get_new - .global __tlsdesc_dynamic .hidden __tlsdesc_dynamic .type __tlsdesc_dynamic,@function diff --git a/src/ldso/loongarch64/dlsym.s b/src/ldso/loongarch64/dlsym.s new file mode 100644 index 00000000..26fabcdb --- /dev/null +++ b/src/ldso/loongarch64/dlsym.s @@ -0,0 +1,7 @@ +.global dlsym +.hidden __dlsym +.type dlsym,@function +dlsym: + move $a2, $ra + la.global $t0, __dlsym + jr $t0 diff --git a/src/ldso/m68k/dlsym_time64.S b/src/ldso/m68k/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/m68k/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/microblaze/dlsym_time64.S b/src/ldso/microblaze/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/microblaze/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/mips/dlsym_time64.S b/src/ldso/mips/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/mips/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/mipsn32/dlsym_time64.S b/src/ldso/mipsn32/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/mipsn32/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/or1k/dlsym_time64.S b/src/ldso/or1k/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/or1k/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/powerpc/dlsym.s b/src/ldso/powerpc/dlsym.s index 357d5771..cfe308ef 100644 --- a/src/ldso/powerpc/dlsym.s +++ b/src/ldso/powerpc/dlsym.s @@ -5,5 +5,4 @@ dlsym: mflr 5 # The return address is arg3. b __dlsym - .end dlsym .size dlsym, .-dlsym diff --git a/src/ldso/powerpc/dlsym_time64.S b/src/ldso/powerpc/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/powerpc/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/powerpc64/dlsym.s b/src/ldso/powerpc64/dlsym.s index 7eb691d9..a14715fd 100644 --- a/src/ldso/powerpc64/dlsym.s +++ b/src/ldso/powerpc64/dlsym.s @@ -8,5 +8,4 @@ dlsym: .localentry dlsym,.-dlsym mflr 5 # The return address is arg3. b __dlsym - .end dlsym .size dlsym, .-dlsym diff --git a/src/ldso/riscv32/dlsym.s b/src/ldso/riscv32/dlsym.s new file mode 100644 index 00000000..2bafd72d --- /dev/null +++ b/src/ldso/riscv32/dlsym.s @@ -0,0 +1,6 @@ +.global dlsym +.hidden __dlsym +.type dlsym, %function +dlsym: + mv a2, ra + tail __dlsym diff --git a/src/ldso/riscv64/dlsym.s b/src/ldso/riscv64/dlsym.s new file mode 100644 index 00000000..2bafd72d --- /dev/null +++ b/src/ldso/riscv64/dlsym.s @@ -0,0 +1,6 @@ +.global dlsym +.hidden __dlsym +.type dlsym, %function +dlsym: + mv a2, ra + tail __dlsym diff --git a/src/ldso/riscv64/tlsdesc.s b/src/ldso/riscv64/tlsdesc.s new file mode 100644 index 00000000..bef8b322 --- /dev/null +++ b/src/ldso/riscv64/tlsdesc.s @@ -0,0 +1,32 @@ +.text +.global __tlsdesc_static +.hidden __tlsdesc_static +.type __tlsdesc_static,%function +__tlsdesc_static: + ld a0,8(a0) + jr t0 + +.global __tlsdesc_dynamic +.hidden __tlsdesc_dynamic +.type __tlsdesc_dynamic,%function +__tlsdesc_dynamic: + add sp,sp,-16 + sd t1,(sp) + sd t2,8(sp) + + ld t2,-8(tp) # t2=dtv + + ld a0,8(a0) # a0=&{modidx,off} + ld t1,8(a0) # t1=off + ld a0,(a0) # a0=modidx + sll a0,a0,3 # a0=8*modidx + + add a0,a0,t2 # a0=dtv+8*modidx + ld a0,(a0) # a0=dtv[modidx] + add a0,a0,t1 # a0=dtv[modidx]+off + sub a0,a0,tp # a0=dtv[modidx]+off-tp + + ld t1,(sp) + ld t2,8(sp) + add sp,sp,16 + jr t0 diff --git a/src/ldso/sh/dlsym.s b/src/ldso/sh/dlsym.s index 11a6fff5..34f3c35c 100644 --- a/src/ldso/sh/dlsym.s +++ b/src/ldso/sh/dlsym.s @@ -5,7 +5,7 @@ dlsym: mov.l L1, r0 1: braf r0 - mov.l @r15, r6 + sts pr, r6 .align 2 L1: .long __dlsym@PLT-(1b+4-.) diff --git a/src/ldso/sh/dlsym_time64.S b/src/ldso/sh/dlsym_time64.S new file mode 100644 index 00000000..bb2e7040 --- /dev/null +++ b/src/ldso/sh/dlsym_time64.S @@ -0,0 +1,3 @@ +#define __dlsym __dlsym_redir_time64 +#define dlsym __dlsym_time64 +#include "dlsym.s" diff --git a/src/ldso/x86_64/tlsdesc.s b/src/ldso/x86_64/tlsdesc.s index 0151d15c..e08f1d7d 100644 --- a/src/ldso/x86_64/tlsdesc.s +++ b/src/ldso/x86_64/tlsdesc.s @@ -6,8 +6,6 @@ __tlsdesc_static: mov 8(%rax),%rax ret -.hidden __tls_get_new - .global __tlsdesc_dynamic .hidden __tlsdesc_dynamic .type __tlsdesc_dynamic,@function |