about summary refs log tree commit diff stats
path: root/src/elfs
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-07-09 12:38:48 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-07-09 12:38:48 +0200
commitdabbca767f9de4fc4cf68252037de3061592eae2 (patch)
treebfc1dadad814a82a155c0c374097177b94154beb /src/elfs
parentca9bc1361943575724eb5152798aa208ed5eed6c (diff)
downloadbox64-dabbca767f9de4fc4cf68252037de3061592eae2.tar.gz
box64-dabbca767f9de4fc4cf68252037de3061592eae2.zip
[ELFLOADER] Added a check if lib version is compatible with what the elf loading it wants (helps Linux games on Steam)
Diffstat (limited to 'src/elfs')
-rwxr-xr-xsrc/elfs/elfloader.c19
-rwxr-xr-xsrc/elfs/elfparser.c52
2 files changed, 58 insertions, 13 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 4caa07ce..7977b592 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -374,6 +374,23 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
     return 0;
 }
 
+int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
+{
+    if(!verneeded || !head)
+        return 1;
+    if(!head->VerDef || !verneeded->VerNeed)
+        return 1;
+    int cnt = GetNeededVersionCnt(verneeded, libname);
+    for (int i=0; i<cnt; ++i) {
+        const char* vername = GetNeededVersionString(verneeded, libname, i);
+        if(vername && !GetVersionIndice(head, vername)) {
+            printf_log(/*LOG_DEBUG*/LOG_INFO, "Discarding %s for missing version %s\n", head->path, vername);
+            return 0;   // missing version
+        }
+    }
+    return 1;
+}
+
 int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
 {
     (void)context;
@@ -1201,7 +1218,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64c
             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, local, bindnow, h->needed, box64, emu)) {
+    if(AddNeededLib(maplib, local, bindnow, h->needed, h, box64, emu)) {
         printf_log(LOG_INFO, "Error loading one of needed lib\n");
         if(!allow_missing_libs)
             return 1;   //error...
diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c
index 7b83e07e..1701378f 100755
--- a/src/elfs/elfparser.c
+++ b/src/elfs/elfparser.c
@@ -416,18 +416,6 @@ int GetVersionIndice(elfheader_t* h, const char* vername)
 {
     if(!vername)
         return 0;
-    if(h->VerNeed) {
-        Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
-        while(ver) {
-            Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
-            for(int j=0; j<ver->vn_cnt; ++j) {
-                if(!strcmp(h->DynStr+aux->vna_name, vername)) 
-                    return aux->vna_other;
-                aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
-            }
-            ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
-        }
-    }
     if(h->VerDef) {
         Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
         while(def) {
@@ -438,4 +426,44 @@ int GetVersionIndice(elfheader_t* h, const char* vername)
         }
     }
     return 0;
+}
+
+int GetNeededVersionCnt(elfheader_t* h, const char* libname)
+{
+    if(!libname)
+        return 0;
+    if(h->VerNeed) {
+        Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
+        while(ver) {
+            char *filename = h->DynStr + ver->vn_file;
+            Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
+            if(!strcmp(filename, libname))
+                return ver->vn_cnt;
+            ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
+        }
+    }
+    return 0;
+}
+
+const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
+{
+    if(!libname)
+        return 0;
+    if(h->VerNeed) {
+        Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
+        while(ver) {
+            char *filename = h->DynStr + ver->vn_file;
+            Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
+            if(!strcmp(filename, libname)) {
+                for(int j=0; j<ver->vn_cnt; ++j) {
+                    if(j==idx) 
+                        return h->DynStr+aux->vna_name;
+                    aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
+                }
+                return NULL;    // idx out of bound, return NULL...
+           }
+            ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
+        }
+    }
+    return NULL;
 }
\ No newline at end of file