Module Name:    src
Committed By:   joerg
Date:           Mon Jun 19 11:57:02 UTC 2017

Modified Files:
        src/libexec/ld.elf_so: Makefile map_object.c rtld.h symbol.c
        src/libexec/ld.elf_so/arch/aarch64: mdreloc.c
        src/libexec/ld.elf_so/arch/alpha: alpha_reloc.c
        src/libexec/ld.elf_so/arch/arm: mdreloc.c
        src/libexec/ld.elf_so/arch/hppa: hppa_reloc.c
        src/libexec/ld.elf_so/arch/i386: mdreloc.c
        src/libexec/ld.elf_so/arch/m68k: mdreloc.c
        src/libexec/ld.elf_so/arch/mips: mips_reloc.c
        src/libexec/ld.elf_so/arch/or1k: mdreloc.c
        src/libexec/ld.elf_so/arch/powerpc: ppc_reloc.c
        src/libexec/ld.elf_so/arch/riscv: mdreloc.c
        src/libexec/ld.elf_so/arch/sh3: mdreloc.c
        src/libexec/ld.elf_so/arch/sparc: mdreloc.c
        src/libexec/ld.elf_so/arch/sparc64: mdreloc.c
        src/libexec/ld.elf_so/arch/vax: mdreloc.c
        src/libexec/ld.elf_so/arch/x86_64: mdreloc.c

Log Message:
Replace COMBREL with just-in-time check in _rtld_relocate_nonplt_objects.

The COMBREL logic predates thread-safety of the dynamic linker and
breaks the use of shared locks for the common symbol lookup case. It is
unlikely to provide any benefit for lazy binding or PLT lookups, so
provide equivalent functionality in the non-PLT relocation handling loop
by checking if the symbol used by the current relocation is the same as
the one used during the last lookup. No inter-object cachine is done as
it is also unlikely to be benefical.

Testing with Firefox startup on AMD64 shows a small performance gain by
the new method.


To generate a diff of this commit:
cvs rdiff -u -r1.136 -r1.137 src/libexec/ld.elf_so/Makefile
cvs rdiff -u -r1.57 -r1.58 src/libexec/ld.elf_so/map_object.c
cvs rdiff -u -r1.126 -r1.127 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.67 -r1.68 src/libexec/ld.elf_so/symbol.c
cvs rdiff -u -r1.2 -r1.3 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
cvs rdiff -u -r1.41 -r1.42 src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c
cvs rdiff -u -r1.38 -r1.39 src/libexec/ld.elf_so/arch/arm/mdreloc.c
cvs rdiff -u -r1.43 -r1.44 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c
cvs rdiff -u -r1.37 -r1.38 src/libexec/ld.elf_so/arch/i386/mdreloc.c
cvs rdiff -u -r1.31 -r1.32 src/libexec/ld.elf_so/arch/m68k/mdreloc.c
cvs rdiff -u -r1.65 -r1.66 src/libexec/ld.elf_so/arch/mips/mips_reloc.c
cvs rdiff -u -r1.1 -r1.2 src/libexec/ld.elf_so/arch/or1k/mdreloc.c
cvs rdiff -u -r1.53 -r1.54 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
cvs rdiff -u -r1.2 -r1.3 src/libexec/ld.elf_so/arch/riscv/mdreloc.c
cvs rdiff -u -r1.32 -r1.33 src/libexec/ld.elf_so/arch/sh3/mdreloc.c
cvs rdiff -u -r1.49 -r1.50 src/libexec/ld.elf_so/arch/sparc/mdreloc.c
cvs rdiff -u -r1.60 -r1.61 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
cvs rdiff -u -r1.31 -r1.32 src/libexec/ld.elf_so/arch/vax/mdreloc.c
cvs rdiff -u -r1.41 -r1.42 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/Makefile
diff -u src/libexec/ld.elf_so/Makefile:1.136 src/libexec/ld.elf_so/Makefile:1.137
--- src/libexec/ld.elf_so/Makefile:1.136	Thu Dec  1 14:29:15 2016
+++ src/libexec/ld.elf_so/Makefile	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.136 2016/12/01 14:29:15 christos Exp $
+#	$NetBSD: Makefile,v 1.137 2017/06/19 11:57:01 joerg Exp $
 #
 # NOTE: when changing ld.so, ensure that ldd still compiles.
 #
@@ -97,7 +97,6 @@ CPPFLAGS+=	-I${.CURDIR} -I. -D_KERNTYPES
 CPPFLAGS+=	-DRTLD_LOADER
 CPPFLAGS+=	-DGNU_RELRO
 CPPFLAGS+=	-D_RTLD_SOURCE
-CPPFLAGS+=	-DCOMBRELOC
 #CPPFLAGS+=	-DDEBUG
 #CPPFLAGS+=	-DRTLD_DEBUG
 #CPPFLAGS+=	-DRTLD_DEBUG_RELOC

Index: src/libexec/ld.elf_so/map_object.c
diff -u src/libexec/ld.elf_so/map_object.c:1.57 src/libexec/ld.elf_so/map_object.c:1.58
--- src/libexec/ld.elf_so/map_object.c:1.57	Fri Mar 10 09:13:49 2017
+++ src/libexec/ld.elf_so/map_object.c	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: map_object.c,v 1.57 2017/03/10 09:13:49 maya Exp $	 */
+/*	$NetBSD: map_object.c,v 1.58 2017/06/19 11:57:01 joerg Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: map_object.c,v 1.57 2017/03/10 09:13:49 maya Exp $");
+__RCSID("$NetBSD: map_object.c,v 1.58 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -462,9 +462,6 @@ _rtld_obj_free(Obj_Entry *obj)
 	}
 	if (!obj->phdr_loaded)
 		xfree((void *)(uintptr_t)obj->phdr);
-#ifdef COMBRELOC
-	_rtld_combreloc_reset(obj);
-#endif
 	xfree(obj);
 }
 

Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.126 src/libexec/ld.elf_so/rtld.h:1.127
--- src/libexec/ld.elf_so/rtld.h:1.126	Wed Nov 30 19:43:32 2016
+++ src/libexec/ld.elf_so/rtld.h	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.h,v 1.126 2016/11/30 19:43:32 christos Exp $	 */
+/*	$NetBSD: rtld.h,v 1.127 2017/06/19 11:57:01 joerg Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -432,9 +432,6 @@ const Elf_Sym *_rtld_symlook_default(con
 const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
     const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *,
     DoneList *, DoneList *);
-#ifdef COMBRELOC
-void _rtld_combreloc_reset(const Obj_Entry *);
-#endif
 
 /* symver.c */
 void _rtld_object_add_name(Obj_Entry *, const char *);

Index: src/libexec/ld.elf_so/symbol.c
diff -u src/libexec/ld.elf_so/symbol.c:1.67 src/libexec/ld.elf_so/symbol.c:1.68
--- src/libexec/ld.elf_so/symbol.c:1.67	Thu Dec  1 14:29:15 2016
+++ src/libexec/ld.elf_so/symbol.c	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: symbol.c,v 1.67 2016/12/01 14:29:15 christos Exp $	 */
+/*	$NetBSD: symbol.c,v 1.68 2017/06/19 11:57:01 joerg Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: symbol.c,v 1.67 2016/12/01 14:29:15 christos Exp $");
+__RCSID("$NetBSD: symbol.c,v 1.68 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -323,21 +323,6 @@ _rtld_symlook_obj(const char *name, unsi
 	return NULL;
 }
 
-#ifdef COMBRELOC
-static const Obj_Entry *_rtld_last_refobj;
-
-/*
- * Called when an object is freed. Reset the cached symbol look up if
- * our last referencing or definition object just got unloaded.
- */
-void
-_rtld_combreloc_reset(const Obj_Entry *obj)
-{
-	if (_rtld_last_refobj == obj)
-		_rtld_last_refobj = NULL;
-}
-#endif
-
 /*
  * Given a symbol number in a referencing object, find the corresponding
  * definition of the symbol.  Returns a pointer to the symbol, or NULL if
@@ -354,25 +339,6 @@ _rtld_find_symdef(unsigned long symnum, 
 	const char     *name;
 	unsigned long   hash;
 
-#ifdef COMBRELOC
-	/*
-	 * COMBRELOC combines multiple reloc sections and sorts them to make
-	 * dynamic symbol lookup caching possible.
-	 *
-	 * So if the lookup we are doing is the same as the previous lookup
-	 * return the cached results.
-	 */
-	static unsigned long last_symnum;
-	static const Obj_Entry *last_defobj;
-	static const Elf_Sym *last_def;
-
-	if (symnum == last_symnum && refobj == _rtld_last_refobj
-	    && !(flags & SYMLOOK_IN_PLT)) {
-		*defobj_out = last_defobj;
-		return last_def;
-	}
-#endif
-
 	ref = refobj->symtab + symnum;
 	name = refobj->strtab + ref->st_name;
 
@@ -409,18 +375,6 @@ _rtld_find_symdef(unsigned long symnum, 
 
 	if (def != NULL) {
 		*defobj_out = defobj;
-#ifdef COMBRELOC
-		if (!(flags & SYMLOOK_IN_PLT)) {
-			/*
-			 * Cache the lookup arguments and results if this was
-			 * non-PLT lookup.
-			 */
-			last_symnum = symnum;
-			_rtld_last_refobj = refobj;
-			last_def = def;
-			last_defobj = defobj;
-		}
-#endif
 	} else {
 		rdbg(("lookup failed"));
 		_rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)",

Index: src/libexec/ld.elf_so/arch/aarch64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.2 src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.3
--- src/libexec/ld.elf_so/arch/aarch64/mdreloc.c:1.2	Mon Aug 25 20:40:52 2014
+++ src/libexec/ld.elf_so/arch/aarch64/mdreloc.c	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:01 joerg Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -78,27 +78,43 @@ _rtld_relocate_nonplt_self(Elf_Dyn *dynp
 int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
-	
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
+
 	for (const Elf_Rela *rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		unsigned long	 symnum;
 		Elf_Addr	 addend;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
 		addend = rela->r_addend;
 
 		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(ABS64):	/* word B + S + A */
+		case R_TYPE(GLOB_DAT):	/* word B + S */
+		case R_TLS_TYPE(TLS_DTPREL):
+		case R_TLS_TYPE(TLS_DTPMOD):
+		case R_TLS_TYPE(TLS_TPREL):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+
+		default:
+			break;
+		}
+
+		switch (ELF_R_TYPE(rela->r_info)) {
 		case R_TYPE(NONE):
 			break;
 
 		case R_TYPE(ABS64):	/* word B + S + A */
 		case R_TYPE(GLOB_DAT):	/* word B + S */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			*where = addend + (Elf_Addr)defobj->relocbase +
 			    def->st_value;
 			rdbg(("ABS64/GLOB_DAT %s in %s --> %p @ %p in %s",
@@ -129,10 +145,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TLS_TYPE(TLS_DTPREL):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = addend + (Elf_Addr)(def->st_value);
 
 			rdbg(("TLS_DTPOFF32 %s in %s --> %p",
@@ -141,10 +153,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 			break;
 		case R_TLS_TYPE(TLS_DTPMOD):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(defobj->tlsindex);
 
 			rdbg(("TLS_DTPMOD %s in %s --> %p",
@@ -154,10 +162,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TLS_TYPE(TLS_TPREL):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -172,7 +176,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, *where,
 			    obj->strtab + obj->symtab[symnum].st_name));
 			_rtld_error("%s: Unsupported relocation type %ld "

Index: src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c
diff -u src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.41 src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.42
--- src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c:1.41	Mon Aug 25 20:40:52 2014
+++ src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 joerg Exp $	*/
+/*	$NetBSD: alpha_reloc.c,v 1.42 2017/06/19 11:57:01 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.41 2014/08/25 20:40:52 joerg Exp $");
+__RCSID("$NetBSD: alpha_reloc.c,v 1.42 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -200,16 +200,36 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 {
 	const Elf_Rela *rela;
 	Elf_Addr target = -1;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(REFQUAD):
+		case R_TYPE(GLOB_DAT):
+		case R_TYPE(TPREL64):
+		case R_TYPE(DTPMOD64):
+		case R_TYPE(DTPREL64):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 		case R_TYPE(NONE):
@@ -217,9 +237,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 		case R_TYPE(REFQUAD):
 		case R_TYPE(GLOB_DAT):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			target = (Elf_Addr)(defobj->relocbase +
 			    def->st_value);
 
@@ -263,10 +280,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TPREL64):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -287,10 +300,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(DTPMOD64):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf64_Addr)defobj->tlsindex;
 			if (__predict_true(RELOC_ALIGNED_P(where)))
 				*where = tmp;
@@ -304,10 +313,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(DTPREL64):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf64_Addr)(def->st_value + rela->r_addend);
 			if (__predict_true(RELOC_ALIGNED_P(where)))
 				*where = tmp;
@@ -323,7 +328,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)load_ptr(where),
 			    obj->strtab + obj->symtab[symnum].st_name));

Index: src/libexec/ld.elf_so/arch/arm/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.38 src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.39
--- src/libexec/ld.elf_so/arch/arm/mdreloc.c:1.38	Mon Aug 25 20:40:52 2014
+++ src/libexec/ld.elf_so/arch/arm/mdreloc.c	Mon Jun 19 11:57:01 2017
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.39 2017/06/19 11:57:01 joerg Exp $	*/
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.39 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -74,16 +74,37 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rel *rel;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rel = obj->rel; rel < obj->rellim; rel++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
-		symnum = ELF_R_SYM(rel->r_info);
+
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_TYPE(PC24):	/* word32 S - P + A */
+		case R_TYPE(ABS32):	/* word32 B + S + A */
+		case R_TYPE(GLOB_DAT):	/* word32 B + S */
+		case R_TYPE(TLS_DTPOFF32):
+		case R_TYPE(TLS_DTPMOD32):
+		case R_TYPE(TLS_TPOFF32):
+			symnum = ELF_R_SYM(rel->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rel->r_info)) {
 		case R_TYPE(NONE):
@@ -99,10 +120,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			addend = *where;
 			if (addend & 0x00800000)
 				addend |= 0xff000000;
-
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			tmp = (Elf_Addr)obj->relocbase + def->st_value
 			    - (Elf_Addr)where + (addend << 2);
 			if ((tmp & 0xfe000000) != 0xfe000000 &&
@@ -126,9 +143,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 		case R_TYPE(ABS32):	/* word32 B + S + A */
 		case R_TYPE(GLOB_DAT):	/* word32 B + S */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			if (__predict_true(RELOC_ALIGNED_P(where))) {
 				tmp = *where + (Elf_Addr)defobj->relocbase +
 				    def->st_value;
@@ -180,10 +194,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(def->st_value);
 			if (__predict_true(RELOC_ALIGNED_P(where)))
 				*where = tmp;
@@ -196,10 +206,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 			break;
 		case R_TYPE(TLS_DTPMOD32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->tlsindex);
 			if (__predict_true(RELOC_ALIGNED_P(where)))
 				*where = tmp;
@@ -213,10 +219,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -235,7 +237,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rel->r_info),
+			    (u_long)ELF_R_SYM(rel->r_info),
+			    (u_long)ELF_R_TYPE(rel->r_info),
 			    (void *)rel->r_offset, (void *)load_ptr(where),
 			    obj->strtab + obj->symtab[symnum].st_name));
 			_rtld_error("%s: Unsupported relocation type %ld "

Index: src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c
diff -u src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.43 src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.44
--- src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c:1.43	Mon Aug 25 20:40:52 2014
+++ src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 joerg Exp $	*/
+/*	$NetBSD: hppa_reloc.c,v 1.44 2017/06/19 11:57:01 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.43 2014/08/25 20:40:52 joerg Exp $");
+__RCSID("$NetBSD: hppa_reloc.c,v 1.44 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <stdlib.h>
@@ -413,46 +413,23 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
-
-		switch (ELF_R_TYPE(rela->r_info)) {
-		case R_TYPE(NONE):
-			break;
-
-		case R_TYPE(DIR32):
-			if (symnum) {
-				/*
-				 * This is either a DIR32 against a symbol
-				 * (def->st_name != 0), or against a local
-				 * section (def->st_name == 0).
-				 */
-				def = obj->symtab + symnum;
-				defobj = obj;
-				if (def->st_name != 0)
-					def = _rtld_find_symdef(symnum, obj,
-					    &defobj, false);
-				if (def == NULL)
-					return -1;
-
-				tmp = (Elf_Addr)(defobj->relocbase +
-				    def->st_value + rela->r_addend);
 
-				if (load_ptr(where) != tmp)
-					store_ptr(where, tmp);
-				rdbg(("DIR32 %s in %s --> %p in %s",
-				    obj->strtab + obj->symtab[symnum].st_name,
-				    obj->path, (void *)load_ptr(where),
-				    defobj->path));
-			} else {
+		/* First, handle DIR32 and PLABEL32 without symbol. */
+		if (ELF_R_SYM(rela->r_info) == 0) {
+			switch (ELF_R_TYPE(rela->r_info)) {
+			default:
+				break;
+			case R_TYPE(DIR32):
 				tmp = (Elf_Addr)(obj->relocbase +
 				    rela->r_addend);
 
@@ -460,27 +437,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 					store_ptr(where, tmp);
 				rdbg(("DIR32 in %s --> %p", obj->path,
 					    (void *)load_ptr(where)));
-			}
-			break;
-
-		case R_TYPE(PLABEL32):
-			if (symnum) {
-				def = _rtld_find_symdef(symnum, obj, &defobj,
-				    false);
-				if (def == NULL)
-					return -1;
-
-				tmp = _rtld_function_descriptor_alloc(defobj,
-				    def, rela->r_addend);
-				if (tmp == (Elf_Addr)-1)
-					return -1;
-
-				if (*where != tmp)
-					*where = tmp;
-				rdbg(("PLABEL32 %s in %s --> %p in %s",
-				    obj->strtab + obj->symtab[symnum].st_name,
-				    obj->path, (void *)*where, defobj->path));
-			} else {
+				continue;
+			case R_TYPE(PLABEL32):
 				/*
 				 * This is a PLABEL for a static function, and
 				 * the dynamic linker has both allocated a PLT
@@ -505,8 +463,68 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 					*where = tmp;
 				rdbg(("PLABEL32 in %s --> %p", obj->path,
 				    (void *)*where));
+				continue;
+			}
+		}
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(DIR32):
+		case R_TYPE(PLABEL32):
+		case R_TYPE(COPY):
+		case R_TYPE(TLS_TPREL32):
+		case R_TYPE(TLS_DTPMOD32):
+		case R_TYPE(TLS_DTPOFF32):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				if (ELF_R_TYPE(rela->r_info) == R_TYPE(DIR32)) {
+					/*
+					 * DIR32 relocation against local
+					 * symbols are special...
+					 */
+					def = obj->symtab + symnum;
+					defobj = obj;
+					if (def->st_name == 0)
+						break;
+				}
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
 			}
 			break;
+		default:
+			break;
+		}
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(NONE):
+			break;
+
+		case R_TYPE(DIR32):
+			tmp = (Elf_Addr)(defobj->relocbase +
+			    def->st_value + rela->r_addend);
+
+			if (load_ptr(where) != tmp)
+				store_ptr(where, tmp);
+			rdbg(("DIR32 %s in %s --> %p in %s",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)load_ptr(where),
+			    defobj->path));
+			break;
+
+		case R_TYPE(PLABEL32):
+			tmp = _rtld_function_descriptor_alloc(defobj,
+			    def, rela->r_addend);
+			if (tmp == (Elf_Addr)-1)
+				return -1;
+
+			if (*where != tmp)
+				*where = tmp;
+			rdbg(("PLABEL32 %s in %s --> %p in %s",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)*where, defobj->path));
+			break;
 
 		case R_TYPE(COPY):
 			/*
@@ -525,10 +543,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPREL32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -541,10 +555,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPMOD32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(defobj->tlsindex);
 
 			rdbg(("TLS_DTPMOD32 %s in %s --> %p",
@@ -554,10 +564,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(def->st_value);
 
 			rdbg(("TLS_DTPOFF32 %s in %s --> %p",

Index: src/libexec/ld.elf_so/arch/i386/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.37 src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.38
--- src/libexec/ld.elf_so/arch/i386/mdreloc.c:1.37	Sun Aug 31 20:06:22 2014
+++ src/libexec/ld.elf_so/arch/i386/mdreloc.c	Mon Jun 19 11:57:01 2017
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.37 2014/08/31 20:06:22 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.38 2017/06/19 11:57:01 joerg Exp $	*/
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.37 2014/08/31 20:06:22 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.38 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -53,16 +53,39 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 {
 	const Elf_Rel *rel;
 	Elf_Addr target = 0;
+	const Elf_Sym   *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rel = obj->rel; rel < obj->rellim; rel++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
-		symnum = ELF_R_SYM(rel->r_info);
+
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_TYPE(PC32):
+		case R_TYPE(GOT32):
+		case R_TYPE(32):
+		case R_TYPE(GLOB_DAT):
+		case R_TYPE(TLS_TPOFF):
+		case R_TYPE(TLS_TPOFF32):
+		case R_TYPE(TLS_DTPMOD32):
+		case R_TYPE(TLS_DTPOFF32):
+			symnum = ELF_R_SYM(rel->r_info);
+			if (symnum != last_symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
+
 
 		switch (ELF_R_TYPE(rel->r_info)) {
 		case R_TYPE(NONE):
@@ -70,9 +93,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 #if 1 /* XXX should not occur */
 		case R_TYPE(PC32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			target = (Elf_Addr)(defobj->relocbase + def->st_value);
 
 			*where += target - (Elf_Addr)where;
@@ -85,9 +105,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 #endif
 		case R_TYPE(32):
 		case R_TYPE(GLOB_DAT):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			target = (Elf_Addr)(defobj->relocbase + def->st_value);
 
 			tmp = target + *where;
@@ -121,10 +138,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPOFF):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -137,10 +150,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -152,10 +161,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPMOD32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(defobj->tlsindex);
 
 			rdbg(("TLS_DTPMOD32 %s in %s --> %p",
@@ -164,10 +169,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(def->st_value);
 
 			rdbg(("TLS_DTPOFF32 %s in %s --> %p",
@@ -179,7 +180,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rel->r_info),
+			    (u_long)ELF_R_SYM(rel->r_info),
+			    (u_long)ELF_R_TYPE(rel->r_info),
 			    (void *)rel->r_offset, (void *)*where,
 			    obj->strtab + obj->symtab[symnum].st_name));
 			_rtld_error("%s: Unsupported relocation type %ld "

Index: src/libexec/ld.elf_so/arch/m68k/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.31 src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.32
--- src/libexec/ld.elf_so/arch/m68k/mdreloc.c:1.31	Thu Apr 14 20:17:07 2016
+++ src/libexec/ld.elf_so/arch/m68k/mdreloc.c	Mon Jun 19 11:57:01 2017
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.31 2016/04/14 20:17:07 skrll Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.32 2017/06/19 11:57:01 joerg Exp $	*/
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.31 2016/04/14 20:17:07 skrll Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.32 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -52,16 +52,37 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(PC32):
+		case R_TYPE(GOT32):
+		case R_TYPE(32):
+		case R_TYPE(GLOB_DAT):
+		case R_TYPE(TLS_DTPMOD32):
+		case R_TYPE(TLS_DTPREL32):
+		case R_TYPE(TLS_TPREL32):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 		case R_TYPE(NONE):
@@ -69,10 +90,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 #if 1 /* XXX should not occur */
 		case R_TYPE(PC32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend) - (Elf_Addr)where;
 			if (*where != tmp)
@@ -86,10 +103,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 #endif
 		case R_TYPE(32):
 		case R_TYPE(GLOB_DAT):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 			if (*where != tmp)
@@ -122,10 +135,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPMOD32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)defobj->tlsindex;
 			rdbg(("DTPMOD32 %s in %s --> %p in %s",
 			    obj->strtab + obj->symtab[symnum].st_name,
@@ -133,10 +142,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPREL32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -148,10 +153,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPREL32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -165,7 +166,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)*where,
 			    obj->strtab + obj->symtab[symnum].st_name));

Index: src/libexec/ld.elf_so/arch/mips/mips_reloc.c
diff -u src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.65 src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.66
--- src/libexec/ld.elf_so/arch/mips/mips_reloc.c:1.65	Sat Feb 20 15:20:23 2016
+++ src/libexec/ld.elf_so/arch/mips/mips_reloc.c	Mon Jun 19 11:57:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_reloc.c,v 1.65 2016/02/20 15:20:23 christos Exp $	*/
+/*	$NetBSD: mips_reloc.c,v 1.66 2017/06/19 11:57:01 joerg Exp $	*/
 
 /*
  * Copyright 1997 Michael L. Hitch <mhi...@montana.edu>
@@ -30,7 +30,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mips_reloc.c,v 1.65 2016/02/20 15:20:23 christos Exp $");
+__RCSID("$NetBSD: mips_reloc.c,v 1.66 2017/06/19 11:57:01 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -230,6 +230,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 	Elf_Addr *got = obj->pltgot;
 	const Elf_Sym *sym, *def;
 	const Obj_Entry *defobj;
+	unsigned long last_symnum = ULONG_MAX;
 	Elf_Word i;
 #ifdef SUPPORT_OLD_BROKEN_LD
 	int broken;
@@ -313,14 +314,35 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 	got = obj->pltgot;
 	for (rel = obj->rel; rel < obj->rellim; rel++) {
-		Elf_Word	r_symndx, r_type;
+		unsigned long symnum;
 		void		*where;
 
 		where = obj->relocbase + rel->r_offset;
-		r_symndx = ELF_R_SYM(rel->r_info);
-		r_type = ELF_R_TYPE(rel->r_info);
 
-		switch (r_type & 0xff) {
+		switch (ELF_R_TYPE(rel->r_info)) {
+#if ELFSIZE == 64
+		case R_TYPE(TLS_DTPMOD64):
+		case R_TYPE(TLS_DTPREL64):
+		case R_TYPE(TLS_TPREL64):
+#else
+		case R_TYPE(TLS_DTPMOD32): 
+		case R_TYPE(TLS_DTPREL32):
+		case R_TYPE(TLS_TPREL32):
+#endif
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
+
+		switch (ELF_R_TYPE(rel->r_info)) {
 		case R_TYPE(NONE):
 			break;
 
@@ -385,10 +407,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			Elf_Addr old = load_ptr(where, ELFSIZE / 8);
 			Elf_Addr val = old;
 
-			def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			val += (Elf_Addr)defobj->tlsindex;
 
 			store_ptr(where, val, ELFSIZE / 8);
@@ -407,10 +425,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			Elf_Addr old = load_ptr(where, ELFSIZE / 8);
 			Elf_Addr val = old;
 
-			def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -432,10 +446,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			Elf_Addr old = load_ptr(where, ELFSIZE / 8);
 			Elf_Addr val = old;
 
-			def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -452,7 +462,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "contents = %p, symbol = %s",
-			    (u_long)r_symndx, (u_long)ELF_R_TYPE(rel->r_info),
+			    (u_long)ELF_R_SYM(rel->r_info),
+			    (u_long)ELF_R_TYPE(rel->r_info),
 			    (void *)rel->r_offset,
 			    (void *)load_ptr(where, sizeof(Elf_Sword)),
 			    obj->strtab + obj->symtab[r_symndx].st_name));

Index: src/libexec/ld.elf_so/arch/or1k/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/or1k/mdreloc.c:1.1 src/libexec/ld.elf_so/arch/or1k/mdreloc.c:1.2
--- src/libexec/ld.elf_so/arch/or1k/mdreloc.c:1.1	Wed Sep  3 19:34:26 2014
+++ src/libexec/ld.elf_so/arch/or1k/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.1 2014/09/03 19:34:26 matt Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.2 2017/06/19 11:57:02 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/09/03 19:34:26 matt Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.2 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <stdarg.h>
@@ -93,16 +93,35 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(32):	/* <address> S + A */
+		case R_TYPE(GLOB_DAT):	/* <address> S + A */
+		case R_TYPE(TLS_DTPMOD):
+		case R_TYPE(TLS_DTPOFF):
+		case R_TYPE(TLS_TPOFF):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 #if 1 /* XXX Should not be necessary. */
@@ -113,10 +132,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 		case R_TYPE(32):	/* <address> S + A */
 		case R_TYPE(GLOB_DAT):	/* <address> S + A */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 			if (*where != tmp)
@@ -149,10 +164,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPMOD):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)defobj->tlsindex;
 			rdbg(("DTPMOD32 %s in %s --> %p in %s",
 			    obj->strtab + obj->symtab[symnum].st_name,
@@ -160,10 +171,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPOFF):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -175,10 +182,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPOFF):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -192,7 +195,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)*where,
 			    obj->strtab + obj->symtab[symnum].st_name));

Index: src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
diff -u src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.53 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.54
--- src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.53	Mon Aug 25 20:40:52 2014
+++ src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c	Mon Jun 19 11:57:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ppc_reloc.c,v 1.53 2014/08/25 20:40:52 joerg Exp $	*/
+/*	$NetBSD: ppc_reloc.c,v 1.54 2017/06/19 11:57:02 joerg Exp $	*/
 
 /*-
  * Copyright (C) 1998	Tsubai Masanari
@@ -30,7 +30,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ppc_reloc.c,v 1.53 2014/08/25 20:40:52 joerg Exp $");
+__RCSID("$NetBSD: ppc_reloc.c,v 1.54 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <stdarg.h>
@@ -178,16 +178,39 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+#ifdef _LP64
+		case R_TYPE(ADDR64):	/* <address> S + A */
+#else
+		case R_TYPE(ADDR32):	/* <address> S + A */
+#endif
+		case R_TYPE(GLOB_DAT):	/* <address> S + A */
+		case R_TYPE(DTPMOD):
+		case R_TYPE(DTPREL):
+		case R_TYPE(TPREL):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 #if 1 /* XXX Should not be necessary. */
@@ -202,10 +225,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		case R_TYPE(ADDR32):	/* <address> S + A */
 #endif
 		case R_TYPE(GLOB_DAT):	/* <address> S + A */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 			if (*where != tmp)
@@ -238,10 +257,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(DTPMOD):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)defobj->tlsindex;
 			rdbg(("DTPMOD32 %s in %s --> %p in %s",
 			    obj->strtab + obj->symtab[symnum].st_name,
@@ -249,10 +264,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(DTPREL):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -264,10 +275,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TPREL):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -281,7 +288,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)*where,
 			    obj->strtab + obj->symtab[symnum].st_name));

Index: src/libexec/ld.elf_so/arch/riscv/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/riscv/mdreloc.c:1.2 src/libexec/ld.elf_so/arch/riscv/mdreloc.c:1.3
--- src/libexec/ld.elf_so/arch/riscv/mdreloc.c:1.2	Fri Mar 27 23:14:53 2015
+++ src/libexec/ld.elf_so/arch/riscv/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.2 2015/03/27 23:14:53 matt Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:02 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.2 2015/03/27 23:14:53 matt Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.3 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -99,14 +99,32 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
-	const Elf_Sym *def;
-	const Obj_Entry *defobj;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr * const where =
 		    (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		const Elf_Word r_symndx = ELF_R_SYM(rela->r_info);
 		const Elf_Word r_type = ELF_R_TYPE(rela->r_info);
+		unsigned long symnum;
+
+		switch (r_type) {
+		case R_TYPESZ(ADDR):
+		case R_TYPESZ(TLS_DTPMOD):
+		case R_TYPESZ(TLS_DTPREL):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
 
 		switch (r_type) {
 		case R_TYPE(NONE):
@@ -126,10 +144,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		}
 
 		case R_TYPESZ(ADDR): {
-			def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			Elf_Addr val = (Elf_Addr)defobj->relocbase + rela->r_addend;
 
 			*where = val;
@@ -140,10 +154,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		}
 
 		case R_TYPESZ(TLS_DTPMOD): {
-			def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			Elf_Addr val = (Elf_Addr)defobj->tlsindex + rela->r_addend;
 
 			*where = val;
@@ -157,10 +167,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			Elf_Addr old = *where;
 			Elf_Addr val = old;
 
-			def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
 				return -1;
 
@@ -176,7 +182,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    (u_long)r_symndx, (u_long)r_type,
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)load_ptr(where, sizeof(Elf_Addr)),
 			    obj->strtab + obj->symtab[r_symndx].st_name));

Index: src/libexec/ld.elf_so/arch/sh3/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.32 src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.33
--- src/libexec/ld.elf_so/arch/sh3/mdreloc.c:1.32	Thu Apr 14 20:17:07 2016
+++ src/libexec/ld.elf_so/arch/sh3/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.32 2016/04/14 20:17:07 skrll Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.33 2017/06/19 11:57:02 joerg Exp $	*/
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.32 2016/04/14 20:17:07 skrll Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.33 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -61,7 +61,27 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(GOT32):
+		case R_TYPE(REL32):
+		case R_TYPE(DIR32):
+		case R_TYPE(GLOB_DAT):
+		case R_TYPE(TLS_DTPOFF32):
+		case R_TYPE(TLS_DTPMOD32):
+		case R_TYPE(TLS_TPOFF32):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 		case R_TYPE(NONE):
@@ -69,10 +89,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 #if 1 /* XXX should not occur */
 		case R_TYPE(GOT32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 			if (*where != tmp)
@@ -83,10 +99,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(REL32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend) - (Elf_Addr)where;
 			if (*where != tmp)
@@ -98,10 +110,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 #endif
 
 		case R_TYPE(DIR32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 			if (*where != tmp)
@@ -112,10 +120,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(GLOB_DAT):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
 			    rela->r_addend;
 			if (*where != tmp)
@@ -151,10 +155,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_DTPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(def->st_value);
 
 			rdbg(("TLS_DTPOFF32 %s in %s --> %p",
@@ -163,10 +163,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 			break;
 		case R_TYPE(TLS_DTPMOD32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where = (Elf_Addr)(defobj->tlsindex);
 
 			rdbg(("TLS_DTPMOD32 %s in %s --> %p",
@@ -176,10 +172,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(TLS_TPOFF32):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -196,7 +188,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)*where,
 			    obj->strtab + obj->symtab[symnum].st_name));

Index: src/libexec/ld.elf_so/arch/sparc/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.49 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.50
--- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.49	Thu Jun 15 23:08:46 2017
+++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.49 2017/06/15 23:08:46 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.50 2017/06/19 11:57:02 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.49 2017/06/15 23:08:46 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.50 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -201,16 +201,16 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr *where;
 		Elf_Word type, value, mask;
-		const Elf_Sym *def = NULL;
-		const Obj_Entry *defobj = NULL;
 		unsigned long	 symnum;
 
 		where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
 
 		type = ELF_R_TYPE(rela->r_info);
 		if (type == R_TYPE(NONE))
@@ -233,17 +233,23 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 		value = rela->r_addend;
 
+		if (RELOC_RESOLVE_SYMBOL(type) || RELOC_TLS(type)) {
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+		}
+
 		/*
 		 * Handle TLS relocations here, they are different.
 		 */
 		if (RELOC_TLS(type)) {
 			switch (type) {
 			case R_TYPE(TLS_DTPMOD32):
-				def = _rtld_find_symdef(symnum, obj,
-				    &defobj, false);
-				if (def == NULL)
-					return -1;
-
 				*where = (Elf_Addr)defobj->tlsindex;
 
 				rdbg(("TLS_DTPMOD32 %s in %s --> %p",
@@ -254,11 +260,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 				break;
 
 			case R_TYPE(TLS_DTPOFF32):
-				def = _rtld_find_symdef(symnum, obj,
-				    &defobj, false);
-				if (def == NULL)
-					return -1;
-
 				*where = (Elf_Addr)(def->st_value
 				    + rela->r_addend);
 
@@ -270,11 +271,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 				break;
 
 			case R_TYPE(TLS_TPOFF32):
-				def = _rtld_find_symdef(symnum, obj,
-				    &defobj, false);
-				if (def == NULL)
-					return -1;
-
 				if (!defobj->tls_done &&
 					_rtld_tls_offset_allocate(obj))
 					     return -1;
@@ -310,12 +306,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		}
 
 		if (RELOC_RESOLVE_SYMBOL(type)) {
-
-			/* Find the symbol */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return (-1);
-
 			/* Add in the symbol's absolute address */
 			value += (Elf_Word)(defobj->relocbase + def->st_value);
 		}

Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.60 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.61
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.60	Thu Jun 15 23:10:12 2017
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.60 2017/06/15 23:10:12 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.61 2017/06/19 11:57:02 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.60 2017/06/15 23:10:12 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.61 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -310,15 +310,15 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 	const Elf_Rela *rela;
 	const Elf_Sym *def = NULL;
 	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr *where;
 		Elf_Word type;
 		Elf_Addr value = 0, mask;
-		unsigned long	 symnum;
+		unsigned long symnum;
 
 		where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
 
 		type = ELF_R_TYPE(rela->r_info);
 		if (type == R_TYPE(NONE))
@@ -347,17 +347,23 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 		value = rela->r_addend;
 
+		if (RELOC_RESOLVE_SYMBOL(type) || RELOC_TLS(type)) {
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+		}
+
 		/*
 		 * Handle TLS relocations here, they are different.
 		 */
 		if (RELOC_TLS(type)) {
 			switch (type) {
 			case R_TYPE(TLS_DTPMOD64):
-				def = _rtld_find_symdef(symnum, obj,
-				    &defobj, false);
-				if (def == NULL)
-					return -1;
-
 				*where = (Elf64_Addr)defobj->tlsindex;
 
 				rdbg(("TLS_DTPMOD64 %s in %s --> %p",
@@ -368,11 +374,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 				break;
 
 			case R_TYPE(TLS_DTPOFF64):
-				def = _rtld_find_symdef(symnum, obj,
-				    &defobj, false);
-				if (def == NULL)
-					return -1;
-
 				*where = (Elf64_Addr)(def->st_value
 				    + rela->r_addend);
 
@@ -384,11 +385,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 				break;
 
 			case R_TYPE(TLS_TPOFF64):
-				def = _rtld_find_symdef(symnum, obj,
-				    &defobj, false);
-				if (def == NULL)
-					return -1;
-
 				if (!defobj->tls_done &&
 					_rtld_tls_offset_allocate(obj))
 					     return -1;
@@ -416,13 +412,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		}
 
 		if (RELOC_RESOLVE_SYMBOL(type)) {
-
-			/* Find the symbol */
-			def = _rtld_find_symdef(symnum, obj, &defobj,
-			    false);
-			if (def == NULL)
-				return -1;
-
 			/* Add in the symbol's absolute address */
 			value += (Elf_Addr)(defobj->relocbase + def->st_value);
 		}

Index: src/libexec/ld.elf_so/arch/vax/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.31 src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.32
--- src/libexec/ld.elf_so/arch/vax/mdreloc.c:1.31	Thu Apr 14 20:17:07 2016
+++ src/libexec/ld.elf_so/arch/vax/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,8 +1,8 @@
-/*	$NetBSD: mdreloc.c,v 1.31 2016/04/14 20:17:07 skrll Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.32 2017/06/19 11:57:02 joerg Exp $	*/
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.31 2016/04/14 20:17:07 skrll Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.32 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -51,16 +51,32 @@ int
 _rtld_relocate_nonplt_objects(Obj_Entry *obj)
 {
 	const Elf_Rela *rela;
+	const Elf_Sym *def = NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf_Addr        *where;
-		const Elf_Sym   *def;
-		const Obj_Entry *defobj;
 		Elf_Addr         tmp;
-		unsigned long	 symnum;
 
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(32):	/* word32 S + A */
+		case R_TYPE(GLOB_DAT):	/* word32 S + A */
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 		case R_TYPE(NONE):
@@ -68,10 +84,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 
 		case R_TYPE(32):	/* word32 S + A */
 		case R_TYPE(GLOB_DAT):	/* word32 S + A */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 
@@ -109,7 +121,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)*where,
 			    obj->strtab + obj->symtab[symnum].st_name));

Index: src/libexec/ld.elf_so/arch/x86_64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.41 src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.42
--- src/libexec/ld.elf_so/arch/x86_64/mdreloc.c:1.41	Mon Aug 25 20:40:53 2014
+++ src/libexec/ld.elf_so/arch/x86_64/mdreloc.c	Mon Jun 19 11:57:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.42 2017/06/19 11:57:02 joerg Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -68,7 +68,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.42 2017/06/19 11:57:02 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -131,18 +131,41 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 {
 	const Elf_Rela *rela;
 	const Elf_Sym *def = NULL;
-	const Obj_Entry *defobj =NULL;
+	const Obj_Entry *defobj = NULL;
+	unsigned long last_symnum = ULONG_MAX;
 
 	for (rela = obj->rela; rela < obj->relalim; rela++) {
 		Elf64_Addr *where64;
 		Elf32_Addr *where32;
 		Elf64_Addr tmp64;
 		Elf32_Addr tmp32;
-		unsigned long	 symnum;
+		unsigned long symnum;
 
 		where64 = (Elf64_Addr *)(obj->relocbase + rela->r_offset);
 		where32 = (Elf32_Addr *)where64;
-		symnum = ELF_R_SYM(rela->r_info);
+
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_TYPE(32):	/* word32 S + A, truncate */
+		case R_TYPE(32S):	/* word32 S + A, signed truncate */
+		case R_TYPE(GOT32):	/* word32 G + A (XXX can we see these?) */
+		case R_TYPE(64):	/* word64 S + A */
+		case R_TYPE(PC32):	/* word32 S + A - P */
+		case R_TYPE(GLOB_DAT):	/* word64 S */
+		case R_TYPE(TPOFF64):
+		case R_TYPE(DTPMOD64):
+		case R_TYPE(DTPOFF64):
+			symnum = ELF_R_SYM(rela->r_info);
+			if (last_symnum != symnum) {
+				last_symnum = symnum;
+				def = _rtld_find_symdef(symnum, obj, &defobj,
+				    false);
+				if (def == NULL)
+					return -1;
+			}
+			break;
+		default:
+			break;
+		}
 
 		switch (ELF_R_TYPE(rela->r_info)) {
 		case R_TYPE(NONE):
@@ -151,9 +174,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		case R_TYPE(32):	/* word32 S + A, truncate */
 		case R_TYPE(32S):	/* word32 S + A, signed truncate */
 		case R_TYPE(GOT32):	/* word32 G + A (XXX can we see these?) */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase +
 			    def->st_value + rela->r_addend);
 
@@ -165,9 +185,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			    defobj->path));
 			break;
 		case R_TYPE(64):	/* word64 S + A */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value +
 			    rela->r_addend);
 
@@ -178,9 +195,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			    obj->path, (void *)*where64, defobj->path));
 			break;
 		case R_TYPE(PC32):	/* word32 S + A - P */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase +
 			    def->st_value + rela->r_addend -
 			    (Elf64_Addr)where64);
@@ -192,9 +206,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			    defobj->path));
 			break;
 		case R_TYPE(GLOB_DAT):	/* word64 S */
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
 			tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value);
 
 			if (*where64 != tmp64)
@@ -212,10 +223,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
        			break;
 
 		case R_TYPE(TPOFF64):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			if (!defobj->tls_done &&
 			    _rtld_tls_offset_allocate(obj))
 				return -1;
@@ -230,10 +237,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(DTPMOD64):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where64 = (Elf64_Addr)defobj->tlsindex;
 
 			rdbg(("DTPMOD64 %s in %s --> %p",
@@ -243,10 +246,6 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			break;
 
 		case R_TYPE(DTPOFF64):
-			def = _rtld_find_symdef(symnum, obj, &defobj, false);
-			if (def == NULL)
-				return -1;
-
 			*where64 = (Elf64_Addr)(def->st_value + rela->r_addend);
 
 			rdbg(("DTPOFF64 %s in %s --> %p",
@@ -262,7 +261,8 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		default:
 			rdbg(("sym = %lu, type = %lu, offset = %p, "
 			    "addend = %p, contents = %p, symbol = %s",
-			    symnum, (u_long)ELF_R_TYPE(rela->r_info),
+			    (u_long)ELF_R_SYM(rela->r_info),
+			    (u_long)ELF_R_TYPE(rela->r_info),
 			    (void *)rela->r_offset, (void *)rela->r_addend,
 			    (void *)*where64,
 			    obj->strtab + obj->symtab[symnum].st_name));

Reply via email to