about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-01-01 16:13:39 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-01-01 16:13:39 +0100
commitee5398b3be5d45ec39e21b503d4ee8023a665141 (patch)
treee44a6f4233c65c22b41d9219772e548613fb7acc /src
parent3d3ab0fedc2b98f7adb84e898ffb32f24a2a1a6a (diff)
downloadbox64-ee5398b3be5d45ec39e21b503d4ee8023a665141.tar.gz
box64-ee5398b3be5d45ec39e21b503d4ee8023a665141.zip
Refactored (again) lib init/fini mecanism
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c3
-rwxr-xr-xsrc/elfs/elfloader.c26
-rwxr-xr-xsrc/elfs/elfloader_private.h7
-rwxr-xr-xsrc/emu/x64emu.c2
-rwxr-xr-xsrc/emu/x64int3.c2
-rwxr-xr-xsrc/include/box64context.h8
-rwxr-xr-xsrc/include/elfloader.h2
-rwxr-xr-xsrc/include/librarian.h2
-rwxr-xr-xsrc/include/library.h6
-rwxr-xr-xsrc/librarian/librarian.c139
-rwxr-xr-xsrc/librarian/library.c153
-rwxr-xr-xsrc/librarian/library_private.h11
-rwxr-xr-xsrc/libtools/signals.c18
-rwxr-xr-xsrc/main.c14
-rwxr-xr-xsrc/tools/bridge.c2
-rwxr-xr-xsrc/wrapped/wrappedlibdl.c26
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)