summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorjoerg <joerg@NetBSD.org>2018-04-03 21:10:27 +0000
committerjoerg <joerg@NetBSD.org>2018-04-03 21:10:27 +0000
commit0c16eee5b40284ce50f348c550fa5906ff794145 (patch)
tree9ce3f6800f056b3681f5bd2e8ce0a42ad566bba0 /libexec
parent6b4d1fe2e0525f1d06796cec71ac986c5bb368bd (diff)
Rework ifunc support to address a number of short comings:
- Move to a shared _rtld_call_ifunc for rel and rela architectures - Architectures using rel format must patch IRELATIVE non-PLT relocations like RELATIVE in additition to the later ifunc handling - Consistently record the delta to the end of the relocation group for non-PLT IRELATIVE relocations Hidden ifunc is now supported on all ifunc platforms, even when using -fno-plt. The combination of -fno-plt and relro is broken due to incorrect GNU ld output though.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.elf_so/arch/arm/Makefile.inc3
-rw-r--r--libexec/ld.elf_so/arch/arm/mdreloc.c30
-rw-r--r--libexec/ld.elf_so/arch/i386/Makefile.inc3
-rw-r--r--libexec/ld.elf_so/arch/i386/mdreloc.c33
-rw-r--r--libexec/ld.elf_so/arch/powerpc/Makefile.inc3
-rw-r--r--libexec/ld.elf_so/arch/powerpc/ppc_reloc.c40
-rw-r--r--libexec/ld.elf_so/arch/sparc/Makefile.inc3
-rw-r--r--libexec/ld.elf_so/arch/sparc/mdreloc.c42
-rw-r--r--libexec/ld.elf_so/arch/sparc64/Makefile.inc3
-rw-r--r--libexec/ld.elf_so/arch/sparc64/mdreloc.c44
-rw-r--r--libexec/ld.elf_so/arch/x86_64/Makefile.inc3
-rw-r--r--libexec/ld.elf_so/arch/x86_64/mdreloc.c33
-rw-r--r--libexec/ld.elf_so/reloc.c94
-rw-r--r--libexec/ld.elf_so/rtld.c6
-rw-r--r--libexec/ld.elf_so/rtld.h6
15 files changed, 155 insertions, 191 deletions
diff --git a/libexec/ld.elf_so/arch/arm/Makefile.inc b/libexec/ld.elf_so/arch/arm/Makefile.inc
index 8259e0bda77..b21be59fe9d 100644
--- a/libexec/ld.elf_so/arch/arm/Makefile.inc
+++ b/libexec/ld.elf_so/arch/arm/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.20 2013/09/10 16:35:10 matt Exp $
+# $NetBSD: Makefile.inc,v 1.21 2018/04/03 21:10:27 joerg Exp $
SRCS+= rtld_start.S mdreloc.c
#CPUFLAGS.rtld_start.S+= -marm
@@ -7,6 +7,7 @@ SRCS+= rtld_start.S mdreloc.c
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=32
+CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_REL
.if !empty(LDELFSO_MACHINE_ARCH:Mearm*)
CPPFLAGS+= -DHAVE_INITFINI_ARRAY
CPPFLAGS+= -DELF_NOTE_MARCH_DESC=\"${LDELFSO_MACHINE_ARCH}\"
diff --git a/libexec/ld.elf_so/arch/arm/mdreloc.c b/libexec/ld.elf_so/arch/arm/mdreloc.c
index e0ed6066b91..73bbd19cebe 100644
--- a/libexec/ld.elf_so/arch/arm/mdreloc.c
+++ b/libexec/ld.elf_so/arch/arm/mdreloc.c
@@ -1,8 +1,8 @@
-/* $NetBSD: mdreloc.c,v 1.43 2017/11/06 21:16:04 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.44 2018/04/03 21:10:27 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.43 2017/11/06 21:16:04 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.44 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -167,6 +167,12 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
defobj->path));
break;
+ case R_TYPE(IRELATIVE):
+ /* IFUNC relocations are handled in _rtld_call_ifunc */
+ if (obj->ifunc_remaining_nonplt == 0)
+ obj->ifunc_remaining_nonplt = obj->rellim - rel;
+ /* FALL-THROUGH */
+
case R_TYPE(RELATIVE): /* word32 B + A */
if (__predict_true(RELOC_ALIGNED_P(where))) {
tmp = *where + (Elf_Addr)obj->relocbase;
@@ -274,26 +280,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
return 0;
}
-void
-_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
-{
- const Elf_Rel *rel;
- Elf_Addr *where, target;
-
- while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
- rel = obj->pltrellim - obj->ifunc_remaining;
- --obj->ifunc_remaining;
- if (ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)) {
- where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
- _rtld_exclusive_exit(mask);
- target = _rtld_resolve_ifunc2(obj, *where);
- _rtld_exclusive_enter(mask);
- if (*where != target)
- *where = target;
- }
- }
-}
-
static int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
Elf_Addr *tp)
diff --git a/libexec/ld.elf_so/arch/i386/Makefile.inc b/libexec/ld.elf_so/arch/i386/Makefile.inc
index 14cbaedf556..710debb63e1 100644
--- a/libexec/ld.elf_so/arch/i386/Makefile.inc
+++ b/libexec/ld.elf_so/arch/i386/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.14 2009/12/13 09:31:47 mrg Exp $
+# $NetBSD: Makefile.inc,v 1.15 2018/04/03 21:10:27 joerg Exp $
SRCS+= rtld_start.S mdreloc.c
@@ -6,5 +6,6 @@ SRCS+= rtld_start.S mdreloc.c
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=32
+CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_REL
LDFLAGS+= -Wl,-e,.rtld_start
diff --git a/libexec/ld.elf_so/arch/i386/mdreloc.c b/libexec/ld.elf_so/arch/i386/mdreloc.c
index 3731e2dec88..5e3f7c959fc 100644
--- a/libexec/ld.elf_so/arch/i386/mdreloc.c
+++ b/libexec/ld.elf_so/arch/i386/mdreloc.c
@@ -1,8 +1,8 @@
-/* $NetBSD: mdreloc.c,v 1.40 2017/11/06 21:16:04 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.41 2018/04/03 21:10:27 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.40 2017/11/06 21:16:04 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.41 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -115,6 +115,15 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
obj->path, (void *)*where, defobj->path));
break;
+
+ case R_TYPE(IRELATIVE):
+ /* IFUNC relocations are handled in _rtld_call_ifunc */
+ if (obj->ifunc_remaining_nonplt == 0) {
+ obj->ifunc_remaining_nonplt =
+ obj->rellim - rel;
+ }
+ /* FALL-THROUGH */
+
case R_TYPE(RELATIVE):
*where += (Elf_Addr)obj->relocbase;
rdbg(("RELATIVE in %s --> %p", obj->path,
@@ -215,26 +224,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
return 0;
}
-void
-_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
-{
- const Elf_Rel *rel;
- Elf_Addr *where, target;
-
- while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
- rel = obj->pltrellim - obj->ifunc_remaining;
- --obj->ifunc_remaining;
- if (ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)) {
- where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
- _rtld_exclusive_exit(mask);
- target = _rtld_resolve_ifunc2(obj, *where);
- _rtld_exclusive_enter(mask);
- if (*where != target)
- *where = target;
- }
- }
-}
-
static inline int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
Elf_Addr *tp)
diff --git a/libexec/ld.elf_so/arch/powerpc/Makefile.inc b/libexec/ld.elf_so/arch/powerpc/Makefile.inc
index b12b71778de..18ac0491b2f 100644
--- a/libexec/ld.elf_so/arch/powerpc/Makefile.inc
+++ b/libexec/ld.elf_so/arch/powerpc/Makefile.inc
@@ -1,9 +1,10 @@
-# $NetBSD: Makefile.inc,v 1.15 2014/08/15 09:40:07 matt Exp $
+# $NetBSD: Makefile.inc,v 1.16 2018/04/03 21:10:27 joerg Exp $
SRCS+= ppc_reloc.c
LDFLAGS+= -Wl,-e,_rtld_start
CPPFLAGS+= -fPIC
+CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_RELA
.if ${LDELFSO_MACHINE_ARCH} == "powerpc64"
SRCS+= rtld_start64.S
diff --git a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
index a58baee2618..b37c87c6ff7 100644
--- a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
+++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ppc_reloc.c,v 1.56 2018/03/09 20:19:11 joerg Exp $ */
+/* $NetBSD: ppc_reloc.c,v 1.57 2018/04/03 21:10:27 joerg Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: ppc_reloc.c,v 1.56 2018/03/09 20:19:11 joerg Exp $");
+__RCSID("$NetBSD: ppc_reloc.c,v 1.57 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <stdarg.h>
@@ -289,7 +289,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
/* IFUNC relocations are handled in _rtld_call_ifunc */
if (obj->ifunc_remaining_nonplt == 0) {
obj->ifunc_remaining_nonplt =
- rela - obj->rela + 1;
+ obj->relalim - rela;
}
break;
@@ -371,40 +371,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
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;
- }
- }
-
- while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
- rela = obj->relalim - --obj->ifunc_remaining_nonplt;
- if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
- continue;
- 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_Rela *rela, int reloff, Elf_Addr *tp)
{
diff --git a/libexec/ld.elf_so/arch/sparc/Makefile.inc b/libexec/ld.elf_so/arch/sparc/Makefile.inc
index e13e6e0c64e..a357be7ab06 100644
--- a/libexec/ld.elf_so/arch/sparc/Makefile.inc
+++ b/libexec/ld.elf_so/arch/sparc/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.14 2009/12/13 09:31:47 mrg Exp $
+# $NetBSD: Makefile.inc,v 1.15 2018/04/03 21:10:27 joerg Exp $
SRCS+= rtld_start.S mdreloc.c
@@ -6,5 +6,6 @@ SRCS+= rtld_start.S mdreloc.c
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=32
+CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_RELA
LDFLAGS+= -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/sparc/mdreloc.c b/libexec/ld.elf_so/arch/sparc/mdreloc.c
index 53d1835e371..526c0dfa1d9 100644
--- a/libexec/ld.elf_so/arch/sparc/mdreloc.c
+++ b/libexec/ld.elf_so/arch/sparc/mdreloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.54 2018/03/29 13:23:39 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.55 2018/04/03 21:10:27 joerg Exp $ */
/*-
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.54 2018/03/29 13:23:39 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.55 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <machine/elf_support.h>
@@ -224,8 +224,10 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
/* IFUNC relocations are handled in _rtld_call_ifunc */
if (type == R_TYPE(IRELATIVE)) {
- if (obj->ifunc_remaining_nonplt == 0)
- obj->ifunc_remaining_nonplt = rela - obj->rela + 1;
+ if (obj->ifunc_remaining_nonplt == 0) {
+ obj->ifunc_remaining_nonplt =
+ obj->relalim - rela;
+ }
continue;
}
@@ -406,38 +408,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
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;
- if (ELF_R_TYPE(rela->r_info) != R_TYPE(JMP_IREL))
- continue;
- 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);
- sparc_write_branch(where + 1, (void *)target);
- }
-
- while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
- rela = obj->relalim - --obj->ifunc_remaining_nonplt;
- if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
- continue;
- 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;
- }
-}
-
caddr_t
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
diff --git a/libexec/ld.elf_so/arch/sparc64/Makefile.inc b/libexec/ld.elf_so/arch/sparc64/Makefile.inc
index a7527c02c91..f63c30f1090 100644
--- a/libexec/ld.elf_so/arch/sparc64/Makefile.inc
+++ b/libexec/ld.elf_so/arch/sparc64/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.8 2005/06/04 16:17:17 lukem Exp $
+# $NetBSD: Makefile.inc,v 1.9 2018/04/03 21:10:27 joerg Exp $
SRCS+= rtld_start.S mdreloc.c
@@ -6,5 +6,6 @@ SRCS+= rtld_start.S mdreloc.c
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=64
+CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_RELA
LDFLAGS+= -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/sparc64/mdreloc.c b/libexec/ld.elf_so/arch/sparc64/mdreloc.c
index 9c559612205..e3ea5a8808e 100644
--- a/libexec/ld.elf_so/arch/sparc64/mdreloc.c
+++ b/libexec/ld.elf_so/arch/sparc64/mdreloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.69 2018/04/03 21:10:27 joerg Exp $ */
/*-
* Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.69 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <machine/elf_support.h>
@@ -323,8 +323,10 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
/* IFUNC relocations are handled in _rtld_call_ifunc */
if (type == R_TYPE(IRELATIVE)) {
- if (obj->ifunc_remaining_nonplt == 0)
- obj->ifunc_remaining_nonplt = rela - obj->rela + 1;
+ if (obj->ifunc_remaining_nonplt == 0) {
+ obj->ifunc_remaining_nonplt =
+ obj->relalim - rela;
+ }
continue;
}
@@ -633,37 +635,3 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
return 0;
}
-
-void
-_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
-{
- const Elf_Rela *rela;
- Elf_Addr *where;
- Elf_Word *where2;
- Elf_Addr target;
-
- while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
- rela = obj->pltrelalim - --obj->ifunc_remaining;
- if (ELF_R_TYPE(rela->r_info) != R_TYPE(JMP_IREL))
- continue;
- where2 = (Elf_Word *)(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);
- sparc_write_branch(where2 + 1, (void *)target);
- }
-
- while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
- rela = obj->relalim - --obj->ifunc_remaining_nonplt;
- if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
- continue;
- 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;
- }
-}
diff --git a/libexec/ld.elf_so/arch/x86_64/Makefile.inc b/libexec/ld.elf_so/arch/x86_64/Makefile.inc
index 96d3660bbaf..c566f2df8c9 100644
--- a/libexec/ld.elf_so/arch/x86_64/Makefile.inc
+++ b/libexec/ld.elf_so/arch/x86_64/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.7 2005/06/04 16:17:17 lukem Exp $
+# $NetBSD: Makefile.inc,v 1.8 2018/04/03 21:10:27 joerg Exp $
SRCS+= rtld_start.S mdreloc.c
@@ -6,5 +6,6 @@ SRCS+= rtld_start.S mdreloc.c
CPPFLAGS+= -fPIC
CPPFLAGS+= -DELFSIZE=64
+CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_RELA
LDFLAGS+= -Wl,-e,.rtld_start
diff --git a/libexec/ld.elf_so/arch/x86_64/mdreloc.c b/libexec/ld.elf_so/arch/x86_64/mdreloc.c
index 644242be154..a04c05ea0aa 100644
--- a/libexec/ld.elf_so/arch/x86_64/mdreloc.c
+++ b/libexec/ld.elf_so/arch/x86_64/mdreloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.46 2017/11/06 21:16:04 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.47 2018/04/03 21:10:27 joerg Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -68,7 +68,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.46 2017/11/06 21:16:04 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.47 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -261,6 +261,14 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
rdbg(("COPY"));
break;
+ case R_TYPE(IRELATIVE):
+ /* IFUNC relocations are handled in _rtld_call_ifunc */
+ if (obj->ifunc_remaining_nonplt == 0) {
+ obj->ifunc_remaining_nonplt =
+ obj->relalim - rela;
+ }
+ break;
+
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
@@ -299,27 +307,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
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 inline int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
{
diff --git a/libexec/ld.elf_so/reloc.c b/libexec/ld.elf_so/reloc.c
index f6027947725..578565de684 100644
--- a/libexec/ld.elf_so/reloc.c
+++ b/libexec/ld.elf_so/reloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: reloc.c,v 1.111 2017/08/10 19:03:25 joerg Exp $ */
+/* $NetBSD: reloc.c,v 1.112 2018/04/03 21:10:27 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.111 2017/08/10 19:03:25 joerg Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.112 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <err.h>
@@ -276,3 +276,93 @@ _rtld_resolve_ifunc2(const Obj_Entry *obj, Elf_Addr addr)
return target;
}
+
+#ifdef RTLD_COMMON_CALL_IFUNC_RELA
+# ifdef __sparc__
+# include <machine/elf_support.h>
+# endif
+
+void
+_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
+{
+ const Elf_Rela *rela;
+ Elf_Addr *where;
+#ifdef __sparc__
+ Elf_Word *where2;
+#endif
+ Elf_Addr target;
+
+ while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
+ rela = obj->pltrelalim - obj->ifunc_remaining--;
+#ifdef __sparc__
+#define PLT_IRELATIVE R_TYPE(JMP_IREL)
+#else
+#define PLT_IRELATIVE R_TYPE(IRELATIVE)
+#endif
+ if (ELF_R_TYPE(rela->r_info) != PLT_IRELATIVE)
+ continue;
+#ifdef __sparc__
+ where2 = (Elf_Word *)(obj->relocbase + rela->r_offset);
+#else
+ where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+#endif
+ target = (Elf_Addr)(obj->relocbase + rela->r_addend);
+ _rtld_exclusive_exit(mask);
+ target = _rtld_resolve_ifunc2(obj, target);
+ _rtld_exclusive_enter(mask);
+#ifdef __sparc__
+ sparc_write_branch(where2 + 1, (void *)target);
+#else
+ if (*where != target)
+ *where = target;
+#endif
+ }
+
+ while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
+ rela = obj->relalim - obj->ifunc_remaining_nonplt--;
+ if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
+ continue;
+ 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;
+ }
+}
+#endif
+
+#ifdef RTLD_COMMON_CALL_IFUNC_REL
+void
+_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
+{
+ const Elf_Rel *rel;
+ Elf_Addr *where, target;
+
+ while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
+ rel = obj->pltrellim - obj->ifunc_remaining;
+ --obj->ifunc_remaining;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)) {
+ where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+ _rtld_exclusive_exit(mask);
+ target = _rtld_resolve_ifunc2(obj, *where);
+ _rtld_exclusive_enter(mask);
+ if (*where != target)
+ *where = target;
+ }
+ }
+
+ while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
+ rel = obj->rellim - obj->ifunc_remaining_nonplt--;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)) {
+ where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+ _rtld_exclusive_exit(mask);
+ target = _rtld_resolve_ifunc2(obj, *where);
+ _rtld_exclusive_enter(mask);
+ if (*where != target)
+ *where = target;
+ }
+ }
+}
+#endif
diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c
index 862fab383dc..119083c0521 100644
--- a/libexec/ld.elf_so/rtld.c
+++ b/libexec/ld.elf_so/rtld.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.191 2018/03/09 20:19:11 joerg Exp $ */
+/* $NetBSD: rtld.c,v 1.192 2018/04/03 21:10:27 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.191 2018/03/09 20:19:11 joerg Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.192 2018/04/03 21:10:27 joerg Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -263,7 +263,7 @@ static bool
_rtld_call_ifunc_functions(sigset_t *mask, Obj_Entry *obj, u_int cur_objgen)
{
if (obj->ifunc_remaining
-#if defined(__sparc__) || defined(__powerpc__)
+#if defined(IFUNC_NONPLT)
|| obj->ifunc_remaining_nonplt
#endif
) {
diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h
index d9e6f8b7dfa..3d0b16641c5 100644
--- a/libexec/ld.elf_so/rtld.h
+++ b/libexec/ld.elf_so/rtld.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.132 2018/03/09 20:19:11 joerg Exp $ */
+/* $NetBSD: rtld.h,v 1.133 2018/04/03 21:10:27 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -300,7 +300,9 @@ typedef struct Struct_Obj_Entry {
size_t fini_arraysz; /* # of entries in it */
/* IRELATIVE relocations */
size_t ifunc_remaining;
-#if defined(__sparc__) || defined(__powerpc__)
+#if defined(__sparc__) || defined(__powerpc__) || defined(__arm__) || \
+ defined(__i386__) || defined(__x86_64__)
+#define IFUNC_NONPLT
/* On SPARC, the PLT variant is called JMP_IREL and counted above. */
size_t ifunc_remaining_nonplt;
#endif