diff --git a/linker/debugger.cpp b/linker/debugger.cpp index 492ca4b00..586cd2f8f 100644 --- a/linker/debugger.cpp +++ b/linker/debugger.cpp @@ -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); diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index a5f8944d8..0603d40e1 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -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(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); diff --git a/linker/linker.cpp b/linker/linker.cpp index d36b1f6b1..e08eaba43 100755 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -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; inchain; i++) { + for (i=0; inchain; 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(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; diff --git a/linker/linker.h b/linker/linker.h index cf6fff9f1..dac555a4c 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -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 diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index 94260fa9c..acd18cd8f 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -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(load_bias + phdr->p_vaddr); if (dynamic_count) { *dynamic_count = (unsigned)(phdr->p_memsz / 8); } diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h index d9a48208f..ec5515905 100644 --- a/linker/linker_phdr.h +++ b/linker/linker_phdr.h @@ -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);