diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-04-12 18:20:05 +0000 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-04-12 18:20:16 +0000 |
| commit | 5ceedab2137ed65c542ca00e528fe07d121799ad (patch) | |
| tree | c5aa961838c81e2a1a356e753c22eec7bc588180 /src | |
| parent | 1c4f3cbf195453b214d3551d012cd17a38b8aaf3 (diff) | |
| download | box64-5ceedab2137ed65c542ca00e528fe07d121799ad.tar.gz box64-5ceedab2137ed65c542ca00e528fe07d121799ad.zip | |
Improve loading/unloading of libs, and fixed a regression when dlopen a lib after some dlclose
Diffstat (limited to 'src')
| -rwxr-xr-x | src/include/box64context.h | 1 | ||||
| -rwxr-xr-x | src/librarian/library.c | 46 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibdl.c | 9 |
3 files changed, 39 insertions, 17 deletions
diff --git a/src/include/box64context.h b/src/include/box64context.h index 2424c130..2c0063e2 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -57,6 +57,7 @@ typedef struct needed_libs_s { void free_neededlib(needed_libs_t* needed); needed_libs_t* new_neededlib(int n); +needed_libs_t* copy_neededlib(needed_libs_t* needed); void add1_neededlib(needed_libs_t* needed); typedef struct base_segment_s { diff --git a/src/librarian/library.c b/src/librarian/library.c index 20b663db..109a11ba 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -598,6 +598,8 @@ int IsSameLib(library_t* lib, const char* path) int ret = 0; if(!lib) return 0; + if(lib->type==LIB_UNNKNOW) + return 0; char* name = Path2Name(path); if(!strchr(path, '/') || lib->type==LIB_WRAPPED || !lib->path) { if(strcmp(name, lib->name)==0) @@ -1039,6 +1041,19 @@ void add1_neededlib(needed_libs_t* needed) needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*)); needed->size++; } +needed_libs_t* copy_neededlib(needed_libs_t* needed) +{ + if(!needed) + return NULL; + needed_libs_t* ret = (needed_libs_t*)calloc(1, sizeof(needed_libs_t)); + ret->cap = needed->cap; + ret->size = needed->size; + ret->libs = (library_t**)calloc(ret->cap, sizeof(library_t*)); + ret->names = (char**)calloc(ret->cap, sizeof(char*)); + memcpy(ret->libs, needed->libs, ret->size*sizeof(library_t*)); + memcpy(ret->names, needed->names, ret->size*sizeof(char*)); + return ret; +} void setNeededLibs(library_t* lib, int n, ...) { @@ -1060,39 +1075,52 @@ void IncRefCount(library_t* lib, x64emu_t* emu) switch (lib->type) { case LIB_WRAPPED: ++lib->w.refcnt; + if(lib->w.needed) + for(int i=0; i<lib->w.needed->size; ++i) + IncRefCount(lib->w.needed->libs[i], emu); break; case LIB_EMULATED: ++lib->e.elf->refcnt; + if(lib->e.elf->needed) + for(int i=0; i<lib->e.elf->needed->size; ++i) + IncRefCount(lib->e.elf->needed->libs[i], emu); } } int DecRefCount(library_t** lib, x64emu_t* emu) { if(!lib || !*lib) - return 0; + return 1; if((*lib)->type==LIB_UNNKNOW) - return 0; - int ret = 0; + return 1; + int ret = 1; + needed_libs_t* needed = NULL; + int freed = 0; switch ((*lib)->type) { case LIB_WRAPPED: + needed = (*lib)->w.needed; if(!(ret=--(*lib)->w.refcnt)) { - if((*lib)->w.needed) - for(int i=0; i<(*lib)->w.needed->size; ++i) - DecRefCount(&(*lib)->w.needed->libs[i], emu); + needed = copy_neededlib(needed); + freed=1; Free1Library(lib, emu); } break; case LIB_EMULATED: + needed = (*lib)->e.elf->needed; if(!(ret=--(*lib)->e.elf->refcnt)) { - if((*lib)->e.elf->needed) - for(int i=0; i<(*lib)->e.elf->needed->size; ++i) - DecRefCount(&(*lib)->e.elf->needed->libs[i], emu); + needed = copy_neededlib(needed); + freed=1; removeLinkMapLib(*lib); FiniLibrary(*lib, emu); Free1Library(lib, emu); } break; } + if(needed) + for(int i=0; i<needed->size; ++i) + DecRefCount(&needed->libs[i], emu); + if(freed) + free_neededlib(needed); return ret; } diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 2089a12c..ab154a27 100755 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -37,8 +37,6 @@ 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 @@ -146,9 +144,6 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) 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); RunDeferredElfInit(emu); } else { @@ -339,9 +334,7 @@ int my_dlclose(x64emu_t* emu, void *handle) return -1; } dl->count[nlib] = dl->count[nlib]-1; - if(!DecRefCount(&dl->libs[nlib], emu)) { - dl->count[nlib] = 0; - } + DecRefCount(&dl->libs[nlib], emu); return 0; } int my_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags) |