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
--- 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
--- 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
--- 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);
--- 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 {
--- 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
--- 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
--- 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 */