[Midnightbsd-cvs] src [11385] trunk/libexec/rtld-elf/xmalloc.c: sync with freebsd, add architectures

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Jul 6 20:23:07 EDT 2018


Revision: 11385
          http://svnweb.midnightbsd.org/src/?rev=11385
Author:   laffer1
Date:     2018-07-06 20:23:06 -0400 (Fri, 06 Jul 2018)
Log Message:
-----------
sync with freebsd, add architectures

Modified Paths:
--------------
    trunk/libexec/rtld-elf/Makefile
    trunk/libexec/rtld-elf/Symbol.map
    trunk/libexec/rtld-elf/amd64/Makefile.inc
    trunk/libexec/rtld-elf/amd64/elf_rtld.x
    trunk/libexec/rtld-elf/amd64/reloc.c
    trunk/libexec/rtld-elf/amd64/rtld_machdep.h
    trunk/libexec/rtld-elf/amd64/rtld_start.S
    trunk/libexec/rtld-elf/debug.c
    trunk/libexec/rtld-elf/debug.h
    trunk/libexec/rtld-elf/i386/Makefile.inc
    trunk/libexec/rtld-elf/i386/Symbol.map
    trunk/libexec/rtld-elf/i386/elf_rtld.x
    trunk/libexec/rtld-elf/i386/reloc.c
    trunk/libexec/rtld-elf/i386/rtld_machdep.h
    trunk/libexec/rtld-elf/i386/rtld_start.S
    trunk/libexec/rtld-elf/libmap.c
    trunk/libexec/rtld-elf/libmap.h
    trunk/libexec/rtld-elf/malloc.c
    trunk/libexec/rtld-elf/map_object.c
    trunk/libexec/rtld-elf/rtld.1
    trunk/libexec/rtld-elf/rtld.c
    trunk/libexec/rtld-elf/rtld.h
    trunk/libexec/rtld-elf/rtld_lock.c
    trunk/libexec/rtld-elf/rtld_lock.h
    trunk/libexec/rtld-elf/rtld_printf.c
    trunk/libexec/rtld-elf/rtld_printf.h
    trunk/libexec/rtld-elf/rtld_tls.h
    trunk/libexec/rtld-elf/sparc64/reloc.c
    trunk/libexec/rtld-elf/sparc64/rtld_machdep.h
    trunk/libexec/rtld-elf/sparc64/rtld_start.S
    trunk/libexec/rtld-elf/xmalloc.c

Added Paths:
-----------
    trunk/libexec/rtld-elf/arm/
    trunk/libexec/rtld-elf/arm/Makefile.inc
    trunk/libexec/rtld-elf/arm/reloc.c
    trunk/libexec/rtld-elf/arm/rtld_machdep.h
    trunk/libexec/rtld-elf/arm/rtld_start.S
    trunk/libexec/rtld-elf/ia64/
    trunk/libexec/rtld-elf/ia64/Makefile.inc
    trunk/libexec/rtld-elf/ia64/reloc.c
    trunk/libexec/rtld-elf/ia64/rtld_machdep.h
    trunk/libexec/rtld-elf/ia64/rtld_start.S
    trunk/libexec/rtld-elf/mips/
    trunk/libexec/rtld-elf/mips/reloc.c
    trunk/libexec/rtld-elf/mips/rtld_machdep.h
    trunk/libexec/rtld-elf/mips/rtld_start.S
    trunk/libexec/rtld-elf/powerpc/
    trunk/libexec/rtld-elf/powerpc/Makefile.inc
    trunk/libexec/rtld-elf/powerpc/reloc.c
    trunk/libexec/rtld-elf/powerpc/rtld_machdep.h
    trunk/libexec/rtld-elf/powerpc/rtld_start.S
    trunk/libexec/rtld-elf/powerpc64/
    trunk/libexec/rtld-elf/powerpc64/Makefile.inc
    trunk/libexec/rtld-elf/powerpc64/reloc.c
    trunk/libexec/rtld-elf/powerpc64/rtld_machdep.h
    trunk/libexec/rtld-elf/powerpc64/rtld_start.S

Property Changed:
----------------
    trunk/libexec/rtld-elf/Symbol.map
    trunk/libexec/rtld-elf/amd64/Makefile.inc
    trunk/libexec/rtld-elf/amd64/elf_rtld.x
    trunk/libexec/rtld-elf/amd64/rtld_start.S
    trunk/libexec/rtld-elf/i386/Makefile.inc
    trunk/libexec/rtld-elf/i386/Symbol.map
    trunk/libexec/rtld-elf/i386/elf_rtld.x
    trunk/libexec/rtld-elf/i386/rtld_start.S
    trunk/libexec/rtld-elf/rtld.1
    trunk/libexec/rtld-elf/sparc64/Makefile.inc
    trunk/libexec/rtld-elf/sparc64/rtld_start.S

Modified: trunk/libexec/rtld-elf/Makefile
===================================================================
--- trunk/libexec/rtld-elf/Makefile	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/Makefile	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,5 +1,10 @@
 # $MidnightBSD$
+# $FreeBSD: stable/10/libexec/rtld-elf/Makefile 308967 2016-11-22 09:49:15Z kib $
 
+# Use the following command to build local debug version of dynamic
+# linker:
+# make DEBUG_FLAGS=-g DEBUG=-DDEBUG WITHOUT_TESTS=yes all
+
 .include <bsd.own.mk>
 MK_SSP=		no
 
@@ -18,12 +23,17 @@
 RTLD_ARCH=	${MACHINE_CPUARCH}
 .endif
 CFLAGS+=	-I${.CURDIR}/${RTLD_ARCH} -I${.CURDIR}
+.if ${MACHINE_ARCH} == "powerpc64"
+CFLAGS+=	-mcall-aixdesc
+LDFLAGS+=	-nostdlib -e _rtld_start
+.else
 LDFLAGS+=	-nostdlib -e .rtld_start
+.endif
 WARNS?=		2
 INSTALLFLAGS=	-C -b
 PRECIOUSPROG=
 BINDIR=		/libexec
-SYMLINKS=	${BINDIR}/${PROG} /usr/libexec/${PROG}
+SYMLINKS=	${BINDIR}/${PROG} ${LIBEXECDIR}/${PROG}
 MLINKS=		rtld.1 ld-elf.so.1.1 \
 		rtld.1 ld.so.1
 
@@ -33,10 +43,23 @@
 CFLAGS+=	-fpic
 .endif
 CFLAGS+=	-DPIC $(DEBUG)
-LDFLAGS+=	-shared -Wl,-Bsymbolic
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
+CFLAGS+=	-fvisibility=hidden
+.endif
+LDFLAGS+=	-shared -Wl,-Bsymbolic -Wl,-z,defs
 DPADD=		${LIBC_PIC}
 LDADD=		-lc_pic
 
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+# Some of the required math functions (div & mod) are implemented in libgcc
+# on ARM. The library also needs to be placed first to be correctly linked.
+# As some of the functions are used before we have shared libraries.
+DPADD+=		${LIBGCC}
+LDADD+=		-lgcc
+.endif
+
+
+
 .if ${MK_SYMVER} == "yes"
 LIBCDIR=	${TOPSRCDIR}/lib/libc
 VERSION_DEF=	${LIBCDIR}/Versions.def
@@ -57,7 +80,7 @@
 # Fixup the existing binary that's there so we can symlink over it.
 beforeinstall:
 .if exists(${DESTDIR}/usr/libexec/${PROG})
-	-chflags noschg ${DESTDIR}/usr/libexec/${PROG}
+	-chflags -h noschg ${DESTDIR}/usr/libexec/${PROG}
 .endif
 
 .PATH: ${.CURDIR}/${RTLD_ARCH}

Modified: trunk/libexec/rtld-elf/Symbol.map
===================================================================
--- trunk/libexec/rtld-elf/Symbol.map	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/Symbol.map	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,5 +1,5 @@
-/*
- * $MidnightBSD$
+/* $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/Symbol.map 276908 2015-01-10 09:22:17Z kib $
  */
 
 FBSD_1.0 {
@@ -30,4 +30,6 @@
     _rtld_atfork_post;
     _rtld_addr_phdr;
     _rtld_get_stack_prot;
+    _rtld_is_dlopened;
+    _r_debug_postinit;
 };


Property changes on: trunk/libexec/rtld-elf/Symbol.map
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/amd64/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/amd64/Makefile.inc	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/amd64/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,6 +1,6 @@
 # $MidnightBSD$
 
-CFLAGS+=	-mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
+CFLAGS+=	${CFLAGS_NO_SIMD} -msoft-float
 # Uncomment this to build the dynamic linker as an executable instead
 # of a shared library:
 #LDSCRIPT=	${.CURDIR}/${MACHINE_CPUARCH}/elf_rtld.x


Property changes on: trunk/libexec/rtld-elf/amd64/Makefile.inc
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/amd64/elf_rtld.x
===================================================================
--- trunk/libexec/rtld-elf/amd64/elf_rtld.x	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/amd64/elf_rtld.x	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 OUTPUT_FORMAT("elf32-i386", "elf32-i386",
 	      "elf32-i386")
 OUTPUT_ARCH(i386)


Property changes on: trunk/libexec/rtld-elf/amd64/elf_rtld.x
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/amd64/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/amd64/reloc.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/amd64/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/amd64/reloc.c 331206 2018-03-19 14:28:58Z marius $
  */
 
 /*
@@ -34,6 +35,7 @@
 #include <sys/param.h>
 #include <sys/mman.h>
 #include <machine/sysarch.h>
+#include <machine/cpufunc.h>
 
 #include <dlfcn.h>
 #include <err.h>
@@ -47,6 +49,7 @@
 
 #include "debug.h"
 #include "rtld.h"
+#include "rtld_tls.h"
 
 /*
  * Process the special R_X86_64_COPY relocations in the main program.  These
@@ -84,7 +87,8 @@
 	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
 	    req.flags = SYMLOOK_EARLY;
 
-	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
+	    for (srcobj = globallist_next(dstobj); srcobj != NULL;
+	      srcobj = globallist_next(srcobj)) {
 		res = symlook_obj(&req, srcobj);
 		if (res == 0) {
 		    srcsym = req.sym_out;
@@ -125,213 +129,188 @@
 	const Elf_Rela *relalim;
 	const Elf_Rela *rela;
 	SymCache *cache;
-	int r = -1;
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+	Elf_Addr *where, symval;
+	Elf32_Addr *where32;
+	int r;
 
+	r = -1;
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().
 	 */
 	if (obj != obj_rtld) {
-	    cache = calloc(obj->dynsymcount, sizeof(SymCache));
-	    /* No need to check for NULL here */
+		cache = calloc(obj->dynsymcount, sizeof(SymCache));
+		/* No need to check for NULL here */
 	} else
-	    cache = NULL;
+		cache = NULL;
 
-	relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
+	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
 	for (rela = obj->rela;  rela < relalim;  rela++) {
-	    Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
-	    Elf32_Addr *where32 = (Elf32_Addr *)where;
-
-	    switch (ELF_R_TYPE(rela->r_info)) {
-
-	    case R_X86_64_NONE:
-		break;
-
-	    case R_X86_64_64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where = (Elf_Addr) (defobj->relocbase + def->st_value + rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_PC32:
 		/*
-		 * I don't think the dynamic linker should ever see this
-		 * type of relocation.  But the binutils-2.6 tools sometimes
-		 * generate it.
+		 * First, resolve symbol for relocations which
+		 * reference symbols.
 		 */
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase +
-		        def->st_value + rela->r_addend - (Elf_Addr) where);
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_X86_64_64:
+		case R_X86_64_PC32:
+		case R_X86_64_GLOB_DAT:
+		case R_X86_64_TPOFF64:
+		case R_X86_64_TPOFF32:
+		case R_X86_64_DTPMOD64:
+		case R_X86_64_DTPOFF64:
+		case R_X86_64_DTPOFF32:
+			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
+			    &defobj, flags, cache, lockstate);
+			if (def == NULL)
+				goto done;
+			/*
+			 * If symbol is IFUNC, only perform relocation
+			 * when caller allowed it by passing
+			 * SYMLOOK_IFUNC flag.  Skip the relocations
+			 * otherwise.
+			 *
+			 * Also error out in case IFUNC relocations
+			 * are specified for TLS, which cannot be
+			 * usefully interpreted.
+			 */
+			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+				switch (ELF_R_TYPE(rela->r_info)) {
+				case R_X86_64_64:
+				case R_X86_64_PC32:
+				case R_X86_64_GLOB_DAT:
+					if ((flags & SYMLOOK_IFUNC) == 0) {
+						obj->non_plt_gnu_ifunc = true;
+						continue;
+					}
+					symval = (Elf_Addr)rtld_resolve_ifunc(
+					    defobj, def);
+					break;
+				case R_X86_64_TPOFF64:
+				case R_X86_64_TPOFF32:
+				case R_X86_64_DTPMOD64:
+				case R_X86_64_DTPOFF64:
+				case R_X86_64_DTPOFF32:
+					_rtld_error("%s: IFUNC for TLS reloc",
+					    obj->path);
+					goto done;
+				}
+			} else {
+				if ((flags & SYMLOOK_IFUNC) != 0)
+					continue;
+				symval = (Elf_Addr)defobj->relocbase +
+				    def->st_value;
+			}
+			break;
+		default:
+			if ((flags & SYMLOOK_IFUNC) != 0)
+				continue;
+			break;
 		}
-		break;
-	/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
+		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+		where32 = (Elf32_Addr *)where;
 
-	    case R_X86_64_COPY:
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_X86_64_NONE:
+			break;
+		case R_X86_64_64:
+			*where = symval + rela->r_addend;
+			break;
+		case R_X86_64_PC32:
+			/*
+			 * I don't think the dynamic linker should
+			 * ever see this type of relocation.  But the
+			 * binutils-2.6 tools sometimes generate it.
+			 */
+			*where32 = (Elf32_Addr)(unsigned long)(symval +
+		            rela->r_addend - (Elf_Addr)where);
+			break;
+		/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
+		case R_X86_64_COPY:
+			/*
+			 * These are deferred until all other relocations have
+			 * been done.  All we do here is make sure that the COPY
+			 * relocation is not in a shared library.  They are allowed
+			 * only in executable files.
+			 */
+			if (!obj->mainprog) {
+				_rtld_error("%s: Unexpected R_X86_64_COPY "
+				    "relocation in shared library", obj->path);
+				goto done;
+			}
+			break;
+		case R_X86_64_GLOB_DAT:
+			*where = symval;
+			break;
+		case R_X86_64_TPOFF64:
+			/*
+			 * We lazily allocate offsets for static TLS
+			 * as we see the first relocation that
+			 * references the TLS block. This allows us to
+			 * support (small amounts of) static TLS in
+			 * dynamically loaded modules. If we run out
+			 * of space, we generate an error.
+			 */
+			if (!defobj->tls_done) {
+				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+					_rtld_error("%s: No space available "
+					    "for static Thread Local Storage",
+					    obj->path);
+					goto done;
+				}
+			}
+			*where = (Elf_Addr)(def->st_value - defobj->tlsoffset +
+			    rela->r_addend);
+			break;
+		case R_X86_64_TPOFF32:
+			/*
+			 * We lazily allocate offsets for static TLS
+			 * as we see the first relocation that
+			 * references the TLS block. This allows us to
+			 * support (small amounts of) static TLS in
+			 * dynamically loaded modules. If we run out
+			 * of space, we generate an error.
+			 */
+			if (!defobj->tls_done) {
+				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+					_rtld_error("%s: No space available "
+					    "for static Thread Local Storage",
+					    obj->path);
+					goto done;
+				}
+			}
+			*where32 = (Elf32_Addr)(def->st_value -
+			    defobj->tlsoffset + rela->r_addend);
+			break;
+		case R_X86_64_DTPMOD64:
+			*where += (Elf_Addr)defobj->tlsindex;
+			break;
+		case R_X86_64_DTPOFF64:
+			*where += (Elf_Addr)(def->st_value + rela->r_addend);
+			break;
+		case R_X86_64_DTPOFF32:
+			*where32 += (Elf32_Addr)(def->st_value +
+			    rela->r_addend);
+			break;
+		case R_X86_64_RELATIVE:
+			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
+			break;
 		/*
-		 * These are deferred until all other relocations have
-		 * been done.  All we do here is make sure that the COPY
-		 * relocation is not in a shared library.  They are allowed
-		 * only in executable files.
+		 * missing:
+		 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16,
+		 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8
 		 */
-		if (!obj->mainprog) {
-		    _rtld_error("%s: Unexpected R_X86_64_COPY relocation"
-		      " in shared library", obj->path);
-		    goto done;
-		}
-		break;
-
-	    case R_X86_64_GLOB_DAT:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
+		default:
+			_rtld_error("%s: Unsupported relocation type %u"
+			    " in non-PLT relocations\n", obj->path,
+			    (unsigned int)ELF_R_TYPE(rela->r_info));
 			goto done;
-
-		    *where = (Elf_Addr) (defobj->relocbase + def->st_value);
 		}
-		break;
-
-	    case R_X86_64_TPOFF64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    /*
-		     * We lazily allocate offsets for static TLS as we
-		     * see the first relocation that references the
-		     * TLS block. This allows us to support (small
-		     * amounts of) static TLS in dynamically loaded
-		     * modules. If we run out of space, we generate an
-		     * error.
-		     */
-		    if (!defobj->tls_done) {
-			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
-			    _rtld_error("%s: No space available for static "
-					"Thread Local Storage", obj->path);
-			    goto done;
-			}
-		    }
-
-		    *where = (Elf_Addr) (def->st_value - defobj->tlsoffset +
-					 rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_TPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    /*
-		     * We lazily allocate offsets for static TLS as we
-		     * see the first relocation that references the
-		     * TLS block. This allows us to support (small
-		     * amounts of) static TLS in dynamically loaded
-		     * modules. If we run out of space, we generate an
-		     * error.
-		     */
-		    if (!defobj->tls_done) {
-			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
-			    _rtld_error("%s: No space available for static "
-					"Thread Local Storage", obj->path);
-			    goto done;
-			}
-		    }
-
-		    *where32 = (Elf32_Addr) (def->st_value -
-					     defobj->tlsoffset +
-					     rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_DTPMOD64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) defobj->tlsindex;
-		}
-		break;
-
-	    case R_X86_64_DTPOFF64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) (def->st_value + rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_DTPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where32 += (Elf32_Addr) (def->st_value + rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_RELATIVE:
-		*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
-		break;
-
-	/* missing: R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 */
-
-	    default:
-		_rtld_error("%s: Unsupported relocation type %u"
-		  " in non-PLT relocations\n", obj->path,
-		  (unsigned int)ELF_R_TYPE(rela->r_info));
-		goto done;
-	    }
 	}
 	r = 0;
 done:
-	if (cache != NULL)
-	    free(cache);
+	free(cache);
 	return (r);
 }
 
@@ -429,7 +408,7 @@
 	  ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
 	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 	  lock_release(rtld_bind_lock, lockstate);
-	  target = ((Elf_Addr (*)(void))ptr)();
+	  target = call_ifunc_resolver(ptr);
 	  wlock_acquire(rtld_bind_lock, lockstate);
 	  *where = target;
 	  break;
@@ -473,7 +452,32 @@
     return (0);
 }
 
+uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2;
+
 void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+	u_int p[4], cpu_high;
+
+	do_cpuid(1, p);
+	cpu_feature = p[3];
+	cpu_feature2 = p[2];
+	do_cpuid(0, p);
+	cpu_high = p[0];
+	if (cpu_high >= 7) {
+		cpuid_count(7, 0, p);
+		cpu_stdext_feature = p[1];
+		cpu_stdext_feature2 = p[2];
+	}
+}
+
+void
+pre_init(void)
+{
+
+}
+
+void
 allocate_initial_tls(Obj_Entry *objs)
 {
     /*
@@ -489,10 +493,8 @@
 void *__tls_get_addr(tls_index *ti)
 {
     Elf_Addr** segbase;
-    Elf_Addr* dtv;
 
     __asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
-    dtv = segbase[1];
 
     return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
 }

Modified: trunk/libexec/rtld-elf/amd64/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/amd64/rtld_machdep.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/amd64/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 1999, 2000 John D. Polstra.
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/amd64/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
  */
 
 #ifndef RTLD_MACHDEP_H
@@ -61,6 +62,14 @@
 #define call_init_pointer(obj, target) \
 	(((InitArrFunc)(target))(main_argc, main_argv, environ))
 
+extern uint32_t cpu_feature;
+extern uint32_t cpu_feature2;
+extern uint32_t cpu_stdext_feature;
+extern uint32_t cpu_stdext_feature2;
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(uint32_t, uint32_t, uint32_t, uint32_t))ptr)( \
+	    cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2))
+
 #define round(size, align) \
 	(((size) + (align) - 1) & ~((align) - 1))
 #define calculate_first_tls_offset(size, align) \
@@ -74,7 +83,7 @@
     unsigned long ti_offset;
 } tls_index;
 
-extern void *__tls_get_addr(tls_index *ti);
+void *__tls_get_addr(tls_index *ti) __exported;
 
 #define	RTLD_DEFAULT_STACK_PF_EXEC	PF_X
 #define	RTLD_DEFAULT_STACK_EXEC		PROT_EXEC

Modified: trunk/libexec/rtld-elf/amd64/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/amd64/rtld_start.S	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/amd64/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996-1998 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/amd64/rtld_start.S 281453 2015-04-12 06:45:40Z kib $
  */
 
 	.text
@@ -36,7 +37,7 @@
 	movq	%rsp,%rsi		# save address of exit proc
 	movq	%rsp,%rdx		# construct address of obj_main
 	addq	$8,%rdx
-	call	_rtld at PLT		# Call rtld(sp); returns entry point
+	call	_rtld			# Call rtld(sp); returns entry point
 	popq	%rsi			# Get exit procedure address
 	movq	%r12,%rdi		# *ap
 /*
@@ -79,17 +80,39 @@
 	.globl	_rtld_bind_start
 	.type	_rtld_bind_start, at function
 _rtld_bind_start:
+	.cfi_startproc
+	.cfi_adjust_cfa_offset	16
 	subq	$8,%rsp
+	.cfi_adjust_cfa_offset	8
 	pushfq				# Save rflags
+	.cfi_adjust_cfa_offset	8
 	pushq	%rax			# Save %rax
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%rax,-32
 	pushq	%rdx			# Save %rdx
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%rdx,-40
 	pushq	%rcx			# Save %rcx
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%rcx,-48
 	pushq	%rsi			# Save %rsi
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%rsi,-56
 	pushq	%rdi			# Save %rdi
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%rdi,-64
 	pushq	%r8			# Save %r8
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%r8,-72
 	pushq	%r9			# Save %r9
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%r9,-80
 	pushq	%r10			# Save %r10
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%r10,-88
 	pushq	%r11			# Save %r11
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset	%r11,-96
 
 	movq	0x58(%rsp),%rdi		# Fetch obj argument
 	movq	0x60(%rsp),%rsi		# Fetch reloff argument
@@ -96,21 +119,42 @@
 	leaq	(%rsi,%rsi,2),%rsi	# multiply by 3
 	leaq	(,%rsi,8),%rsi		# now 8, for 24 (sizeof Elf_Rela)
 
-	call	_rtld_bind at PLT		# Transfer control to the binder
+	call	_rtld_bind		# Transfer control to the binder
 	/* Now %rax contains the entry point of the function being called. */
 
 	movq	%rax,0x60(%rsp)		# Store target over reloff argument
 	popq	%r11			# Restore %r11
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %r11
 	popq	%r10			# Restore %r10
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %r10
 	popq	%r9			# Restore %r9
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %r9
 	popq	%r8			# Restore %r8
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %r8
 	popq	%rdi			# Restore %rdi
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %rdi
 	popq	%rsi			# Restore %rsi
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %rsi
 	popq	%rcx			# Restore %rcx
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %rcx
 	popq	%rdx			# Restore %rdx
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %rdx
 	popq	%rax			# Restore %rax
+	.cfi_adjust_cfa_offset -8
+	.cfi_restore %rax
 	popfq				# Restore rflags
+	.cfi_adjust_cfa_offset -8
 	leaq	16(%rsp),%rsp		# Discard spare, obj, do not change rflags
 	ret				# "Return" to target address
+	.cfi_endproc
+	.size	_rtld_bind_start, . - _rtld_bind_start
 
 	.section .note.GNU-stack,"",%progbits


Property changes on: trunk/libexec/rtld-elf/amd64/rtld_start.S
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/libexec/rtld-elf/arm/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/arm/Makefile.inc	                        (rev 0)
+++ trunk/libexec/rtld-elf/arm/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1 @@
+# $MidnightBSD$


Property changes on: trunk/libexec/rtld-elf/arm/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/arm/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/arm/reloc.c	                        (rev 0)
+++ trunk/libexec/rtld-elf/arm/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,488 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $	*/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/libexec/rtld-elf/arm/reloc.c 331206 2018-03-19 14:28:58Z marius $");
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "machine/sysarch.h"
+
+#include "debug.h"
+#include "rtld.h"
+
+void
+init_pltgot(Obj_Entry *obj)
+{       
+	if (obj->pltgot != NULL) {
+		obj->pltgot[1] = (Elf_Addr) obj;
+		obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+	}
+}
+
+int             
+do_copy_relocations(Obj_Entry *dstobj)
+{
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+
+	assert(dstobj->mainprog);	/* COPY relocations are invalid elsewhere */
+
+   	rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
+	for (rel = dstobj->rel;  rel < rellim;  rel++) {
+		if (ELF_R_TYPE(rel->r_info) == R_ARM_COPY) {
+	    		void *dstaddr;
+			const Elf_Sym *dstsym;
+			const char *name;
+			size_t size;
+			const void *srcaddr;
+			const Elf_Sym *srcsym;
+			const Obj_Entry *srcobj, *defobj;
+			SymLook req;
+			int res;
+			
+			dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
+			dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
+			name = dstobj->strtab + dstsym->st_name;
+			size = dstsym->st_size;
+
+			symlook_init(&req, name);
+			req.ventry = fetch_ventry(dstobj,
+			    ELF_R_SYM(rel->r_info));
+			req.flags = SYMLOOK_EARLY;
+
+			for (srcobj = globallist_next(dstobj); srcobj != NULL;
+			    srcobj = globallist_next(srcobj)) {
+				res = symlook_obj(&req, srcobj);
+				if (res == 0) {
+					srcsym = req.sym_out;
+					defobj = req.defobj_out;
+					break;
+				}
+			}			
+			if (srcobj == NULL) {
+				_rtld_error(
+"Undefined symbol \"%s\" referenced from COPY relocation in %s",
+				    name, dstobj->path);
+				return (-1);
+			}
+			
+			srcaddr = (const void *)(defobj->relocbase +
+			    srcsym->st_value);
+			memcpy(dstaddr, srcaddr, size);
+		}
+	}
+	return 0;			     
+}
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+
+int open();
+int _open();
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+	const Elf_Rel *rel = 0, *rellim;
+	Elf_Addr relsz = 0;
+	Elf_Addr *where;
+	uint32_t size;
+
+	for (; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_REL:
+			rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
+			break;
+		case DT_RELSZ:
+			relsz = dynp->d_un.d_val;
+			break;
+		}
+	}
+	rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
+	size = (rellim - 1)->r_offset - rel->r_offset;
+	for (; rel < rellim; rel++) {
+		where = (Elf_Addr *)(relocbase + rel->r_offset);
+		
+		*where += (Elf_Addr)relocbase;
+	}
+}
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#define	RELOC_ALIGNED_P(x) \
+	(((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+
+static __inline Elf_Addr
+load_ptr(void *where)
+{
+	Elf_Addr res;
+
+	memcpy(&res, where, sizeof(res));
+
+	return (res);
+}
+
+static __inline void
+store_ptr(void *where, Elf_Addr val)
+{
+
+	memcpy(where, &val, sizeof(val));
+}
+
+static int
+reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
+    int flags, RtldLockState *lockstate)
+{
+	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_ARM_NONE:
+		break;
+		
+#if 1 /* XXX should not occur */
+	case R_ARM_PC24: {	/* word32 S - P + A */
+		Elf32_Sword addend;
+		
+		/*
+		 * Extract addend and sign-extend if needed.
+		 */
+		addend = *where;
+		if (addend & 0x00800000)
+			addend |= 0xff000000;
+		
+		def = find_symdef(symnum, obj, &defobj, flags, cache,
+		    lockstate);
+		if (def == NULL)
+				return -1;
+			tmp = (Elf_Addr)obj->relocbase + def->st_value
+			    - (Elf_Addr)where + (addend << 2);
+			if ((tmp & 0xfe000000) != 0xfe000000 &&
+			    (tmp & 0xfe000000) != 0) {
+				_rtld_error(
+				"%s: R_ARM_PC24 relocation @ %p to %s failed "
+				"(displacement %ld (%#lx) out of range)",
+				    obj->path, where,
+				    obj->strtab + obj->symtab[symnum].st_name,
+				    (long) tmp, (long) tmp);
+				return -1;
+			}
+			tmp >>= 2;
+			*where = (*where & 0xff000000) | (tmp & 0x00ffffff);
+			dbg("PC24 %s in %s --> %p @ %p in %s",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)*where, where, defobj->path);
+			break;
+		}
+#endif
+
+		case R_ARM_ABS32:	/* word32 B + S + A */
+		case R_ARM_GLOB_DAT:	/* word32 B + S */
+			def = find_symdef(symnum, obj, &defobj, flags, cache,
+			    lockstate);
+			if (def == NULL)
+				return -1;
+			if (__predict_true(RELOC_ALIGNED_P(where))) {
+				tmp =  *where + (Elf_Addr)defobj->relocbase +
+				    def->st_value;
+				*where = tmp;
+			} else {
+				tmp = load_ptr(where) +
+				    (Elf_Addr)defobj->relocbase +
+				    def->st_value;
+				store_ptr(where, tmp);
+			}
+			dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)tmp, where, defobj->path);
+			break;
+
+		case R_ARM_RELATIVE:	/* word32 B + A */
+			if (__predict_true(RELOC_ALIGNED_P(where))) {
+				tmp = *where + (Elf_Addr)obj->relocbase;
+				*where = tmp;
+			} else {
+				tmp = load_ptr(where) +
+				    (Elf_Addr)obj->relocbase;
+				store_ptr(where, tmp);
+			}
+			dbg("RELATIVE in %s --> %p", obj->path,
+			    (void *)tmp);
+			break;
+
+		case R_ARM_COPY:
+			/*
+			 * These are deferred until all other relocations have
+			 * been done.  All we do here is make sure that the
+			 * COPY relocation is not in a shared library.  They
+			 * are allowed only in executable files.
+			 */
+			if (!obj->mainprog) {
+				_rtld_error(
+			"%s: Unexpected R_COPY relocation in shared library",
+				    obj->path);
+				return -1;
+			}
+			dbg("COPY (avoid in main)");
+			break;
+
+		case R_ARM_TLS_DTPOFF32:
+			def = find_symdef(symnum, obj, &defobj, flags, cache,
+			    lockstate);
+			if (def == NULL)
+				return -1;
+
+			tmp = (Elf_Addr)(def->st_value);
+			if (__predict_true(RELOC_ALIGNED_P(where)))
+				*where = tmp;
+			else
+				store_ptr(where, tmp);
+
+			dbg("TLS_DTPOFF32 %s in %s --> %p",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)tmp);
+
+			break;
+		case R_ARM_TLS_DTPMOD32:
+			def = find_symdef(symnum, obj, &defobj, flags, cache,
+			    lockstate);
+			if (def == NULL)
+				return -1;
+
+			tmp = (Elf_Addr)(defobj->tlsindex);
+			if (__predict_true(RELOC_ALIGNED_P(where)))
+				*where = tmp;
+			else
+				store_ptr(where, tmp);
+
+			dbg("TLS_DTPMOD32 %s in %s --> %p",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)tmp);
+
+			break;
+
+		case R_ARM_TLS_TPOFF32:
+			def = find_symdef(symnum, obj, &defobj, flags, cache,
+			    lockstate);
+			if (def == NULL)
+				return -1;
+
+			if (!defobj->tls_done && allocate_tls_offset(obj))
+				return -1;
+
+			/* XXX: FIXME */
+			tmp = (Elf_Addr)def->st_value + defobj->tlsoffset +
+			    TLS_TCB_SIZE;
+			if (__predict_true(RELOC_ALIGNED_P(where)))
+				*where = tmp;
+			else
+				store_ptr(where, tmp);
+			dbg("TLS_TPOFF32 %s in %s --> %p",
+			    obj->strtab + obj->symtab[symnum].st_name,
+			    obj->path, (void *)tmp);
+			break;
+
+
+		default:
+			dbg("sym = %lu, type = %lu, offset = %p, "
+			    "contents = %p, symbol = %s",
+			    symnum, (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 "
+			    "in non-PLT relocations\n",
+			    obj->path, (u_long) ELF_R_TYPE(rel->r_info));
+			return -1;
+	}
+	return 0;
+}
+
+/*
+ *  * Process non-PLT relocations
+ *   */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
+    RtldLockState *lockstate)
+{
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+	SymCache *cache;
+	int r = -1;
+	
+	/* The relocation for the dynamic loader has already been done. */
+	if (obj == obj_rtld)
+		return (0);
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
+	/*
+ 	 * The dynamic loader may be called from a thread, we have
+	 * limited amounts of stack available so we cannot use alloca().
+	 */
+	cache = calloc(obj->dynsymcount, sizeof(SymCache));
+	/* No need to check for NULL here */
+
+	rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
+	for (rel = obj->rel; rel < rellim; rel++) {
+		if (reloc_nonplt_object(obj, rel, cache, flags, lockstate) < 0)
+			goto done;
+	}
+	r = 0;
+done:
+	if (cache != NULL)
+		free(cache);
+	return (r);
+}
+
+/*
+ *  * Process the PLT relocations.
+ *   */
+int
+reloc_plt(Obj_Entry *obj)
+{
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+		
+	rellim = (const Elf_Rel *)((char *)obj->pltrel +
+	    obj->pltrelsize);
+	for (rel = obj->pltrel;  rel < rellim;  rel++) {
+		Elf_Addr *where;
+
+		assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
+		
+		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+		*where += (Elf_Addr )obj->relocbase;
+	}
+	
+	return (0);
+}
+
+/*
+ *  * LD_BIND_NOW was set - force relocation for all jump slots
+ *   */
+int
+reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
+{
+	const Obj_Entry *defobj;
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+	const Elf_Sym *def;
+	Elf_Addr *where;
+	Elf_Addr target;
+	
+	rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
+	for (rel = obj->pltrel; rel < rellim; rel++) {
+		assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
+		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+		def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+		    SYMLOOK_IN_PLT | flags, NULL, lockstate);
+		if (def == NULL) {
+			dbg("reloc_jmpslots: sym not found");
+			return (-1);
+		}
+		
+		target = (Elf_Addr)(defobj->relocbase + def->st_value);		
+		reloc_jmpslot(where, target, defobj, obj,
+		    (const Elf_Rel *) rel);
+	}
+	
+	obj->jmpslots_done = true;
+	
+	return (0);
+}
+
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, int flags,
+    struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+Elf_Addr
+reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
+    		const Obj_Entry *obj, const Elf_Rel *rel)
+{
+
+	assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
+
+	if (*where != target)
+		*where = target;
+
+	return target;
+}
+
+void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+
+}
+
+void
+pre_init(void)
+{
+
+}
+
+void
+allocate_initial_tls(Obj_Entry *objs)
+{
+#ifdef ARM_TP_ADDRESS
+	void **_tp = (void **)ARM_TP_ADDRESS;
+#endif
+
+	/*
+	* Fix the size of the static TLS block by using the maximum
+	* offset allocated so far and adding a bit for dynamic modules to
+	* use.
+	*/
+
+	tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
+
+#ifdef ARM_TP_ADDRESS
+	(*_tp) = (void *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8);
+#else
+	sysarch(ARM_SET_TP, allocate_tls(objs, NULL, TLS_TCB_SIZE, 8));
+#endif
+}
+
+void *
+__tls_get_addr(tls_index* ti)
+{
+	char *p;
+#ifdef ARM_TP_ADDRESS
+	void **_tp = (void **)ARM_TP_ADDRESS;
+
+	p = tls_get_addr_common((Elf_Addr **)(*_tp), ti->ti_module, ti->ti_offset);
+#else
+	void *_tp;
+	__asm __volatile("mrc  p15, 0, %0, c13, c0, 3"		\
+	    : "=r" (_tp));
+	p = tls_get_addr_common((Elf_Addr **)(_tp), ti->ti_module, ti->ti_offset);
+#endif
+
+	return (p);
+}


Property changes on: trunk/libexec/rtld-elf/arm/reloc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/arm/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/arm/rtld_machdep.h	                        (rev 0)
+++ trunk/libexec/rtld-elf/arm/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,82 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999, 2000 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/arm/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
+ */
+
+#ifndef RTLD_MACHDEP_H
+#define RTLD_MACHDEP_H	1
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+
+struct Struct_Obj_Entry;
+
+/* Return the address of the .dynamic section in the dynamic linker. */
+#define rtld_dynamic(obj) (&_DYNAMIC)
+
+Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
+		       const struct Struct_Obj_Entry *defobj,
+		       const struct Struct_Obj_Entry *obj,
+		       const Elf_Rel *rel);
+
+#define make_function_pointer(def, defobj) \
+	((defobj)->relocbase + (def)->st_value)
+
+#define call_initfini_pointer(obj, target) \
+	(((InitFunc)(target))())
+	
+#define call_init_pointer(obj, target) \
+	(((InitArrFunc)(target))(main_argc, main_argv, environ))
+
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(void))ptr)())
+
+#define	TLS_TCB_SIZE	8
+typedef struct {
+	unsigned long ti_module;
+	unsigned long ti_offset;
+} tls_index;
+
+#define round(size, align) \
+    (((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+    round(8, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+    round(prev_offset + prev_size, align)
+#define calculate_tls_end(off, size)    ((off) + (size))
+	
+/*
+ * Lazy binding entry point, called via PLT.
+ */
+void _rtld_bind_start(void);
+
+extern void *__tls_get_addr(tls_index *ti);
+
+#define	RTLD_DEFAULT_STACK_PF_EXEC	PF_X
+#define	RTLD_DEFAULT_STACK_EXEC		PROT_EXEC
+
+#endif


Property changes on: trunk/libexec/rtld-elf/arm/rtld_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/arm/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/arm/rtld_start.S	                        (rev 0)
+++ trunk/libexec/rtld-elf/arm/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,97 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: rtld_start.S,v 1.7 2002/09/12 17:18:38 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/libexec/rtld-elf/arm/rtld_start.S 239031 2012-08-04 05:30:20Z andrew $");
+
+	.text
+	.align	0
+	.globl	.rtld_start
+	.type	.rtld_start,%function
+.rtld_start:
+	mov	r6, sp			/* save the stack pointer */
+	bic	sp, sp, #7		/* align the stack pointer */
+	sub	sp, sp, #8		/* make room for obj_main & exit proc */
+	mov	r4, r0			/* save ps_strings */
+	ldr	sl, .L2
+	ldr	r5, .L2+4
+	ldr	r0, .L2+8
+.L1:
+	add	sl, pc, sl
+	ldr	r5, [sl, r5]
+	ldr	r0, [sl, r0]
+
+	sub	r1, sl, r5		/* relocbase */
+	add	r0, r1, r0		/* &_DYNAMIC */
+	bl	_rtld_relocate_nonplt_self
+	mov	r1, sp
+	add	r2, sp, #4
+	mov	r0, r6			/* load the sp the kernel gave us */
+	bl	_rtld			/* call the shared loader */
+	mov	r3, r0			/* save entry point */
+
+	ldr	r2, [sp, #0]		/* r2 = cleanup */
+	ldr	r1, [sp, #4]		/* r1 = obj_main */
+	mov	sp, r6			/* restore stack */
+	mov	r0, r4			/* restore ps_strings */
+	mov	pc, r3			/* jump to the entry point */
+.L2:
+	.word	_GLOBAL_OFFSET_TABLE_ - (.L1+8)
+	.word	_GLOBAL_OFFSET_TABLE_(GOT)
+	.word	_DYNAMIC(GOT)
+
+	.align	0
+	.globl	_rtld_bind_start
+	.type	_rtld_bind_start,%function
+/*
+ *	stack[0] = RA
+ *	ip = &GOT[n+3]
+ *	lr = &GOT[2]
+ */
+_rtld_bind_start:
+	stmdb	sp!,{r0-r4,sl,fp}
+
+	sub	r1, ip, lr		/* r1 = 4 * (n + 1) */
+	sub	r1, r1, #4		/* r1 = 4 * n */
+	add	r1, r1, r1		/* r1 = 8 * n */
+
+	ldr	r0, [lr, #-4]		/* get obj ptr from GOT[1] */
+	mov	r4, ip			/* save GOT location */
+
+	bl	_rtld_bind		/* Call the binder */
+
+	str	r0, [r4]		/* save address in GOT */
+	mov	ip, r0			/* save new address */
+
+	ldmia	sp!,{r0-r4,sl,fp,lr}	/* restore the stack */
+	mov	pc, ip			/* jump to the new address */
+


Property changes on: trunk/libexec/rtld-elf/arm/rtld_start.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/debug.c
===================================================================
--- trunk/libexec/rtld-elf/debug.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/debug.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996-1998 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/debug.c 296727 2016-03-12 17:12:00Z kib $
  */
 
 /*
@@ -62,7 +63,8 @@
 {
     Obj_Entry *obj;
 
-    for (obj = obj0; obj != NULL; obj = obj->next) {
+    for (obj = globallist_curr(obj0); obj != NULL;
+      obj = globallist_next(obj)) {
         dump_obj_relocations(obj);
     }
 }

Modified: trunk/libexec/rtld-elf/debug.h
===================================================================
--- trunk/libexec/rtld-elf/debug.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/debug.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996-1998 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/debug.h 287331 2015-08-31 19:20:18Z emaste $
  */
 
 /*
@@ -32,10 +33,6 @@
 #ifndef DEBUG_H
 #define DEBUG_H 1
 
-#ifndef __GNUC__
-#error "This file must be compiled with GCC"
-#endif
-
 #include <sys/cdefs.h>
 
 #include <string.h>

Modified: trunk/libexec/rtld-elf/i386/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/i386/Makefile.inc	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/i386/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,6 +1,6 @@
 # $MidnightBSD$
 
-CFLAGS+=	-mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
+CFLAGS+=	${CFLAGS_NO_SIMD} -msoft-float
 # Uncomment this to build the dynamic linker as an executable instead
 # of a shared library:
 #LDSCRIPT=	${.CURDIR}/${MACHINE_CPUARCH}/elf_rtld.x


Property changes on: trunk/libexec/rtld-elf/i386/Makefile.inc
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/i386/Symbol.map
===================================================================
--- trunk/libexec/rtld-elf/i386/Symbol.map	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/i386/Symbol.map	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,5 +1,5 @@
-/*
- * $MidnightBSD$
+/* $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/i386/Symbol.map 169092 2007-04-29 14:05:22Z deischen $
  */
 
 FBSD_1.0 {


Property changes on: trunk/libexec/rtld-elf/i386/Symbol.map
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/i386/elf_rtld.x
===================================================================
--- trunk/libexec/rtld-elf/i386/elf_rtld.x	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/i386/elf_rtld.x	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 OUTPUT_FORMAT("elf32-i386", "elf32-i386",
 	      "elf32-i386")
 OUTPUT_ARCH(i386)


Property changes on: trunk/libexec/rtld-elf/i386/elf_rtld.x
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/i386/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/i386/reloc.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/i386/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/i386/reloc.c 331206 2018-03-19 14:28:58Z marius $
  */
 
 /*
@@ -48,6 +49,7 @@
 
 #include "debug.h"
 #include "rtld.h"
+#include "rtld_tls.h"
 
 /*
  * Process the special R_386_COPY relocations in the main program.  These
@@ -85,7 +87,8 @@
 	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info));
 	    req.flags = SYMLOOK_EARLY;
 
-	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
+	    for (srcobj = globallist_next(dstobj);  srcobj != NULL;
+	      srcobj = globallist_next(srcobj)) {
 		res = symlook_obj(&req, srcobj);
 		if (res == 0) {
 		    srcsym = req.sym_out;
@@ -126,168 +129,144 @@
 	const Elf_Rel *rellim;
 	const Elf_Rel *rel;
 	SymCache *cache;
-	int r = -1;
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+	Elf_Addr *where, symval, add;
+	int r;
 
+	r = -1;
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().
 	 */
 	if (obj != obj_rtld) {
-	    cache = calloc(obj->dynsymcount, sizeof(SymCache));
-	    /* No need to check for NULL here */
+		cache = calloc(obj->dynsymcount, sizeof(SymCache));
+		/* No need to check for NULL here */
 	} else
-	    cache = NULL;
+		cache = NULL;
 
-	rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
+	rellim = (const Elf_Rel *)((caddr_t) obj->rel + obj->relsize);
 	for (rel = obj->rel;  rel < rellim;  rel++) {
-	    Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
-
-	    switch (ELF_R_TYPE(rel->r_info)) {
-
-	    case R_386_NONE:
-		break;
-
-	    case R_386_32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) (defobj->relocbase + def->st_value);
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_386_32:
+		case R_386_PC32:
+		case R_386_GLOB_DAT:
+		case R_386_TLS_TPOFF:
+		case R_386_TLS_TPOFF32:
+		case R_386_TLS_DTPMOD32:
+		case R_386_TLS_DTPOFF32:
+			def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+			    flags, cache, lockstate);
+			if (def == NULL)
+				goto done;
+			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+				switch (ELF_R_TYPE(rel->r_info)) {
+				case R_386_32:
+				case R_386_PC32:
+				case R_386_GLOB_DAT:
+					if ((flags & SYMLOOK_IFUNC) == 0) {
+						obj->non_plt_gnu_ifunc = true;
+						continue;
+					}
+					symval = (Elf_Addr)rtld_resolve_ifunc(
+					    defobj, def);
+					break;
+				case R_386_TLS_TPOFF:
+				case R_386_TLS_TPOFF32:
+				case R_386_TLS_DTPMOD32:
+				case R_386_TLS_DTPOFF32:
+					_rtld_error("%s: IFUNC for TLS reloc",
+					    obj->path);
+					goto done;
+				}
+			} else {
+				if ((flags & SYMLOOK_IFUNC) != 0)
+					continue;
+				symval = (Elf_Addr)defobj->relocbase +
+				    def->st_value;
+			}
+			break;
+		default:
+			if ((flags & SYMLOOK_IFUNC) != 0)
+				continue;
+			break;
 		}
-		break;
+		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
 
-	    case R_386_PC32:
-		/*
-		 * I don't think the dynamic linker should ever see this
-		 * type of relocation.  But the binutils-2.6 tools sometimes
-		 * generate it.
-		 */
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where +=
-		      (Elf_Addr) (defobj->relocbase + def->st_value) -
-		      (Elf_Addr) where;
-		}
-		break;
-
-	    case R_386_COPY:
-		/*
-		 * These are deferred until all other relocations have
-		 * been done.  All we do here is make sure that the COPY
-		 * relocation is not in a shared library.  They are allowed
-		 * only in executable files.
-		 */
-		if (!obj->mainprog) {
-		    _rtld_error("%s: Unexpected R_386_COPY relocation"
-		      " in shared library", obj->path);
-		    goto done;
-		}
-		break;
-
-	    case R_386_GLOB_DAT:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where = (Elf_Addr) (defobj->relocbase + def->st_value);
-		}
-		break;
-
-	    case R_386_RELATIVE:
-		*where += (Elf_Addr) obj->relocbase;
-		break;
-
-	    case R_386_TLS_TPOFF:
-	    case R_386_TLS_TPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-		    Elf_Addr add;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_386_NONE:
+			break;
+		case R_386_32:
+			*where += symval;
+			break;
+		case R_386_PC32:
 		    /*
-		     * We lazily allocate offsets for static TLS as we
-		     * see the first relocation that references the
-		     * TLS block. This allows us to support (small
-		     * amounts of) static TLS in dynamically loaded
-		     * modules. If we run out of space, we generate an
-		     * error.
+		     * I don't think the dynamic linker should ever
+		     * see this type of relocation.  But the
+		     * binutils-2.6 tools sometimes generate it.
 		     */
-		    if (!defobj->tls_done) {
-			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
-			    _rtld_error("%s: No space available for static "
-					"Thread Local Storage", obj->path);
-			    goto done;
+		    *where += symval - (Elf_Addr)where;
+		    break;
+		case R_386_COPY:
+			/*
+			 * These are deferred until all other
+			 * relocations have been done.  All we do here
+			 * is make sure that the COPY relocation is
+			 * not in a shared library.  They are allowed
+			 * only in executable files.
+			 */
+			if (!obj->mainprog) {
+				_rtld_error("%s: Unexpected R_386_COPY "
+				    "relocation in shared library", obj->path);
+				goto done;
 			}
-		    }
-		    add = (Elf_Addr) (def->st_value - defobj->tlsoffset);
-		    if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
-			*where += add;
-		    else
-			*where -= add;
-		}
-		break;
-
-	    case R_386_TLS_DTPMOD32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
+			break;
+		case R_386_GLOB_DAT:
+			*where = symval;
+			break;
+		case R_386_RELATIVE:
+			*where += (Elf_Addr)obj->relocbase;
+			break;
+		case R_386_TLS_TPOFF:
+		case R_386_TLS_TPOFF32:
+			/*
+			 * We lazily allocate offsets for static TLS
+			 * as we see the first relocation that
+			 * references the TLS block. This allows us to
+			 * support (small amounts of) static TLS in
+			 * dynamically loaded modules. If we run out
+			 * of space, we generate an error.
+			 */
+			if (!defobj->tls_done) {
+				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+					_rtld_error("%s: No space available "
+					    "for static Thread Local Storage",
+					    obj->path);
+					goto done;
+				}
+			}
+			add = (Elf_Addr)(def->st_value - defobj->tlsoffset);
+			if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
+				*where += add;
+			else
+				*where -= add;
+			break;
+		case R_386_TLS_DTPMOD32:
+			*where += (Elf_Addr)defobj->tlsindex;
+			break;
+		case R_386_TLS_DTPOFF32:
+			*where += (Elf_Addr) def->st_value;
+			break;
+		default:
+			_rtld_error("%s: Unsupported relocation type %d"
+			    " in non-PLT relocations\n", obj->path,
+			    ELF_R_TYPE(rel->r_info));
 			goto done;
-
-		    *where += (Elf_Addr) defobj->tlsindex;
 		}
-		break;
-
-	    case R_386_TLS_DTPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) def->st_value;
-		}
-		break;
-
-	    default:
-		_rtld_error("%s: Unsupported relocation type %d"
-		  " in non-PLT relocations\n", obj->path,
-		  ELF_R_TYPE(rel->r_info));
-		goto done;
-	    }
 	}
 	r = 0;
 done:
-	if (cache != NULL)
-	    free(cache);
+	free(cache);
 	return (r);
 }
 
@@ -381,7 +360,7 @@
 	case R_386_IRELATIVE:
 	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
 	  lock_release(rtld_bind_lock, lockstate);
-	  target = ((Elf_Addr (*)(void))(obj->relocbase + *where))();
+	  target = call_ifunc_resolver(obj->relocbase + *where);
 	  wlock_acquire(rtld_bind_lock, lockstate);
 	  *where = target;
 	  break;
@@ -426,7 +405,65 @@
     return (0);
 }
 
+uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2;
+
+static void
+rtld_cpuid_count(int idx, int cnt, u_int *p)
+{
+
+	__asm __volatile(
+	    "	pushl	%%ebx\n"
+	    "	cpuid\n"
+	    "	movl	%%ebx,%1\n"
+	    "	popl	%%ebx\n"
+	    : "=a" (p[0]), "=r" (p[1]), "=c" (p[2]), "=d" (p[3])
+	    :  "0" (idx), "2" (cnt));
+}
+
 void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+	u_int p[4], cpu_high;
+	int cpuid_supported;
+
+	__asm __volatile(
+	    "	pushfl\n"
+	    "	popl	%%eax\n"
+	    "	movl    %%eax,%%ecx\n"
+	    "	xorl    $0x200000,%%eax\n"
+	    "	pushl	%%eax\n"
+	    "	popfl\n"
+	    "	pushfl\n"
+	    "	popl    %%eax\n"
+	    "	xorl    %%eax,%%ecx\n"
+	    "	je	1f\n"
+	    "	movl	$1,%0\n"
+	    "	jmp	2f\n"
+	    "1:	movl	$0,%0\n"
+	    "2:\n"
+	    : "=r" (cpuid_supported) : : "eax", "ecx");
+	if (!cpuid_supported)
+		return;
+
+	rtld_cpuid_count(1, 0, p);
+	cpu_feature = p[3];
+	cpu_feature2 = p[2];
+	rtld_cpuid_count(0, 0, p);
+	cpu_high = p[0];
+	if (cpu_high >= 7) {
+		rtld_cpuid_count(7, 0, p);
+		cpu_stdext_feature = p[1];
+		cpu_stdext_feature2 = p[2];
+	}
+}
+
+void
+pre_init(void)
+{
+
+}
+
+void
 allocate_initial_tls(Obj_Entry *objs)
 {
     void* tls;
@@ -446,10 +483,8 @@
 void *___tls_get_addr(tls_index *ti)
 {
     Elf_Addr** segbase;
-    Elf_Addr* dtv;
 
     __asm __volatile("movl %%gs:0, %0" : "=r" (segbase));
-    dtv = segbase[1];
 
     return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
 }
@@ -458,10 +493,8 @@
 void *__tls_get_addr(tls_index *ti)
 {
     Elf_Addr** segbase;
-    Elf_Addr* dtv;
 
     __asm __volatile("movl %%gs:0, %0" : "=r" (segbase));
-    dtv = segbase[1];
 
     return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
 }

Modified: trunk/libexec/rtld-elf/i386/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/i386/rtld_machdep.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/i386/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 1999, 2000 John D. Polstra.
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/i386/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
  */
 
 #ifndef RTLD_MACHDEP_H
@@ -61,6 +62,14 @@
 #define call_init_pointer(obj, target) \
 	(((InitArrFunc)(target))(main_argc, main_argv, environ))
 
+extern uint32_t cpu_feature;
+extern uint32_t cpu_feature2;
+extern uint32_t cpu_stdext_feature;
+extern uint32_t cpu_stdext_feature2;
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(uint32_t, uint32_t, uint32_t, uint32_t))ptr)( \
+	    cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2))
+
 #define round(size, align) \
 	(((size) + (align) - 1) & ~((align) - 1))
 #define calculate_first_tls_offset(size, align) \
@@ -74,8 +83,8 @@
     unsigned long ti_offset;
 } tls_index;
 
-extern void *___tls_get_addr(tls_index *ti) __attribute__((__regparm__(1)));
-extern void *__tls_get_addr(tls_index *ti);
+void *___tls_get_addr(tls_index *ti) __attribute__((__regparm__(1))) __exported;
+void *__tls_get_addr(tls_index *ti) __exported;
 
 #define	RTLD_DEFAULT_STACK_PF_EXEC	PF_X
 #define	RTLD_DEFAULT_STACK_EXEC		PROT_EXEC

Modified: trunk/libexec/rtld-elf/i386/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/i386/rtld_start.S	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/i386/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996-1998 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/i386/rtld_start.S 281453 2015-04-12 06:45:40Z kib $
  */
 
 	.text
@@ -42,7 +43,7 @@
 	pushl	%ecx			# Pass address of obj_main
 	pushl	%ebx			# Pass address of exit proc
 	pushl	%eax			# Pass initial stack pointer to rtld
-	call	_rtld at PLT		# Call rtld(sp); returns entry point
+	call	_rtld			# Call rtld(sp); returns entry point
 	addl	$16,%esp		# Remove arguments from stack
 	popl	%edx			# Get exit procedure address
 	movl	%esi,%esp		# Ignore obj_main
@@ -78,7 +79,7 @@
 	pushl	20(%esp)		# Copy reloff argument
 	pushl	20(%esp)		# Copy obj argument
 
-	call	_rtld_bind at PLT		# Transfer control to the binder
+	call	_rtld_bind		# Transfer control to the binder
 	/* Now %eax contains the entry point of the function being called. */
 
 	addl	$8,%esp			# Discard binder arguments


Property changes on: trunk/libexec/rtld-elf/i386/rtld_start.S
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/libexec/rtld-elf/ia64/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/ia64/Makefile.inc	                        (rev 0)
+++ trunk/libexec/rtld-elf/ia64/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1 @@
+# $MidnightBSD$


Property changes on: trunk/libexec/rtld-elf/ia64/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/ia64/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/ia64/reloc.c	                        (rev 0)
+++ trunk/libexec/rtld-elf/ia64/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,675 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/ia64/reloc.c 331206 2018-03-19 14:28:58Z marius $
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp at polstra.com>.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <machine/ia64_cpu.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+extern Elf_Dyn _DYNAMIC;
+
+/*
+ * Macros for loading/storing unaligned 64-bit values.  These are
+ * needed because relocations can point to unaligned data.  This
+ * occurs in the DWARF2 exception frame tables generated by the
+ * compiler, for instance.
+ *
+ * We don't use these when relocating jump slots and GOT entries,
+ * since they are guaranteed to be aligned.
+ *
+ * XXX dfr stub for now.
+ */
+#define load64(p)	(*(u_int64_t *) (p))
+#define store64(p, v)	(*(u_int64_t *) (p) = (v))
+
+/* Allocate an @fptr. */
+
+#define FPTR_CHUNK_SIZE		64
+
+struct fptr_chunk {
+	struct fptr fptrs[FPTR_CHUNK_SIZE];
+};
+
+static struct fptr_chunk first_chunk;
+static struct fptr_chunk *current_chunk = &first_chunk;
+static struct fptr *next_fptr = &first_chunk.fptrs[0];
+static struct fptr *last_fptr = &first_chunk.fptrs[FPTR_CHUNK_SIZE];
+
+/*
+ * We use static storage initially so that we don't have to call
+ * malloc during init_rtld().
+ */
+static struct fptr *
+alloc_fptr(Elf_Addr target, Elf_Addr gp)
+{
+	struct fptr* fptr;
+
+	if (next_fptr == last_fptr) {
+		current_chunk = xmalloc(sizeof(struct fptr_chunk));
+		next_fptr = &current_chunk->fptrs[0];
+		last_fptr = &current_chunk->fptrs[FPTR_CHUNK_SIZE];
+	}
+	fptr = next_fptr;
+	next_fptr++;
+	fptr->target = target;
+	fptr->gp = gp;
+	return fptr;
+}
+
+static struct fptr **
+alloc_fptrs(Obj_Entry *obj, bool mapped)
+{
+	struct fptr **fptrs;
+	size_t fbytes;
+
+	fbytes = obj->dynsymcount * sizeof(struct fptr *);
+
+	/*
+	 * Avoid malloc, if requested. Happens when relocating
+	 * rtld itself on startup.
+	 */
+	if (mapped) {
+		fptrs = mmap(NULL, fbytes, PROT_READ|PROT_WRITE,
+	    	    MAP_ANON, -1, 0);
+		if (fptrs == MAP_FAILED)
+			fptrs = NULL;
+	} else {
+		fptrs = xcalloc(1, fbytes);
+	}
+
+	/*
+	 * This assertion is necessary to guarantee function pointer
+	 * uniqueness
+ 	 */
+	assert(fptrs != NULL);
+
+	return (obj->priv = fptrs);
+}
+
+static void
+free_fptrs(Obj_Entry *obj, bool mapped)
+{
+	struct fptr **fptrs;
+	size_t fbytes;
+
+	fptrs  = obj->priv;
+	if (fptrs == NULL)
+		return;
+
+	fbytes = obj->dynsymcount * sizeof(struct fptr *);
+	if (mapped)
+		munmap(fptrs, fbytes);
+	else
+		free(fptrs);
+	obj->priv = NULL;
+}
+
+/* Relocate a non-PLT object with addend. */
+static int
+reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
+    SymCache *cache, int flags, RtldLockState *lockstate)
+{
+	struct fptr **fptrs;
+	Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
+
+	switch (ELF_R_TYPE(rela->r_info)) {
+	case R_IA_64_REL64LSB:
+		/*
+		 * We handle rtld's relocations in rtld_start.S
+		 */
+		if (obj != obj_rtld)
+			store64(where,
+				load64(where) + (Elf_Addr) obj->relocbase);
+		break;
+
+	case R_IA_64_DIR64LSB: {
+		const Elf_Sym *def;
+		const Obj_Entry *defobj;
+		Elf_Addr target;
+
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL)
+			return -1;
+
+		target = (def->st_shndx != SHN_UNDEF)
+		    ? (Elf_Addr)(defobj->relocbase + def->st_value) : 0;
+		store64(where, target + rela->r_addend);
+		break;
+	}
+
+	case R_IA_64_FPTR64LSB: {
+		/*
+		 * We have to make sure that all @fptr references to
+		 * the same function are identical so that code can
+		 * compare function pointers.
+		 */
+		const Elf_Sym *def;
+		const Obj_Entry *defobj;
+		struct fptr *fptr = 0;
+		Elf_Addr target, gp;
+		int sym_index;
+
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    SYMLOOK_IN_PLT | flags, cache, lockstate);
+		if (def == NULL) {
+			/*
+			 * XXX r_debug_state is problematic and find_symdef()
+			 * returns NULL for it. This probably has something to
+			 * do with symbol versioning (r_debug_state is in the
+			 * symbol map). If we return -1 in that case we abort
+			 * relocating rtld, which typically is fatal. So, for
+			 * now just skip the symbol when we're relocating
+			 * rtld. We don't care about r_debug_state unless we
+			 * are being debugged.
+			 */
+			if (obj != obj_rtld)
+				return -1;
+			break;
+		}
+
+		if (def->st_shndx != SHN_UNDEF) {
+			target = (Elf_Addr)(defobj->relocbase + def->st_value);
+			gp = (Elf_Addr)defobj->pltgot;
+
+			/* rtld is allowed to reference itself only */
+			assert(!obj->rtld || obj == defobj);
+			fptrs = defobj->priv;
+			if (fptrs == NULL)
+				fptrs = alloc_fptrs((Obj_Entry *) defobj, 
+				    obj->rtld);
+
+			sym_index = def - defobj->symtab;
+
+			/*
+			 * Find the @fptr, using fptrs as a helper.
+			 */
+			if (fptrs)
+				fptr = fptrs[sym_index];
+			if (!fptr) {
+				fptr = alloc_fptr(target, gp);
+				if (fptrs)
+					fptrs[sym_index] = fptr;
+			}
+		} else
+			fptr = NULL;
+
+		store64(where, (Elf_Addr)fptr);
+		break;
+	}
+
+	case R_IA_64_IPLTLSB: {
+		/*
+		 * Relocation typically used to populate C++ virtual function
+		 * tables. It creates a 128-bit function descriptor at the
+		 * specified memory address.
+		 */
+		const Elf_Sym *def;
+		const Obj_Entry *defobj;
+		struct fptr *fptr;
+		Elf_Addr target, gp;
+
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL)
+			return -1;
+
+		if (def->st_shndx != SHN_UNDEF) {
+			target = (Elf_Addr)(defobj->relocbase + def->st_value);
+			gp = (Elf_Addr)defobj->pltgot;
+		} else {
+			target = 0;
+			gp = 0;
+		}
+
+		fptr = (void*)where;
+		store64(&fptr->target, target);
+		store64(&fptr->gp, gp);
+		break;
+	}
+
+	case R_IA_64_DTPMOD64LSB: {
+		const Elf_Sym *def;
+		const Obj_Entry *defobj;
+
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL)
+			return -1;
+
+		store64(where, defobj->tlsindex);
+		break;
+	}
+
+	case R_IA_64_DTPREL64LSB: {
+		const Elf_Sym *def;
+		const Obj_Entry *defobj;
+
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL)
+			return -1;
+
+		store64(where, def->st_value + rela->r_addend);
+		break;
+	}
+
+	case R_IA_64_TPREL64LSB: {
+		const Elf_Sym *def;
+		const Obj_Entry *defobj;
+
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL)
+			return -1;
+
+		/*
+		 * We lazily allocate offsets for static TLS as we
+		 * see the first relocation that references the
+		 * TLS block. This allows us to support (small
+		 * amounts of) static TLS in dynamically loaded
+		 * modules. If we run out of space, we generate an
+		 * error.
+		 */
+		if (!defobj->tls_done) {
+			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+				_rtld_error("%s: No space available for static "
+				    "Thread Local Storage", obj->path);
+				return -1;
+			}
+		}
+
+		store64(where, defobj->tlsoffset + def->st_value + rela->r_addend);
+		break;
+	}
+
+	case R_IA_64_NONE:
+		break;
+
+	default:
+		_rtld_error("%s: Unsupported relocation type %u"
+			    " in non-PLT relocations\n", obj->path,
+			    (unsigned int)ELF_R_TYPE(rela->r_info));
+		return -1;
+	}
+
+	return(0);
+}
+
+/* Process the non-PLT relocations. */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
+    RtldLockState *lockstate)
+{
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+	SymCache *cache;
+	int bytes = obj->dynsymcount * sizeof(SymCache);
+	int r = -1;
+
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
+	/*
+	 * The dynamic loader may be called from a thread, we have
+	 * limited amounts of stack available so we cannot use alloca().
+	 */
+	cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
+	if (cache == MAP_FAILED)
+		cache = NULL;
+
+	/* Perform relocations without addend if there are any: */
+	rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
+	for (rel = obj->rel;  obj->rel != NULL && rel < rellim;  rel++) {
+		Elf_Rela locrela;
+
+		locrela.r_info = rel->r_info;
+		locrela.r_offset = rel->r_offset;
+		locrela.r_addend = 0;
+		if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache, flags,
+		    lockstate))
+			goto done;
+	}
+
+	/* Perform relocations with addend if there are any: */
+	relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
+	for (rela = obj->rela;  obj->rela != NULL && rela < relalim;  rela++) {
+		if (reloc_non_plt_obj(obj_rtld, obj, rela, cache, flags,
+		    lockstate))
+			goto done;
+	}
+
+	r = 0;
+done:
+	if (cache)
+		munmap(cache, bytes);
+
+	/*
+	 * Release temporarily mapped fptrs if relocating
+	 * rtld object itself. A new table will be created
+	 * in make_function_pointer using malloc when needed.
+	 */
+	if (obj->rtld && obj->priv)
+		free_fptrs(obj, true);
+
+	return (r);
+}
+
+/* Process the PLT relocations. */
+int
+reloc_plt(Obj_Entry *obj)
+{
+	/* All PLT relocations are the same kind: Elf_Rel or Elf_Rela. */
+	if (obj->pltrelsize != 0) {
+		const Elf_Rel *rellim;
+		const Elf_Rel *rel;
+
+		rellim = (const Elf_Rel *)
+			((char *)obj->pltrel + obj->pltrelsize);
+		for (rel = obj->pltrel;  rel < rellim;  rel++) {
+			Elf_Addr *where;
+
+			assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB);
+
+			/* Relocate the @fptr pointing into the PLT. */
+			where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+			*where += (Elf_Addr)obj->relocbase;
+		}
+	} else {
+		const Elf_Rela *relalim;
+		const Elf_Rela *rela;
+
+		relalim = (const Elf_Rela *)
+			((char *)obj->pltrela + obj->pltrelasize);
+		for (rela = obj->pltrela;  rela < relalim;  rela++) {
+			Elf_Addr *where;
+
+			assert(ELF_R_TYPE(rela->r_info) == R_IA_64_IPLTLSB);
+
+			/* Relocate the @fptr pointing into the PLT. */
+			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+			*where += (Elf_Addr)obj->relocbase;
+		}
+	}
+	return 0;
+}
+
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, int flags,
+    struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+/* Relocate the jump slots in an object. */
+int
+reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
+{
+	if (obj->jmpslots_done)
+		return 0;
+	/* All PLT relocations are the same kind: Elf_Rel or Elf_Rela. */
+	if (obj->pltrelsize != 0) {
+		const Elf_Rel *rellim;
+		const Elf_Rel *rel;
+
+		rellim = (const Elf_Rel *)
+			((char *)obj->pltrel + obj->pltrelsize);
+		for (rel = obj->pltrel;  rel < rellim;  rel++) {
+			Elf_Addr *where;
+			const Elf_Sym *def;
+			const Obj_Entry *defobj;
+
+			assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB);
+			where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+			def = find_symdef(ELF_R_SYM(rel->r_info), obj,
+			    &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate);
+			if (def == NULL)
+				return -1;
+			reloc_jmpslot(where,
+				      (Elf_Addr)(defobj->relocbase
+						 + def->st_value),
+				      defobj, obj, rel);
+		}
+	} else {
+		const Elf_Rela *relalim;
+		const Elf_Rela *rela;
+
+		relalim = (const Elf_Rela *)
+			((char *)obj->pltrela + obj->pltrelasize);
+		for (rela = obj->pltrela;  rela < relalim;  rela++) {
+			Elf_Addr *where;
+			const Elf_Sym *def;
+			const Obj_Entry *defobj;
+
+			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
+			    &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate);
+			if (def == NULL)
+				return -1;
+			reloc_jmpslot(where,
+				      (Elf_Addr)(defobj->relocbase
+						 + def->st_value),
+				      defobj, obj, (Elf_Rel *)rela);
+		}
+	}
+	obj->jmpslots_done = true;
+	return 0;
+}
+
+/* Fixup the jump slot at "where" to transfer control to "target". */
+Elf_Addr
+reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *obj,
+	      const Obj_Entry *refobj, const Elf_Rel *rel)
+{
+	Elf_Addr stubaddr;
+
+	dbg(" reloc_jmpslot: where=%p, target=%p, gp=%p",
+	    (void *)where, (void *)target, (void *)obj->pltgot);
+	stubaddr = *where;
+	if (stubaddr != target) {
+
+		/*
+		 * Point this @fptr directly at the target. Update the
+		 * gp value first so that we don't break another cpu
+		 * which is currently executing the PLT entry.
+		 */
+		where[1] = (Elf_Addr) obj->pltgot;
+		ia64_mf();
+		where[0] = target;
+		ia64_mf();
+	}
+
+	/*
+	 * The caller needs an @fptr for the adjusted entry. The PLT
+	 * entry serves this purpose nicely.
+	 */
+	return (Elf_Addr) where;
+}
+
+/*
+ * XXX ia64 doesn't seem to have copy relocations.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+
+	return 0;
+}
+
+/*
+ * Return the @fptr representing a given function symbol.
+ */
+void *
+make_function_pointer(const Elf_Sym *sym, const Obj_Entry *obj)
+{
+	struct fptr **fptrs = obj->priv;
+	int index = sym - obj->symtab;
+
+	if (!fptrs) {
+		/*
+		 * This should only happen for something like
+		 * dlsym("dlopen"). Actually, I'm not sure it can ever 
+		 * happen.
+		 */
+		fptrs = alloc_fptrs((Obj_Entry *) obj, false);
+	}
+	if (!fptrs[index]) {
+		Elf_Addr target, gp;
+		target = (Elf_Addr) (obj->relocbase + sym->st_value);
+		gp = (Elf_Addr) obj->pltgot;
+		fptrs[index] = alloc_fptr(target, gp);
+	}
+	return fptrs[index];
+}
+
+void
+call_initfini_pointer(const Obj_Entry *obj, Elf_Addr target)
+{
+	struct fptr fptr;
+
+	fptr.gp = (Elf_Addr) obj->pltgot;
+	fptr.target = target;
+	dbg(" initfini: target=%p, gp=%p",
+	    (void *) fptr.target, (void *) fptr.gp);
+	((InitFunc) &fptr)();
+}
+
+void
+call_init_pointer(const Obj_Entry *obj, Elf_Addr target)
+{
+	struct fptr fptr;
+
+	fptr.gp = (Elf_Addr) obj->pltgot;
+	fptr.target = target;
+	dbg(" initfini: target=%p, gp=%p",
+	    (void *) fptr.target, (void *) fptr.gp);
+	((InitArrFunc) &fptr)(main_argc, main_argv, environ);
+}
+
+void  
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+
+}
+
+void
+pre_init(void)
+{
+
+}
+
+/* Initialize the special PLT entries. */
+void
+init_pltgot(Obj_Entry *obj)
+{
+	const Elf_Dyn *dynp;
+	Elf_Addr *pltres = 0;
+
+	/*
+	 * When there are no PLT relocations, the DT_IA_64_PLT_RESERVE entry
+	 * is bogus. Do not setup the BOR pointers in that case. An example
+	 * of where this happens is /usr/lib/libxpg4.so.3.
+	 */
+	if (obj->pltrelasize == 0 && obj->pltrelsize == 0)
+		return;
+
+	/*
+	 * Find the PLT RESERVE section.
+	 */
+	for (dynp = obj->dynamic;  dynp->d_tag != DT_NULL;  dynp++) {
+		if (dynp->d_tag == DT_IA_64_PLT_RESERVE)
+			pltres = (u_int64_t *)
+				(obj->relocbase + dynp->d_un.d_ptr);
+	}
+	if (!pltres)
+		errx(1, "Can't find DT_IA_64_PLT_RESERVE entry");
+
+	/*
+	 * The PLT RESERVE section is used to get values to pass to
+	 * _rtld_bind when lazy binding.
+	 */
+	pltres[0] = (Elf_Addr) obj;
+	pltres[1] = FPTR_TARGET(_rtld_bind_start);
+	pltres[2] = FPTR_GP(_rtld_bind_start);
+}
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+    void *tpval;
+
+    /*
+     * Fix the size of the static TLS block by using the maximum
+     * offset allocated so far and adding a bit for dynamic modules to
+     * use.
+     */
+    tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
+
+    tpval = allocate_tls(list, NULL, TLS_TCB_SIZE, 16);
+    __asm __volatile("mov r13 = %0" :: "r"(tpval));
+}
+
+void *__tls_get_addr(unsigned long module, unsigned long offset)
+{
+    register Elf_Addr** tp __asm__("r13");
+
+    return tls_get_addr_common(tp, module, offset);
+}


Property changes on: trunk/libexec/rtld-elf/ia64/reloc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/ia64/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/ia64/rtld_machdep.h	                        (rev 0)
+++ trunk/libexec/rtld-elf/ia64/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,78 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999, 2000 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/ia64/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
+ */
+
+#ifndef RTLD_MACHDEP_H
+#define RTLD_MACHDEP_H	1
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+
+/*
+ * Macros for cracking ia64 function pointers.
+ */
+struct fptr {
+	Elf_Addr	target;
+	Elf_Addr	gp;
+};
+
+#define FPTR_TARGET(f)	(((struct fptr *) (f))->target)
+#define FPTR_GP(f)	(((struct fptr *) (f))->gp)
+
+/* Return the address of the .dynamic section in the dynamic linker. */
+#define rtld_dynamic(obj)	(&_DYNAMIC)
+
+struct Struct_Obj_Entry;
+
+Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr, const struct Struct_Obj_Entry *,
+		       const struct Struct_Obj_Entry *, const Elf_Rel *);
+void *make_function_pointer(const Elf_Sym *, const struct Struct_Obj_Entry *);
+void call_initfini_pointer(const struct Struct_Obj_Entry *, Elf_Addr);
+void call_init_pointer(const struct Struct_Obj_Entry *, Elf_Addr);
+
+#define        call_ifunc_resolver(ptr) \
+       (((Elf_Addr (*)(void))ptr)())
+
+#define	TLS_TCB_SIZE	16
+
+#define round(size, align) \
+	(((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+	round(TLS_TCB_SIZE, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+	round(prev_offset + prev_size, align)
+#define calculate_tls_end(off, size) 	((off) + (size))
+
+extern void *__tls_get_addr(unsigned long module, unsigned long offset);
+
+#define	RTLD_DEFAULT_STACK_PF_EXEC	0
+#define	RTLD_DEFAULT_STACK_EXEC		0
+
+#define	RTLD_INIT_PAGESIZES_EARLY	1
+
+#endif


Property changes on: trunk/libexec/rtld-elf/ia64/rtld_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/ia64/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/ia64/rtld_start.S	                        (rev 0)
+++ trunk/libexec/rtld-elf/ia64/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,253 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/libexec/rtld-elf/ia64/rtld_start.S 154957 2006-01-28 17:56:16Z marcel $	*/
+/*	From: NetBSD: rtld_start.S,v 1.1 1996/12/16 20:38:09 cgd Exp 	*/
+
+/*
+ * Copyright 1996 Matt Thomas <matt at 3am-software.com>
+ * Copyright 2000 John D. Polstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <sys/syscall.h>
+
+ENTRY(_rtld_start, 0)
+	alloc	r2=ar.pfs,3,0,3,0
+	;;
+1:	mov	r14=ip			// calculate gp
+	addl	r3=@gprel(1b),r0
+	;;
+	sub	gp=r14,r3
+	;;
+	.section .sdata
+2:	data4	@ltv(1b)		// unrelocated address of 1b
+	.align	8
+	.previous
+	add	r15=@gprel(2b),gp
+	;;
+	ld8	r15=[r15]
+	;;
+	sub	out0=r14,r15		// out0 is image base address
+	br.call.sptk.many rp=_rtld_reloc // fixup image
+
+	add	sp=-16,sp		// 16 bytes for us, 16 for _rtld
+	;;
+	mov	out0=in0
+	add	out1=16,sp		// address for exit proc
+	add	out2=24,sp		// address for obj_main
+
+	br.call.sptk.many rp=_rtld	// r8=_rtld(sp, &exit_proc, &obj_main)
+
+	add	r16=16,sp		// address for exit proc
+	;;
+	ld8	r15=[r16]		// read exit proc
+	add	sp=16,sp		// readjust stack
+	mov	b7=r8			// address of real _start
+	;;
+	alloc	r2=ar.pfs,0,0,3,0	// dump register frame
+	mov	out2=r15
+	;;
+	br.call.sptk.many rp=b7		// transfer to main program
+	br.call.sptk.many rp=exit	// die
+END(_rtld_start)
+
+/*
+ * _rtld_bind_start:	lookup a lazy binding and transfer to real target
+ *
+ * Arguments:
+ *	r1	gp value for rtld
+ *	r15	Index in plt
+ *	r16	Obj_Entry of caller
+ *	in0-in7	Arguments for target procedure
+ *	rp	Return address back to caller
+ */
+ENTRY(_rtld_bind_start, 0)
+{ .mii
+	alloc	loc0=ar.pfs,8,6,3,0	// space to save r8-r11
+	add	r17=16-8*16,sp		// leave 16 bytes for _rtld_bind
+	add	r18=32-8*16,sp
+	;;
+} { .mii
+	mov	loc2=r8			// structure return address
+	add	sp=-8*16,sp		// space to save f8-f15
+	mov	loc1=rp
+	;;
+} { .mii
+	stf.spill [r17]=f8,32		// save float arguments
+	mov	loc3=r9			// language specific
+	mov	loc4=r10		// language specific
+} { .mii
+	stf.spill [r18]=f9,32
+	mov	loc5=r11		// language specific
+	shl	out1=r15,4		// 16 * index
+	;;
+} { .mmi
+	stf.spill [r17]=f10,32
+	stf.spill [r18]=f11,32
+	mov	out0=r16		// Obj_Entry for caller
+	;;
+} { .mmi
+	stf.spill [r17]=f12,32
+	stf.spill [r18]=f13,32
+	shladd	out1=r15,3,out1		// rela offset = 24 * index
+	;;
+} { .mmb
+	stf.spill [r17]=f14,32
+	stf.spill [r18]=f15,32
+	br.call.sptk.many rp=_rtld_bind
+} { .mii
+	ld8	r14=[r8],8		// target address
+	add	r17=16,sp
+	add	r18=32,sp
+	;;
+} { .mii
+	ld8	r1=[r8]			// target gp
+	mov	ar.pfs=loc0		// clean up
+	mov	rp=loc1
+} { .mmi
+	ldf.fill f8=[r17],32		// restore float arguments
+	ldf.fill f9=[r18],32
+	mov	r8=loc2			// restore structure pointer
+	;;
+} { .mmi
+	ldf.fill f10=[r17],32
+	ldf.fill f11=[r18],32
+	mov	r9=loc3
+	;;
+} { .mmi
+	ldf.fill f12=[r17],32
+	ldf.fill f13=[r18],32
+	mov	r10=loc4
+	;;
+} { .mmi
+	ldf.fill f14=[r17],32
+	ldf.fill f15=[r18],32
+	mov	r11=loc5
+	;;
+} { .mii
+	nop.m	0
+	mov	b7=r14
+	add	sp=8*16,sp
+	;;
+} { .mib
+	alloc	r14=ar.pfs,0,0,8,0	// drop our register frame
+	nop.i	0
+	br.sptk.many b7			// jump to target
+}
+END(_rtld_bind_start)
+
+#define DT_NULL		0	/* Terminating entry. */
+#define DT_RELA		7	/* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ	8	/* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT	9	/* Size of each ElfNN_Rela relocation entry. */
+
+#define R_IA_64_NONE		0	/* None */
+#define R_IA_64_DIR64LSB	0x27	/* word64 LSB	S + A */
+#define R_IA_64_REL64LSB	0x6f	/* word64 LSB	BD + A */
+
+/*
+ * _rtld_reloc:	relocate the rtld image, apart from @fptrs.
+ *
+ * Assumes that rtld was linked at zero and that we only need to
+ * handle REL64LSB and DIR64LSB relocations.
+ *
+ * Arguments:
+ *	r1	gp value for rtld
+ *	in0	rtld base address
+ */
+STATIC_ENTRY(_rtld_reloc, 1)
+	alloc	loc0=ar.pfs,1,2,0,0
+	mov	loc1=rp
+	;;
+	movl	r15=@gprel(_DYNAMIC)	// find _DYNAMIC etc.
+	;;
+	add	r15=r15,gp		// relocate _DYNAMIC etc.
+	;;
+1:	ld8	r16=[r15],8		// read r15->d_tag
+	;;
+	ld8	r17=[r15],8		// and r15->d_val
+	;;
+	cmp.eq	p6,p0=DT_NULL,r16	// done?
+(p6)	br.cond.dpnt.few 2f
+	;;
+	cmp.eq	p6,p0=DT_RELA,r16
+	;;
+(p6)	add	r18=r17,in0		// found rela section
+	;;
+	cmp.eq	p6,p0=DT_RELASZ,r16
+	;;
+(p6)	mov	r19=r17			// found rela size
+	;;
+	cmp.eq	p6,p0=DT_RELAENT,r16
+	;;
+(p6)	mov	r22=r17			// found rela entry size
+	;;
+	br.sptk.few 1b
+
+2:
+	ld8	r15=[r18],8		// read r_offset
+	;;
+	ld8	r16=[r18],8		// read r_info
+	add	r15=r15,in0		// relocate r_offset
+	;;
+	ld8	r17=[r18],8		// read r_addend
+	sub	r19=r19,r22		// update relasz
+
+	extr.u	r23=r16,0,32		// ELF64_R_TYPE(r16)
+	;;
+	cmp.eq	p6,p0=R_IA_64_NONE,r23
+(p6)	br.cond.dpnt.few 3f
+	;;
+	cmp.eq	p6,p0=R_IA_64_DIR64LSB,r23
+	;;
+(p6)	br.cond.dptk.few 4f
+	;;
+	cmp.eq	p6,p0=R_IA_64_REL64LSB,r23
+	;;
+(p6)	br.cond.dptk.few 4f
+	;;
+
+3:	cmp.ltu	p6,p0=0,r19		// more?
+(p6)	br.cond.dptk.few 2b		// loop
+
+	mov	r8=0			// success return value
+	;;
+	br.cond.sptk.few 9f		// done
+
+4:
+	ld8	r16=[r15]		// read value
+	;;
+	add	r16=r16,in0		// relocate it
+	;;
+	st8	[r15]=r16		// and store it back
+	br.cond.sptk.few 3b
+
+9:
+	mov	ar.pfs=loc0
+	mov	rp=loc1
+	;;
+	br.ret.sptk.few rp
+
+END(_rtld_reloc)


Property changes on: trunk/libexec/rtld-elf/ia64/rtld_start.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/libmap.c
===================================================================
--- trunk/libexec/rtld-elf/libmap.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/libmap.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,5 +1,6 @@
+/* $MidnightBSD$ */
 /*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/libmap.c 270756 2014-08-28 18:11:05Z pfg $
  */
 
 #include <sys/types.h>
@@ -80,7 +81,7 @@
 
 	if (libmap_override) {
 		/*
-		 * Do some character replacement to make $LIBMAP look
+		 * Do some character replacement to make $LDLIBMAP look
 		 * like a text file, then parse it.
 		 */
 		libmap_override = xstrdup(libmap_override);
@@ -94,8 +95,8 @@
 				break;
 			}
 		}
-		lmc_parse(p, strlen(p));
-		free(p);
+		lmc_parse(libmap_override, p - libmap_override);
+		free(libmap_override);
 	}
 
 	return (lm_count == 0);
@@ -121,7 +122,7 @@
 		}
 	}
 
-	fd = open(rpath, O_RDONLY);
+	fd = open(rpath, O_RDONLY | O_CLOEXEC);
 	if (fd == -1) {
 		dbg("lm_parse_file: open(\"%s\") failed, %s", rpath,
 		    rtld_strerror(errno));
@@ -216,7 +217,7 @@
 	p = NULL;
 	while (cnt < lm_len) {
 		i = 0;
-		while (lm_p[cnt] != '\n' && cnt < lm_len &&
+		while (cnt < lm_len && lm_p[cnt] != '\n' &&
 		    i < sizeof(line) - 1) {
 			line[i] = lm_p[cnt];
 			cnt++;
@@ -223,7 +224,7 @@
 			i++;
 		}
 		line[i] = '\0';
-		while (lm_p[cnt] != '\n' && cnt < lm_len)
+		while (cnt < lm_len && lm_p[cnt] != '\n')
 			cnt++;
 		/* skip over nl */
 		cnt++;
@@ -396,7 +397,6 @@
 
 /* Given a libmap translation list and a library name, return the
    replacement library, or NULL */
-#ifdef COMPAT_32BIT
 char *
 lm_findn (const char *p, const char *f, const int n)
 {
@@ -413,7 +413,6 @@
 		free(s);
 	return (t);
 }
-#endif
 
 static char *
 lml_find (struct lm_list *lmh, const char *f)

Modified: trunk/libexec/rtld-elf/libmap.h
===================================================================
--- trunk/libexec/rtld-elf/libmap.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/libmap.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,10 +1,9 @@
+/* $MidnightBSD$ */
 /*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/libmap.h 255765 2013-09-21 21:03:52Z des $
  */
 
 int	lm_init (char *);
 void	lm_fini (void);
 char *	lm_find (const char *, const char *);
-#ifdef COMPAT_32BIT
 char *	lm_findn (const char *, const char *, const int);
-#endif

Modified: trunk/libexec/rtld-elf/malloc.c
===================================================================
--- trunk/libexec/rtld-elf/malloc.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/malloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 1983 Regents of the University of California.
  * All rights reserved.
@@ -10,11 +11,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +30,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)malloc.c	5.11 (Berkeley) 2/23/91";*/
-static char *rcsid = "$MidnightBSD$";
+static char *rcsid = "$FreeBSD: stable/10/libexec/rtld-elf/malloc.c 281452 2015-04-12 06:43:13Z kib $";
 #endif /* LIBC_SCCS and not lint */
 
 /*
@@ -143,26 +140,15 @@
 /* Debugging stuff */
 #define TRACE()	rtld_printf("TRACE %s:%d\n", __FILE__, __LINE__)
 
-extern int pagesize;
+/*
+ * The array of supported page sizes is provided by the user, i.e., the
+ * program that calls this storage allocator.  That program must initialize
+ * the array before making its first call to allocate storage.  The array
+ * must contain at least one page size.  The page sizes must be stored in
+ * increasing order.
+ */
+extern size_t *pagesizes;
 
-static int
-rtld_getpagesize(void)
-{
-	int mib[2];
-	size_t size;
-
-	if (pagesize != 0)
-		return (pagesize);
-
-	mib[0] = CTL_HW;
-	mib[1] = HW_PAGESIZE;
-	size = sizeof(pagesize);
-	if (sysctl(mib, 2, &pagesize, &size, NULL, 0) == -1)
-		return (-1);
-	return (pagesize);
-
-}
-
 void *
 malloc(nbytes)
 	size_t nbytes;
@@ -177,7 +163,7 @@
 	 * align break pointer so all data will be page aligned.
 	 */
 	if (pagesz == 0) {
-		pagesz = n = rtld_getpagesize();
+		pagesz = n = pagesizes[0];
 		if (morepages(NPOOLPAGES) == 0)
 			return NULL;
 		op = (union overhead *)(pagepool_start);

Modified: trunk/libexec/rtld-elf/map_object.c
===================================================================
--- trunk/libexec/rtld-elf/map_object.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/map_object.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996-1998 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/map_object.c 296939 2016-03-16 15:34:16Z kib $
  */
 
 #include <sys/param.h>
@@ -39,7 +40,6 @@
 #include "rtld.h"
 
 static Elf_Ehdr *get_elf_header(int, const char *);
-static int convert_prot(int);	/* Elf flags -> mmap protection */
 static int convert_flags(int); /* Elf flags -> mmap flags */
 
 /*
@@ -68,6 +68,7 @@
     Elf_Addr base_vaddr;
     Elf_Addr base_vlimit;
     caddr_t base_addr;
+    int base_flags;
     Elf_Off data_offset;
     Elf_Addr data_vaddr;
     Elf_Addr data_vlimit;
@@ -87,6 +88,8 @@
     size_t relro_size;
     Elf_Addr note_start;
     Elf_Addr note_end;
+    char *note_map;
+    size_t note_map_len;
 
     hdr = get_elf_header(fd, path);
     if (hdr == NULL)
@@ -107,6 +110,7 @@
     relro_size = 0;
     note_start = 0;
     note_end = 0;
+    note_map = NULL;
     segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
     stack_flags = RTLD_DEFAULT_STACK_PF_EXEC | PF_R | PF_W;
     while (phdr < phlimit) {
@@ -149,9 +153,20 @@
 
 	case PT_NOTE:
 	    if (phdr->p_offset > PAGE_SIZE ||
-	      phdr->p_offset + phdr->p_filesz > PAGE_SIZE)
-		break;
-	    note_start = (Elf_Addr)(char *)hdr + phdr->p_offset;
+	      phdr->p_offset + phdr->p_filesz > PAGE_SIZE) {
+		note_map_len = round_page(phdr->p_offset +
+		  phdr->p_filesz) - trunc_page(phdr->p_offset);
+		note_map = mmap(NULL, note_map_len, PROT_READ,
+		  MAP_PRIVATE, fd, trunc_page(phdr->p_offset));
+		if (note_map == MAP_FAILED) {
+		    _rtld_error("%s: error mapping PT_NOTE (%d)", path, errno);
+		    goto error;
+		}
+		note_start = (Elf_Addr)(note_map + phdr->p_offset -
+		  trunc_page(phdr->p_offset));
+	    } else {
+		note_start = (Elf_Addr)(char *)hdr + phdr->p_offset;
+	    }
 	    note_end = note_start + phdr->p_filesz;
 	    break;
 	}
@@ -176,9 +191,11 @@
     base_vlimit = round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz);
     mapsize = base_vlimit - base_vaddr;
     base_addr = (caddr_t) base_vaddr;
+    base_flags = MAP_PRIVATE | MAP_ANON | MAP_NOCORE;
+    if (npagesizes > 1 && round_page(segs[0]->p_filesz) >= pagesizes[1])
+	base_flags |= MAP_ALIGNED_SUPER;
 
-    mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE |
-      MAP_NOCORE, -1, 0);
+    mapbase = mmap(base_addr, mapsize, PROT_NONE, base_flags, -1, 0);
     if (mapbase == (caddr_t) -1) {
 	_rtld_error("%s: mmap of entire address space failed: %s",
 	  path, rtld_strerror(errno));
@@ -292,6 +309,8 @@
     obj->relro_size = round_page(relro_size);
     if (note_start < note_end)
 	digest_notes(obj, note_start, note_end);
+    if (note_map != NULL)
+	munmap(note_map, note_map_len);
     munmap(hdr, PAGE_SIZE);
     return (obj);
 
@@ -298,6 +317,8 @@
 error1:
     munmap(mapbase, mapsize);
 error:
+    if (note_map != NULL && note_map != MAP_FAILED)
+	munmap(note_map, note_map_len);
     munmap(hdr, PAGE_SIZE);
     return (NULL);
 }
@@ -418,7 +439,7 @@
  * Given a set of ELF protection flags, return the corresponding protection
  * flags for MMAP.
  */
-static int
+int
 convert_prot(int elfflags)
 {
     int prot = 0;

Added: trunk/libexec/rtld-elf/mips/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/mips/reloc.c	                        (rev 0)
+++ trunk/libexec/rtld-elf/mips/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,661 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: mips_reloc.c,v 1.58 2010/01/14 11:57:06 skrll Exp $	*/
+
+/*
+ * Copyright 1997 Michael L. Hitch <mhitch at montana.edu>
+ * Portions copyright 2002 Charles M. Hannum <root at ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/libexec/rtld-elf/mips/reloc.c 331206 2018-03-19 14:28:58Z marius $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/endian.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <machine/sysarch.h>
+#include <machine/tls.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+#ifdef __mips_n64
+#define	GOT1_MASK	0x8000000000000000UL
+#else
+#define	GOT1_MASK	0x80000000UL
+#endif
+
+void
+init_pltgot(Obj_Entry *obj)
+{
+	if (obj->pltgot != NULL) {
+		obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start;
+		if (obj->pltgot[1] & 0x80000000)
+			obj->pltgot[1] = (Elf_Addr) obj | GOT1_MASK;
+	}
+}
+
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+	/* Do nothing */
+	return 0;
+}
+
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#ifdef __mips_n64
+/*
+ * ELF64 MIPS encodes the relocs uniquely.  The first 32-bits of info contain
+ * the symbol index.  The top 32-bits contain three relocation types encoded
+ * in big-endian integer with first relocation in LSB.  This means for little
+ * endian we have to byte swap that integer (r_type).
+ */
+#define	Elf_Sxword			Elf64_Sxword
+#define	ELF_R_NXTTYPE_64_P(r_type)	((((r_type) >> 8) & 0xff) == R_TYPE(64))
+#if BYTE_ORDER == LITTLE_ENDIAN
+#undef ELF_R_SYM
+#undef ELF_R_TYPE
+#define ELF_R_SYM(r_info)		((r_info) & 0xffffffff)
+#define ELF_R_TYPE(r_info)		bswap32((r_info) >> 32)
+#endif
+#else
+#define	ELF_R_NXTTYPE_64_P(r_type)	(0)
+#define	Elf_Sxword			Elf32_Sword
+#endif
+
+static __inline Elf_Sxword
+load_ptr(void *where, size_t len)
+{
+	Elf_Sxword val;
+
+	if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) {
+#ifdef __mips_n64
+		if (len == sizeof(Elf_Sxword))
+			return *(Elf_Sxword *)where;
+#endif
+		return *(Elf_Sword *)where;
+	}
+
+	val = 0;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	(void)memcpy(&val, where, len);
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	(void)memcpy((uint8_t *)((&val)+1) - len, where, len);
+#endif
+	return (len == sizeof(Elf_Sxword)) ? val : (Elf_Sword)val;
+}
+
+static __inline void
+store_ptr(void *where, Elf_Sxword val, size_t len)
+{
+	if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) {
+#ifdef __mips_n64
+		if (len == sizeof(Elf_Sxword)) {
+			*(Elf_Sxword *)where = val;
+			return;
+		}
+#endif
+		*(Elf_Sword *)where = val;
+		return;
+	}
+#if BYTE_ORDER == LITTLE_ENDIAN
+	(void)memcpy(where, &val, len);
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	(void)memcpy(where, (const uint8_t *)((&val)+1) - len, len);
+#endif
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+	const Elf_Rel *rel = 0, *rellim;
+	Elf_Addr relsz = 0;
+	const Elf_Sym *symtab = NULL, *sym;
+	Elf_Addr *where;
+	Elf_Addr *got = NULL;
+	Elf_Word local_gotno = 0, symtabno = 0, gotsym = 0;
+	size_t i;
+
+	for (; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_REL:
+			rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
+			break;
+		case DT_RELSZ:
+			relsz = dynp->d_un.d_val;
+			break;
+		case DT_SYMTAB:
+			symtab = (const Elf_Sym *)(relocbase + dynp->d_un.d_ptr);
+			break;
+		case DT_PLTGOT:
+			got = (Elf_Addr *)(relocbase + dynp->d_un.d_ptr);
+			break;
+		case DT_MIPS_LOCAL_GOTNO:
+			local_gotno = dynp->d_un.d_val;
+			break;
+		case DT_MIPS_SYMTABNO:
+			symtabno = dynp->d_un.d_val;
+			break;
+		case DT_MIPS_GOTSYM:
+			gotsym = dynp->d_un.d_val;
+			break;
+		}
+	}
+
+	i = (got[1] & GOT1_MASK) ? 2 : 1;
+	/* Relocate the local GOT entries */
+	got += i;
+	for (; i < local_gotno; i++) {
+		*got++ += relocbase;
+	}
+
+	sym = symtab + gotsym;
+	/* Now do the global GOT entries */
+	for (i = gotsym; i < symtabno; i++) {
+		*got = sym->st_value + relocbase;
+		++sym;
+		++got;
+	}
+
+	rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
+	for (; rel < rellim; rel++) {
+		Elf_Word r_symndx, r_type;
+
+		where = (void *)(relocbase + rel->r_offset);
+
+		r_symndx = ELF_R_SYM(rel->r_info);
+		r_type = ELF_R_TYPE(rel->r_info);
+
+		switch (r_type & 0xff) {
+		case R_TYPE(REL32): {
+			const size_t rlen =
+			    ELF_R_NXTTYPE_64_P(r_type)
+				? sizeof(Elf_Sxword)
+				: sizeof(Elf_Sword);
+			Elf_Sxword old = load_ptr(where, rlen);
+			Elf_Sxword val = old;
+#ifdef __mips_n64
+			assert(r_type == R_TYPE(REL32)
+			    || r_type == (R_TYPE(REL32)|(R_TYPE(64) << 8)));
+#endif
+			assert(r_symndx < gotsym);
+			sym = symtab + r_symndx;
+			assert(ELF_ST_BIND(sym->st_info) == STB_LOCAL);
+			val += relocbase;
+			store_ptr(where, val, sizeof(Elf_Sword));
+			dbg("REL32/L(%p) %p -> %p in <self>",
+			    where, (void *)old, (void *)val);
+			store_ptr(where, val, rlen);
+			break;
+		}
+
+		case R_TYPE(GPREL32):
+		case R_TYPE(NONE):
+			break;
+
+
+		default:
+			abort();
+			break;
+		}
+	}
+}
+
+Elf_Addr
+_mips_rtld_bind(Obj_Entry *obj, Elf_Size reloff)
+{
+        Elf_Addr *got = obj->pltgot;
+        const Elf_Sym *def;
+        const Obj_Entry *defobj;
+        Elf_Addr target;
+
+        def = find_symdef(reloff, obj, &defobj, SYMLOOK_IN_PLT, NULL,
+	    NULL);
+        if (def == NULL)
+		rtld_die();
+
+        target = (Elf_Addr)(defobj->relocbase + def->st_value);
+        dbg("bind now/fixup at %s sym # %jd in %s --> was=%p new=%p",
+	    obj->path,
+	    (intmax_t)reloff, defobj->strtab + def->st_name, 
+	    (void *)got[obj->local_gotno + reloff - obj->gotsym],
+	    (void *)target);
+        got[obj->local_gotno + reloff - obj->gotsym] = target;
+	return (Elf_Addr)target;
+}
+
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
+    RtldLockState *lockstate)
+{
+	const Elf_Rel *rel;
+	const Elf_Rel *rellim;
+	Elf_Addr *got = obj->pltgot;
+	const Elf_Sym *sym, *def;
+	const Obj_Entry *defobj;
+	Elf_Word i;
+#ifdef SUPPORT_OLD_BROKEN_LD
+	int broken;
+#endif
+
+	/* The relocation for the dynamic loader has already been done. */
+	if (obj == obj_rtld)
+		return (0);
+
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
+#ifdef SUPPORT_OLD_BROKEN_LD
+	broken = 0;
+	sym = obj->symtab;
+	for (i = 1; i < 12; i++)
+		if (sym[i].st_info == ELF_ST_INFO(STB_LOCAL, STT_NOTYPE))
+			broken = 1;
+	dbg("%s: broken=%d", obj->path, broken);
+#endif
+
+	i = (got[1] & GOT1_MASK) ? 2 : 1;
+
+	/* Relocate the local GOT entries */
+	got += i;
+	dbg("got:%p for %d entries adding %p",
+	    got, obj->local_gotno, obj->relocbase);
+	for (; i < obj->local_gotno; i++) {
+		*got += (Elf_Addr)obj->relocbase;
+		got++;
+	}
+	sym = obj->symtab + obj->gotsym;
+
+	dbg("got:%p for %d entries",
+	    got, obj->symtabno);
+	/* Now do the global GOT entries */
+	for (i = obj->gotsym; i < obj->symtabno; i++) {
+		dbg(" doing got %d sym %p (%s, %lx)", i - obj->gotsym, sym,
+		    sym->st_name + obj->strtab, (u_long) *got);
+
+#ifdef SUPPORT_OLD_BROKEN_LD
+		if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+		    broken && sym->st_shndx == SHN_UNDEF) {
+			/*
+			 * XXX DANGER WILL ROBINSON!
+			 * You might think this is stupid, as it intentionally
+			 * defeats lazy binding -- and you'd be right.
+			 * Unfortunately, for lazy binding to work right, we
+			 * need to a way to force the GOT slots used for
+			 * function pointers to be resolved immediately.  This
+			 * is supposed to be done automatically by the linker,
+			 * by not outputting a PLT slot and setting st_value
+			 * to 0 if there are non-PLT references, but older
+			 * versions of GNU ld do not do this.
+			 */
+			def = find_symdef(i, obj, &defobj, flags, NULL,
+			    lockstate);
+			if (def == NULL)
+				return -1;
+			*got = def->st_value + (Elf_Addr)defobj->relocbase;
+		} else
+#endif
+		if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+		    sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) {
+			/*
+			 * If there are non-PLT references to the function,
+			 * st_value should be 0, forcing us to resolve the
+			 * address immediately.
+			 *
+			 * XXX DANGER WILL ROBINSON!
+			 * The linker is not outputting PLT slots for calls to
+			 * functions that are defined in the same shared
+			 * library.  This is a bug, because it can screw up
+			 * link ordering rules if the symbol is defined in
+			 * more than one module.  For now, if there is a
+			 * definition, we fail the test above and force a full
+			 * symbol lookup.  This means that all intra-module
+			 * calls are bound immediately.  - mycroft, 2003/09/24
+			 */
+			*got = sym->st_value + (Elf_Addr)obj->relocbase;
+			if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) {
+				dbg("Warning2, i:%d maps to relocbase address:%p",
+				    i, obj->relocbase);
+			}
+
+		} else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) {
+			/* Symbols with index SHN_ABS are not relocated. */
+			if (sym->st_shndx != SHN_ABS) {
+				*got = sym->st_value +
+				    (Elf_Addr)obj->relocbase;
+				if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) {
+					dbg("Warning3, i:%d maps to relocbase address:%p",
+					    i, obj->relocbase);
+				}
+			}
+		} else {
+			/* TODO: add cache here */
+			def = find_symdef(i, obj, &defobj, flags, NULL,
+			    lockstate);
+			if (def == NULL) {
+				dbg("Warning4, can't find symbole %d", i);
+				return -1;
+			}
+			*got = def->st_value + (Elf_Addr)defobj->relocbase;
+			if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) {
+				dbg("Warning4, i:%d maps to relocbase address:%p",
+				    i, obj->relocbase);
+				dbg("via first obj symbol %s",
+				    obj->strtab + obj->symtab[i].st_name);
+				dbg("found in obj %p:%s",
+				    defobj, defobj->path);
+			}
+		}
+
+		dbg("  --> now %lx", (u_long) *got);
+		++sym;
+		++got;
+	}
+
+	got = obj->pltgot;
+	rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
+	for (rel = obj->rel; rel < rellim; rel++) {
+		Elf_Word	r_symndx, r_type;
+		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) {
+		case R_TYPE(NONE):
+			break;
+
+		case R_TYPE(REL32): {
+			/* 32-bit PC-relative reference */
+			const size_t rlen =
+			    ELF_R_NXTTYPE_64_P(r_type)
+				? sizeof(Elf_Sxword)
+				: sizeof(Elf_Sword);
+			Elf_Sxword old = load_ptr(where, rlen);
+			Elf_Sxword val = old;
+
+			def = obj->symtab + r_symndx;
+
+			if (r_symndx >= obj->gotsym) {
+				val += got[obj->local_gotno + r_symndx - obj->gotsym];
+				dbg("REL32/G(%p) %p --> %p (%s) in %s",
+				    where, (void *)old, (void *)val,
+				    obj->strtab + def->st_name,
+				    obj->path);
+			} else {
+				/*
+				 * XXX: ABI DIFFERENCE!
+				 *
+				 * Old NetBSD binutils would generate shared
+				 * libs with section-relative relocations being
+				 * already adjusted for the start address of
+				 * the section.
+				 *
+				 * New binutils, OTOH, generate shared libs
+				 * with the same relocations being based at
+				 * zero, so we need to add in the start address
+				 * of the section.
+				 *
+				 * --rkb, Oct 6, 2001
+				 */
+
+				if (def->st_info ==
+				    ELF_ST_INFO(STB_LOCAL, STT_SECTION)
+#ifdef SUPPORT_OLD_BROKEN_LD
+				    && !broken
+#endif
+				    )
+					val += (Elf_Addr)def->st_value;
+
+				val += (Elf_Addr)obj->relocbase;
+
+				dbg("REL32/L(%p) %p -> %p (%s) in %s",
+				    where, (void *)old, (void *)val,
+				    obj->strtab + def->st_name, obj->path);
+			}
+			store_ptr(where, val, rlen);
+			break;
+		}
+
+#ifdef __mips_n64
+		case R_TYPE(TLS_DTPMOD64):
+#else
+		case R_TYPE(TLS_DTPMOD32): 
+#endif
+		{
+
+			const size_t rlen = sizeof(Elf_Addr);
+			Elf_Addr old = load_ptr(where, rlen);
+			Elf_Addr val = old;
+
+        		def = find_symdef(r_symndx, obj, &defobj, flags, NULL,
+	    			lockstate);
+			if (def == NULL)
+				return -1;
+
+			val += (Elf_Addr)defobj->tlsindex;
+
+			store_ptr(where, val, rlen);
+			dbg("DTPMOD %s in %s %p --> %p in %s",
+			    obj->strtab + obj->symtab[r_symndx].st_name,
+			    obj->path, (void *)old, (void*)val, defobj->path);
+			break;
+		}
+
+#ifdef __mips_n64
+		case R_TYPE(TLS_DTPREL64):
+#else
+		case R_TYPE(TLS_DTPREL32):
+#endif
+		{
+			const size_t rlen = sizeof(Elf_Addr);
+			Elf_Addr old = load_ptr(where, rlen);
+			Elf_Addr val = old;
+
+        		def = find_symdef(r_symndx, obj, &defobj, flags, NULL,
+	    			lockstate);
+			if (def == NULL)
+				return -1;
+
+			if (!defobj->tls_done && allocate_tls_offset(obj))
+				return -1;
+
+			val += (Elf_Addr)def->st_value - TLS_DTP_OFFSET;
+			store_ptr(where, val, rlen);
+
+			dbg("DTPREL %s in %s %p --> %p in %s",
+			    obj->strtab + obj->symtab[r_symndx].st_name,
+			    obj->path, (void*)old, (void *)val, defobj->path);
+			break;
+		}
+
+#ifdef __mips_n64
+		case R_TYPE(TLS_TPREL64):
+#else
+		case R_TYPE(TLS_TPREL32):
+#endif
+		{
+			const size_t rlen = sizeof(Elf_Addr);
+			Elf_Addr old = load_ptr(where, rlen);
+			Elf_Addr val = old;
+
+        		def = find_symdef(r_symndx, obj, &defobj, flags, NULL,
+	    			lockstate);
+
+			if (def == NULL)
+				return -1;
+
+			if (!defobj->tls_done && allocate_tls_offset(obj))
+				return -1;
+
+			val += (Elf_Addr)(def->st_value + defobj->tlsoffset
+			    - TLS_TP_OFFSET - TLS_TCB_SIZE);
+			store_ptr(where, val, rlen);
+
+			dbg("TPREL %s in %s %p --> %p in %s",
+			    obj->strtab + obj->symtab[r_symndx].st_name,
+			    obj->path, (void*)old, (void *)val, defobj->path);
+			break;
+		}
+
+
+
+		default:
+			dbg("sym = %lu, type = %lu, offset = %p, "
+			    "contents = %p, symbol = %s",
+			    (u_long)r_symndx, (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);
+			_rtld_error("%s: Unsupported relocation type %ld "
+			    "in non-PLT relocations",
+			    obj->path, (u_long) ELF_R_TYPE(rel->r_info));
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *  Process the PLT relocations.
+ */
+int
+reloc_plt(Obj_Entry *obj)
+{
+#if 0
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+		
+	dbg("reloc_plt obj:%p pltrel:%p sz:%s", obj, obj->pltrel, (int)obj->pltrelsize);
+	dbg("gottable %p num syms:%s", obj->pltgot, obj->symtabno );
+	dbg("*****************************************************");
+	rellim = (const Elf_Rel *)((char *)obj->pltrel +
+	    obj->pltrelsize);
+	for (rel = obj->pltrel;  rel < rellim;  rel++) {
+		Elf_Addr *where;
+		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+		*where += (Elf_Addr )obj->relocbase;
+	}
+
+#endif
+	/* PLT fixups were done above in the GOT relocation. */
+	return (0);
+}
+
+/*
+ * LD_BIND_NOW was set - force relocation for all jump slots
+ */
+int
+reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
+{
+	/* Do nothing */
+	obj->jmpslots_done = true;
+	
+	return (0);
+}
+
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, int flags,
+    struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+Elf_Addr
+reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
+    		const Obj_Entry *obj, const Elf_Rel *rel)
+{
+
+	/* Do nothing */
+
+	return target;
+}
+
+void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+
+}
+
+void
+pre_init(void)
+{
+
+}
+
+void
+allocate_initial_tls(Obj_Entry *objs)
+{
+	char *tls;
+	
+	/*
+	 * Fix the size of the static TLS block by using the maximum
+	 * offset allocated so far and adding a bit for dynamic modules to
+	 * use.
+	 */
+	tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
+
+	tls = (char *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8);
+
+	sysarch(MIPS_SET_TLS, tls);
+}
+
+void *
+__tls_get_addr(tls_index* ti)
+{
+	Elf_Addr** tls;
+	char *p;
+
+	sysarch(MIPS_GET_TLS, &tls);
+
+	p = tls_get_addr_common(tls, ti->ti_module, ti->ti_offset + TLS_DTP_OFFSET);
+
+	return (p);
+}


Property changes on: trunk/libexec/rtld-elf/mips/reloc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/mips/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/mips/rtld_machdep.h	                        (rev 0)
+++ trunk/libexec/rtld-elf/mips/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,82 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999, 2000 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/mips/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
+ */
+
+#ifndef RTLD_MACHDEP_H
+#define RTLD_MACHDEP_H	1
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+#include <machine/tls.h>
+
+struct Struct_Obj_Entry;
+
+/* Return the address of the .dynamic section in the dynamic linker. */
+#define rtld_dynamic(obj) (&_DYNAMIC)
+
+Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
+		       const struct Struct_Obj_Entry *defobj,
+		       const struct Struct_Obj_Entry *obj,
+		       const Elf_Rel *rel);
+
+#define make_function_pointer(def, defobj) \
+	((defobj)->relocbase + (def)->st_value)
+
+#define call_initfini_pointer(obj, target) \
+	(((InitFunc)(target))())
+
+#define call_init_pointer(obj, target) \
+	(((InitArrFunc)(target))(main_argc, main_argv, environ))
+
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(void))ptr)())
+
+typedef struct {
+	unsigned long ti_module;
+	unsigned long ti_offset;
+} tls_index;
+
+#define round(size, align) \
+    (((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+    round(TLS_TCB_SIZE, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+    round(prev_offset + prev_size, align)
+#define calculate_tls_end(off, size)    ((off) + (size))
+
+/*
+ * Lazy binding entry point, called via PLT.
+ */
+void _rtld_bind_start(void);
+
+extern void *__tls_get_addr(tls_index *ti);
+
+#define	RTLD_DEFAULT_STACK_PF_EXEC	PF_X
+#define	RTLD_DEFAULT_STACK_EXEC		PROT_EXEC
+
+#endif


Property changes on: trunk/libexec/rtld-elf/mips/rtld_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/mips/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/mips/rtld_start.S	                        (rev 0)
+++ trunk/libexec/rtld-elf/mips/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,167 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: rtld_start.S,v 1.10 2009/12/14 00:41:19 matt Exp $	*/
+
+/*
+ * Copyright 1997 Michael L. Hitch <mhitch at montana.edu>
+ * Portions copyright 2002 Charles M. Hannum <root at ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/mips/rtld_start.S 233378 2012-03-23 17:54:06Z gonzo $
+ */
+
+#include <machine/asm.h>
+
+.globl _C_LABEL(_rtld_relocate_nonplt_self)
+.globl _C_LABEL(_rtld)
+
+#define	PTR_SIZE	(1<<PTR_SCALESHIFT)
+
+/*
+ *      a0      stack pointer
+ *      a1      rtld cleanup (filled in by dynamic loader)
+ *      a2      rtld object (filled in by dynamic loader)
+ *      a3      ps_strings
+ */
+LEAF(rtld_start)
+	.frame	sp, 4*PTR_SIZE, ra
+	.mask	0x10090000,-PTR_SIZE
+	.set	noreorder
+	SETUP_GP
+	PTR_SUBU sp, 4*PTR_SIZE		/* adjust stack pointer */
+	SETUP_GP64(s4, rtld_start)
+	SAVE_GP(0)
+					/* -> 1*PTR_SIZE(sp) for atexit */
+					/* -> 2*PTR_SIZE(sp) for obj_main */
+	move	s0, a0			/* save stack pointer from a0 */
+	move	s3, a3			/* save ps_strings pointer */
+
+	PTR_LA	a1, 1f
+	bal	1f
+	PTR_LA	t0, _C_LABEL(_rtld_relocate_nonplt_self)
+1:	PTR_SUBU a1, ra, a1		/* relocbase */
+	PTR_LA	a0, _DYNAMIC
+	PTR_ADDU t9, a1, t0
+	jalr	t9			/* _rtld_relocate_nonplt_self(dynp, relocabase) */
+	PTR_ADDU a0, a1, a0		/* &_DYNAMIC */
+
+	move	a0, s0			/* sp */
+	PTR_ADDU a1, sp, 2*PTR_SIZE	/* &our atexit function */
+	PTR_ADDU a2, sp, 3*PTR_SIZE	/* obj_main entry */
+	PTR_SUBU sp, 4*SZREG		/* ABI requires to reserve memory for 4 regs */
+	PTR_LA	t9, _C_LABEL(_rtld)
+	jalr	t9			/* v0 = _rtld(sp, cleanup, objp) */
+	nop
+	PTR_ADDU sp, 4*SZREG
+
+	PTR_L	a1, 2*PTR_SIZE(sp)	/* our atexit function */
+	PTR_L	a2, 3*PTR_SIZE(sp)	/* obj_main entry */
+	PTR_ADDU sp, 4*PTR_SIZE		/* readjust stack */
+	move	a0, s0			/* stack pointer */
+	move	t9, v0
+	PTR_SUBU sp, 4*SZREG		/* ABI requires to reserve memory for 4 regs */
+	move	ra,t9			/* RA == PC signals backtrace routine to stop */
+	j	t9			/* _start(sp, cleanup, obj); */
+	move	a3, s3			/* restore ps_strings */
+END(rtld_start)
+
+#define	XCALLFRAME_SIZ		(12*SZREG)
+#define	XCALLFRAME_RA		(10*SZREG)
+#define	XCALLFRAME_GP		(9*SZREG)
+#define	XCALLFRAME_S0		(8*SZREG)
+#define	XCALLFRAME_A3		(7*SZREG)
+#define	XCALLFRAME_A2		(6*SZREG)
+#define	XCALLFRAME_A1		(5*SZREG)
+#define	XCALLFRAME_A0		(4*SZREG)
+#if defined(__mips_n32) || defined(__mips_n64)
+#define	XCALLFRAME_A7		(3*SZREG)
+#define	XCALLFRAME_A6		(2*SZREG)
+#define	XCALLFRAME_A5		(1*SZREG)
+#define	XCALLFRAME_A4		(0*SZREG)
+#endif
+
+	.globl	_rtld_bind_start
+	.ent	_rtld_bind_start
+_rtld_bind_start:
+	.frame	sp, XCALLFRAME_SIZ, $15
+	move	v1, gp			/* save old GP */
+#if defined(__mips_o32) || defined(__mips_o64)
+	PTR_ADDU t9, 8			/* modify T9 to point at .cpload */
+#endif
+	SETUP_GP
+	PTR_SUBU sp, XCALLFRAME_SIZ	/* save arguments and sp value in stack */
+	SETUP_GP64(XCALLFRAME_GP, _rtld_bind_start)
+	SAVE_GP(XCALLFRAME_GP)
+#if defined(__mips_n32) || defined(__mips_n64)
+	REG_S	a4,  XCALLFRAME_A4(sp)
+	REG_S	a5,  XCALLFRAME_A5(sp)
+	REG_S	a6,  XCALLFRAME_A6(sp)
+	REG_S	a7,  XCALLFRAME_A7(sp)
+#endif
+	REG_S	a0,  XCALLFRAME_A0(sp)
+	REG_S	a1,  XCALLFRAME_A1(sp)
+	REG_S	a2,  XCALLFRAME_A2(sp)
+	REG_S	a3,  XCALLFRAME_A3(sp)
+	REG_S	$15,  XCALLFRAME_RA(sp)	/* ra is in t7/t3 */
+	REG_S	s0,  XCALLFRAME_S0(sp)
+	move	s0, sp
+
+	move	a0, v1			/* old GP */
+	PTR_SUBU	a0, a0, 0x7ff0		/* The offset of $gp from the	*/
+       					/* beginning of the .got section: */
+					/* $gp = .got + 0x7ff0, so	*/
+					/* .got = $gp - 0x7ff0		*/
+					/* Simple math as you can see.	*/
+#if defined(__mips_n64)
+	ld	a0, 8(a0)		/* object = pltgot[1] */
+	and	a0, a0, 0x7fffffffffffffff
+#else
+	lw	a0, 4(a0)		/* object = pltgot[1] & 0x7fffffff */
+	and	a0, a0, 0x7fffffff
+#endif
+	move	a1, t8			/* symbol index */
+
+	PTR_LA	t9, _C_LABEL(_mips_rtld_bind)
+	jalr	t9
+	nop
+
+	move	sp, s0
+	REG_L	ra, XCALLFRAME_RA(sp)
+	REG_L	s0, XCALLFRAME_S0(sp)
+	REG_L	a0, XCALLFRAME_A0(sp)
+	REG_L	a1, XCALLFRAME_A1(sp)
+	REG_L	a2, XCALLFRAME_A2(sp)
+	REG_L	a3, XCALLFRAME_A3(sp)
+#if defined(__mips_n32) || defined(__mips_n64)
+	REG_L	a4, XCALLFRAME_A4(sp)
+	REG_L	a5, XCALLFRAME_A5(sp)
+	REG_L	a6, XCALLFRAME_A6(sp)
+	REG_L	a7, XCALLFRAME_A7(sp)
+#endif
+	RESTORE_GP64
+	PTR_ADDU sp, XCALLFRAME_SIZ
+	move	t9, v0
+	jr	t9
+	nop
+END(_rtld_bind_start)


Property changes on: trunk/libexec/rtld-elf/mips/rtld_start.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/powerpc/Makefile.inc	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1 @@
+# $MidnightBSD$


Property changes on: trunk/libexec/rtld-elf/powerpc/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/powerpc/reloc.c	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,669 @@
+/* $MidnightBSD$ */
+/*      $NetBSD: ppc_reloc.c,v 1.10 2001/09/10 06:09:41 mycroft Exp $   */
+
+/*-
+ * Copyright (C) 1998   Tsubai Masanari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/powerpc/reloc.c 331206 2018-03-19 14:28:58Z marius $
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <machine/cpu.h>
+#include <machine/atomic.h>
+#include <machine/md_var.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+#define _ppc_ha(x) ((((u_int32_t)(x) & 0x8000) ? \
+                        ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
+#define _ppc_la(x) ((u_int32_t)(x) & 0xffff)
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+#define PLT_EXTENDED_BEGIN	(1 << 13)
+#define JMPTAB_BASE(N)		(18 + N*2 + ((N > PLT_EXTENDED_BEGIN) ? \
+				    (N - PLT_EXTENDED_BEGIN)*2 : 0))
+
+/*
+ * Process the R_PPC_COPY relocations
+ */
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+
+	/*
+	 * COPY relocs are invalid outside of the main program
+	 */
+	assert(dstobj->mainprog);
+
+	relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela +
+	    dstobj->relasize);
+	for (rela = dstobj->rela;  rela < relalim;  rela++) {
+		void *dstaddr;
+		const Elf_Sym *dstsym;
+		const char *name;
+		size_t size;
+		const void *srcaddr;
+		const Elf_Sym *srcsym = NULL;
+		const Obj_Entry *srcobj, *defobj;
+		SymLook req;
+		int res;
+
+		if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) {
+			continue;
+		}
+
+		dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
+		dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
+		name = dstobj->strtab + dstsym->st_name;
+		size = dstsym->st_size;
+		symlook_init(&req, name);
+		req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
+		req.flags = SYMLOOK_EARLY;
+
+		for (srcobj = globallist_next(dstobj); srcobj != NULL;
+		     srcobj = globallist_next(srcobj)) {
+			res = symlook_obj(&req, srcobj);
+			if (res == 0) {
+				srcsym = req.sym_out;
+				defobj = req.defobj_out;
+				break;
+			}
+		}
+
+		if (srcobj == NULL) {
+			_rtld_error("Undefined symbol \"%s\" "
+				    " referenced from COPY"
+				    " relocation in %s", name, dstobj->path);
+			return (-1);
+		}
+
+		srcaddr = (const void *) (defobj->relocbase+srcsym->st_value);
+		memcpy(dstaddr, srcaddr, size);
+		dbg("copy_reloc: src=%p,dst=%p,size=%d\n",srcaddr,dstaddr,size);
+	}
+
+	return (0);
+}
+
+
+/*
+ * Perform early relocation of the run-time linker image
+ */
+void
+reloc_non_plt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+	const Elf_Rela *rela = 0, *relalim;
+	Elf_Addr relasz = 0;
+	Elf_Addr *where;
+
+	/*
+	 * Extract the rela/relasz values from the dynamic section
+	 */
+	for (; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_RELA:
+			rela = (const Elf_Rela *)(relocbase+dynp->d_un.d_ptr);
+			break;
+		case DT_RELASZ:
+			relasz = dynp->d_un.d_val;
+			break;
+		}
+	}
+
+	/*
+	 * Relocate these values
+	 */
+	relalim = (const Elf_Rela *)((caddr_t)rela + relasz);
+	for (; rela < relalim; rela++) {
+		where = (Elf_Addr *)(relocbase + rela->r_offset);
+		*where = (Elf_Addr)(relocbase + rela->r_addend);
+	}
+}
+
+
+/*
+ * Relocate a non-PLT object with addend.
+ */
+static int
+reloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
+    SymCache *cache, int flags, RtldLockState *lockstate)
+{
+	Elf_Addr        *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	const Elf_Sym   *def;
+	const Obj_Entry *defobj;
+	Elf_Addr         tmp;
+
+	switch (ELF_R_TYPE(rela->r_info)) {
+
+	case R_PPC_NONE:
+		break;
+
+        case R_PPC_ADDR32:    /* word32 S + A */
+        case R_PPC_GLOB_DAT:  /* word32 S + A */
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL) {
+			return (-1);
+		}
+
+                tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                    rela->r_addend);
+
+		/* Don't issue write if unnecessary; avoid COW page fault */
+                if (*where != tmp) {
+                        *where = tmp;
+		}
+                break;
+
+        case R_PPC_RELATIVE:  /* word32 B + A */
+		tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
+
+		/* As above, don't issue write unnecessarily */
+		if (*where != tmp) {
+			*where = tmp;
+		}
+		break;
+
+	case R_PPC_COPY:
+		/*
+		 * These are deferred until all other relocations
+		 * have been done.  All we do here is make sure
+		 * that the COPY relocation is not in a shared
+		 * library.  They are allowed only in executable
+		 * files.
+		 */
+		if (!obj->mainprog) {
+			_rtld_error("%s: Unexpected R_COPY "
+				    " relocation in shared library",
+				    obj->path);
+			return (-1);
+		}
+		break;
+
+	case R_PPC_JMP_SLOT:
+		/*
+		 * These will be handled by the plt/jmpslot routines
+		 */
+		break;
+
+	case R_PPC_DTPMOD32:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+
+		if (def == NULL)
+			return (-1);
+
+		*where = (Elf_Addr) defobj->tlsindex;
+
+		break;
+
+	case R_PPC_TPREL32:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+
+		if (def == NULL)
+			return (-1);
+
+		/*
+		 * We lazily allocate offsets for static TLS as we
+		 * see the first relocation that references the
+		 * TLS block. This allows us to support (small
+		 * amounts of) static TLS in dynamically loaded
+		 * modules. If we run out of space, we generate an
+		 * error.
+		 */
+		if (!defobj->tls_done) {
+			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+				_rtld_error("%s: No space available for static "
+				    "Thread Local Storage", obj->path);
+				return (-1);
+			}
+		}
+
+		*(Elf_Addr **)where = *where * sizeof(Elf_Addr)
+		    + (Elf_Addr *)(def->st_value + rela->r_addend 
+		    + defobj->tlsoffset - TLS_TP_OFFSET);
+		
+		break;
+		
+	case R_PPC_DTPREL32:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+
+		if (def == NULL)
+			return (-1);
+
+		*where += (Elf_Addr)(def->st_value + rela->r_addend 
+		    - TLS_DTV_OFFSET);
+
+		break;
+		
+	default:
+		_rtld_error("%s: Unsupported relocation type %d"
+			    " in non-PLT relocations\n", obj->path,
+			    ELF_R_TYPE(rela->r_info));
+		return (-1);
+        }
+	return (0);
+}
+
+
+/*
+ * Process non-PLT relocations
+ */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
+    RtldLockState *lockstate)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+	SymCache *cache;
+	int r = -1;
+
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
+	/*
+	 * The dynamic loader may be called from a thread, we have
+	 * limited amounts of stack available so we cannot use alloca().
+	 */
+	if (obj != obj_rtld) {
+		cache = calloc(obj->dynsymcount, sizeof(SymCache));
+		/* No need to check for NULL here */
+	} else
+		cache = NULL;
+
+	/*
+	 * From the SVR4 PPC ABI:
+	 * "The PowerPC family uses only the Elf32_Rela relocation
+	 *  entries with explicit addends."
+	 */
+	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
+	for (rela = obj->rela; rela < relalim; rela++) {
+		if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags,
+		    lockstate) < 0)
+			goto done;
+	}
+	r = 0;
+done:
+	if (cache != NULL)
+		free(cache);
+
+	/* Synchronize icache for text seg in case we made any changes */
+	__syncicache(obj->mapbase, obj->textsize);
+
+	return (r);
+}
+
+/*
+ * Initialise a PLT slot to the resolving trampoline
+ */
+static int
+reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
+{
+	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+	Elf_Addr *pltresolve, *pltlongresolve, *jmptab;
+	Elf_Addr distance;
+	int N = obj->pltrelasize / sizeof(Elf_Rela);
+	int reloff;
+
+	reloff = rela - obj->pltrela;
+
+	if (reloff < 0)
+		return (-1);
+
+	pltlongresolve = obj->pltgot + 5;
+	pltresolve = pltlongresolve + 5;
+
+	distance = (Elf_Addr)pltresolve - (Elf_Addr)(where + 1);
+
+	dbg(" reloc_plt_object: where=%p,pltres=%p,reloff=%x,distance=%x",
+	    (void *)where, (void *)pltresolve, reloff, distance);
+
+	if (reloff < PLT_EXTENDED_BEGIN) {
+		/* li   r11,reloff  */
+		/* b    pltresolve  */
+		where[0] = 0x39600000 | reloff;
+		where[1] = 0x48000000 | (distance & 0x03fffffc);
+	} else {
+		jmptab = obj->pltgot + JMPTAB_BASE(N);
+		jmptab[reloff] = (u_int)pltlongresolve;
+
+		/* lis	r11,jmptab[reloff]@ha */
+		/* lwzu	r12,jmptab[reloff]@l(r11) */
+		/* mtctr r12 */
+		/* bctr */
+		where[0] = 0x3d600000 | _ppc_ha(&jmptab[reloff]);
+		where[1] = 0x858b0000 | _ppc_la(&jmptab[reloff]);
+		where[2] = 0x7d8903a6;
+		where[3] = 0x4e800420;
+	}
+		
+
+	/*
+	 * The icache will be sync'd in reloc_plt, which is called
+	 * after all the slots have been updated
+	 */
+
+	return (0);
+}
+
+
+/*
+ * Process the PLT relocations.
+ */
+int
+reloc_plt(Obj_Entry *obj)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+	int N = obj->pltrelasize / sizeof(Elf_Rela);
+
+	if (obj->pltrelasize != 0) {
+
+		relalim = (const Elf_Rela *)((char *)obj->pltrela +
+		    obj->pltrelasize);
+		for (rela = obj->pltrela;  rela < relalim;  rela++) {
+			assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT);
+
+			if (reloc_plt_object(obj, rela) < 0) {
+				return (-1);
+			}
+		}
+	}
+
+	/*
+	 * Sync the icache for the byte range represented by the
+	 * trampoline routines and call slots.
+	 */
+	if (obj->pltgot != NULL)
+		__syncicache(obj->pltgot, JMPTAB_BASE(N)*4);
+
+	return (0);
+}
+
+
+/*
+ * LD_BIND_NOW was set - force relocation for all jump slots
+ */
+int
+reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
+{
+	const Obj_Entry *defobj;
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+	const Elf_Sym *def;
+	Elf_Addr *where;
+	Elf_Addr target;
+
+	relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
+	for (rela = obj->pltrela; rela < relalim; rela++) {
+		assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT);
+		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    SYMLOOK_IN_PLT | flags, NULL, lockstate);
+		if (def == NULL) {
+			dbg("reloc_jmpslots: sym not found");
+			return (-1);
+		}
+
+		target = (Elf_Addr)(defobj->relocbase + def->st_value);
+
+#if 0
+		/* PG XXX */
+		dbg("\"%s\" in \"%s\" --> %p in \"%s\"",
+		    defobj->strtab + def->st_name, basename(obj->path),
+		    (void *)target, basename(defobj->path));
+#endif
+
+		reloc_jmpslot(where, target, defobj, obj,
+		    (const Elf_Rel *) rela);
+	}
+
+	obj->jmpslots_done = true;
+
+	return (0);
+}
+
+
+/*
+ * Update the value of a PLT jump slot. Branch directly to the target if
+ * it is within +/- 32Mb, otherwise go indirectly via the pltcall
+ * trampoline call and jump table.
+ */
+Elf_Addr
+reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
+	      const Obj_Entry *obj, const Elf_Rel *rel)
+{
+	Elf_Addr offset;
+	const Elf_Rela *rela = (const Elf_Rela *) rel;
+
+	dbg(" reloc_jmpslot: where=%p, target=%p",
+	    (void *)wherep, (void *)target);
+
+	/*
+	 * At the PLT entry pointed at by `wherep', construct
+	 * a direct transfer to the now fully resolved function
+	 * address.
+	 */
+	offset = target - (Elf_Addr)wherep;
+
+	if (abs(offset) < 32*1024*1024) {     /* inside 32MB? */
+		/* b    value   # branch directly */
+		*wherep = 0x48000000 | (offset & 0x03fffffc);
+		__syncicache(wherep, 4);
+	} else {
+		Elf_Addr *pltcall, *jmptab;
+		int distance;
+		int N = obj->pltrelasize / sizeof(Elf_Rela);
+		int reloff = rela - obj->pltrela;
+
+		if (reloff < 0)
+			return (-1);
+
+		pltcall = obj->pltgot;
+
+		dbg(" reloc_jmpslot: indir, reloff=%x, N=%x\n",
+		    reloff, N);
+
+		jmptab = obj->pltgot + JMPTAB_BASE(N);
+		jmptab[reloff] = target;
+		mb(); /* Order jmptab update before next changes */
+
+		if (reloff < PLT_EXTENDED_BEGIN) {
+			/* for extended PLT entries, we keep the old code */
+
+			distance = (Elf_Addr)pltcall - (Elf_Addr)(wherep + 1);
+
+			/* li   r11,reloff */
+			/* b    pltcall  # use indirect pltcall routine */
+
+			/* first instruction same as before */
+			wherep[1] = 0x48000000 | (distance & 0x03fffffc);
+			__syncicache(wherep, 8);
+		}
+	}
+
+	return (target);
+}
+
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, int flags,
+    struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+/*
+ * Setup the plt glue routines.
+ */
+#define PLTCALL_SIZE	   	20
+#define PLTLONGRESOLVE_SIZE	20
+#define PLTRESOLVE_SIZE		24
+
+void
+init_pltgot(Obj_Entry *obj)
+{
+	Elf_Word *pltcall, *pltresolve, *pltlongresolve;
+	Elf_Word *jmptab;
+	int N = obj->pltrelasize / sizeof(Elf_Rela);
+
+	pltcall = obj->pltgot;
+
+	if (pltcall == NULL) {
+		return;
+	}
+
+	/*
+	 * From the SVR4 PPC ABI:
+	 *
+	 * 'The first 18 words (72 bytes) of the PLT are reserved for
+	 * use by the dynamic linker.
+	 *   ...
+	 * 'If the executable or shared object requires N procedure
+	 *  linkage table entries, the link editor shall reserve 3*N
+	 *  words (12*N bytes) following the 18 reserved words. The
+	 *  first 2*N of these words are the procedure linkage table
+	 *  entries themselves. The static linker directs calls to bytes
+	 *  (72 + (i-1)*8), for i between 1 and N inclusive. The remaining
+	 *  N words (4*N bytes) are reserved for use by the dynamic linker.'
+	 */
+
+	/*
+	 * Copy the absolute-call assembler stub into the first part of
+	 * the reserved PLT area.
+	 */
+	memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
+
+	/*
+	 * Determine the address of the jumptable, which is the dyn-linker
+	 * reserved area after the call cells. Write the absolute address
+	 * of the jumptable into the absolute-call assembler code so it
+	 * can determine this address.
+	 */
+	jmptab = obj->pltgot + JMPTAB_BASE(N);
+	pltcall[1] |= _ppc_ha(jmptab);	   /* addis 11,11,jmptab at ha */
+	pltcall[2] |= _ppc_la(jmptab);     /* lwz   11,jmptab at l(11) */
+
+	/*
+	 * Skip down 20 bytes into the initial reserved area and copy
+	 * in the standard resolving assembler call. Into this assembler,
+	 * insert the absolute address of the _rtld_bind_start routine
+	 * and the address of the relocation object.
+	 *
+	 * We place pltlongresolve first, so it can fix up its arguments
+	 * and then fall through to the regular PLT resolver.
+	 */
+	pltlongresolve = obj->pltgot + 5;
+
+	memcpy(pltlongresolve, _rtld_powerpc_pltlongresolve,
+	    PLTLONGRESOLVE_SIZE);
+	pltlongresolve[0] |= _ppc_ha(jmptab);	/* lis	12,jmptab at ha	*/
+	pltlongresolve[1] |= _ppc_la(jmptab);	/* addi	12,12,jmptab at l	*/
+
+	pltresolve = pltlongresolve + PLTLONGRESOLVE_SIZE/sizeof(uint32_t);
+	memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
+	pltresolve[0] |= _ppc_ha(_rtld_bind_start);
+	pltresolve[1] |= _ppc_la(_rtld_bind_start);
+	pltresolve[3] |= _ppc_ha(obj);
+	pltresolve[4] |= _ppc_la(obj);
+
+	/*
+	 * The icache will be sync'd in reloc_plt, which is called
+	 * after all the slots have been updated
+	 */
+}
+
+void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+
+}
+
+void
+pre_init(void)
+{
+
+}
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+	register Elf_Addr **tp __asm__("r2");
+	Elf_Addr **_tp;
+
+	/*
+	* Fix the size of the static TLS block by using the maximum
+	* offset allocated so far and adding a bit for dynamic modules to
+	* use.
+	*/
+
+	tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
+
+	_tp = (Elf_Addr **) ((char *) allocate_tls(list, NULL, TLS_TCB_SIZE, 8) 
+	    + TLS_TP_OFFSET + TLS_TCB_SIZE);
+
+	/*
+	 * XXX gcc seems to ignore 'tp = _tp;' 
+	 */
+	 
+	__asm __volatile("mr %0,%1" : "=r"(tp) : "r"(_tp));
+}
+
+void*
+__tls_get_addr(tls_index* ti)
+{
+	register Elf_Addr **tp __asm__("r2");
+	char *p;
+
+	p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET 
+	    - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset);
+
+	return (p + TLS_DTV_OFFSET);
+}


Property changes on: trunk/libexec/rtld-elf/powerpc/reloc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/powerpc/rtld_machdep.h	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,97 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999, 2000 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/powerpc/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
+ */
+
+#ifndef RTLD_MACHDEP_H
+#define RTLD_MACHDEP_H	1
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+
+struct Struct_Obj_Entry;
+
+/* Return the address of the .dynamic section in the dynamic linker. */
+#define rtld_dynamic(obj)    (&_DYNAMIC)
+
+Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
+		       const struct Struct_Obj_Entry *defobj,
+		       const struct Struct_Obj_Entry *obj,
+		       const Elf_Rel *rel);
+
+#define make_function_pointer(def, defobj) \
+	((defobj)->relocbase + (def)->st_value)
+
+#define call_initfini_pointer(obj, target) \
+	(((InitFunc)(target))())
+
+#define call_init_pointer(obj, target) \
+	(((InitArrFunc)(target))(main_argc, main_argv, environ))
+
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(void))ptr)())
+
+/*
+ * Lazy binding entry point, called via PLT.
+ */
+void _rtld_bind_start(void);
+
+/*
+ * PLT functions. Not really correct prototypes, but the
+ * symbol values are needed.
+ */
+void _rtld_powerpc_pltlongresolve(void);
+void _rtld_powerpc_pltresolve(void);
+void _rtld_powerpc_pltcall(void);
+
+/*
+ * TLS
+ */
+
+#define TLS_TP_OFFSET	0x7000
+#define TLS_DTV_OFFSET	0x8000
+#define TLS_TCB_SIZE	8
+
+#define round(size, align) \
+    (((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+    round(8, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+    round(prev_offset + prev_size, align)
+#define calculate_tls_end(off, size)    ((off) + (size))
+ 
+typedef struct {
+	unsigned long ti_module;
+	unsigned long ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr(tls_index* ti);
+
+#define	RTLD_DEFAULT_STACK_PF_EXEC	PF_X
+#define	RTLD_DEFAULT_STACK_EXEC		PROT_EXEC
+
+#endif


Property changes on: trunk/libexec/rtld-elf/powerpc/rtld_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/powerpc/rtld_start.S	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,201 @@
+/* $MidnightBSD$ */
+/*      $NetBSD: rtld_start.S,v 1.4 2001/09/26 04:06:43 mycroft Exp $   */
+
+/*-
+ * Copyright (C) 1998   Tsubai Masanari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/powerpc/rtld_start.S 217397 2011-01-14 11:32:31Z kib $
+ */
+
+#include <machine/asm.h>
+
+.extern _GLOBAL_OFFSET_TABLE_
+.extern _DYNAMIC
+
+_ENTRY(.rtld_start)
+	stwu    %r1,-48(%r1)	/* 16-byte aligned stack for reg saves +
+				exit_proc & obj _rtld args +
+				backchain & lrsave stack frame */
+	stw     %r3,16(%r1)	/*  argc */
+	stw     %r4,20(%r1)	/*  argv */
+	stw     %r5,24(%r1)	/*  envp */
+/*	stw     %r6,28(%r1)   *//*  obj (always 0) */
+/*	stw     %r7,32(%r1)   *//*  cleanup (always 0) */
+	stw     %r8,36(%r1)	/*  ps_strings */
+
+	/*
+	 * Perform initial relocation of ld-elf.so. Not as easy as it
+	 * sounds.
+	 *  - perform small forward branch to put PC into link reg
+	 *  - use link-time constants to determine offset to the
+	 *    _DYNAMIC section and the GOT. Add these to the PC to
+	 *    convert to absolute addresses.
+	 *  - sync icache to allow execution of the SVR4 ABI-specified
+	 *    blrl instruction preceding the GOT
+	 *  - Use this instruction to determine the GOT absolute address
+	 *  - read GOT[0], which is the SVR4 ABI-specified link-time
+	 *    value of _DYNAMIC. Subtract this value from the absolute
+	 *    value to determine the load address
+	 *  - call reloc_non_plt_self() to fix up ld-elf.so's relocations
+	 */
+	bl	1f
+	.long	_DYNAMIC-.
+	.long	_GLOBAL_OFFSET_TABLE_-.	/* branch lr + 4 */
+1:
+	mflr	%r3		/* PC value at .long */
+	lwz	%r4,4(%r3)
+	add	%r4,%r4,%r3	/* &_GLOBAL_OFFSET_TABLE-4, blrl insn. */
+	dcbst   %r0,%r4         /* sync i-cache with d-cache */
+	sync
+	icbi    %r0,%r4
+	isync
+
+	lwz	%r4,0(%r3)	/* offset to _DYNAMIC */
+	add	%r3,%r4,%r3	/* r3 = &_DYNAMIC, absolute value */
+
+	bl	_GLOBAL_OFFSET_TABLE_ at local-4
+	mflr	%r4		/* &_GLOBAL_OFFSET_TABLE_, absolute value */
+	lwz	%r4,0(%r4)	/* linker &_DYNAMIC, from got[0] */
+	subf	%r4,%r4,%r3	/* subtract to calculate relocbase */
+
+	bl	reloc_non_plt_self at plt /* reloc_non_plt_self(&_DYNAMIC,base) */
+
+	/*
+	 * The _rtld() function likes to see a stack layout containing
+	 * { argc, argv[0], argv[1] ... argv[N], 0, env[0], ... , env[N] }
+	 * Since the PowerPC stack was 16-byte aligned at exec time, the
+	 * original stack layout has to be found by moving back a word
+	 * from the argv pointer.
+	 */
+        lwz     %r4,20(%r1)	/* restore argv */
+        addi    %r3,%r4,-4	/* locate argc ptr, &argv[-1] */
+
+	addi	%r4,%r1,8	/* &exit_proc on stack */
+	addi	%r5,%r1,12	/* &obj_main on stack */
+
+	bl      _rtld at plt	/* &_start = _rtld(sp, &exit_proc, &obj_main)*/
+	mtlr    %r3
+
+	/*
+	 * Restore args, with new obj/exit proc
+	 */
+	lwz     %r3,16(%r1)     /* argc */
+	lwz     %r4,20(%r1)	/* argv */
+	lwz     %r5,24(%r1)	/* envp */
+	lwz     %r6,12(%r1)	/* obj */
+	lwz     %r7,8(%r1)	/* exit proc */
+	lwz     %r8,36(%r1)	/* ps_strings */
+        addi    %r1,%r1,48	/* restore original stackptr */
+
+	blrl	/* _start(argc, argv, envp, obj, cleanup, ps_strings) */
+
+	li      %r0,1		/* _exit() */
+	sc
+
+/*
+ * _rtld_bind_start()
+ *
+ * Call into the MI binder. This routine is reached via the PLT call cell,
+ * and then _rtld_powerpc_pltresolve().
+ * On entry, %r11 contains the index of the PLT cell, and %r12 contains
+ * a pointer to the ELF object for the file.
+ *  Save all registers, call into the binder to resolve and fixup the external
+ * routine, and then transfer to the external routine on return.
+ */
+	.globl  _rtld_bind
+
+_ENTRY(_rtld_bind_start)
+	stwu    %r1,-160(%r1)		# stack space for 29 regs + r0/lr/cr
+	stw     %r0,20(%r1)		# save r0
+	mflr    %r0
+	stw     %r0,16(%r1)		# save lr
+	mfcr    %r0
+	stw     %r0,12(%r1)		# save cr
+	stmw    %r3,24(%r1)		# save r3-r31
+
+	mr      %r3,%r12		# obj
+	mulli   %r4,%r11,12		# rela index * sizeof(Elf_Rela)
+	bl      _rtld_bind at PLT		# target addr = _rtld_bind(obj, reloff)
+	mtctr   %r3			# move absolute target addr into ctr
+
+        lmw     %r3,24(%r1)		# restore r3-r31
+        lwz     %r0,12(%r1)		# restore cr
+        mtcr    %r0
+        lwz     %r0,16(%r1)		# restore lr
+        mtlr    %r0
+        lwz     %r0,20(%r1)		# restore r0
+
+        addi    %r1,%r1,160		# restore stack
+        bctr				# jump to target
+
+
+/*
+ * _rtld_powerpc_pltresolve()
+ *
+ *  This routine is copied into the latter part of the 72-byte reserved
+ * area at the start of the PLT. The absolute address of the _rtld_bind_start
+ * routine, and the ELF object for the loaded file, are inserted into
+ * the code by the reloc.c:init_pltgot() routine.
+ *  The first time an external routine is called, the PLT slot will
+ * set up %r11 to the offset of the slot, and will jump to this routine.
+ * The ELF object is shifted into %r11, and _rtld_bind_start is called
+ * to complete the binding.
+ */
+_ENTRY(_rtld_powerpc_pltlongresolve)
+	lis	%r12,0			# lis	12,jmptab at ha
+	addi    %r12,%r12,0		# addi  12,12,jmptab at l
+	subf	%r11,%r12,%r11		# reloff
+	li	%r12,2
+	srw	%r11,%r11,%r12		# index = reloff/sizeof(Elf_Addr)
+_ENTRY(_rtld_powerpc_pltresolve)
+        lis     %r12,0			# lis   12,_rtld_bind_start at ha
+        addi    %r12,%r12,0		# addi  12,12,_rtld_bind_start at l
+        mtctr   %r12
+        lis     %r12,0			# lis   12,obj at ha
+        addi    %r12,%r12,0		# addi  12,12,obj at l
+        bctr
+
+/*
+ * _rtld_powerpc_pltcall()
+ *
+ *  This routine is copied into the 72-byte reserved area at the
+ * start of the PLT. The reloc.c:init_pltgot() routine inserts
+ * the absolute address of the jumptable.
+ *  Control is transferred to this routine when the binder has
+ * located the external routine, but determined that it is > 32Mb
+ * from the PLT slot. Code is inserted into the PLT slot to set up
+ * %r11 with the jumptable index, and jump to here, where the
+ * absolute address of the external routine is loaded from the
+ * jumptable and transferred to
+ */
+_ENTRY(_rtld_powerpc_pltcall)
+        slwi    %r11,%r11,2		# jmptab offset = index * 4
+        addis   %r11,%r11,0		# addis 11,11,jmptab at ha
+        lwz     %r11,0(%r11)		# lwz   11,jmptab at l(11)
+        mtctr   %r11
+        bctr				# (*jmptab[index])()
+
+	.section .note.GNU-stack,"",%progbits


Property changes on: trunk/libexec/rtld-elf/powerpc/rtld_start.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc64/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/powerpc64/Makefile.inc	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc64/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1 @@
+# $MidnightBSD$


Property changes on: trunk/libexec/rtld-elf/powerpc64/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc64/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/powerpc64/reloc.c	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc64/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,533 @@
+/* $MidnightBSD$ */
+/*      $NetBSD: ppc_reloc.c,v 1.10 2001/09/10 06:09:41 mycroft Exp $   */
+
+/*-
+ * Copyright (C) 1998   Tsubai Masanari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/powerpc64/reloc.c 331206 2018-03-19 14:28:58Z marius $
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+struct funcdesc {
+	Elf_Addr addr;
+	Elf_Addr toc;
+	Elf_Addr env;
+};
+
+/*
+ * Process the R_PPC_COPY relocations
+ */
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+
+	/*
+	 * COPY relocs are invalid outside of the main program
+	 */
+	assert(dstobj->mainprog);
+
+	relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela +
+	    dstobj->relasize);
+	for (rela = dstobj->rela;  rela < relalim;  rela++) {
+		void *dstaddr;
+		const Elf_Sym *dstsym;
+		const char *name;
+		size_t size;
+		const void *srcaddr;
+		const Elf_Sym *srcsym = NULL;
+		const Obj_Entry *srcobj, *defobj;
+		SymLook req;
+		int res;
+
+		if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) {
+			continue;
+		}
+
+		dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
+		dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
+		name = dstobj->strtab + dstsym->st_name;
+		size = dstsym->st_size;
+		symlook_init(&req, name);
+		req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
+		req.flags = SYMLOOK_EARLY;
+
+		for (srcobj = globallist_next(dstobj); srcobj != NULL;
+		     srcobj = globallist_next(srcobj)) {
+			res = symlook_obj(&req, srcobj);
+			if (res == 0) {
+				srcsym = req.sym_out;
+				defobj = req.defobj_out;
+				break;
+			}
+		}
+
+		if (srcobj == NULL) {
+			_rtld_error("Undefined symbol \"%s\" "
+				    " referenced from COPY"
+				    " relocation in %s", name, dstobj->path);
+			return (-1);
+		}
+
+		srcaddr = (const void *) (defobj->relocbase+srcsym->st_value);
+		memcpy(dstaddr, srcaddr, size);
+		dbg("copy_reloc: src=%p,dst=%p,size=%zd\n",srcaddr,dstaddr,size);
+	}
+
+	return (0);
+}
+
+
+/*
+ * Perform early relocation of the run-time linker image
+ */
+void
+reloc_non_plt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+	const Elf_Rela *rela = 0, *relalim;
+	Elf_Addr relasz = 0;
+	Elf_Addr *where;
+
+	/*
+	 * Extract the rela/relasz values from the dynamic section
+	 */
+	for (; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_RELA:
+			rela = (const Elf_Rela *)(relocbase+dynp->d_un.d_ptr);
+			break;
+		case DT_RELASZ:
+			relasz = dynp->d_un.d_val;
+			break;
+		}
+	}
+
+	/*
+	 * Relocate these values
+	 */
+	relalim = (const Elf_Rela *)((caddr_t)rela + relasz);
+	for (; rela < relalim; rela++) {
+		where = (Elf_Addr *)(relocbase + rela->r_offset);
+		*where = (Elf_Addr)(relocbase + rela->r_addend);
+	}
+}
+
+
+/*
+ * Relocate a non-PLT object with addend.
+ */
+static int
+reloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
+    SymCache *cache, int flags, RtldLockState *lockstate)
+{
+	Elf_Addr        *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	const Elf_Sym   *def;
+	const Obj_Entry *defobj;
+	Elf_Addr         tmp;
+
+	switch (ELF_R_TYPE(rela->r_info)) {
+
+	case R_PPC_NONE:
+		break;
+
+        case R_PPC64_UADDR64:    /* doubleword64 S + A */
+        case R_PPC64_ADDR64:
+        case R_PPC_GLOB_DAT:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+		if (def == NULL) {
+			return (-1);
+		}
+
+                tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                    rela->r_addend);
+
+		/* Don't issue write if unnecessary; avoid COW page fault */
+                if (*where != tmp) {
+                        *where = tmp;
+		}
+                break;
+
+        case R_PPC_RELATIVE:  /* doubleword64 B + A */
+		tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
+
+		/* As above, don't issue write unnecessarily */
+		if (*where != tmp) {
+			*where = tmp;
+		}
+		break;
+
+	case R_PPC_COPY:
+		/*
+		 * These are deferred until all other relocations
+		 * have been done.  All we do here is make sure
+		 * that the COPY relocation is not in a shared
+		 * library.  They are allowed only in executable
+		 * files.
+		 */
+		if (!obj->mainprog) {
+			_rtld_error("%s: Unexpected R_COPY "
+				    " relocation in shared library",
+				    obj->path);
+			return (-1);
+		}
+		break;
+
+	case R_PPC_JMP_SLOT:
+		/*
+		 * These will be handled by the plt/jmpslot routines
+		 */
+		break;
+
+	case R_PPC64_DTPMOD64:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+
+		if (def == NULL)
+			return (-1);
+
+		*where = (Elf_Addr) defobj->tlsindex;
+
+		break;
+
+	case R_PPC64_TPREL64:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+
+		if (def == NULL)
+			return (-1);
+
+		/*
+		 * We lazily allocate offsets for static TLS as we
+		 * see the first relocation that references the
+		 * TLS block. This allows us to support (small
+		 * amounts of) static TLS in dynamically loaded
+		 * modules. If we run out of space, we generate an
+		 * error.
+		 */
+		if (!defobj->tls_done) {
+			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+				_rtld_error("%s: No space available for static "
+				    "Thread Local Storage", obj->path);
+				return (-1);
+			}
+		}
+
+		*(Elf_Addr **)where = *where * sizeof(Elf_Addr)
+		    + (Elf_Addr *)(def->st_value + rela->r_addend 
+		    + defobj->tlsoffset - TLS_TP_OFFSET);
+		
+		break;
+		
+	case R_PPC64_DTPREL64:
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    flags, cache, lockstate);
+
+		if (def == NULL)
+			return (-1);
+
+		*where += (Elf_Addr)(def->st_value + rela->r_addend 
+		    - TLS_DTV_OFFSET);
+
+		break;
+		
+	default:
+		_rtld_error("%s: Unsupported relocation type %ld"
+			    " in non-PLT relocations\n", obj->path,
+			    ELF_R_TYPE(rela->r_info));
+		return (-1);
+        }
+	return (0);
+}
+
+
+/*
+ * Process non-PLT relocations
+ */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
+    RtldLockState *lockstate)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+	SymCache *cache;
+	int bytes = obj->dynsymcount * sizeof(SymCache);
+	int r = -1;
+
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
+	/*
+	 * The dynamic loader may be called from a thread, we have
+	 * limited amounts of stack available so we cannot use alloca().
+	 */
+	if (obj != obj_rtld) {
+		cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON,
+		    -1, 0);
+		if (cache == MAP_FAILED)
+			cache = NULL;
+	} else
+		cache = NULL;
+
+	/*
+	 * From the SVR4 PPC ABI:
+	 * "The PowerPC family uses only the Elf32_Rela relocation
+	 *  entries with explicit addends."
+	 */
+	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
+	for (rela = obj->rela; rela < relalim; rela++) {
+		if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags,
+		    lockstate) < 0)
+			goto done;
+	}
+	r = 0;
+done:
+	if (cache)
+		munmap(cache, bytes);
+
+	/* Synchronize icache for text seg in case we made any changes */
+	__syncicache(obj->mapbase, obj->textsize);
+
+	return (r);
+}
+
+
+/*
+ * Initialise a PLT slot to the resolving trampoline
+ */
+static int
+reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
+{
+	Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	Elf_Addr *glink;
+	long reloff;
+
+	reloff = rela - obj->pltrela;
+
+	if (obj->priv == NULL)
+		obj->priv = xmalloc(obj->pltrelasize);
+	glink = obj->priv + reloff*sizeof(Elf_Addr)*2;
+
+	dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%p", (void *)where, reloff, glink);
+
+	memcpy(where, _rtld_bind_start, sizeof(struct funcdesc));
+	((struct funcdesc *)(where))->env = (Elf_Addr)glink;
+	*(glink++) = (Elf_Addr)obj;
+	*(glink++) = reloff*sizeof(Elf_Rela);
+
+	return (0);
+}
+
+
+/*
+ * Process the PLT relocations.
+ */
+int
+reloc_plt(Obj_Entry *obj)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+
+	if (obj->pltrelasize != 0) {
+		relalim = (const Elf_Rela *)((char *)obj->pltrela +
+		    obj->pltrelasize);
+		for (rela = obj->pltrela;  rela < relalim;  rela++) {
+			assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT);
+
+			if (reloc_plt_object(obj, rela) < 0) {
+				return (-1);
+			}
+		}
+	}
+
+	return (0);
+}
+
+
+/*
+ * LD_BIND_NOW was set - force relocation for all jump slots
+ */
+int
+reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
+{
+	const Obj_Entry *defobj;
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+	const Elf_Sym *def;
+	Elf_Addr *where;
+	Elf_Addr target;
+
+	relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
+	for (rela = obj->pltrela; rela < relalim; rela++) {
+		assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT);
+		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+		    SYMLOOK_IN_PLT | flags, NULL, lockstate);
+		if (def == NULL) {
+			dbg("reloc_jmpslots: sym not found");
+			return (-1);
+		}
+
+		target = (Elf_Addr)(defobj->relocbase + def->st_value);
+
+#if 0
+		/* PG XXX */
+		dbg("\"%s\" in \"%s\" --> %p in \"%s\"",
+		    defobj->strtab + def->st_name, basename(obj->path),
+		    (void *)target, basename(defobj->path));
+#endif
+
+		if (def == &sym_zero) {
+			/* Zero undefined weak symbols */
+			bzero(where, sizeof(struct funcdesc));
+		} else {
+			reloc_jmpslot(where, target, defobj, obj,
+			    (const Elf_Rel *) rela);
+		}
+	}
+
+	obj->jmpslots_done = true;
+
+	return (0);
+}
+
+
+/*
+ * Update the value of a PLT jump slot.
+ */
+Elf_Addr
+reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
+	      const Obj_Entry *obj, const Elf_Rel *rel)
+{
+	dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)",
+	    (void *)wherep, (void *)target, *(Elf_Addr *)target,
+	    (Elf_Addr)defobj->relocbase);
+
+	/*
+	 * At the PLT entry pointed at by `wherep', construct
+	 * a direct transfer to the now fully resolved function
+	 * address.
+	 */
+
+	memcpy(wherep, (void *)target, sizeof(struct funcdesc));
+	if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) {
+		/*
+		 * XXX: It is possible (e.g. LD_BIND_NOW) that the function
+		 * descriptor we are copying has not yet been relocated.
+		 * If this happens, fix it.
+		 */
+
+		((struct funcdesc *)(wherep))->addr +=
+		    (Elf_Addr)defobj->relocbase;
+		((struct funcdesc *)(wherep))->toc +=
+		    (Elf_Addr)defobj->relocbase;
+	}
+
+	__asm __volatile("dcbst 0,%0; sync" :: "r"(wherep) : "memory");
+
+	return (target);
+}
+
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, int flags,
+    struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+void
+init_pltgot(Obj_Entry *obj)
+{
+}
+
+void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+
+}
+
+void
+pre_init(void)
+{
+
+}
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+	Elf_Addr **tp;
+
+	/*
+	* Fix the size of the static TLS block by using the maximum
+	* offset allocated so far and adding a bit for dynamic modules to
+	* use.
+	*/
+
+	tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
+
+	tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16) 
+	    + TLS_TP_OFFSET + TLS_TCB_SIZE);
+
+	__asm __volatile("mr 13,%0" :: "r"(tp));
+}
+
+void*
+__tls_get_addr(tls_index* ti)
+{
+	Elf_Addr **tp;
+	char *p;
+
+	__asm __volatile("mr %0,13" : "=r"(tp));
+	p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET 
+	    - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset);
+
+	return (p + TLS_DTV_OFFSET);
+}


Property changes on: trunk/libexec/rtld-elf/powerpc64/reloc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc64/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/powerpc64/rtld_machdep.h	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc64/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,89 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999, 2000 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/powerpc64/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
+ */
+
+#ifndef RTLD_MACHDEP_H
+#define RTLD_MACHDEP_H	1
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+
+struct Struct_Obj_Entry;
+
+/* Return the address of the .dynamic section in the dynamic linker. */
+#define rtld_dynamic(obj)    (&_DYNAMIC)
+
+Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
+		       const struct Struct_Obj_Entry *defobj,
+		       const struct Struct_Obj_Entry *obj,
+		       const Elf_Rel *rel);
+
+#define make_function_pointer(def, defobj) \
+	((defobj)->relocbase + (def)->st_value)
+
+#define call_initfini_pointer(obj, target) \
+	(((InitFunc)(target))())
+
+#define call_init_pointer(obj, target) \
+	(((InitArrFunc)(target))(main_argc, main_argv, environ))
+
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(void))ptr)())
+
+/*
+ * Lazy binding entry point, called via PLT.
+ */
+void _rtld_bind_start(void);
+
+/*
+ * TLS
+ */
+
+#define TLS_TP_OFFSET	0x7000
+#define TLS_DTV_OFFSET	0x8000
+#define TLS_TCB_SIZE	16
+
+#define round(size, align) \
+    (((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+    round(16, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+    round(prev_offset + prev_size, align)
+#define calculate_tls_end(off, size)    ((off) + (size))
+ 
+typedef struct {
+	unsigned long ti_module;
+	unsigned long ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr(tls_index* ti);
+
+#define	RTLD_DEFAULT_STACK_PF_EXEC	PF_X
+#define	RTLD_DEFAULT_STACK_EXEC		PROT_EXEC
+
+#endif


Property changes on: trunk/libexec/rtld-elf/powerpc64/rtld_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/libexec/rtld-elf/powerpc64/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/powerpc64/rtld_start.S	                        (rev 0)
+++ trunk/libexec/rtld-elf/powerpc64/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -0,0 +1,163 @@
+/* $MidnightBSD$ */
+/*      $NetBSD: rtld_start.S,v 1.4 2001/09/26 04:06:43 mycroft Exp $   */
+
+/*-
+ * Copyright (C) 1998   Tsubai Masanari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/libexec/rtld-elf/powerpc64/rtld_start.S 218824 2011-02-18 21:44:53Z nwhitehorn $
+ */
+
+#include <machine/asm.h>
+
+.extern _GLOBAL_OFFSET_TABLE_
+.extern _DYNAMIC
+
+_ENTRY(_rtld_start)
+	stdu    %r1,-144(%r1)	/* 16-byte aligned stack for reg saves +
+				exit_proc & obj _rtld args +
+				backchain & lrsave stack frame */
+	std     %r3,96(%r1)	/*  argc */
+	std     %r4,104(%r1)	/*  argv */
+	std     %r5,112(%r1)	/*  envp */
+/*	std     %r6,120(%r1)   *//*  obj (always 0) */
+/*	std     %r7,128(%r1)   *//*  cleanup (always 0) */
+	std     %r8,136(%r1)	/*  ps_strings */
+
+	/*
+	 * Perform initial relocation of ld-elf.so. Not as easy as it
+	 * sounds.
+	 *  - perform small forward branch to put PC into link reg
+	 *  - use link-time constants to determine offset to the
+	 *    _DYNAMIC section and the GOT. Add these to the PC to
+	 *    convert to absolute addresses.
+	 *  - call reloc_non_plt_self() to fix up ld-elf.so's relocations
+	 */
+
+	bl	1f
+	.llong	_DYNAMIC-.
+1:
+	mflr	%r3		/* PC value at .llong */
+	ld	%r4,0(%r3)	/* offset to _DYNAMIC */
+	add	%r3,%r4,%r3	/* r3 = &_DYNAMIC, absolute value */
+
+	ld	%r4,-0x8000(%r2) /* First TOC entry is TOC base */
+	subf	%r4,%r4,%r2	/* Subtract from real TOC base to get base */
+
+	bl	reloc_non_plt_self /* reloc_non_plt_self(&_DYNAMIC,base) */
+	nop
+
+	/*
+	 * The _rtld() function likes to see a stack layout containing
+	 * { argc, argv[0], argv[1] ... argv[N], 0, env[0], ... , env[N] }
+	 * Since the PowerPC stack was 16-byte aligned at exec time, the
+	 * original stack layout has to be found by moving back a word
+	 * from the argv pointer.
+	 */
+	ld	%r4,104(%r1)
+        addi    %r3,%r4,-8	/* locate argc ptr, &argv[-1] */
+	addi	%r4,%r1,128	/* &exit_proc on stack */
+	addi	%r5,%r1,120	/* &obj_main on stack */
+
+	bl      _rtld		/* &_start = _rtld(sp, &exit_proc, &obj_main)*/
+	nop
+	ld	%r2,8(%r3)
+	ld	%r11,16(%r3)
+	ld	%r3,0(%r3)
+	mtlr    %r3
+
+	/*
+	 * Restore args, with new obj/exit proc
+	 */
+	ld      %r3,96(%r1)     /* argc */
+	ld      %r4,104(%r1)	/* argv */
+	ld      %r5,112(%r1)	/* envp */
+	ld      %r6,120(%r1)	/* obj */
+	ld      %r7,128(%r1)	/* exit proc */
+	ld      %r8,136(%r1)	/* ps_strings */
+
+	blrl	/* _start(argc, argv, envp, obj, cleanup, ps_strings) */
+
+	li      %r0,1		/* _exit() */
+	sc
+
+/*
+ * _rtld_bind_start()
+ *
+ * Call into the MI binder. This routine is reached via the PLT call cell
+ * On entry, %r11 contains a pointer to the (object, relocation) tuple.
+ *
+ * Save all registers, call into the binder to resolve and fixup the external
+ * routine, and then transfer to the external routine on return.
+ */
+	.globl  _rtld_bind
+
+_ENTRY(_rtld_bind_start)
+	mflr    %r0
+	std     %r0,16(%r1)		# save lr
+	mfcr    %r0
+	std     %r0,8(%r1)		# save cr
+
+	stdu    %r1,-48-12*8(%r1)	# stack space for 8 regs + header
+					#   + 2 save regs
+	std	%r3,64+0*8(%r1)		# save r3-r31
+	std	%r4,64+1*8(%r1)
+	std	%r5,64+2*8(%r1)
+	std	%r6,64+3*8(%r1)
+	std	%r7,64+4*8(%r1)
+	std	%r8,64+5*8(%r1)
+	std	%r9,64+6*8(%r1)
+	std	%r10,64+7*8(%r1)
+	std	%r12,64+8*8(%r1)
+
+	ld	%r3,0(%r11)
+	ld	%r4,8(%r11)
+	bl      _rtld_bind		# target addr = _rtld_bind(obj, reloff)
+	nop
+
+	ld	%r2,8(%r3)
+	ld	%r11,16(%r3)
+	ld	%r3,0(%r3)
+	mtctr   %r3			# move absolute target addr into ctr
+
+	ld	%r3,64+0*8(%r1)		# restore r3-r31
+	ld	%r4,64+1*8(%r1)
+	ld	%r5,64+2*8(%r1)
+	ld	%r6,64+3*8(%r1)
+	ld	%r7,64+4*8(%r1)
+	ld	%r8,64+5*8(%r1)
+	ld	%r9,64+6*8(%r1)
+	ld	%r10,64+7*8(%r1)
+	ld	%r12,64+8*8(%r1)
+
+	ld	%r1,0(%r1)		# restore stack
+	ld	%r0,8(%r1)		# restore cr
+	mtcr    %r0
+	ld	%r0,16(%r1)		# restore lr
+	mtlr    %r0
+
+	bctr				# jump to target
+
+	.section .note.GNU-stack,"",%progbits


Property changes on: trunk/libexec/rtld-elf/powerpc64/rtld_start.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/rtld.1
===================================================================
--- trunk/libexec/rtld-elf/rtld.1	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld.1	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+.\" $MidnightBSD$
 .\" Copyright (c) 1995 Paul Kranenburg
 .\" All rights reserved.
 .\"
@@ -26,7 +27,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: stable/10/libexec/rtld-elf/rtld.1 238471 2012-07-15 10:53:48Z kib $
 .\"
 .Dd June 28, 2012
 .Dt RTLD 1


Property changes on: trunk/libexec/rtld-elf/rtld.1
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/rtld.c
===================================================================
--- trunk/libexec/rtld-elf/rtld.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
  * Copyright 2003 Alexander Kabaev <kan at FreeBSD.ORG>.
@@ -25,7 +26,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/rtld.c 331206 2018-03-19 14:28:58Z marius $
  */
 
 /*
@@ -34,10 +35,6 @@
  * John Polstra <jdp at polstra.com>.
  */
 
-#ifndef __GNUC__
-#error "GCC is needed to compile this file"
-#endif
-
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <sys/mman.h>
@@ -78,7 +75,6 @@
  * Function declarations.
  */
 static const char *basename(const char *);
-static void die(void) __dead2;
 static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **,
     const Elf_Dyn **, const Elf_Dyn **);
 static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *,
@@ -97,9 +93,10 @@
 static char *find_library(const char *, const Obj_Entry *);
 static const char *gethints(bool);
 static void init_dag(Obj_Entry *);
+static void init_pagesizes(Elf_Auxinfo **aux_info);
 static void init_rtld(caddr_t, Elf_Auxinfo **);
 static void initlist_add_neededs(Needed_Entry *, Objlist *);
-static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *);
+static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *);
 static void linkmap_add(Obj_Entry *);
 static void linkmap_delete(Obj_Entry *);
 static void load_filtees(Obj_Entry *, int flags, RtldLockState *);
@@ -108,6 +105,7 @@
 static int load_preload_objects(void);
 static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int);
 static void map_stacks_exec(RtldLockState *);
+static int obj_enforce_relro(Obj_Entry *);
 static Obj_Entry *obj_from_addr(const void *);
 static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *);
 static void objlist_call_init(Objlist *, RtldLockState *);
@@ -116,6 +114,7 @@
 static void objlist_init(Objlist *);
 static void objlist_push_head(Objlist *, Obj_Entry *);
 static void objlist_push_tail(Objlist *, Obj_Entry *);
+static void objlist_put_after(Objlist *, Obj_Entry *, Obj_Entry *);
 static void objlist_remove(Objlist *, Obj_Entry *);
 static void *path_enumerate(const char *, path_enum_proc, void *);
 static int relocate_object_dag(Obj_Entry *root, bool bind_now,
@@ -145,8 +144,10 @@
 static void unload_object(Obj_Entry *);
 static void unref_dag(Obj_Entry *);
 static void ref_dag(Obj_Entry *);
-static char *origin_subst_one(char *, const char *, const char *, bool);
-static char *origin_subst(char *, const char *);
+static char *origin_subst_one(Obj_Entry *, char *, const char *,
+    const char *, bool);
+static char *origin_subst(Obj_Entry *, char *);
+static bool obj_resolve_origin(Obj_Entry *obj);
 static void preinit_main(void);
 static int  rtld_verify_versions(const Objlist *);
 static int  rtld_verify_object_versions(Obj_Entry *);
@@ -159,13 +160,14 @@
 static bool matched_symbol(SymLook *, const Obj_Entry *, Sym_Match_Result *,
     const unsigned long);
 
-void r_debug_state(struct r_debug *, struct link_map *) __noinline;
+void r_debug_state(struct r_debug *, struct link_map *) __noinline __exported;
+void _r_debug_postinit(struct link_map *) __noinline __exported;
 
 /*
  * Data declarations.
  */
 static char *error_message;	/* Message for dlerror(), or NULL */
-struct r_debug r_debug;		/* for GDB; */
+struct r_debug r_debug __exported;	/* for GDB; */
 static bool libmap_disable;	/* Disable libmap */
 static bool ld_loadfltr;	/* Immediate filters processing */
 static char *libmap_override;	/* Maps to use in addition to libmap.conf */
@@ -180,12 +182,11 @@
 static char *ld_elf_hints_path;	/* Environment variable for alternative hints path */
 static char *ld_tracing;	/* Called from ldd to print libs */
 static char *ld_utrace;		/* Use utrace() to log events. */
-static Obj_Entry *obj_list;	/* Head of linked list of shared objects */
-static Obj_Entry **obj_tail;	/* Link field of last object in list */
+static struct obj_entry_q obj_list;	/* Queue of all loaded objects */
 static Obj_Entry *obj_main;	/* The main program shared object */
 static Obj_Entry obj_rtld;	/* The dynamic linker shared object */
 static unsigned int obj_count;	/* Number of objects in obj_list */
-static unsigned int obj_loads;	/* Number of objects in obj_list */
+static unsigned int obj_loads;	/* Number of loads of objects (gen count) */
 
 static Objlist list_global =	/* Objects dlopened with RTLD_GLOBAL */
   STAILQ_HEAD_INITIALIZER(list_global);
@@ -204,8 +205,26 @@
 #define	RTLD_IS_DYNAMIC()	(&_DYNAMIC != NULL)
 #endif
 
-int osreldate, pagesize;
+int dlclose(void *) __exported;
+char *dlerror(void) __exported;
+void *dlopen(const char *, int) __exported;
+void *fdlopen(int, int) __exported;
+void *dlsym(void *, const char *) __exported;
+dlfunc_t dlfunc(void *, const char *) __exported;
+void *dlvsym(void *, const char *, const char *) __exported;
+int dladdr(const void *, Dl_info *) __exported;
+void dllockinit(void *, void *(*)(void *), void (*)(void *), void (*)(void *),
+    void (*)(void *), void (*)(void *), void (*)(void *)) __exported;
+int dlinfo(void *, int , void *) __exported;
+int dl_iterate_phdr(__dl_iterate_hdr_callback, void *) __exported;
+int _rtld_addr_phdr(const void *, struct dl_phdr_info *) __exported;
+int _rtld_get_stack_prot(void) __exported;
+int _rtld_is_dlopened(void *) __exported;
+void _rtld_error(const char *, ...) __exported;
 
+int npagesizes, osreldate;
+size_t *pagesizes;
+
 long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 
 static int stack_prot = PROT_READ | PROT_WRITE | RTLD_DEFAULT_STACK_EXEC;
@@ -230,10 +249,11 @@
 size_t tls_last_offset;		/* Static TLS offset of last module */
 size_t tls_last_size;		/* Static TLS size of last module */
 size_t tls_static_space;	/* Static TLS space allocated */
+size_t tls_static_max_align;
 int tls_dtv_generation = 1;	/* Used to detect when dtv size changes  */
 int tls_max_index = 1;		/* Largest module index allocated */
 
-bool ld_library_path_rpath = true;
+bool ld_library_path_rpath = false;
 
 /*
  * Fill in a DoneList with an allocation large enough to hold all of
@@ -256,6 +276,8 @@
 #define	UTRACE_PRELOAD_FINISHED		8
 #define	UTRACE_INIT_CALL		9
 #define	UTRACE_FINI_CALL		10
+#define	UTRACE_DLSYM_START		11
+#define	UTRACE_DLSYM_STOP		12
 
 struct utrace_rtld {
 	char sig[4];			/* 'RTLD' */
@@ -322,7 +344,8 @@
     const char *argv0;
     Objlist_Entry *entry;
     Obj_Entry *obj;
-    Obj_Entry **preload_tail;
+    Obj_Entry *preload_tail;
+    Obj_Entry *last_interposer;
     Objlist initlist;
     RtldLockState lockstate;
     char *library_path_rpath;
@@ -399,7 +422,7 @@
 	    unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") ||
 	    unsetenv(LD_ "LOADFLTR") || unsetenv(LD_ "LIBRARY_PATH_RPATH")) {
 		_rtld_error("environment corrupt; aborting");
-		die();
+		rtld_die();
 	}
     }
     ld_debug = getenv(LD_ "DEBUG");
@@ -447,8 +470,8 @@
 	obj_main = map_object(fd, argv0, NULL);
 	close(fd);
 	if (obj_main == NULL)
-	    die();
-	max_stack_flags = obj->stack_flags;
+	    rtld_die();
+	max_stack_flags = obj_main->stack_flags;
     } else {				/* Main program already loaded. */
 	const Elf_Phdr *phdr;
 	int phnum;
@@ -464,7 +487,7 @@
 	assert(aux_info[AT_ENTRY] != NULL);
 	entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr;
 	if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL)
-	    die();
+	    rtld_die();
     }
 
     if (aux_info[AT_EXECPATH] != 0) {
@@ -492,6 +515,7 @@
       aux_info[AT_STACKPROT]->a_un.a_val != 0)
 	    stack_prot = aux_info[AT_STACKPROT]->a_un.a_val;
 
+#ifndef COMPAT_32BIT
     /*
      * Get the actual dynamic linker pathname from the executable if
      * possible.  (It should always be possible.)  That ensures that
@@ -504,6 +528,7 @@
 	obj_rtld.path = xstrdup(obj_main->interp);
         __progname = obj_rtld.path;
     }
+#endif
 
     digest_dynamic(obj_main, 0);
     dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d",
@@ -514,8 +539,7 @@
     linkmap_add(&obj_rtld);
 
     /* Link the main program into the list of objects. */
-    *obj_tail = obj_main;
-    obj_tail = &obj_main->next;
+    TAILQ_INSERT_HEAD(&obj_list, obj_main, next);
     obj_count++;
     obj_loads++;
 
@@ -529,22 +553,30 @@
 
     dbg("loading LD_PRELOAD libraries");
     if (load_preload_objects() == -1)
-	die();
-    preload_tail = obj_tail;
+	rtld_die();
+    preload_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q));
 
     dbg("loading needed objects");
     if (load_needed_objects(obj_main, 0) == -1)
-	die();
+	rtld_die();
 
     /* Make a list of all objects loaded at startup. */
-    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
-	objlist_push_tail(&list_main, obj);
+    last_interposer = obj_main;
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
+	if (obj->z_interpose && obj != obj_main) {
+	    objlist_put_after(&list_main, last_interposer, obj);
+	    last_interposer = obj;
+	} else {
+	    objlist_push_tail(&list_main, obj);
+	}
     	obj->refcount++;
     }
 
     dbg("checking for required versions");
     if (rtld_verify_versions(&list_main) == -1 && !ld_tracing)
-	die();
+	rtld_die();
 
     if (ld_tracing) {		/* We're done */
 	trace_loaded_objects(obj_main);
@@ -573,12 +605,16 @@
     if (relocate_objects(obj_main,
       ld_bind_now != NULL && *ld_bind_now != '\0',
       &obj_rtld, SYMLOOK_EARLY, NULL) == -1)
-	die();
+	rtld_die();
 
     dbg("doing copy relocations");
     if (do_copy_relocations(obj_main) == -1)
-	die();
+	rtld_die();
 
+    dbg("enforcing main obj relro");
+    if (obj_enforce_relro(obj_main) == -1)
+	rtld_die();
+
     if (getenv(LD_ "DUMP_REL_POST") != NULL) {
        dump_relocations(obj_main);
        exit (0);
@@ -590,7 +626,7 @@
      * might be the subject for relocations.
      */
     dbg("initializing initial thread local storage");
-    allocate_initial_tls(obj_list);
+    allocate_initial_tls(globallist_curr(TAILQ_FIRST(&obj_list)));
 
     dbg("initializing key program variables");
     set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : "");
@@ -599,17 +635,19 @@
 
     /* Make a list of init functions to call. */
     objlist_init(&initlist);
-    initlist_add_objects(obj_list, preload_tail, &initlist);
+    initlist_add_objects(globallist_curr(TAILQ_FIRST(&obj_list)),
+      preload_tail, &initlist);
 
     r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */
 
     map_stacks_exec(NULL);
+    ifunc_init(aux);
 
     dbg("resolving ifuncs");
     if (resolve_objects_ifunc(obj_main,
       ld_bind_now != NULL && *ld_bind_now != '\0', SYMLOOK_EARLY,
       NULL) == -1)
-	die();
+	rtld_die();
 
     if (!obj_main->crt_no_init) {
 	/*
@@ -622,13 +660,22 @@
 	    obj_main->fini_array = (Elf_Addr)NULL;
     }
 
+    /*
+     * Execute MD initializers required before we call the objects'
+     * init functions.
+     */
+    pre_init();
+
     wlock_acquire(rtld_bind_lock, &lockstate);
     if (obj_main->crt_no_init)
 	preinit_main();
     objlist_call_init(&initlist, &lockstate);
+    _r_debug_postinit(&obj_main->linkmap);
     objlist_clear(&initlist);
     dbg("loading filtees");
-    for (obj = obj_list->next; obj != NULL; obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (ld_loadfltr || obj->z_loadfltr)
 	    load_filtees(obj, 0, &lockstate);
     }
@@ -649,7 +696,7 @@
 	Elf_Addr target;
 
 	ptr = (void *)make_function_pointer(def, obj);
-	target = ((Elf_Addr (*)(void))ptr)();
+	target = call_ifunc_resolver(ptr);
 	return ((void *)target);
 }
 
@@ -672,10 +719,10 @@
 	rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
 
     where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
-    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
-	&lockstate);
+    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, SYMLOOK_IN_PLT,
+	NULL, &lockstate);
     if (def == NULL)
-	die();
+	rtld_die();
     if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC)
 	target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
     else
@@ -748,8 +795,8 @@
 static struct utsname uts;
 
 static char *
-origin_subst_one(char *real, const char *kw, const char *subst,
-    bool may_free)
+origin_subst_one(Obj_Entry *obj, char *real, const char *kw,
+    const char *subst, bool may_free)
 {
 	char *p, *p1, *res, *resp;
 	int subst_len, kw_len, subst_count, old_len, new_len;
@@ -768,9 +815,15 @@
 
 	/*
 	 * If the keyword is not found, just return.
+	 *
+	 * Return non-substituted string if resolution failed.  We
+	 * cannot do anything more reasonable, the failure mode of the
+	 * caller is unresolved library anyway.
 	 */
-	if (subst_count == 0)
+	if (subst_count == 0 || (obj != NULL && !obj_resolve_origin(obj)))
 		return (may_free ? real : xstrdup(real));
+	if (obj != NULL)
+		subst = obj->origin_path;
 
 	/*
 	 * There is indeed something to substitute.  Calculate the
@@ -807,10 +860,12 @@
 }
 
 static char *
-origin_subst(char *real, const char *origin_path)
+origin_subst(Obj_Entry *obj, char *real)
 {
 	char *res1, *res2, *res3, *res4;
 
+	if (obj == NULL || !trust)
+		return (xstrdup(real));
 	if (uts.sysname[0] == '\0') {
 		if (uname(&uts) != 0) {
 			_rtld_error("utsname failed: %d", errno);
@@ -817,15 +872,15 @@
 			return (NULL);
 		}
 	}
-	res1 = origin_subst_one(real, "$ORIGIN", origin_path, false);
-	res2 = origin_subst_one(res1, "$OSNAME", uts.sysname, true);
-	res3 = origin_subst_one(res2, "$OSREL", uts.release, true);
-	res4 = origin_subst_one(res3, "$PLATFORM", uts.machine, true);
+	res1 = origin_subst_one(obj, real, "$ORIGIN", NULL, false);
+	res2 = origin_subst_one(NULL, res1, "$OSNAME", uts.sysname, true);
+	res3 = origin_subst_one(NULL, res2, "$OSREL", uts.release, true);
+	res4 = origin_subst_one(NULL, res3, "$PLATFORM", uts.machine, true);
 	return (res4);
 }
 
-static void
-die(void)
+void
+rtld_die(void)
 {
     const char *msg = dlerror();
 
@@ -852,7 +907,6 @@
     const Elf32_Word *hashval;
     Elf32_Word bkt, nmaskwords;
     int bloom_size32;
-    bool nmw_power2;
     int plttype = DT_REL;
 
     *dyn_rpath = NULL;
@@ -962,8 +1016,6 @@
 		obj->symndx_gnu = hashtab[1];
 		nmaskwords = hashtab[2];
 		bloom_size32 = (__ELF_WORD_SIZE / 32) * nmaskwords;
-		/* Number of bitmask words is required to be power of 2 */
-		nmw_power2 = ((nmaskwords & (nmaskwords - 1)) == 0);
 		obj->maskwords_bm_gnu = nmaskwords - 1;
 		obj->shift2_gnu = hashtab[3];
 		obj->bloom_gnu = (Elf_Addr *) (hashtab + 4);
@@ -970,8 +1022,9 @@
 		obj->buckets_gnu = hashtab + 4 + bloom_size32;
 		obj->chain_zero_gnu = obj->buckets_gnu + obj->nbuckets_gnu -
 		  obj->symndx_gnu;
-		obj->valid_hash_gnu = nmw_power2 && obj->nbuckets_gnu > 0 &&
-		  obj->buckets_gnu != NULL;
+		/* Number of bitmask words is required to be power of 2 */
+		obj->valid_hash_gnu = powerof2(nmaskwords) &&
+		    obj->nbuckets_gnu > 0 && obj->buckets_gnu != NULL;
 	    }
 	    break;
 
@@ -1078,7 +1131,6 @@
 
 #ifndef __mips__
 	case DT_DEBUG:
-	    /* XXX - not implemented yet */
 	    if (!early)
 		dbg("Filling in DT_DEBUG entry");
 	    ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug;
@@ -1086,7 +1138,7 @@
 #endif
 
 	case DT_FLAGS:
-		if ((dynp->d_un.d_val & DF_ORIGIN) && trust)
+		if (dynp->d_un.d_val & DF_ORIGIN)
 		    obj->z_origin = true;
 		if (dynp->d_un.d_val & DF_SYMBOLIC)
 		    obj->symbolic = true;
@@ -1111,11 +1163,7 @@
 		break;
 
 	case DT_MIPS_RLD_MAP:
-#ifdef notyet
-		if (!early)
-			dbg("Filling in DT_DEBUG entry");
-		((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug;
-#endif
+		*((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) &r_debug;
 		break;
 #endif
 
@@ -1122,10 +1170,10 @@
 	case DT_FLAGS_1:
 		if (dynp->d_un.d_val & DF_1_NOOPEN)
 		    obj->z_noopen = true;
-		if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust)
+		if (dynp->d_un.d_val & DF_1_ORIGIN)
 		    obj->z_origin = true;
-		/*if (dynp->d_un.d_val & DF_1_GLOBAL)
-		    XXX ;*/
+		if (dynp->d_un.d_val & DF_1_GLOBAL)
+		    obj->z_global = true;
 		if (dynp->d_un.d_val & DF_1_BIND_NOW)
 		    obj->bind_now = true;
 		if (dynp->d_un.d_val & DF_1_NODELETE)
@@ -1132,6 +1180,8 @@
 		    obj->z_nodelete = true;
 		if (dynp->d_un.d_val & DF_1_LOADFLTR)
 		    obj->z_loadfltr = true;
+		if (dynp->d_un.d_val & DF_1_INTERPOSE)
+		    obj->z_interpose = true;
 		if (dynp->d_un.d_val & DF_1_NODEFLIB)
 		    obj->z_nodeflib = true;
 	    break;
@@ -1171,30 +1221,33 @@
     }
 }
 
+static bool
+obj_resolve_origin(Obj_Entry *obj)
+{
+
+	if (obj->origin_path != NULL)
+		return (true);
+	obj->origin_path = xmalloc(PATH_MAX);
+	return (rtld_dirname_abs(obj->path, obj->origin_path) != -1);
+}
+
 static void
 digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath,
     const Elf_Dyn *dyn_soname, const Elf_Dyn *dyn_runpath)
 {
 
-    if (obj->z_origin && obj->origin_path == NULL) {
-	obj->origin_path = xmalloc(PATH_MAX);
-	if (rtld_dirname_abs(obj->path, obj->origin_path) == -1)
-	    die();
-    }
+	if (obj->z_origin && !obj_resolve_origin(obj))
+		rtld_die();
 
-    if (dyn_runpath != NULL) {
-	obj->runpath = (char *)obj->strtab + dyn_runpath->d_un.d_val;
-	if (obj->z_origin)
-	    obj->runpath = origin_subst(obj->runpath, obj->origin_path);
-    }
-    else if (dyn_rpath != NULL) {
-	obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val;
-	if (obj->z_origin)
-	    obj->rpath = origin_subst(obj->rpath, obj->origin_path);
-    }
-
-    if (dyn_soname != NULL)
-	object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val);
+	if (dyn_runpath != NULL) {
+		obj->runpath = (char *)obj->strtab + dyn_runpath->d_un.d_val;
+		obj->runpath = origin_subst(obj, obj->runpath);
+	} else if (dyn_rpath != NULL) {
+		obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val;
+		obj->rpath = origin_subst(obj, obj->rpath);
+	}
+	if (dyn_soname != NULL)
+		object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val);
 }
 
 static void
@@ -1336,9 +1389,10 @@
 {
     Obj_Entry *obj;
 
-    for (obj = obj_list;  obj != NULL;  obj = obj->next)
+    TAILQ_FOREACH(obj, &obj_list, next) {
 	if (obj == (Obj_Entry *) handle)
 	    break;
+    }
 
     if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) {
 	_rtld_error("Invalid shared object handle %p", handle);
@@ -1439,12 +1493,8 @@
 	      xname);
 	    return NULL;
 	}
-	if (objgiven && refobj->z_origin) {
-		return (origin_subst(__DECONST(char *, xname),
-		    refobj->origin_path));
-	} else {
-		return (xstrdup(xname));
-	}
+	return (origin_subst(__DECONST(Obj_Entry *, refobj),
+	  __DECONST(char *, xname)));
     }
 
     if (libmap_disable || !objgiven ||
@@ -1504,6 +1554,7 @@
     const Elf_Sym *ref;
     const Elf_Sym *def;
     const Obj_Entry *defobj;
+    const Ver_Entry *ve;
     SymLook req;
     const char *name;
     int res;
@@ -1523,6 +1574,7 @@
     name = refobj->strtab + ref->st_name;
     def = NULL;
     defobj = NULL;
+    ve = NULL;
 
     /*
      * We don't have to do a full scale lookup if the symbol is local.
@@ -1539,7 +1591,7 @@
 	}
 	symlook_init(&req, name);
 	req.flags = flags;
-	req.ventry = fetch_ventry(refobj, symnum);
+	ve = req.ventry = fetch_ventry(refobj, symnum);
 	req.lockstate = lockstate;
 	res = symlook_default(&req, refobj);
 	if (res == 0) {
@@ -1569,7 +1621,8 @@
 	}
     } else {
 	if (refobj != &obj_rtld)
-	    _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name);
+	    _rtld_error("%s: Undefined symbol \"%s%s%s\"", refobj->path, name,
+	      ve != NULL ? "@" : "", ve != NULL ? ve->name : "");
     }
     return def;
 }
@@ -1586,14 +1639,16 @@
 gethints(bool nostdlib)
 {
 	static char *hints, *filtered_path;
-	struct elfhints_hdr hdr;
+	static struct elfhints_hdr hdr;
 	struct fill_search_info_args sargs, hargs;
 	struct dl_serinfo smeta, hmeta, *SLPinfo, *hintinfo;
 	struct dl_serpath *SLPpath, *hintpath;
 	char *p;
+	struct stat hint_stat;
 	unsigned int SLPndx, hintndx, fndx, fcount;
 	int fd;
 	size_t flen;
+	uint32_t dl;
 	bool skip;
 
 	/* First call, read the hints file */
@@ -1601,21 +1656,40 @@
 		/* Keep from trying again in case the hints file is bad. */
 		hints = "";
 
-		if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
+		if ((fd = open(ld_elf_hints_path, O_RDONLY | O_CLOEXEC)) == -1)
 			return (NULL);
+
+		/*
+		 * Check of hdr.dirlistlen value against type limit
+		 * intends to pacify static analyzers.  Further
+		 * paranoia leads to checks that dirlist is fully
+		 * contained in the file range.
+		 */
 		if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
 		    hdr.magic != ELFHINTS_MAGIC ||
-		    hdr.version != 1) {
+		    hdr.version != 1 || hdr.dirlistlen > UINT_MAX / 2 ||
+		    fstat(fd, &hint_stat) == -1) {
+cleanup1:
 			close(fd);
+			hdr.dirlistlen = 0;
 			return (NULL);
 		}
+		dl = hdr.strtab;
+		if (dl + hdr.dirlist < dl)
+			goto cleanup1;
+		dl += hdr.dirlist;
+		if (dl + hdr.dirlistlen < dl)
+			goto cleanup1;
+		dl += hdr.dirlistlen;
+		if (dl > hint_stat.st_size)
+			goto cleanup1;
 		p = xmalloc(hdr.dirlistlen + 1);
+
 		if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
 		    read(fd, p, hdr.dirlistlen + 1) !=
-		    (ssize_t)hdr.dirlistlen + 1) {
+		    (ssize_t)hdr.dirlistlen + 1 || p[hdr.dirlistlen] != '\0') {
 			free(p);
-			close(fd);
-			return (NULL);
+			goto cleanup1;
 		}
 		hints = p;
 		close(fd);
@@ -1648,7 +1722,7 @@
 	hargs.serinfo = &hmeta;
 
 	path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs);
-	path_enumerate(p, fill_search_info, &hargs);
+	path_enumerate(hints, fill_search_info, &hargs);
 
 	SLPinfo = xmalloc(smeta.dls_size);
 	hintinfo = xmalloc(hmeta.dls_size);
@@ -1667,7 +1741,7 @@
 	hargs.strspace = (char *)&hintinfo->dls_serpath[hmeta.dls_cnt];
 
 	path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs);
-	path_enumerate(p, fill_search_info, &hargs);
+	path_enumerate(hints, fill_search_info, &hargs);
 
 	/*
 	 * Now calculate the difference between two sets, by excluding
@@ -1746,24 +1820,63 @@
     root->dag_inited = true;
 }
 
+Obj_Entry *
+globallist_curr(const Obj_Entry *obj)
+{
+
+	for (;;) {
+		if (obj == NULL)
+			return (NULL);
+		if (!obj->marker)
+			return (__DECONST(Obj_Entry *, obj));
+		obj = TAILQ_PREV(obj, obj_entry_q, next);
+	}
+}
+
+Obj_Entry *
+globallist_next(const Obj_Entry *obj)
+{
+
+	for (;;) {
+		obj = TAILQ_NEXT(obj, next);
+		if (obj == NULL)
+			return (NULL);
+		if (!obj->marker)
+			return (__DECONST(Obj_Entry *, obj));
+	}
+}
+
 static void
-process_nodelete(Obj_Entry *root)
+process_z(Obj_Entry *root)
 {
 	const Objlist_Entry *elm;
+	Obj_Entry *obj;
 
 	/*
-	 * Walk over object DAG and process every dependent object that
-	 * is marked as DF_1_NODELETE. They need to grow their own DAG,
-	 * which then should have its reference upped separately.
+	 * Walk over object DAG and process every dependent object
+	 * that is marked as DF_1_NODELETE or DF_1_GLOBAL. They need
+	 * to grow their own DAG.
+	 *
+	 * For DF_1_GLOBAL, DAG is required for symbol lookups in
+	 * symlook_global() to work.
+	 *
+	 * For DF_1_NODELETE, the DAG should have its reference upped.
 	 */
 	STAILQ_FOREACH(elm, &root->dagmembers, link) {
-		if (elm->obj != NULL && elm->obj->z_nodelete &&
-		    !elm->obj->ref_nodel) {
-			dbg("obj %s nodelete", elm->obj->path);
-			init_dag(elm->obj);
-			ref_dag(elm->obj);
-			elm->obj->ref_nodel = true;
+		obj = elm->obj;
+		if (obj == NULL)
+			continue;
+		if (obj->z_nodelete && !obj->ref_nodel) {
+			dbg("obj %s -z nodelete", obj->path);
+			init_dag(obj);
+			ref_dag(obj);
+			obj->ref_nodel = true;
 		}
+		if (obj->z_global && objlist_find(&list_global, obj) == NULL) {
+			dbg("obj %s -z global", obj->path);
+			objlist_push_tail(&list_global, obj);
+			init_dag(obj);
+		}
 	}
 }
 /*
@@ -1775,10 +1888,16 @@
 init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
 {
     Obj_Entry objtmp;	/* Temporary rtld object */
+    const Elf_Ehdr *ehdr;
     const Elf_Dyn *dyn_rpath;
     const Elf_Dyn *dyn_soname;
     const Elf_Dyn *dyn_runpath;
 
+#ifdef RTLD_INIT_PAGESIZES_EARLY
+    /* The page size is required by the dynamic memory allocator. */
+    init_pagesizes(aux_info);
+#endif
+
     /*
      * Conjure up an Obj_Entry structure for the dynamic linker.
      *
@@ -1808,15 +1927,21 @@
 
 	relocate_objects(&objtmp, true, &objtmp, 0, NULL);
     }
+    ehdr = (Elf_Ehdr *)mapbase;
+    objtmp.phdr = (Elf_Phdr *)((char *)mapbase + ehdr->e_phoff);
+    objtmp.phsize = ehdr->e_phnum * sizeof(objtmp.phdr[0]);
 
     /* Initialize the object list. */
-    obj_tail = &obj_list;
+    TAILQ_INIT(&obj_list);
 
     /* Now that non-local variables can be accesses, copy out obj_rtld. */
     memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld));
 
-    if (aux_info[AT_PAGESZ] != NULL)
-	    pagesize = aux_info[AT_PAGESZ]->a_un.a_val;
+#ifndef RTLD_INIT_PAGESIZES_EARLY
+    /* The page size is required by the dynamic memory allocator. */
+    init_pagesizes(aux_info);
+#endif
+
     if (aux_info[AT_OSRELDATE] != NULL)
 	    osreldate = aux_info[AT_OSRELDATE]->a_un.a_val;
 
@@ -1830,6 +1955,50 @@
 }
 
 /*
+ * Retrieve the array of supported page sizes.  The kernel provides the page
+ * sizes in increasing order.
+ */
+static void
+init_pagesizes(Elf_Auxinfo **aux_info)
+{
+	static size_t psa[MAXPAGESIZES];
+	int mib[2];
+	size_t len, size;
+
+	if (aux_info[AT_PAGESIZES] != NULL && aux_info[AT_PAGESIZESLEN] !=
+	    NULL) {
+		size = aux_info[AT_PAGESIZESLEN]->a_un.a_val;
+		pagesizes = aux_info[AT_PAGESIZES]->a_un.a_ptr;
+	} else {
+		len = 2;
+		if (sysctlnametomib("hw.pagesizes", mib, &len) == 0)
+			size = sizeof(psa);
+		else {
+			/* As a fallback, retrieve the base page size. */
+			size = sizeof(psa[0]);
+			if (aux_info[AT_PAGESZ] != NULL) {
+				psa[0] = aux_info[AT_PAGESZ]->a_un.a_val;
+				goto psa_filled;
+			} else {
+				mib[0] = CTL_HW;
+				mib[1] = HW_PAGESIZE;
+				len = 2;
+			}
+		}
+		if (sysctl(mib, len, psa, &size, NULL, 0) == -1) {
+			_rtld_error("sysctl for hw.pagesize(s) failed");
+			rtld_die();
+		}
+psa_filled:
+		pagesizes = psa;
+	}
+	npagesizes = size / sizeof(pagesizes[0]);
+	/* Discard any invalid entries at the end of the array. */
+	while (npagesizes > 0 && pagesizes[npagesizes - 1] == 0)
+		npagesizes--;
+}
+
+/*
  * Add the init functions from a needed object list (and its recursive
  * needed objects) to "list".  This is not used directly; it is a helper
  * function for initlist_add_objects().  The write lock must be held
@@ -1844,7 +2013,7 @@
 
     /* Process the current needed object. */
     if (needed->obj != NULL)
-	initlist_add_objects(needed->obj, &needed->obj->next, list);
+	initlist_add_objects(needed->obj, needed->obj, list);
 }
 
 /*
@@ -1857,8 +2026,9 @@
  * held when this function is called.
  */
 static void
-initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list)
+initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list)
 {
+    Obj_Entry *nobj;
 
     if (obj->init_scanned || obj->init_done)
 	return;
@@ -1865,8 +2035,9 @@
     obj->init_scanned = true;
 
     /* Recursively process the successor objects. */
-    if (&obj->next != tail)
-	initlist_add_objects(obj->next, tail, list);
+    nobj = globallist_next(obj);
+    if (nobj != NULL && obj != tail)
+	initlist_add_objects(nobj, tail, list);
 
     /* Recursively process the needed objects. */
     if (obj->needed != NULL)
@@ -1969,7 +2140,9 @@
 {
     Obj_Entry *obj;
 
-    for (obj = first;  obj != NULL;  obj = obj->next) {
+    for (obj = first; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
+	if (obj->marker)
+	    continue;
 	if (process_needed(obj, obj->needed, flags) == -1)
 	    return (-1);
     }
@@ -1980,6 +2153,7 @@
 load_preload_objects(void)
 {
     char *p = ld_preload;
+    Obj_Entry *obj;
     static const char delim[] = " \t:;";
 
     if (p == NULL)
@@ -1992,8 +2166,10 @@
 
 	savech = p[len];
 	p[len] = '\0';
-	if (load_object(p, -1, NULL, 0) == NULL)
+	obj = load_object(p, -1, NULL, 0);
+	if (obj == NULL)
 	    return -1;	/* XXX - cleanup */
+	obj->z_interpose = true;
 	p[len] = savech;
 	p += len;
 	p += strspn(p, delim);
@@ -2027,7 +2203,9 @@
     char *path;
 
     if (name != NULL) {
-	for (obj = obj_list->next;  obj != NULL;  obj = obj->next) {
+	TAILQ_FOREACH(obj, &obj_list, next) {
+	    if (obj->marker)
+		continue;
 	    if (object_match_name(obj, name))
 		return (obj);
 	}
@@ -2049,13 +2227,13 @@
      */
     fd = -1;
     if (fd_u == -1) {
-	if ((fd = open(path, O_RDONLY)) == -1) {
+	if ((fd = open(path, O_RDONLY | O_CLOEXEC)) == -1) {
 	    _rtld_error("Cannot open \"%s\"", path);
 	    free(path);
 	    return (NULL);
 	}
     } else {
-	fd = dup(fd_u);
+	fd = fcntl(fd_u, F_DUPFD_CLOEXEC, 0);
 	if (fd == -1) {
 	    _rtld_error("Cannot dup fd");
 	    free(path);
@@ -2068,9 +2246,12 @@
 	free(path);
 	return NULL;
     }
-    for (obj = obj_list->next;  obj != NULL;  obj = obj->next)
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (obj->ino == sb.st_ino && obj->dev == sb.st_dev)
 	    break;
+    }
     if (obj != NULL && name != NULL) {
 	object_add_name(obj, name);
 	free(path);
@@ -2137,8 +2318,8 @@
 	return (NULL);
     }
 
-    *obj_tail = obj;
-    obj_tail = &obj->next;
+    obj->dlopened = (flags & RTLD_LO_DLOPEN) != 0;
+    TAILQ_INSERT_TAIL(&obj_list, obj, next);
     obj_count++;
     obj_loads++;
     linkmap_add(obj);	/* for GDB & dlinfo() */
@@ -2159,7 +2340,9 @@
 {
     Obj_Entry *obj;
 
-    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (addr < (void *) obj->mapbase)
 	    continue;
 	if (addr < (void *) (obj->mapbase + obj->mapsize))
@@ -2285,8 +2468,11 @@
      * possibly initialized earlier if any of vectors called below
      * cause the change by using dlopen.
      */
-    for (obj = obj_list;  obj != NULL;  obj = obj->next)
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	obj->init_scanned = false;
+    }
 
     /*
      * Preserve the current error message since an init function might
@@ -2298,7 +2484,7 @@
 	    continue;
 	/*
 	 * Race: other thread might try to use this object before current
-	 * one completes the initilization. Not much can be done here
+	 * one completes the initialization. Not much can be done here
 	 * without better locking.
 	 */
 	elm->obj->init_done = true;
@@ -2382,6 +2568,23 @@
 }
 
 static void
+objlist_put_after(Objlist *list, Obj_Entry *listobj, Obj_Entry *obj)
+{
+	Objlist_Entry *elm, *listelm;
+
+	STAILQ_FOREACH(listelm, list, link) {
+		if (listelm->obj == listobj)
+			break;
+	}
+	elm = NEW(Objlist_Entry);
+	elm->obj = obj;
+	if (listelm != NULL)
+		STAILQ_INSERT_AFTER(list, listelm, elm, link);
+	else
+		STAILQ_INSERT_TAIL(list, elm, link);
+}
+
+static void
 objlist_remove(Objlist *list, Obj_Entry *obj)
 {
     Objlist_Entry *elm;
@@ -2415,6 +2618,40 @@
 }
 
 /*
+ * Prepare for, or clean after, relocating an object marked with
+ * DT_TEXTREL or DF_TEXTREL.  Before relocating, all read-only
+ * segments are remapped read-write.  After relocations are done, the
+ * segment's permissions are returned back to the modes specified in
+ * the phdrs.  If any relocation happened, or always for wired
+ * program, COW is triggered.
+ */
+static int
+reloc_textrel_prot(Obj_Entry *obj, bool before)
+{
+	const Elf_Phdr *ph;
+	void *base;
+	size_t l, sz;
+	int prot;
+
+	for (l = obj->phsize / sizeof(*ph), ph = obj->phdr; l > 0;
+	    l--, ph++) {
+		if (ph->p_type != PT_LOAD || (ph->p_flags & PF_W) != 0)
+			continue;
+		base = obj->relocbase + trunc_page(ph->p_vaddr);
+		sz = round_page(ph->p_vaddr + ph->p_filesz) -
+		    trunc_page(ph->p_vaddr);
+		prot = convert_prot(ph->p_flags) | (before ? PROT_WRITE : 0);
+		if (mprotect(base, sz, prot) == -1) {
+			_rtld_error("%s: Cannot write-%sable text segment: %s",
+			    obj->path, before ? "en" : "dis",
+			    rtld_strerror(errno));
+			return (-1);
+		}
+	}
+	return (0);
+}
+
+/*
  * Relocate single object.
  * Returns 0 on success, or -1 on failure.
  */
@@ -2436,30 +2673,18 @@
 		return (-1);
 	}
 
-	if (obj->textrel) {
-		/* There are relocations to the write-protected text segment. */
-		if (mprotect(obj->mapbase, obj->textsize,
-		    PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
-			_rtld_error("%s: Cannot write-enable text segment: %s",
-			    obj->path, rtld_strerror(errno));
-			return (-1);
-		}
-	}
+	/* There are relocations to the write-protected text segment. */
+	if (obj->textrel && reloc_textrel_prot(obj, true) != 0)
+		return (-1);
 
-	/* Process the non-PLT relocations. */
+	/* Process the non-PLT non-IFUNC relocations. */
 	if (reloc_non_plt(obj, rtldobj, flags, lockstate))
 		return (-1);
 
-	if (obj->textrel) {	/* Re-protected the text segment. */
-		if (mprotect(obj->mapbase, obj->textsize,
-		    PROT_READ|PROT_EXEC) == -1) {
-			_rtld_error("%s: Cannot write-protect text segment: %s",
-			    obj->path, rtld_strerror(errno));
-			return (-1);
-		}
-	}
+	/* Re-protected the text segment. */
+	if (obj->textrel && reloc_textrel_prot(obj, false) != 0)
+		return (-1);
 
-
 	/* Set the special PLT or GOT entries. */
 	init_pltgot(obj);
 
@@ -2471,15 +2696,19 @@
 		if (reloc_jmpslots(obj, flags, lockstate) == -1)
 			return (-1);
 
-	if (obj->relro_size > 0) {
-		if (mprotect(obj->relro_page, obj->relro_size,
-		    PROT_READ) == -1) {
-			_rtld_error("%s: Cannot enforce relro protection: %s",
-			    obj->path, rtld_strerror(errno));
-			return (-1);
-		}
-	}
+	/*
+	 * Process the non-PLT IFUNC relocations.  The relocations are
+	 * processed in two phases, because IFUNC resolvers may
+	 * reference other symbols, which must be readily processed
+	 * before resolvers are called.
+	 */
+	if (obj->non_plt_gnu_ifunc &&
+	    reloc_non_plt(obj, rtldobj, flags | SYMLOOK_IFUNC, lockstate))
+		return (-1);
 
+	if (!obj->mainprog && obj_enforce_relro(obj) == -1)
+		return (-1);
+
 	/*
 	 * Set up the magic number and version in the Obj_Entry.  These
 	 * were checked in the crt1.o from the original ElfKit, so we
@@ -2504,7 +2733,10 @@
 	Obj_Entry *obj;
 	int error;
 
-	for (error = 0, obj = first;  obj != NULL;  obj = obj->next) {
+	for (error = 0, obj = first;  obj != NULL;
+	    obj = TAILQ_NEXT(obj, next)) {
+		if (obj->marker)
+			continue;
 		error = relocate_object(obj, bind_now, rtldobj, flags,
 		    lockstate);
 		if (error == -1)
@@ -2542,7 +2774,9 @@
 {
 	Obj_Entry *obj;
 
-	for (obj = first;  obj != NULL;  obj = obj->next) {
+	for (obj = first; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
+		if (obj->marker)
+			continue;
 		if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1)
 			return (-1);
 	}
@@ -2581,12 +2815,14 @@
     lock_release(rtld_bind_lock, &lockstate);
 }
 
+/*
+ * Iterate over a search path, translate each element, and invoke the
+ * callback on the result.
+ */
 static void *
 path_enumerate(const char *path, path_enum_proc callback, void *arg)
 {
-#ifdef COMPAT_32BIT
     const char *trans;
-#endif
     if (path == NULL)
 	return (NULL);
 
@@ -2596,13 +2832,11 @@
 	char  *res;
 
 	len = strcspn(path, ":;");
-#ifdef COMPAT_32BIT
 	trans = lm_findn(NULL, path, len);
 	if (trans)
 	    res = callback(trans, strlen(trans), arg);
 	else
-#endif
-	res = callback(path, len, arg);
+	    res = callback(path, len, arg);
 
 	if (res != NULL)
 	    return (res);
@@ -2793,7 +3027,7 @@
 dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
     int mode, RtldLockState *lockstate)
 {
-    Obj_Entry **old_obj_tail;
+    Obj_Entry *old_obj_tail;
     Obj_Entry *obj;
     Objlist initlist;
     RtldLockState mlockstate;
@@ -2807,7 +3041,7 @@
     }
     GDB_STATE(RT_ADD,NULL);
 
-    old_obj_tail = obj_tail;
+    old_obj_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q));
     obj = NULL;
     if (name == NULL && fd == -1) {
 	obj = obj_main;
@@ -2820,8 +3054,9 @@
 	obj->dl_refcount++;
 	if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL)
 	    objlist_push_tail(&list_global, obj);
-	if (*old_obj_tail != NULL) {		/* We loaded something new. */
-	    assert(*old_obj_tail == obj);
+	if (globallist_next(old_obj_tail) != NULL) {
+	    /* We loaded something new. */
+	    assert(globallist_next(old_obj_tail) == obj);
 	    result = load_needed_objects(obj,
 		lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY));
 	    init_dag(obj);
@@ -2848,16 +3083,16 @@
 		 */
 	    } else {
 		/* Make list of init functions to call. */
-		initlist_add_objects(obj, &obj->next, &initlist);
+		initlist_add_objects(obj, obj, &initlist);
 	    }
 	    /*
-	     * Process all no_delete objects here, given them own
-	     * DAGs to prevent their dependencies from being unloaded.
-	     * This has to be done after we have loaded all of the
-	     * dependencies, so that we do not miss any.
+	     * Process all no_delete or global objects here, given
+	     * them own DAGs to prevent their dependencies from being
+	     * unloaded.  This has to be done after we have loaded all
+	     * of the dependencies, so that we do not miss any.
 	     */
 	    if (obj != NULL)
-		process_nodelete(obj);
+		process_z(obj);
 	} else {
 	    /*
 	     * Bump the reference counts for objects on this DAG.  If
@@ -2924,6 +3159,7 @@
 #ifndef __ia64__
     tls_index ti;
 #endif
+    void *sym;
     int res;
 
     def = NULL;
@@ -2933,6 +3169,7 @@
     req.flags = flags | SYMLOOK_IN_PLT;
     req.lockstate = &lockstate;
 
+    LD_UTRACE(UTRACE_DLSYM_START, handle, NULL, 0, 0, name);
     rlock_acquire(rtld_bind_lock, &lockstate);
     if (sigsetjmp(lockstate.env, 0) != 0)
 	    lock_upgrade(rtld_bind_lock, &lockstate);
@@ -2942,6 +3179,7 @@
 	if ((obj = obj_from_addr(retaddr)) == NULL) {
 	    _rtld_error("Cannot determine caller's shared object");
 	    lock_release(rtld_bind_lock, &lockstate);
+	    LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name);
 	    return NULL;
 	}
 	if (handle == NULL) {	/* Just the caller's shared object. */
@@ -2953,8 +3191,10 @@
 	} else if (handle == RTLD_NEXT || /* Objects after caller's */
 		   handle == RTLD_SELF) { /* ... caller included */
 	    if (handle == RTLD_NEXT)
-		obj = obj->next;
-	    for (; obj != NULL; obj = obj->next) {
+		obj = globallist_next(obj);
+	    for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
+		if (obj->marker)
+		    continue;
 		res = symlook_obj(&req, obj);
 		if (res == 0) {
 		    if (def == NULL ||
@@ -2989,6 +3229,7 @@
     } else {
 	if ((obj = dlcheck(handle)) == NULL) {
 	    lock_release(rtld_bind_lock, &lockstate);
+	    LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name);
 	    return NULL;
 	}
 
@@ -3035,9 +3276,9 @@
 	 * the relocated value of the symbol.
 	 */
 	if (ELF_ST_TYPE(def->st_info) == STT_FUNC)
-	    return (make_function_pointer(def, defobj));
+	    sym = make_function_pointer(def, defobj);
 	else if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC)
-	    return (rtld_resolve_ifunc(defobj, def));
+	    sym = rtld_resolve_ifunc(defobj, def);
 	else if (ELF_ST_TYPE(def->st_info) == STT_TLS) {
 #ifdef __ia64__
 	    return (__tls_get_addr(defobj->tlsindex, def->st_value));
@@ -3044,14 +3285,18 @@
 #else
 	    ti.ti_module = defobj->tlsindex;
 	    ti.ti_offset = def->st_value;
-	    return (__tls_get_addr(&ti));
+	    sym = __tls_get_addr(&ti);
 #endif
 	} else
-	    return (defobj->relocbase + def->st_value);
+	    sym = defobj->relocbase + def->st_value;
+	LD_UTRACE(UTRACE_DLSYM_STOP, handle, sym, 0, 0, name);
+	return (sym);
     }
 
-    _rtld_error("Undefined symbol \"%s\"", name);
+    _rtld_error("Undefined symbol \"%s%s%s\"", name, ve != NULL ? "@" : "",
+      ve != NULL ? ve->name : "");
     lock_release(rtld_bind_lock, &lockstate);
+    LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name);
     return NULL;
 }
 
@@ -3214,8 +3459,7 @@
 {
 
 	phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase;
-	phdr_info->dlpi_name = STAILQ_FIRST(&obj->names) ?
-	    STAILQ_FIRST(&obj->names)->name : obj->path;
+	phdr_info->dlpi_name = obj->path;
 	phdr_info->dlpi_phdr = obj->phdr;
 	phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
 	phdr_info->dlpi_tls_modid = obj->tlsindex;
@@ -3227,26 +3471,41 @@
 int
 dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
 {
-    struct dl_phdr_info phdr_info;
-    const Obj_Entry *obj;
-    RtldLockState bind_lockstate, phdr_lockstate;
-    int error;
+	struct dl_phdr_info phdr_info;
+	Obj_Entry *obj, marker;
+	RtldLockState bind_lockstate, phdr_lockstate;
+	int error;
 
-    wlock_acquire(rtld_phdr_lock, &phdr_lockstate);
-    rlock_acquire(rtld_bind_lock, &bind_lockstate);
+	bzero(&marker, sizeof(marker));
+	marker.marker = true;
+	error = 0;
 
-    error = 0;
+	wlock_acquire(rtld_phdr_lock, &phdr_lockstate);
+	wlock_acquire(rtld_bind_lock, &bind_lockstate);
+	for (obj = globallist_curr(TAILQ_FIRST(&obj_list)); obj != NULL;) {
+		TAILQ_INSERT_AFTER(&obj_list, obj, &marker, next);
+		rtld_fill_dl_phdr_info(obj, &phdr_info);
+		lock_release(rtld_bind_lock, &bind_lockstate);
 
-    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
-	rtld_fill_dl_phdr_info(obj, &phdr_info);
-	if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0)
-		break;
+		error = callback(&phdr_info, sizeof phdr_info, param);
 
-    }
-    lock_release(rtld_bind_lock, &bind_lockstate);
-    lock_release(rtld_phdr_lock, &phdr_lockstate);
+		wlock_acquire(rtld_bind_lock, &bind_lockstate);
+		obj = globallist_next(&marker);
+		TAILQ_REMOVE(&obj_list, &marker, next);
+		if (error != 0) {
+			lock_release(rtld_bind_lock, &bind_lockstate);
+			lock_release(rtld_phdr_lock, &phdr_lockstate);
+			return (error);
+		}
+	}
 
-    return (error);
+	if (error == 0) {
+		rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info);
+		lock_release(rtld_bind_lock, &bind_lockstate);
+		error = callback(&phdr_info, sizeof(phdr_info), param);
+	}
+	lock_release(rtld_phdr_lock, &phdr_lockstate);
+	return (error);
 }
 
 static void *
@@ -3382,17 +3641,16 @@
 static int
 rtld_dirname_abs(const char *path, char *base)
 {
-	char base_rel[PATH_MAX];
+	char *last;
 
-	if (rtld_dirname(path, base) == -1)
+	if (realpath(path, base) == NULL)
 		return (-1);
-	if (base[0] == '/')
-		return (0);
-	if (getcwd(base_rel, sizeof(base_rel)) == NULL ||
-	    strlcat(base_rel, "/", sizeof(base_rel)) >= sizeof(base_rel) ||
-	    strlcat(base_rel, base, sizeof(base_rel)) >= sizeof(base_rel))
+	dbg("%s -> %s", path, base);
+	last = strrchr(base, '/');
+	if (last == NULL)
 		return (-1);
-	strcpy(base, base_rel);
+	if (last != base)
+		*last = '\0';
 	return (0);
 }
 
@@ -3470,10 +3728,23 @@
      * even when marked __noinline.  However, gdb depends on those
      * calls being made.
      */
-    __asm __volatile("" : : : "memory");
+    __compiler_membar();
 }
 
 /*
+ * A function called after init routines have completed. This can be used to
+ * break before a program's entry routine is called, and can be used when
+ * main is not available in the symbol table.
+ */
+void
+_r_debug_postinit(struct link_map *m)
+{
+
+	/* See r_debug_state(). */
+	__compiler_membar();
+}
+
+/*
  * Get address of the pointer variable in the main program.
  * Prefer non-weak symbol over the weak one.
  */
@@ -3573,15 +3844,19 @@
     donelist_init(&donelist);
     symlook_init_from_req(&req1, req);
 
-    /* Look first in the referencing object if linked symbolically. */
-    if (refobj->symbolic && !donelist_check(&donelist, refobj)) {
-	res = symlook_obj(&req1, refobj);
-	if (res == 0) {
-	    req->sym_out = req1.sym_out;
-	    req->defobj_out = req1.defobj_out;
-	    assert(req->defobj_out != NULL);
-	}
+    /*
+     * Look first in the referencing object if linked symbolically,
+     * and similarly handle protected symbols.
+     */
+    res = symlook_obj(&req1, refobj);
+    if (res == 0 && (refobj->symbolic ||
+      ELF_ST_VISIBILITY(req1.sym_out->st_other) == STV_PROTECTED)) {
+	req->sym_out = req1.sym_out;
+	req->defobj_out = req1.defobj_out;
+	assert(req->defobj_out != NULL);
     }
+    if (refobj->symbolic || req->defobj_out != NULL)
+	donelist_check(&donelist, refobj);
 
     symlook_global(req, &donelist);
 
@@ -3954,11 +4229,13 @@
 
     list_containers = getenv(LD_ "TRACE_LOADED_OBJECTS_ALL");
 
-    for (; obj; obj = obj->next) {
+    for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
 	Needed_Entry		*needed;
 	char			*name, *path;
 	bool			is_lib;
 
+	if (obj->marker)
+	    continue;
 	if (list_containers && obj->needed != NULL)
 	    rtld_printf("%s:\n", obj->path);
 	for (needed = obj->needed; needed; needed = needed->next) {
@@ -4041,34 +4318,30 @@
 static void
 unload_object(Obj_Entry *root)
 {
-    Obj_Entry *obj;
-    Obj_Entry **linkp;
+	Obj_Entry *obj, *obj1;
 
-    assert(root->refcount == 0);
+	assert(root->refcount == 0);
 
-    /*
-     * Pass over the DAG removing unreferenced objects from
-     * appropriate lists.
-     */
-    unlink_object(root);
+	/*
+	 * Pass over the DAG removing unreferenced objects from
+	 * appropriate lists.
+	 */
+	unlink_object(root);
 
-    /* Unmap all objects that are no longer referenced. */
-    linkp = &obj_list->next;
-    while ((obj = *linkp) != NULL) {
-	if (obj->refcount == 0) {
-	    LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0,
-		obj->path);
-	    dbg("unloading \"%s\"", obj->path);
-	    unload_filtees(root);
-	    munmap(obj->mapbase, obj->mapsize);
-	    linkmap_delete(obj);
-	    *linkp = obj->next;
-	    obj_count--;
-	    obj_free(obj);
-	} else
-	    linkp = &obj->next;
-    }
-    obj_tail = linkp;
+	/* Unmap all objects that are no longer referenced. */
+	TAILQ_FOREACH_SAFE(obj, &obj_list, next, obj1) {
+		if (obj->marker || obj->refcount != 0)
+			continue;
+		LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase,
+		    obj->mapsize, 0, obj->path);
+		dbg("unloading \"%s\"", obj->path);
+		unload_filtees(root);
+		munmap(obj->mapbase, obj->mapsize);
+		linkmap_delete(obj);
+		TAILQ_REMOVE(&obj_list, obj, next);
+		obj_count--;
+		obj_free(obj);
+	}
 }
 
 static void
@@ -4160,7 +4433,7 @@
 	return (tls_get_addr_slow(dtvp, index, offset));
 }
 
-#if defined(__arm__) || defined(__ia64__) || defined(__powerpc__)
+#if defined(__arm__) || defined(__ia64__) || defined(__mips__) || defined(__powerpc__)
 
 /*
  * Allocate Static TLS using the Variant I method.
@@ -4200,7 +4473,8 @@
 	dtv[0] = tls_dtv_generation;
 	dtv[1] = tls_max_index;
 
-	for (obj = objs; obj; obj = obj->next) {
+	for (obj = globallist_curr(objs); obj != NULL;
+	  obj = globallist_next(obj)) {
 	    if (obj->tlsoffset > 0) {
 		addr = (Elf_Addr)tls + obj->tlsoffset;
 		if (obj->tlsinitsize > 0)
@@ -4241,8 +4515,7 @@
 
 #endif
 
-#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \
-    defined(__mips__)
+#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__)
 
 /*
  * Allocate Static TLS using the Variant II method.
@@ -4251,19 +4524,22 @@
 allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign)
 {
     Obj_Entry *obj;
-    size_t size;
+    size_t size, ralign;
     char *tls;
     Elf_Addr *dtv, *olddtv;
     Elf_Addr segbase, oldsegbase, addr;
     int i;
 
-    size = round(tls_static_space, tcbalign);
+    ralign = tcbalign;
+    if (tls_static_max_align > ralign)
+	    ralign = tls_static_max_align;
+    size = round(tls_static_space, ralign) + round(tcbsize, ralign);
 
     assert(tcbsize >= 2*sizeof(Elf_Addr));
-    tls = xcalloc(1, size + tcbsize);
+    tls = malloc_aligned(size, ralign);
     dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
 
-    segbase = (Elf_Addr)(tls + size);
+    segbase = (Elf_Addr)(tls + round(tls_static_space, ralign));
     ((Elf_Addr*)segbase)[0] = segbase;
     ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
 
@@ -4297,8 +4573,9 @@
 	 */
 	free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr));
     } else {
-	for (obj = objs; obj; obj = obj->next) {
-	    if (obj->tlsoffset) {
+	for (obj = objs; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
+		if (obj->marker || obj->tlsoffset == 0)
+			continue;
 		addr = segbase - obj->tlsoffset;
 		memset((void*) (addr + obj->tlsinitsize),
 		       0, obj->tlssize - obj->tlsinitsize);
@@ -4305,7 +4582,6 @@
 		if (obj->tlsinit)
 		    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
 		dtv[obj->tlsindex + 1] = addr;
-	    }
 	}
     }
 
@@ -4315,8 +4591,8 @@
 void
 free_tls(void *tls, size_t tcbsize, size_t tcbalign)
 {
-    size_t size;
     Elf_Addr* dtv;
+    size_t size, ralign;
     int dtvsize, i;
     Elf_Addr tlsstart, tlsend;
 
@@ -4324,7 +4600,10 @@
      * Figure out the size of the initial TLS block so that we can
      * find stuff which ___tls_get_addr() allocated dynamically.
      */
-    size = round(tls_static_space, tcbalign);
+    ralign = tcbalign;
+    if (tls_static_max_align > ralign)
+	    ralign = tls_static_max_align;
+    size = round(tls_static_space, ralign);
 
     dtv = ((Elf_Addr**)tls)[1];
     dtvsize = dtv[1];
@@ -4331,12 +4610,12 @@
     tlsend = (Elf_Addr) tls;
     tlsstart = tlsend - size;
     for (i = 0; i < dtvsize; i++) {
-	if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] > tlsend)) {
-	    free((void*) dtv[i+2]);
+	if (dtv[i + 2] != 0 && (dtv[i + 2] < tlsstart || dtv[i + 2] > tlsend)) {
+		free_aligned((void *)dtv[i + 2]);
 	}
     }
 
-    free((void*) tlsstart);
+    free_aligned((void *)tlsstart);
     free((void*) dtv);
 }
 
@@ -4351,20 +4630,18 @@
     Obj_Entry* obj;
     char* p;
 
-    for (obj = obj_list; obj; obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (obj->tlsindex == index)
 	    break;
     }
     if (!obj) {
 	_rtld_error("Can't find module with TLS index %d", index);
-	die();
+	rtld_die();
     }
 
-    p = malloc(obj->tlssize);
-    if (p == NULL) {
-	_rtld_error("Cannot allocate TLS block for index %d", index);
-	die();
-    }
+    p = malloc_aligned(obj->tlssize, obj->tlsalign);
     memcpy(p, obj->tlsinit, obj->tlsinitsize);
     memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
 
@@ -4384,7 +4661,7 @@
 	return true;
     }
 
-    if (obj->tlsindex == 1)
+    if (tls_last_offset == 0)
 	off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign);
     else
 	off = calculate_tls_offset(tls_last_offset, tls_last_size,
@@ -4396,9 +4673,11 @@
      * leave a small amount of space spare to be used for dynamically
      * loading modules which use static TLS.
      */
-    if (tls_static_space) {
+    if (tls_static_space != 0) {
 	if (calculate_tls_end(off, obj->tlssize) > tls_static_space)
 	    return false;
+    } else if (obj->tlsalign > tls_static_max_align) {
+	    tls_static_max_align = obj->tlsalign;
     }
 
     tls_last_offset = obj->tlsoffset = off;
@@ -4432,7 +4711,8 @@
     RtldLockState lockstate;
 
     wlock_acquire(rtld_bind_lock, &lockstate);
-    ret = allocate_tls(obj_list, oldtls, tcbsize, tcbalign);
+    ret = allocate_tls(globallist_curr(TAILQ_FIRST(&obj_list)), oldtls,
+      tcbsize, tcbalign);
     lock_release(rtld_bind_lock, &lockstate);
     return (ret);
 }
@@ -4500,7 +4780,7 @@
     }
     _rtld_error("%s: Unexpected inconsistency: dependency %s not found",
 	obj->path, name);
-    die();
+    rtld_die();
 }
 
 static int
@@ -4699,6 +4979,40 @@
 	return (stack_prot);
 }
 
+int
+_rtld_is_dlopened(void *arg)
+{
+	Obj_Entry *obj;
+	RtldLockState lockstate;
+	int res;
+
+	rlock_acquire(rtld_bind_lock, &lockstate);
+	obj = dlcheck(arg);
+	if (obj == NULL)
+		obj = obj_from_addr(arg);
+	if (obj == NULL) {
+		_rtld_error("No shared object contains address");
+		lock_release(rtld_bind_lock, &lockstate);
+		return (-1);
+	}
+	res = obj->dlopened ? 1 : 0;
+	lock_release(rtld_bind_lock, &lockstate);
+	return (res);
+}
+
+int
+obj_enforce_relro(Obj_Entry *obj)
+{
+
+	if (obj->relro_size > 0 && mprotect(obj->relro_page, obj->relro_size,
+	    PROT_READ) == -1) {
+		_rtld_error("%s: Cannot enforce relro protection: %s",
+		    obj->path, rtld_strerror(errno));
+		return (-1);
+	}
+	return (0);
+}
+
 static void
 map_stacks_exec(RtldLockState *lockstate)
 {
@@ -4786,7 +5100,7 @@
 {
 
 	_rtld_error("stack overflow detected; terminated");
-	die();
+	rtld_die();
 }
 __weak_reference(__stack_chk_fail, __stack_chk_fail_local);
 
@@ -4795,7 +5109,7 @@
 {
 
 	_rtld_error("buffer overflow detected; terminated");
-	die();
+	rtld_die();
 }
 
 const char *

Modified: trunk/libexec/rtld-elf/rtld.h
===================================================================
--- trunk/libexec/rtld-elf/rtld.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/rtld.h 331206 2018-03-19 14:28:58Z marius $
  */
 
 #ifndef RTLD_H /* { */
@@ -71,6 +72,9 @@
 extern int tls_dtv_generation;
 extern int tls_max_index;
 
+extern int npagesizes;
+extern size_t *pagesizes;
+
 extern int main_argc;
 extern char **main_argv;
 extern char **environ;
@@ -152,7 +156,7 @@
     Elf_Size magic;		/* Magic number (sanity check) */
     Elf_Size version;		/* Version number of struct format */
 
-    struct Struct_Obj_Entry *next;
+    TAILQ_ENTRY(Struct_Obj_Entry) next;
     char *path;			/* Pathname of underlying file (%) */
     char *origin_path;		/* Directory path of origin file */
     int refcount;
@@ -259,7 +263,9 @@
     bool z_nodelete : 1;	/* Do not unload the object and dependencies */
     bool z_noopen : 1;		/* Do not load on dlopen */
     bool z_loadfltr : 1;	/* Immediately load filtees */
+    bool z_interpose : 1;	/* Interpose all objects but main */
     bool z_nodeflib : 1;	/* Don't search default library path */
+    bool z_global : 1;		/* Make the object global */
     bool ref_nodel : 1;		/* Refcount increased to prevent dlclose */
     bool init_scanned: 1;	/* Object is already on init list. */
     bool on_fini_list: 1;	/* Object is already on fini list. */
@@ -267,9 +273,12 @@
     bool filtees_loaded : 1;	/* Filtees loaded */
     bool irelative : 1;		/* Object has R_MACHDEP_IRELATIVE relocs */
     bool gnu_ifunc : 1;		/* Object has references to STT_GNU_IFUNC */
+    bool non_plt_gnu_ifunc : 1;	/* Object has non-plt IFUNC references */
     bool crt_no_init : 1;	/* Object' crt does not call _init/_fini */
     bool valid_hash_sysv : 1;	/* A valid System V hash hash tag is available */
     bool valid_hash_gnu : 1;	/* A valid GNU hash tag is available */
+    bool dlopened : 1;		/* dlopen()-ed (vs. load statically) */
+    bool marker : 1;		/* marker on the global obj list */
 
     struct link_map linkmap;	/* For GDB and dlinfo() */
     Objlist dldags;		/* Object belongs to these dlopened DAGs (%) */
@@ -276,12 +285,14 @@
     Objlist dagmembers;		/* DAG has these members (%) */
     dev_t dev;			/* Object's filesystem's device */
     ino_t ino;			/* Object's inode number */
-    void *priv;			/* Platform-dependant */
+    void *priv;			/* Platform-dependent */
 } Obj_Entry;
 
 #define RTLD_MAGIC	0xd550b87a
 #define RTLD_VERSION	1
 
+TAILQ_HEAD(obj_entry_q, Struct_Obj_Entry);
+
 #define RTLD_STATIC_TLS_EXTRA	128
 
 /* Flags to be passed into symlook_ family of functions. */
@@ -289,6 +300,8 @@
 #define SYMLOOK_DLSYM	0x02	/* Return newest versioned symbol. Used by
 				   dlsym. */
 #define	SYMLOOK_EARLY	0x04	/* Symlook is done during initialization. */
+#define	SYMLOOK_IFUNC	0x08	/* Allow IFUNC processing in
+				   reloc_non_plt(). */
 
 /* Flags for load_object(). */
 #define	RTLD_LO_NOLOAD	0x01	/* dlopen() specified RTLD_NOLOAD. */
@@ -345,12 +358,15 @@
     struct Struct_RtldLockState *lockstate;
 } SymLook;
 
-void _rtld_error(const char *, ...) __printflike(1, 2);
+void _rtld_error(const char *, ...) __printflike(1, 2) __exported;
+void rtld_die(void) __dead2;
 const char *rtld_strerror(int);
 Obj_Entry *map_object(int, const char *, const struct stat *);
 void *xcalloc(size_t, size_t);
 void *xmalloc(size_t);
 char *xstrdup(const char *);
+void *malloc_aligned(size_t size, size_t align);
+void free_aligned(void *ptr);
 extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
 extern Elf_Sym sym_zero;	/* For resolving undefined weak refs. */
 
@@ -365,9 +381,10 @@
 unsigned long elf_hash(const char *);
 const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *,
   const Obj_Entry **, int, SymCache *, struct Struct_RtldLockState *);
-void init_pltgot(Obj_Entry *);
 void lockdflt_init(void);
 void digest_notes(Obj_Entry *, Elf_Addr, Elf_Addr);
+Obj_Entry *globallist_curr(const Obj_Entry *obj);
+Obj_Entry *globallist_next(const Obj_Entry *obj);
 void obj_free(Obj_Entry *);
 Obj_Entry *obj_new(void);
 void _rtld_bind_start(void);
@@ -381,6 +398,7 @@
 bool allocate_tls_offset(Obj_Entry *obj);
 void free_tls_offset(Obj_Entry *obj);
 const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long);
+int convert_prot(int elfflags);
 
 /*
  * MD function declarations.
@@ -392,6 +410,9 @@
 int reloc_jmpslots(Obj_Entry *, int flags, struct Struct_RtldLockState *);
 int reloc_iresolve(Obj_Entry *, struct Struct_RtldLockState *);
 int reloc_gnu_ifunc(Obj_Entry *, int flags, struct Struct_RtldLockState *);
+void ifunc_init(Elf_Auxinfo *);
+void pre_init(void);
+void init_pltgot(Obj_Entry *);
 void allocate_initial_tls(Obj_Entry *);
 
 #endif /* } */

Modified: trunk/libexec/rtld-elf/rtld_lock.c
===================================================================
--- trunk/libexec/rtld-elf/rtld_lock.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld_lock.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1999, 2000 John D. Polstra.
  * All rights reserved.
@@ -23,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *	from: FreeBSD: src/libexec/rtld-elf/sparc64/lockdflt.c,v 1.3 2002/10/09
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/rtld_lock.c 312701 2017-01-24 17:30:13Z kib $
  */
 
 /*
@@ -38,8 +39,8 @@
  * In this algorithm the lock is a single word.  Its low-order bit is
  * set when a writer holds the lock.  The remaining high-order bits
  * contain a count of readers desiring the lock.  The algorithm requires
- * atomic "compare_and_store" and "add" operations, which we implement
- * using assembly language sequences in "rtld_start.S".
+ * atomic "compare_and_store" and "add" operations, which we take
+ * from machine/atomic.h.
  */
 
 #include <sys/param.h>
@@ -51,6 +52,10 @@
 #include "rtld.h"
 #include "rtld_machdep.h"
 
+void _rtld_thread_init(struct RtldLockInfo *) __exported;
+void _rtld_atfork_pre(int *) __exported;
+void _rtld_atfork_post(int *) __exported;
+
 #define WAFLAG		0x1	/* A writer holds the lock */
 #define RC_INCR		0x2	/* Adjusts count of readers desiring lock */
 
@@ -60,10 +65,10 @@
 } Lock;
 
 static sigset_t fullsigmask, oldsigmask;
-static int thread_flag;
+static int thread_flag, wnested;
 
 static void *
-def_lock_create()
+def_lock_create(void)
 {
     void *base;
     char *p;
@@ -113,29 +118,34 @@
 static void
 def_wlock_acquire(void *lock)
 {
-    Lock *l = (Lock *)lock;
-    sigset_t tmp_oldsigmask;
+	Lock *l;
+	sigset_t tmp_oldsigmask;
 
-    for ( ; ; ) {
-	sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask);
-	if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG))
-	    break;
-	sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL);
-    }
-    oldsigmask = tmp_oldsigmask;
+	l = (Lock *)lock;
+	for (;;) {
+		sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask);
+		if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG))
+			break;
+		sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL);
+	}
+	if (atomic_fetchadd_int(&wnested, 1) == 0)
+		oldsigmask = tmp_oldsigmask;
 }
 
 static void
 def_lock_release(void *lock)
 {
-    Lock *l = (Lock *)lock;
+	Lock *l;
 
-    if ((l->lock & WAFLAG) == 0)
-    	atomic_add_rel_int(&l->lock, -RC_INCR);
-    else {
-    	atomic_add_rel_int(&l->lock, -WAFLAG);
-    	sigprocmask(SIG_SETMASK, &oldsigmask, NULL);
-    }
+	l = (Lock *)lock;
+	if ((l->lock & WAFLAG) == 0)
+		atomic_add_rel_int(&l->lock, -RC_INCR);
+	else {
+		assert(wnested > 0);
+		atomic_add_rel_int(&l->lock, -WAFLAG);
+		if (atomic_fetchadd_int(&wnested, -1) == 1)
+			sigprocmask(SIG_SETMASK, &oldsigmask, NULL);
+	}
 }
 
 static int
@@ -265,7 +275,7 @@
 }
 
 void
-lockdflt_init()
+lockdflt_init(void)
 {
     int i;
 
@@ -365,8 +375,19 @@
 {
 	RtldLockState ls[2];
 
+	if (locks == NULL)
+		return;
+
+	/*
+	 * Warning: this did not worked well with the rtld compat
+	 * locks above, when the thread signal mask was corrupted (set
+	 * to all signals blocked) if two locks were taken
+	 * simultaneously in the write mode.  The caller of the
+	 * _rtld_atfork_pre() must provide the working implementation
+	 * of the locks anyway, and libthr locks are fine.
+	 */
 	wlock_acquire(rtld_phdr_lock, &ls[0]);
-	rlock_acquire(rtld_bind_lock, &ls[1]);
+	wlock_acquire(rtld_bind_lock, &ls[1]);
 
 	/* XXXKIB: I am really sorry for this. */
 	locks[0] = ls[1].lockstate;
@@ -378,6 +399,9 @@
 {
 	RtldLockState ls[2];
 
+	if (locks == NULL)
+		return;
+
 	bzero(ls, sizeof(ls));
 	ls[0].lockstate = locks[2];
 	ls[1].lockstate = locks[0];

Modified: trunk/libexec/rtld-elf/rtld_lock.h
===================================================================
--- trunk/libexec/rtld-elf/rtld_lock.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld_lock.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 2003 Alexander Kabaev.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/rtld_lock.h 281453 2015-04-12 06:45:40Z kib $
  */
 
 #ifndef _RTLD_LOCK_H_
@@ -44,9 +45,9 @@
 	void  (*at_fork)(void);
 };
 
-extern void _rtld_thread_init(struct RtldLockInfo *);
-extern void _rtld_atfork_pre(int *);
-extern void _rtld_atfork_post(int *);
+extern void _rtld_thread_init(struct RtldLockInfo *) __exported;
+extern void _rtld_atfork_pre(int *) __exported;
+extern void _rtld_atfork_post(int *) __exported;
 
 #ifdef IN_RTLD
 

Modified: trunk/libexec/rtld-elf/rtld_printf.c
===================================================================
--- trunk/libexec/rtld-elf/rtld_printf.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld_printf.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 1986, 1988, 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -32,7 +33,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/rtld_printf.c 232729 2012-03-09 16:21:40Z kib $
  */
 
 #include <sys/param.h>

Modified: trunk/libexec/rtld-elf/rtld_printf.h
===================================================================
--- trunk/libexec/rtld-elf/rtld_printf.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld_printf.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 2011 Konstantin Belousov <kib at FreeBSD.org>.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/rtld_printf.h 225152 2011-08-24 20:05:13Z kib $
  */
 
 #ifndef RTLD_PRINTF_H

Modified: trunk/libexec/rtld-elf/rtld_tls.h
===================================================================
--- trunk/libexec/rtld-elf/rtld_tls.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/rtld_tls.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2004 Doug Rabson
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$MidnightBSD$
+ *	$FreeBSD: stable/10/libexec/rtld-elf/rtld_tls.h 281453 2015-04-12 06:45:40Z kib $
  */
 
 /*
@@ -57,7 +58,8 @@
  * The value returned from this function is suitable for installing
  * directly into the thread pointer register.
  */
-extern void *_rtld_allocate_tls(void* oldtls, size_t tcbsize, size_t tcbalign);
+void *_rtld_allocate_tls(void* oldtls, size_t tcbsize, size_t tcbalign)
+    __exported;
 
 /*
  * Free a TLS block allocated using _rtld_allocate_tls(). The tcbsize
@@ -64,6 +66,6 @@
  * and tcbalign parameters must be the same as those used to allocate
  * the block.
  */
-extern void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign);
+void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) __exported;
 
 #endif

Index: trunk/libexec/rtld-elf/sparc64/Makefile.inc
===================================================================
--- trunk/libexec/rtld-elf/sparc64/Makefile.inc	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/sparc64/Makefile.inc	2018-07-07 00:23:06 UTC (rev 11385)

Property changes on: trunk/libexec/rtld-elf/sparc64/Makefile.inc
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/sparc64/reloc.c
===================================================================
--- trunk/libexec/rtld-elf/sparc64/reloc.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/sparc64/reloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*	$NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $	*/
 
 /*-
@@ -31,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/libexec/rtld-elf/sparc64/reloc.c 331206 2018-03-19 14:28:58Z marius $");
 
 #include <sys/param.h>
 #include <sys/mman.h>
@@ -266,8 +267,8 @@
 			    ELF_R_SYM(rela->r_info));
 			req.flags = SYMLOOK_EARLY;
 
-			for (srcobj = dstobj->next; srcobj != NULL;
-			    srcobj = srcobj->next) {
+			for (srcobj = globallist_next(dstobj); srcobj != NULL;
+			    srcobj = globallist_next(srcobj)) {
 				res = symlook_obj(&req, srcobj);
 				if (res == 0) {
 					srcsym = req.sym_out;
@@ -300,6 +301,10 @@
 	SymCache *cache;
 	int r = -1;
 
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().
@@ -361,8 +366,7 @@
 	 * Note: R_SPARC_TLS_TPOFF64 must be the numerically largest
 	 * relocation type.
 	 */
-	if (type >= sizeof(reloc_target_bitmask) /
-	    sizeof(*reloc_target_bitmask)) {
+	if (type >= nitems(reloc_target_bitmask)) {
 		_rtld_error("%s: Unsupported relocation type %d in non-PLT "
 		    "object\n", obj->path, type);
 		return (-1);
@@ -499,7 +503,7 @@
 		assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT);
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		    true, NULL, lockstate);
+		    SYMLOOK_IN_PLT, NULL, lockstate);
 		value = (Elf_Addr)(defobj->relocbase + def->st_value);
 		*where = value;
 	}
@@ -626,7 +630,7 @@
 			flush(where, 4);
 		} else if (target >= 0 && target < (1L<<32)) {
 			/*
-			 * We're withing 32-bits of address zero.
+			 * We're within 32-bits of address zero.
 			 *
 			 * The resulting code in the jump slot is:
 			 *
@@ -646,7 +650,7 @@
 			flush(where, 4);
 		} else if (target <= 0 && target > -(1L<<32)) {
 			/*
-			 * We're withing 32-bits of address -1.
+			 * We're within 32-bits of address -1.
 			 *
 			 * The resulting code in the jump slot is:
 			 *
@@ -668,7 +672,7 @@
 			flush(where, 4);
 		} else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) {
 			/*
-			 * We're withing 32-bits -- we can use a direct call
+			 * We're within 32-bits -- we can use a direct call
 			 * insn
 			 *
 			 * The resulting code in the jump slot is:
@@ -691,7 +695,7 @@
 			flush(where, 4);
 		} else if (offset >= 0 && offset < (1L<<44)) {
 			/*
-			 * We're withing 44 bits.  We can generate this
+			 * We're within 44 bits.  We can generate this
 			 * pattern:
 			 *
 			 * The resulting code in the jump slot is:
@@ -716,7 +720,7 @@
 			flush(where, 4);
 		} else if (offset < 0 && offset > -(1L<<44)) {
 			/*
-			 * We're withing 44 bits.  We can generate this
+			 * We're within 44 bits.  We can generate this
 			 * pattern:
 			 *
 			 * The resulting code in the jump slot is:
@@ -782,6 +786,21 @@
 	return (target);
 }
 
+void
+ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
+{
+
+}
+
+extern void __sparc_utrap_setup(void);
+
+void
+pre_init(void)
+{
+
+	__sparc_utrap_setup();
+}
+
 /*
  * Install rtld function call into this PLT slot.
  */
@@ -810,6 +829,7 @@
 static void
 install_plt(Elf_Word *pltgot, Elf_Addr proc)
 {
+
 	pltgot[0] = SAVE;
 	flush(pltgot, 0);
 	pltgot[1] = SETHI_l0 | HIVAL(proc, 42);

Modified: trunk/libexec/rtld-elf/sparc64/rtld_machdep.h
===================================================================
--- trunk/libexec/rtld-elf/sparc64/rtld_machdep.h	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/sparc64/rtld_machdep.h	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 1999, 2000 John D. Polstra.
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/sparc64/rtld_machdep.h 309061 2016-11-23 17:48:43Z kib $
  */
 
 #ifndef RTLD_MACHDEP_H
@@ -53,7 +54,10 @@
 #define call_init_pointer(obj, target) \
 	(((InitArrFunc)(target))(main_argc, main_argv, environ))
 
-#define round(size, align) \
+#define	call_ifunc_resolver(ptr) \
+	(((Elf_Addr (*)(void))ptr)())
+
+#define round(size, align)				\
 	(((size) + (align) - 1) & ~((align) - 1))
 #define calculate_first_tls_offset(size, align) \
 	round(size, align)

Modified: trunk/libexec/rtld-elf/sparc64/rtld_start.S
===================================================================
--- trunk/libexec/rtld-elf/sparc64/rtld_start.S	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/sparc64/rtld_start.S	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*	$NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $	*/
 
 /*-
@@ -37,7 +38,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/sparc64/rtld_start.S 130661 2004-06-18 02:01:37Z tmm $
  */
 
 #include <machine/asm.h>


Property changes on: trunk/libexec/rtld-elf/sparc64/rtld_start.S
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/libexec/rtld-elf/xmalloc.c
===================================================================
--- trunk/libexec/rtld-elf/xmalloc.c	2018-07-07 00:16:08 UTC (rev 11384)
+++ trunk/libexec/rtld-elf/xmalloc.c	2018-07-07 00:23:06 UTC (rev 11385)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright 1996-1998 John D. Polstra.
  * All rights reserved.
@@ -22,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/libexec/rtld-elf/xmalloc.c 262544 2014-02-27 02:36:09Z davidxu $
  */
 
 #include <stddef.h>
@@ -67,3 +68,31 @@
 	memcpy(copy, str, len);
 	return (copy);
 }
+
+void *
+malloc_aligned(size_t size, size_t align)
+{
+	void *mem, *res;
+
+	if (align < sizeof(void *))
+		align = sizeof(void *);
+
+	mem = xmalloc(size + sizeof(void *) + align - 1);
+	res = (void *)round((uintptr_t)mem + sizeof(void *), align);
+	*(void **)((uintptr_t)res - sizeof(void *)) = mem;
+	return (res);
+}
+
+void
+free_aligned(void *ptr)
+{
+	void *mem;
+	uintptr_t x;
+
+	if (ptr == NULL)
+		return;
+	x = (uintptr_t)ptr;
+	x -= sizeof(void *);
+	mem = *(void **)x;
+	free(mem);
+}



More information about the Midnightbsd-cvs mailing list