Module Name:    src
Committed By:   martin
Date:           Sun Mar  6 18:17:56 UTC 2016

Modified Files:
        src/libexec/ld.elf_so [netbsd-7]: headers.c map_object.c paths.c
            reloc.c rtld.c rtld.h
        src/libexec/ld.elf_so/arch/aarch64 [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/alpha [netbsd-7]: alpha_reloc.c
        src/libexec/ld.elf_so/arch/arm [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/hppa [netbsd-7]: hppa_reloc.c
        src/libexec/ld.elf_so/arch/i386 [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/m68k [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/mips [netbsd-7]: mips_reloc.c
        src/libexec/ld.elf_so/arch/powerpc [netbsd-7]: ppc_reloc.c
        src/libexec/ld.elf_so/arch/sh3 [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/sparc [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/sparc64 [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/vax [netbsd-7]: mdreloc.c
        src/libexec/ld.elf_so/arch/x86_64 [netbsd-7]: mdreloc.c

Log Message:
Catch up to -current, via patch, requested by christos in ticket #1126:


To generate a diff of this commit:
cvs rdiff -u -r1.54 -r1.54.4.1 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.52 -r1.52.4.1 src/libexec/ld.elf_so/map_object.c
cvs rdiff -u -r1.41 -r1.41.6.1 src/libexec/ld.elf_so/paths.c
cvs rdiff -u -r1.106 -r1.106.18.1 src/libexec/ld.elf_so/reloc.c
cvs rdiff -u -r1.173.4.2 -r1.173.4.3 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.118 -r1.118.2.1 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.1 -r1.1.2.1 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
cvs rdiff -u -r1.40 -r1.40.22.1 \
    src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c
cvs rdiff -u -r1.37 -r1.37.18.1 src/libexec/ld.elf_so/arch/arm/mdreloc.c
cvs rdiff -u -r1.42 -r1.42.18.1 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c
cvs rdiff -u -r1.35 -r1.35.8.1 src/libexec/ld.elf_so/arch/i386/mdreloc.c
cvs rdiff -u -r1.29 -r1.29.18.1 src/libexec/ld.elf_so/arch/m68k/mdreloc.c
cvs rdiff -u -r1.62 -r1.62.22.1 src/libexec/ld.elf_so/arch/mips/mips_reloc.c
cvs rdiff -u -r1.52 -r1.52.2.1 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
cvs rdiff -u -r1.30 -r1.30.22.1 src/libexec/ld.elf_so/arch/sh3/mdreloc.c
cvs rdiff -u -r1.47 -r1.47.22.1 src/libexec/ld.elf_so/arch/sparc/mdreloc.c
cvs rdiff -u -r1.56 -r1.56.4.1 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
cvs rdiff -u -r1.29 -r1.29.4.1 src/libexec/ld.elf_so/arch/vax/mdreloc.c
cvs rdiff -u -r1.40 -r1.40.22.1 src/libexec/ld.elf_so/arch/x86_64/mdreloc.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/headers.c
diff -u src/libexec/ld.elf_so/headers.c:1.54 src/libexec/ld.elf_so/headers.c:1.54.4.1
--- src/libexec/ld.elf_so/headers.c:1.54	Fri Mar  7 01:27:14 2014
+++ src/libexec/ld.elf_so/headers.c	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: headers.c,v 1.54 2014/03/07 01:27:14 matt Exp $	 */
+/*	$NetBSD: headers.c,v 1.54.4.1 2016/03/06 18:17:55 martin 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.54.4.1 2016/03/06 18:17:55 martin Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -74,7 +74,9 @@ _rtld_digest_dynamic(const char *execnam
 	bool		use_pltrela = false;
 	Elf_Addr        relsz = 0, relasz = 0;
 	Elf_Addr	pltrel = 0, pltrelsz = 0;
+#ifdef RTLD_LOADER
 	Elf_Addr	init = 0, fini = 0;
+#endif
 
 	dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic));
 	for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
@@ -227,13 +229,15 @@ _rtld_digest_dynamic(const char *execnam
 			break;
 
 		case DT_INIT:
+#ifdef RTLD_LOADER
 			init = dynp->d_un.d_ptr;
+#endif
 			break;
 
 #ifdef HAVE_INITFINI_ARRAY
 		case DT_INIT_ARRAY:
 			obj->init_array =
-			    (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr);
+			    (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
 			dbg(("headers: DT_INIT_ARRAY at %p",
 			    obj->init_array));
 			break;
@@ -246,13 +250,15 @@ _rtld_digest_dynamic(const char *execnam
 #endif
 
 		case DT_FINI:
+#ifdef RTLD_LOADER
 			fini = dynp->d_un.d_ptr;
+#endif
 			break;
 
 #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,20 +351,11 @@ _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);
-	if (fini != 0)
-		obj->fini = (void (*)(void))
-		    _rtld_function_descriptor_alloc(obj, NULL, fini);
-#else
+#ifdef RTLD_LOADER
 	if (init != 0)
-		obj->init = (void (*)(void))
-		    (obj->relocbase + init);
+		obj->init = (Elf_Addr) obj->relocbase + init;
 	if (fini != 0)
-		obj->fini = (void (*)(void))
-		    (obj->relocbase + fini);
+		obj->fini = (Elf_Addr) obj->relocbase + fini;
 #endif
 
 	if (dyn_rpath != NULL) {

Index: src/libexec/ld.elf_so/map_object.c
diff -u src/libexec/ld.elf_so/map_object.c:1.52 src/libexec/ld.elf_so/map_object.c:1.52.4.1
--- src/libexec/ld.elf_so/map_object.c:1.52	Sat Aug  3 13:17:05 2013
+++ src/libexec/ld.elf_so/map_object.c	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: map_object.c,v 1.52 2013/08/03 13:17:05 skrll Exp $	 */
+/*	$NetBSD: map_object.c,v 1.52.4.1 2016/03/06 18:17:55 martin Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: map_object.c,v 1.52 2013/08/03 13:17:05 skrll Exp $");
+__RCSID("$NetBSD: map_object.c,v 1.52.4.1 2016/03/06 18:17:55 martin Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -442,10 +442,10 @@ _rtld_obj_free(Obj_Entry *obj)
 	}
 	if (!obj->phdr_loaded)
 		xfree((void *)(uintptr_t)obj->phdr);
-	xfree(obj);
 #ifdef COMBRELOC
 	_rtld_combreloc_reset(obj);
 #endif
+	xfree(obj);
 }
 
 Obj_Entry *

Index: src/libexec/ld.elf_so/paths.c
diff -u src/libexec/ld.elf_so/paths.c:1.41 src/libexec/ld.elf_so/paths.c:1.41.6.1
--- src/libexec/ld.elf_so/paths.c:1.41	Mon May  6 08:02:20 2013
+++ src/libexec/ld.elf_so/paths.c	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: paths.c,v 1.41 2013/05/06 08:02:20 skrll Exp $	 */
+/*	$NetBSD: paths.c,v 1.41.6.1 2016/03/06 18:17:55 martin Exp $	 */
 
 /*
  * Copyright 1996 Matt Thomas <[email protected]>
@@ -30,7 +30,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: paths.c,v 1.41 2013/05/06 08:02:20 skrll Exp $");
+__RCSID("$NetBSD: paths.c,v 1.41.6.1 2016/03/06 18:17:55 martin Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -49,7 +49,6 @@ __RCSID("$NetBSD: paths.c,v 1.41 2013/05
 #include <sys/gmon.h>
 #include <sys/socket.h>
 #include <sys/mount.h>
-#include <sys/mbuf.h>
 #include <sys/resource.h>
 #include <machine/cpu.h>
 

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.106.18.1
--- src/libexec/ld.elf_so/reloc.c:1.106	Fri Jan  6 10:38:56 2012
+++ src/libexec/ld.elf_so/reloc.c	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: reloc.c,v 1.106 2012/01/06 10:38:56 skrll Exp $	 */
+/*	$NetBSD: reloc.c,v 1.106.18.1 2016/03/06 18:17:55 martin 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.106.18.1 2016/03/06 18:17:55 martin 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.4.2 src/libexec/ld.elf_so/rtld.c:1.173.4.3
--- src/libexec/ld.elf_so/rtld.c:1.173.4.2	Mon Apr  6 02:01:39 2015
+++ src/libexec/ld.elf_so/rtld.c	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.c,v 1.173.4.2 2015/04/06 02:01:39 snj Exp $	 */
+/*	$NetBSD: rtld.c,v 1.173.4.3 2016/03/06 18:17:55 martin Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.173.4.2 2015/04/06 02:01:39 snj Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.173.4.3 2016/03/06 18:17:55 martin 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,
@@ -1533,6 +1544,7 @@ _rtld_shared_enter(void)
 			/* Yes, so increment use counter */
 			if (atomic_cas_uint(&_rtld_mutex, cur, cur + 1) != cur)
 				continue;
+			membar_enter();
 			return;
 		}
 		/*
@@ -1550,6 +1562,7 @@ _rtld_shared_enter(void)
 		/*
 		 * Check for race against _rtld_exclusive_exit before sleeping.
 		 */
+		membar_sync();
 		if ((_rtld_mutex & RTLD_EXCLUSIVE_MASK) ||
 		    _rtld_waiter_exclusive)
 			_lwp_park(CLOCK_REALTIME, 0, NULL, 0,
@@ -1577,12 +1590,12 @@ _rtld_shared_exit(void)
 	 * Wakeup LWPs waiting for an exclusive lock if this is the last
 	 * LWP on the shared lock.
 	 */
+	membar_exit();
 	if (atomic_dec_uint_nv(&_rtld_mutex))
 		return;
+	membar_sync();
 	if ((waiter = _rtld_waiter_exclusive) != 0)
 		_lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
-
-	membar_exit();
 }
 
 void
@@ -1597,12 +1610,13 @@ _rtld_exclusive_enter(sigset_t *mask)
 	sigdelset(&blockmask, SIGTRAP);	/* Allow the debugger */
 	sigprocmask(SIG_BLOCK, &blockmask, mask);
 
-	membar_enter();
-
 	for (;;) {
-		if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0)
+		if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) {
+			membar_enter();
 			break;
+		}
 		waiter = atomic_swap_uint(&_rtld_waiter_exclusive, self);
+		membar_sync();
 		cur = _rtld_mutex;
 		if (cur == locked_value) {
 			_rtld_error("dead lock detected");
@@ -1622,13 +1636,14 @@ _rtld_exclusive_exit(sigset_t *mask)
 {
 	lwpid_t waiter;
 
+	membar_exit();
 	_rtld_mutex = 0;
+	membar_sync();
 	if ((waiter = _rtld_waiter_exclusive) != 0)
 		_lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
 
 	if ((waiter = _rtld_waiter_shared) != 0)
 		_lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
 
-	membar_exit();
 	sigprocmask(SIG_SETMASK, mask, NULL);
 }

Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.118 src/libexec/ld.elf_so/rtld.h:1.118.2.1
--- src/libexec/ld.elf_so/rtld.h:1.118	Sun Aug 10 23:35:26 2014
+++ src/libexec/ld.elf_so/rtld.h	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.h,v 1.118 2014/08/10 23:35:26 matt Exp $	 */
+/*	$NetBSD: rtld.h,v 1.118.2.1 2016/03/06 18:17:55 martin Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -179,7 +179,7 @@ typedef struct Struct_Obj_Entry {
 	const Elf_Sym  *symtab;		/* Symbol table */
 	const char     *strtab;		/* String table */
 	unsigned long   strsize;	/* Size in bytes of string table */
-#ifdef __mips__
+#if defined(__mips__) || defined(__riscv__)
 	Elf_Word        local_gotno;	/* Number of local GOT entries */
 	Elf_Word        symtabno;	/* Number of dynamic symbols */
 	Elf_Word        gotsym;		/* First dynamic symbol in GOT */
@@ -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;
@@ -326,7 +326,7 @@ extern Elf_Sym _rtld_sym_zero;
 
 /* Flags to be passed into _rtld_symlook_ family of functions. */
 #define SYMLOOK_IN_PLT	0x01	/* Lookup for PLT symbol */
-#define SYMLOOK_DLSYM	0x02	/* Return newes versioned symbol.
+#define SYMLOOK_DLSYM	0x02	/* Return newest versioned symbol.
 				   Used by dlsym. */
 
 /* Flags for _rtld_load_object() and friends. */
@@ -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);
@@ -474,12 +475,28 @@ Obj_Entry *_rtld_map_object(const char *
 void _rtld_obj_free(Obj_Entry *);
 Obj_Entry *_rtld_obj_new(void);
 
+#ifdef RTLD_LOADER
 /* function descriptors */
 #ifdef __HAVE_FUNCTION_DESCRIPTORS
 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_LOADER */
 
 #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.1.2.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.1 2014/08/10 05:47:37 matt Exp $ */
+/* $NetBSD: mdreloc.c,v 1.1.2.1 2016/03/06 18:17:55 martin 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.1.2.1 2016/03/06 18:17:55 martin 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.40.22.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -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.40.22.1 2016/03/06 18:17:55 martin 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.40.22.1 2016/03/06 18:17:55 martin 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.37.18.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.37.18.1 2016/03/06 18:17:55 martin 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.37.18.1 2016/03/06 18:17:55 martin 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.42.18.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -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.42.18.1 2016/03/06 18:17:55 martin 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.42.18.1 2016/03/06 18:17:55 martin 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.35.8.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.35.8.1 2016/03/06 18:17:55 martin 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.35.8.1 2016/03/06 18:17:55 martin Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -230,7 +230,14 @@ _rtld_relocate_plt_object(const Obj_Entr
 	if (__predict_false(def == &_rtld_sym_zero))
 		return 0;
 
-	target = (Elf_Addr)(defobj->relocbase + def->st_value);
+	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);
+	}
+
 	rdbg(("bind now/fixup in %s --> old=%p new=%p",
 	    defobj->strtab + def->st_name, (void *)*where, 
 	    (void *)target));

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.29.18.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -1,13 +1,13 @@
-/*	$NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.29.18.1 2016/03/06 18:17:55 martin 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.29.18.1 2016/03/06 18:17:55 martin 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.29.18.1 2016/03/06 18:17:55 martin 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.62.22.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -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.62.22.1 2016/03/06 18:17:55 martin 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.62.22.1 2016/03/06 18:17:55 martin Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -445,7 +445,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 			rdbg(("TPREL %s in %s --> %p in %s",
 			    obj->strtab + obj->symtab[r_symndx].st_name,
-			    obj->path, (void *)*where, defobj->path));
+			    obj->path, where, defobj->path));
 			break;
 		}
 
@@ -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.52.2.1
--- 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	Sun Mar  6 18:17:55 2016
@@ -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.52.2.1 2016/03/06 18:17:55 martin 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.52.2.1 2016/03/06 18:17:55 martin 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.30.22.1
--- 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	Sun Mar  6 18:17:56 2016
@@ -1,13 +1,13 @@
-/*	$NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.30.22.1 2016/03/06 18:17:56 martin 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.30.22.1 2016/03/06 18:17:56 martin 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.30.22.1 2016/03/06 18:17:56 martin 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.47.22.1
--- 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	Sun Mar  6 18:17:56 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.47 2011/03/31 12:47:01 nakayama Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.47.22.1 2016/03/06 18:17:56 martin 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.47.22.1 2016/03/06 18:17:56 martin 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.56.4.1
--- 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	Sun Mar  6 18:17:56 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.56.4.1 2016/03/06 18:17:56 martin 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.56.4.1 2016/03/06 18:17:56 martin 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.29.4.1
--- 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	Sun Mar  6 18:17:56 2016
@@ -1,13 +1,13 @@
-/*	$NetBSD: mdreloc.c,v 1.29 2014/03/21 01:43:33 matt Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.29.4.1 2016/03/06 18:17:56 martin 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.29.4.1 2016/03/06 18:17:56 martin 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.29.4.1 2016/03/06 18:17:56 martin 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.40.22.1
--- 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	Sun Mar  6 18:17:56 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.40 2011/03/25 18:07:07 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.40.22.1 2016/03/06 18:17:56 martin 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.40.22.1 2016/03/06 18:17:56 martin 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)

Reply via email to