[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 = ¤t_chunk->fptrs[0];
+ last_fptr = ¤t_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