Module Name: src Committed By: joerg Date: Thu Aug 10 19:03:27 UTC 2017
Modified Files: src/libexec/ld.elf_so: reloc.c rtld.c rtld.h src/libexec/ld.elf_so/arch/aarch64: mdreloc.c src/libexec/ld.elf_so/arch/alpha: alpha_reloc.c src/libexec/ld.elf_so/arch/arm: mdreloc.c src/libexec/ld.elf_so/arch/hppa: hppa_reloc.c src/libexec/ld.elf_so/arch/i386: mdreloc.c src/libexec/ld.elf_so/arch/m68k: mdreloc.c src/libexec/ld.elf_so/arch/mips: mips_reloc.c src/libexec/ld.elf_so/arch/or1k: mdreloc.c src/libexec/ld.elf_so/arch/powerpc: ppc_reloc.c src/libexec/ld.elf_so/arch/riscv: mdreloc.c src/libexec/ld.elf_so/arch/sh3: mdreloc.c src/libexec/ld.elf_so/arch/sparc: mdreloc.c src/libexec/ld.elf_so/arch/sparc64: mdreloc.c src/libexec/ld.elf_so/arch/vax: mdreloc.c src/libexec/ld.elf_so/arch/x86_64: mdreloc.c src/sys/arch/arm/include: elf_machdep.h src/sys/arch/powerpc/include: elf_machdep.h src/sys/sys: cdefs_elf.h src/tests/libexec/ld.elf_so: t_ifunc.c src/tests/libexec/ld.elf_so/helper_ifunc_dso: h_helper_ifunc.c Log Message: Add IRELATIVE support for ARM, X86 and PowerPC. To generate a diff of this commit: cvs rdiff -u -r1.110 -r1.111 src/libexec/ld.elf_so/reloc.c cvs rdiff -u -r1.185 -r1.186 src/libexec/ld.elf_so/rtld.c cvs rdiff -u -r1.129 -r1.130 src/libexec/ld.elf_so/rtld.h cvs rdiff -u -r1.3 -r1.4 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c cvs rdiff -u -r1.42 -r1.43 src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c cvs rdiff -u -r1.41 -r1.42 src/libexec/ld.elf_so/arch/arm/mdreloc.c cvs rdiff -u -r1.44 -r1.45 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c cvs rdiff -u -r1.38 -r1.39 src/libexec/ld.elf_so/arch/i386/mdreloc.c cvs rdiff -u -r1.32 -r1.33 src/libexec/ld.elf_so/arch/m68k/mdreloc.c cvs rdiff -u -r1.68 -r1.69 src/libexec/ld.elf_so/arch/mips/mips_reloc.c cvs rdiff -u -r1.2 -r1.3 src/libexec/ld.elf_so/arch/or1k/mdreloc.c cvs rdiff -u -r1.54 -r1.55 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c cvs rdiff -u -r1.3 -r1.4 src/libexec/ld.elf_so/arch/riscv/mdreloc.c cvs rdiff -u -r1.34 -r1.35 src/libexec/ld.elf_so/arch/sh3/mdreloc.c cvs rdiff -u -r1.50 -r1.51 src/libexec/ld.elf_so/arch/sparc/mdreloc.c cvs rdiff -u -r1.63 -r1.64 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c cvs rdiff -u -r1.33 -r1.34 src/libexec/ld.elf_so/arch/vax/mdreloc.c cvs rdiff -u -r1.44 -r1.45 src/libexec/ld.elf_so/arch/x86_64/mdreloc.c cvs rdiff -u -r1.17 -r1.18 src/sys/arch/arm/include/elf_machdep.h cvs rdiff -u -r1.12 -r1.13 src/sys/arch/powerpc/include/elf_machdep.h cvs rdiff -u -r1.52 -r1.53 src/sys/sys/cdefs_elf.h cvs rdiff -u -r1.2 -r1.3 src/tests/libexec/ld.elf_so/t_ifunc.c cvs rdiff -u -r1.4 -r1.5 \ src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c 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/reloc.c diff -u src/libexec/ld.elf_so/reloc.c:1.110 src/libexec/ld.elf_so/reloc.c:1.111 --- src/libexec/ld.elf_so/reloc.c:1.110 Thu Apr 27 08:37:15 2017 +++ src/libexec/ld.elf_so/reloc.c Thu Aug 10 19:03:25 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: reloc.c,v 1.110 2017/04/27 08:37:15 uwe Exp $ */ +/* $NetBSD: reloc.c,v 1.111 2017/08/10 19:03:25 joerg Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -39,7 +39,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: reloc.c,v 1.110 2017/04/27 08:37:15 uwe Exp $"); +__RCSID("$NetBSD: reloc.c,v 1.111 2017/08/10 19:03:25 joerg Exp $"); #endif /* not lint */ #include <err.h> @@ -261,9 +261,18 @@ _rtld_resolve_ifunc(const Obj_Entry *obj Elf_Addr target; _rtld_shared_exit(); - target = _rtld_call_function_addr(obj, + target = _rtld_resolve_ifunc2(obj, (Elf_Addr)obj->relocbase + def->st_value); _rtld_shared_enter(); + return target; +} + +Elf_Addr +_rtld_resolve_ifunc2(const Obj_Entry *obj, Elf_Addr addr) +{ + Elf_Addr target; + + target = _rtld_call_function_addr(obj, addr); return target; } Index: src/libexec/ld.elf_so/rtld.c diff -u src/libexec/ld.elf_so/rtld.c:1.185 src/libexec/ld.elf_so/rtld.c:1.186 --- src/libexec/ld.elf_so/rtld.c:1.185 Tue Jul 11 15:21:35 2017 +++ src/libexec/ld.elf_so/rtld.c Thu Aug 10 19:03:25 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.c,v 1.185 2017/07/11 15:21:35 joerg Exp $ */ +/* $NetBSD: rtld.c,v 1.186 2017/08/10 19:03:25 joerg Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: rtld.c,v 1.185 2017/07/11 15:21:35 joerg Exp $"); +__RCSID("$NetBSD: rtld.c,v 1.186 2017/08/10 19:03:25 joerg Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -273,7 +273,20 @@ restart: SIMPLEQ_INIT(&initlist); _rtld_initlist_tsort(&initlist, 0); - /* First pass: objects marked with DF_1_INITFIRST. */ + /* First pass: objects with IRELATIVE relocations. */ + SIMPLEQ_FOREACH(elm, &initlist, link) { + Obj_Entry * const obj = elm->obj; + if (obj->ifunc_remaining) { + _rtld_call_ifunc(obj, mask, cur_objgen); + if (_rtld_objgen != cur_objgen) { + dbg(("restarting init iteration")); + _rtld_objlist_clear(&initlist); + goto restart; + } + } + } + + /* Second pass: objects marked with DF_1_INITFIRST. */ SIMPLEQ_FOREACH(elm, &initlist, link) { Obj_Entry * const obj = elm->obj; if (obj->z_initfirst) { @@ -286,7 +299,7 @@ restart: } } - /* Second pass: all other objects. */ + /* Third pass: all other objects. */ SIMPLEQ_FOREACH(elm, &initlist, link) { _rtld_call_init_function(elm->obj, mask, cur_objgen); if (_rtld_objgen != cur_objgen) { Index: src/libexec/ld.elf_so/rtld.h diff -u src/libexec/ld.elf_so/rtld.h:1.129 src/libexec/ld.elf_so/rtld.h:1.130 --- src/libexec/ld.elf_so/rtld.h:1.129 Tue Jul 11 15:21:35 2017 +++ src/libexec/ld.elf_so/rtld.h Thu Aug 10 19:03:25 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.h,v 1.129 2017/07/11 15:21:35 joerg Exp $ */ +/* $NetBSD: rtld.h,v 1.130 2017/08/10 19:03:25 joerg Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -298,6 +298,8 @@ typedef struct Struct_Obj_Entry { size_t init_arraysz; /* # of entries in it */ Elf_Addr *fini_array; /* start of fini array */ size_t fini_arraysz; /* # of entries in it */ + /* IRELATIVE relocations */ + size_t ifunc_remaining; size_t cxa_refcount; /* For TLS destructors. */ #ifdef __ARM_EABI__ void *exidx_start; @@ -328,6 +330,7 @@ extern bool _rtld_trust; extern Objlist _rtld_list_global; extern Objlist _rtld_list_main; extern Elf_Sym _rtld_sym_zero; +extern u_int _rtld_objgen; #define RTLD_MODEMASK 0x3 @@ -407,10 +410,13 @@ int _rtld_sysctl(const char *, void *, s int _rtld_do_copy_relocations(const Obj_Entry *); int _rtld_relocate_objects(Obj_Entry *, bool); int _rtld_relocate_nonplt_objects(Obj_Entry *); -int _rtld_relocate_plt_lazy(const Obj_Entry *); +int _rtld_relocate_plt_lazy(Obj_Entry *); int _rtld_relocate_plt_objects(const Obj_Entry *); void _rtld_setup_pltgot(const Obj_Entry *); Elf_Addr _rtld_resolve_ifunc(const Obj_Entry *, const Elf_Sym *); +Elf_Addr _rtld_resolve_ifunc2(const Obj_Entry *, Elf_Addr); + +void _rtld_call_ifunc(Obj_Entry *, sigset_t *, u_int); /* search.c */ Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); Index: src/libexec/ld.elf_so/arch/aarch64/mdreloc.c diff -u src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.3 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.4 --- src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.3 Mon Jun 19 11:57:01 2017 +++ src/libexec/ld.elf_so/arch/aarch64/mdreloc.c Thu Aug 10 19:03:25 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:01 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.4 2017/08/10 19:03:25 joerg Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:01 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.4 2017/08/10 19:03:25 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -190,7 +190,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { if (!obj->relocbase) Index: src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c diff -u src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.42 src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.43 --- src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.42 Mon Jun 19 11:57:01 2017 +++ src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: alpha_reloc.c,v 1.42 2017/06/19 11:57:01 joerg Exp $ */ +/* $NetBSD: alpha_reloc.c,v 1.43 2017/08/10 19:03:26 joerg Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -62,7 +62,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: alpha_reloc.c,v 1.42 2017/06/19 11:57:01 joerg Exp $"); +__RCSID("$NetBSD: alpha_reloc.c,v 1.43 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -343,7 +343,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; Index: src/libexec/ld.elf_so/arch/arm/mdreloc.c diff -u src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.41 src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.42 --- src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.41 Tue Jun 20 12:41:49 2017 +++ src/libexec/ld.elf_so/arch/arm/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,8 +1,8 @@ -/* $NetBSD: mdreloc.c,v 1.41 2017/06/20 12:41:49 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.42 2017/08/10 19:03:26 joerg Exp $ */ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.41 2017/06/20 12:41:49 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.42 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -253,17 +253,21 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rel *rel; if (!obj->relocbase) return 0; - for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { + for (rel = obj->pltrellim; rel-- > obj->pltrel; ) { Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT)); + assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT) || + ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)); + + if (ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)) + obj->ifunc_remaining = obj->pltrellim - rel; /* Just relocate the GOT slots pointing into the PLT */ *where += (Elf_Addr)obj->relocbase; @@ -273,6 +277,26 @@ _rtld_relocate_plt_lazy(const Obj_Entry 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) Index: src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c diff -u src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.44 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.45 --- src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.44 Mon Jun 19 11:57:01 2017 +++ src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: hppa_reloc.c,v 1.44 2017/06/19 11:57:01 joerg Exp $ */ +/* $NetBSD: hppa_reloc.c,v 1.45 2017/08/10 19:03:26 joerg Exp $ */ /*- * Copyright (c) 2002, 2004 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: hppa_reloc.c,v 1.44 2017/06/19 11:57:01 joerg Exp $"); +__RCSID("$NetBSD: hppa_reloc.c,v 1.45 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <stdlib.h> @@ -589,7 +589,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; Index: src/libexec/ld.elf_so/arch/i386/mdreloc.c diff -u src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.38 src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.39 --- src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.38 Mon Jun 19 11:57:01 2017 +++ src/libexec/ld.elf_so/arch/i386/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,8 +1,8 @@ -/* $NetBSD: mdreloc.c,v 1.38 2017/06/19 11:57:01 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.39 2017/08/10 19:03:26 joerg Exp $ */ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.38 2017/06/19 11:57:01 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.39 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -194,17 +194,21 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rel *rel; if (!obj->relocbase) return 0; - for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { + for (rel = obj->pltrellim; rel-- > obj->pltrel; ) { Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JMP_SLOT)); + assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JMP_SLOT) || + ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)); + + if (ELF_R_TYPE(rel->r_info) == R_TYPE(IRELATIVE)) + obj->ifunc_remaining = obj->pltrellim - rel; /* Just relocate the GOT slots pointing into the PLT */ *where += (Elf_Addr)obj->relocbase; @@ -214,6 +218,26 @@ _rtld_relocate_plt_lazy(const Obj_Entry 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) @@ -224,6 +248,9 @@ _rtld_relocate_plt_object(const Obj_Entr const Obj_Entry *defobj; unsigned long info = rel->r_info; + if (ELF_R_TYPE(info) == R_TYPE(IRELATIVE)) + return 0; + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); Index: src/libexec/ld.elf_so/arch/m68k/mdreloc.c diff -u src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.32 src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.33 --- src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.32 Mon Jun 19 11:57:01 2017 +++ src/libexec/ld.elf_so/arch/m68k/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,8 +1,8 @@ -/* $NetBSD: mdreloc.c,v 1.32 2017/06/19 11:57:01 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.33 2017/08/10 19:03:26 joerg Exp $ */ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.32 2017/06/19 11:57:01 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.33 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -181,7 +181,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; Index: src/libexec/ld.elf_so/arch/mips/mips_reloc.c diff -u src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.68 src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.69 --- src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.68 Wed Jun 21 12:34:01 2017 +++ src/libexec/ld.elf_so/arch/mips/mips_reloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mips_reloc.c,v 1.68 2017/06/21 12:34:01 joerg Exp $ */ +/* $NetBSD: mips_reloc.c,v 1.69 2017/08/10 19:03:26 joerg Exp $ */ /* * Copyright 1997 Michael L. Hitch <mhi...@montana.edu> @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mips_reloc.c,v 1.68 2017/06/21 12:34:01 joerg Exp $"); +__RCSID("$NetBSD: mips_reloc.c,v 1.69 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -480,7 +480,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { /* PLT fixups were done above in the GOT relocation. */ return 0; Index: src/libexec/ld.elf_so/arch/or1k/mdreloc.c diff -u src/libexec/ld.elf_so/arch/or1k/mdreloc.c:1.2 src/libexec/ld.elf_so/arch/or1k/mdreloc.c:1.3 --- src/libexec/ld.elf_so/arch/or1k/mdreloc.c:1.2 Mon Jun 19 11:57:02 2017 +++ src/libexec/ld.elf_so/arch/or1k/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mdreloc.c,v 1.2 2017/06/19 11:57:02 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.3 2017/08/10 19:03:26 joerg Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.2 2017/06/19 11:57:02 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.3 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <stdarg.h> @@ -210,7 +210,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; int reloff; Index: src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c diff -u src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.54 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.55 --- src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.54 Mon Jun 19 11:57:02 2017 +++ src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ppc_reloc.c,v 1.54 2017/06/19 11:57:02 joerg Exp $ */ +/* $NetBSD: ppc_reloc.c,v 1.55 2017/08/10 19:03:26 joerg Exp $ */ /*- * Copyright (C) 1998 Tsubai Masanari @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: ppc_reloc.c,v 1.54 2017/06/19 11:57:02 joerg Exp $"); +__RCSID("$NetBSD: ppc_reloc.c,v 1.55 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <stdarg.h> @@ -303,24 +303,31 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { #ifdef _LP64 /* * For PowerPC64, the plt stubs handle an empty function descriptor * so there's nothing to do. */ + /* XXX ifunc support */ #else Elf_Addr * const pltresolve = obj->pltgot + 8; const Elf_Rela *rela; int reloff; - for (rela = obj->pltrela, reloff = 0; - rela < obj->pltrelalim; - rela++, reloff++) { + rela = obj->pltrelalim; + for (reloff = rela - obj->pltrela; rela-- > obj->pltrela; --reloff) { Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); - assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT) || + ELF_R_TYPE(rela->r_info) == R_TYPE(IRELATIVE)); + + if (ELF_R_TYPE(rela->r_info) == R_TYPE(IRELATIVE)) { + /* No ifunc support for old-style insecure PLT. */ + assert(obj->gotptr != NULL); + obj->ifunc_remaining = obj->pltrelalim - rela; + } if (obj->gotptr != NULL) { /* @@ -357,6 +364,27 @@ _rtld_relocate_plt_lazy(const Obj_Entry 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_Rela *rela, int reloff, Elf_Addr *tp) { Index: src/libexec/ld.elf_so/arch/riscv/mdreloc.c diff -u src/libexec/ld.elf_so/arch/riscv/mdreloc.c:1.3 src/libexec/ld.elf_so/arch/riscv/mdreloc.c:1.4 --- src/libexec/ld.elf_so/arch/riscv/mdreloc.c:1.3 Mon Jun 19 11:57:02 2017 +++ src/libexec/ld.elf_so/arch/riscv/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:02 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.4 2017/08/10 19:03:26 joerg Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:02 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.4 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -198,7 +198,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { /* PLT fixups were done above in the GOT relocation. */ return 0; Index: src/libexec/ld.elf_so/arch/sh3/mdreloc.c diff -u src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.34 src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.35 --- src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.34 Tue Jun 20 13:45:20 2017 +++ src/libexec/ld.elf_so/arch/sh3/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,8 +1,8 @@ -/* $NetBSD: mdreloc.c,v 1.34 2017/06/20 13:45:20 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.35 2017/08/10 19:03:26 joerg Exp $ */ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.34 2017/06/20 13:45:20 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.35 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -204,7 +204,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; Index: src/libexec/ld.elf_so/arch/sparc/mdreloc.c diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.50 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.51 --- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.50 Mon Jun 19 11:57:02 2017 +++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mdreloc.c,v 1.50 2017/06/19 11:57:02 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.51 2017/08/10 19:03:26 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.50 2017/06/19 11:57:02 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.51 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <errno.h> @@ -385,7 +385,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { return (0); } Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.63 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.64 --- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.63 Mon Jul 24 08:08:34 2017 +++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c Thu Aug 10 19:03:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mdreloc.c,v 1.63 2017/07/24 08:08:34 martin Exp $ */ +/* $NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $ */ /*- * Copyright (c) 2000 Eduardo Horvath. @@ -32,7 +32,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.63 2017/07/24 08:08:34 martin Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $"); #endif /* not lint */ #include <errno.h> @@ -505,7 +505,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { return (0); } Index: src/libexec/ld.elf_so/arch/vax/mdreloc.c diff -u src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.33 src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.34 --- src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.33 Tue Jun 20 15:02:54 2017 +++ src/libexec/ld.elf_so/arch/vax/mdreloc.c Thu Aug 10 19:03:27 2017 @@ -1,8 +1,8 @@ -/* $NetBSD: mdreloc.c,v 1.33 2017/06/20 15:02:54 joerg Exp $ */ +/* $NetBSD: mdreloc.c,v 1.34 2017/08/10 19:03:27 joerg Exp $ */ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: mdreloc.c,v 1.33 2017/06/20 15:02:54 joerg Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.34 2017/08/10 19:03:27 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -136,7 +136,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; Index: src/libexec/ld.elf_so/arch/x86_64/mdreloc.c diff -u src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.44 src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.45 --- src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.44 Wed Jul 12 17:55:24 2017 +++ src/libexec/ld.elf_so/arch/x86_64/mdreloc.c Thu Aug 10 19:03:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mdreloc.c,v 1.44 2017/07/12 17:55:24 christos Exp $ */ +/* $NetBSD: mdreloc.c,v 1.45 2017/08/10 19:03: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.44 2017/07/12 17:55:24 christos Exp $"); +__RCSID("$NetBSD: mdreloc.c,v 1.45 2017/08/10 19:03:27 joerg Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -278,17 +278,21 @@ _rtld_relocate_nonplt_objects(Obj_Entry } int -_rtld_relocate_plt_lazy(const Obj_Entry *obj) +_rtld_relocate_plt_lazy(Obj_Entry *obj) { const Elf_Rela *rela; if (!obj->relocbase) return 0; - for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + for (rela = obj->pltrelalim; rela-- > obj->pltrela; ) { Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); - assert(ELF_R_TYPE(rela->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(IRELATIVE)); + + if (ELF_R_TYPE(rela->r_info) == R_TYPE(IRELATIVE)) + obj->ifunc_remaining = obj->pltrelalim - rela; /* Just relocate the GOT slots pointing into the PLT */ *where += (Elf_Addr)obj->relocbase; @@ -298,6 +302,27 @@ _rtld_relocate_plt_lazy(const Obj_Entry 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) { @@ -307,6 +332,9 @@ _rtld_relocate_plt_object(const Obj_Entr const Obj_Entry *defobj; unsigned long info = rela->r_info; + if (ELF_R_TYPE(info) == R_TYPE(IRELATIVE)) + return 0; + assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT)); def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); Index: src/sys/arch/arm/include/elf_machdep.h diff -u src/sys/arch/arm/include/elf_machdep.h:1.17 src/sys/arch/arm/include/elf_machdep.h:1.18 --- src/sys/arch/arm/include/elf_machdep.h:1.17 Tue Feb 25 19:20:09 2014 +++ src/sys/arch/arm/include/elf_machdep.h Thu Aug 10 19:03:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: elf_machdep.h,v 1.17 2014/02/25 19:20:09 matt Exp $ */ +/* $NetBSD: elf_machdep.h,v 1.18 2017/08/10 19:03:27 joerg Exp $ */ #ifndef _ARM_ELF_MACHDEP_H_ #define _ARM_ELF_MACHDEP_H_ @@ -119,6 +119,8 @@ /* 112-127 are reserved for private experiments. */ +#define R_ARM_IRELATIVE 160 + #define R_ARM_RXPC25 249 #define R_ARM_RSBREL32 250 #define R_ARM_THM_RPC22 251 Index: src/sys/arch/powerpc/include/elf_machdep.h diff -u src/sys/arch/powerpc/include/elf_machdep.h:1.12 src/sys/arch/powerpc/include/elf_machdep.h:1.13 --- src/sys/arch/powerpc/include/elf_machdep.h:1.12 Fri Mar 7 04:11:07 2014 +++ src/sys/arch/powerpc/include/elf_machdep.h Thu Aug 10 19:03:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: elf_machdep.h,v 1.12 2014/03/07 04:11:07 matt Exp $ */ +/* $NetBSD: elf_machdep.h,v 1.13 2017/08/10 19:03:27 joerg Exp $ */ #ifndef _POWERPC_ELF_MACHDEP_H_ #define _POWERPC_ELF_MACHDEP_H_ @@ -198,6 +198,9 @@ #define R_PPC_DTPREL16_HIGHEST 105 // #highest(@dtprel) #define R_PPC_DTPREL16_HIGHESTA 106 // #highesta(@dtprel) +/* Indirect-function support */ +#define R_PPC_IRELATIVE 248 + /* Used for the secure-plt PIC code sequences */ #define R_PPC_REL16 249 // S + A - P #define R_PPC_REL16_LO 250 // #lo(S + A - P) Index: src/sys/sys/cdefs_elf.h diff -u src/sys/sys/cdefs_elf.h:1.52 src/sys/sys/cdefs_elf.h:1.53 --- src/sys/sys/cdefs_elf.h:1.52 Tue Jun 7 12:09:29 2016 +++ src/sys/sys/cdefs_elf.h Thu Aug 10 19:03:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: cdefs_elf.h,v 1.52 2016/06/07 12:09:29 joerg Exp $ */ +/* $NetBSD: cdefs_elf.h,v 1.53 2017/08/10 19:03:27 joerg Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -117,11 +117,21 @@ __asm(".globl " _C_LABEL_STRING(#name) "\n" \ ".type " _C_LABEL_STRING(#name) ", %gnu_indirect_function\n" \ _C_LABEL_STRING(#name) " = " _C_LABEL_STRING(#resolver)) +#define __hidden_ifunc(name, resolver) \ + __asm(".globl " _C_LABEL_STRING(#name) "\n" \ + ".hidden " _C_LABEL_STRING(#name) "\n" \ + ".type " _C_LABEL_STRING(#name) ", %gnu_indirect_function\n" \ + _C_LABEL_STRING(#name) " = " _C_LABEL_STRING(#resolver)) #else #define __ifunc(name, resolver) \ __asm(".globl " _C_LABEL_STRING(#name) "\n" \ ".type " _C_LABEL_STRING(#name) ", @gnu_indirect_function\n" \ _C_LABEL_STRING(#name) " = " _C_LABEL_STRING(#resolver)) +#define __hidden_ifunc(name, resolver) \ + __asm(".globl " _C_LABEL_STRING(#name) "\n" \ + ".hidden " _C_LABEL_STRING(#name) "\n" \ + ".type " _C_LABEL_STRING(#name) ", @gnu_indirect_function\n" \ + _C_LABEL_STRING(#name) " = " _C_LABEL_STRING(#resolver)) #endif #if __STDC__ Index: src/tests/libexec/ld.elf_so/t_ifunc.c diff -u src/tests/libexec/ld.elf_so/t_ifunc.c:1.2 src/tests/libexec/ld.elf_so/t_ifunc.c:1.3 --- src/tests/libexec/ld.elf_so/t_ifunc.c:1.2 Fri Jan 13 21:30:42 2017 +++ src/tests/libexec/ld.elf_so/t_ifunc.c Thu Aug 10 19:03:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: t_ifunc.c,v 1.2 2017/01/13 21:30:42 christos Exp $ */ +/* $NetBSD: t_ifunc.c,v 1.3 2017/08/10 19:03:27 joerg Exp $ */ /* * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -56,6 +56,10 @@ ATF_TC_BODY(rtld_ifunc, tc) const char *error; size_t i; +#if !defined( __arm__) && !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) + atf_tc_expect_fail("Missing linker support for hidden ifunc relocations"); +#endif + for (i = 0; i < __arraycount(envstr); ++i) { setenv("USE_IFUNC2", envstr[i], 1); @@ -85,8 +89,59 @@ ATF_TC_BODY(rtld_ifunc, tc) } } +ATF_TC(rtld_hidden_ifunc); + +ATF_TC_HEAD(rtld_hidden_ifunc, tc) +{ + atf_tc_set_md_var(tc, "descr", "hidden ifunc functions are resolved"); +} + +ATF_TC_BODY(rtld_hidden_ifunc, tc) +{ + const char *envstr[] = { + "0", "1" + }; + int expected_result[] = { + 0xdeadbeef, 0xbeefdead + }; + void *handle; + int (*sym)(void); + int result; + const char *error; + size_t i; + + for (i = 0; i < __arraycount(envstr); ++i) { + setenv("USE_IFUNC2", envstr[i], 1); + + handle = dlopen("libh_helper_ifunc_dso.so", RTLD_LAZY); + error = dlerror(); + ATF_CHECK(error == NULL); + ATF_CHECK(handle != NULL); + + sym = dlsym(handle, "ifunc_plt"); + error = dlerror(); + ATF_CHECK(error == NULL); + ATF_CHECK(sym != NULL); + + result = (*sym)(); + ATF_CHECK(result == expected_result[!i]); + + dlclose(handle); + error = dlerror(); + ATF_CHECK(error == NULL); + + char *command; + easprintf(&command, "%s/h_ifunc %d", + atf_tc_get_config_var(tc, "srcdir"), expected_result[i]); + if (system(command) != EXIT_SUCCESS) + atf_tc_fail("Test failed; see output for details"); + free(command); + } +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, rtld_ifunc); + ATF_TP_ADD_TC(tp, rtld_hidden_ifunc); return 0; } Index: src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c diff -u src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c:1.4 src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c:1.5 --- src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c:1.4 Tue Aug 26 17:13:42 2014 +++ src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c Thu Aug 10 19:03:27 2017 @@ -49,4 +49,20 @@ int (*resolve_ifunc(void))(void) return e && strcmp(e, "1") == 0 ? ifunc2 : ifunc1; } +static __attribute__((used)) +int (*resolve_ifunc2(void))(void) +{ + const char *e = getenv("USE_IFUNC2"); + return e && strcmp(e, "1") == 0 ? ifunc1 : ifunc2; +} + __ifunc(ifunc, resolve_ifunc); +__hidden_ifunc(ifunc_hidden, resolve_ifunc2); + +int ifunc_hidden(void); +int ifunc_plt(void); + +int ifunc_plt(void) +{ + return ifunc_hidden(); +}