Merge change 27075 into eclair

* changes:
  bionic/linker: fix symbol lookup during relocations
This commit is contained in:
Android (Google) Code Review 2009-09-27 20:23:22 -04:00
commit 4e5a965d6a

View File

@ -87,6 +87,12 @@ static soinfo *freelist = NULL;
static soinfo *solist = &libdl_info;
static soinfo *sonext = &libdl_info;
static inline int validate_soinfo(soinfo *si)
{
return (si >= sopool && si < sopool + SO_MAX) ||
si == &libdl_info;
}
static char ldpaths_buf[LDPATH_BUFSIZE];
static const char *ldpaths[LDPATH_MAX + 1];
@ -421,32 +427,70 @@ _do_lookup_in_so(soinfo *si, const char *name, unsigned *elf_hash)
return _elf_lookup (si, *elf_hash, name);
}
/* This is used by dl_sym() */
static Elf32_Sym *
_do_lookup(soinfo *si, const char *name, unsigned *base)
{
unsigned elf_hash = 0;
Elf32_Sym *s;
unsigned *d;
soinfo *lsi = si;
/* Look for symbols in the local scope first (the object who is
* searching). This happens with C++ templates on i386 for some
* reason. */
s = _do_lookup_in_so(si, name, &elf_hash);
if(s != NULL)
goto done;
for(d = si->dynamic; *d; d += 2) {
if(d[0] == DT_NEEDED){
lsi = (soinfo *)d[1];
if (!validate_soinfo(lsi)) {
DL_ERR("%5d bad DT_NEEDED pointer in %s",
pid, si->name);
return 0;
}
DEBUG("%5d %s: looking up %s in %s\n",
pid, si->name, name, lsi->name);
s = _do_lookup_in_so(lsi, name, &elf_hash);
if(s != NULL)
goto done;
}
}
done:
if(s != NULL) {
TRACE_TYPE(LOOKUP, "%5d si %s sym %s s->st_value = 0x%08x, "
"found in %s, base = 0x%08x\n",
pid, si->name, name, s->st_value, lsi->name, lsi->base);
*base = lsi->base;
return s;
}
return 0;
}
/* This is used by dl_sym(). It performs symbol lookup only within the
specified soinfo object and not in any of its dependencies.
*/
Elf32_Sym *lookup_in_library(soinfo *si, const char *name)
{
unsigned unused = 0;
return _do_lookup_in_so(si, name, &unused);
}
static Elf32_Sym *
_do_lookup(soinfo *user_si, const char *name, unsigned *base)
/* This is used by dl_sym(). It performs a global symbol lookup.
*/
Elf32_Sym *lookup(const char *name, unsigned *base)
{
unsigned elf_hash = 0;
Elf32_Sym *s = NULL;
soinfo *si;
/* Look for symbols in the local scope first (the object who is
* searching). This happens with C++ templates on i386 for some
* reason. */
if (user_si) {
s = _do_lookup_in_so(user_si, name, &elf_hash);
if (s != NULL)
*base = user_si->base;
}
for(si = solist; (s == NULL) && (si != NULL); si = si->next)
{
if((si->flags & FLAG_ERROR) || (si == user_si))
if(si->flags & FLAG_ERROR)
continue;
s = _do_lookup_in_so(si, name, &elf_hash);
if (s != NULL) {
@ -455,7 +499,7 @@ _do_lookup(soinfo *user_si, const char *name, unsigned *base)
}
}
if (s != NULL) {
if(s != NULL) {
TRACE_TYPE(LOOKUP, "%5d %s s->st_value = 0x%08x, "
"si->base = 0x%08x\n", pid, name, s->st_value, si->base);
return s;
@ -464,12 +508,6 @@ _do_lookup(soinfo *user_si, const char *name, unsigned *base)
return 0;
}
/* This is used by dl_sym() */
Elf32_Sym *lookup(const char *name, unsigned *base)
{
return _do_lookup(NULL, name, base);
}
#if 0
static void dump(soinfo *si)
{
@ -1116,14 +1154,16 @@ unsigned unload_library(soinfo *si)
for(d = si->dynamic; *d; d += 2) {
if(d[0] == DT_NEEDED){
TRACE("%5d %s needs to unload %s\n", pid,
si->name, si->strtab + d[1]);
soinfo *lsi = find_library(si->strtab + d[1]);
if(lsi)
soinfo *lsi = (soinfo *)d[1];
d[1] = 0;
if (validate_soinfo(lsi)) {
TRACE("%5d %s needs to unload %s\n", pid,
si->name, lsi->name);
unload_library(lsi);
}
else
DL_ERR("%5d could not unload '%s'",
pid, si->strtab + d[1]);
DL_ERR("%5d %s: could not unload dependent library",
pid, si->name);
}
}
@ -1641,6 +1681,14 @@ static int link_image(soinfo *si, unsigned wr_offset)
pid, si->strtab + d[1], si->name, tmp_err_buf);
goto fail;
}
/* Save the soinfo of the loaded DT_NEEDED library in the payload
of the DT_NEEDED entry itself, so that we can retrieve the
soinfo directly later from the dynamic segment. This is a hack,
but it allows us to map from DT_NEEDED to soinfo efficiently
later on when we resolve relocations, trying to look up a symgol
with dlsym().
*/
d[1] = (unsigned)lsi;
lsi->refcount++;
}
}