Merge "Minor linker cleanup, primarily to use Elf32_Dyn"

This commit is contained in:
Brian Carlstrom 2013-03-06 01:01:23 +00:00 committed by Gerrit Code Review
commit 036f909720
6 changed files with 188 additions and 176 deletions

View file

@ -174,7 +174,7 @@ static bool haveSiginfo(int signum) {
* Catches fatal signals so we can ask debuggerd to ptrace us before
* we crash.
*/
void debugger_signal_handler(int n, siginfo_t* info, void*) {
void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
/*
* It's possible somebody cleared the SA_SIGINFO flag, which would mean
* our "info" arg holds an undefined value.
@ -245,10 +245,10 @@ void debugger_signal_handler(int n, siginfo_t* info, void*) {
}
}
void debugger_init() {
void debuggerd_init() {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = debugger_signal_handler;
act.sa_sigaction = debuggerd_signal_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);

View file

@ -85,18 +85,18 @@ void* dlsym(void* handle, const char* symbol) {
soinfo* found = NULL;
Elf32_Sym* sym = NULL;
if (handle == RTLD_DEFAULT) {
sym = lookup(symbol, &found, NULL);
sym = dlsym_linear_lookup(symbol, &found, NULL);
} else if (handle == RTLD_NEXT) {
void* ret_addr = __builtin_return_address(0);
soinfo* si = find_containing_library(ret_addr);
sym = NULL;
if (si && si->next) {
sym = lookup(symbol, &found, si->next);
sym = dlsym_linear_lookup(symbol, &found, si->next);
}
} else {
found = (soinfo*) handle;
sym = soinfo_lookup(found, symbol);
found = reinterpret_cast<soinfo*>(handle);
sym = dlsym_handle_lookup(found, symbol);
}
if (sym != NULL) {
@ -131,7 +131,7 @@ int dladdr(const void* addr, Dl_info* info) {
info->dli_fbase = (void*) si->base;
// Determine if any symbol in the library contains the specified address.
Elf32_Sym *sym = soinfo_find_symbol(si, addr);
Elf32_Sym *sym = dladdr_find_symbol(si, addr);
if (sym != NULL) {
info->dli_sname = si->strtab + sym->st_name;
info->dli_saddr = (void*)(si->load_bias + sym->st_value);

View file

@ -87,9 +87,9 @@ struct soinfo_pool_t {
static struct soinfo_pool_t* gSoInfoPools = NULL;
static soinfo* gSoInfoFreeList = NULL;
static soinfo *solist = &libdl_info;
static soinfo *sonext = &libdl_info;
static soinfo *somain; /* main process, always the one after libdl_info */
static soinfo* solist = &libdl_info;
static soinfo* sonext = &libdl_info;
static soinfo* somain; /* main process, always the one after libdl_info */
static const char* const gSoPaths[] = {
"/vendor/lib",
@ -103,7 +103,7 @@ static const char* gLdPaths[LDPATH_MAX + 1];
static char gLdPreloadsBuffer[LDPRELOAD_BUFSIZE];
static const char* gLdPreloadNames[LDPRELOAD_MAX + 1];
static soinfo *preloads[LDPRELOAD_MAX + 1];
static soinfo* gLdPreloads[LDPRELOAD_MAX + 1];
static int debug_verbosity;
@ -332,13 +332,13 @@ static void soinfo_free(soinfo* si)
TRACE("name %s: freeing soinfo @ %p\n", si->name, si);
for(trav = solist; trav != NULL; trav = trav->next){
for (trav = solist; trav != NULL; trav = trav->next) {
if (trav == si)
break;
prev = trav;
}
if (trav == NULL) {
/* si was not ni solist */
/* si was not in solist */
DL_ERR("name \"%s\" is not in solist!", si->name);
return;
}
@ -347,7 +347,9 @@ static void soinfo_free(soinfo* si)
always the static libdl_info.
*/
prev->next = si->next;
if (si == sonext) sonext = prev;
if (si == sonext) {
sonext = prev;
}
si->next = gSoInfoFreeList;
gSoInfoFreeList = si;
}
@ -440,27 +442,27 @@ dl_iterate_phdr(int (*cb)(dl_phdr_info *info, size_t size, void *data),
#endif
static Elf32_Sym *soinfo_elf_lookup(soinfo *si, unsigned hash, const char *name)
{
Elf32_Sym *s;
Elf32_Sym *symtab = si->symtab;
const char *strtab = si->strtab;
static Elf32_Sym* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
Elf32_Sym* s;
Elf32_Sym* symtab = si->symtab;
const char* strtab = si->strtab;
unsigned n;
TRACE_TYPE(LOOKUP, "SEARCH %s in %s@0x%08x %08x %d\n",
name, si->name, si->base, hash, hash % si->nbucket);
n = hash % si->nbucket;
for(n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]){
for (n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]) {
s = symtab + n;
if(strcmp(strtab + s->st_name, name)) continue;
if (strcmp(strtab + s->st_name, name)) continue;
/* only concern ourselves with global and weak symbol definitions */
switch(ELF32_ST_BIND(s->st_info)){
case STB_GLOBAL:
case STB_WEAK:
if(s->st_shndx == SHN_UNDEF)
if (s->st_shndx == SHN_UNDEF) {
continue;
}
TRACE_TYPE(LOOKUP, "FOUND %s in %s (%08x) %d\n",
name, si->name, s->st_value, s->st_size);
@ -471,9 +473,8 @@ static Elf32_Sym *soinfo_elf_lookup(soinfo *si, unsigned hash, const char *name)
return NULL;
}
static unsigned elfhash(const char *_name)
{
const unsigned char *name = (const unsigned char *) _name;
static unsigned elfhash(const char* _name) {
const unsigned char* name = (const unsigned char*) _name;
unsigned h = 0, g;
while(*name) {
@ -485,13 +486,9 @@ static unsigned elfhash(const char *_name)
return h;
}
static Elf32_Sym *
soinfo_do_lookup(soinfo *si, const char *name, soinfo **lsi,
soinfo *needed[])
{
static Elf32_Sym* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, soinfo* needed[]) {
unsigned elf_hash = elfhash(name);
Elf32_Sym *s = NULL;
int i;
Elf32_Sym* s = NULL;
if (si != NULL && somain != NULL) {
@ -559,15 +556,15 @@ soinfo_do_lookup(soinfo *si, const char *name, soinfo **lsi,
}
/* Next, look for it in the preloads list */
for(i = 0; preloads[i] != NULL; i++) {
s = soinfo_elf_lookup(preloads[i], elf_hash, name);
if(s != NULL) {
*lsi = preloads[i];
for (int i = 0; gLdPreloads[i] != NULL; i++) {
s = soinfo_elf_lookup(gLdPreloads[i], elf_hash, name);
if (s != NULL) {
*lsi = gLdPreloads[i];
goto done;
}
}
for(i = 0; needed[i] != NULL; i++) {
for (int i = 0; needed[i] != NULL; i++) {
DEBUG("%s: looking up %s in %s\n",
si->name, name, needed[i]->name);
s = soinfo_elf_lookup(needed[i], elf_hash, name);
@ -578,7 +575,7 @@ soinfo_do_lookup(soinfo *si, const char *name, soinfo **lsi,
}
done:
if(s != NULL) {
if (s != NULL) {
TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = 0x%08x, "
"found in %s, base = 0x%08x, load bias = 0x%08x\n",
si->name, name, s->st_value,
@ -589,17 +586,26 @@ done:
return NULL;
}
/* This is used by dl_sym(). It performs symbol lookup only within the
/* This is used by dlsym(3). It performs symbol lookup only within the
specified soinfo object and not in any of its dependencies.
TODO: Only looking in the specified soinfo seems wrong. dlsym(3) says
that it should do a breadth first search through the dependency
tree. This agrees with the ELF spec (aka System V Application
Binary Interface) where in Chapter 5 it discuss resolving "Shared
Object Dependencies" in breadth first search order.
*/
Elf32_Sym *soinfo_lookup(soinfo *si, const char *name)
Elf32_Sym* dlsym_handle_lookup(soinfo* si, const char* name)
{
return soinfo_elf_lookup(si, elfhash(name), name);
}
/* This is used by dl_sym(). It performs a global symbol lookup.
/* This is used by dlsym(3) to performs a global symbol lookup. If the
start value is null (for RTLD_DEFAULT), the search starts at the
beginning of the global solist. Otherwise the search starts at the
specified soinfo (for RTLD_NEXT).
*/
Elf32_Sym* lookup(const char* name, soinfo** found, soinfo* start) {
Elf32_Sym* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) {
unsigned elf_hash = elfhash(name);
if (start == NULL) {
@ -623,31 +629,25 @@ Elf32_Sym* lookup(const char* name, soinfo** found, soinfo* start) {
return s;
}
soinfo *find_containing_library(const void *addr)
{
soinfo *si;
for(si = solist; si != NULL; si = si->next)
{
if((unsigned)addr >= si->base && (unsigned)addr - si->base < si->size) {
soinfo* find_containing_library(const void* addr) {
for (soinfo* si = solist; si != NULL; si = si->next) {
if ((unsigned)addr >= si->base && (unsigned)addr - si->base < si->size) {
return si;
}
}
return NULL;
}
Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr)
{
Elf32_Sym* dladdr_find_symbol(soinfo* si, const void* addr) {
unsigned int i;
unsigned soaddr = (unsigned)addr - si->base;
/* Search the library's symbol table for any defined symbol which
* contains this address */
for(i=0; i<si->nchain; i++) {
for (i=0; i<si->nchain; i++) {
Elf32_Sym *sym = &si->symtab[i];
if(sym->st_shndx != SHN_UNDEF &&
if (sym->st_shndx != SHN_UNDEF &&
soaddr >= sym->st_value &&
soaddr < sym->st_value + sym->st_size) {
return sym;
@ -658,12 +658,10 @@ Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr)
}
#if 0
static void dump(soinfo *si)
static void dump(soinfo* si)
{
Elf32_Sym *s = si->symtab;
unsigned n;
for(n = 0; n < si->nchain; n++) {
Elf32_Sym* s = si->symtab;
for (unsigned n = 0; n < si->nchain; n++) {
TRACE("%04d> %08x: %02x %04x %08x %08x %s\n", n, s,
s->st_info, s->st_shndx, s->st_value, s->st_size,
si->strtab + s->st_name);
@ -890,7 +888,7 @@ static soinfo* load_library(const char* name) {
si.ptr->load_bias = load_bias;
si.ptr->flags = 0;
si.ptr->entry = 0;
si.ptr->dynamic = (unsigned *)-1;
si.ptr->dynamic = NULL;
si.ptr->phnum = phdr_count;
si.ptr->phdr = phdr_table_get_loaded_phdr(phdr_table, phdr_count, load_bias);
if (si.ptr->phdr == NULL) {
@ -912,8 +910,8 @@ static soinfo *find_loaded_library(const char *name)
bname = strrchr(name, '/');
bname = bname ? bname + 1 : name;
for(si = solist; si != NULL; si = si->next){
if(!strcmp(bname, si->name)) {
for (si = solist; si != NULL; si = si->next) {
if (!strcmp(bname, si->name)) {
return si;
}
}
@ -967,9 +965,10 @@ static int soinfo_unload(soinfo* si) {
TRACE("unloading '%s'\n", si->name);
si->CallDestructors();
for (unsigned* d = si->dynamic; *d; d += 2) {
if (d[0] == DT_NEEDED) {
soinfo* lsi = find_loaded_library(si->strtab + d[1]);
for (Elf32_Dyn* d = si->dynamic; d->d_tag != DT_NEEDED; ++d) {
if (d->d_tag == DT_NEEDED) {
const char* library_name = si->strtab + d->d_un.d_val;
soinfo* lsi = find_loaded_library(library_name);
if (lsi != NULL) {
TRACE("%s needs to unload %s\n", si->name, lsi->name);
soinfo_unload(lsi);
@ -1022,30 +1021,30 @@ int do_dlclose(soinfo* si) {
* ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned
* long.
*/
static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
soinfo *needed[])
static int soinfo_relocate(soinfo* si, Elf32_Rel* rel, unsigned count,
soinfo* needed[])
{
Elf32_Sym *symtab = si->symtab;
const char *strtab = si->strtab;
Elf32_Sym *s;
Elf32_Rel *start = rel;
soinfo *lsi;
Elf32_Sym* symtab = si->symtab;
const char* strtab = si->strtab;
Elf32_Sym* s;
Elf32_Rel* start = rel;
soinfo* lsi;
for (size_t idx = 0; idx < count; ++idx, ++rel) {
unsigned type = ELF32_R_TYPE(rel->r_info);
unsigned sym = ELF32_R_SYM(rel->r_info);
unsigned reloc = (unsigned)(rel->r_offset + si->load_bias);
unsigned sym_addr = 0;
char *sym_name = NULL;
char* sym_name = NULL;
DEBUG("Processing '%s' relocation at index %d\n", si->name, idx);
if (type == 0) { // R_*_NONE
continue;
}
if(sym != 0) {
if (sym != 0) {
sym_name = (char *)(strtab + symtab[sym].st_name);
s = soinfo_do_lookup(si, sym_name, &lsi, needed);
if(s == NULL) {
if (s == NULL) {
/* We only allow an undefined symbol if this is a weak
reference.. */
s = &symtab[sym];
@ -1103,7 +1102,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
} else {
/* We got a definition. */
#if 0
if((base == 0) && (si->base != 0)){
if ((base == 0) && (si->base != 0)) {
/* linking from libraries to main image is bad */
DL_ERR("cannot locate \"%s\"...",
strtab + symtab[sym].st_name);
@ -1300,9 +1299,9 @@ static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
sym = symtab + gotsym;
got = si->plt_got + local_gotno;
for (g = gotsym; g < symtabno; g++, sym++, got++) {
const char *sym_name;
Elf32_Sym *s;
soinfo *lsi;
const char* sym_name;
Elf32_Sym* s;
soinfo* lsi;
/* This is an undefined reference... try to locate it */
sym_name = si->strtab + sym->st_name;
@ -1407,10 +1406,11 @@ void soinfo::CallConstructors() {
return;
}
if (dynamic) {
for (unsigned* d = dynamic; *d; d += 2) {
if (d[0] == DT_NEEDED) {
soinfo* lsi = find_loaded_library(strtab + d[1]);
if (dynamic != NULL) {
for (Elf32_Dyn* d = dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_NEEDED) {
const char* library_name = strtab + d->d_un.d_val;
soinfo* lsi = find_loaded_library(library_name);
if (lsi == NULL) {
DL_ERR("\"%s\": could not initialize dependent library", name);
} else {
@ -1495,8 +1495,7 @@ static bool soinfo_link_image(soinfo* si) {
Elf32_Addr base = si->load_bias;
const Elf32_Phdr *phdr = si->phdr;
int phnum = si->phnum;
int relocating_linker = (si->flags & FLAG_LINKER) != 0;
soinfo **needed, **pneeded;
bool relocating_linker = (si->flags & FLAG_LINKER) != 0;
/* We can't debug anything until the linker is relocated */
if (!relocating_linker) {
@ -1526,81 +1525,82 @@ static bool soinfo_link_image(soinfo* si) {
#endif
/* extract useful information from dynamic section */
for (unsigned* d = si->dynamic; *d; ++d) {
DEBUG("d = %p, d[0] = 0x%08x d[1] = 0x%08x\n", d, d[0], d[1]);
switch(*d++){
uint32_t needed_count = 0;
for (Elf32_Dyn* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
DEBUG("d = %p, d[0](tag) = 0x%08x d[1](val) = 0x%08x\n", d, d->d_tag, d->d_un.d_val);
switch(d->d_tag){
case DT_HASH:
si->nbucket = ((unsigned *) (base + *d))[0];
si->nchain = ((unsigned *) (base + *d))[1];
si->bucket = (unsigned *) (base + *d + 8);
si->chain = (unsigned *) (base + *d + 8 + si->nbucket * 4);
si->nbucket = ((unsigned *) (base + d->d_un.d_ptr))[0];
si->nchain = ((unsigned *) (base + d->d_un.d_ptr))[1];
si->bucket = (unsigned *) (base + d->d_un.d_ptr + 8);
si->chain = (unsigned *) (base + d->d_un.d_ptr + 8 + si->nbucket * 4);
break;
case DT_STRTAB:
si->strtab = (const char *) (base + *d);
si->strtab = (const char *) (base + d->d_un.d_ptr);
break;
case DT_SYMTAB:
si->symtab = (Elf32_Sym *) (base + *d);
si->symtab = (Elf32_Sym *) (base + d->d_un.d_ptr);
break;
case DT_PLTREL:
if(*d != DT_REL) {
if (d->d_un.d_val != DT_REL) {
DL_ERR("unsupported DT_RELA in \"%s\"", si->name);
return false;
}
break;
case DT_JMPREL:
si->plt_rel = (Elf32_Rel*) (base + *d);
si->plt_rel = (Elf32_Rel*) (base + d->d_un.d_ptr);
break;
case DT_PLTRELSZ:
si->plt_rel_count = *d / 8;
si->plt_rel_count = d->d_un.d_val / sizeof(Elf32_Rel);
break;
case DT_REL:
si->rel = (Elf32_Rel*) (base + *d);
si->rel = (Elf32_Rel*) (base + d->d_un.d_ptr);
break;
case DT_RELSZ:
si->rel_count = *d / 8;
si->rel_count = d->d_un.d_val / sizeof(Elf32_Rel);
break;
case DT_PLTGOT:
/* Save this in case we decide to do lazy binding. We don't yet. */
si->plt_got = (unsigned *)(base + *d);
si->plt_got = (unsigned *)(base + d->d_un.d_ptr);
break;
case DT_DEBUG:
// Set the DT_DEBUG entry to the address of _r_debug for GDB
// if the dynamic table is writable
if ((dynamic_flags & PF_W) != 0) {
*d = (int) &_r_debug;
d->d_un.d_val = (int) &_r_debug;
}
break;
case DT_RELA:
DL_ERR("unsupported DT_RELA in \"%s\"", si->name);
return false;
case DT_INIT:
si->init_func = (void (*)(void))(base + *d);
si->init_func = (void (*)(void))(base + d->d_un.d_ptr);
DEBUG("%s constructors (init func) found at %p\n", si->name, si->init_func);
break;
case DT_FINI:
si->fini_func = (void (*)(void))(base + *d);
si->fini_func = (void (*)(void))(base + d->d_un.d_ptr);
DEBUG("%s destructors (fini func) found at %p\n", si->name, si->fini_func);
break;
case DT_INIT_ARRAY:
si->init_array = (unsigned *)(base + *d);
si->init_array = (unsigned *)(base + d->d_un.d_ptr);
DEBUG("%s constructors (init_array) found at %p\n", si->name, si->init_array);
break;
case DT_INIT_ARRAYSZ:
si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
si->init_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf32_Addr);
break;
case DT_FINI_ARRAY:
si->fini_array = (unsigned *)(base + *d);
si->fini_array = (unsigned *)(base + d->d_un.d_ptr);
DEBUG("%s destructors (fini_array) found at %p\n", si->name, si->fini_array);
break;
case DT_FINI_ARRAYSZ:
si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
si->fini_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf32_Addr);
break;
case DT_PREINIT_ARRAY:
si->preinit_array = (unsigned *)(base + *d);
si->preinit_array = (unsigned *)(base + d->d_un.d_ptr);
DEBUG("%s constructors (preinit_array) found at %p\n", si->name, si->preinit_array);
break;
case DT_PREINIT_ARRAYSZ:
si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
si->preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf32_Addr);
break;
case DT_TEXTREL:
si->has_text_relocations = true;
@ -1608,18 +1608,21 @@ static bool soinfo_link_image(soinfo* si) {
case DT_SYMBOLIC:
si->has_DT_SYMBOLIC = true;
break;
#if defined(DT_FLAGS)
case DT_NEEDED:
++needed_count;
break;
#if defined DT_FLAGS
// TODO: why is DT_FLAGS not defined?
case DT_FLAGS:
if (*d & DF_TEXTREL) {
if (d->d_un.d_val & DF_TEXTREL) {
si->has_text_relocations = true;
}
if (*d & DF_SYMBOLIC) {
if (d->d_un.d_val & DF_SYMBOLIC) {
si->has_DT_SYMBOLIC = true;
}
break;
#endif
#if defined(ANDROID_MIPS_LINKER)
case DT_NEEDED:
case DT_STRSZ:
case DT_SYMENT:
case DT_RELENT:
@ -1627,7 +1630,7 @@ static bool soinfo_link_image(soinfo* si) {
case DT_MIPS_RLD_MAP:
// Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB.
{
r_debug** dp = (r_debug**) *d;
r_debug** dp = (r_debug**) d->d_un.d_ptr;
*dp = &_r_debug;
}
break;
@ -1638,15 +1641,15 @@ static bool soinfo_link_image(soinfo* si) {
break;
case DT_MIPS_SYMTABNO:
si->mips_symtabno = *d;
si->mips_symtabno = d->d_un.d_val;
break;
case DT_MIPS_LOCAL_GOTNO:
si->mips_local_gotno = *d;
si->mips_local_gotno = d->d_un.d_val;
break;
case DT_MIPS_GOTSYM:
si->mips_gotsym = *d;
si->mips_gotsym = d->d_un.d_val;
break;
default:
@ -1660,6 +1663,10 @@ static bool soinfo_link_image(soinfo* si) {
si->base, si->strtab, si->symtab);
// Sanity checks.
if (relocating_linker && needed_count != 0) {
DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
return false;
}
if (si->nbucket == 0) {
DL_ERR("empty/missing DT_HASH in \"%s\" (built with --hash-style=gnu?)", si->name);
return false;
@ -1675,7 +1682,7 @@ static bool soinfo_link_image(soinfo* si) {
/* if this is the main executable, then load all of the preloads now */
if (si->flags & FLAG_EXE) {
memset(preloads, 0, sizeof(preloads));
memset(gLdPreloads, 0, sizeof(gLdPreloads));
for (size_t i = 0; gLdPreloadNames[i] != NULL; i++) {
soinfo* lsi = find_library(gLdPreloadNames[i]);
if (lsi == NULL) {
@ -1684,21 +1691,22 @@ static bool soinfo_link_image(soinfo* si) {
gLdPreloadNames[i], si->name, tmp_err_buf);
return false;
}
preloads[i] = lsi;
gLdPreloads[i] = lsi;
}
}
/* dynamic_count is an upper bound for the number of needed libs */
pneeded = needed = (soinfo**) alloca((1 + dynamic_count) * sizeof(soinfo*));
soinfo** needed = (soinfo**) alloca((1 + needed_count) * sizeof(soinfo*));
soinfo** pneeded = needed;
for (unsigned* d = si->dynamic; *d; d += 2) {
if (d[0] == DT_NEEDED) {
DEBUG("%s needs %s\n", si->name, si->strtab + d[1]);
soinfo* lsi = find_library(si->strtab + d[1]);
for (Elf32_Dyn* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_NEEDED) {
const char* library_name = si->strtab + d->d_un.d_val;
DEBUG("%s needs %s\n", si->name, library_name);
soinfo* lsi = find_library(library_name);
if (lsi == NULL) {
strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf));
DL_ERR("could not load library \"%s\" needed by \"%s\"; caused by %s",
si->strtab + d[1], si->name, tmp_err_buf);
library_name, si->name, tmp_err_buf);
return false;
}
*pneeded++ = lsi;
@ -1719,15 +1727,15 @@ static bool soinfo_link_image(soinfo* si) {
}
}
if (si->plt_rel) {
if (si->plt_rel != NULL) {
DEBUG("[ relocating %s plt ]\n", si->name );
if(soinfo_relocate(si, si->plt_rel, si->plt_rel_count, needed)) {
if (soinfo_relocate(si, si->plt_rel, si->plt_rel_count, needed)) {
return false;
}
}
if (si->rel) {
if (si->rel != NULL) {
DEBUG("[ relocating %s ]\n", si->name );
if(soinfo_relocate(si, si->rel, si->rel_count, needed)) {
if (soinfo_relocate(si, si->rel, si->rel_count, needed)) {
return false;
}
}
@ -1791,7 +1799,7 @@ static unsigned __linker_init_post_relocation(KernelArgumentBlock& args, unsigne
// Initialize environment functions, and get to the ELF aux vectors table.
linker_env_init(args);
debugger_init();
debuggerd_init();
// Get a few environment variables.
const char* LD_DEBUG = linker_env_get("LD_DEBUG");
@ -1827,29 +1835,31 @@ static unsigned __linker_init_post_relocation(KernelArgumentBlock& args, unsigne
_r_debug.r_map = map;
r_debug_tail = map;
/* gdb expects the linker to be in the debug shared object list.
* Without this, gdb has trouble locating the linker's ".text"
* and ".plt" sections. Gdb could also potentially use this to
* relocate the offset of our exported 'rtld_db_dlactivity' symbol.
* Don't use soinfo_alloc(), because the linker shouldn't
* be on the soinfo list.
*/
static soinfo linker_soinfo;
strlcpy(linker_soinfo.name, "/system/bin/linker", sizeof(linker_soinfo.name));
linker_soinfo.flags = 0;
linker_soinfo.base = linker_base;
/*
* Set the dynamic field in the link map otherwise gdb will complain with
* the following:
* warning: .dynamic section for "/system/bin/linker" is not at the
* expected address (wrong library or version mismatch?)
/* gdb expects the linker to be in the debug shared object list.
* Without this, gdb has trouble locating the linker's ".text"
* and ".plt" sections. Gdb could also potentially use this to
* relocate the offset of our exported 'rtld_db_dlactivity' symbol.
* Don't use soinfo_alloc(), because the linker shouldn't
* be on the soinfo list.
*/
Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_base;
Elf32_Phdr *phdr = (Elf32_Phdr*)((unsigned char*) linker_base + elf_hdr->e_phoff);
phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base,
&linker_soinfo.dynamic, NULL, NULL);
insert_soinfo_into_debug_map(&linker_soinfo);
{
static soinfo linker_soinfo;
strlcpy(linker_soinfo.name, "/system/bin/linker", sizeof(linker_soinfo.name));
linker_soinfo.flags = 0;
linker_soinfo.base = linker_base;
/*
* Set the dynamic field in the link map otherwise gdb will complain with
* the following:
* warning: .dynamic section for "/system/bin/linker" is not at the
* expected address (wrong library or version mismatch?)
*/
Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_base;
Elf32_Phdr *phdr = (Elf32_Phdr*)((unsigned char*) linker_base + elf_hdr->e_phoff);
phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base,
&linker_soinfo.dynamic, NULL, NULL);
insert_soinfo_into_debug_map(&linker_soinfo);
}
// Extract information passed from the kernel.
si->phdr = reinterpret_cast<Elf32_Phdr*>(args.getauxval(AT_PHDR));
@ -1870,7 +1880,7 @@ static unsigned __linker_init_post_relocation(KernelArgumentBlock& args, unsigne
break;
}
}
si->dynamic = (unsigned *)-1;
si->dynamic = NULL;
si->refcount = 1;
// Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
@ -1888,14 +1898,14 @@ static unsigned __linker_init_post_relocation(KernelArgumentBlock& args, unsigne
si->CallPreInitConstructors();
for (size_t i = 0; preloads[i] != NULL; ++i) {
preloads[i]->CallConstructors();
for (size_t i = 0; gLdPreloads[i] != NULL; ++i) {
gLdPreloads[i]->CallConstructors();
}
/*After the link_image, the si->load_bias is initialized.
*For so lib, the map->l_addr will be updated in notify_gdb_of_load.
*We need to update this value for so exe here. So Unwind_Backtrace
*for some arch like x86 could work correctly within so exe.
/* After the link_image, the si->load_bias is initialized.
* For so lib, the map->l_addr will be updated in notify_gdb_of_load.
* We need to update this value for so exe here. So Unwind_Backtrace
* for some arch like x86 could work correctly within so exe.
*/
map->l_addr = si->load_bias;
si->CallConstructors();
@ -1919,11 +1929,13 @@ static unsigned __linker_init_post_relocation(KernelArgumentBlock& args, unsigne
unsigned n;
unsigned i;
unsigned count = 0;
for(n = 0; n < 4096; n++){
if(bitmask[n]){
for (n = 0; n < 4096; n++) {
if (bitmask[n]) {
unsigned x = bitmask[n];
for(i = 0; i < 8; i++){
if(x & 1) count++;
for (i = 0; i < 8; i++) {
if (x & 1) {
count++;
}
x >>= 1;
}
}
@ -1989,7 +2001,7 @@ extern "C" unsigned __linker_init(void* raw_args) {
linker_so.base = linker_addr;
linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
linker_so.dynamic = (unsigned*) -1;
linker_so.dynamic = NULL;
linker_so.phdr = phdr;
linker_so.phnum = elf_hdr->e_phnum;
linker_so.flags |= FLAG_LINKER;

View file

@ -50,10 +50,10 @@
struct link_map {
uintptr_t l_addr;
char * l_name;
char* l_name;
uintptr_t l_ld;
struct link_map * l_next;
struct link_map * l_prev;
struct link_map* l_next;
struct link_map* l_prev;
};
// Values for r_debug->state
@ -87,7 +87,7 @@ struct soinfo {
int unused; // DO NOT USE, maintained for compatibility.
unsigned* dynamic;
Elf32_Dyn* dynamic;
unsigned unused2; // DO NOT USE, maintained for compatibility
unsigned unused3; // DO NOT USE, maintained for compatibility
@ -167,14 +167,14 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
soinfo* do_dlopen(const char* name, int flags);
int do_dlclose(soinfo* si);
Elf32_Sym* lookup(const char* name, soinfo** found, soinfo* start);
Elf32_Sym* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start);
soinfo* find_containing_library(const void* addr);
const char* linker_get_error();
Elf32_Sym* soinfo_find_symbol(soinfo* si, const void* addr);
Elf32_Sym* soinfo_lookup(soinfo* si, const char* name);
Elf32_Sym* dladdr_find_symbol(soinfo* si, const void* addr);
Elf32_Sym* dlsym_handle_lookup(soinfo* si, const char* name);
void debugger_init();
void debuggerd_init();
extern "C" void notify_gdb_of_libraries();
#endif

View file

@ -550,7 +550,7 @@ void
phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table,
int phdr_count,
Elf32_Addr load_bias,
Elf32_Addr** dynamic,
Elf32_Dyn** dynamic,
size_t* dynamic_count,
Elf32_Word* dynamic_flags)
{
@ -562,7 +562,7 @@ phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table,
continue;
}
*dynamic = (Elf32_Addr*)(load_bias + phdr->p_vaddr);
*dynamic = reinterpret_cast<Elf32_Dyn*>(load_bias + phdr->p_vaddr);
if (dynamic_count) {
*dynamic_count = (unsigned)(phdr->p_memsz / 8);
}

View file

@ -98,7 +98,7 @@ void
phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table,
int phdr_count,
Elf32_Addr load_bias,
Elf32_Addr** dynamic,
Elf32_Dyn** dynamic,
size_t* dynamic_count,
Elf32_Word* dynamic_flags);