about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <seebastien.chev@gmail.com>2023-08-19 16:35:57 +0200
committerptitSeb <seebastien.chev@gmail.com>2023-08-19 16:35:57 +0200
commit9e7225be3698bbb970ef0674ebb282dada8fec45 (patch)
tree42674381cd2d6a0501eef54daa96f3d60b4412fb
parent154acbef72706a72787f56083bae72689808c3b1 (diff)
downloadbox64-9e7225be3698bbb970ef0674ebb282dada8fec45.tar.gz
box64-9e7225be3698bbb970ef0674ebb282dada8fec45.zip
[ELFLOADER] Adjusted fetching of symbol (help Steam Unity3d linux games, like Canabalt)
-rw-r--r--src/elfs/elfloader.c42
-rw-r--r--src/include/librarian.h1
-rw-r--r--src/librarian/librarian.c94
3 files changed, 121 insertions, 16 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 265a6241..6a516601 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -490,11 +490,20 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
                 end = offs + sym->st_size;
             }*/
             // so weak symbol are the one left
-            if(!offs && !end) {
-                if(!offs && !end && local_maplib)
-                    GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
-                if(!offs && !end && local_maplib)
-                    GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+            if(bind==STB_WEAK) {
+                if(!offs && !end) {
+                    if(!offs && !end && local_maplib)
+                        GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                    if(!offs && !end && local_maplib)
+                        GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                }
+            } else {
+                if(!offs && !end) {
+                    if(!offs && !end && local_maplib)
+                        GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                    if(!offs && !end && local_maplib)
+                        GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                }
             }
         }
         uintptr_t globoffs, globend;
@@ -692,13 +701,24 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
                 end = offs + sym->st_size;
             }*/
             // so weak symbol are the one left
-            if(old_version==version && old_bind==bind && old_symname==symname) {
-                offs = old_offs;
-                end = old_end;
+            if(bind==STB_WEAK) {
+                if(old_version==version && old_bind==bind && old_symname==symname) {
+                    offs = old_offs;
+                    end = old_end;
+                } else {
+                    GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                    if(!offs && !end && local_maplib)
+                        GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                }
             } else {
-                GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
-                if(!offs && !end && local_maplib)
-                    GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                if(old_version==version && old_bind==bind && old_symname==symname) {
+                    offs = old_offs;
+                    end = old_end;
+                } else {
+                    GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                    if(!offs && !end && local_maplib)
+                        GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                }
             }
         }
         old_bind = bind;
diff --git a/src/include/librarian.h b/src/include/librarian.h
index 80e108ca..6fc89320 100644
--- a/src/include/librarian.h
+++ b/src/include/librarian.h
@@ -30,6 +30,7 @@ int isLibLocal(library_t* lib);
 uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
 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, const char* globdefver, const char* weakdefver);
 int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
+int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
 int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver);
 int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
 elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
index 8d4c6cbb..072ef811 100644
--- a/src/librarian/librarian.c
+++ b/src/librarian/librarian.c
@@ -451,6 +451,91 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
             if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
                 if(*start)
                     return 1;
+    // search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
+    if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
+        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
+    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]), globdefver))
+                if(*start)
+                    return 1;
+    // search in global symbols
+    if(maplib) {
+        if(self && self!=my_context->elfs[0] && self!=(void*)1)
+            if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver))
+                if(*start)
+                    return 1;
+        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]), globdefver))
+                if(*start)
+                    return 1;
+        }
+    }
+
+    // check with default version...
+    int ok = 0;
+    // GetSymbolStartEnd should not change start/end if symbol is not found
+    if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
+        if(*start)
+            ok = 1;
+
+    if(maplib)
+    for(int i=0; i<maplib->libsz; ++i) {
+        if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
+            if(*start)
+                ok = 1;
+    }
+    // nope, not found
+    return (ok && *start)?1:0;
+}
+void** my_GetGTKDisplay();
+void** my_GetGthreadsGotInitialized();
+int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
+{
+    if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
+        if(start && end && *end==*start) {  // object is of 0 sized, try to see an "_END" object of null size
+            uintptr_t start2, end2;
+            char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
+            strcpy(buff, name);
+            strcat(buff, "_END");
+            if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
+                if(end2>*end && start2==end2)
+                    *end = end2;
+            }
+            box_free(buff);
+        }
+        return 1;
+    }
+    // some special case symbol, defined inside box64 itself
+    if(!strcmp(name, "gdk_display")) {
+        *start = (uintptr_t)my_GetGTKDisplay();
+        *end = *start+sizeof(void*);
+        printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
+        return 1;
+    }
+    if(!strcmp(name, "g_threads_got_initialized")) {
+        *start = (uintptr_t)my_GetGthreadsGotInitialized();
+        *end = *start+sizeof(int);
+        printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
+        return 1;
+    }
+    // not found...
+    return 0;
+}
+
+static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
+{
+    int weak = 0;
+    size_t size = 0;
+    // 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]), globdefver))
+                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, globdefver))
         if(*start)
@@ -486,17 +571,16 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
     // nope, not found
     return (ok && *start)?1:0;
 }
-void** my_GetGTKDisplay();
-void** my_GetGthreadsGotInitialized();
-int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
+
+int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
 {
-    if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
+    if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
         if(start && end && *end==*start) {  // object is of 0 sized, try to see an "_END" object of null size
             uintptr_t start2, end2;
             char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
             strcpy(buff, name);
             strcat(buff, "_END");
-            if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
+            if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
                 if(end2>*end && start2==end2)
                     *end = end2;
             }