diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-01-01 16:13:39 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-01-01 16:13:39 +0100 |
| commit | ee5398b3be5d45ec39e21b503d4ee8023a665141 (patch) | |
| tree | e44a6f4233c65c22b41d9219772e548613fb7acc /src | |
| parent | 3d3ab0fedc2b98f7adb84e898ffb32f24a2a1a6a (diff) | |
| download | box64-ee5398b3be5d45ec39e21b503d4ee8023a665141.tar.gz box64-ee5398b3be5d45ec39e21b503d4ee8023a665141.zip | |
Refactored (again) lib init/fini mecanism
Diffstat (limited to 'src')
| -rwxr-xr-x | src/box64context.c | 3 | ||||
| -rwxr-xr-x | src/elfs/elfloader.c | 26 | ||||
| -rwxr-xr-x | src/elfs/elfloader_private.h | 7 | ||||
| -rwxr-xr-x | src/emu/x64emu.c | 2 | ||||
| -rwxr-xr-x | src/emu/x64int3.c | 2 | ||||
| -rwxr-xr-x | src/include/box64context.h | 8 | ||||
| -rwxr-xr-x | src/include/elfloader.h | 2 | ||||
| -rwxr-xr-x | src/include/librarian.h | 2 | ||||
| -rwxr-xr-x | src/include/library.h | 6 | ||||
| -rwxr-xr-x | src/librarian/librarian.c | 139 | ||||
| -rwxr-xr-x | src/librarian/library.c | 153 | ||||
| -rwxr-xr-x | src/librarian/library_private.h | 11 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 18 | ||||
| -rwxr-xr-x | src/main.c | 14 | ||||
| -rwxr-xr-x | src/tools/bridge.c | 2 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibdl.c | 26 |
16 files changed, 213 insertions, 208 deletions
diff --git a/src/box64context.c b/src/box64context.c index a70b40d0..467accfa 100755 --- a/src/box64context.c +++ b/src/box64context.c @@ -302,7 +302,8 @@ void FreeBox64Context(box64context_t** context) if(ctx->tlsdata) box_free(ctx->tlsdata); - free_neededlib(&ctx->neededlibs); + free_neededlib(ctx->neededlibs); + ctx->neededlibs = NULL; if(ctx->emu_sig) FreeX64Emu(&ctx->emu_sig); diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index e0c52008..0a0f0cf2 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -62,6 +62,7 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec) h->mapsymbols = NewMapSymbols(); h->weaksymbols = NewMapSymbols(); h->localsymbols = NewMapSymbols(); + h->refcnt = 1; return h; } @@ -1059,8 +1060,10 @@ $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, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu) +int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu) { + if(h->needed) // already done + return 0; DumpDynamicRPath(h); // update RPATH first for (size_t i=0; i<h->numDynamic; ++i) @@ -1119,22 +1122,21 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib box_free(rpath); } - if(!h->neededlibs && neededlibs) - h->neededlibs = neededlibs; - DumpDynamicNeeded(h); int cnt = 0; for (int i=0; i<h->numDynamic; ++i) if(h->Dynamic[i].d_tag==DT_NEEDED) ++cnt; - const char* nlibs[cnt]; + h->needed = new_neededlib(cnt); + if(h == my_context->elfs[0]) + my_context->neededlibs = h->needed; int j=0; for (int i=0; i<h->numDynamic; ++i) if(h->Dynamic[i].d_tag==DT_NEEDED) - nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; + 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, neededlibs, deplib, local, bindnow, nlibs, cnt, box64, emu)) { + if(AddNeededLib(maplib, local, bindnow, h->needed, box64, emu)) { printf_log(LOG_INFO, "Error loading one of needed lib\n"); if(!allow_missing_libs) return 1; //error... @@ -1185,8 +1187,8 @@ void RunElfInitPltResolver(elfheader_t* h, x64emu_t *emu) return; uintptr_t p = h->initentry + h->delta; h->init_done = 1; - for(int i=0; i<h->neededlibs->size; ++i) { - library_t *lib = h->neededlibs->libs[i]; + for(int i=0; i<h->needed->size; ++i) { + library_t *lib = h->needed->libs[i]; elfheader_t *lib_elf = GetElf(lib); if(lib_elf) RunElfInitPltResolver(lib_elf, emu); @@ -1229,8 +1231,8 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu) return; } h->init_done = 1; - for(int i=0; i<h->neededlibs->size; ++i) { - library_t *lib = h->neededlibs->libs[i]; + for(int i=0; i<h->needed->size; ++i) { + library_t *lib = h->needed->libs[i]; elfheader_t *lib_elf = GetElf(lib); if(lib_elf) RunElfInit(lib_elf, emu); @@ -1289,6 +1291,8 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu) RunFunctionWithEmu(emu, 0, p, 0); } h->init_done = 0; // can be re-inited again... + for(int i=0; i<h->needed->size; ++i) + FiniLibrary(h->needed->libs[i], emu); return; } diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index eb5e81af..c4637535 100755 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -83,15 +83,16 @@ struct elfheader_s { int init_done; int fini_done; + int refcnt; // ref count for the elf - char* memory; // char* and not void* to allow math on memory pointer + char* memory; // char* and not void* to allow math on memory pointer void** multiblock; uintptr_t* multiblock_offs; uint64_t* multiblock_size; int multiblock_n; - library_t *lib; - needed_libs_t *neededlibs; + library_t *lib; // attached lib (exept on main elf) + needed_libs_t* needed; kh_mapsymbols_t *mapsymbols; kh_mapsymbols_t *weaksymbols; diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index d23e10e7..6442adf7 100755 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -182,9 +182,9 @@ void CallAllCleanup(x64emu_t *emu) printf_log(LOG_DEBUG, "Calling atexit registered functions\n"); for(int i=my_context->clean_sz-1; i>=0; --i) { printf_log(LOG_DEBUG, "Call cleanup #%d\n", i); + --my_context->clean_sz; RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a ); } - my_context->clean_sz = 0; box_free(my_context->cleanups); my_context->cleanups = NULL; } diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c index 704ddd5a..d0d71c89 100755 --- a/src/emu/x64int3.c +++ b/src/emu/x64int3.c @@ -80,7 +80,7 @@ static uint8_t Peek8(uintptr_t addr, uintptr_t offset) { return *(uint8_t*)(addr+offset); } -extern int errno; + void x64Int3(x64emu_t* emu, uintptr_t* addr) { if(Peek8(*addr, 0)=='S' && Peek8(*addr, 1)=='C') // Signature for "Out of x86 door" diff --git a/src/include/box64context.h b/src/include/box64context.h index 682cdae8..3d8e0061 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -49,10 +49,13 @@ void free_tlsdatasize(void* p); typedef struct needed_libs_s { int cap; int size; - library_t **libs; + char** names; + library_t** libs; } needed_libs_t; void free_neededlib(needed_libs_t* needed); +needed_libs_t* new_neededlib(int n); +void add1_neededlib(needed_libs_t* needed); typedef struct base_segment_s { uintptr_t base; @@ -95,7 +98,8 @@ typedef struct box64context_s { int elfsize; // number of elf loaded - needed_libs_t neededlibs; // needed libs for main elf + needed_libs_t *neededlibs; // needed libs for main elf + needed_libs_t *preload; uintptr_t ep; // entry point diff --git a/src/include/elfloader.h b/src/include/elfloader.h index 891a62ac..d5116f56 100755 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -31,7 +31,7 @@ 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, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu); +int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, 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 87a78a34..5c1fe0f2 100755 --- 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, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error +int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error library_t* GetLibMapLib(lib_t* maplib, const char* name); library_t* GetLibInternal(const char* name); uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername); diff --git a/src/include/library.h b/src/include/library.h index b88aaa04..4fdfa65a 100755 --- a/src/include/library.h +++ b/src/include/library.h @@ -19,6 +19,7 @@ library_t *NewLibrary(const char* path, box64context_t* box64); 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 ReloadLibrary(library_t* lib, x64emu_t* emu); +int FiniLibrary(library_t* lib, x64emu_t* emu); void InactiveLibrary(library_t* lib); void Free1Library(library_t **lib, x64emu_t* emu); @@ -31,13 +32,14 @@ void fillGLProcWrapper(box64context_t* context); void freeGLProcWrapper(box64context_t* context); void fillALProcWrapper(box64context_t* context); void freeALProcWrapper(box64context_t* context); -needed_libs_t* GetNeededLibs(library_t* lib); -int GetNeededLibN(library_t* lib); +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 GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped) elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped) void* GetHandle(library_t* lib); // NULL if not wrapped +void IncRefCount(library_t* lib); #endif //__LIBRARY_H_ diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index 6ed71edc..5504e961 100755 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -29,39 +29,7 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs) return maplib; } -static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed, library_t* owner) { - if (freed[idx]) return; // Already freed - - library_t *lib = maplib->libraries[idx]; - if(lib==owner) return; // don't free owner of maplib - freed[idx] = 1; // Avoid infinite loops - printf_log(LOG_DEBUG, "Unloading %s\n", lib->name); - for (int i = lib->dependedby.size - 1; i >= 0; --i) { - int j; - for (j = 0; j < maplib->libsz; ++j) { - if (lib->dependedby.libs[i] == maplib->libraries[j]) break; - } - if (j == maplib->libsz) { - // dependant lib already freed - // library as been freed already - continue; - } - if (freed[j] == 1) { - printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->dependedby.libs[i]->name); - continue; - } - freeLibraryRecurse(maplib, emu, j, freed, owner); - if (freed[idx] != 1) { - printf_log(LOG_DEBUG, "Note: library already freed (cyclic dependancy break)\n"); - return; - } - } - - library_t *ptr = maplib->libraries[idx]; - if(maplib->ownlibs/* && (!maplib->owner || ptr->maplib==maplib)*/) - Free1Library(&ptr, emu); - freed[idx] = 2; -} + void FreeLibrarian(lib_t **maplib, x64emu_t *emu) { // should that be in reverse order? @@ -70,24 +38,14 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu) library_t* owner = (*maplib)->owner; (*maplib)->owner = NULL; // to avoid recursive free... + + // free the memory only. All the uninit logic is elsewhere + if((*maplib)->ownlibs && (*maplib)->libsz) { - printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib); - char *freed = (char*)box_calloc((*maplib)->libsz, sizeof(char)); - if (!freed) { - printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n"); - for (int i=(*maplib)->libsz-1; i>=0; --i) - if((*maplib)->libraries[i]!=owner) { - printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); - Free1Library(&(*maplib)->libraries[i], emu); - } - } else { - for (int i=(*maplib)->libsz-1; i>=0; --i) { - freeLibraryRecurse(*maplib, emu, i, freed, owner); - } - memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway - (*maplib)->libsz = 0; - box_free(freed); + for(int i=0; i<(*maplib)->libsz; ++i) { + printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); + Free1Library(&(*maplib)->libraries[i], emu); } } box_free((*maplib)->libraries); @@ -203,14 +161,15 @@ static void MapLibRemoveMapLib(lib_t* dest, lib_t* src) } } -int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu) +int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, 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)":""); // first check if lib is already loaded library_t *lib = getLib(my_context->maplib, path); if(lib) { - add_neededlib(neededlibs, lib); - if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib); + IncRefCount(lib); // increment cntref + needed->libs[n] = lib; printf_log(LOG_DEBUG, "Already present in maplib => success\n"); return 0; } @@ -218,6 +177,8 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib lib = getLib(my_context->local_maplib, path); if(lib) { printf_log(LOG_DEBUG, "Already present in local_maplib => success\n"); + needed->libs[n] = lib; + IncRefCount(lib); // increment cntref if(local) { // add lib to maplib... if(maplib) { @@ -239,20 +200,15 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib MapLibAddLib(my_context->maplib, lib); MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib); } - add_neededlib(neededlibs, lib); - if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib); return 0; } // load a new one - lib = NewLibrary(path, box64); + needed->libs[n] = lib = NewLibrary(path, box64); if(!lib) { printf_log(LOG_DEBUG, "Faillure to create lib => fail\n"); return 1; //Error } - add_neededlib(neededlibs, lib); - if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib); - // add lib now if(local) { MapLibAddLib(my_context->local_maplib, lib); @@ -291,8 +247,10 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib return 0; } -int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu) +int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu) { + if(!lib) // no lib, error is already detected, no need to return a new one + return 0; if(!maplib) maplib = (local)?lib->maplib:my_context->maplib; @@ -303,18 +261,28 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli } else { // it's an emulated lib, // load dependancies and launch init sequence - if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, box64, emu)) { + if(LoadNeededLibs(box64->elfs[mainelf], maplib, 0, bindnow, box64, emu)) { printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); return 1; } // some special case, where dependancies may not be correct if(!strcmp(GetNameLib(lib), "libCgGL.so")) { - const char* libs[] = {"libGL.so.1"}; - AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box64, emu); + char* names[] = {"libGL.so.1"}; // TODO: it will never be uninit... + library_t* libs[] = { NULL }; + needed_libs_t tmp = {0}; + tmp.size = tmp.cap = 1; + tmp.names = names; + tmp.libs = libs; + AddNeededLib(maplib, 0, 0, &tmp, box64, emu); } if(!strcmp(GetNameLib(lib), "libmss.so.6")) { - const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"}; - AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box64, emu); + char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit... + library_t* libs[] = { NULL, NULL }; + needed_libs_t tmp = {0}; + tmp.size = tmp.cap = 2; + tmp.names = names; + tmp.libs = libs; + AddNeededLib(maplib, 0, 0, &tmp, box64, emu); } // finalize the lib @@ -330,28 +298,26 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli } EXPORTDYN -int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu) +int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu) { + if(!needed) // no needed libs, no problems + return 0; box64_mapclean = 0; - if(!neededlibs) { - neededlibs = box_calloc(1, sizeof(needed_libs_t)); - } - int idx = neededlibs->size; + int ret = 0; // Add libs and symbol - for(int i=0; i<npath; ++i) { - if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box64, emu)) { - printf_log(strchr(paths[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", paths[i]); - return 1; + for(int i=0; i<needed->size; ++i) { + if(AddNeededLib_add(maplib, local, needed, i, box64, emu)) { + printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]); + ret = 1; } } - int idx_end = neededlibs->size; // add dependant libs and init them - for (int i=idx; i<idx_end; ++i) - if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, neededlibs->libs[i], box64, emu)) { - printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name); - if(!allow_missing_libs) return 1; + for (int i=0; i<needed->size; ++i) + if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], box64, emu)) { + printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]); + if(!allow_missing_libs) ret = 1; } - return 0; + return ret; } library_t* GetLibMapLib(lib_t* maplib, const char* name) @@ -442,16 +408,23 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin size_t size = 0; // check with default version... const char* defver = GetDefaultVersion(my_context->globaldefver, name); + // search in needed libs from preloaded first, in order + 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]))) + if(*start) + return 1; // search non-weak symbol, from older to newer (first GLOBAL object wins) if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver)) if(*start) return 1; // TODO: create a temporary map to search lib only 1 time, and in order of needed... // search in needed libs from neededlibs first, in order - 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]))) - if(*start) - return 1; + 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]))) + if(*start) + return 1; // search in global symbols 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]))) diff --git a/src/librarian/library.c b/src/librarian/library.c index f5561674..1c18c9dc 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -110,10 +110,8 @@ void WrappedLib_FinishFini(library_t* lib) box_free(lib->w.altprefix); if(lib->w.altmy) box_free(lib->w.altmy); - if(lib->w.neededlibs) { - for(int i=0; i<lib->w.needed; ++i) - box_free(lib->w.neededlibs[i]); - box_free(lib->w.neededlibs); + if(lib->w.needed) { + free_neededlib(lib->w.needed); } FreeBridge(&lib->w.bridge); } @@ -221,8 +219,9 @@ static void initWrappedLib(library_t *lib, box64context_t* context) { lib->getweak = WrappedLib_GetWeak; lib->getlocal = WrappedLib_GetLocal; lib->type = LIB_WRAPPED; + lib->w.refcnt = 1; // Call librarian to load all dependant elf - if(AddNeededLib(context->maplib, &lib->needed, lib, 0, 0, (const char**)lib->w.neededlibs, lib->w.needed, context, thread_get_emu())) { + if(AddNeededLib(context->maplib, 0, 0, lib->w.needed, context, thread_get_emu())) { printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name); return; } @@ -362,7 +361,6 @@ library_t *NewLibrary(const char* path, box64context_t* context) lib->name = Path2Name(path); lib->nbdot = NbDot(lib->name); lib->type = LIB_UNNKNOW; - lib->refcnt = 1; printf_log(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) { @@ -510,6 +508,25 @@ int ReloadLibrary(library_t* lib, x64emu_t* emu) return 0; } +int FiniLibrary(library_t* lib, x64emu_t* emu) +{ + if(!lib->active) + return 0; // nothing to do + switch (lib->type) { + case LIB_WRAPPED: + if(!--lib->w.refcnt) + lib->active = 0; + return 0; + case LIB_EMULATED: + if(emu) + RunElfFini(lib->e.elf, emu); + if(!lib->e.elf->refcnt) + lib->active = 0; + return 0; + } + return 1; // bad type +} + void InactiveLibrary(library_t* lib) { lib->active = 0; @@ -519,14 +536,7 @@ void Free1Library(library_t **lib, x64emu_t* emu) { if(!(*lib)) return; - if(--(*lib)->refcnt) - return; - - if((*lib)->type==LIB_EMULATED && emu) { - elfheader_t *elf_header = (*lib)->e.elf; - RunElfFini(elf_header, emu); - } - + // No "Fini" logic here, only memory handling if((*lib)->maplib) FreeLibrarian(&(*lib)->maplib, emu); @@ -577,8 +587,6 @@ void Free1Library(library_t **lib, x64emu_t* emu) if((*lib)->w.symbol2map) kh_destroy(symbol2map, (*lib)->w.symbol2map); } - free_neededlib(&(*lib)->needed); - free_neededlib(&(*lib)->dependedby); box_free(*lib); *lib = NULL; @@ -642,7 +650,7 @@ int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, } int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local) { - if(!name[0] || !lib->active) + if(!name[0] || !lib || !lib->active) return 0; khint_t k; // get a new symbol @@ -915,18 +923,34 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add return 0; } -int GetNeededLibN(library_t* lib) { - return lib->needed.size; +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; + } + return 0; } library_t* GetNeededLib(library_t* lib, int idx) { - if(idx<0 || idx>=lib->needed.size) - return NULL; - return lib->needed.libs[idx]; + switch (lib->type) { + case LIB_WRAPPED: + if(idx<0 || !lib->w.needed || idx>=lib->w.needed->size) + return NULL; + return lib->w.needed->libs[idx]; + case LIB_EMULATED: + if(idx<0 || idx>=lib->e.elf->needed->size) + return NULL; + return lib->e.elf->needed->libs[idx]; + } + return NULL; } -needed_libs_t* GetNeededLibs(library_t* lib) +char** GetNeededLibs(library_t* lib) { - return &lib->needed; + switch (lib->type) { + case LIB_WRAPPED: return lib->w.needed?lib->w.needed->names:NULL; + case LIB_EMULATED: return lib->e.elf->needed->names; + } + return NULL; } void* GetHandle(library_t* lib) @@ -990,74 +1014,57 @@ void AddMainElfToLinkmap(elfheader_t* elf) lm->l_ld = GetDynamicSection(elf); } -static int is_neededlib_present(needed_libs_t* needed, library_t* lib) +needed_libs_t* new_neededlib(int n) { - if(!needed || !lib) - return 0; - if(!needed->size) - return 0; - for(int i=0; i<needed->size; ++i) - if(needed->libs[i] == lib) - return 1; - return 0; -} - -void add_neededlib(needed_libs_t* needed, library_t* lib) -{ - ++lib->refcnt; - if(!needed) - return; - if(is_neededlib_present(needed, lib)) - return; - if(needed->size == needed->cap) { - needed->cap += 8; - needed->libs = (library_t**)box_realloc(needed->libs, needed->cap*sizeof(library_t*)); - } - needed->libs[needed->size++] = lib; + needed_libs_t* ret = (needed_libs_t*)calloc(1, sizeof(needed_libs_t)); + ret->cap = ret->size = n; + ret->libs = (library_t**)calloc(n, sizeof(library_t*)); + ret->names = (char**)calloc(n, sizeof(char*)); + return ret; } void free_neededlib(needed_libs_t* needed) { - if(!needed) + if(needed) return; - needed->cap = 0; - needed->size = 0; - if(needed->libs) - box_free(needed->libs); + free(needed->libs); + free(needed->names); needed->libs = NULL; + needed->names = NULL; + needed->cap = needed->size = 0; + free(needed); } -void add_dependedbylib(needed_libs_t* dependedby, library_t* lib) +void add1_neededlib(needed_libs_t* needed) { - if(!dependedby) - return; - if(is_neededlib_present(dependedby, lib)) + if(!needed) return; - if(dependedby->size == dependedby->cap) { - dependedby->cap += 8; - dependedby->libs = (library_t**)box_realloc(dependedby->libs, dependedby->cap*sizeof(library_t*)); - } - dependedby->libs[dependedby->size++] = lib; -} -void free_dependedbylib(needed_libs_t* dependedby) -{ - if(!dependedby) + if(needed->size+1<=needed->cap) return; - dependedby->cap = 0; - dependedby->size = 0; - if(dependedby->libs) - box_free(dependedby->libs); - dependedby->libs = NULL; + needed->cap = needed->size+1; + needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); + needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*)); + needed->size++; } void setNeededLibs(library_t* lib, int n, ...) { if(lib->type!=LIB_WRAPPED && lib->type!=LIB_UNNKNOW) return; - lib->w.needed = n; - lib->w.neededlibs = (char**)box_calloc(n, sizeof(char*)); + lib->w.needed = new_neededlib(n); va_list va; va_start (va, n); for (int i=0; i<n; ++i) { - lib->w.neededlibs[i] = box_strdup(va_arg(va, char*)); + lib->w.needed->names[i] = va_arg(va, char*); } va_end (va); } + +void IncRefCount(library_t* lib) +{ + if(lib->type!=LIB_WRAPPED && lib->type!=LIB_UNNKNOW) + return; + if(lib->type==LIB_WRAPPED) { + ++lib->w.refcnt; + } else { + ++lib->e.elf->refcnt; + } +} \ No newline at end of file diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h index 021e78b6..2b2c5eff 100755 --- a/src/librarian/library_private.h +++ b/src/librarian/library_private.h @@ -37,8 +37,7 @@ typedef struct wlib_s { void* lib; // dlopen result void* priv; // actual private char* altprefix; // if function names are mangled.. - int needed; - char** neededlibs; + needed_libs_t* needed; kh_symbolmap_t *symbolmap; kh_symbolmap_t *wsymbolmap; kh_symbolmap_t *mysymbolmap; @@ -49,6 +48,7 @@ typedef struct wlib_s { kh_datamap_t *wdatamap; kh_datamap_t *mydatamap; char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2 + int refcnt; // refcounting the lib } wlib_t; typedef struct elib_s { @@ -71,18 +71,11 @@ typedef struct library_s { wlib_t w; elib_t e; }; // private lib data - needed_libs_t needed; - needed_libs_t dependedby; // used to free library - int refcnt; // refcounting the lib lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen) kh_bridgemap_t *gbridgemap; // global symbol bridgemap kh_bridgemap_t *wbridgemap; // weak symbol bridgemap kh_bridgemap_t *lbridgemap; // local symbol bridgemap } library_t; -void add_neededlib(needed_libs_t* needed, library_t* lib); -void free_neededlib(needed_libs_t* needed); -void add_dependedbylib(needed_libs_t* dependedby, library_t* lib); -void free_dependedbylib(needed_libs_t* dependedby); // type for map elements typedef struct map_onesymbol_s { diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 0b4c98c5..f2121f73 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -751,10 +751,16 @@ extern __thread void* current_helper; static pthread_mutex_t mutex_dynarec_prot; #endif +extern int box64_quit; + void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) { // sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here! int log_minimum = (box64_showsegv)?LOG_NONE:((my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_DEBUG:LOG_INFO); + if((sig==SIGSEGV || sig==SIGBUS) && box64_quit) { + printf_log(LOG_INFO, "Sigfault/Segbus while quitting, exiting silently\n"); + exit(0); // Hack, segfault while quiting, exit silently + } ucontext_t *p = (ucontext_t *)ucntx; void* addr = (void*)info->si_addr; // address that triggered the issue void* rsp = NULL; @@ -1003,8 +1009,10 @@ exit(-1); elfname = ElfName(elf); if(jit_gdb) { pid_t pid = getpid(); - int v = fork(); // is this ok in a signal handler??? - if(v) { + int v = vfork(); // is this ok in a signal handler??? + if(v<0) { + printf("Error while forking, cannot launch gdb (errp%d/%s)\n", errno, strerror(errno)); + } else if(v) { // parent process, the one that have the segfault volatile int waiting = 1; printf("Waiting for %s (pid %d)...\n", (jit_gdb==2)?"gdbserver":"gdb", pid); @@ -1035,7 +1043,8 @@ exit(-1); for (int j = 0; j < nptrs; j++) printf_log(log_minimum, "NativeBT: %s\n", strings[j]); free(strings); - } + } else + printf_log(log_minimum, "NativeBT: none (%d/%s)\n", errno, strerror(errno)); extern int my_backtrace(x64emu_t* emu, void** buffer, int size); // in wrappedlibc extern char** my_backtrace_symbols(x64emu_t* emu, uintptr_t* buffer, int size); nptrs = my_backtrace(emu, buffer, BT_BUF_SIZE); @@ -1044,7 +1053,8 @@ exit(-1); for (int j = 0; j < nptrs; j++) printf_log(log_minimum, "EmulatedBT: %s\n", strings[j]); free(strings); - } + } else + printf_log(log_minimum, "EmulatedBT: none\n"); } #ifdef DYNAREC uint32_t hash = 0; diff --git a/src/main.c b/src/main.c index 78f46daa..229b38cc 100755 --- a/src/main.c +++ b/src/main.c @@ -36,6 +36,7 @@ #include "rcfile.h" box64context_t *my_context = NULL; +int box64_quit = 0; int box64_log = LOG_INFO; //LOG_NONE; int box64_dump = 0; int box64_nobanner = 0; @@ -1039,7 +1040,7 @@ void setupTrace() void endBox64() { - if(!my_context) + if(!my_context || box64_quit) return; x64emu_t* emu = thread_get_emu(); @@ -1047,6 +1048,7 @@ void endBox64() printf_log(LOG_DEBUG, "Calling atexit registered functions (exiting box64)\n"); CallAllCleanup(emu); // then call all the fini + box64_quit = 1; printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n"); RunElfFini(my_context->elfs[0], emu); #ifdef DYNAREC @@ -1579,14 +1581,16 @@ int main(int argc, const char **argv, char **env) { AddMainElfToLinkmap(elf_header); // pre-load lib if needed if(ld_preload.size) { + my_context->preload = new_neededlib(ld_preload.size); for(int i=0; i<ld_preload.size; ++i) - if(AddNeededLib(my_context->maplib, &my_context->neededlibs, NULL, 0, 0, (const char**)&ld_preload.paths[i], 1, my_context, emu)) { - printf_log(LOG_INFO, "Warning, cannot pre-load the lib (%s)\n", ld_preload.paths[i]); - } + my_context->preload->names[i] = ld_preload.paths[i]; + if(AddNeededLib(my_context->maplib, 0, 0, my_context->preload, my_context, emu)) { + printf_log(LOG_INFO, "Warning, cannot pre-load of the libs\n"); + } } FreeCollection(&ld_preload); // Call librarian to load all dependant elf - if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, 0, my_context, emu)) { + if(LoadNeededLibs(elf_header, my_context->maplib, 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; diff --git a/src/tools/bridge.c b/src/tools/bridge.c index 5884e48a..d462155f 100755 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -5,6 +5,8 @@ #include <dlfcn.h> #include <pthread.h> #include <sys/mman.h> +#include <errno.h> +#include <execinfo.h> #include <wrappedlibs.h> #include "custommem.h" diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 62fce387..3e7cc4d4 100755 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -37,6 +37,8 @@ void FreeDLPrivate(dlprivate_t **lib) { box_free(*lib); } +static needed_libs_t dl_loaded = {0}; + // dead_cells consider the "2" value to be some king of issue? #define MIN_NLIB 3 @@ -128,16 +130,24 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) } dlopened = (GetLibInternal(rfilename)==NULL); // Then open the lib - const char* libs[] = {rfilename}; my_context->deferedInit = 1; int bindnow = (!box64_musl && (flag&0x2))?1:0; - if(AddNeededLib(NULL, NULL, NULL, is_local, bindnow, libs, 1, my_context, emu)) { + needed_libs_t tmp = {0}; + char* names[] = {rfilename}; + library_t* libs[] = { NULL }; + tmp.size = tmp.cap = 1; + tmp.names = names; + tmp.libs = libs; + if(AddNeededLib(NULL, is_local, bindnow, &tmp, 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_malloc(129); snprintf(dl->last_error, 129, "Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag); return NULL; } + add1_neededlib(&dl_loaded); + dl_loaded.names[dl_loaded.size-1] = tmp.names[0]; + dl_loaded.libs[dl_loaded.size-1] = tmp.libs[0]; lib = GetLibInternal(rfilename); RunDeferedElfInit(emu); } else { @@ -145,6 +155,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) for (size_t i=MIN_NLIB; i<dl->lib_sz; ++i) { if(!dl->libs[i]) { dl->count[i] = dl->count[i]+1; + IncRefCount(dl->libs[i]); return (void*)(i+1); } } @@ -202,7 +213,7 @@ int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymb if(lib->getweak(lib, rsymbol, start, end, 0, &weak, version, vername, 1)) return 1; // look in other libs - int n = GetNeededLibN(lib); + int n = GetNeededLibsN(lib); for (int i=0; i<n; ++i) { library_t *l = GetNeededLib(lib, i); if(recursive_dlsym_lib(collection, l, rsymbol, start, end, version, vername)) @@ -322,14 +333,7 @@ int my_dlclose(x64emu_t* emu, void *handle) return -1; } dl->count[nlib] = dl->count[nlib]-1; - if(dl->count[nlib]==0 && dl->dlopened[nlib]) { // need to call Fini... - int idx = GetElfIndex(dl->libs[nlib]); - if(idx!=-1) { - printf_dlsym(LOG_DEBUG, "dlclose: Call to Fini for %p\n", handle); - RunElfFini(my_context->elfs[idx], emu); - InactiveLibrary(dl->libs[nlib]); - } - } + FiniLibrary(dl->libs[nlib], emu); return 0; } int my_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags) |