Merge "Execute .preinit_array before any shared object initialization functions."

This commit is contained in:
David Turner 2012-01-12 01:04:46 -08:00 committed by Android (Google) Code Review
commit 5977ee02f6
4 changed files with 28 additions and 3 deletions

View File

@ -87,6 +87,7 @@ section:
present in executables, not shared libraries, which contains present in executables, not shared libraries, which contains
a list of functions that need to be called before any other a list of functions that need to be called before any other
initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY) initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY)
in the executable or any of its libraries.
Note: this is generally stored in a .preinit_array section Note: this is generally stored in a .preinit_array section

View File

@ -60,6 +60,7 @@ void *dlopen(const char *filename, int flag)
if (unlikely(ret == NULL)) { if (unlikely(ret == NULL)) {
set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY); set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY);
} else { } else {
call_constructors_recursive(ret);
ret->refcount++; ret->refcount++;
} }
pthread_mutex_unlock(&dl_lock); pthread_mutex_unlock(&dl_lock);

View File

@ -1617,8 +1617,11 @@ static void call_array(unsigned *ctor, int count, int reverse)
} }
} }
static void call_constructors(soinfo *si) void call_constructors_recursive(soinfo *si)
{ {
if (si->constructors_called)
return;
if (si->flags & FLAG_EXE) { if (si->flags & FLAG_EXE) {
TRACE("[ %5d Calling preinit_array @ 0x%08x [%d] for '%s' ]\n", TRACE("[ %5d Calling preinit_array @ 0x%08x [%d] for '%s' ]\n",
pid, (unsigned)si->preinit_array, si->preinit_array_count, pid, (unsigned)si->preinit_array, si->preinit_array_count,
@ -1633,6 +1636,21 @@ static void call_constructors(soinfo *si)
} }
} }
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) { if (si->init_func) {
TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid, TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid,
(unsigned)si->init_func, si->name); (unsigned)si->init_func, si->name);
@ -1646,8 +1664,9 @@ static void call_constructors(soinfo *si)
call_array(si->init_array, si->init_array_count, 0); call_array(si->init_array, si->init_array_count, 0);
TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name); TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name);
} }
}
si->constructors_called = 1;
}
static void call_destructors(soinfo *si) static void call_destructors(soinfo *si)
{ {
@ -2046,7 +2065,6 @@ static int link_image(soinfo *si, unsigned wr_offset)
if (program_is_setuid) if (program_is_setuid)
nullify_closed_stdio (); nullify_closed_stdio ();
notify_gdb_of_load(si); notify_gdb_of_load(si);
call_constructors(si);
return 0; return 0;
fail: fail:
@ -2251,6 +2269,8 @@ static unsigned __linker_init_post_relocation(unsigned **elfdata)
exit(-1); exit(-1);
} }
call_constructors_recursive(si);
#if ALLOW_SYMBOLS_FROM_MAIN #if ALLOW_SYMBOLS_FROM_MAIN
/* Set somain after we've loaded all the libraries in order to prevent /* 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 * linking of symbols back to the main image, which is not set up at that

View File

@ -149,6 +149,8 @@ struct soinfo
unsigned refcount; unsigned refcount;
struct link_map linkmap; struct link_map linkmap;
int constructors_called;
}; };
@ -217,6 +219,7 @@ Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start);
soinfo *find_containing_library(const void *addr); soinfo *find_containing_library(const void *addr);
Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si);
const char *linker_get_error(void); const char *linker_get_error(void);
void call_constructors_recursive(soinfo *si);
#ifdef ANDROID_ARM_LINKER #ifdef ANDROID_ARM_LINKER
typedef long unsigned int *_Unwind_Ptr; typedef long unsigned int *_Unwind_Ptr;