diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-02-11 16:46:21 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-02-11 16:46:21 +0100 |
| commit | c70581abc9380ab57deba3f8076e26191b5c2755 (patch) | |
| tree | 267e6630695ffc7b618d58e0cb01117bd9975abc /src | |
| parent | 5e6af3753292b8da43d4fbee186a78f3e5068141 (diff) | |
| download | box64-c70581abc9380ab57deba3f8076e26191b5c2755.tar.gz box64-c70581abc9380ab57deba3f8076e26191b5c2755.zip | |
Added support for RTLD_DEEPBIND flag on dlopen
Diffstat (limited to 'src')
| -rw-r--r-- | src/elfs/elfloader.c | 72 | ||||
| -rw-r--r-- | src/include/elfloader.h | 6 | ||||
| -rw-r--r-- | src/include/librarian.h | 4 | ||||
| -rw-r--r-- | src/include/library.h | 3 | ||||
| -rw-r--r-- | src/librarian/librarian.c | 52 | ||||
| -rw-r--r-- | src/librarian/library.c | 16 | ||||
| -rw-r--r-- | src/librarian/library_private.h | 5 | ||||
| -rw-r--r-- | src/main.c | 8 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibdl.c | 38 |
9 files changed, 119 insertions, 85 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 4edd194b..8d8500d7 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -445,7 +445,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** return 0; } -int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rel *rel) +int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rel *rel) { int ret_ok = 0; for (int i=0; i<cnt; ++i) { @@ -462,17 +462,19 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rel[i].r_info)]:-1; if(version!=-1) version &=0x7fff; const char* vername = GetSymbolVersion(head, version); - const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname); - const char* weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL; + const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, deepbind, symname); + const char* weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, deepbind, symname):NULL; if(bind==STB_LOCAL) { if(!symname || !symname[0]) { offs = sym->st_value + head->delta; end = offs + sym->st_size; } else { - if(!offs && !end && local_maplib) + if(!offs && !end && local_maplib && deepbind) GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); if(!offs && !end) GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); } } else { // this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now @@ -484,17 +486,21 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* // so weak symbol are the one left if(bind==STB_WEAK) { if(!offs && !end) { - if(!offs && !end && local_maplib) + if(!offs && !end && local_maplib && deepbind) GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); if(!offs && !end) GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); } } else { if(!offs && !end) { - if(!offs && !end && local_maplib) + if(!offs && !end && local_maplib && deepbind) GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); if(!offs && !end) GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); } } } @@ -635,7 +641,7 @@ EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu) } -int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv) +int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv) { int ret_ok = 0; const char* old_globdefver = NULL; @@ -665,8 +671,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t globdefver = old_globdefver; weakdefver = old_weakdefver; } else { - old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname); - old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL; + old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, deepbind, symname); + old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, deepbind, symname):NULL; } if(bind==STB_LOCAL) { if(!symname || !symname[0]) { @@ -677,10 +683,12 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t offs = old_offs; end = old_end; } else { - if(local_maplib) + if(local_maplib && deepbind) GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); if(!offs && !end) GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); } } } else { @@ -696,8 +704,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t offs = old_offs; end = old_end; } else { - GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib) + if(local_maplib && deepbind) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + else + GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); } } else { @@ -705,10 +716,12 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t offs = old_offs; end = old_end; } else { - if(!offs && !end && local_maplib) + if(!offs && !end && local_maplib && deepbind) GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); if(!offs && !end) GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); } } } @@ -921,7 +934,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t } return bindnow?ret_ok:0; } -int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head) +int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { if((head->flags&DF_BIND_NOW) && !bindnow) { bindnow = 1; @@ -931,20 +944,20 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* he int cnt = head->relsz / head->relent; DumpRelTable(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel"); printf_dump(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name); - if(RelocateElfREL(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rel *)(head->rel + head->delta))) + if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rel *)(head->rel + head->delta))) return -1; } if(head->rela) { int cnt = head->relasz / head->relaent; DumpRelATable(head, cnt, (Elf64_Rela *)(head->rela + head->delta), "RelA"); printf_dump(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name); - if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL)) + if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL)) return -1; } return 0; } -int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head) +int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { int need_resolver = 0; if((head->flags&DF_BIND_NOW) && !bindnow) { @@ -956,12 +969,12 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* if(head->pltrel==DT_REL) { DumpRelTable(head, cnt, (Elf64_Rel *)(head->jmprel + head->delta), "PLT"); printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name); - if(RelocateElfREL(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta))) + if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta))) return -1; } else if(head->pltrel==DT_RELA) { DumpRelATable(head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), "PLT"); printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name); - if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver)) + if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver)) return -1; } if(need_resolver) { @@ -1106,6 +1119,9 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea } } + int deepbind = 0; + if(h && h->lib) + deepbind = GetDeepBind(h->lib); printf_dump(LOG_NEVER, "Will look for Symbol to add in DynSym (%zu)\n", h->numDynSym); for (size_t i=0; i<h->numDynSym; ++i) { const char * symname = h->DynStr+h->DynSym[i].st_name; @@ -1117,7 +1133,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta); size_t sz = h->DynSym[i].st_size; int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; - int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetMaplibDefaultVersion(my_context->maplib, (maplib==my_context->maplib)?NULL:maplib, (bind==STB_WEAK)?1:0, symname))?1:0; + int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetMaplibDefaultVersion(my_context->maplib, (maplib==my_context->maplib)?NULL:maplib, (bind==STB_WEAK)?1:0, deepbind, symname))?1:0; if(version!=-1) version &= 0x7fff; const char* vername = GetSymbolVersion(h, version); if(add_default) { @@ -1155,7 +1171,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the uname(1) man page description of the -i option). For more details of this token expansion, see “System Specific Shared Objects” */ -int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu) +int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu) { if(h->needed) // already done return 0; @@ -1235,7 +1251,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64c h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; // TODO: Add LD_LIBRARY_PATH and RPATH handling - if(AddNeededLib(maplib, local, bindnow, h->needed, h, box64, emu)) { + if(AddNeededLib(maplib, local, bindnow, deepbind, h->needed, h, box64, emu)) { printf_log(LOG_INFO, "Error loading one of needed lib\n"); if(!allow_missing_libs) return 1; //error... @@ -1889,10 +1905,14 @@ EXPORT void PltResolver(x64emu_t* emu) library_t* lib = h->lib; lib_t* local_maplib = GetMaplib(lib); - const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 0, symname); - const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 1, symname):NULL; - GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib) { + int deepbind = GetDeepBind(lib); + const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 0, deepbind, symname); + const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 1, deepbind, symname):NULL; + if(!offs && !end && local_maplib && deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); + else + GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib && !deepbind) { GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); } if(!offs && !end && !version) diff --git a/src/include/elfloader.h b/src/include/elfloader.h index bc09ad31..80289c5c 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -26,13 +26,13 @@ int CalcLoadAddr(elfheader_t* head); int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin); void FreeElfMemory(elfheader_t* head); int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded); -int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head); -int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head); +int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, int deepbind, elfheader_t* head); +int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, int deepbind, elfheader_t* head); void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign); uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h); uintptr_t GetLastByte(elfheader_t* h); void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h); -int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu); +int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu); uintptr_t GetElfInit(elfheader_t* h); uintptr_t GetElfFini(elfheader_t* h); void RefreshElfTLS(elfheader_t* h); diff --git a/src/include/librarian.h b/src/include/librarian.h index 13cb3890..2864f246 100644 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -21,7 +21,7 @@ void FreeDLPrivate(dlprivate_t **lib); box64context_t* GetLibrarianContext(lib_t* maplib); kh_mapsymbols_t* GetGlobalData(lib_t* maplib); -int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error +int AddNeededLib(lib_t* maplib, int local, int bindnow, int deepbind, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu); library_t* GetLibMapLib(lib_t* maplib, const char* name); library_t* GetLibInternal(const char* name); @@ -39,7 +39,7 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c void MapLibRemoveLib(lib_t* maplib, library_t* lib); void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref); -const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname); +const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, int deepbind, const char* symname); const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib); diff --git a/src/include/library.h b/src/include/library.h index b08927e0..4cc1012f 100644 --- a/src/include/library.h +++ b/src/include/library.h @@ -17,7 +17,7 @@ typedef struct elfheader_s elfheader_t; library_t *NewLibrary(const char* path, box64context_t* box64, elfheader_t* verneeded); int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu); -int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu); +int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, int deepbind, x64emu_t* emu); char* GetNameLib(library_t *lib); int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name) @@ -28,6 +28,7 @@ char** GetNeededLibsNames(library_t* lib); int GetNeededLibsN(library_t* lib); library_t* GetNeededLib(library_t* lib, int idx); lib_t* GetMaplib(library_t* lib); +int GetDeepBind(library_t* lib); int GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped) elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped) diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index 52e4def3..cc8c746c 100644 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -269,7 +269,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in return 0; } -int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) +int AddNeededLib_init(lib_t* maplib, int local, int bindnow, int deepbind, library_t* lib, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { if(!lib) // no lib, error is already detected, no need to return a new one return 0; @@ -283,7 +283,7 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf } else { // it's an emulated lib, // load dependancies and launch init sequence - if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box64, emu)) { + if(LoadNeededLibs(mainelf, maplib, 0, bindnow, deepbind, box64, emu)) { printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); return 1; } @@ -295,7 +295,7 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf tmp.size = tmp.cap = 1; tmp.names = names; tmp.libs = libs; - AddNeededLib(maplib, 0, 0, &tmp, verneeded, box64, emu); + AddNeededLib(maplib, 0, 0, deepbind, &tmp, verneeded, box64, emu); } if(!strcmp(GetNameLib(lib), "libmss.so.6")) { char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit... @@ -304,11 +304,11 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf tmp.size = tmp.cap = 2; tmp.names = names; tmp.libs = libs; - AddNeededLib(maplib, 0, 0, &tmp, verneeded, box64, emu); + AddNeededLib(maplib, 0, 0, deepbind, &tmp, verneeded, box64, emu); } // finalize the lib - if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) { + if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, deepbind, emu)) { printf_dump(LOG_DEBUG, "Failure to finalizing lib => fail\n"); return 1; } @@ -330,7 +330,7 @@ void AddNeededLib_remove(lib_t* maplib, int local, library_t** lib, box64context } EXPORTDYN -int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) +int AddNeededLib(lib_t* maplib, int local, int bindnow, int deepbind, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { if(!needed) // no needed libs, no problems return 0; @@ -349,7 +349,7 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, e } // add dependant libs and init them for (int i=0; i<needed->size; ++i) - if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], verneeded, box64, emu)) { + if(AddNeededLib_init(maplib, local, bindnow, deepbind, needed->libs[i], verneeded, box64, emu)) { printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]); if(!allow_missing_libs) ret = 1; } @@ -386,8 +386,8 @@ EXPORTDYN uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername) { uintptr_t start = 0, end = 0; - const char *globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, name); - const char *weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, name); + const char *globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, 0, name); + const char *weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, 0, name); if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, globdefver, weakdefver)) return start; return 0; @@ -652,28 +652,28 @@ int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* star return 0; } -const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t* local_maplib, int isweak, const char* symname) +static const char* internal_GetMaplibDefaultVersion(lib_t* maplib, int isweak, const char* symname) { - const char* ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(my_context->elfs[0]):GetGlobalDefaultVersion(my_context->elfs[0]), symname); - if(ret) - return ret; - for(int i=0; i<maplib->libsz; ++i) { + const char* ret = NULL; + for(int i=0; maplib && i<maplib->libsz; ++i) { elfheader_t *h = GetElf(maplib->libraries[i]); if(h) ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname); if(ret) return ret; } - if(local_maplib) - for(int i=0; i<local_maplib->libsz; ++i) { - elfheader_t *h = GetElf(local_maplib->libraries[i]); - if(h) - ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname); - if(ret) - return ret; - } - - return NULL; + return ret; +} +const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t* local_maplib, int isweak, int deepbind, const char* symname) +{ + const char* ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(my_context->elfs[0]):GetGlobalDefaultVersion(my_context->elfs[0]), symname); + if(ret) + return ret; + ret = internal_GetMaplibDefaultVersion(deepbind?local_maplib:maplib, isweak, symname); + if(ret) + return ret; + ret = internal_GetMaplibDefaultVersion(deepbind?maplib:local_maplib, isweak, symname); + return ret; } elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername) @@ -684,7 +684,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co int weak = 0; elfheader_t* ret = NULL; // check with default version... - const char* defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, name); + const char* defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, 0, name); if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver)) return my_context->elfs[0]; @@ -702,7 +702,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co } } - defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, name); + defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, 0, name); if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver)) ret = my_context->elfs[0]; for(int i=0; i<maplib->libsz; ++i) { diff --git a/src/librarian/library.c b/src/librarian/library.c index eb34ccbb..cb5862ee 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -238,7 +238,7 @@ static void initWrappedLib(library_t *lib, box64context_t* context) { lib->type = LIB_WRAPPED; lib->w.refcnt = 1; // Call librarian to load all dependant elf - if(AddNeededLib(context->maplib, 0, 0, lib->w.needed, NULL, context, thread_get_emu())) { + if(AddNeededLib(context->maplib, 0, 0, 0, lib->w.needed, NULL, context, thread_get_emu())) { printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name); return; } @@ -500,21 +500,22 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu) } return 0; } -int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu) +int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, int deepbind, x64emu_t* emu) { if(!lib) return 0; + lib->deepbind = deepbind; if(lib->type==LIB_EMULATED) { if(lib->e.finalized) return 0; lib->e.finalized = 1; elfheader_t *elf_header = my_context->elfs[lib->e.elf_index]; // finalize relocations - if(RelocateElf(my_context->maplib, local_maplib, bindnow, elf_header)) { + if(RelocateElf(my_context->maplib, local_maplib, bindnow, deepbind, elf_header)) { printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name); return 1; } - if(RelocateElfPlt(my_context->maplib, local_maplib, bindnow, elf_header)) { + if(RelocateElfPlt(my_context->maplib, local_maplib, bindnow, deepbind, elf_header)) { printf_log(LOG_NONE, "Error: relocating Plt symbols in elf %s\n", lib->name); return 1; } @@ -1043,6 +1044,13 @@ lib_t* GetMaplib(library_t* lib) return lib->maplib; } +int GetDeepBind(library_t* lib) +{ + if(!lib) + return 0; + return lib->deepbind; +} + linkmap_t* getLinkMapLib(library_t* lib) { linkmap_t* lm = my_context->linkmap; diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h index 6bb291de..b7e1e45d 100644 --- a/src/librarian/library_private.h +++ b/src/librarian/library_private.h @@ -68,8 +68,9 @@ typedef struct elib_s { typedef struct library_s { char* name; // <> path char* path; // original path - int nbdot; // nombre of "." after .so - int type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined + int8_t nbdot; // nombre of "." after .so + int8_t type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined + uint8_t deepbind; wrappedlib_fini_t fini; wrappedlib_get_t getglobal; // get global (non-weak) wrappedlib_get_t getweak; // get weak symbol diff --git a/src/main.c b/src/main.c index 7c4f806b..7c74bc5a 100644 --- a/src/main.c +++ b/src/main.c @@ -2002,7 +2002,7 @@ int main(int argc, const char **argv, char **env) { for(int i=0; i<ld_preload.size; ++i) { needed_libs_t* tmp = new_neededlib(1); tmp->names[0] = ld_preload.paths[i]; - if(AddNeededLib(my_context->maplib, 0, 0, tmp, elf_header, my_context, emu)) { + if(AddNeededLib(my_context->maplib, 0, 0, 0, tmp, elf_header, my_context, emu)) { printf_log(LOG_INFO, "Warning, cannot pre-load %s\n", tmp->names[0]); RemoveNeededLib(my_context->maplib, 0, tmp, my_context, emu); } else { @@ -2014,20 +2014,20 @@ int main(int argc, const char **argv, char **env) { } FreeCollection(&ld_preload); // Call librarian to load all dependant elf - if(LoadNeededLibs(elf_header, my_context->maplib, 0, 0, my_context, emu)) { + if(LoadNeededLibs(elf_header, my_context->maplib, 0, 0, 0, my_context, emu)) { printf_log(LOG_NONE, "Error: Loading needed libs in elf %s\n", my_context->argv[0]); FreeBox64Context(&my_context); return -1; } // reloc... printf_log(LOG_DEBUG, "And now export symbols / relocation for %s...\n", ElfName(elf_header)); - if(RelocateElf(my_context->maplib, NULL, 0, elf_header)) { + if(RelocateElf(my_context->maplib, NULL, 0, 0, elf_header)) { printf_log(LOG_NONE, "Error: Relocating symbols in elf %s\n", my_context->argv[0]); FreeBox64Context(&my_context); return -1; } // and handle PLT - RelocateElfPlt(my_context->maplib, NULL, 0, elf_header); + RelocateElfPlt(my_context->maplib, NULL, 0, 0, elf_header); // deferred init setupTraceInit(); RunDeferredElfInit(emu); diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 11278c1c..48b56e46 100644 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -90,6 +90,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) dlprivate_t *dl = my_context->dlprivate; size_t dlopened = 0; int is_local = (flag&0x100)?0:1; // if not global, then local, and that means symbols are not put in the global "pot" for other libs + int deepbind = (flag&0x0008)?1:0; // RTLD_DEEPBIND means LOCAL before GLOBAL scope during symbol resolution CLEARERR if(filename) { char* rfilename = (char*)alloca(MAX_PATH); @@ -189,7 +190,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) int bindnow = (!box64_musl && (flag&0x2))?1:0; needed_libs_t *tmp = new_neededlib(1); tmp->names[0] = rfilename; - if(AddNeededLib(NULL, is_local, bindnow, tmp, NULL, my_context, emu)) { + if(AddNeededLib(NULL, is_local, bindnow, deepbind, tmp, NULL, my_context, emu)) { printf_dlsym(strchr(rfilename,'/')?LOG_DEBUG:LOG_INFO, "Warning: Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag); if(!dl->last_error) dl->last_error = box_calloc(1, 129); @@ -256,6 +257,7 @@ char* my_dlerror(x64emu_t* emu) KHASH_SET_INIT_INT(libs); +// TODO: deepbind is probably not followed correctly here int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername, const char* globdefver, const char* weakdefver) { if(!lib) @@ -304,8 +306,8 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) printf_dlsym(LOG_DEBUG, "%04d|Call to dlsym(%p, \"%s\")%s", GetTID(), handle, rsymbol, dlsym_error?"":"\n"); if(handle==NULL) { // special case, look globably - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, rsymbol); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); pthread_mutex_unlock(&mutex); @@ -320,8 +322,8 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } if(handle==(void*)~0LL) { // special case, look globably but no self (RTLD_NEXT) - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, rsymbol); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); elfheader_t *elf = FindElfAddress(my_context, *(uintptr_t*)R_RSP); // use return address to guess "self" if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, globdefver, weakdefver)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); @@ -355,8 +357,9 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) return NULL; } if(dl->dllibs[nlib].lib) { - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, rsymbol); + int deepbind = GetDeepBind(dl->dllibs[nlib].lib); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, deepbind, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, deepbind, rsymbol); if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, -1, NULL, globdefver, weakdefver)==0) { // not found printf_dlsym(LOG_NEVER, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol); @@ -370,8 +373,8 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } else { // still usefull? // => look globably - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, rsymbol); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); pthread_mutex_unlock(&mutex); @@ -460,8 +463,8 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) printf_dlsym(LOG_DEBUG, "Call to dlvsym(%p, \"%s\", %s)%s", handle, rsymbol, vername?vername:"(nil)", dlsym_error?"":"\n"); if(handle==NULL) { // special case, look globably - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, rsymbol); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, version, vername, globdefver, weakdefver)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); return (void*)start; @@ -474,8 +477,8 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) } if(handle==(void*)~0LL) { // special case, look globably but no self (RTLD_NEXT) - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, rsymbol); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); elfheader_t *elf = FindElfAddress(my_context, *(uintptr_t*)R_RSP); // use return address to guess "self" if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, version, vername, globdefver, weakdefver)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); @@ -505,8 +508,9 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) return NULL; } if(dl->dllibs[nlib].lib) { - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, rsymbol); + int deepbind = GetDeepBind(dl->dllibs[nlib].lib); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, deepbind, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, deepbind, rsymbol); if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, version, vername, globdefver, weakdefver)==0) { // not found printf_dlsym(LOG_NEVER, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol, vername?vername:"(nil)"); @@ -518,8 +522,8 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) } } else { // still usefull? - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, rsymbol); + const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); + const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); return (void*)start; |