Execute .preinit_array before any shared object initialization functions.
This change makes linker handling of .preinit_array compliant with the
System V ABI:
"These [pre-initialization] functions are executed after the dynamic linker has
built the process image and performed relocations but before any shared object
initialization functions."
http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#init_fini
Change-Id: Iebfee22bb1ebe1d7c7e69cb4686e4ebae0dfc4bb
diff --git a/linker/linker.c b/linker/linker.c
index e4618e3..a692d62 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -1617,8 +1617,11 @@
}
}
-static void call_constructors(soinfo *si)
+void call_constructors_recursive(soinfo *si)
{
+ if (si->constructors_called)
+ return;
+
if (si->flags & FLAG_EXE) {
TRACE("[ %5d Calling preinit_array @ 0x%08x [%d] for '%s' ]\n",
pid, (unsigned)si->preinit_array, si->preinit_array_count,
@@ -1633,6 +1636,21 @@
}
}
+ if (si->dynamic) {
+ unsigned *d;
+ for(d = si->dynamic; *d; d += 2) {
+ if(d[0] == DT_NEEDED){
+ soinfo* lsi = (soinfo *)d[1];
+ if (!validate_soinfo(lsi)) {
+ DL_ERR("%5d bad DT_NEEDED pointer in %s",
+ pid, si->name);
+ } else {
+ call_constructors_recursive(lsi);
+ }
+ }
+ }
+ }
+
if (si->init_func) {
TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid,
(unsigned)si->init_func, si->name);
@@ -1646,8 +1664,9 @@
call_array(si->init_array, si->init_array_count, 0);
TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name);
}
-}
+ si->constructors_called = 1;
+}
static void call_destructors(soinfo *si)
{
@@ -2046,7 +2065,6 @@
if (program_is_setuid)
nullify_closed_stdio ();
notify_gdb_of_load(si);
- call_constructors(si);
return 0;
fail:
@@ -2251,6 +2269,8 @@
exit(-1);
}
+ call_constructors_recursive(si);
+
#if ALLOW_SYMBOLS_FROM_MAIN
/* Set somain after we've loaded all the libraries in order to prevent
* linking of symbols back to the main image, which is not set up at that