diff options
| author | ptitSeb <seebastien.chev@gmail.com> | 2023-08-27 11:38:00 +0200 |
|---|---|---|
| committer | ptitSeb <seebastien.chev@gmail.com> | 2023-08-27 11:38:00 +0200 |
| commit | c7db4470e4ea0bab6fb05f29b1f4cfb69d7b7afe (patch) | |
| tree | a43df95f8a831ec2d6ee30041311b31d4b0dc38b /src | |
| parent | 2e55fc8c3207df407f775a0d531519ad561b8817 (diff) | |
| download | box64-c7db4470e4ea0bab6fb05f29b1f4cfb69d7b7afe.tar.gz box64-c7db4470e4ea0bab6fb05f29b1f4cfb69d7b7afe.zip | |
[ELFLOADER] Better handling of dlopen library without RTLD_GLOBAL flags
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/box64context.h | 1 | ||||
| -rw-r--r-- | src/include/librarian.h | 1 | ||||
| -rw-r--r-- | src/librarian/librarian.c | 106 | ||||
| -rw-r--r-- | src/librarian/library.c | 40 |
4 files changed, 100 insertions, 48 deletions
diff --git a/src/include/box64context.h b/src/include/box64context.h index aa8c95b6..0a8f6532 100644 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -59,6 +59,7 @@ typedef struct needed_libs_s { int size; char** names; library_t** libs; + int nb_done; } needed_libs_t; void free_neededlib(needed_libs_t* needed); diff --git a/src/include/librarian.h b/src/include/librarian.h index 6fc89320..13cb3890 100644 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -37,6 +37,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver); 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); diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index 072ef811..fad45e4f 100644 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -41,7 +41,7 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu) /*if((*maplib)->ownlibs && (*maplib)->libsz) { for(int i=0; i<(*maplib)->libsz; ++i) { - printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); + printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); DecRefCount(&(*maplib)->libraries[i], emu); } }*/ @@ -105,6 +105,28 @@ void MapLibAddLib(lib_t* maplib, library_t* lib) ++maplib->libsz; } +void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref) +{ + if(libraryInMapLib(maplib, lib)) + return; + if (maplib->libsz == maplib->libcap) { + maplib->libcap += 8; + maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*)); + } + // find insersion point + int point = ref?maplib->libsz:0; + if(ref) + for(int i=0; i<maplib->libsz; ++i) + if(maplib->libraries[i]==ref) { + point = i; + i = maplib->libsz; + } + if(point<maplib->libsz) + memmove(&maplib->libraries[point+1], &maplib->libraries[point], sizeof(library_t*)*(maplib->libsz-point)); + maplib->libraries[point] = lib; + ++maplib->libsz; +} + static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src) { if(!src) @@ -180,29 +202,26 @@ int isLibLocal(library_t* lib) static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { const char* path = needed->names[n]; - printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":""); + printf_dump(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":""); // first check if lib is already loaded library_t *lib = getLib(my_context->maplib, path); if(lib) { IncRefCount(lib, emu); // increment cntref needed->libs[n] = lib; - printf_log(LOG_DEBUG, "Already present in maplib => success\n"); + printf_dump(LOG_DEBUG, "Already present in maplib => success\n"); return 0; } // check also in the local loaded lib lib = getLib(my_context->local_maplib, path); if(lib) { - printf_log(LOG_DEBUG, "Already present in local_maplib => success\n"); + printf_dump(LOG_DEBUG, "Already present in local_maplib => success\n"); needed->libs[n] = lib; IncRefCount(lib, emu); // increment cntref if(local) { // add lib to maplib... if(maplib) { - if(lib->maplib) { - MapLibAddMapLib(maplib, lib, lib->maplib); - } if(!libraryInMapLib(maplib, lib)) - MapLibAddLib(maplib, lib); + MapLibPrependLib(maplib, lib, NULL); // todo: Also insert libs needed by lib, after lib? But current lib->maplib is probably not the solution if(maplib->ownlibs) MapLibRemoveMapLib(my_context->local_maplib, maplib); } @@ -215,7 +234,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int // load a new one needed->libs[n] = lib = NewLibrary(path, box64, verneeded); if(!lib) { - printf_log(LOG_DEBUG, "Faillure to create lib => fail\n"); + printf_dump(LOG_DEBUG, "Faillure to create lib => fail\n"); return 1; //Error } @@ -224,8 +243,6 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int MapLibAddLib(my_context->local_maplib, lib); if(maplib) { MapLibAddLib(maplib, lib); - if(!lib->maplib) - lib->maplib = maplib; } else { lib->maplib = NewLibrarian(box64, 0); MapLibAddLib(lib->maplib, lib); @@ -238,7 +255,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int maplib = (local)?lib->maplib:my_context->maplib; if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs - printf_log(LOG_DEBUG, "Failure to Add lib => fail\n"); + printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n"); return 1; } @@ -247,7 +264,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int linkmap_t *lm = addLinkMapLib(lib); if(!lm) { // Crashed already - printf_log(LOG_DEBUG, "Failure to add lib linkmap\n"); + printf_dump(LOG_DEBUG, "Failure to add lib linkmap\n"); return 1; } lm->l_addr = (Elf64_Addr)GetElfDelta(lib->e.elf); @@ -272,7 +289,7 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf // it's an emulated lib, // load dependancies and launch init sequence if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box64, emu)) { - printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); + printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); return 1; } // some special case, where dependancies may not be correct @@ -297,12 +314,12 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf // finalize the lib if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) { - printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n"); + printf_dump(LOG_DEBUG, "Failure to finalizing lib => fail\n"); return 1; } } // success - printf_log(LOG_DEBUG, "Created lib and added to maplib => success\n"); + printf_dump(LOG_DEBUG, "Created lib and added to maplib => success\n"); return 0; } @@ -351,20 +368,20 @@ void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box64conte return; for(int i=0; i<needed->size; ++i) { if(box64_log>=LOG_DEBUG && needed->libs[i]) - printf_log(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]); + printf_dump(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]); AddNeededLib_remove(maplib, local, &needed->libs[i], box64, emu); } } library_t* GetLibMapLib(lib_t* maplib, const char* name) { - printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); + printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); return getLib(maplib, name); } library_t* GetLibInternal(const char* name) { - printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); + printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); library_t* lib = getLib(my_context->maplib, name); if(!lib) lib = getLib(my_context->local_maplib, name); return lib; @@ -388,6 +405,20 @@ static int isLocal(elfheader_t* self, library_t* l) return 0; } +static void CheckNeededLibs(needed_libs_t* needed) +{ + while(needed->nb_done<needed->size) { + library_t* lib = needed->libs[needed->nb_done++]; + if(lib) { + int n = GetNeededLibsN(lib); + char** names = GetNeededLibsNames(lib); + for (int i=0; i<n; ++i) { + add1lib_neededlib(needed, GetNeededLib(lib, i), names[i]); + } + } + } +} + int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver) { assert(self); // need self for this one @@ -449,29 +480,36 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin if(my_context->preload) for(int i=0; i<my_context->preload->size; ++i) if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver)) - if(*start) + if(*start) { return 1; + } // search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self) if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver)) - if(*start) + if(*start) { return 1; - // TODO: create a temporary map to search lib only 1 time, and in order of needed... + } + // This kind-of create a map to search lib only 1 time, and in order of needed... + if(my_context->neededlibs) + CheckNeededLibs(my_context->neededlibs); // search in needed libs from neededlibs first, in order if(my_context->neededlibs) for(int i=0; i<my_context->neededlibs->size; ++i) if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver)) - if(*start) + if(*start) { return 1; + } // search in global symbols if(maplib) { if(self && self!=my_context->elfs[0] && self!=(void*)1) if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver)) - if(*start) + if(*start) { return 1; + } for(int i=0; i<maplib->libsz; ++i) { if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver)) - if(*start) + if(*start) { return 1; + } } } @@ -479,14 +517,24 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin int ok = 0; // GetSymbolStartEnd should not change start/end if symbol is not found if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver)) - if(*start) + if(*start) { ok = 1; + } + + // search in needed libs from neededlibs first, in order + if(my_context->neededlibs) + for(int i=0; i<my_context->neededlibs->size; ++i) + if(GetLibWeakSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), weakdefver)) + if(*start) { + return 1; + } if(maplib) for(int i=0; i<maplib->libsz; ++i) { if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver)) - if(*start) + if(*start) { ok = 1; + } } // nope, not found return (ok && *start)?1:0; @@ -540,7 +588,9 @@ static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver)) if(*start) return 1; - // TODO: create a temporary map to search lib only 1 time, and in order of needed... + // This kind-of create a map to search lib only 1 time, and in order of needed... + if(my_context->neededlibs) + CheckNeededLibs(my_context->neededlibs); // search in needed libs from neededlibs first, in order if(my_context->neededlibs) for(int i=0; i<my_context->neededlibs->size; ++i) diff --git a/src/librarian/library.c b/src/librarian/library.c index 86eb507f..a6c355d1 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -209,7 +209,7 @@ static void initWrappedLib(library_t *lib, box64context_t* context) { printf_log(LOG_NONE, "Error initializing native %s (last dlerror is %s)\n", lib->name, error_str); return; // non blocker... } - printf_log(LOG_INFO, "Using native(wrapped) %s\n", lib->name); + printf_dump(LOG_INFO, "Using native(wrapped) %s\n", lib->name); lib->fini = wrappedlibs[i].fini; lib->getglobal = WrappedLib_GetGlobal; lib->getweak = WrappedLib_GetWeak; @@ -225,12 +225,12 @@ static void initWrappedLib(library_t *lib, box64context_t* context) { linkmap_t *lm = addLinkMapLib(lib); if(!lm) { // Crashed already - printf_log(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name); + printf_dump(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name); break; } struct link_map real_lm; if(dlinfo(lib->w.lib, RTLD_DI_LINKMAP, &real_lm)) { - printf_log(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name); + printf_dump(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name); } lm->l_addr = real_lm.l_addr; lm->l_name = real_lm.l_name; @@ -251,7 +251,7 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* } elfheader_t *elf_header = LoadAndCheckElfHeader(f, libname, 0); if(!elf_header) { - printf_log(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming... + printf_dump(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming... fclose(f); return 0; } @@ -302,21 +302,21 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* lib->path = box_strdup(libname); } - printf_log(LOG_INFO, "Using emulated %s\n", libname); + printf_dump(LOG_INFO, "Using emulated %s\n", libname); #ifdef DYNAREC if(libname && box64_dynarec_bleeding_edge && strstr(libname, "libmonobdwgc-2.0.so")) { - printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n"); + printf_dump(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n"); box64_dynarec_bigblock = 0; box64_dynarec_strongmem = 1; } if(libname && box64_dynarec_jvm && strstr(libname, "libjvm.so")) { - printf_log(LOG_INFO, "libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n"); + printf_dump(LOG_INFO, "libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n"); box64_dynarec_bigblock = 0; box64_dynarec_strongmem = 1; } #endif if(libname && box64_libcef && strstr(libname, "libcef.so")) { - printf_log(LOG_INFO, "libcef detected, using malloc_hack_2\n"); + printf_dump(LOG_INFO, "libcef detected, using malloc_hack_2\n"); box64_malloc_hack = 2; } return 1; @@ -370,7 +370,7 @@ static int isEssentialLib(const char* name) { library_t *NewLibrary(const char* path, box64context_t* context, elfheader_t* verneeded) { - printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path); + printf_dump(LOG_DEBUG, "Trying to load \"%s\"\n", path); library_t *lib = (library_t*)box_calloc(1, sizeof(library_t)); lib->path = box_realpath(path, NULL); if(!lib->path) @@ -381,7 +381,7 @@ library_t *NewLibrary(const char* path, box64context_t* context, elfheader_t* ve lib->name = Path2Name(path); lib->nbdot = NbDot(lib->name); lib->type = LIB_UNNKNOW; - printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name); + printf_dump(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name); if(box64_nopulse) { if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) { box_free(lib->name); @@ -466,12 +466,12 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* int weak; if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL, NULL, NULL)) { SetTraceEmu(trace_start, trace_end); - printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); + printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); box_free(trace_func); trace_func = NULL; } else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, -1, NULL, 0, NULL)) { SetTraceEmu(trace_start, trace_end); - printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); + printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); box_free(trace_func); trace_func = NULL; } @@ -544,7 +544,7 @@ void Free1Library(library_t **the_lib, x64emu_t* emu) library_t* lib = *the_lib; - printf_log(LOG_DEBUG, "Free1Library %s\n", lib->name); + printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name); // remove lib from maplib/local_maplib... if(my_context) { MapLibRemoveLib(my_context->maplib, lib); @@ -653,7 +653,7 @@ int IsSameLib(library_t* lib, const char* path) } int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) { - if(!name[0]) + if(!lib || !name[0]) return 0; khint_t k; kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap); @@ -865,7 +865,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui symbol = GetNativeSymbolUnversioned(lib->w.lib, newname); } if(!symbol) { - printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name); + printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name); return 0; } s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name); @@ -921,7 +921,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui symbol = GetNativeSymbolUnversioned(lib->w.lib, newname); } if(!symbol) { - printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name); + printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name); return 0; } s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name); @@ -946,7 +946,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui if(!symbol) symbol = GetNativeSymbolUnversioned(lib->w.lib, kh_value(lib->w.symbol2map, k).name); if(!symbol) { - printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->w.symbol2map, k).name, lib->name); + printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->w.symbol2map, k).name, lib->name); return 0; } s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name); @@ -981,7 +981,7 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add int GetNeededLibsN(library_t* lib) { switch (lib->type) { case LIB_WRAPPED: return lib->w.needed?lib->w.needed->size:0; - case LIB_EMULATED: return lib->e.elf->needed->size; + case LIB_EMULATED: return lib->e.elf->needed?lib->e.elf->needed->size:0; } return 0; } @@ -999,11 +999,11 @@ library_t* GetNeededLib(library_t* lib, int idx) } return NULL; } -char** GetNeededLibs(library_t* lib) +char** GetNeededLibsNames(library_t* lib) { switch (lib->type) { case LIB_WRAPPED: return lib->w.needed?lib->w.needed->names:NULL; - case LIB_EMULATED: return lib->e.elf->needed->names; + case LIB_EMULATED: return lib->e.elf->needed?lib->e.elf->needed->names:NULL; } return NULL; } |