Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so Add .init_array/.fini_array support (condi...
details: https://anonhg.NetBSD.org/src/rev/aa8833abc32c
branches: trunk
changeset: 781009:aa8833abc32c
user: matt <matt%NetBSD.org@localhost>
date: Wed Aug 15 03:46:06 2012 +0000
description:
Add .init_array/.fini_array support (conditionalized on HAVE_INITFINI_ARRAY).
diffstat:
libexec/ld.elf_so/arch/arm/Makefile.inc | 5 +-
libexec/ld.elf_so/headers.c | 26 ++++-
libexec/ld.elf_so/rtld.c | 164 +++++++++++++++++++------------
libexec/ld.elf_so/rtld.h | 15 ++-
libexec/ld.elf_so/symbol.c | 6 +-
5 files changed, 140 insertions(+), 76 deletions(-)
diffs (truncated from 376 to 300 lines):
diff -r 1d06ac4ca23a -r aa8833abc32c libexec/ld.elf_so/arch/arm/Makefile.inc
--- a/libexec/ld.elf_so/arch/arm/Makefile.inc Wed Aug 15 01:03:16 2012 +0000
+++ b/libexec/ld.elf_so/arch/arm/Makefile.inc Wed Aug 15 03:46:06 2012 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.11 2005/06/04 16:17:17 lukem Exp $
+# $NetBSD: Makefile.inc,v 1.12 2012/08/15 03:46:07 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
diff -r 1d06ac4ca23a -r aa8833abc32c libexec/ld.elf_so/headers.c
--- a/libexec/ld.elf_so/headers.c Wed Aug 15 01:03:16 2012 +0000
+++ b/libexec/ld.elf_so/headers.c Wed Aug 15 03:46:06 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: headers.c,v 1.42 2012/07/22 09:16:35 martin Exp $ */
+/* $NetBSD: headers.c,v 1.43 2012/08/15 03:46:06 matt Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.42 2012/07/22 09:16:35 martin Exp $");
+__RCSID("$NetBSD: headers.c,v 1.43 2012/08/15 03:46:06 matt Exp $");
#endif /* not lint */
#include <err.h>
@@ -227,10 +227,32 @@
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
* is mapped read-only. DT_MIPS_RLD_MAP is used instead.
diff -r 1d06ac4ca23a -r aa8833abc32c libexec/ld.elf_so/rtld.c
--- a/libexec/ld.elf_so/rtld.c Wed Aug 15 01:03:16 2012 +0000
+++ b/libexec/ld.elf_so/rtld.c Wed Aug 15 03:46:06 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.157 2012/03/13 21:00:31 joerg Exp $ */
+/* $NetBSD: rtld.c,v 1.158 2012/08/15 03:46:06 matt Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.157 2012/03/13 21:00:31 joerg Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.158 2012/08/15 03:46:06 matt Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -135,13 +135,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));
@@ -153,49 +190,33 @@
/* First pass: objects _not_ marked with DF_1_INITFIRST. */
SIMPLEQ_FOREACH(elm, &finilist, link) {
- obj = elm->obj;
- if (obj->refcount > 0 && !force) {
- continue;
- }
- if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) {
- 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;
}
- 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);
@@ -207,12 +228,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()"));
@@ -224,37 +275,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;
- }
- 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;
+ 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;
+ }
}
}
/* 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);
diff -r 1d06ac4ca23a -r aa8833abc32c libexec/ld.elf_so/rtld.h
Home |
Main Index |
Thread Index |
Old Index