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.s23
-rw-r--r--src/ldso/arm/dlsym_time64.S3
-rw-r--r--src/ldso/arm/tlsdesc.S6
-rw-r--r--src/ldso/dl_iterate_phdr.c3
-rw-r--r--src/ldso/dlerror.c44
-rw-r--r--src/ldso/i386/dlsym_time64.S3
-rw-r--r--src/ldso/i386/tlsdesc.s2
-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.s2
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