summaryrefslogtreecommitdiff
path: root/src/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/__dlsym.c4
-rw-r--r--src/ldso/aarch64/tlsdesc.s80
-rw-r--r--src/ldso/arm/dlsym_time64.S3
-rw-r--r--src/ldso/arm/tlsdesc.S25
-rw-r--r--src/ldso/dl_iterate_phdr.c3
-rw-r--r--src/ldso/dlerror.c34
-rw-r--r--src/ldso/i386/dlsym_time64.S3
-rw-r--r--src/ldso/i386/tlsdesc.s10
-rw-r--r--src/ldso/loongarch64/dlsym.s7
-rw-r--r--src/ldso/m68k/dlsym_time64.S3
-rw-r--r--src/ldso/microblaze/dlsym_time64.S3
-rw-r--r--src/ldso/mips/dlsym_time64.S3
-rw-r--r--src/ldso/mipsn32/dlsym_time64.S3
-rw-r--r--src/ldso/or1k/dlsym_time64.S3
-rw-r--r--src/ldso/powerpc/dlsym.s1
-rw-r--r--src/ldso/powerpc/dlsym_time64.S3
-rw-r--r--src/ldso/powerpc64/dlsym.s1
-rw-r--r--src/ldso/riscv32/dlsym.s6
-rw-r--r--src/ldso/riscv64/dlsym.s6
-rw-r--r--src/ldso/riscv64/tlsdesc.s32
-rw-r--r--src/ldso/sh/dlsym.s2
-rw-r--r--src/ldso/sh/dlsym_time64.S3
-rw-r--r--src/ldso/x86_64/tlsdesc.s23
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