about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-04-10 15:44:18 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-04-10 15:44:18 +0200
commit51e840a1506eec6cccdde3895b276a8d70e32d72 (patch)
tree378385c549d111ef4ca737372fec21e5d30e1c64 /src
parentf6b4ec0fdf19b2ac2084456c5a64232b75511982 (diff)
downloadbox64-51e840a1506eec6cccdde3895b276a8d70e32d72.tar.gz
box64-51e840a1506eec6cccdde3895b276a8d70e32d72.zip
[ELFLOADER] Optimized RelocateElfRELA for subsequent identical symbols
Diffstat (limited to 'src')
-rwxr-xr-xsrc/elfs/elfloader.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index a0007f41..22045a8c 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -617,6 +617,13 @@ EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu)
 int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv)
 {
     int ret_ok = 0;
+    const char* old_globdefver = NULL;
+    const char* old_weakdefver = NULL;
+    int old_bind = -1;
+    const char* old_symname = NULL;
+    uintptr_t old_offs = 0;
+    uintptr_t old_end = 0;
+    int old_version = -1;
     for (int i=0; i<cnt; ++i) {
         int t = ELF64_R_TYPE(rela[i].r_info);
         Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)];
@@ -631,17 +638,29 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
         int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
         if(version!=-1) version &=0x7fff;
         const char* vername = GetSymbolVersion(head, version);
-        const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
-        const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
+        const char* globdefver = NULL;
+        const char* weakdefver = NULL;
+        if(old_bind==bind && old_symname==symname) {
+            globdefver = old_globdefver;
+            weakdefver = old_weakdefver;
+        } else {
+            old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
+            old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
+        }
         if(bind==STB_LOCAL) {
             if(!symname || !symname[0]) {
                 offs = sym->st_value + head->delta;
                 end = offs + sym->st_size;
             } else {
-                if(!offs && !end && local_maplib)
-                    GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
-                if(!offs && !end)
-                    GetLocalSymbolStartEnd(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 {
+                    if(local_maplib)
+                        GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                    if(!offs && !end)
+                        GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
+                }
             }
         } else {
             // this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now
@@ -651,13 +670,19 @@ 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(!offs && !end) {
+            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) {
+                if(!offs && !end && local_maplib)
                     GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
-                }
             }
         }
+        old_bind = bind;
+        old_symname = symname;
+        old_offs = offs;
+        old_end = end;
         uintptr_t globoffs, globend;
         uint64_t* globp;
         uintptr_t tmp = 0;