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
This commit is contained in:
parent
334379dada
commit
e83c56dfbb
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user