about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-04-15 16:18:55 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-04-15 16:18:55 +0200
commitdd3ea0b5e6639e65b9e72e7fa0a36d162ccece1f (patch)
treeb99a6d0752d2d2e483662939db91de04768466d2 /src
parent4dbb1f6101b12a189a9c61c153c328b29889c6cf (diff)
downloadbox64-dd3ea0b5e6639e65b9e72e7fa0a36d162ccece1f.tar.gz
box64-dd3ea0b5e6639e65b9e72e7fa0a36d162ccece1f.zip
More fixes for dlclose/dlopen sequences
Diffstat (limited to 'src')
-rwxr-xr-xsrc/include/library.h1
-rwxr-xr-xsrc/librarian/library.c11
-rwxr-xr-xsrc/librarian/library_private.h3
-rwxr-xr-xsrc/wrapped/wrappedlibdl.c95
4 files changed, 72 insertions, 38 deletions
diff --git a/src/include/library.h b/src/include/library.h
index 35d1d40a..ff48b691 100755
--- a/src/include/library.h
+++ b/src/include/library.h
@@ -36,4 +36,5 @@ 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);
 
+void SetDlOpenIdx(library_t* lib, int dlopen);
 #endif //__LIBRARY_H_
diff --git a/src/librarian/library.c b/src/librarian/library.c
index 109a11ba..085d954d 100755
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -585,6 +585,9 @@ void Free1Library(library_t **lib, x64emu_t* emu)
             kh_destroy(symbol2map, (*lib)->w.symbol2map);
     }
 
+    // remove frim the dlopen collection
+    if((*lib)->dlopen)
+        RemoveDlopen(lib, (*lib)->dlopen);
     box_free(*lib);
     *lib = NULL;
 }
@@ -1135,4 +1138,10 @@ int GetRefCount(library_t* lib)
         default:
             return 0;
     }
-}
\ No newline at end of file
+}
+
+void SetDlOpenIdx(library_t* lib, int dlopen)
+{
+    if(lib)
+        lib->dlopen = dlopen;
+}
diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h
index bb8188d8..d50da99e 100755
--- a/src/librarian/library_private.h
+++ b/src/librarian/library_private.h
@@ -74,6 +74,7 @@ typedef struct library_s {
     kh_bridgemap_t      *gbridgemap;    // global symbol bridgemap
     kh_bridgemap_t      *wbridgemap;    // weak symbol bridgemap
     kh_bridgemap_t      *lbridgemap;    // local symbol bridgemap
+    int                 dlopen;   // idx to the dlopen idx (or 0 if not dlopen)
 } library_t;
 
 // type for map elements
@@ -114,4 +115,6 @@ void removeLinkMapLib(library_t* lib);
 int FiniLibrary(library_t* lib, x64emu_t* emu);
 void Free1Library(library_t **lib, x64emu_t* emu);
 
+void RemoveDlopen(library_t** lib, int idx); // defined in wrappedlibdl.c
+
 #endif //__LIBRARY_PRIVATE_H_
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
index ab154a27..899443b5 100755
--- a/src/wrapped/wrappedlibdl.c
+++ b/src/wrapped/wrappedlibdl.c
@@ -19,10 +19,16 @@
 #include "elfloader.h"
 #include "elfs/elfloader_private.h"
 
+typedef struct dllib_s {
+    library_t*  lib;
+    int         count;
+    int         dlopened;
+    int         is_self;
+    int         full;
+} dllib_t;
+
 typedef struct dlprivate_s {
-    library_t   **libs;
-    size_t      *count;
-    size_t      *dlopened;
+    dllib_t     *dllibs;
     size_t      lib_sz;
     size_t      lib_cap;
     char*       last_error;
@@ -55,6 +61,20 @@ const char* libdlName = "libdl.so.2";
 
 #define CLEARERR    if(dl->last_error) box_free(dl->last_error); dl->last_error = NULL;
 
+void RemoveDlopen(library_t** lib, int idx)
+{
+    if(!my_context)
+        return;
+    dlprivate_t *dl = my_context->dlprivate;
+    if(dl && idx<dl->lib_sz) {
+        if(lib!=&dl->dllibs[idx].lib)
+            dl->dllibs[idx].lib = NULL;
+        dl->dllibs[idx].count = 0;
+        dl->dllibs[idx].dlopened = 0;
+        dl->dllibs[idx].full = 0;
+    }
+}
+
 extern int box64_zoom;
 // Implementation
 void* my_dlopen(x64emu_t* emu, void *filename, int flag)
@@ -110,16 +130,16 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag)
         }
         // check if alread dlopenned...
         for (size_t i=MIN_NLIB; i<dl->lib_sz; ++i) {
-            if(IsSameLib(dl->libs[i], rfilename)) {
+            if(dl->dllibs[i].full && IsSameLib(dl->dllibs[i].lib, rfilename)) {
                 if(flag&0x4) {   // don't re-open in RTLD_NOLOAD mode
-                    if(dl->count[i]==0 && dl->dlopened[i]) {
+                    if(dl->dllibs[i].count==0 && dl->dllibs[i].dlopened) {
                         printf_dlsym(LOG_DEBUG, " => not present anymore\n");
                         return NULL;    // don't re-open in RTLD_NOLOAD mode
                     }
                 }
-                IncRefCount(dl->libs[i], emu);
-                dl->count[i] = dl->count[i]+1;
-                printf_dlsym(LOG_DEBUG, "dlopen: Recycling %s/%p count=%ld (dlopened=%ld, elf_index=%d)\n", rfilename, (void*)(i+1), dl->count[i], dl->dlopened[i], GetElfIndex(dl->libs[i]));
+                IncRefCount(dl->dllibs[i].lib, emu);
+                ++dl->dllibs[i].count;
+                printf_dlsym(LOG_DEBUG, "dlopen: Recycling %s/%p count=%ld (dlopened=%ld, elf_index=%d)\n", rfilename, (void*)(i+1), dl->dllibs[i].count, dl->dllibs[i].dlopened, GetElfIndex(dl->dllibs[i].lib));
                 return (void*)(i+1);
             }
         }
@@ -149,8 +169,8 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag)
     } else {
         // check if already dlopenned...
         for (size_t i=MIN_NLIB; i<dl->lib_sz; ++i) {
-            if(!dl->libs[i]) {
-                dl->count[i] = dl->count[i]+1;
+            if(dl->dllibs[i].is_self) {
+                ++dl->dllibs[i].count;
                 return (void*)(i+1);
             }
         }
@@ -160,18 +180,19 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag)
     
     if(dl->lib_sz == dl->lib_cap) {
         dl->lib_cap += 4;
-        dl->libs = (library_t**)box_realloc(dl->libs, sizeof(library_t*)*dl->lib_cap);
-        dl->count = (size_t*)box_realloc(dl->count, sizeof(size_t)*dl->lib_cap);
-        dl->dlopened = (size_t*)box_realloc(dl->dlopened, sizeof(size_t)*dl->lib_cap);
+        dl->dllibs = (dllib_t*)box_realloc(dl->dllibs, sizeof(dllib_t)*dl->lib_cap);
         // memset count...
-        memset(dl->count+dl->lib_sz, 0, (dl->lib_cap-dl->lib_sz)*sizeof(size_t));
+        memset(dl->dllibs+dl->lib_sz, 0, (dl->lib_cap-dl->lib_sz)*sizeof(dllib_t));
         if(!dl->lib_sz)
             dl->lib_sz = MIN_NLIB;
     }
-    intptr_t idx = dl->lib_sz++; 
-    dl->libs[idx] = lib;
-    dl->count[idx] = dl->count[idx]+1;
-    dl->dlopened[idx] = dlopened;
+    intptr_t idx = dl->lib_sz++;
+    dl->dllibs[idx].lib = lib;
+    ++dl->dllibs[idx].count;
+    dl->dllibs[idx].dlopened = dlopened;
+    dl->dllibs[idx].is_self = lib?0:1;
+    dl->dllibs[idx].full = 1;
+    SetDlOpenIdx(lib, idx);
     printf_dlsym(LOG_DEBUG, "dlopen: New handle %p (%s), dlopened=%ld\n", (void*)(idx+1), (char*)filename, dlopened);
     return (void*)(idx+1);
 }
@@ -273,23 +294,23 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
         printf_dlsym(LOG_NEVER, "%p\n", NULL);
         return NULL;
     }
-    if(dl->count[nlib]==0) {
+    if(!dl->dllibs[nlib].count || !dl->dllibs[nlib].full) {
         if(!dl->last_error)
             dl->last_error = box_malloc(129);
         snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
         printf_dlsym(LOG_NEVER, "%p\n", (void*)NULL);
         return NULL;
     }
-    if(dl->libs[nlib]) {
-        const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->libs[nlib]->maplib)?NULL:dl->libs[nlib]->maplib, 0, rsymbol);
-        const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->libs[nlib]->maplib)?NULL:dl->libs[nlib]->maplib, 1, rsymbol);
-        if(my_dlsym_lib(dl->libs[nlib], rsymbol, &start, &end, -1, NULL, globdefver, weakdefver)==0) {
+    if(dl->dllibs[nlib].lib) {
+        const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, rsymbol);
+        const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, rsymbol);
+        if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, -1, NULL, globdefver, weakdefver)==0) {
             // not found
-            printf_dlsym(LOG_NEVER, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->libs[nlib]), rsymbol);
+            printf_dlsym(LOG_NEVER, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol);
             printf_log(LOG_DEBUG, " Symbol not found\n");
             if(!dl->last_error)
                 dl->last_error = box_malloc(129);
-            snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p(%s)", rsymbol, handle, GetNameLib(dl->libs[nlib]));
+            snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p(%s)", rsymbol, handle, GetNameLib(dl->dllibs[nlib].lib));
             return NULL;
         }
     } else {
@@ -326,15 +347,15 @@ int my_dlclose(x64emu_t* emu, void *handle)
         printf_dlsym(LOG_DEBUG, "dlclose: %s\n", dl->last_error);
         return -1;
     }
-    if(dl->count[nlib]==0) {
+    if(!dl->dllibs[nlib].count || !dl->dllibs[nlib].full) {
         if(!dl->last_error)
             dl->last_error = box_malloc(129);
         snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
         printf_dlsym(LOG_DEBUG, "dlclose: %s\n", dl->last_error);
         return -1;
     }
-    dl->count[nlib] = dl->count[nlib]-1;
-    DecRefCount(&dl->libs[nlib], emu);
+    --dl->dllibs[nlib].count;
+    DecRefCount(&dl->dllibs[nlib].lib, emu);
     return 0;
 }
 int my_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags)
@@ -410,23 +431,23 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername)
             printf_dlsym(LOG_NEVER, "%p\n", NULL);
         return NULL;
     }
-    if(dl->count[nlib]==0) {
+    if(!dl->dllibs[nlib].count || !dl->dllibs[nlib].full) {
         if(!dl->last_error)
             dl->last_error = box_malloc(129);
         snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
             printf_dlsym(LOG_NEVER, "%p\n", (void*)NULL);
         return NULL;
     }
-    if(dl->libs[nlib]) {
-        const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->libs[nlib]->maplib)?NULL:dl->libs[nlib]->maplib, 0, rsymbol);
-        const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->libs[nlib]->maplib)?NULL:dl->libs[nlib]->maplib, 1, rsymbol);
-        if(my_dlsym_lib(dl->libs[nlib], rsymbol, &start, &end, version, vername, globdefver, weakdefver)==0) {
+    if(dl->dllibs[nlib].lib) {
+        const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, rsymbol);
+        const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, rsymbol);
+        if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, version, vername, globdefver, weakdefver)==0) {
             // not found
-                printf_dlsym(LOG_NEVER, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, GetNameLib(dl->libs[nlib]), rsymbol, vername?vername:"(nil)");
+                printf_dlsym(LOG_NEVER, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol, vername?vername:"(nil)");
             printf_log(LOG_DEBUG, " Symbol not found\n");
             if(!dl->last_error)
                 dl->last_error = box_malloc(129);
-            snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p(%s)", rsymbol, handle, GetNameLib(dl->libs[nlib]));
+            snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p(%s)", rsymbol, handle, GetNameLib(dl->dllibs[nlib].lib));
             return NULL;
         }
     } else {
@@ -465,14 +486,14 @@ int my_dlinfo(x64emu_t* emu, void* handle, int request, void* info)
         printf_dlsym(LOG_DEBUG, "dlinfo: %s\n", dl->last_error);
         return -1;
     }
-    if(dl->count[nlib]==0) {
+    if(!dl->dllibs[nlib].count || !dl->dllibs[nlib].full) {
         if(!dl->last_error)
             dl->last_error = box_malloc(129);
         snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
         printf_dlsym(LOG_DEBUG, "dlinfo: %s\n", dl->last_error);
         return -1;
     }
-    library_t *lib = dl->libs[nlib];
+    library_t *lib = dl->dllibs[nlib].lib;
     //elfheader_t *h = (GetElfIndex(lib)>-1)?my_context->elfs[GetElfIndex(lib)]:NULL;
     switch(request) {
         case 2: // RTLD_DI_LINKMAP