about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-04-10 18:51:07 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-04-10 18:51:16 +0200
commit5d6307184941f6f2171153df6a5bb0105fcbce9e (patch)
treec0c31a50eac0c58725ba8418154ca48a3c4ae2a9 /src
parent8c98c7b67580b2807d37fa03f59416f4526df770 (diff)
downloadbox64-5d6307184941f6f2171153df6a5bb0105fcbce9e.tar.gz
box64-5d6307184941f6f2171153df6a5bb0105fcbce9e.zip
[ELFLOADER] Improved handling of Failed-to-load library (and unloading of libs too)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c38
-rwxr-xr-xsrc/elfs/elfloader.c36
-rwxr-xr-xsrc/include/box64context.h2
-rwxr-xr-xsrc/include/librarian.h2
-rwxr-xr-xsrc/include/library.h6
-rwxr-xr-xsrc/librarian/librarian.c80
-rwxr-xr-xsrc/librarian/library.c81
-rwxr-xr-xsrc/librarian/library_private.h4
-rwxr-xr-xsrc/tools/bridge.c3
-rwxr-xr-xsrc/wrapped/wrappedlibdl.c4
10 files changed, 172 insertions, 84 deletions
diff --git a/src/box64context.c b/src/box64context.c
index 082831f3..f6ca346a 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -338,20 +338,44 @@ void FreeBox64Context(box64context_t** context)
 }
 
 int AddElfHeader(box64context_t* ctx, elfheader_t* head) {
-    int idx = ctx->elfsize;
-    if(idx==ctx->elfcap) {
-        // resize...
-        ctx->elfcap += 16;
-        ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
+    int idx = 0;
+    while(idx<ctx->elfsize && ctx->elfs[idx]) idx++;
+    if(idx == ctx->elfsize) {
+        if(idx==ctx->elfcap) {
+            // resize...
+            ctx->elfcap += 16;
+            ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
+        }
+        ctx->elfs[idx] = head;
+        ctx->elfsize++;
+    } else {
+        ctx->elfs[idx] = head;
     }
-    ctx->elfs[idx] = head;
-    ctx->elfsize++;
     printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
     return idx;
 }
 
+void RemoveElfHeader(box64context_t* ctx, elfheader_t* head) {
+    if(GetTLSBase(head)) {
+        // should remove the tls info
+        int tlsbase = GetTLSBase(head);
+        if(tlsbase == -ctx->tlssize) {
+            // not really correct, but will do for now
+            ctx->tlssize -= GetTLSSize(head);
+            if(!(++ctx->sel_serial))
+                ++ctx->sel_serial;
+        }
+    }
+    for(int i=0; i<ctx->elfsize; ++i)
+        if(ctx->elfs[i] == head) {
+            ctx->elfs[i] = NULL;
+            return;
+        }
+}
+
 int AddTLSPartition(box64context_t* context, int tlssize) {
     int oldsize = context->tlssize;
+    // should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities
     context->tlssize += tlssize;
     context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
     memmove(context->tlsdata+tlssize, context->tlsdata, oldsize);   // move to the top, using memmove as regions will probably overlap
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 22045a8c..10db2c86 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -77,12 +77,9 @@ void FreeElfHeader(elfheader_t** head)
     if(!head || !*head)
         return;
     elfheader_t *h = *head;
-#ifdef DYNAREC
-    /*if(h->text) {
-        dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
-        cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
-    }*/ // will be free at the end, no need to free it now
-#endif
+    if(my_context)
+        RemoveElfHeader(my_context, h);
+
     box_free(h->name);
     box_free(h->path);
     box_free(h->PHEntries);
@@ -311,6 +308,7 @@ void FreeElfMemory(elfheader_t* head)
     if(head->multiblock_n) {
         for(int i=0; i<head->multiblock_n; ++i) {
 #ifdef DYNAREC
+            dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
             cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
 #endif
             munmap(head->multiblock[i], head->multiblock_size[i]);
@@ -1333,7 +1331,7 @@ void RunDeferredElfInit(x64emu_t *emu)
 
 void RunElfFini(elfheader_t* h, x64emu_t *emu)
 {
-    if(!h || h->fini_done)
+    if(!h || h->fini_done || !h->init_done)
         return;
     h->fini_done = 1;
     // first check fini array
@@ -1350,7 +1348,7 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
     }
     h->init_done = 0;   // can be re-inited again...
     for(int i=0; i<h->needed->size; ++i)
-        FiniLibrary(h->needed->libs[i], emu);
+        DecRefCount(&h->needed->libs[i], emu);
     return;
 }
 
@@ -1506,17 +1504,17 @@ void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned l
 
 int32_t GetTLSBase(elfheader_t* h)
 {
-    return h->tlsbase;
+    return h?h->tlsbase:0;
 }
 
 uint32_t GetTLSSize(elfheader_t* h)
 {
-    return h->tlssize;
+    return h?h->tlssize:0;
 }
 
 void* GetTLSPointer(box64context_t* context, elfheader_t* h)
 {
-    if(!h->tlssize)
+    if(!h || !h->tlssize)
         return NULL;
     tlsdatasize_t* ptr = getTLSData(context);
     return ptr->data+h->tlsbase;
@@ -1607,13 +1605,15 @@ EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) {
     const char* empty = "";
     int ret = 0;
     for (int idx=0; idx<context->elfsize; ++idx) {
-        my_dl_phdr_info_t info;
-        info.dlpi_addr = GetElfDelta(context->elfs[idx]);
-        info.dlpi_name = idx?context->elfs[idx]->name:empty;    //1st elf is program, and this one doesn't get a name
-        info.dlpi_phdr = context->elfs[idx]->PHEntries;
-        info.dlpi_phnum = context->elfs[idx]->numPHEntries;
-        if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) {
-            return ret;
+        if(context->elfs[idx]) {
+            my_dl_phdr_info_t info;
+            info.dlpi_addr = GetElfDelta(context->elfs[idx]);
+            info.dlpi_name = idx?context->elfs[idx]->name:empty;    //1st elf is program, and this one doesn't get a name
+            info.dlpi_phdr = context->elfs[idx]->PHEntries;
+            info.dlpi_phnum = context->elfs[idx]->numPHEntries;
+            if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) {
+                return ret;
+            }
         }
     }
     // and now, go on native version
diff --git a/src/include/box64context.h b/src/include/box64context.h
index c4e88a83..2424c130 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -213,6 +213,8 @@ void print_cycle_log(int loglevel);
 
 // return the index of the added header
 int AddElfHeader(box64context_t* ctx, elfheader_t* head);
+// remove an elf from list (but list is never reduced, so there can be holes)
+void RemoveElfHeader(box64context_t* ctx, elfheader_t* head);
 
 // return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context)
 int AddTLSPartition(box64context_t* context, int tlssize);
diff --git a/src/include/librarian.h b/src/include/librarian.h
index d374ae93..b7a46880 100755
--- a/src/include/librarian.h
+++ b/src/include/librarian.h
@@ -32,6 +32,8 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
 elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
 int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver);
 
+void MapLibRemoveLib(lib_t* maplib, library_t* lib);
+
 const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname);
 
 const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib);
diff --git a/src/include/library.h b/src/include/library.h
index 29c7061d..35d1d40a 100755
--- a/src/include/library.h
+++ b/src/include/library.h
@@ -18,10 +18,6 @@ typedef struct elfheader_s     elfheader_t;
 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);
 
 char* GetNameLib(library_t *lib);
 int IsSameLib(library_t* lib, const char* path);    // check if lib is same (path -> name)
@@ -37,5 +33,7 @@ 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, x64emu_t* emu);
+int DecRefCount(library_t** lib, x64emu_t* emu);   // might unload the lib!
+int GetRefCount(library_t* lib);
 
 #endif //__LIBRARY_H_
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
index e3cca3de..f704239d 100755
--- a/src/librarian/librarian.c
+++ b/src/librarian/librarian.c
@@ -39,13 +39,10 @@ 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) {
         for(int i=0; i<(*maplib)->libsz; ++i) {
             printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
-            Free1Library(&(*maplib)->libraries[i], emu);
+            DecRefCount(&(*maplib)->libraries[i], emu);
         }
     }
     box_free((*maplib)->libraries);
@@ -108,8 +105,6 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
     ++maplib->libsz;
 }
 
-static void MapLibRemoveLib(lib_t* maplib, library_t* lib);
-
 static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
 {
     if(!src)
@@ -130,7 +125,7 @@ static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
         FreeLibrarian(&src, NULL);
 }
 
-static void MapLibRemoveLib(lib_t* maplib, library_t* lib)
+void MapLibRemoveLib(lib_t* maplib, library_t* lib)
 {
     if(!maplib || !lib)
         return;
@@ -240,9 +235,9 @@ int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, box
             printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
             return 1;
         }
-        lm->l_addr = (Elf64_Addr)GetElfDelta(my_context->elfs[lib->e.elf_index]);
+        lm->l_addr = (Elf64_Addr)GetElfDelta(lib->e.elf);
         lm->l_name = lib->name;
-        lm->l_ld = GetDynamicSection(my_context->elfs[lib->e.elf_index]);
+        lm->l_ld = GetDynamicSection(lib->e.elf);
     }
     return 0;
 }
@@ -254,14 +249,14 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box
     if(!maplib)
         maplib = (local)?lib->maplib:my_context->maplib;
 
-    int mainelf = GetElfIndex(lib);
+    elfheader_t* mainelf = GetElf(lib);
 
-    if(mainelf==-1) {
+    if(!mainelf) {
         // It's a native libs, nothing else to do
     } else {
         // it's an emulated lib, 
         // load dependancies and launch init sequence
-        if(LoadNeededLibs(box64->elfs[mainelf], maplib, 0, bindnow, box64, emu)) {
+        if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box64, emu)) {
             printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
             return 1;
         }
@@ -296,6 +291,16 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box
     
     return 0;
 }
+void AddNeededLib_remove(lib_t* maplib, int local, library_t** lib, box64context_t* box64, x64emu_t* emu)
+{
+    
+    if(!lib || !*lib)    // no lib, error is already detected, no need to return a new one
+        return;
+    if(!maplib)
+        maplib = (local)?(*lib)->maplib:my_context->maplib;
+
+    DecRefCount(lib, emu);
+}
 
 EXPORTDYN
 int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu)
@@ -311,12 +316,29 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, b
             ret = 1;
         }
     }
+    // error while loadind lib, unload...
+    if(ret) {
+        for(int i=0; i<needed->size; ++i) {
+            if(box64_log>=LOG_DEBUG && needed->libs[i])
+                printf_log(LOG_DEBUG, "Will decref after failed load %s\n", needed->names[i]);
+            AddNeededLib_remove(maplib, local, &needed->libs[i], box64, emu);
+        }
+        return ret;
+    }
     // add dependant libs and init them
     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;
         }
+    // error while loadind lib, unload...
+    if(ret) {
+        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]);
+            AddNeededLib_remove(maplib, local, &needed->libs[i], box64, emu);
+        }
+    }
     return ret;
 }
 
@@ -365,13 +387,13 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
     if(go<0)
         go = 0; // not found...
     for(int i=go; i<maplib->libsz; ++i) {
-        if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
+        if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
             if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, globdefver))
                 if(*start)
                     return 1;
     }
     for(int i=go; i<maplib->libsz; ++i)
-        if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
+        if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
             GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, weakdefver);
     // loop done, weak symbol found
     if(weak && *start)
@@ -387,13 +409,13 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
                     weak = 1;
         }
         for(int i=0; i<go; ++i) {
-            if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
+            if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
                 if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, globdefver))
                     if(*start)
                         return 1;
         }
         for(int i=0; i<go; ++i) {
-            if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
+            if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
                 GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, weakdefver);
         }
     if(weak && *start)
@@ -518,15 +540,15 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
         return my_context->elfs[0];
     for(int i=0; i<maplib->libsz; ++i) {
         if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
-            int idx = GetElfIndex(maplib->libraries[i]);
-            if(idx==-1) {
+            elfheader_t* h = GetElf(maplib->libraries[i]);
+            if(!h) {
                 printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
                 return NULL;
             }
             if(weak)
-                ret = my_context->elfs[idx];
+                ret = h;
             else
-                return my_context->elfs[idx];
+                return h;
         }
     }
 
@@ -535,15 +557,15 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
         ret = my_context->elfs[0];
     for(int i=0; i<maplib->libsz; ++i) {
         if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
-            int idx = GetElfIndex(maplib->libraries[i]);
-            if(idx==-1) {
+            elfheader_t* h = GetElf(maplib->libraries[i]);
+            if(!h) {
                 printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
                 return NULL;
             }
             if(weak)
-                ret = my_context->elfs[idx];
+                ret = h;
             else
-                return my_context->elfs[idx];
+                return h;
         }
     }
     // return what has been found (maybe nothing)
@@ -597,7 +619,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
             return 0;
     }
     for(int i=0; i<maplib->libsz; ++i) {
-        if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || my_context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
+        if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) {
             if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
                 if(*start || *end)
                     return 1;
@@ -633,15 +655,15 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, c
                 *lib = NULL;    // main elf
             else {
                 for(int i=0; i<my_context->maplib->libsz; ++i) {
-                    int idx = GetElfIndex(my_context->maplib->libraries[i]);
-                    if((idx!=-1) && (my_context->elfs[idx]==h)) {
+                    elfheader_t* head = GetElf(my_context->maplib->libraries[i]);
+                    if((head) && (head==h)) {
                         *lib = my_context->maplib->libraries[i];
                         return ret;
                     }
                 }
                 for(int i=0; i<my_context->local_maplib->libsz; ++i) {
-                    int idx = GetElfIndex(my_context->local_maplib->libraries[i]);
-                    if((idx!=-1) && (my_context->elfs[idx]==h)) {
+                    elfheader_t* head = GetElf(my_context->local_maplib->libraries[i]);
+                    if((head) && (head==h)) {
                         *lib = my_context->local_maplib->libraries[i];
                         return ret;
                     }
diff --git a/src/librarian/library.c b/src/librarian/library.c
index 6a88b5c2..20b663db 100755
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -416,7 +416,6 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu)
 {
     (void)emu;
 
-    lib->active = 1;
     if(lib->type==LIB_EMULATED) {
         elfheader_t *elf_header = lib->e.elf;
         // add symbols
@@ -465,7 +464,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t*
 
 int ReloadLibrary(library_t* lib, x64emu_t* emu)
 {
-    lib->active = 1;
     if(lib->type==LIB_EMULATED) {
         elfheader_t *elf_header = lib->e.elf;
         // reload image in memory and re-run the mapping
@@ -510,33 +508,31 @@ int ReloadLibrary(library_t* lib, x64emu_t* emu)
 
 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(!--lib->e.elf->refcnt) {
-                if(emu)
-                    RunElfFini(lib->e.elf, emu);
-                lib->active = 0;
-            }
+            RunElfFini(lib->e.elf, emu);
             return 0;
     }
     return 1;   // bad type
 }
 
-void InactiveLibrary(library_t* lib)
-{
-    lib->active = 0;
-}
-
 void Free1Library(library_t **lib, x64emu_t* emu)
 {
     if(!(*lib)) return;
 
+    printf_log(LOG_DEBUG, "Free1Library %s\n", (*lib)->name);
+    // remove lib from maplib/local_maplib...
+    if(my_context) {
+        MapLibRemoveLib(my_context->maplib, *lib);
+        MapLibRemoveLib(my_context->local_maplib, *lib);
+    }
+    // free elf is relevant
+    if((*lib)->type==LIB_EMULATED) {
+        FreeElfHeader(&(*lib)->e.elf);
+    }
+
     // No "Fini" logic here, only memory handling
     if((*lib)->maplib)
         FreeLibrarian(&(*lib)->maplib, emu);
@@ -624,7 +620,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] || !lib->active)
+    if(!name[0])
         return 0;
     khint_t k;
     // get a new symbol
@@ -651,7 +647,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, const char* defver)
 {
-    if(!name[0] || !lib || !lib->active)
+    if(!name[0] || !lib)
         return 0;
     khint_t k;
     // get a new symbol
@@ -678,7 +674,7 @@ int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star
 }
 int GetLibLocalSymbolStartEnd(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] || !lib->active)
+    if(!name[0])
         return 0;
     khint_t k;
     // get a new symbol
@@ -907,8 +903,6 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
 
 int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int* weak, int version, const char* vername, int local)
 {
-    if(!lib->active)
-        return 0;
     if(version==-2) // don't send global native symbol for a version==-2 search
         return 0;
     // check in datamaps (but no version, it's not handled there)
@@ -1063,8 +1057,6 @@ void IncRefCount(library_t* lib, x64emu_t* emu)
 {
     if(lib->type==LIB_UNNKNOW)
         return;
-    if(!lib->active)
-        ReloadLibrary(lib, emu);
     switch (lib->type) {
         case LIB_WRAPPED:
             ++lib->w.refcnt;
@@ -1072,4 +1064,47 @@ void IncRefCount(library_t* lib, x64emu_t* emu)
         case LIB_EMULATED:
             ++lib->e.elf->refcnt;
     }
+}
+
+int DecRefCount(library_t** lib, x64emu_t* emu)
+{
+    if(!lib || !*lib)
+        return 0;
+    if((*lib)->type==LIB_UNNKNOW)
+        return 0;
+    int ret = 0;
+    switch ((*lib)->type) {
+        case LIB_WRAPPED:
+            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);
+                Free1Library(lib, emu);
+            }
+            break;
+        case LIB_EMULATED:
+            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);
+                removeLinkMapLib(*lib);
+                FiniLibrary(*lib, emu);
+                Free1Library(lib, emu);
+            }
+            break;
+    }
+    return ret;
+}
+
+int GetRefCount(library_t* lib)
+{
+    switch (lib->type) {
+        case LIB_WRAPPED:
+            return lib->w.refcnt;
+            break;
+        case LIB_EMULATED:
+            return lib->e.elf->refcnt;
+        default:
+            return 0;
+    }
 }
\ No newline at end of file
diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h
index 2b2c5eff..bb8188d8 100755
--- a/src/librarian/library_private.h
+++ b/src/librarian/library_private.h
@@ -62,7 +62,6 @@ typedef struct library_s {
     char*               path;   // original path
     int                 nbdot;  // nombre of "." after .so
     int                 type;   // 0: native(wrapped) 1: emulated(elf) -1: undetermined
-    int                 active;
     wrappedlib_fini_t   fini;
     wrappedlib_get_t    getglobal;  // get global (non-weak)
     wrappedlib_get_t    getweak;    // get weak symbol
@@ -112,4 +111,7 @@ linkmap_t* getLinkMapLib(library_t* lib);
 linkmap_t* addLinkMapLib(library_t* lib);
 void removeLinkMapLib(library_t* lib);
 
+int FiniLibrary(library_t* lib, x64emu_t* emu);
+void Free1Library(library_t **lib, x64emu_t* emu);
+
 #endif //__LIBRARY_PRIVATE_H_
diff --git a/src/tools/bridge.c b/src/tools/bridge.c
index 16aaaf74..54c380b1 100755
--- a/src/tools/bridge.c
+++ b/src/tools/bridge.c
@@ -61,7 +61,7 @@ brick_t* NewBrick(void* old)
         printf_log(LOG_NONE, "Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t));
     }
     #ifdef DYNAREC
-    setProtection((uintptr_t)ptr, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NOPROT);
+    setProtection((uintptr_t)ptr, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NOPROT | PROT_MMAP);
     #endif
     dynarec_log(LOG_INFO, "New Bridge brick at %p (size 0x%zx)\n", ptr, NBRICK*sizeof(onebridge_t));
     ret->b = ptr;
@@ -85,6 +85,7 @@ void FreeBridge(bridge_t** bridge)
     x64emu_t* emu = thread_get_emu();
     while(b) {
         brick_t *n = b->next;
+        dynarec_log(LOG_INFO, "FreeBridge brick at %p (size 0x%zx)\n", b->b, NBRICK*sizeof(onebridge_t));
         my_munmap(emu, b->b, NBRICK*sizeof(onebridge_t));
         box_free(b);
         b = n;
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
index 952de79d..2089a12c 100755
--- a/src/wrapped/wrappedlibdl.c
+++ b/src/wrapped/wrappedlibdl.c
@@ -339,7 +339,9 @@ int my_dlclose(x64emu_t* emu, void *handle)
         return -1;
     }
     dl->count[nlib] = dl->count[nlib]-1;
-    FiniLibrary(dl->libs[nlib], emu);
+    if(!DecRefCount(&dl->libs[nlib], emu)) {
+        dl->count[nlib] = 0;
+    }
     return 0;
 }
 int my_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags)