diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-08-26 17:45:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-26 17:45:13 +0200 |
| commit | b5105a1e57bba3305d5dce93ab4d2f7faab6b34a (patch) | |
| tree | ab26b700d3c48f2c8e32a1084ae7c2e7a8448b06 /src/elfs | |
| parent | 9beb745765e9c99bad6410094a97bf0bf9ebc1eb (diff) | |
| download | box64-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.c | 14 | ||||
| -rw-r--r-- | src/elfs/elfhash32.c | 46 | ||||
| -rw-r--r-- | src/elfs/elfload_dump.c | 4 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 101 | ||||
| -rw-r--r-- | src/elfs/elfloader32.c | 264 | ||||
| -rw-r--r-- | src/elfs/elfloader_private.h | 6 | ||||
| -rwxr-xr-x | src/elfs/elfparser32.c | 6 |
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; |