diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/elfs/elfloader.c | 65 | ||||
| -rwxr-xr-x | src/include/elfloader.h | 2 | ||||
| -rwxr-xr-x | src/librarian/library.c | 18 |
3 files changed, 85 insertions, 0 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index d688d0a8..0927ab3c 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -1539,6 +1539,71 @@ void ElfAttachLib(elfheader_t* head, library_t* lib) head->lib = lib; } +typedef struct search_symbol_s{ + const char* name; + void* addr; + void* lib; +} search_symbol_t; +int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* data) +{ + search_symbol_t* s = (search_symbol_t*)data; + + for(int j = 0; j<info->dlpi_phnum; ++j) { + if (info->dlpi_phdr[j].p_type == PT_DYNAMIC) { + ElfW(Sym)* sym = NULL; + ElfW(Word) sym_cnt = 0; + ElfW(Verdef)* verdef = NULL; + ElfW(Word) verdef_cnt = 0; + char *strtab = NULL; + ElfW(Dyn)* dyn = (ElfW(Dyn)*)(info->dlpi_addr + info->dlpi_phdr[j].p_vaddr); //Dynamic Section + // grab the needed info + while(dyn->d_tag != DT_NULL) { + switch(dyn->d_tag) { + case DT_STRTAB: + strtab = (char *)(dyn->d_un.d_ptr); + break; + case DT_VERDEF: + verdef = (ElfW(Verdef)*)(info->dlpi_addr + dyn->d_un.d_ptr); + break; + case DT_VERDEFNUM: + verdef_cnt = dyn->d_un.d_val; + break; + } + ++dyn; + } + if(strtab && verdef && verdef_cnt) { + // Look fr all defined versions now + ElfW(Verdef)* v = verdef; + for(int k=0; k<verdef_cnt; ++k) { + ElfW(Verdaux)* vda = (ElfW(Verdaux)*)(((uintptr_t)v) + v->vd_aux); + for(int i=0; i<v->vd_cnt; ++i) { + const char* vername = &strtab[vda->vda_name]; + if((s->addr = dlvsym(s->lib, s->name, vername))) { + printf_log(LOG_DEBUG, "Found symbol with version %s, value = %p\n", vername, s->addr); + return 1; // stop searching + } + vda = (ElfW(Verdaux)*)(((uintptr_t)vda) + vda->vda_next); + } + v = (ElfW(Verdef)*)((uintptr_t)v + v->vd_next); + } + } + } + } + return 0; +} + +void* GetNativeSymbolUnversionned(void* lib, const char* name) +{ + // try to find "name" in loaded elf, whithout checking for the symbol version (like dlsym, but no version check) + search_symbol_t s; + s.name = name; + s.addr = NULL; + s.lib = lib; + printf_log(LOG_INFO, "Look for %s in loaded elfs\n", name); + dl_iterate_phdr(dl_iterate_phdr_findsymbol, &s); + return s.addr; +} + uintptr_t pltResolver = ~0LL; EXPORT void PltResolver(x64emu_t* emu) { diff --git a/src/include/elfloader.h b/src/include/elfloader.h index afef7981..c1b4ce89 100755 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -60,4 +60,6 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index); const char* VersionnedName(const char* name, int ver, const char* vername); int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2); +void* GetNativeSymbolUnversionned(void* lib, const char* name); + #endif //__ELF_LOADER_H_ diff --git a/src/librarian/library.c b/src/librarian/library.c index 86638591..647d014c 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -704,6 +704,14 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui strcat(newname, name); symbol = dlsym(lib->priv.w.lib, newname); } + if(!symbol) + symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, name); + if(!symbol && lib->priv.w.altprefix) { + char newname[200]; + strcpy(newname, lib->priv.w.altprefix); + strcat(newname, name); + symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, newname); + } if(!symbol) { printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name); return 0; @@ -741,6 +749,14 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui strcat(newname, name); symbol = dlsym(lib->priv.w.lib, newname); } + if(!symbol) + symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, name); + if(!symbol && lib->priv.w.altprefix) { + char newname[200]; + strcpy(newname, lib->priv.w.altprefix); + strcat(newname, name); + symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, newname); + } if(!symbol) { printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name); return 0; @@ -759,6 +775,8 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui symbol = dlsym(lib->priv.w.lib, kh_value(lib->symbol2map, k).name); if(!symbol) symbol = dlsym(RTLD_DEFAULT, kh_value(lib->symbol2map, k).name); // search globaly maybe + if(!symbol) + symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, kh_value(lib->symbol2map, k).name); if(!symbol) { printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->symbol2map, k).name, lib->name); return 0; |