Tue Jan 22 21:47:29 2013 UTC ()
Pullup from HEAD:
Add .init_array/.fini_array support (conditionalized on HAVE_INITFINI_ARRAY).


(matt)
diff -r1.110 -r1.110.6.1 src/libexec/ld.elf_so/Makefile
diff -r1.41.4.1 -r1.41.4.1.2.1 src/libexec/ld.elf_so/headers.c
diff -r1.155 -r1.155.4.1 src/libexec/ld.elf_so/rtld.c
diff -r1.107 -r1.107.4.1 src/libexec/ld.elf_so/rtld.h
diff -r1.59 -r1.59.4.1 src/libexec/ld.elf_so/symbol.c
diff -r1.11 -r1.11.46.1 src/libexec/ld.elf_so/arch/arm/Makefile.inc
diff -r1.10 -r1.10.10.1 src/libexec/ld.elf_so/arch/arm/rtld_start.S

cvs diff -r1.110 -r1.110.6.1 src/libexec/ld.elf_so/Makefile (expand / switch to context diff)
--- src/libexec/ld.elf_so/Makefile 2011/10/07 09:15:21 1.110
+++ src/libexec/ld.elf_so/Makefile 2013/01/22 21:47:27 1.110.6.1
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.110 2011/10/07 09:15:21 mrg Exp $
+#	$NetBSD: Makefile,v 1.110.6.1 2013/01/22 21:47:27 matt Exp $
 #
 # NOTE: when changing ld.so, ensure that ldd still compiles.
 #
@@ -43,7 +43,7 @@
 LDFLAGS+=	-Wl,-static
 LDFLAGS+=	-Wl,--warn-shared-textrel
 
-CFLAGS+=	-fvisibility=hidden
+COPTS+=		-fvisibility=hidden
 
 # Adds SRCS, CPPFLAGS, LDFLAGS, etc.  Must go first so MD startup source
 # is first.
@@ -92,10 +92,10 @@
 #CPPFLAGS+=	-DRTLD_DEBUG
 #CPPFLAGS+=	-DRTLD_DEBUG_RELOC
 #DBG=		-g
-DBG=		-O3 -fomit-frame-pointer
+COPTS=		-O3 -fomit-frame-pointer
 
 .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64"
-DBG+=		-mno-3dnow -mno-mmx -mno-sse -mno-sse2 -mno-sse3
+COPTS+=		-mno-3dnow -mno-mmx -mno-sse -mno-sse2 -mno-sse3
 .endif
 
 

cvs diff -r1.41.4.1 -r1.41.4.1.2.1 src/libexec/ld.elf_so/headers.c (expand / switch to context diff)
--- src/libexec/ld.elf_so/headers.c 2012/08/08 06:24:51 1.41.4.1
+++ src/libexec/ld.elf_so/headers.c 2013/01/22 21:47:27 1.41.4.1.2.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: headers.c,v 1.41.4.1 2012/08/08 06:24:51 jdc Exp $	 */
+/*	$NetBSD: headers.c,v 1.41.4.1.2.1 2013/01/22 21:47:27 matt Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.41.4.1 2012/08/08 06:24:51 jdc Exp $");
+__RCSID("$NetBSD: headers.c,v 1.41.4.1.2.1 2013/01/22 21:47:27 matt Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -227,9 +227,31 @@
 			init = dynp->d_un.d_ptr;
 			break;
 
+#ifdef HAVE_INITFINI_ARRAY
+		case DT_INIT_ARRAY:
+			obj->init_array =
+			    (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr);
+			break;
+
+		case DT_INIT_ARRAYSZ:
+			obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
+			break;
+#endif
+
 		case DT_FINI:
 			fini = dynp->d_un.d_ptr;
 			break;
+
+#ifdef HAVE_INITFINI_ARRAY
+		case DT_FINI_ARRAY:
+			obj->fini_array =
+			    (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr);
+			break;
+
+		case DT_FINI_ARRAYSZ:
+			obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t); 
+			break;
+#endif
 
 		/*
 		 * Don't process DT_DEBUG on MIPS as the dynamic section

cvs diff -r1.155 -r1.155.4.1 src/libexec/ld.elf_so/rtld.c (expand / switch to context diff)
--- src/libexec/ld.elf_so/rtld.c 2011/11/25 21:27:15 1.155
+++ src/libexec/ld.elf_so/rtld.c 2013/01/22 21:47:28 1.155.4.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.c,v 1.155 2011/11/25 21:27:15 joerg Exp $	 */
+/*	$NetBSD: rtld.c,v 1.155.4.1 2013/01/22 21:47:28 matt Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.155 2011/11/25 21:27:15 joerg Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.155.4.1 2013/01/22 21:47:28 matt Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -134,13 +134,50 @@
 static void _rtld_unref_dag(Obj_Entry *);
 static Obj_Entry *_rtld_obj_from_addr(const void *);
 
+static inline void
+_rtld_call_initfini_function(fptr_t func, sigset_t *mask)
+{
+	_rtld_exclusive_exit(mask);
+	(*func)();
+	_rtld_exclusive_enter(mask);
+}
+
 static void
+_rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
+{
+	if (obj->fini_arraysz == 0 && (obj->fini == NULL || obj->fini_called)) {
+		    	return;
+	}
+	if (obj->fini != NULL && !obj->fini_called) {
+		dbg (("calling fini function %s at %p%s", obj->path,
+		    (void *)obj->fini,
+		    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
+		obj->fini_called = 1; 
+		_rtld_call_initfini_function(obj->fini, mask);
+	}
+#ifdef HAVE_INITFINI_ARRAY
+	/*
+	 * Now process the fini_array if it exists.  Simply go from
+	 * start to end.  We need to make restartable so just advance
+	 * the array pointer and decrement the size each time through
+	 * the loop.
+	 */
+	while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) {
+		fptr_t fini = *obj->fini_array++;
+		obj->fini_arraysz--;
+		dbg (("calling fini array function %s at %p%s", obj->path,
+		    (void *)fini,
+		    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
+		_rtld_call_initfini_function(fini, mask);
+	}
+#endif /* HAVE_INITFINI_ARRAY */
+}
+
+static void
 _rtld_call_fini_functions(sigset_t *mask, int force)
 {
 	Objlist_Entry *elm;
 	Objlist finilist;
-	Obj_Entry *obj;
-	void (*fini)(void);
 	u_int cur_objgen;
 
 	dbg(("_rtld_call_fini_functions(%d)", force));
@@ -152,49 +189,33 @@
 
 	/* First pass: objects _not_ marked with DF_1_INITFIRST. */
 	SIMPLEQ_FOREACH(elm, &finilist, link) {
-		obj = elm->obj;
-		if (obj->refcount > 0 && !force) {
-			continue;
+		Obj_Entry * const obj = elm->obj;
+		if (!obj->z_initfirst) {
+			if (obj->refcount > 0 && !force) {
+				continue;
+			}
+			/*
+			 * XXX This can race against a concurrent dlclose().
+			 * XXX In that case, the object could be unmapped before
+			 * XXX the fini() call or the fini_array has completed.
+			 */
+			_rtld_call_fini_function(obj, mask, cur_objgen);
+			if (_rtld_objgen != cur_objgen) {
+				dbg(("restarting fini iteration"));
+				_rtld_objlist_clear(&finilist);
+				goto restart;
 		}
-		if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) {
-		    	continue;
 		}
-		dbg (("calling fini function %s at %p",  obj->path,
-		    (void *)obj->fini));
-		obj->fini_called = 1;
-		/*
-		 * XXX This can race against a concurrent dlclose().
-		 * XXX In that case, the object could be unmapped before
-		 * XXX the fini() call is done.
-		 */
-		fini = obj->fini;
-		_rtld_exclusive_exit(mask);
-		(*fini)();
-		_rtld_exclusive_enter(mask);
-		if (_rtld_objgen != cur_objgen) {
-			dbg(("restarting fini iteration"));
-			_rtld_objlist_clear(&finilist);
-			goto restart;
-		}
 	}
 
 	/* Second pass: objects marked with DF_1_INITFIRST. */
 	SIMPLEQ_FOREACH(elm, &finilist, link) {
-		obj = elm->obj;
+		Obj_Entry * const obj = elm->obj;
 		if (obj->refcount > 0 && !force) {
 			continue;
 		}
-		if (obj->fini == NULL || obj->fini_called) {
-		    	continue;
-		}
-		dbg (("calling fini function %s at %p (DF_1_INITFIRST)",
-		    obj->path, (void *)obj->fini));
-		obj->fini_called = 1;
 		/* XXX See above for the race condition here */
-		fini = obj->fini;
-		_rtld_exclusive_exit(mask);
-		(*fini)();
-		_rtld_exclusive_enter(mask);
+		_rtld_call_fini_function(obj, mask, cur_objgen);
 		if (_rtld_objgen != cur_objgen) {
 			dbg(("restarting fini iteration"));
 			_rtld_objlist_clear(&finilist);
@@ -206,12 +227,42 @@
 }
 
 static void
+_rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
+{
+	if (obj->init_arraysz == 0 && (obj->init_called || obj->init == NULL)) {
+		return;
+	}
+	if (!obj->init_called && obj->init != NULL) {
+		dbg (("calling init function %s at %p%s",
+		    obj->path, (void *)obj->init,
+		    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
+		obj->init_called = 1;
+		_rtld_call_initfini_function(obj->init, mask);
+	}
+
+#ifdef HAVE_INITFINI_ARRAY
+	/*
+	 * Now process the init_array if it exists.  Simply go from
+	 * start to end.  We need to make restartable so just advance
+	 * the array pointer and decrement the size each time through
+	 * the loop.
+	 */
+	while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) {
+		fptr_t init = *obj->init_array++;
+		obj->init_arraysz--;
+		dbg (("calling init_array function %s at %p%s",
+		    obj->path, (void *)init,
+		    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
+		_rtld_call_initfini_function(init, mask);
+	}
+#endif /* HAVE_INITFINI_ARRAY */
+}
+
+static void
 _rtld_call_init_functions(sigset_t *mask)
 {
 	Objlist_Entry *elm;
 	Objlist initlist;
-	Obj_Entry *obj;
-	void (*init)(void);
 	u_int cur_objgen;
 
 	dbg(("_rtld_call_init_functions()"));
@@ -223,37 +274,20 @@
 
 	/* First pass: objects marked with DF_1_INITFIRST. */
 	SIMPLEQ_FOREACH(elm, &initlist, link) {
-		obj = elm->obj;
-		if (obj->init == NULL || obj->init_called || !obj->z_initfirst) {
-			continue;
+		Obj_Entry * const obj = elm->obj;
+		if (obj->z_initfirst) {
+			_rtld_call_init_function(obj, mask, cur_objgen);
+			if (_rtld_objgen != cur_objgen) {
+				dbg(("restarting init iteration"));
+				_rtld_objlist_clear(&initlist);
+				goto restart;
+			}
 		}
-		dbg (("calling init function %s at %p (DF_1_INITFIRST)",
-		    obj->path, (void *)obj->init));
-		obj->init_called = 1;
-		init = obj->init;
-		_rtld_exclusive_exit(mask);
-		(*init)();
-		_rtld_exclusive_enter(mask);
-		if (_rtld_objgen != cur_objgen) {
-			dbg(("restarting init iteration"));
-			_rtld_objlist_clear(&initlist);
-			goto restart;
-		}
 	}
 
 	/* Second pass: all other objects. */
 	SIMPLEQ_FOREACH(elm, &initlist, link) {
-		obj = elm->obj;
-		if (obj->init == NULL || obj->init_called) {
-			continue;
-		}
-		dbg (("calling init function %s at %p",  obj->path,
-		    (void *)obj->init));
-		obj->init_called = 1;
-		init = obj->init;
-		_rtld_exclusive_exit(mask);
-		(*init)();
-		_rtld_exclusive_enter(mask);
+		_rtld_call_init_function(elm->obj, mask, cur_objgen);
 		if (_rtld_objgen != cur_objgen) {
 			dbg(("restarting init iteration"));
 			_rtld_objlist_clear(&initlist);

cvs diff -r1.107 -r1.107.4.1 src/libexec/ld.elf_so/rtld.h (expand / switch to context diff)
--- src/libexec/ld.elf_so/rtld.h 2011/12/02 09:06:49 1.107
+++ src/libexec/ld.elf_so/rtld.h 2013/01/22 21:47:28 1.107.4.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.h,v 1.107 2011/12/02 09:06:49 skrll Exp $	 */
+/*	$NetBSD: rtld.h,v 1.107.4.1 2013/01/22 21:47:28 matt Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -114,7 +114,6 @@
 /* Ver_Entry.flags */
 #define VER_INFO_HIDDEN	0x01
 
-
 #define RTLD_MAX_ENTRY 10
 #define RTLD_MAX_LIBRARY 4
 #define RTLD_MAX_CTL 2
@@ -141,6 +140,8 @@
 #define RTLD_MAGIC	0xd550b87a
 #define RTLD_VERSION	1
 
+typedef void (*fptr_t)(void);
+
 typedef struct Struct_Obj_Entry {
 	Elf32_Word      magic;		/* Magic number (sanity check) */
 	Elf32_Word      version;	/* Version number of struct format */
@@ -188,8 +189,8 @@
 	Search_Path    *rpaths;		/* Search path specified in object */
 	Needed_Entry   *needed;		/* Shared objects needed by this (%) */
 
-	void            (*init)(void); 	/* Initialization function to call */
-	void            (*fini)(void);	/* Termination function to call */
+	fptr_t		init;		/* Initialization function to call */
+	fptr_t		fini;		/* Termination function to call */
 
 	/*
 	 * BACKWARDS COMPAT Entry points for dlopen() and friends.
@@ -277,6 +278,12 @@
 	Ver_Entry	*vertab;	/* Versions required/defined by this
 					 * object */
 	int		vertabnum;	/* Number of entries in vertab */
+
+	/* init_array/fini_array */
+	fptr_t		*init_array;	/* start of init array */
+	size_t		init_arraysz;	/* # of entries in it */
+	fptr_t		*fini_array;	/* start of fini array */
+	size_t		fini_arraysz;	/* # of entries in it */
 } Obj_Entry;
 
 typedef struct Struct_DoneList {

cvs diff -r1.59 -r1.59.4.1 src/libexec/ld.elf_so/symbol.c (expand / switch to context diff)
--- src/libexec/ld.elf_so/symbol.c 2011/11/25 14:39:02 1.59
+++ src/libexec/ld.elf_so/symbol.c 2013/01/22 21:47:28 1.59.4.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: symbol.c,v 1.59 2011/11/25 14:39:02 joerg Exp $	 */
+/*	$NetBSD: symbol.c,v 1.59.4.1 2013/01/22 21:47:28 matt Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: symbol.c,v 1.59 2011/11/25 14:39:02 joerg Exp $");
+__RCSID("$NetBSD: symbol.c,v 1.59.4.1 2013/01/22 21:47:28 matt Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -58,8 +58,6 @@
 
 #include "debug.h"
 #include "rtld.h"
-
-typedef void (*fptr_t)(void);
 
 /*
  * If the given object is already in the donelist, return true.  Otherwise

cvs diff -r1.11 -r1.11.46.1 src/libexec/ld.elf_so/arch/arm/Makefile.inc (expand / switch to context diff)
--- src/libexec/ld.elf_so/arch/arm/Makefile.inc 2005/06/04 16:17:17 1.11
+++ src/libexec/ld.elf_so/arch/arm/Makefile.inc 2013/01/22 21:47:28 1.11.46.1
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.11 2005/06/04 16:17:17 lukem Exp $
+#	$NetBSD: Makefile.inc,v 1.11.46.1 2013/01/22 21:47:28 matt Exp $
 
 SRCS+=		rtld_start.S mdreloc.c
 
@@ -6,5 +6,8 @@
 CPPFLAGS+=	-fpic
 
 CPPFLAGS+=	-DELFSIZE=32
+.if ${MACHINE_ARCH} == "earm" || ${MACHINE_ARCH} == "earmeb"
+CPPFLAGS+=	-DHAVE_INITFINI_ARRAY
+.endif
 
 LDFLAGS+=	-Wl,-e,_rtld_start

cvs diff -r1.10 -r1.10.10.1 src/libexec/ld.elf_so/arch/arm/rtld_start.S (expand / switch to context diff)
--- src/libexec/ld.elf_so/arch/arm/rtld_start.S 2009/11/11 14:15:41 1.10
+++ src/libexec/ld.elf_so/arch/arm/rtld_start.S 2013/01/22 21:47:28 1.10.10.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $	*/
+/*	$NetBSD: rtld_start.S,v 1.10.10.1 2013/01/22 21:47:28 matt Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <machine/asm.h>
 
-RCSID("$NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $")
+RCSID("$NetBSD: rtld_start.S,v 1.10.10.1 2013/01/22 21:47:28 matt Exp $")
 
 	.text
 	.align	0
@@ -58,9 +58,8 @@
 	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 */
-	add	sp, sp, #8		/* restore stack */
+	ldr	r2, [sp], #4		/* pop r2 = cleanup */
+	ldr	r1, [sp], #4		/* pop r1 = obj_main */
 	mov	r0, r4			/* restore ps_strings */
 #ifdef _ARM_ARCH_4T
 	bx	r3			/* jump to the entry point */
@@ -81,7 +80,7 @@
  *	lr = &GOT[2]
  */
 _rtld_bind_start:
-	stmdb	sp!,{r0-r4,sl,fp}
+	stmdb	sp!,{r0-r4,sl,fp}	/* 8 byte aligned (lr already saved) */
 
 	sub	r1, ip, lr		/* r1 = 4 * (n + 1) */
 	sub	r1, r1, #4		/* r1 = 4 * n */