Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so/arch/aarch64 Various fixes / changes from ...
details: https://anonhg.NetBSD.org/src/rev/573c1718439b
branches: trunk
changeset: 359215:573c1718439b
user: skrll <skrll%NetBSD.org@localhost>
date: Sun Feb 04 21:49:51 2018 +0000
description:
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.
diffstat:
libexec/ld.elf_so/arch/aarch64/mdreloc.c | 98 +++++++++++++++++++---------
libexec/ld.elf_so/arch/aarch64/rtld_start.S | 85 ++++++++++++++----------
2 files changed, 116 insertions(+), 67 deletions(-)
diffs (truncated from 316 to 300 lines):
diff -r 146e804c00e3 -r 573c1718439b libexec/ld.elf_so/arch/aarch64/mdreloc.c
--- a/libexec/ld.elf_so/arch/aarch64/mdreloc.c Sun Feb 04 20:38:41 2018 +0000
+++ b/libexec/ld.elf_so/arch/aarch64/mdreloc.c Sun Feb 04 21:49:51 2018 +0000
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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(rela->r_info) == R_TYPE(JUMP_SLOT)) ||
+ (ELF_R_TYPE(rela->r_info) == R_TYPE(TLSDESC)));
- assert(ELF_R_TYPE(rel->r_info) == 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));
+ 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 @@
}
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 @@
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;
}
diff -r 146e804c00e3 -r 573c1718439b libexec/ld.elf_so/arch/aarch64/rtld_start.S
--- a/libexec/ld.elf_so/arch/aarch64/rtld_start.S Sun Feb 04 20:38:41 2018 +0000
+++ b/libexec/ld.elf_so/arch/aarch64/rtld_start.S Sun Feb 04 21:49:51 2018 +0000
@@ -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 @@
* 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 @@
/*
* 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 */
+ 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]!
- 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 */
+ 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 */
- 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 */
+ /* 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
+
Home |
Main Index |
Thread Index |
Old Index