Module Name:    src
Committed By:   joerg
Date:           Sat Aug 12 09:03:28 UTC 2017

Modified Files:
        src/libexec/ld.elf_so: rtld.c rtld.h
        src/libexec/ld.elf_so/arch/sparc: mdreloc.c
        src/libexec/ld.elf_so/arch/sparc64: mdreloc.c
        src/sys/arch/sparc/include: elf_machdep.h
        src/sys/arch/sparc64/include: elf_machdep.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 sparc/sparc64 support for irelative relocations.


To generate a diff of this commit:
cvs rdiff -u -r1.186 -r1.187 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.130 -r1.131 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.51 -r1.52 src/libexec/ld.elf_so/arch/sparc/mdreloc.c
cvs rdiff -u -r1.64 -r1.65 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/sparc/include/elf_machdep.h
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/sparc64/include/elf_machdep.h
cvs rdiff -u -r1.3 -r1.4 src/tests/libexec/ld.elf_so/t_ifunc.c
cvs rdiff -u -r1.5 -r1.6 \
    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/rtld.c
diff -u src/libexec/ld.elf_so/rtld.c:1.186 src/libexec/ld.elf_so/rtld.c:1.187
--- src/libexec/ld.elf_so/rtld.c:1.186	Thu Aug 10 19:03:25 2017
+++ src/libexec/ld.elf_so/rtld.c	Sat Aug 12 09:03:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.c,v 1.186 2017/08/10 19:03:25 joerg Exp $	 */
+/*	$NetBSD: rtld.c,v 1.187 2017/08/12 09:03:27 joerg Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.186 2017/08/10 19:03:25 joerg Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.187 2017/08/12 09:03:27 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -276,7 +276,11 @@ restart:
 	/* First pass: objects with IRELATIVE relocations. */
 	SIMPLEQ_FOREACH(elm, &initlist, link) {
 		Obj_Entry * const obj = elm->obj;
-		if (obj->ifunc_remaining) {
+		if (obj->ifunc_remaining
+#ifdef __sparc__
+		    || obj->ifunc_remaining_nonplt
+#endif
+		) {
 			_rtld_call_ifunc(obj, mask, cur_objgen);
 			if (_rtld_objgen != cur_objgen) {
 				dbg(("restarting init iteration"));

Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.130 src/libexec/ld.elf_so/rtld.h:1.131
--- src/libexec/ld.elf_so/rtld.h:1.130	Thu Aug 10 19:03:25 2017
+++ src/libexec/ld.elf_so/rtld.h	Sat Aug 12 09:03:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.h,v 1.130 2017/08/10 19:03:25 joerg Exp $	 */
+/*	$NetBSD: rtld.h,v 1.131 2017/08/12 09:03:27 joerg Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -300,6 +300,10 @@ typedef struct Struct_Obj_Entry {
 	size_t		fini_arraysz;	/* # of entries in it */
 	/* IRELATIVE relocations */
 	size_t		ifunc_remaining;
+#ifdef __sparc__
+	/* On SPARC, the PLT variant is called JMP_IREL and counted above. */
+	size_t		ifunc_remaining_nonplt;
+#endif
 	size_t		cxa_refcount;	/* For TLS destructors. */
 #ifdef __ARM_EABI__
 	void		*exidx_start;

Index: src/libexec/ld.elf_so/arch/sparc/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.51 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.52
--- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.51	Thu Aug 10 19:03:26 2017
+++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c	Sat Aug 12 09:03:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.51 2017/08/10 19:03:26 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.52 2017/08/12 09:03: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.51 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.52 2017/08/12 09:03:27 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -220,6 +220,13 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		if (type == R_TYPE(JMP_SLOT))
 			continue;
 
+		/* 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;
+			continue;
+		}
+
 		/* COPY relocs are also handled elsewhere */
 		if (type == R_TYPE(COPY))
 			continue;
@@ -387,7 +394,74 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 int
 _rtld_relocate_plt_lazy(Obj_Entry *obj)
 {
-	return (0);
+	const Elf_Rela *rela;
+
+	if (!obj->relocbase)
+		return 0;
+
+	for (rela = obj->pltrelalim; rela-- > obj->pltrela; ) {
+		if (ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_IREL))
+			obj->ifunc_remaining = obj->pltrelalim - rela + 1;
+	}
+
+	return 0;
+}
+
+static inline void
+_rtld_write_plt(Elf_Word *where, Elf_Addr value)
+{
+	/*
+	 * At the PLT entry pointed at by `where', we now construct
+	 * a direct transfer to the now fully resolved function
+	 * address.  The resulting code in the jump slot is:
+	 *
+	 *	sethi	%hi(roffset), %g1
+	 *	sethi	%hi(addr), %g1
+	 *	jmp	%g1+%lo(addr)
+	 *
+	 * We write the third instruction first, since that leaves the
+	 * previous `b,a' at the second word in place. Hence the whole
+	 * PLT slot can be atomically change to the new sequence by
+	 * writing the `sethi' instruction at word 2.
+	 */
+	const uint32_t SETHI = 0x03000000U;
+	const uint32_t JMP = 0x81c06000U;
+	where[2] = JMP   | (value & 0x000003ff);
+	where[1] = SETHI | ((value >> 10) & 0x003fffff);
+	__asm volatile("iflush %0+8" : : "r" (where));
+	__asm volatile("iflush %0+4" : : "r" (where));
+}
+
+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);
+		_rtld_write_plt(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;
+	}
 }
 
 caddr_t
@@ -429,6 +503,9 @@ _rtld_relocate_plt_object(const Obj_Entr
 	Elf_Addr value;
 	unsigned long info = rela->r_info;
 
+	if (ELF_R_TYPE(info) == R_TYPE(JMP_IREL))
+		return 0;
+
 	assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
 
 	def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
@@ -447,27 +524,7 @@ _rtld_relocate_plt_object(const Obj_Entr
 	rdbg(("bind now/fixup in %s --> new=%p", 
 	    defobj->strtab + def->st_name, (void *)value));
 
-	/*
-	 * At the PLT entry pointed at by `where', we now construct
-	 * a direct transfer to the now fully resolved function
-	 * address.  The resulting code in the jump slot is:
-	 *
-	 *	sethi	%hi(roffset), %g1
-	 *	sethi	%hi(addr), %g1
-	 *	jmp	%g1+%lo(addr)
-	 *
-	 * We write the third instruction first, since that leaves the
-	 * previous `b,a' at the second word in place. Hence the whole
-	 * PLT slot can be atomically change to the new sequence by
-	 * writing the `sethi' instruction at word 2.
-	 */
-#define SETHI	0x03000000
-#define JMP	0x81c06000
-#define NOP	0x01000000
-	where[2] = JMP   | (value & 0x000003ff);
-	where[1] = SETHI | ((value >> 10) & 0x003fffff);
-	__asm volatile("iflush %0+8" : : "r" (where));
-	__asm volatile("iflush %0+4" : : "r" (where));
+	_rtld_write_plt(where, value);
 
 	if (tp)
 		*tp = value;

Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.64 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.65
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.64	Thu Aug 10 19:03:26 2017
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c	Sat Aug 12 09:03:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.65 2017/08/12 09:03:27 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.65 2017/08/12 09:03:27 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -332,6 +332,13 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		if (type == R_TYPE(JMP_SLOT))
 			continue;
 
+		/* 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;
+			continue;
+		}
+
 		/* COPY relocs are also handled elsewhere */
 		if (type == R_TYPE(COPY))
 			continue;
@@ -507,7 +514,17 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 int
 _rtld_relocate_plt_lazy(Obj_Entry *obj)
 {
-	return (0);
+	const Elf_Rela *rela;
+
+	if (!obj->relocbase)
+		return 0;
+
+	for (rela = obj->pltrelalim; rela-- > obj->pltrela; ) {
+		if (ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_IREL))
+			obj->ifunc_remaining = obj->pltrelalim - rela + 1;
+	}
+
+	return 0;
 }
 
 caddr_t
@@ -568,37 +585,11 @@ _rtld_relocate_plt_objects(const Obj_Ent
 	return 0;
 }
 
-/*
- * New inline function that is called by _rtld_relocate_plt_object and
- * _rtld_bind
- */
-static inline int
-_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
-    Elf_Addr *tp)
+static inline void
+_rtld_write_plt(Elf_Word *where, Elf_Addr value, const Elf_Rela *rela,
+    const Obj_Entry *obj)
 {
-	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
-	const Elf_Sym *def;
-	const Obj_Entry *defobj;
-	Elf_Addr value, offset, offBAA;
-	unsigned long info = rela->r_info;
-
-	assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
-
-	def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
-	if (__predict_false(def == NULL))
-		return -1;
-	if (__predict_false(def == &_rtld_sym_zero))
-		return 0;
-
-	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
-		if (tp == NULL)
-			return 0;
-		value = _rtld_resolve_ifunc(defobj, def);
-	} else {
-		value = (Elf_Addr)(defobj->relocbase + def->st_value);
-	}
-	rdbg(("bind now/fixup in %s at %p --> new=%p", 
-	    defobj->strtab + def->st_name, (void*)where, (void *)value));
+	Elf_Addr offset, offBAA;
 
 	/*
 	 * At the PLT entry pointed at by `where', we now construct a direct
@@ -625,8 +616,8 @@ _rtld_relocate_plt_object(const Obj_Entr
 	 */
 
 	offset = ((Elf_Addr)where) - value;
-	offBAA = value - (((Elf_Addr)where) +4);	/* ba,a at where[1] */
-	if (rela->r_addend) {
+	offBAA = value - (((Elf_Addr)where) + 4);	/* ba,a at where[1] */
+	if (rela && rela->r_addend) {
 		Elf_Addr *ptr = (Elf_Addr *)where;
 		/*
 		 * This entry is >= 32768.  The relocations points to a
@@ -634,7 +625,6 @@ _rtld_relocate_plt_object(const Obj_Entr
 		 * PLT section.  Update it to point to the target function.
 		 */
 		ptr[0] += value - (Elf_Addr)obj->pltgot;
-
 	} else if (offBAA <= (1L<<20) && (Elf_SOff)offBAA >= -(1L<<20)) {
 		/* 
 		 * We're within 1MB -- we can use a direct branch insn.
@@ -673,7 +663,6 @@ _rtld_relocate_plt_object(const Obj_Entr
 		where[1] = SETHI | HIVAL(value, 10);
 		__asm volatile("iflush %0+8" : : "r" (where));
 		__asm volatile("iflush %0+4" : : "r" (where));
-
 	} else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) {
 		/* 
 		 * We're within 32-bits of address -1.
@@ -696,7 +685,6 @@ _rtld_relocate_plt_object(const Obj_Entr
 		__asm volatile("iflush %0+12" : : "r" (where));
 		__asm volatile("iflush %0+8" : : "r" (where));
 		__asm volatile("iflush %0+4" : : "r" (where));
-
 	} else if ((offset+8) <= (1L<<31) &&
 	    (Elf_SOff)(offset+8) >= -((1L<<31) - 4)) {
 		/* 
@@ -721,7 +709,6 @@ _rtld_relocate_plt_object(const Obj_Entr
 		__asm volatile("iflush %0+12" : : "r" (where));
 		__asm volatile("iflush %0+8" : : "r" (where));
 		__asm volatile("iflush %0+4" : : "r" (where));
-
 	} else if ((Elf_SOff)value > 0 && value < (1L<<44)) {
 		/* 
 		 * We're within 44 bits.  We can generate this pattern:
@@ -746,7 +733,6 @@ _rtld_relocate_plt_object(const Obj_Entr
 		__asm volatile("iflush %0+12" : : "r" (where));
 		__asm volatile("iflush %0+8" : : "r" (where));
 		__asm volatile("iflush %0+4" : : "r" (where));
-
 	} else if ((Elf_SOff)value < 0 && (Elf_SOff)value > -(1L<<44)) {
 		/*
 		 *  We're within 44 bits.  We can generate this pattern:
@@ -774,7 +760,6 @@ _rtld_relocate_plt_object(const Obj_Entr
 		__asm volatile("iflush %0+12" : : "r" (where));
 		__asm volatile("iflush %0+8" : : "r" (where));
 		__asm volatile("iflush %0+4" : : "r" (where));
-
 	} else {
 		/* 
 		 * We need to load all 64-bits
@@ -803,11 +788,82 @@ _rtld_relocate_plt_object(const Obj_Entr
 		__asm volatile("iflush %0+12" : : "r" (where));
 		__asm volatile("iflush %0+8" : : "r" (where));
 		__asm volatile("iflush %0+4" : : "r" (where));
+	}
+}
+
+/*
+ * New inline function that is called by _rtld_relocate_plt_object and
+ * _rtld_bind
+ */
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
+    Elf_Addr *tp)
+{
+	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+	Elf_Addr value;
+	unsigned long info = rela->r_info;
+
+	if (ELF_R_TYPE(info) == R_TYPE(JMP_IREL))
+		return 0;
+
+	assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+	def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+	if (__predict_false(def == NULL))
+		return -1;
+	if (__predict_false(def == &_rtld_sym_zero))
+		return 0;
 
+	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+		if (tp == NULL)
+			return 0;
+		value = _rtld_resolve_ifunc(defobj, def);
+	} else {
+		value = (Elf_Addr)(defobj->relocbase + def->st_value);
 	}
+	rdbg(("bind now/fixup in %s at %p --> new=%p", 
+	    defobj->strtab + def->st_name, (void*)where, (void *)value));
+
+	_rtld_write_plt(where, value, rela, obj);
 
 	if (tp)
 		*tp = value;
 
 	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);
+		_rtld_write_plt(where2, target, NULL, obj);
+	}
+
+	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;
+	}
+}

Index: src/sys/arch/sparc/include/elf_machdep.h
diff -u src/sys/arch/sparc/include/elf_machdep.h:1.8 src/sys/arch/sparc/include/elf_machdep.h:1.9
--- src/sys/arch/sparc/include/elf_machdep.h:1.8	Thu Feb  2 08:12:08 2017
+++ src/sys/arch/sparc/include/elf_machdep.h	Sat Aug 12 09:03:28 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: elf_machdep.h,v 1.8 2017/02/02 08:12:08 martin Exp $	*/
+/*	$NetBSD: elf_machdep.h,v 1.9 2017/08/12 09:03:28 joerg Exp $	*/
 
 #define ELF32_MACHDEP_ENDIANNESS	ELFDATA2MSB
 #define	ELF32_MACHDEP_ID_CASES						\
@@ -87,4 +87,7 @@
 #define R_SPARC_TLS_TPOFF32	78
 #define R_SPARC_TLS_TPOFF64	79
 
+#define R_SPARC_JMP_IREL	248
+#define R_SPARC_IRELATIVE	249
+
 #define R_TYPE(name)		__CONCAT(R_SPARC_,name)

Index: src/sys/arch/sparc64/include/elf_machdep.h
diff -u src/sys/arch/sparc64/include/elf_machdep.h:1.12 src/sys/arch/sparc64/include/elf_machdep.h:1.13
--- src/sys/arch/sparc64/include/elf_machdep.h:1.12	Tue Jan 31 16:13:56 2017
+++ src/sys/arch/sparc64/include/elf_machdep.h	Sat Aug 12 09:03:28 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: elf_machdep.h,v 1.12 2017/01/31 16:13:56 martin Exp $	*/
+/*	$NetBSD: elf_machdep.h,v 1.13 2017/08/12 09:03:28 joerg Exp $	*/
 
 #define ELF32_MACHDEP_ENDIANNESS	ELFDATA2MSB
 #define	ELF32_MACHDEP_ID_CASES						\
@@ -137,4 +137,7 @@ void sparc64_elf_mcmodel_check(struct ex
 #define R_SPARC_TLS_TPOFF32	78
 #define R_SPARC_TLS_TPOFF64	79
 
+#define R_SPARC_JMP_IREL	248
+#define R_SPARC_IRELATIVE	249
+
 #define R_TYPE(name)		__CONCAT(R_SPARC_,name)

Index: src/tests/libexec/ld.elf_so/t_ifunc.c
diff -u src/tests/libexec/ld.elf_so/t_ifunc.c:1.3 src/tests/libexec/ld.elf_so/t_ifunc.c:1.4
--- src/tests/libexec/ld.elf_so/t_ifunc.c:1.3	Thu Aug 10 19:03:27 2017
+++ src/tests/libexec/ld.elf_so/t_ifunc.c	Sat Aug 12 09:03:28 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_ifunc.c,v 1.3 2017/08/10 19:03:27 joerg Exp $	*/
+/*	$NetBSD: t_ifunc.c,v 1.4 2017/08/12 09:03:28 joerg Exp $	*/
 
 /*
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@ ATF_TC_BODY(rtld_ifunc, tc)
 	const char *error;
 	size_t i;
 
-#if !defined( __arm__) && !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__)
+#if !defined( __arm__) && !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) && !defined(__sparc__)
 	atf_tc_expect_fail("Missing linker support for hidden ifunc relocations");
 #endif
 
@@ -106,6 +106,7 @@ ATF_TC_BODY(rtld_hidden_ifunc, tc)
 	};
 	void *handle;
 	int (*sym)(void);
+	int (*(*sym2)(void))(void);
 	int result;
 	const char *error;
 	size_t i;
@@ -126,6 +127,15 @@ ATF_TC_BODY(rtld_hidden_ifunc, tc)
 		result = (*sym)();
 		ATF_CHECK(result == expected_result[!i]);
 
+		sym2 = dlsym(handle, "ifunc_indirect");
+		error = dlerror();
+		ATF_CHECK(error == NULL);
+		ATF_CHECK(sym2 != NULL);
+
+		sym = (*sym2)();
+		result = (*sym)();
+		ATF_CHECK(result == expected_result[!i]);
+
 		dlclose(handle);
 		error = dlerror();
 		ATF_CHECK(error == NULL);

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.5 src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c:1.6
--- src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c:1.5	Thu Aug 10 19:03:27 2017
+++ src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c	Sat Aug 12 09:03:28 2017
@@ -66,3 +66,10 @@ int ifunc_plt(void)
 {
 	return ifunc_hidden();
 }
+
+int (*ifunc_indirect(void))(void);
+
+int (*ifunc_indirect(void))(void)
+{
+	return ifunc_hidden;
+}

Reply via email to