diff options
| author | joerg <joerg@NetBSD.org> | 2018-04-03 21:10:27 +0000 |
|---|---|---|
| committer | joerg <joerg@NetBSD.org> | 2018-04-03 21:10:27 +0000 |
| commit | 0c16eee5b40284ce50f348c550fa5906ff794145 (patch) | |
| tree | 9ce3f6800f056b3681f5bd2e8ce0a42ad566bba0 /libexec | |
| parent | 6b4d1fe2e0525f1d06796cec71ac986c5bb368bd (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.inc | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/arm/mdreloc.c | 30 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/i386/Makefile.inc | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/i386/mdreloc.c | 33 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/powerpc/Makefile.inc | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/powerpc/ppc_reloc.c | 40 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/sparc/Makefile.inc | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/sparc/mdreloc.c | 42 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/sparc64/Makefile.inc | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/sparc64/mdreloc.c | 44 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/x86_64/Makefile.inc | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/x86_64/mdreloc.c | 33 | ||||
| -rw-r--r-- | libexec/ld.elf_so/reloc.c | 94 | ||||
| -rw-r--r-- | libexec/ld.elf_so/rtld.c | 6 | ||||
| -rw-r--r-- | libexec/ld.elf_so/rtld.h | 6 |
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 |
