Module Name:    src
Committed By:   skrll
Date:           Sun Feb  4 21:49:51 UTC 2018

Modified Files:
        src/libexec/ld.elf_so/arch/aarch64: mdreloc.c rtld_start.S

Log Message:
Various fixes / changes from Ryo Shimizu / Toru Nishimura to make this
work.

_rtld_call_ifunc copied from other rela platforms by me - not tested in
any way.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
cvs rdiff -u -r1.1 -r1.2 src/libexec/ld.elf_so/arch/aarch64/rtld_start.S

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.6 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.7
--- src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.6	Mon Aug 28 06:59:25 2017
+++ src/libexec/ld.elf_so/arch/aarch64/mdreloc.c	Sun Feb  4 21:49:51 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.6 2017/08/28 06:59:25 nisimura Exp $ */
+/* $NetBSD: mdreloc.c,v 1.7 2018/02/04 21:49:51 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.6 2017/08/28 06:59:25 nisimura Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.7 2018/02/04 21:49:51 skrll Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -43,6 +43,7 @@ __RCSID("$NetBSD: mdreloc.c,v 1.6 2017/0
 void _rtld_bind_start(void);
 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
 Elf_Addr _rtld_bind(const Obj_Entry *, Elf_Word);
+void *_rtld_tlsdesc(void *);
 
 /*
  * AARCH64 PLT looks like this;
@@ -81,23 +82,23 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
 void
 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
 {
-	const Elf_Rel *rel = 0, *rellim;
-	Elf_Addr relsz = 0;
+	const Elf_Rela *rela = 0, *relalim;
+	Elf_Addr relasz = 0;
 	Elf_Addr *where;
 
 	for (; dynp->d_tag != DT_NULL; dynp++) {
 		switch (dynp->d_tag) {
-		case DT_REL:
-			rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
+		case DT_RELA:
+			rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
 			break;
-		case DT_RELSZ:
-			relsz = dynp->d_un.d_val;
+		case DT_RELASZ:
+			relasz = dynp->d_un.d_val;
 			break;
 		}
 	}
-	rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz);
-	for (; rel < rellim; rel++) {
-		where = (Elf_Addr *)(relocbase + rel->r_offset);
+	relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+	for (; rela < relalim; rela++) {
+		where = (Elf_Addr *)(relocbase + rela->r_offset);
 		*where += (Elf_Addr)relocbase;
 	}
 }
@@ -117,8 +118,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 
 		switch (ELF_R_TYPE(rela->r_info)) {
-		case R_TYPE(ABS64):	/* word B + S + A */
-		case R_TYPE(GLOB_DAT):	/* word B + S */
+		case R_TYPE(ABS64):	/* word S + A */
+		case R_TYPE(GLOB_DAT):	/* word S + A */
 		case R_TLS_TYPE(TLS_DTPREL):
 		case R_TLS_TYPE(TLS_DTPMOD):
 		case R_TLS_TYPE(TLS_TPREL):
@@ -139,8 +140,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		case R_TYPE(NONE):
 			break;
 
-		case R_TYPE(ABS64):	/* word B + S + A */
-		case R_TYPE(GLOB_DAT):	/* word B + S */
+		case R_TYPE(ABS64):	/* word S + A */
+		case R_TYPE(GLOB_DAT):	/* word S + A */
 			tmp = (Elf_Addr)defobj->relocbase + def->st_value +
 			    rela->r_addend;
 			if (*where != tmp)
@@ -225,28 +226,61 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
 	if (!obj->relocbase)
 		return 0;
 
-	for (const Elf_Rel *rel = obj->pltrel; rel < obj->pltrellim; rel++) {
-		Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	for (const Elf_Rela *rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+		Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 
-		assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT));
+		assert((ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)) ||
+		    (ELF_R_TYPE(rela->r_info) == R_TYPE(TLSDESC)));
 
-		/* Just relocate the GOT slots pointing into the PLT */
-		*where += (Elf_Addr)obj->relocbase;
-		rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(JUMP_SLOT):
+			/* Just relocate the GOT slots pointing into the PLT */
+			*where += (Elf_Addr)obj->relocbase;
+			rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+			break;
+		case R_TYPE(TLSDESC):
+			assert(ELF_R_SYM(rela->r_info) == 0);	/* XXX */
+			if (ELF_R_SYM(rela->r_info) == 0) {
+				where[0] = (Elf_Addr)_rtld_tlsdesc;
+				where[1] = obj->tlsoffset + rela->r_addend + sizeof(struct tls_tcb);
+			}
+			break;
+		}
 	}
 
 	return 0;
 }
 
+void
+_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
+{
+	const Elf_Rela *rela;
+	Elf_Addr *where, target;
+
+	while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
+		rela = obj->pltrelalim - obj->ifunc_remaining;
+		--obj->ifunc_remaining;
+		if (ELF_R_TYPE(rela->r_info) == R_TYPE(IRELATIVE)) {
+			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+			target = (Elf_Addr)(obj->relocbase + rela->r_addend);
+			_rtld_exclusive_exit(mask);
+			target = _rtld_resolve_ifunc2(obj, target);
+			_rtld_exclusive_enter(mask);
+			if (*where != target)
+				*where = target;
+		}
+	}
+}
+
 static int
-_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
 	Elf_Addr *tp)
 {
-	Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 	Elf_Addr new_value;
 	const Elf_Sym  *def;
 	const Obj_Entry *defobj;
-	unsigned long info = rel->r_info;
+	unsigned long info = rela->r_info;
 
 	assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT));
 
@@ -274,13 +308,13 @@ _rtld_relocate_plt_object(const Obj_Entr
 }
 
 Elf_Addr
-_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+_rtld_bind(const Obj_Entry *obj, Elf_Word relaidx)
 {
-	const Elf_Rel *rel = obj->pltrel + reloff;
-	Elf_Addr new_value = 0;	/* XXX gcc */
+	const Elf_Rela *rela = obj->pltrela + relaidx;
+	Elf_Addr new_value;
 
 	_rtld_shared_enter();
-	int err = _rtld_relocate_plt_object(obj, rel, &new_value);
+	int err = _rtld_relocate_plt_object(obj, rela, &new_value);
 	if (err)
 		_rtld_die();
 	_rtld_shared_exit();
@@ -290,11 +324,11 @@ _rtld_bind(const Obj_Entry *obj, Elf_Wor
 int
 _rtld_relocate_plt_objects(const Obj_Entry *obj)
 {
-	const Elf_Rel *rel;
+	const Elf_Rela *rela;
 	int err = 0;
 	
-	for (rel = obj->pltrel; rel < obj->pltrellim; rel++) {
-		err = _rtld_relocate_plt_object(obj, rel, NULL);
+	for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+		err = _rtld_relocate_plt_object(obj, rela, NULL);
 		if (err)
 			break;
 	}

Index: src/libexec/ld.elf_so/arch/aarch64/rtld_start.S
diff -u src/libexec/ld.elf_so/arch/aarch64/rtld_start.S:1.1 src/libexec/ld.elf_so/arch/aarch64/rtld_start.S:1.2
--- src/libexec/ld.elf_so/arch/aarch64/rtld_start.S:1.1	Sun Aug 10 05:47:37 2014
+++ src/libexec/ld.elf_so/arch/aarch64/rtld_start.S	Sun Feb  4 21:49:51 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld_start.S,v 1.1 2014/08/10 05:47:37 matt Exp $ */
+/* $NetBSD: rtld_start.S,v 1.2 2018/02/04 21:49:51 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <machine/asm.h>
 
-RCSID("$NetBSD: rtld_start.S,v 1.1 2014/08/10 05:47:37 matt Exp $")
+RCSID("$NetBSD: rtld_start.S,v 1.2 2018/02/04 21:49:51 skrll Exp $")
 
 /*
  * void _rtld_start(void (*cleanup)(void), const Obj_Entry *obj,
@@ -43,28 +43,23 @@ RCSID("$NetBSD: rtld_start.S,v 1.1 2014/
  * X30 (LR)	= 0
  * X29 (FP)	= 0
  */
-
 ENTRY_NP(_rtld_start)
 	mov	x24, x2			/* save ps_strings */
 
-#if 1
-	adrp	x1, _PROCEDURE_LINKAGE_TABLE_	/* load _DYNAMIC offset from GOT */
-	ldr	x1, [x1, #:got_lo12:_PROCEDURE_LINKAGE_TABLE_]
-#else
 	adrp	x1, :got:_DYNAMIC	/* load _DYNAMIC offset from GOT */
 	ldr	x1, [x1, #:got_lo12:_DYNAMIC]
-#endif
 
 	adrp	x0, _DYNAMIC		/* get &_DYNAMIC */
 	add	x0, x0, #:lo12:_DYNAMIC
+
 	sub	x25, x0, x1		/* relocbase = &_DYNAMIC - GOT:_DYNAMIC */
 	mov	x1, x25			/* pass as 2nd argument */
-	bl	_rtld_relocate_nonplt_self
+	bl	_C_LABEL(_rtld_relocate_nonplt_self)
 
 	sub	sp, sp, #16		/* reserve space for returns */
 	mov	x0, sp			/* pointer to reserved space */
 	mov	x1, x25			/* pass relocbase */
-	bl	_rtld
+	bl	_C_LABEL(_rtld)
 	mov	x17, x0			/* save entry point */
 
 	ldp	x0, x1, [sp], #16	/* pop cleanup & obj_main */
@@ -75,34 +70,54 @@ END(_rtld_start)
 
 /*
  * Upon entry from plt0 entry:
- * X17 = &PLTGOT[n]
- * X16 = &PLTGOT[2]
+ *
+ * SP+0		= &PLTGOT[n + 3]
+ * SP+8		= return addr
+ * X16		= &PLTGOT[2]
  */
 ENTRY_NP(_rtld_bind_start)
-	sub	sp, sp, #96		/* reserve stack space */
-	stp	x29, x30, [sp, #80]	/* save FP & LR */
-	add	x29, sp, #80		/* get new FP */
-	str	x24, [sp, #64]		/* save caller-saved register */
-	stp	x6, x7, [sp, #48]	/* save arguments */
-	stp	x4, x5, [sp, #32]	/* save arguments */
-	stp	x2, x3, [sp, #16]	/* save arguments */
-	stp	x0, x1, [sp, #0]	/* save arguments */
-
-	sub	x16, x16, #16		/* adjust to &PLTGOT[0] */
-	mov	x24, x17		/* preserve across _rtld_bind */
-	sub	x1, x17, x16		/* x1 = &PLTGOT[N] - &PLTGOT[2] */
-	lsr	x1, x1, #3		/* x1 = N - 2 */
-	ldr	x0, [x16, #8]		/* get obj ptr from &PLTGOT[1] */
-	bl	_rtld_bind
-	str	x0, [x24]		/* save address in PLTGOT[N] */
-	mov	x17, x0			/* save address */
-
-	ldp	x0, x1, [sp, #0]	/* restore arguments */
-	ldp	x2, x3, [sp, #16]	/* restore arguments */
-	ldp	x4, x5, [sp, #32]	/* restore arguments */
-	ldp	x6, x7, [sp, #48]	/* restore arguments */
-	ldr	x24, [sp, #64]		/* save caller-saved register */
-	ldp	x29, x30, [sp, #80]	/* restore FP & LR */
-	add	sp, sp, #96		/* reclaim stack */
+	ldr	x9, [sp]		/* x9 = &PLTGOT[n+3] */
+
+	/* save x0-x8 for arguments */
+	stp	x0, x1, [sp, #-16]!
+	stp	x2, x3, [sp, #-16]!
+	stp	x4, x5, [sp, #-16]!
+	stp	x6, x7, [sp, #-16]!
+	stp	x8, xzr, [sp, #-16]!
+
+	/* save q0-q7 for arguments */
+	stp	q0, q1, [sp, #-32]!
+	stp	q2, q3, [sp, #-32]!
+	stp	q4, q5, [sp, #-32]!
+	stp	q6, q7, [sp, #-32]!
+
+	ldr	x0, [x16, #-8]	/* x0 = PLTGOT[1] */
+	sub	x1, x9, x16	/* x1 = &PLTGOT[n+3] - &PLTGOT[1] = offset+8 */
+	sub	x1, x1, #8	/* x1 = offset */
+	lsr	x1, x1, #3	/* x1 /= sizeof(void *) */
+
+	bl	_C_LABEL(_rtld_bind)
+	mov	x17, x0		/* save result */
+
+	/* restore q0-q7 for arguments */
+	ldp	q6, q7, [sp], #32
+	ldp	q4, q5, [sp], #32
+	ldp	q2, q3, [sp], #32
+	ldp	q0, q1, [sp], #32
+
+	/* restore x0-x8 for arguments */
+	ldp	x8, xzr, [sp], #16
+	ldp	x6, x7, [sp], #16
+	ldp	x4, x5, [sp], #16
+	ldp	x2, x3, [sp], #16
+	ldp	x0, x1, [sp], #16
+
+	ldp	xzr, lr, [sp], #16	/* restore original lr pushed by plt0 */
 	br	x17			/* call bound function */
 END(_rtld_bind_start)
+
+
+ENTRY(_rtld_tlsdesc)
+	ldr	x0, [x0, #8]
+	ret
+END(_rtld_tlsdesc)

Reply via email to