Module Name: src
Committed By: joerg
Date: Mon Aug 25 20:40:53 UTC 2014
Modified Files:
src/distrib/sets/lists/debug: mi shl.mi
src/distrib/sets/lists/tests: mi shl.mi
src/libexec/ld.elf_so: headers.c 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/powerpc: ppc_reloc.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/sys: cdefs_elf.h exec_elf.h
src/tests/libexec/ld.elf_so: Makefile
Added Files:
src/tests/libexec/ld.elf_so: h_ifunc.c t_ifunc.c
src/tests/libexec/ld.elf_so/helper_ifunc_dso: Makefile h_helper_ifunc.c
Log Message:
Add basic support for indirect functions. It allows providing a public
function symbol with an implementation choosen at run time.
Refactor calls to functions by address in ld.elf_so to create temporary
function descriptors on the stack, if the address is not leaked outside.
Limitations:
- no support for initialising static storage with function pointers
- no support for unnamed resolver functions
Inspired by FreeBSD's r228435 by [email protected].
To generate a diff of this commit:
cvs rdiff -u -r1.84 -r1.85 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.72 -r1.73 src/distrib/sets/lists/debug/shl.mi
cvs rdiff -u -r1.589 -r1.590 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.8 -r1.9 src/distrib/sets/lists/tests/shl.mi
cvs rdiff -u -r1.54 -r1.55 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.106 -r1.107 src/libexec/ld.elf_so/reloc.c
cvs rdiff -u -r1.173 -r1.174 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.119 -r1.120 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.1 -r1.2 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
cvs rdiff -u -r1.40 -r1.41 src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c
cvs rdiff -u -r1.37 -r1.38 src/libexec/ld.elf_so/arch/arm/mdreloc.c
cvs rdiff -u -r1.42 -r1.43 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c
cvs rdiff -u -r1.35 -r1.36 src/libexec/ld.elf_so/arch/i386/mdreloc.c
cvs rdiff -u -r1.29 -r1.30 src/libexec/ld.elf_so/arch/m68k/mdreloc.c
cvs rdiff -u -r1.62 -r1.63 src/libexec/ld.elf_so/arch/mips/mips_reloc.c
cvs rdiff -u -r1.52 -r1.53 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
cvs rdiff -u -r1.30 -r1.31 src/libexec/ld.elf_so/arch/sh3/mdreloc.c
cvs rdiff -u -r1.47 -r1.48 src/libexec/ld.elf_so/arch/sparc/mdreloc.c
cvs rdiff -u -r1.56 -r1.57 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
cvs rdiff -u -r1.29 -r1.30 src/libexec/ld.elf_so/arch/vax/mdreloc.c
cvs rdiff -u -r1.40 -r1.41 src/libexec/ld.elf_so/arch/x86_64/mdreloc.c
cvs rdiff -u -r1.44 -r1.45 src/sys/sys/cdefs_elf.h
cvs rdiff -u -r1.142 -r1.143 src/sys/sys/exec_elf.h
cvs rdiff -u -r1.7 -r1.8 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/libexec/ld.elf_so/h_ifunc.c \
src/tests/libexec/ld.elf_so/t_ifunc.c
cvs rdiff -u -r0 -r1.1 src/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile \
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/distrib/sets/lists/debug/mi
diff -u src/distrib/sets/lists/debug/mi:1.84 src/distrib/sets/lists/debug/mi:1.85
--- src/distrib/sets/lists/debug/mi:1.84 Mon Aug 25 18:44:03 2014
+++ src/distrib/sets/lists/debug/mi Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.84 2014/08/25 18:44:03 pooka Exp $
+# $NetBSD: mi,v 1.85 2014/08/25 20:40:52 joerg Exp $
./etc/mtree/set.debug comp-sys-root
./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib
@@ -2131,11 +2131,13 @@
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v0.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v1.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v2.debug tests-libexec-debug debug,atf,pic
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_ifunc.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_locking.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlvsym.debug tests-libexec-debug debug,atf,pic
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_ifunc.debug tests-libexec-debug debug,atf,pic
./usr/libdata/debug/usr/tests/net/bpf/t_bpf.debug tests-net-debug debug,atf,rump
./usr/libdata/debug/usr/tests/net/bpf/t_div-by-zero.debug tests-net-debug debug,atf,rump
./usr/libdata/debug/usr/tests/net/bpf/t_mbuf.debug tests-net-debug debug,atf,rump
@@ -2224,3 +2226,4 @@
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso_g.a comp-c-debuglib atf,debuglib
./usr/tests/libexec/ld.elf_so/libh_helper_dso1_g.a comp-c-debuglib atf,debuglib
./usr/tests/libexec/ld.elf_so/libh_helper_dso2_g.a comp-c-debuglib atf,debuglib
+./usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso_g.a comp-c-debuglib atf,debuglib
Index: src/distrib/sets/lists/debug/shl.mi
diff -u src/distrib/sets/lists/debug/shl.mi:1.72 src/distrib/sets/lists/debug/shl.mi:1.73
--- src/distrib/sets/lists/debug/shl.mi:1.72 Mon Aug 25 18:44:03 2014
+++ src/distrib/sets/lists/debug/shl.mi Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.72 2014/08/25 18:44:03 pooka Exp $
+# $NetBSD: shl.mi,v 1.73 2014/08/25 20:40:52 joerg Exp $
./usr/libdata/debug/lib/libc.so.12.193.debug comp-sys-debug debug
./usr/libdata/debug/lib/libcrypt.so.1.0.debug comp-sys-debug debug
./usr/libdata/debug/lib/libcrypto.so.8.3.debug comp-sys-debug debug
@@ -287,3 +287,4 @@
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1.debug tests-libexec-debug debug,atf
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso.so.1.debug tests-libexec-debug debug,atf
Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.589 src/distrib/sets/lists/tests/mi:1.590
--- src/distrib/sets/lists/tests/mi:1.589 Sun Aug 24 11:52:45 2014
+++ src/distrib/sets/lists/tests/mi Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.589 2014/08/24 11:52:45 apb Exp $
+# $NetBSD: mi,v 1.590 2014/08/25 20:40:52 joerg Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -3068,6 +3068,7 @@
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/h_ifunc tests-libexec-tests atf,pic
./usr/tests/libexec/ld.elf_so/h_locking tests-libexec-tests atf,pic
./usr/tests/libexec/ld.elf_so/t_df_1_noopen tests-libexec-tests atf,pic
./usr/tests/libexec/ld.elf_so/t_dl_symver tests-libexec-tests atf,pic
@@ -3075,6 +3076,7 @@
./usr/tests/libexec/ld.elf_so/t_dlerror-false tests-libexec-tests atf,pic
./usr/tests/libexec/ld.elf_so/t_dlinfo tests-libexec-tests atf,pic
./usr/tests/libexec/ld.elf_so/t_dlvsym tests-libexec-tests atf,pic
+./usr/tests/libexec/ld.elf_so/t_ifunc tests-libexec-tests atf,pic
./usr/tests/modules tests-sys-tests
./usr/tests/net tests-net-tests
./usr/tests/net/Atffile tests-net-tests atf
Index: src/distrib/sets/lists/tests/shl.mi
diff -u src/distrib/sets/lists/tests/shl.mi:1.8 src/distrib/sets/lists/tests/shl.mi:1.9
--- src/distrib/sets/lists/tests/shl.mi:1.8 Sun Aug 11 22:29:03 2013
+++ src/distrib/sets/lists/tests/shl.mi Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.8 2013/08/11 22:29:03 joerg Exp $
+# $NetBSD: shl.mi,v 1.9 2014/08/25 20:40:52 joerg Exp $
#
./usr/tests/lib/csu/h_initfini3_dso.so tests-lib-tests atf
./usr/tests/lib/csu/h_initfini3_dso.so.1 tests-lib-tests atf
@@ -16,9 +16,11 @@
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1 tests-libexec-tests atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so tests-libexec-tests atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1 tests-libexec-tests atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so tests-libexec-tests atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1 tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1 tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1 tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso.so tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso.so.1 tests-libexec-tests atf
./usr/tests/util/id/libfake.so.0 tests-obsolete obsolete
./usr/tests/util/id/libfake.so.0.0 tests-obsolete obsolete
Index: src/libexec/ld.elf_so/headers.c
diff -u src/libexec/ld.elf_so/headers.c:1.54 src/libexec/ld.elf_so/headers.c:1.55
--- src/libexec/ld.elf_so/headers.c:1.54 Fri Mar 7 01:27:14 2014
+++ src/libexec/ld.elf_so/headers.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: headers.c,v 1.54 2014/03/07 01:27:14 matt Exp $ */
+/* $NetBSD: headers.c,v 1.55 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.54 2014/03/07 01:27:14 matt Exp $");
+__RCSID("$NetBSD: headers.c,v 1.55 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <err.h>
@@ -232,8 +232,7 @@ _rtld_digest_dynamic(const char *execnam
#ifdef HAVE_INITFINI_ARRAY
case DT_INIT_ARRAY:
- obj->init_array =
- (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr);
+ obj->init_array = (Elf_Addr *)obj->relocbase + dynp->d_un.d_ptr;
dbg(("headers: DT_INIT_ARRAY at %p",
obj->init_array));
break;
@@ -252,7 +251,7 @@ _rtld_digest_dynamic(const char *execnam
#ifdef HAVE_INITFINI_ARRAY
case DT_FINI_ARRAY:
obj->fini_array =
- (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr);
+ (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
dbg(("headers: DT_FINI_ARRAY at %p",
obj->fini_array));
break;
@@ -345,21 +344,10 @@ _rtld_digest_dynamic(const char *execnam
obj->relalim = obj->pltrela;
}
-#if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
if (init != 0)
- obj->init = (void (*)(void))
- _rtld_function_descriptor_alloc(obj, NULL, init);
+ obj->init = (Elf_Addr)obj->relocbase + init;
if (fini != 0)
- obj->fini = (void (*)(void))
- _rtld_function_descriptor_alloc(obj, NULL, fini);
-#else
- if (init != 0)
- obj->init = (void (*)(void))
- (obj->relocbase + init);
- if (fini != 0)
- obj->fini = (void (*)(void))
- (obj->relocbase + fini);
-#endif
+ obj->fini = (Elf_Addr)obj->relocbase + fini;
if (dyn_rpath != NULL) {
_rtld_add_paths(execname, &obj->rpaths, obj->strtab +
Index: src/libexec/ld.elf_so/reloc.c
diff -u src/libexec/ld.elf_so/reloc.c:1.106 src/libexec/ld.elf_so/reloc.c:1.107
--- src/libexec/ld.elf_so/reloc.c:1.106 Fri Jan 6 10:38:56 2012
+++ src/libexec/ld.elf_so/reloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: reloc.c,v 1.106 2012/01/06 10:38:56 skrll Exp $ */
+/* $NetBSD: reloc.c,v 1.107 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.106 2012/01/06 10:38:56 skrll Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.107 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <err.h>
@@ -226,3 +226,16 @@ _rtld_relocate_objects(Obj_Entry *first,
return 0;
}
+
+Elf_Addr
+_rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def)
+{
+ Elf_Addr target;
+
+ _rtld_shared_exit();
+ target = _rtld_call_function_addr(obj,
+ (Elf_Addr)obj->relocbase + def->st_value);
+ _rtld_shared_enter();
+
+ return target;
+}
Index: src/libexec/ld.elf_so/rtld.c
diff -u src/libexec/ld.elf_so/rtld.c:1.173 src/libexec/ld.elf_so/rtld.c:1.174
--- src/libexec/ld.elf_so/rtld.c:1.173 Tue Mar 18 16:05:34 2014
+++ src/libexec/ld.elf_so/rtld.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.173 2014/03/18 16:05:34 joerg Exp $ */
+/* $NetBSD: rtld.c,v 1.174 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.173 2014/03/18 16:05:34 joerg Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.174 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -136,25 +136,25 @@ static void _rtld_unref_dag(Obj_Entry *)
static Obj_Entry *_rtld_obj_from_addr(const void *);
static inline void
-_rtld_call_initfini_function(fptr_t func, sigset_t *mask)
+_rtld_call_initfini_function(const Obj_Entry *obj, Elf_Addr func, sigset_t *mask)
{
_rtld_exclusive_exit(mask);
- (*func)();
+ _rtld_call_function_void(obj, func);
_rtld_exclusive_enter(mask);
}
static void
_rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
{
- if (obj->fini_arraysz == 0 && (obj->fini == NULL || obj->fini_called)) {
- return;
- }
- if (obj->fini != NULL && !obj->fini_called) {
+ if (obj->fini_arraysz == 0 && (obj->fini == 0 || obj->fini_called))
+ return;
+
+ if (obj->fini != 0 && !obj->fini_called) {
dbg (("calling fini function %s at %p%s", obj->path,
(void *)obj->fini,
obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
obj->fini_called = 1;
- _rtld_call_initfini_function(obj->fini, mask);
+ _rtld_call_initfini_function(obj, obj->fini, mask);
}
#ifdef HAVE_INITFINI_ARRAY
/*
@@ -164,12 +164,12 @@ _rtld_call_fini_function(Obj_Entry *obj,
* the loop.
*/
while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) {
- fptr_t fini = *obj->fini_array++;
+ Elf_Addr fini = *obj->fini_array++;
obj->fini_arraysz--;
dbg (("calling fini array function %s at %p%s", obj->path,
(void *)fini,
obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
- _rtld_call_initfini_function(fini, mask);
+ _rtld_call_initfini_function(obj, fini, mask);
}
#endif /* HAVE_INITFINI_ARRAY */
}
@@ -230,15 +230,15 @@ restart:
static void
_rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
{
- if (obj->init_arraysz == 0 && (obj->init_called || obj->init == NULL)) {
+ if (obj->init_arraysz == 0 && (obj->init_called || obj->init == 0))
return;
- }
- if (!obj->init_called && obj->init != NULL) {
+
+ if (!obj->init_called && obj->init != 0) {
dbg (("calling init function %s at %p%s",
obj->path, (void *)obj->init,
obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
obj->init_called = 1;
- _rtld_call_initfini_function(obj->init, mask);
+ _rtld_call_initfini_function(obj, obj->init, mask);
}
#ifdef HAVE_INITFINI_ARRAY
@@ -249,12 +249,12 @@ _rtld_call_init_function(Obj_Entry *obj,
* the loop.
*/
while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) {
- fptr_t init = *obj->init_array++;
+ Elf_Addr init = *obj->init_array++;
obj->init_arraysz--;
dbg (("calling init_array function %s at %p%s",
obj->path, (void *)init,
obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
- _rtld_call_initfini_function(init, mask);
+ _rtld_call_initfini_function(obj, init, mask);
}
#endif /* HAVE_INITFINI_ARRAY */
}
@@ -1176,6 +1176,17 @@ do_dlsym(void *handle, const char *name,
if (def != NULL) {
void *p;
+
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+#ifdef __HAVE_FUNCTION_DESCRIPTORS
+ lookup_mutex_exit();
+ _rtld_shared_enter();
+#endif
+ p = (void *)_rtld_resolve_ifunc(defobj, def);
+ _rtld_shared_exit();
+ return p;
+ }
+
#ifdef __HAVE_FUNCTION_DESCRIPTORS
if (ELF_ST_TYPE(def->st_info) == STT_FUNC) {
p = (void *)_rtld_function_descriptor_alloc(defobj,
Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.119 src/libexec/ld.elf_so/rtld.h:1.120
--- src/libexec/ld.elf_so/rtld.h:1.119 Sat Aug 23 18:05:33 2014
+++ src/libexec/ld.elf_so/rtld.h Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.119 2014/08/23 18:05:33 joerg Exp $ */
+/* $NetBSD: rtld.h,v 1.120 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -193,8 +193,8 @@ typedef struct Struct_Obj_Entry {
Search_Path *rpaths; /* Search path specified in object */
Needed_Entry *needed; /* Shared objects needed by this (%) */
- fptr_t init; /* Initialization function to call */
- fptr_t fini; /* Termination function to call */
+ Elf_Addr init; /* Initialization function to call */
+ Elf_Addr fini; /* Termination function to call */
/*
* BACKWARDS COMPAT Entry points for dlopen() and friends.
@@ -288,9 +288,9 @@ typedef struct Struct_Obj_Entry {
int vertabnum; /* Number of entries in vertab */
/* init_array/fini_array */
- fptr_t *init_array; /* start of init array */
+ Elf_Addr *init_array; /* start of init array */
size_t init_arraysz; /* # of entries in it */
- fptr_t *fini_array; /* start of fini array */
+ Elf_Addr *fini_array; /* start of fini array */
size_t fini_arraysz; /* # of entries in it */
#ifdef __ARM_EABI__
void *exidx_start;
@@ -404,6 +404,7 @@ int _rtld_relocate_nonplt_objects(Obj_En
int _rtld_relocate_plt_lazy(const 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 *);
/* search.c */
Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
@@ -479,6 +480,20 @@ Obj_Entry *_rtld_obj_new(void);
Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *,
const Elf_Sym *, Elf_Addr);
const void *_rtld_function_descriptor_function(const void *);
+
+void _rtld_call_function_void(const Obj_Entry *, Elf_Addr);
+Elf_Addr _rtld_call_function_addr(const Obj_Entry *, Elf_Addr);
+#else
+static inline void
+_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr addr)
+{
+ ((void (*)(void))addr)();
+}
+static inline Elf_Addr
+_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr addr)
+{
+ return ((Elf_Addr(*)(void))addr)();
+}
#endif /* __HAVE_FUNCTION_DESCRIPTORS */
#endif /* _RTLD_SOURCE */
Index: src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.1 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.2
--- src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.1 Sun Aug 10 05:47:37 2014
+++ src/libexec/ld.elf_so/arch/aarch64/mdreloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.1 2014/08/10 05:47:37 matt Exp $ */
+/* $NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 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.1 2014/08/10 05:47:37 matt Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -222,7 +222,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ }
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
Index: src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c
diff -u src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.40 src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.41
--- src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.40 Thu Mar 31 15:30:31 2011
+++ src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: alpha_reloc.c,v 1.40 2011/03/31 15:30:31 skrll Exp $ */
+/* $NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 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.40 2011/03/31 15:30:31 skrll Exp $");
+__RCSID("$NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -376,7 +376,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ }
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
Index: src/libexec/ld.elf_so/arch/arm/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.37 src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.38
--- src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.37 Fri Nov 18 16:10:03 2011
+++ src/libexec/ld.elf_so/arch/arm/mdreloc.c Mon Aug 25 20:40:52 2014
@@ -1,8 +1,8 @@
-/* $NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -286,7 +286,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ }
/* Set the Thumb bit, if needed. */
if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
new_value |= 1;
Index: src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c
diff -u src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.42 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.43
--- src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.42 Fri Jan 6 10:38:57 2012
+++ src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: hppa_reloc.c,v 1.42 2012/01/06 10:38:57 skrll Exp $ */
+/* $NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 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.42 2012/01/06 10:38:57 skrll Exp $");
+__RCSID("$NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <stdlib.h>
@@ -656,9 +656,19 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
- rela->r_addend);
- func_sl = (Elf_Addr)(defobj->pltgot);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ Elf_Addr ptr = _rtld_resolve_ifunc(defobj, def);
+ assert(RTLD_IS_PLABEL(ptr));
+ hppa_plabel *label = RTLD_GET_PLABEL(ptr);
+ func_pc = label->hppa_plabel_pc;
+ func_sl = label->hppa_plabel_sl;
+ } else {
+ func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
+ rela->r_addend);
+ func_sl = (Elf_Addr)(defobj->pltgot);
+ }
rdbg(("bind now/fixup in %s --> old=(%p,%p) new=(%p,%p)",
defobj->strtab + def->st_name,
@@ -710,3 +720,29 @@ _rtld_relocate_plt_objects(const Obj_Ent
}
return 0;
}
+
+void
+_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr ptr)
+{
+ volatile hppa_plabel plabel;
+ void (*f)(void);
+
+ plabel.hppa_plabel_pc = (Elf_Addr)ptr;
+ plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot);
+ f = (void (*)(void))RTLD_MAKE_PLABEL(&plabel);
+
+ f();
+}
+
+Elf_Addr
+_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr ptr)
+{
+ volatile hppa_plabel plabel;
+ Elf_Addr (*f)(void);
+
+ plabel.hppa_plabel_pc = (Elf_Addr)ptr;
+ plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot);
+ f = (Elf_Addr (*)(void))RTLD_MAKE_PLABEL(&plabel);
+
+ return f();
+}
Index: src/libexec/ld.elf_so/arch/i386/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.35 src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.36
--- src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.35 Wed Nov 7 07:24:46 2012
+++ src/libexec/ld.elf_so/arch/i386/mdreloc.c Mon Aug 25 20:40:52 2014
@@ -1,8 +1,8 @@
-/* $NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $ */
+/* $NetBSD: mdreloc.c,v 1.36 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.36 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -230,6 +230,14 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ target = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ target = (Elf_Addr)(defobj->relocbase + def->st_value);
+ }
+
target = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where,
Index: src/libexec/ld.elf_so/arch/m68k/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.29 src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.30
--- src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.29 Tue Nov 22 15:25:28 2011
+++ src/libexec/ld.elf_so/arch/m68k/mdreloc.c Mon Aug 25 20:40:52 2014
@@ -1,13 +1,13 @@
-/* $NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -223,8 +223,14 @@ _rtld_relocate_plt_object(const Obj_Entr
return 0;
assert(rela->r_addend == 0);
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
- rela->r_addend);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
+ rela->r_addend);
+ }
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
Index: src/libexec/ld.elf_so/arch/mips/mips_reloc.c
diff -u src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.62 src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.63
--- src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.62 Fri Mar 25 18:07:05 2011
+++ src/libexec/ld.elf_so/arch/mips/mips_reloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: mips_reloc.c,v 1.62 2011/03/25 18:07:05 joerg Exp $ */
+/* $NetBSD: mips_reloc.c,v 1.63 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright 1997 Michael L. Hitch <[email protected]>
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mips_reloc.c,v 1.62 2011/03/25 18:07:05 joerg Exp $");
+__RCSID("$NetBSD: mips_reloc.c,v 1.63 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -487,7 +487,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ }
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)new_value));
got[obj->local_gotno + sym - obj->gotsym] = new_value;
Index: src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
diff -u src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.52 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.53
--- src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.52 Mon Jul 28 17:28:13 2014
+++ src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: ppc_reloc.c,v 1.52 2014/07/28 17:28:13 matt Exp $ */
+/* $NetBSD: ppc_reloc.c,v 1.53 2014/08/25 20:40:52 joerg Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: ppc_reloc.c,v 1.52 2014/07/28 17:28:13 matt Exp $");
+__RCSID("$NetBSD: ppc_reloc.c,v 1.53 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <stdarg.h>
@@ -366,7 +366,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ 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 --> new=%p",
defobj->strtab + def->st_name, (void *)value));
Index: src/libexec/ld.elf_so/arch/sh3/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.30 src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.31
--- src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.30 Fri Mar 25 18:07:06 2011
+++ src/libexec/ld.elf_so/arch/sh3/mdreloc.c Mon Aug 25 20:40:52 2014
@@ -1,13 +1,13 @@
-/* $NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.31 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.31 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.31 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -282,7 +282,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ }
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
Index: src/libexec/ld.elf_so/arch/sparc/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.47 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.48
--- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.47 Thu Mar 31 12:47:01 2011
+++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.47 2011/03/31 12:47:01 nakayama Exp $ */
+/* $NetBSD: mdreloc.c,v 1.48 2014/08/25 20:40:52 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.47 2011/03/31 12:47:01 nakayama Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.48 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <errno.h>
@@ -448,7 +448,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ 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 --> new=%p",
defobj->strtab + def->st_name, (void *)value));
Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.56 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.57
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.56 Wed Apr 2 14:11:25 2014
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c Mon Aug 25 20:40:53 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $ */
+/* $NetBSD: mdreloc.c,v 1.57 2014/08/25 20:40:53 joerg Exp $ */
/*-
* Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.57 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <errno.h>
@@ -602,7 +602,13 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- value = (Elf_Addr)(defobj->relocbase + def->st_value);
+ 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));
Index: src/libexec/ld.elf_so/arch/vax/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.29 src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.30
--- src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.29 Fri Mar 21 01:43:33 2014
+++ src/libexec/ld.elf_so/arch/vax/mdreloc.c Mon Aug 25 20:40:53 2014
@@ -1,13 +1,13 @@
-/* $NetBSD: mdreloc.c,v 1.29 2014/03/21 01:43:33 matt Exp $ */
+/* $NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:53 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.29 2014/03/21 01:43:33 matt Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.29 2014/03/21 01:43:33 matt Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -166,8 +166,14 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
- rela->r_addend);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
+ rela->r_addend);
+ }
rdbg(("bind now/fixup pltgot %p in %s --> old=%p new=%p", where,
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
Index: src/libexec/ld.elf_so/arch/x86_64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.40 src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.41
--- src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.40 Fri Mar 25 18:07:07 2011
+++ src/libexec/ld.elf_so/arch/x86_64/mdreloc.c Mon Aug 25 20:40:53 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.40 2011/03/25 18:07:07 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -68,7 +68,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.40 2011/03/25 18:07:07 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -313,8 +313,15 @@ _rtld_relocate_plt_object(const Obj_Entr
if (__predict_false(def == &_rtld_sym_zero))
return 0;
- new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
- rela->r_addend);
+ if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+ if (tp == NULL)
+ return 0;
+ new_value = _rtld_resolve_ifunc(defobj, def);
+ } else {
+ new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
+ rela->r_addend);
+ }
+
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
Index: src/sys/sys/cdefs_elf.h
diff -u src/sys/sys/cdefs_elf.h:1.44 src/sys/sys/cdefs_elf.h:1.45
--- src/sys/sys/cdefs_elf.h:1.44 Tue May 13 19:58:23 2014
+++ src/sys/sys/cdefs_elf.h Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: cdefs_elf.h,v 1.44 2014/05/13 19:58:23 christos Exp $ */
+/* $NetBSD: cdefs_elf.h,v 1.45 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
@@ -106,6 +106,18 @@
#endif /* !__STDC__ */
+#if __arm__
+#define __ifunc(name, resolver) \
+ __asm(".globl " _C_LABEL_STRING(#name) "\n" \
+ ".type " _C_LABEL_STRING(#name) ", %gnu_indirect_function\n" \
+ ".set " _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" \
+ ".set " _C_LABEL_STRING(#name) ", " _C_LABEL_STRING(#resolver))
+#endif
+
#if __STDC__
#define __SECTIONSTRING(_sec, _str) \
__asm(".pushsection " #_sec "\n" \
Index: src/sys/sys/exec_elf.h
diff -u src/sys/sys/exec_elf.h:1.142 src/sys/sys/exec_elf.h:1.143
--- src/sys/sys/exec_elf.h:1.142 Tue Aug 19 07:26:45 2014
+++ src/sys/sys/exec_elf.h Mon Aug 25 20:40:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_elf.h,v 1.142 2014/08/19 07:26:45 matt Exp $ */
+/* $NetBSD: exec_elf.h,v 1.143 2014/08/25 20:40:52 joerg Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
@@ -516,6 +516,7 @@ typedef struct {
#define STT_NUM 7
#define STT_LOOS 10 /* Operating system specific range */
+#define STT_GNU_IFUNC 10 /* GNU extension: indirect function */
#define STT_HIOS 12
#define STT_LOPROC 13 /* Processor-specific range */
#define STT_HIPROC 15
Index: src/tests/libexec/ld.elf_so/Makefile
diff -u src/tests/libexec/ld.elf_so/Makefile:1.7 src/tests/libexec/ld.elf_so/Makefile:1.8
--- src/tests/libexec/ld.elf_so/Makefile:1.7 Sun Jul 3 15:28:25 2011
+++ src/tests/libexec/ld.elf_so/Makefile Mon Aug 25 20:40:53 2014
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.7 2011/07/03 15:28:25 mrg Exp $
+# $NetBSD: Makefile,v 1.8 2014/08/25 20:40:53 joerg Exp $
#
NOMAN= # defined
@@ -8,16 +8,19 @@ NOMAN= # defined
.if ${MKPIC} != "no"
SUBDIR+= helper_dso1 .WAIT helper_dso2 .WAIT \
+ helper_ifunc_dso \
helper_symver_dso0 .WAIT helper_symver_dso1 .WAIT \
helper_symver_dso2 .WAIT \
data
TESTSDIR= ${TESTSBASE}/libexec/ld.elf_so
-TESTS_C+= t_dlerror-cleared t_dlerror-false t_dlinfo t_dlvsym
+TESTS_C+= t_dlerror-cleared t_dlerror-false t_dlinfo t_dlvsym t_ifunc
LDADD.t_dlerror-false= -Wl,-rpath,/var/nonexistent/lib
LDADD.t_dlvsym= -Wl,-rpath,${TESTSDIR}/h_helper_symver_dso2
+LDADD.t_ifunc= -Wl,-rpath,${TESTSDIR} -lutil
+DPADD.t_ifunc= ${LIBUTIL}
TESTS_SH+= t_df_1_noopen t_dl_symver
@@ -29,6 +32,11 @@ PROGS+= h_df_1_noopen2
SRCS.h_df_1_noopen2= h_df_1_noopen.c
LDADD.h_df_1_noopen2= -lpthread
+PROGS+= h_ifunc
+SRCS.h_ifunc= h_ifunc.c
+IFUNCDIR!= cd ${.CURDIR}/helper_ifunc_dso && ${PRINTOBJDIR}
+LDADD.h_ifunc= -Wl,-rpath,${TESTSDIR} -L${IFUNCDIR} -lh_helper_ifunc_dso
+
PROGS+= h_locking
SRCS.h_locking= h_locking.c
LDADD.h_locking= -lpthread -Wl,--export-dynamic -Wl,-rpath,${TESTSDIR}
Added files:
Index: src/tests/libexec/ld.elf_so/h_ifunc.c
diff -u /dev/null src/tests/libexec/ld.elf_so/h_ifunc.c:1.1
--- /dev/null Mon Aug 25 20:40:53 2014
+++ src/tests/libexec/ld.elf_so/h_ifunc.c Mon Aug 25 20:40:53 2014
@@ -0,0 +1,43 @@
+/* $NetBSD: h_ifunc.c,v 1.1 2014/08/25 20:40:53 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+extern int ifunc(void);
+
+int
+main(int argc, char **argv)
+{
+
+ if (argc != 2)
+ return 1;
+ return ifunc() != atoi(argv[1]);
+}
Index: src/tests/libexec/ld.elf_so/t_ifunc.c
diff -u /dev/null src/tests/libexec/ld.elf_so/t_ifunc.c:1.1
--- /dev/null Mon Aug 25 20:40:53 2014
+++ src/tests/libexec/ld.elf_so/t_ifunc.c Mon Aug 25 20:40:53 2014
@@ -0,0 +1,92 @@
+/* $NetBSD: t_ifunc.c,v 1.1 2014/08/25 20:40:53 joerg Exp $ */
+
+/*
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#include <atf-c.h>
+#include <dlfcn.h>
+#include <util.h>
+
+#include "../../h_macros.h"
+
+ATF_TC(rtld_ifunc);
+
+ATF_TC_HEAD(rtld_ifunc, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "ifunc functions are resolved");
+}
+
+ATF_TC_BODY(rtld_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");
+ 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);
+ return 0;
+}
Index: src/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile
diff -u /dev/null src/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile:1.1
--- /dev/null Mon Aug 25 20:40:53 2014
+++ src/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile Mon Aug 25 20:40:53 2014
@@ -0,0 +1,19 @@
+# $NetBSD: Makefile,v 1.1 2014/08/25 20:40:53 joerg Exp $
+
+.include <bsd.own.mk>
+
+LIB= h_helper_ifunc_dso
+SRCS= h_helper_ifunc.c
+
+LIBDIR= ${TESTSBASE}/libexec/ld.elf_so
+SHLIBDIR= ${TESTSBASE}/libexec/ld.elf_so
+SHLIB_MAJOR= 1
+
+MKSTATICLIB= no
+MKPROFILE= no
+MKPICINSTALL= no
+MKLINT= no
+
+NOMAN= # defined
+
+.include <bsd.lib.mk>
Index: src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c
diff -u /dev/null src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c:1.1
--- /dev/null Mon Aug 25 20:40:53 2014
+++ src/tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c Mon Aug 25 20:40:53 2014
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+static int
+ifunc1(void)
+{
+ return 0xdeadbeef;
+}
+
+static int
+ifunc2(void)
+{
+ return 0xbeefdead;
+}
+
+static __attribute__((used))
+int (*resolve_ifunc(void))(void)
+{
+ const char *e = getenv("USE_IFUNC2");
+ return e && strcmp(e, "1") == 0 ? ifunc2 : ifunc1;
+}
+
+__ifunc(ifunc, resolve_ifunc);