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