about summary refs log tree commit diff
path: root/src/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/aarch64/dlsym.s5
-rw-r--r--src/ldso/aarch64/start.s18
-rw-r--r--src/ldso/aarch64/tlsdesc.s92
3 files changed, 115 insertions, 0 deletions
diff --git a/src/ldso/aarch64/dlsym.s b/src/ldso/aarch64/dlsym.s
new file mode 100644
index 00000000..be2dce52
--- /dev/null
+++ b/src/ldso/aarch64/dlsym.s
@@ -0,0 +1,5 @@
+.global dlsym
+.type dlsym,%function
+dlsym:
+	mov x2,x30
+	b __dlsym
diff --git a/src/ldso/aarch64/start.s b/src/ldso/aarch64/start.s
new file mode 100644
index 00000000..41d1d1e2
--- /dev/null
+++ b/src/ldso/aarch64/start.s
@@ -0,0 +1,18 @@
+.global _dlstart
+_dlstart:
+	ldr x0,[sp]
+	add x1,sp,#8
+	bl __dynlink
+	mov x1,sp
+	ldr x2,[x1],#8
+1:	sub x2,x2,1
+	ldr x3,[x1],#8
+	cmn x3,#1
+	b.eq 1b
+	add x2,x2,1
+	str x3,[x1,#-8]!
+	str x2,[x1,#-8]!
+	mov sp,x1
+	mov x1,x0
+	mov x0,#0
+	blr x1
diff --git a/src/ldso/aarch64/tlsdesc.s b/src/ldso/aarch64/tlsdesc.s
new file mode 100644
index 00000000..32064bd7
--- /dev/null
+++ b/src/ldso/aarch64/tlsdesc.s
@@ -0,0 +1,92 @@
+// long __tlsdesc_static(long *a)
+// {
+// 	return a[1];
+// }
+.global __tlsdesc_static
+.type __tlsdesc_static,@function
+__tlsdesc_static:
+	ldr x0,[x0,#8]
+	ret
+
+// long __tlsdesc_dynamic(long *a)
+// {
+// 	struct {size_t modidx,off;} *p = (void*)a[1];
+// 	size_t *dtv = *(size_t**)(tp + 16 - 8);
+// 	if (p->modidx <= dtv[0])
+// 		return dtv[p->modidx] + p->off - tp;
+// 	return __tls_get_addr(p) - tp;
+// }
+.global __tlsdesc_dynamic
+.type __tlsdesc_dynamic,@function
+__tlsdesc_dynamic:
+	stp x1,x2,[sp,#-32]!
+	stp x3,x4,[sp,#16]
+	mrs x1,tpidr_el0      // tp
+	ldr x0,[x0,#8]        // p
+	ldr x2,[x0]           // p->modidx
+	add x3,x1,#8
+	ldr x3,[x3]           // 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
+	ret
+
+	// save all registers __tls_get_addr may clobber
+	// ugly because addr 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_addr
+	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