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();
+}

Reply via email to