about summary refs log tree commit diff stats
path: root/src/elfs
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-08-26 17:45:13 +0200
committerGitHub <noreply@github.com>2024-08-26 17:45:13 +0200
commitb5105a1e57bba3305d5dce93ab4d2f7faab6b34a (patch)
treeab26b700d3c48f2c8e32a1084ae7c2e7a8448b06 /src/elfs
parent9beb745765e9c99bad6410094a97bf0bf9ebc1eb (diff)
downloadbox64-b5105a1e57bba3305d5dce93ab4d2f7faab6b34a.tar.gz
box64-b5105a1e57bba3305d5dce93ab4d2f7faab6b34a.zip
Added preliminary Box32 support (#1760)
* Improve the ReserveHigMemory helper function

* [BOX32] Added some wrapping infrastructure

* [BOX32] More wrapped 32bits lib infrastructure

* [BOX32] Added callback and tls 32bits handling

* [BOX32] Added more 32bits, around wrappers and elfs

* [BOX32] Added the 32bits version of myalign

* [BOX32] More wrapped libs and 32bits fixes and imrpovments

* [BOX32] Added some 32bits tests

* [BOX32] Try to enable some Box32 build and test on the CI

* [BOX32] Disable Box32 testing on CI platform that use qemu

* [BOX32] Another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Small fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Yet another fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Fixed a typo in CI script

* [BOX32] Better scratch alighnment and enabled more tests

* [BOX32] Added (partial) wrapped 32bits librt

* [BOX32] Added mention of Box32 in README

* [BOX32] Added phtread handling, and numerous fixes to 32bits handling. [ARM64_DYNAREC] Fixed access to segment with negative offset

* [BOX32] Added system libs and cpp testing, plus some more fixes

* [BOX32] Fix previous commit

* [BOX32] Better stack adjustment for 32bits processes

* [BOX32] Added getenv wrapped 32bits function and friends

* [BOX32] Don't look for box86 for a Box32 build

* [BOX32] Don't do 32bits cppThreads test for now on CI

* [BOX32] Enabled a few more 32bits tests

* [BOX32] For ld_lib_path for both CppThreads tests

* [BOX32] [ANDROID] Some Fixes for Android Build

* [BOX32] Still need to disable cppThread_32bits test on CI for some reason

* [BOX32] [ANDROID] Don't show PreInit Array Warning (#1751)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to … (#1752)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to push before

* [BOX32] [ANDROID] Try to Create __libc_init

* [BOX32] [ANDROID] Try to disable NEEDED_LIBS for now (libdl is not wrapped)

* [BOX32] Updated generated files

* [BOX32] Added 32bits context functions

* [BOX32] Added 32bits signal handling

* [BOX32] Added some missing 32bits elfloader functions

* [BOX32] Fix build on x86_64 machine

* [BOX32] Better fix for x86_64 build

* [BOX32] Actually added missing libs, and re-enabled cppThreads_32bits test

* [BOX32] Added wrapped 32bits libdl

* [BOX32] Try to re-enabled Box32 test on CI for ARM64 builds

* [BOX32] fine-tuning Box32 test on CI for ARM64 builds

* [BOX32] More fine-tuning to Box32 test on CI for ARM64 builds

* [BOX32] Enabled Box32 test on CI for LA64 and RV64 builds too

* [BOX32] re-Disabled Box32 test on CI for LA64 and RV64 builds, not working for now

* [BOX32] Temporarily disabled cppThreads_32bits test on CI

---------

Co-authored-by: KreitinnSoftware <pablopro5051@gmail.com>
Co-authored-by: KreitinnSoftware <80591934+KreitinnSoftware@users.noreply.github.com>
Diffstat (limited to 'src/elfs')
-rw-r--r--src/elfs/elfhash.c14
-rw-r--r--src/elfs/elfhash32.c46
-rw-r--r--src/elfs/elfload_dump.c4
-rw-r--r--src/elfs/elfloader.c101
-rw-r--r--src/elfs/elfloader32.c264
-rw-r--r--src/elfs/elfloader_private.h6
-rwxr-xr-xsrc/elfs/elfparser32.c6
7 files changed, 400 insertions, 41 deletions
diff --git a/src/elfs/elfhash.c b/src/elfs/elfhash.c
index 966a18b7..ebb81285 100644
--- a/src/elfs/elfhash.c
+++ b/src/elfs/elfhash.c
@@ -78,7 +78,12 @@ const char* GetParentSymbolVersion(elfheader_t* h, int version)
     return box64_is32bits?GetParentSymbolVersion32(h, version):GetParentSymbolVersion64(h, version);
 }
 
-uint16_t GetParentSymbolVersionFlag32(elfheader_t* h, int index) { /* TODO */ return (uint16_t)-1; }
+uint16_t GetParentSymbolVersionFlag32(elfheader_t* h, int index)
+#ifndef BOX32
+ { return (uint16_t)-1; }
+#else
+ ;
+#endif
 uint16_t GetParentSymbolVersionFlag64(elfheader_t* h, int index)
 {
     if(!h->VerDef._64 || (index<1))
@@ -97,7 +102,12 @@ uint16_t GetParentSymbolVersionFlag(elfheader_t* h, int index)
     return box64_is32bits?GetParentSymbolVersionFlag32(h, index):GetParentSymbolVersionFlag64(h, index);
 }
 
-uint16_t GetSymbolVersionFlag32(elfheader_t* h, int version) { /* TODO */ return (uint16_t)-1; }
+uint16_t GetSymbolVersionFlag32(elfheader_t* h, int version)
+#ifndef BOX32
+{ return (uint16_t)-1; }
+#else
+ ;
+#endif
 uint16_t GetSymbolVersionFlag64(elfheader_t* h, int version)
 {
     if(version<2)
diff --git a/src/elfs/elfhash32.c b/src/elfs/elfhash32.c
index 00423b0a..3773e59a 100644
--- a/src/elfs/elfhash32.c
+++ b/src/elfs/elfhash32.c
@@ -41,6 +41,40 @@ static int SymbolMatch(elfheader_t* h, uint32_t i, int ver, const char* vername,
     return strcmp(vername, symvername)?0:1;
 }
 
+uint16_t GetParentSymbolVersionFlag32(elfheader_t* h, int index)
+{
+    if(!h->VerDef._32 || (index<1))
+        return (uint16_t)-1;
+    Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef._32 + h->delta);
+    while(def) {
+        if(def->vd_ndx==index) {
+            return def->vd_flags;
+        }
+        def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
+    }
+    return (uint16_t)-1;
+}
+
+uint16_t GetSymbolVersionFlag32(elfheader_t* h, int version)
+{
+    if(version<2)
+        return (uint16_t)-1;
+    if(h->VerNeed._32) {
+        Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed._32 + h->delta);
+        while(ver) {
+            Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
+            for(int j=0; j<ver->vn_cnt; ++j) {
+                if(aux->vna_other==version) 
+                    return aux->vna_flags;
+                aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
+            }
+            ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
+        }
+    }
+    return GetParentSymbolVersionFlag32(h, version);  // if symbol is "internal", use Def table instead
+}
+
+
 static Elf32_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt)
 {
     // Prepare hash table
@@ -90,16 +124,16 @@ static Elf32_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, c
     const uint32_t symoffset = hashtab[1];
     const uint32_t bloom_size = hashtab[2];
     const uint32_t bloom_shift = hashtab[3];
-    const uint64_t *blooms = (uint64_t*)&hashtab[4];
+    const uint32_t *blooms = (uint32_t*)&hashtab[4];
     const uint32_t *buckets = (uint32_t*)&blooms[bloom_size];
     const uint32_t *chains = &buckets[nbuckets];
     // get hash from symname to lookup
     const uint32_t hash = new_elf_hash(symname);
     // early check with bloom: if at least one bit is not set, a symbol is surely missing.
-    uint64_t word = blooms[(hash/64)%bloom_size];
-    uint64_t mask = 0
-        | 1LL << (hash%64)
-        | 1LL << ((hash>>bloom_shift)%64);
+    uint32_t word = blooms[(hash/32)%bloom_size];
+    uint32_t mask = 0
+        | 1LL << (hash%32)
+        | 1LL << ((hash>>bloom_shift)%32);
     if ((word & mask) != mask) {
         return NULL;
     }
@@ -127,7 +161,7 @@ static void new_elf_hash_dump(elfheader_t* h)
     const uint32_t symoffset = hashtab[1];
     const uint32_t bloom_size = hashtab[2];
     const uint32_t bloom_shift = hashtab[3];
-    const uint64_t *blooms = (uint64_t*)&hashtab[4];
+    const uint32_t *blooms = (uint32_t*)&hashtab[4];
     const uint32_t *buckets = (uint32_t*)&blooms[bloom_size];
     const uint32_t *chains = &buckets[nbuckets];
     printf_log(LOG_NONE, "===============Dump GNU_HASH from %s\n", h->name);
diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c
index 18d4dbc6..95fc70d3 100644
--- a/src/elfs/elfload_dump.c
+++ b/src/elfs/elfload_dump.c
@@ -9,10 +9,6 @@
 #include "elfload_dump.h"
 #include "elfloader_private.h"
 
-#ifndef SHT_CHECKSUM
-#define SHT_CHECKSUM 0x6ffffff8
-#endif
-
 static const char* DumpSection(Elf64_Shdr *s, char* SST) {
     static char buff[400];
     switch (s->sh_type) {
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 248c4282..d251abaa 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -875,7 +875,12 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, e
     return box64_is32bits?RelocateElf32(maplib, local_maplib, bindnow, deepbind, head):RelocateElf64(maplib, local_maplib, bindnow, deepbind, head);
 }
 
-int RelocateElfPlt32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { /* TODO */ return -1; }
+int RelocateElfPlt32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
+#ifndef BOX32
+{ return -1; }
+#else
+ ;
+#endif
 int RelocateElfPlt64(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
 {
     int need_resolver = 0;
@@ -953,7 +958,12 @@ uintptr_t GetLastByte(elfheader_t* h)
 #endif
 
 void checkHookedSymbols(elfheader_t* h); // in mallochook.c
-void AddSymbols32(lib_t *maplib, elfheader_t* h) { /* TODO */ }
+void AddSymbols32(lib_t *maplib, elfheader_t* h)
+#ifndef BOX32
+{ }
+#else
+ ;
+#endif
 void AddSymbols(lib_t *maplib, elfheader_t* h)
 {
     if(box64_is32bits) {
@@ -1121,15 +1131,10 @@ void startMallocHook();
 #else
 void startMallocHook() {}
 #endif
-void RunElfInit32(elfheader_t* h, x64emu_t *emu) { /* TODO*/ }
 void RunElfInit(elfheader_t* h, x64emu_t *emu)
 {
     if(!h || h->init_done)
         return;
-    if(box64_is32bits) {
-        RunElfInit32(h, emu);
-        return;
-    }
     // reset Segs Cache
     memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
     uintptr_t p = h->initentry + h->delta;
@@ -1157,11 +1162,24 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
         RunFunctionWithEmu(emu, 0, p, 3, my_context->argc, my_context->argv, my_context->envv);
     printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
     // and check init array now
-    Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
-    for (size_t i=0; i<h->initarray_sz; ++i) {
-        if(addr[i]) {
-            printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
-            RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
+    #ifdef BOX32
+    if(box64_is32bits) {
+        Elf32_Addr *addr = (Elf32_Addr*)(h->initarray + h->delta);
+        for (size_t i=0; i<h->initarray_sz; ++i) {
+            if(addr[i]) {
+                printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), from_ptrv(addr[i]));
+                RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
+            }
+        }
+    } else
+    #endif
+    {
+        Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
+        for (size_t i=0; i<h->initarray_sz; ++i) {
+            if(addr[i]) {
+                printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
+                RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
+            }
         }
     }
 
@@ -1191,15 +1209,10 @@ void RunDeferredElfInit(x64emu_t *emu)
     box_free(List);
 }
 
-void RunElfFini32(elfheader_t* h, x64emu_t *emu) { /* TODO */ }
 void RunElfFini(elfheader_t* h, x64emu_t *emu)
 {
     if(!h || h->fini_done || !h->init_done)
         return;
-    if(box64_is32bits) {
-        RunElfFini32(h, emu);
-        return;
-    }
     h->fini_done = 1;
     // Call the registered cxa_atexit functions
     CallCleanup(emu, h);
@@ -1208,10 +1221,21 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
     printf_log(LOG_DEBUG, "Android does not support Fini for %s\n", ElfName(h));
 #else
     // first check fini array
-    Elf64_Addr *addr = (Elf64_Addr*)(h->finiarray + h->delta);
-    for (int i=h->finiarray_sz-1; i>=0; --i) {
-        printf_dump(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
-        RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
+    #ifdef BOX32
+    if(box64_is32bits) {
+        Elf32_Addr *addr = (Elf32_Addr*)(h->finiarray + h->delta);
+        for (int i=h->finiarray_sz-1; i>=0; --i) {
+            printf_dump(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), from_ptrv(addr[i]));
+            RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
+        }
+    } else
+    #endif
+    {
+        Elf64_Addr *addr = (Elf64_Addr*)(h->finiarray + h->delta);
+        for (int i=h->finiarray_sz-1; i>=0; --i) {
+            printf_dump(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
+            RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
+        }
     }
     // then the "old-style" fini
     if(h->finientry) {
@@ -1499,7 +1523,12 @@ EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) {
     return ret;
 }
 
-void ResetSpecialCaseMainElf32(elfheader_t* h) { /* TODO */ }
+void ResetSpecialCaseMainElf32(elfheader_t* h)
+#ifndef BOX32
+{ }
+#else
+ ;
+#endif
 void ResetSpecialCaseMainElf(elfheader_t* h)
 {
     if(box64_is32bits) {
@@ -1620,7 +1649,12 @@ static Elf64_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t
     return sym;
 }
 
-void* ElfGetLocalSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { /* TOODO */ return NULL; }
+void* ElfGetLocalSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+#ifndef BOX32
+{ return NULL; }
+#else
+ ;
+#endif
 void* ElfGetLocalSymbolStartEnd64(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
 {
     Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
@@ -1636,7 +1670,12 @@ void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *e
     return box64_is32bits?ElfGetLocalSymbolStartEnd32(head, offs, end, symname, ver, vername, local, veropt):ElfGetLocalSymbolStartEnd64(head, offs, end, symname, ver, vername, local, veropt);
 }
 
-void* ElfGetGlobalSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { /*T ODO */ return NULL; }
+void* ElfGetGlobalSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+#ifndef BOX32
+{ return NULL; }
+#else
+ ;
+#endif
 void* ElfGetGlobalSymbolStartEnd64(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
 {
     Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
@@ -1652,7 +1691,12 @@ void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *
     return box64_is32bits?ElfGetGlobalSymbolStartEnd32(head, offs, end, symname, ver, vername, local, veropt):ElfGetGlobalSymbolStartEnd64(head, offs, end, symname, ver, vername, local, veropt);
 }
 
-void* ElfGetWeakSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { /* TODO */ return NULL; }
+void* ElfGetWeakSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+#ifndef BOX32
+{ return NULL; }
+#else
+ ;
+#endif
 void* ElfGetWeakSymbolStartEnd64(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
 {
     Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
@@ -1668,7 +1712,12 @@ void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *en
     return box64_is32bits?ElfGetWeakSymbolStartEnd32(head, offs, end, symname, ver, vername, local, veropt):ElfGetWeakSymbolStartEnd64(head, offs, end, symname, ver, vername, local, veropt);
 }
 
-int ElfGetSymTabStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname) { /* TODO */ return 0; }
+int ElfGetSymTabStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname)
+#ifndef BOX32
+{ return 0; }
+#else
+ ;
+#endif
 int ElfGetSymTabStartEnd64(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname)
 {
     Elf64_Sym* sym = ElfSymTabLookup64(head, symname);
diff --git a/src/elfs/elfloader32.c b/src/elfs/elfloader32.c
index 3b30bc07..62a3918e 100644
--- a/src/elfs/elfloader32.c
+++ b/src/elfs/elfloader32.c
@@ -42,6 +42,12 @@
 #include "x64tls.h"
 #include "box32.h"
 
+ptr_t pltResolver32 = ~(ptr_t)0;
+
+extern void* my__IO_2_1_stderr_;
+extern void* my__IO_2_1_stdin_ ;
+extern void* my__IO_2_1_stdout_;
+
 // return the index of header (-1 if it doesn't exist)
 static int getElfIndex(box64context_t* ctx, elfheader_t* head) {
     for (int i=0; i<ctx->elfsize; ++i)
@@ -60,6 +66,68 @@ static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib)
     return h;
 }
 
+static Elf32_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+{
+    Elf32_Sym* sym = ElfLookup32(head, symname, *ver, *vername, local, *veropt);
+    if(!sym) return NULL;
+    if(head->VerSym && !*veropt) {
+        int idx = ((uintptr_t)sym - (uintptr_t)head->DynSym._32)/sizeof(Elf32_Sym);
+        int version = ((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[idx];
+        if(version!=-1) version &=0x7fff;
+        const char* symvername = GetSymbolVersion(head, version);
+        Elf32_Half flags = GetSymbolVersionFlag(head, version);
+        if(version>1 && *ver<2 && (flags==0)) {
+            *ver = version;
+            *vername = symvername;
+            *veropt = 1;
+        } else if(flags==0 && !*veropt && version>1 && *ver>1 && !strcmp(symvername, *vername)) {
+            *veropt = 1;
+        }
+    }
+    if(!sym->st_shndx) return NULL;
+    int vis = ELF32_ST_VISIBILITY(sym->st_other);
+    if(vis==STV_HIDDEN && !local)
+        return NULL;
+    return sym;
+}
+
+
+static void GrabX32CopyMainElfReloc(elfheader_t* head)
+{
+    if(head->rela) {
+        int cnt = head->relasz / head->relaent;
+        Elf32_Rela* rela = (Elf32_Rela *)(head->rela + head->delta);
+        printf_dump(LOG_DEBUG, "Grabbing R_386_COPY Relocation(s) in advance for %s\n", head->name);
+        for (int i=0; i<cnt; ++i) {
+            int t = ELF32_R_TYPE(rela[i].r_info);
+            if(t == R_386_COPY) {
+                Elf32_Sym *sym = &head->DynSym._32[ELF32_R_SYM(rela[i].r_info)];
+                const char* symname = SymName32(head, sym);
+                int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rela[i].r_info)]:-1;
+                if(version!=-1) version &=0x7fff;
+                const char* vername = GetSymbolVersion(head, version);
+                Elf32_Half flags = GetSymbolVersionFlag(head, version);
+                int veropt = flags?0:1;
+                uintptr_t offs = sym->st_value + head->delta;
+                AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername, veropt);
+            }
+        }
+    }
+}
+
+void checkHookedSymbols(elfheader_t* h);
+void AddSymbols32(lib_t *maplib, elfheader_t* h)
+{
+    //if(box64_dump && h->hash)   old_elf_hash_dump(h);
+    //if(box64_dump && h->gnu_hash)   new_elf_hash_dump(h);
+    if(box64_dump && h->DynSym._32) DumpDynSym32(h);
+    if(h==my_context->elfs[0]) 
+        GrabX32CopyMainElfReloc(h);
+    #ifndef STATICBUILD
+    checkHookedSymbols(h);
+    #endif
+}
+
 int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin)
 {
     ptr_t offs = 0;
@@ -624,3 +692,199 @@ int RelocateElf32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind,
     }
     return 0;
 }
+
+int RelocateElfPlt32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
+{
+    int need_resolver = 0;
+    if(0 && (head->flags&DF_BIND_NOW) && !bindnow) { // disable for now, needs more symbol in a fow libs like gtk and nss3
+        bindnow = 1;
+        printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name);
+    }
+    if(head->pltrel) {
+        int cnt = head->pltsz / head->pltent;
+        if(head->pltrel==DT_REL) {
+            DumpRelTable32(head, cnt, (Elf32_Rel *)(head->jmprel + head->delta), "PLT");
+            printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name);
+            if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf32_Rel *)(head->jmprel + head->delta), &need_resolver))
+                return -1;
+        } else if(head->pltrel==DT_RELA) {
+            DumpRelATable32(head, cnt, (Elf32_Rela *)(head->jmprel + head->delta), "PLT");
+            printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name);
+            if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf32_Rela *)(head->jmprel + head->delta), &need_resolver))
+                return -1;
+        }
+        if(need_resolver) {
+            if(pltResolver32==~(ptr_t)0) {
+                pltResolver32 = AddBridge(my_context->system, vFEv, PltResolver32, 0, "(PltResolver)");
+            }
+            if(head->pltgot) {
+                *(ptr_t*)from_ptrv(head->pltgot+head->delta+8) = pltResolver32;
+                *(ptr_t*)from_ptrv(head->pltgot+head->delta+4) = to_ptrv(head);
+                printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", from_ptrv(head->pltgot+head->delta+8));
+            } else if(head->got) {
+                *(ptr_t*)from_ptrv(head->got+head->delta+8) = pltResolver32;
+                *(ptr_t*)from_ptrv(head->got+head->delta+4) = to_ptrv(head);
+                printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", from_ptrv(head->got+head->delta+8));
+            }
+        }
+    }
+    return 0;
+}
+
+void ResetSpecialCaseMainElf32(elfheader_t* h)
+{
+    Elf32_Sym *sym = NULL;
+     for (uint32_t i=0; i<h->numDynSym; ++i) {
+        if(h->DynSym._32[i].st_info == 17) {
+            sym = h->DynSym._32+i;
+            const char * symname = h->DynStr+sym->st_name;
+            if(strcmp(symname, "_IO_2_1_stderr_")==0 && (from_ptrv(sym->st_value+h->delta))) {
+                memcpy(from_ptrv(sym->st_value+h->delta), stderr, sym->st_size);
+                my__IO_2_1_stderr_ = from_ptrv(sym->st_value+h->delta);
+                printf_log(LOG_DEBUG, "BOX32: Set @_IO_2_1_stderr_ to %p\n", my__IO_2_1_stderr_);
+            } else
+            if(strcmp(symname, "_IO_2_1_stdin_")==0 && (from_ptrv(sym->st_value+h->delta))) {
+                memcpy(from_ptrv(sym->st_value+h->delta), stdin, sym->st_size);
+                my__IO_2_1_stdin_ = from_ptrv(sym->st_value+h->delta);
+                printf_log(LOG_DEBUG, "BOX32: Set @_IO_2_1_stdin_ to %p\n", my__IO_2_1_stdin_);
+            } else
+            if(strcmp(symname, "_IO_2_1_stdout_")==0 && (from_ptrv(sym->st_value+h->delta))) {
+                memcpy(from_ptrv(sym->st_value+h->delta), stdout, sym->st_size);
+                my__IO_2_1_stdout_ = from_ptrv(sym->st_value+h->delta);
+                printf_log(LOG_DEBUG, "BOX32: Set @_IO_2_1_stdout_ to %p\n", my__IO_2_1_stdout_);
+            } else
+            if(strcmp(symname, "_IO_stderr_")==0 && (from_ptrv(sym->st_value+h->delta))) {
+                memcpy(from_ptrv(sym->st_value+h->delta), stderr, sym->st_size);
+                my__IO_2_1_stderr_ = from_ptrv(sym->st_value+h->delta);
+                printf_log(LOG_DEBUG, "BOX32: Set @_IO_stderr_ to %p\n", my__IO_2_1_stderr_);
+            } else
+            if(strcmp(symname, "_IO_stdin_")==0 && (from_ptrv(sym->st_value+h->delta))) {
+                memcpy(from_ptrv(sym->st_value+h->delta), stdin, sym->st_size);
+                my__IO_2_1_stdin_ = from_ptrv(sym->st_value+h->delta);
+                printf_log(LOG_DEBUG, "BOX32: Set @_IO_stdin_ to %p\n", my__IO_2_1_stdin_);
+            } else
+            if(strcmp(symname, "_IO_stdout_")==0 && (from_ptrv(sym->st_value+h->delta))) {
+                memcpy(from_ptrv(sym->st_value+h->delta), stdout, sym->st_size);
+                my__IO_2_1_stdout_ = from_ptrv(sym->st_value+h->delta);
+                printf_log(LOG_DEBUG, "BOX32: Set @_IO_stdout_ to %p\n", my__IO_2_1_stdout_);
+            }
+        }
+    }
+}
+
+void* ElfGetLocalSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+{
+    Elf32_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
+    if(!sym) return NULL;
+    int bind = ELF32_ST_BIND(sym->st_info);
+    if(bind!=STB_LOCAL) return 0;
+    if(offs) *offs = sym->st_value + head->delta;
+    if(end) *end = sym->st_value + head->delta + sym->st_size;
+    return sym;
+}
+
+void* ElfGetGlobalSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+{
+    Elf32_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
+    if(!sym) return NULL;
+    int bind = ELF32_ST_BIND(sym->st_info);
+    if(bind!=STB_GLOBAL && bind!=STB_GNU_UNIQUE) return 0;
+    if(offs) *offs = sym->st_value + head->delta;
+    if(end) *end = sym->st_value + head->delta + sym->st_size;
+    return sym;
+}
+
+void* ElfGetWeakSymbolStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
+{
+    Elf32_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
+    if(!sym) return NULL;
+    int bind = ELF32_ST_BIND(sym->st_info);
+    if(bind!=STB_WEAK) return 0;
+    if(offs) *offs = sym->st_value + head->delta;
+    if(end) *end = sym->st_value + head->delta + sym->st_size;
+    return sym;
+}
+
+int ElfGetSymTabStartEnd32(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname)
+{
+    Elf32_Sym* sym = ElfSymTabLookup32(head, symname);
+    if(!sym) return 0;
+    if(!sym->st_shndx) return 0;
+    if(!sym->st_size) return 0; //needed?
+    if(offs) *offs = sym->st_value + head->delta;
+    if(end) *end = sym->st_value + head->delta + sym->st_size;
+    return 1;
+}
+
+EXPORT void PltResolver32(x64emu_t* emu)
+{
+    ptr_t addr = Pop32(emu);
+    int slot = (int)Pop32(emu);
+    elfheader_t *h = (elfheader_t*)from_ptrv(addr);
+    library_t* lib = h->lib;
+    lib_t* local_maplib = GetMaplib(lib);
+    int deepbind = GetDeepBind(lib);
+    printf_dump(LOG_DEBUG, "PltResolver32: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", from_ptrv(addr), slot, *(ptr_t*)from_ptrv(R_ESP), h->name, h->VerSym);
+
+    Elf32_Rel * rel = (Elf32_Rel *)(from_ptrv(h->jmprel + h->delta + slot));
+
+    Elf32_Sym *sym = &h->DynSym._32[ELF32_R_SYM(rel->r_info)];
+    int bind = ELF32_ST_BIND(sym->st_info);
+    const char* symname = SymName32(h, sym);
+    int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel->r_info)]:-1;
+    if(version!=-1) version &= 0x7fff;
+    const char* vername = GetSymbolVersion(h, version);
+    Elf32_Half flags = GetSymbolVersionFlag(h, version);
+    int veropt = flags?0:1;
+    ptr_t *p = (uint32_t*)from_ptrv(rel->r_offset + h->delta);
+    uintptr_t offs = 0;
+    uintptr_t end = 0;
+
+    Elf32_Sym *elfsym = NULL;
+    if(bind==STB_LOCAL) {
+        elfsym = ElfDynSymLookup32(h, symname);
+        if(elfsym && elfsym->st_shndx) {
+            offs = elfsym->st_value + h->delta;
+            end = offs + elfsym->st_size;
+        }
+        if(!offs && !end && local_maplib && deepbind)
+            GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+        if(!offs && !end)
+            GetLocalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+        if(!offs && !end && local_maplib && !deepbind)
+            GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+    } else if(bind==STB_WEAK) {
+        if(local_maplib && deepbind)
+            GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+        else
+            GetGlobalWeakSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+        if(!offs && !end && local_maplib && !deepbind)
+            GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+    } else {
+        if(!offs && !end && local_maplib && deepbind)
+            GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+        if(!offs && !end)
+            GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+        if(!offs && !end && local_maplib && !deepbind)
+            GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
+    }
+
+    if (!offs) {
+        printf_log(LOG_NONE, "Error: PltResolver32: Symbol %s(ver %d: %s%s%s) not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, version, symname, vername?"@":"", vername?vername:"", p, from_ptrv(*p), h->name);
+        emu->quit = 1;
+        return;
+    } else {
+        elfheader_t* sym_elf = FindElfSymbol(my_context, elfsym);
+        offs = (uintptr_t)getAlternate(from_ptrv(offs));
+
+        if(p) {
+            printf_dump(LOG_DEBUG, "            Apply %s R_386_JMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, symname, vername?"@":"", vername?vername:"",from_ptrv(*p), from_ptrv(offs), ElfName(FindElfAddress(my_context, offs)));
+            *p = offs;
+        } else {
+            printf_log(LOG_NONE, "PltResolver32: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:"");
+        }
+    }
+
+    // jmp to function
+    R_EIP = offs;
+}
diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h
index 6bcf6d82..535dbfad 100644
--- a/src/elfs/elfloader_private.h
+++ b/src/elfs/elfloader_private.h
@@ -194,8 +194,12 @@ typedef struct elfheader_s {
 #define STB_GNU_UNIQUE  10
 #endif
 
+#ifndef ELF32_ST_VISIBILITY
+#define ELF32_ST_VISIBILITY(o)  ((o) & 0x03)
+#endif
+
 #ifndef ELF64_ST_VISIBILITY
-#define ELF64_ST_VISIBILITY(o)   ((o) & 0x03)
+#define ELF64_ST_VISIBILITY(o)  ELF32_ST_VISIBILITY (o)
 #endif
 
 elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec);
diff --git a/src/elfs/elfparser32.c b/src/elfs/elfparser32.c
index b4bb78e4..376bb34d 100755
--- a/src/elfs/elfparser32.c
+++ b/src/elfs/elfparser32.c
@@ -252,8 +252,10 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec)
                     printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
                     break;
                 case DT_PREINIT_ARRAYSZ:
-                    if(val)
-                        printf_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
+                    #ifndef ANDROID
+                        if(val)
+                            printf_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
+                    #endif
                     break;
                 case DT_FINI: // Exit hook
                     h->finientry = ptr;