diff options
Diffstat (limited to 'src/ldso')
-rw-r--r-- | src/ldso/__dlsym.c | 4 | ||||
-rw-r--r-- | src/ldso/aarch64/tlsdesc.s | 80 | ||||
-rw-r--r-- | src/ldso/arm/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/arm/tlsdesc.S | 25 | ||||
-rw-r--r-- | src/ldso/dl_iterate_phdr.c | 3 | ||||
-rw-r--r-- | src/ldso/dlerror.c | 34 | ||||
-rw-r--r-- | src/ldso/i386/dlsym_time64.S | 3 | ||||
-rw-r--r-- | src/ldso/i386/tlsdesc.s | 10 | ||||
-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 | 23 |
23 files changed, 131 insertions, 130 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 8e4004d7..c6c685b3 100644 --- a/src/ldso/aarch64/tlsdesc.s +++ b/src/ldso/aarch64/tlsdesc.s @@ -9,87 +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 x4,[x3] // dtv[0] - cmp x2,x4 - b.hi 1f - ldr x2,[x3,x2,lsl #3] // dtv[p->modidx] - ldr x0,[x0,#8] // p->off - add x0,x0,x2 -2: 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 - - // save all registers __tls_get_new may clobber - // update sp in two steps because offset must be in [-512,509] -1: stp x29,x30,[sp,#-160]! - stp x5,x6,[sp,#16] - stp x7,x8,[sp,#32] - stp x9,x10,[sp,#48] - stp x11,x12,[sp,#64] - stp x13,x14,[sp,#80] - stp x15,x16,[sp,#96] - stp x17,x18,[sp,#112] - stp q0,q1,[sp,#128] - stp q2,q3,[sp,#-480]! - stp q4,q5,[sp,#32] - stp q6,q7,[sp,#64] - stp q8,q9,[sp,#96] - stp q10,q11,[sp,#128] - stp q12,q13,[sp,#160] - stp q14,q15,[sp,#192] - stp q16,q17,[sp,#224] - stp q18,q19,[sp,#256] - stp q20,q21,[sp,#288] - stp q22,q23,[sp,#320] - stp q24,q25,[sp,#352] - stp q26,q27,[sp,#384] - stp q28,q29,[sp,#416] - stp q30,q31,[sp,#448] - bl __tls_get_new - mrs x1,tpidr_el0 - ldp q4,q5,[sp,#32] - ldp q6,q7,[sp,#64] - ldp q8,q9,[sp,#96] - ldp q10,q11,[sp,#128] - ldp q12,q13,[sp,#160] - ldp q14,q15,[sp,#192] - ldp q16,q17,[sp,#224] - ldp q18,q19,[sp,#256] - ldp q20,q21,[sp,#288] - ldp q22,q23,[sp,#320] - ldp q24,q25,[sp,#352] - ldp q26,q27,[sp,#384] - ldp q28,q29,[sp,#416] - ldp q30,q31,[sp,#448] - ldp q2,q3,[sp],#480 - ldp x5,x6,[sp,#16] - ldp x7,x8,[sp,#32] - ldp x9,x10,[sp,#48] - ldp x11,x12,[sp,#64] - ldp x13,x14,[sp,#80] - ldp x15,x16,[sp,#96] - ldp x17,x18,[sp,#112] - ldp q0,q1,[sp,#128] - ldp x29,x30,[sp],#160 - b 2b 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 4e67c3e2..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,18 +28,18 @@ __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 ldr r3,[r0,#-4] // r3 = dtv - ldr ip,[r3] // ip = dtv slot count - cmp r1,ip - bhi 3f ldr ip,[r3,r1,LSL #2] sub r0,ip,r0 add r0,r0,r2 // r0 = r3[r1]-r0+r2 -4: #if __ARM_ARCH >= 5 pop {r2,r3,ip,pc} #else @@ -49,21 +47,6 @@ __tlsdesc_dynamic: bx lr #endif -3: -#if __ARM_PCS_VFP || !__SOFTFP__ - .fpu vfp - vpush {d0-d7} -#endif - push {r0-r3} - add r0,sp,#4 - bl __tls_get_new - pop {r1-r3,ip} -#if __ARM_PCS_VFP || !__SOFTFP__ - vpop {d0-d7} -#endif - sub r0,r0,r1 // r0 = retval-tp - b 4b - #if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 #else 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 06ed8542..dae0f3a9 100644 --- a/src/ldso/dlerror.c +++ b/src/ldso/dlerror.c @@ -3,6 +3,12 @@ #include <stdarg.h> #include "pthread_impl.h" #include "dynlink.h" +#include "atomic.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc __libc_realloc +#define free __libc_free char *dlerror() { @@ -16,21 +22,45 @@ char *dlerror() return s; } +/* 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 != (void *)-1) - free(self->dlerror_buf); + 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) { + 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; + } + va_list ap2; va_copy(ap2, ap); pthread_t self = __pthread_self(); if (self->dlerror_buf != (void *)-1) free(self->dlerror_buf); size_t len = vsnprintf(0, 0, fmt, ap2); + if (len < sizeof(void *)) len = sizeof(void *); va_end(ap2); char *buf = malloc(len+1); if (buf) { 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 4a553bce..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 @@ -17,15 +15,9 @@ __tlsdesc_dynamic: mov %gs:4,%edx push %ecx mov (%eax),%ecx - cmp %ecx,(%edx) - jc 1f mov 4(%eax),%eax add (%edx,%ecx,4),%eax -2: pop %ecx + pop %ecx sub %gs:0,%eax pop %edx ret -1: push %eax - call __tls_get_new - pop %ecx - jmp 2b 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 8238c3eb..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 @@ -17,28 +15,9 @@ __tlsdesc_dynamic: mov %fs:8,%rdx push %rcx mov (%rax),%rcx - cmp %rcx,(%rdx) - jc 1f mov 8(%rax),%rax add (%rdx,%rcx,8),%rax -2: pop %rcx + pop %rcx sub %fs:0,%rax pop %rdx ret -1: push %rdi - push %rdi - push %rsi - push %r8 - push %r9 - push %r10 - push %r11 - mov %rax,%rdi - call __tls_get_new - pop %r11 - pop %r10 - pop %r9 - pop %r8 - pop %rsi - pop %rdi - pop %rdi - jmp 2b |