about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-01-15 11:48:58 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-01-15 11:48:58 +0100
commit72df0bd1a034f0e7f85b4d778f78ba2e542f5148 (patch)
tree72099c6cf4d11fc41215f68c4eed493dbbf43ca1 /src
parent6035cbd5c1204d7c68bb144b948b0ee1c66061d9 (diff)
downloadbox64-72df0bd1a034f0e7f85b4d778f78ba2e542f5148.tar.gz
box64-72df0bd1a034f0e7f85b4d778f78ba2e542f5148.zip
Fixed dlsym with RTLD_NEXT and preloaded libs
Diffstat (limited to 'src')
-rw-r--r--src/core.c2
-rw-r--r--src/include/librarian.h1
-rw-r--r--src/librarian/librarian.c61
-rw-r--r--src/librarian/library_private.h2
-rw-r--r--src/wrapped/wrappedlibdl.c4
5 files changed, 66 insertions, 4 deletions
diff --git a/src/core.c b/src/core.c
index a6972f8b..530f616d 100644
--- a/src/core.c
+++ b/src/core.c
@@ -2513,7 +2513,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
         dynarec_wine_prereserve();
         #endif
     }
-    AddMainElfToLinkmap(elf_header);
+    AddMainElfToLinkmap(elf_header);    //TODO: LinkMap seems incorect
     // pre-load lib if needed
     if(ld_preload.size) {
         my_context->preload = new_neededlib(0);
diff --git a/src/include/librarian.h b/src/include/librarian.h
index 710c3d43..836b053d 100644
--- a/src/include/librarian.h
+++ b/src/include/librarian.h
@@ -30,6 +30,7 @@ void promoteLocalLibGlobal(library_t* lib);
 int isLibLocal(library_t* lib);
 uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername, int veropt);
 int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym);
+int GetNextSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym);
 int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym);
 int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym);
 int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt, void** elfsym);
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
index 415278ae..4298ee05 100644
--- a/src/librarian/librarian.c
+++ b/src/librarian/librarian.c
@@ -462,6 +462,67 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
     // nope, not found
     return weak;
 }
+static int isLibPreloaded(library_t* lib)
+{
+    if(my_context->preload)
+        for(int i=0; i<my_context->preload->size; ++i)
+            if(my_context->preload->libs[i] == lib)
+                return 1;
+    return 0;
+}
+int GetNextSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym)
+{
+    assert(self);   // need self for this one
+    int weak = 0;
+    int next = 0;
+    void* sym;
+    // search in needed libs from preloaded first, in order
+    if(my_context->preload)
+        for(int i=0; i<my_context->preload->size; ++i) {
+            if(next) {
+                if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) {
+                    return 1;
+                }
+                if(GetLibWeakSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) {
+                    return 1;
+                }
+            }
+            if(self==GetElf(my_context->preload->libs[i])) {
+                next = 1;
+            }
+        }
+    if(maplib==my_context->maplib) {
+        if(next) {
+            if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) {
+                if(elfsym) *elfsym = sym;
+                return 1;
+            }
+            if((sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) {
+                if(elfsym) *elfsym = sym;
+                return 1;
+            }
+        }
+        if(self==my_context->elfs[0]) {
+            next = 1;
+        }
+    }
+    // search in global symbols
+    if(maplib) {
+        for(int i=0; i<maplib->libsz; ++i) if(!isLibPreloaded(maplib->libraries[i])) {
+            if(next) {
+                if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) {
+                    return 1;
+                }
+                if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) {
+                    return 1;
+                }
+            }
+            if(self==GetElf(maplib->libraries[i]))
+                next = 1;
+        }
+    }
+    return 0;
+}
 static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym)
 {
     int weak = 0;
diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h
index 495ad000..bd69a364 100644
--- a/src/librarian/library_private.h
+++ b/src/librarian/library_private.h
@@ -78,7 +78,7 @@ typedef struct elib_s {
 typedef struct library_s {
     char*               name;   // <> path
     char*               path;   // original path
-    int8_t              nbdot;  // nombre of "." after .so
+    int8_t              nbdot;  // number of "." after .so
     int8_t              type;   // 0: native(wrapped) 1: emulated(elf) -1: undetermined
     uint8_t             deepbind;
     wrappedlib_fini_t   fini;
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
index 81ee1ff6..2687b7ad 100644
--- a/src/wrapped/wrappedlibdl.c
+++ b/src/wrapped/wrappedlibdl.c
@@ -370,7 +370,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
         return NULL;
     }
     if(handle==(void*)~0LL) {
-        // special case, look globably but no self (RTLD_NEXT)
+        // special case, look globably after self in the lm chain (RTLD_NEXT)
         uintptr_t ret_addr = 0;
         #ifdef BOX32
         if(box64_is32bits)
@@ -379,7 +379,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
         #endif
             ret_addr = *(uintptr_t*)R_RSP;
         elfheader_t *elf = FindElfAddress(my_context, ret_addr); // use return address to guess "self"
-        if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, 0, NULL)) {
+        if(GetNextSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, 0, NULL)) {
             printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
             pthread_mutex_unlock(&mutex);
             return (void*)start;