diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-08-18 16:02:27 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-18 16:02:27 +0200 |
| commit | fda0e9a4cba9b71de60f974fadfa74c7fbff5b15 (patch) | |
| tree | f18d6631d62761d1556abd18a91d4729bd1f41e1 /src | |
| parent | f1da5d433a707a1308732884c455ae50ffbe4fe1 (diff) | |
| parent | dead2003fa59cbfa6a2fd8ba285bdf28aac953f3 (diff) | |
| download | box64-fda0e9a4cba9b71de60f974fadfa74c7fbff5b15.tar.gz box64-fda0e9a4cba9b71de60f974fadfa74c7fbff5b15.zip | |
Merge branch 'box32' into main
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.c | 8 | ||||
| -rw-r--r-- | src/custommem.c | 26 | ||||
| -rw-r--r-- | src/custommmap.c | 3 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.c | 2 | ||||
| -rw-r--r-- | src/elfs/elfhash.c | 149 | ||||
| -rw-r--r-- | src/elfs/elfhash32.c | 190 | ||||
| -rw-r--r-- | src/elfs/elfload_dump.c | 136 | ||||
| -rwxr-xr-x | src/elfs/elfload_dump32.c | 352 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 384 | ||||
| -rw-r--r-- | src/elfs/elfloader32.c | 626 | ||||
| -rw-r--r-- | src/elfs/elfloader_private.h | 61 | ||||
| -rw-r--r-- | src/elfs/elfparser.c | 87 | ||||
| -rwxr-xr-x | src/elfs/elfparser32.c | 466 | ||||
| -rw-r--r-- | src/emu/x64int3.c | 6 | ||||
| -rw-r--r-- | src/include/box32.h | 112 | ||||
| -rw-r--r-- | src/include/custommem.h | 3 | ||||
| -rw-r--r-- | src/include/debug.h | 1 | ||||
| -rw-r--r-- | src/include/elfload_dump.h | 32 | ||||
| -rw-r--r-- | src/include/elfloader.h | 3 | ||||
| -rw-r--r-- | src/include/x64run.h | 4 | ||||
| -rw-r--r-- | src/librarian/librarian.c | 8 | ||||
| -rw-r--r-- | src/librarian/library.c | 4 | ||||
| -rw-r--r-- | src/mallochook.c | 48 |
23 files changed, 2344 insertions, 367 deletions
diff --git a/src/core.c b/src/core.c index e93a75ea..3283a6c2 100644 --- a/src/core.c +++ b/src/core.c @@ -58,6 +58,7 @@ int box64_dynarec_test = 0; path_collection_t box64_addlibs = {0}; int box64_maxcpu = 0; int box64_maxcpu_immutable = 0; +int box64_is32bits = 0; #if defined(SD845) || defined(SD888) || defined(SD8G2) || defined(TEGRAX1) int box64_mmap32 = 1; #else @@ -2084,6 +2085,13 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf FreeCollection(&ld_preload); return -1; } + #ifdef BOX32 + box64_is32bits = FileIsX86ELF(my_context->fullpath); + if(box64_is32bits) { + printf_log(LOG_INFO, "BOX64: Using Box32 to load 32bits elf\n"); + reserveHighMem(); + } + #endif elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->fullpath, 1); if(!elf_header) { int x86 = my_context->box86path?FileIsX86ELF(my_context->fullpath):0; diff --git a/src/custommem.c b/src/custommem.c index da11885f..06b48328 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -1438,6 +1438,21 @@ void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask) return ret; } +void* find31bitBlockElf(size_t size, int mainbin, uintptr_t mask) +{ + static void* startingpoint = NULL; + if(!startingpoint) { + startingpoint = (void*)WINE_LOWEST; + } + void* mainaddr = (void*)0x1000000; + void* ret = find31bitBlockNearHint(MEDIUM, size, mask); + if(!ret) + ret = find31bitBlockNearHint(LOWEST, size, mask); + if(!mainbin) + startingpoint = (void*)(((uintptr_t)startingpoint+size+0x1000000)&~0xffffff); + return ret; +} + int isBlockFree(void* hint, size_t size) { uint32_t prot; @@ -1510,10 +1525,10 @@ static void atfork_child_custommem(void) void my_reserveHighMem() { static int reserved = 0; - if(reserved || !have48bits) + if(reserved || (!have48bits && !box64_is32bits)) return; reserved = 1; - uintptr_t cur = 1ULL<<47; + uintptr_t cur = box64_is32bits?(1ULL<<32):(1ULL<<47); uintptr_t bend = 0; uint32_t prot; while (bend!=0xffffffffffffffffLL) { @@ -1533,12 +1548,13 @@ void my_reserveHighMem() void reserveHighMem() { char* p = getenv("BOX64_RESERVE_HIGH"); + if(!box64_is32bits) #if 0//def ADLINK - if(p && p[0]=='0') + if(p && p[0]=='0') #else - if(!p || p[0]=='0') + if(!p || p[0]=='0') #endif - return; // don't reserve by default + return; // don't reserve by default my_reserveHighMem(); } diff --git a/src/custommmap.c b/src/custommmap.c index 93173098..7ad26b7d 100644 --- a/src/custommmap.c +++ b/src/custommmap.c @@ -15,6 +15,7 @@ typedef void x64emu_t; extern void* mapallmem; +extern int box64_is32bits; void setProtection(uintptr_t addr, size_t size, uint32_t prot); void freeProtection(uintptr_t addr, size_t size); void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset); @@ -28,7 +29,7 @@ extern int box64_mmap32; EXPORT void* mmap64(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset) { void* ret; - if(!addr && ((running32bits && box64_mmap32) || (flags&0x40))) + if(!addr && ((running32bits && box64_mmap32) || (flags&0x40) || box64_is32bits)) ret = my_mmap64(NULL, addr, length, prot, flags | 0x40, fd, offset); else ret = internal_mmap(addr, length, prot, flags, fd, offset); diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index 376541d1..c29e5083 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -608,7 +608,7 @@ int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, if(!addr || !getProtection(addr)) return 0; onebridge_t *b = (onebridge_t*)(addr); - if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) { + if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver64) { // found ! if(retn) *retn = (b->C3==0xC2)?b->N:0; if(calladdress) *calladdress = addr+1; diff --git a/src/elfs/elfhash.c b/src/elfs/elfhash.c index fefb0e7f..966a18b7 100644 --- a/src/elfs/elfhash.c +++ b/src/elfs/elfhash.c @@ -18,14 +18,20 @@ #include "elfload_dump.h" #include "elfloader_private.h" -const char* GetSymbolVersion(elfheader_t* h, int version) +const char* GetSymbolVersion32(elfheader_t* h, int version) +#ifndef BOX32 +{ return NULL; } +#else + ; +#endif +const char* GetSymbolVersion64(elfheader_t* h, int version) { if(version<2) return NULL; /*if(version==1) return "*";*/ - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + if(h->VerNeed._64) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed._64 + h->delta); while(ver) { Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); for(int j=0; j<ver->vn_cnt; ++j) { @@ -38,12 +44,22 @@ const char* GetSymbolVersion(elfheader_t* h, int version) } return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead } +const char* GetSymbolVersion(elfheader_t* h, int version) +{ + return box64_is32bits?GetSymbolVersion32(h, version):GetSymbolVersion64(h, version); +} -const char* GetParentSymbolVersion(elfheader_t* h, int index) +const char* GetParentSymbolVersion32(elfheader_t* h, int index) +#ifndef BOX32 +{ return NULL; } +#else + ; +#endif +const char* GetParentSymbolVersion64(elfheader_t* h, int index) { - if(!h->VerDef || (index<1)) + if(!h->VerDef._64 || (index<1)) return NULL; - Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); + Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef._64 + h->delta); while(def) { if(def->vd_ndx==index) { if(def->vd_cnt<1) @@ -57,26 +73,37 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index) } return NULL; } +const char* GetParentSymbolVersion(elfheader_t* h, int version) +{ + return box64_is32bits?GetParentSymbolVersion32(h, version):GetParentSymbolVersion64(h, version); +} -Elf64_Half GetParentSymbolVersionFlag(elfheader_t* h, int index) +uint16_t GetParentSymbolVersionFlag32(elfheader_t* h, int index) { /* TODO */ return (uint16_t)-1; } +uint16_t GetParentSymbolVersionFlag64(elfheader_t* h, int index) { - if(!h->VerDef || (index<1)) - return (Elf64_Half)-1; - Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); + if(!h->VerDef._64 || (index<1)) + return (uint16_t)-1; + Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef._64 + h->delta); while(def) { if(def->vd_ndx==index) { return def->vd_flags; } def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL; } - return (Elf64_Half)-1; + return (uint16_t)-1; } -Elf64_Half GetSymbolVersionFlag(elfheader_t* h, int version) +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 GetSymbolVersionFlag64(elfheader_t* h, int version) { if(version<2) - return (Elf64_Half)-1; - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + return (uint16_t)-1; + if(h->VerNeed._64) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed._64 + h->delta); while(ver) { Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); for(int j=0; j<ver->vn_cnt; ++j) { @@ -89,14 +116,23 @@ Elf64_Half GetSymbolVersionFlag(elfheader_t* h, int version) } return GetParentSymbolVersionFlag(h, version); // if symbol is "internal", use Def table instead } +uint16_t GetSymbolVersionFlag(elfheader_t* h, int index) { + return box64_is32bits?GetSymbolVersionFlag32(h, index):GetSymbolVersionFlag64(h, index); +} -int GetVersionIndice(elfheader_t* h, const char* vername) +int GetVersionIndice32(elfheader_t* h, const char* vername) +#ifndef BOX32 +{ return 0; } +#else + ; +#endif +int GetVersionIndice64(elfheader_t* h, const char* vername) { if(!vername) return 0; - if(h->VerDef) { - Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); + if(h->VerDef._64) { + Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef._64 + h->delta); while(def) { Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux); if(!strcmp(h->DynStr+aux->vda_name, vername)) @@ -106,13 +142,23 @@ int GetVersionIndice(elfheader_t* h, const char* vername) } return 0; } +int GetVersionIndice(elfheader_t* h, const char* vername) +{ + return box64_is32bits?GetVersionIndice32(h, vername):GetVersionIndice64(h, vername); +} -int GetNeededVersionCnt(elfheader_t* h, const char* libname) +int GetNeededVersionCnt32(elfheader_t* h, const char* libname) +#ifndef BOX32 +{ return 0; } +#else + ; +#endif +int GetNeededVersionCnt64(elfheader_t* h, const char* libname) { if(!libname) return 0; - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + if(h->VerNeed._64) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed._64 + h->delta); while(ver) { char *filename = h->DynStr + ver->vn_file; if(!strcmp(filename, libname)) @@ -122,13 +168,23 @@ int GetNeededVersionCnt(elfheader_t* h, const char* libname) } return 0; } +int GetNeededVersionCnt(elfheader_t* h, const char* libname) +{ + return box64_is32bits?GetNeededVersionCnt32(h, libname):GetNeededVersionCnt64(h, libname); +} -const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) +const char* GetNeededVersionString32(elfheader_t* h, const char* libname, int idx) +#ifndef BOX32 +{ return NULL; } +#else + ; +#endif +const char* GetNeededVersionString64(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); + return NULL; + if(h->VerNeed._64) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed._64 + h->delta); while(ver) { char *filename = h->DynStr + ver->vn_file; Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); @@ -145,6 +201,10 @@ const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) } return NULL; } +const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) +{ + return box64_is32bits?GetNeededVersionString32(h, libname, idx):GetNeededVersionString64(h, libname, idx); +} int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver) { @@ -197,7 +257,7 @@ uint32_t old_elf_hash(const char* name) return h; } -Elf64_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) +static Elf64_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) { // Prepare hash table const uint32_t *hashtab = (uint32_t*)(h->hash + h->delta); @@ -209,16 +269,16 @@ Elf64_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const ch const uint32_t hash = old_elf_hash(symname); // Search for it for (uint32_t i = buckets[hash % nbuckets]; i; i = chains[i]) { - const char* name = h->DynStr + h->DynSym[i].st_name; + const char* name = h->DynStr + h->DynSym._64[i].st_name; if (!strcmp(symname, name) && SymbolMatch(h, i, ver, vername, local, veropt)) { - return &h->DynSym[i]; + return &h->DynSym._64[i]; } } return NULL; } -void old_elf_hash_dump(elfheader_t* h) +static void old_elf_hash_dump(elfheader_t* h) { // Prepare hash table const uint32_t *hashtab = (uint32_t*)(h->hash + h->delta); @@ -229,7 +289,7 @@ void old_elf_hash_dump(elfheader_t* h) printf_log(LOG_NONE, "------------ Dump HASH from %s\n", h->name); printf_log(LOG_NONE, "Buckets[%d] = \n", nbuckets); for(uint32_t i=0; i<nbuckets; ++i) { - const char* name = h->DynStr + h->DynSym[buckets[i]].st_name; + const char* name = h->DynStr + h->DynSym._64[buckets[i]].st_name; printf_log(LOG_NONE, "%d: %s\n", buckets[i], name); } printf_log(LOG_NONE,"Chains[%d] = ", nchains); @@ -246,7 +306,7 @@ uint32_t new_elf_hash(const char *name) return h; } -Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) +static Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) { // Prepare hash table const uint32_t *hashtab = (uint32_t*)(h->gnu_hash + h->delta); @@ -272,10 +332,10 @@ Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const ch if (symidx < symoffset) return NULL; while(1) { - const char* name = h->DynStr + h->DynSym[symidx].st_name; + const char* name = h->DynStr + h->DynSym._64[symidx].st_name; const uint32_t symhash = chains[symidx-symoffset]; if ((hash|1) == (symhash|1) && !strcmp(name, symname) && SymbolMatch(h, symidx, ver, vername, local, veropt)) { - return &h->DynSym[symidx]; + return &h->DynSym._64[symidx]; } if(symhash&1) return NULL; @@ -283,7 +343,7 @@ Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const ch } } -void new_elf_hash_dump(elfheader_t* h) +static void new_elf_hash_dump(elfheader_t* h) { // Prepare hash table const uint32_t *hashtab = (uint32_t*)(h->gnu_hash + h->delta); @@ -301,7 +361,7 @@ void new_elf_hash_dump(elfheader_t* h) uint32_t symidx = buckets[i]; printf_log(LOG_NONE, "%d:", symidx); while(symidx>=symoffset) { - const char* name = h->DynStr + h->DynSym[symidx].st_name; + const char* name = h->DynStr + h->DynSym._64[symidx].st_name; const uint32_t hash = chains[symidx-symoffset]; if(hash&1) symidx=0; @@ -314,19 +374,24 @@ void new_elf_hash_dump(elfheader_t* h) printf_log(LOG_NONE, "\n===============\n"); } -Elf64_Sym* ElfLookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) +#ifndef BOX32 +Elf32_Sym* ElfLookup32(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) { return NULL; } +Elf32_Sym* ElfSymTabLookup32(elfheader_t* h, const char* symname) { return NULL; } +Elf32_Sym* ElfDynSymLookup32(elfheader_t* h, const char* symname) { return NULL; } +#endif +Elf64_Sym* ElfLookup64(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) { if(h->gnu_hash) return new_elf_lookup(h, symname, ver, vername, local, veropt); return old_elf_lookup(h, symname, ver, vername, local, veropt); } -Elf64_Sym* ElfSymTabLookup(elfheader_t* h, const char* symname) +Elf64_Sym* ElfSymTabLookup64(elfheader_t* h, const char* symname) { - if(!h->SymTab) + if(!h->SymTab._64) return 0; for(size_t i=0; i<h->numSymTab; ++i) { - Elf64_Sym* sym = &h->SymTab[i]; + Elf64_Sym* sym = &h->SymTab._64[i]; int type = ELF64_ST_TYPE(sym->st_info); if(type==STT_FUNC || type==STT_TLS || type==STT_OBJECT) { const char * name = h->StrTab+sym->st_name; @@ -337,12 +402,12 @@ Elf64_Sym* ElfSymTabLookup(elfheader_t* h, const char* symname) return NULL; } -Elf64_Sym* ElfDynSymLookup(elfheader_t* h, const char* symname) +Elf64_Sym* ElfDynSymLookup64(elfheader_t* h, const char* symname) { - if(!h->DynSym) + if(!h->DynSym._64) return 0; for(size_t i=0; i<h->numDynSym; ++i) { - Elf64_Sym* sym = &h->DynSym[i]; + Elf64_Sym* sym = &h->DynSym._64[i]; int type = ELF64_ST_TYPE(sym->st_info); if(type==STT_FUNC || type==STT_TLS || type==STT_OBJECT) { const char * name = h->DynStr+sym->st_name; diff --git a/src/elfs/elfhash32.c b/src/elfs/elfhash32.c new file mode 100644 index 00000000..00423b0a --- /dev/null +++ b/src/elfs/elfhash32.c @@ -0,0 +1,190 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <sys/types.h> +#include <link.h> +#include <unistd.h> +#include <errno.h> + +#include "custommem.h" +#include "box64version.h" +#include "elfloader.h" +#include "debug.h" +#include "elfload_dump.h" +#include "elfloader_private.h" + +static int SymbolMatch(elfheader_t* h, uint32_t i, int ver, const char* vername, int local, int veropt) +{ + int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; + if(version!=-1) version &=0x7fff; + const char* symvername = GetSymbolVersion(h, version); + Elf32_Half flags = GetSymbolVersionFlag(h, version); + if(ver==-1 || version==-1) + return 1; + if(version==0 && !local) + return 0; + if(version<2 && ver>1 && veropt) + return 1; + if(ver==0 && version<2) + return 1; + if(ver==1 && version<2) + return 1; + if(ver<2 && version>1 && flags==0) // flag is not WEAK, so global works + return 1; + if(ver<2 || !symvername) + return 0; + return strcmp(vername, symvername)?0:1; +} + +static Elf32_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) +{ + // Prepare hash table + const uint32_t *hashtab = (uint32_t*)(h->hash + h->delta); + const uint32_t nbuckets = hashtab[0]; + const uint32_t nchains = hashtab[1]; + const uint32_t *buckets = &hashtab[2]; + const uint32_t *chains = &buckets[nbuckets]; + // get hash from symname to lookup + const uint32_t hash = old_elf_hash(symname); + // Search for it + for (uint32_t i = buckets[hash % nbuckets]; i; i = chains[i]) { + const char* name = h->DynStr + h->DynSym._32[i].st_name; + if (!strcmp(symname, name) && SymbolMatch(h, i, ver, vername, local, veropt)) { + return &h->DynSym._32[i]; + } + } + return NULL; +} + + +static void old_elf_hash_dump(elfheader_t* h) +{ + // Prepare hash table + const uint32_t *hashtab = (uint32_t*)(h->hash + h->delta); + const uint32_t nbuckets = hashtab[0]; + const uint32_t nchains = hashtab[1]; + const uint32_t *buckets = &hashtab[2]; + const uint32_t *chains = &buckets[nbuckets]; + printf_log(LOG_NONE, "------------ Dump HASH from %s\n", h->name); + printf_log(LOG_NONE, "Buckets[%d] = \n", nbuckets); + for(uint32_t i=0; i<nbuckets; ++i) { + const char* name = h->DynStr + h->DynSym._32[buckets[i]].st_name; + printf_log(LOG_NONE, "%d: %s\n", buckets[i], name); + } + printf_log(LOG_NONE,"Chains[%d] = ", nchains); + for (uint32_t i = 0; i<nchains; ++i) + printf_log(LOG_NONE, "%d ", chains[i]); + printf_log(LOG_NONE, "\n------------\n"); +} + +static Elf32_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) +{ + // Prepare hash table + const uint32_t *hashtab = (uint32_t*)(h->gnu_hash + h->delta); + const uint32_t nbuckets = hashtab[0]; + 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 *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); + if ((word & mask) != mask) { + return NULL; + } + // now look at the bucket chain for the symbol + uint32_t symidx = buckets[hash%nbuckets]; + if (symidx < symoffset) + return NULL; + while(1) { + const char* name = h->DynStr + h->DynSym._32[symidx].st_name; + const uint32_t symhash = chains[symidx-symoffset]; + if ((hash|1) == (symhash|1) && !strcmp(name, symname) && SymbolMatch(h, symidx, ver, vername, local, veropt)) { + return &h->DynSym._32[symidx]; + } + if(symhash&1) + return NULL; + symidx++; + } +} + +static void new_elf_hash_dump(elfheader_t* h) +{ + // Prepare hash table + const uint32_t *hashtab = (uint32_t*)(h->gnu_hash + h->delta); + const uint32_t nbuckets = hashtab[0]; + 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 *buckets = (uint32_t*)&blooms[bloom_size]; + const uint32_t *chains = &buckets[nbuckets]; + printf_log(LOG_NONE, "===============Dump GNU_HASH from %s\n", h->name); + printf_log(LOG_NONE, "Bloom: size=%d, shift=%d\n", bloom_size, bloom_shift); + printf_log(LOG_NONE, "Buckets[%d] offset=%d = \n", nbuckets, symoffset); + for(uint32_t i=0; i<nbuckets; ++i) { + uint32_t symidx = buckets[i]; + printf_log(LOG_NONE, "%d:", symidx); + while(symidx>=symoffset) { + const char* name = h->DynStr + h->DynSym._32[symidx].st_name; + const uint32_t hash = chains[symidx-symoffset]; + if(hash&1) + symidx=0; + else + symidx++; + printf_log(LOG_NONE, " %s (%x) -> %d", name, hash, symidx); + } + printf_log(LOG_NONE, "\n"); + } + printf_log(LOG_NONE, "\n===============\n"); +} + +Elf32_Sym* ElfLookup32(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) +{ + if(h->gnu_hash) + return new_elf_lookup(h, symname, ver, vername, local, veropt); + return old_elf_lookup(h, symname, ver, vername, local, veropt); +} + +Elf32_Sym* ElfSymTabLookup32(elfheader_t* h, const char* symname) +{ + if(!h->SymTab._32) + return 0; + for(size_t i=0; i<h->numSymTab; ++i) { + Elf32_Sym* sym = &h->SymTab._32[i]; + int type = ELF32_ST_TYPE(sym->st_info); + if(type==STT_FUNC || type==STT_TLS || type==STT_OBJECT) { + const char * name = h->StrTab+sym->st_name; + if(name && !strcmp(symname, name)) + return sym; + } + } + return NULL; +} + +Elf32_Sym* ElfDynSymLookup32(elfheader_t* h, const char* symname) +{ + if(!h->DynSym._32) + return 0; + for(size_t i=0; i<h->numDynSym; ++i) { + Elf32_Sym* sym = &h->DynSym._32[i]; + int type = ELF32_ST_TYPE(sym->st_info); + if(type==STT_FUNC || type==STT_TLS || type==STT_OBJECT) { + const char * name = h->DynStr+sym->st_name; + if(name && !strcmp(symname, name)) + return sym; + } + } + return NULL; +} diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c index 62cedcf6..18d4dbc6 100644 --- a/src/elfs/elfload_dump.c +++ b/src/elfs/elfload_dump.c @@ -13,7 +13,7 @@ #define SHT_CHECKSUM 0x6ffffff8 #endif -const char* DumpSection(Elf64_Shdr *s, char* SST) { +static const char* DumpSection(Elf64_Shdr *s, char* SST) { static char buff[400]; switch (s->sh_type) { case SHT_NULL: @@ -64,7 +64,7 @@ const char* DumpSection(Elf64_Shdr *s, char* SST) { return buff; } -const char* DumpDynamic(Elf64_Dyn *s) { +static const char* DumpDynamic(Elf64_Dyn *s) { static char buff[200]; switch (s->d_tag) { case DT_NULL: @@ -148,7 +148,7 @@ const char* DumpDynamic(Elf64_Dyn *s) { return buff; } -const char* DumpPHEntry(Elf64_Phdr *e) +static const char* DumpPHEntry(Elf64_Phdr *e) { static char buff[500]; memset(buff, 0, sizeof(buff)); @@ -174,8 +174,10 @@ const char* DumpPHEntry(Elf64_Phdr *e) } return buff; } - -const char* DumpRelType(int t) +#ifndef BOX32 +const char* DumpRelType32(int t) { return NULL; } +#endif +const char* DumpRelType64(int t) { static char buff[50]; memset(buff, 0, sizeof(buff)); @@ -229,7 +231,7 @@ const char* DumpRelType(int t) return buff; } -const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version) +static const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version) { static char buff[4096]; const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version))); @@ -241,16 +243,22 @@ const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version) return buff; } -const char* SymName(elfheader_t *h, Elf64_Sym* sym) +#ifndef BOX32 +const char* SymName32(elfheader_t *h, Elf32_Sym* sym) { return NULL; } +#endif +const char* SymName64(elfheader_t *h, Elf64_Sym* sym) { return h->DynStr+sym->st_name; } -const char* IdxSymName(elfheader_t *h, int sym) +static const char* IdxSymName(elfheader_t *h, int sym) { - return h->DynStr+h->DynSym[sym].st_name; + return h->DynStr+h->DynSym._64[sym].st_name; } -void DumpMainHeader(Elf64_Ehdr *header, elfheader_t *h) +#ifndef BOX32 +void DumpMainHeader32(Elf32_Ehdr *header, elfheader_t *h) { } +#endif +void DumpMainHeader64(Elf64_Ehdr *header, elfheader_t *h) { if(box64_dump) { printf_dump(LOG_NEVER, "ELF Dump main header\n"); @@ -266,108 +274,142 @@ void DumpMainHeader(Elf64_Ehdr *header, elfheader_t *h) printf_dump(LOG_NEVER, "ELF Dump PEntries (%zu)\n", h->numPHEntries); for (size_t i=0; i<h->numPHEntries; ++i) - printf_dump(LOG_NEVER, " PHEntry %04zu : %s\n", i, DumpPHEntry(h->PHEntries+i)); + printf_dump(LOG_NEVER, " PHEntry %04zu : %s\n", i, DumpPHEntry(h->PHEntries._64+i)); printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n"); printf_dump(LOG_NEVER, "ELF Dump Sections (%zu)\n", h->numSHEntries); for (size_t i=0; i<h->numSHEntries; ++i) - printf_dump(LOG_NEVER, " Section %04zu : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab)); + printf_dump(LOG_NEVER, " Section %04zu : %s\n", i, DumpSection(h->SHEntries._64+i, h->SHStrTab)); printf_dump(LOG_NEVER, "ELF Dump Sections ====\n"); } } - -void DumpSymTab(elfheader_t *h) +#ifndef BOX32 +void DumpSymTab32(elfheader_t *h) { } +#endif +void DumpSymTab64(elfheader_t *h) { - if(box64_dump && h->SymTab) { + if(box64_dump && h->SymTab._64) { const char* name = ElfName(h); printf_dump(LOG_NEVER, "ELF Dump SymTab(%zu)=\n", h->numSymTab); for (size_t i=0; i<h->numSymTab; ++i) printf_dump(LOG_NEVER, " %s:SymTab[%zu] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name, - i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size, - h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx); + i, h->StrTab+h->SymTab._64[i].st_name, (void*)h->SymTab._64[i].st_value, h->SymTab._64[i].st_size, + h->SymTab._64[i].st_info, h->SymTab._64[i].st_other, h->SymTab._64[i].st_shndx); printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n"); } } -void DumpDynamicSections(elfheader_t *h) +#ifndef BOX32 +void DumpDynamicSections32(elfheader_t *h) { } +#endif +void DumpDynamicSections64(elfheader_t *h) { - if(box64_dump && h->Dynamic) { + if(box64_dump && h->Dynamic._64) { printf_dump(LOG_NEVER, "ELF Dump Dynamic(%zu)=\n", h->numDynamic); for (size_t i=0; i<h->numDynamic; ++i) - printf_dump(LOG_NEVER, " Dynamic %04zu : %s\n", i, DumpDynamic(h->Dynamic+i)); + printf_dump(LOG_NEVER, " Dynamic %04zu : %s\n", i, DumpDynamic(h->Dynamic._64+i)); printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n"); } } -void DumpDynSym(elfheader_t *h) +#ifndef BOX32 +void DumpDynSym32(elfheader_t *h) { } +#endif +void DumpDynSym64(elfheader_t *h) { - if(box64_dump && h->DynSym) { + if(box64_dump && h->DynSym._64) { const char* name = ElfName(h); printf_dump(LOG_NEVER, "ELF Dump DynSym(%zu)=\n", h->numDynSym); for (size_t i=0; i<h->numDynSym; ++i) { int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; - printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym+i, version)); + printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym._64+i, version)); } printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n"); } } +void DumpDynamicNeeded32(elfheader_t *h) +#ifndef BOX32 + { } +#else + ; +#endif void DumpDynamicNeeded(elfheader_t *h) { - if(box64_dump && h->DynStrTab) { - printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n"); - for (size_t i=0; i<h->numDynamic; ++i) - if(h->Dynamic[i].d_tag==DT_NEEDED) { - printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta); - } - printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n"); - } + if(box64_is32bits) + DumpDynamicNeeded32(h); + else + if(box64_dump && h->DynStrTab) { + printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n"); + for (size_t i=0; i<h->numDynamic; ++i) + if(h->Dynamic._64[i].d_tag==DT_NEEDED) { + printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic._64[i].d_un.d_val + h->delta); + } + printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n"); + } } +void DumpDynamicRPath32(elfheader_t *h) +#ifndef BOX32 +{ } +#else + ; +#endif void DumpDynamicRPath(elfheader_t *h) { - if(box64_dump && h->DynStrTab) { - printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n"); - for (size_t i=0; i<h->numDynamic; ++i) { - if(h->Dynamic[i].d_tag==DT_RPATH) { - printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta); - } - if(h->Dynamic[i].d_tag==DT_RUNPATH) { - printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta); + if(box64_is32bits) + DumpDynamicRPath32(h); + else + if(box64_dump && h->DynStrTab) { + printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n"); + for (size_t i=0; i<h->numDynamic; ++i) { + if(h->Dynamic._64[i].d_tag==DT_RPATH) { + printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic._64[i].d_un.d_val + h->delta); + } + if(h->Dynamic._64[i].d_tag==DT_RUNPATH) { + printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic._64[i].d_un.d_val + h->delta); + } } + printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n"); } - printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n"); - } } -void DumpRelTable(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name) +#ifndef BOX32 +void DumpRelTable32(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name) { } +#endif +void DumpRelTable64(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name) { if(box64_dump) { const char* elfname = ElfName(h); printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel); for (int i = 0; i<cnt; ++i) printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname, - i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType(ELF64_R_TYPE(rel[i].r_info)), + i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType64(ELF64_R_TYPE(rel[i].r_info)), ELF64_R_SYM(rel[i].r_info), IdxSymName(h, ELF64_R_SYM(rel[i].r_info))); printf_dump(LOG_NEVER, "ELF Dump Rel Table=====\n"); } } - -void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name) +#ifndef BOX32 +void DumpRelATable32(elfheader_t *h, int cnt, Elf32_Rela *rela, const char* name) { } +#endif +void DumpRelATable64(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name) { if(box64_dump && h->rela) { const char* elfname = ElfName(h); printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela); for (int i = 0; i<cnt; ++i) printf_dump(LOG_NEVER, " %s:%s[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname, name, - i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), + i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType64(ELF64_R_TYPE(rela[i].r_info)), ELF64_R_SYM(rela[i].r_info), IdxSymName(h, ELF64_R_SYM(rela[i].r_info)), rela[i].r_addend); printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name); } } -void DumpRelRTable(elfheader_t *h, int cnt, Elf64_Relr *relr, const char *name) +#ifndef BOX32 +void DumpRelRTable32(elfheader_t *h, int cnt, Elf32_Relr *relr, const char *name) { } +#endif +void DumpRelRTable64(elfheader_t *h, int cnt, Elf64_Relr *relr, const char *name) { if(box64_dump && h->relr) { const char* elfname = ElfName(h); diff --git a/src/elfs/elfload_dump32.c b/src/elfs/elfload_dump32.c new file mode 100755 index 00000000..b6d8df41 --- /dev/null +++ b/src/elfs/elfload_dump32.c @@ -0,0 +1,352 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> + +#include "box64version.h" +#include "elfloader.h" +#include "debug.h" +#include "elfload_dump.h" +#include "elfloader_private.h" +#include "box32.h" + +static const char* DumpSection(Elf32_Shdr *s, char* SST) { + static char buff[400]; + switch (s->sh_type) { + case SHT_NULL: + return "SHT_NULL"; + #define GO(A) \ + case A: \ + sprintf(buff, #A " Name=\"%s\"(%d) off=0x%X, size=%d, attr=0x%04X, addr=%p(%02X), link/info=%d/%d", \ + SST+s->sh_name, s->sh_name, s->sh_offset, s->sh_size, s->sh_flags, from_ptrv(s->sh_addr), s->sh_addralign, s->sh_link, s->sh_info); \ + break + GO(SHT_PROGBITS); + GO(SHT_SYMTAB); + GO(SHT_STRTAB); + GO(SHT_RELA); + GO(SHT_HASH); + GO(SHT_DYNAMIC); + GO(SHT_NOTE); + GO(SHT_NOBITS); + GO(SHT_REL); + GO(SHT_SHLIB); + GO(SHT_DYNSYM); + GO(SHT_INIT_ARRAY); + GO(SHT_FINI_ARRAY); + GO(SHT_PREINIT_ARRAY); + GO(SHT_GROUP); + GO(SHT_SYMTAB_SHNDX); + GO(SHT_NUM); + GO(SHT_LOPROC); + GO(SHT_HIPROC); + GO(SHT_LOUSER); + GO(SHT_HIUSER); + #if defined(SHT_GNU_versym) && defined(SHT_GNU_ATTRIBUTES) + GO(SHT_GNU_versym); + GO(SHT_GNU_ATTRIBUTES); + GO(SHT_GNU_HASH); + GO(SHT_GNU_LIBLIST); + GO(SHT_CHECKSUM); + GO(SHT_LOSUNW); + //GO(SHT_SUNW_move); + GO(SHT_SUNW_COMDAT); + GO(SHT_SUNW_syminfo); + GO(SHT_GNU_verdef); + GO(SHT_GNU_verneed); + #endif + #undef GO + default: + sprintf(buff, "0x%X unknown type", s->sh_type); + } + return buff; +} + +static const char* DumpDynamic(Elf32_Dyn *s) { + static char buff[200]; + switch (s->d_tag) { + case DT_NULL: + return "DT_NULL: End Dynamic Section"; + #define GO(A, Add) \ + case A: \ + sprintf(buff, #A " %s=0x%X", (Add)?"Addr":"Val", (Add)?s->d_un.d_ptr:s->d_un.d_val); \ + break + GO(DT_NEEDED, 0); + GO(DT_PLTRELSZ, 0); + GO(DT_PLTGOT, 1); + GO(DT_HASH, 1); + GO(DT_STRTAB, 1); + GO(DT_SYMTAB, 1); + GO(DT_RELA, 1); + GO(DT_RELASZ, 0); + GO(DT_RELAENT, 0); + GO(DT_STRSZ, 0); + GO(DT_SYMENT, 0); + GO(DT_INIT, 1); + GO(DT_FINI, 1); + GO(DT_SONAME, 0); + GO(DT_RPATH, 0); + GO(DT_SYMBOLIC, 0); + GO(DT_REL, 1); + GO(DT_RELSZ, 0); + GO(DT_RELENT, 0); + GO(DT_PLTREL, 0); + GO(DT_DEBUG, 0); + GO(DT_TEXTREL, 0); + GO(DT_JMPREL, 1); + GO(DT_BIND_NOW, 1); + GO(DT_INIT_ARRAY, 1); + GO(DT_FINI_ARRAY, 1); + GO(DT_INIT_ARRAYSZ, 0); + GO(DT_FINI_ARRAYSZ, 0); + GO(DT_RUNPATH, 0); + GO(DT_FLAGS, 0); + GO(DT_ENCODING, 0); + #if defined(DT_NUM) && defined(DT_TLSDESC_PLT) + GO(DT_NUM, 0); + GO(DT_VALRNGLO, 0); + GO(DT_GNU_PRELINKED, 0); + GO(DT_GNU_CONFLICTSZ, 0); + GO(DT_GNU_LIBLISTSZ, 0); + GO(DT_CHECKSUM, 0); + GO(DT_PLTPADSZ, 0); + GO(DT_MOVEENT, 0); + GO(DT_MOVESZ, 0); + GO(DT_FEATURE_1, 0); + GO(DT_POSFLAG_1, 0); + GO(DT_SYMINSZ, 0); + GO(DT_SYMINENT, 0); + GO(DT_ADDRRNGLO, 0); + GO(DT_GNU_HASH, 0); + GO(DT_TLSDESC_PLT, 0); + GO(DT_TLSDESC_GOT, 0); + GO(DT_GNU_CONFLICT, 0); + GO(DT_GNU_LIBLIST, 0); + GO(DT_CONFIG, 0); + GO(DT_DEPAUDIT, 0); + GO(DT_AUDIT, 0); + GO(DT_PLTPAD, 0); + GO(DT_MOVETAB, 0); + GO(DT_SYMINFO, 0); + GO(DT_VERSYM, 0); + GO(DT_RELACOUNT, 0); + GO(DT_RELCOUNT, 0); + GO(DT_FLAGS_1, 0); + GO(DT_VERDEF, 0); + GO(DT_VERDEFNUM, 0); + GO(DT_VERNEED, 0); + GO(DT_VERNEEDNUM, 0); + GO(DT_AUXILIARY, 0); + GO(DT_FILTER, 0); + #endif + #undef GO + default: + sprintf(buff, "0x%X unknown type", s->d_tag); + } + return buff; +} + +static const char* DumpPHEntry(Elf32_Phdr *e) +{ + static char buff[500]; + memset(buff, 0, sizeof(buff)); + switch(e->p_type) { + case PT_NULL: sprintf(buff, "type: %s", "PT_NULL"); break; + #define GO(T) case T: sprintf(buff, "type: %s, Off=%x vaddr=%p paddr=%p filesz=%u memsz=%u flags=%x align=%u", #T, e->p_offset, from_ptrv(e->p_vaddr), from_ptrv(e->p_paddr), e->p_filesz, e->p_memsz, e->p_flags, e->p_align); break + GO(PT_LOAD); + GO(PT_DYNAMIC); + GO(PT_INTERP); + GO(PT_NOTE); + GO(PT_SHLIB); + GO(PT_PHDR); + GO(PT_TLS); + #ifdef PT_NUM + GO(PT_NUM); + GO(PT_LOOS); + GO(PT_GNU_EH_FRAME); + GO(PT_GNU_STACK); + GO(PT_GNU_RELRO); + #endif + #undef GO + default: sprintf(buff, "type: %x, Off=%x vaddr=%p paddr=%p filesz=%u memsz=%u flags=%x align=%u", e->p_type, e->p_offset, from_ptrv(e->p_vaddr), from_ptrv(e->p_paddr), e->p_filesz, e->p_memsz, e->p_flags, e->p_align); break; + } + return buff; +} + +const char* DumpRelType32(int t) +{ + static char buff[50]; + memset(buff, 0, sizeof(buff)); + switch(t) { + #define GO(T) case T: sprintf(buff, "type: %s", #T); break + GO(R_386_NONE); + GO(R_386_32); + GO(R_386_PC32); + GO(R_386_GOT32); + GO(R_386_PLT32); + GO(R_386_COPY); + GO(R_386_GLOB_DAT); + GO(R_386_JMP_SLOT); + GO(R_386_RELATIVE); + GO(R_386_GOTOFF); + GO(R_386_GOTPC); + GO(R_386_PC8); + GO(R_386_TLS_TPOFF); + GO(R_386_TLS_GD_32); + GO(R_386_TLS_DTPMOD32); + GO(R_386_TLS_DTPOFF32); + GO(R_386_TLS_TPOFF32); + #undef GO + default: sprintf(buff, "type: 0x%x (unknown)", t); break; + } + return buff; +} + +static const char* DumpSym(elfheader_t *h, Elf32_Sym* sym, int version) +{ + static char buff[4096]; + const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version))); + memset(buff, 0, sizeof(buff)); + sprintf(buff, "\"%s\", value=%p, size=%d, info/other=%d/%d index=%d (ver=%d/%s)", + h->DynStr+sym->st_name, from_ptrv(sym->st_value), sym->st_size, + sym->st_info, sym->st_other, sym->st_shndx, version, vername); + return buff; +} + +const char* SymName32(elfheader_t *h, Elf32_Sym* sym) +{ + return h->DynStr+sym->st_name; +} +static const char* IdxSymName(elfheader_t *h, int sym) +{ + return h->DynStr+h->DynSym._32[sym].st_name; +} + +void DumpMainHeader32(Elf32_Ehdr *header, elfheader_t *h) +{ + if(box64_dump) { + printf_dump(LOG_NEVER, "ELF Dump main header\n"); + printf_dump(LOG_NEVER, " Entry point = %p\n", from_ptrv(header->e_entry)); + printf_dump(LOG_NEVER, " Program Header table offset = %p\n", from_ptrv(header->e_phoff)); + printf_dump(LOG_NEVER, " Section Header table offset = %p\n", from_ptrv(header->e_shoff)); + printf_dump(LOG_NEVER, " Flags = 0x%X\n", header->e_flags); + printf_dump(LOG_NEVER, " ELF Header size = %d\n", header->e_ehsize); + printf_dump(LOG_NEVER, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize); + printf_dump(LOG_NEVER, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize); + printf_dump(LOG_NEVER, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx); + printf_dump(LOG_NEVER, "ELF Dump ==========\n"); + + printf_dump(LOG_NEVER, "ELF Dump PEntries (%d)\n", h->numSHEntries); + for (int i=0; i<h->numPHEntries; ++i) + printf_dump(LOG_NEVER, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries._32+i)); + printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n"); + + printf_dump(LOG_NEVER, "ELF Dump Sections (%d)\n", h->numSHEntries); + for (int i=0; i<h->numSHEntries; ++i) + printf_dump(LOG_NEVER, " Section %04d : %s\n", i, DumpSection(h->SHEntries._32+i, h->SHStrTab)); + printf_dump(LOG_NEVER, "ELF Dump Sections ====\n"); + } +} + +void DumpSymTab32(elfheader_t *h) +{ + if(box64_dump && h->SymTab._32) { + const char* name = ElfName(h); + printf_dump(LOG_NEVER, "ELF Dump SymTab(%d)=\n", h->numSymTab); + for (int i=0; i<h->numSymTab; ++i) + printf_dump(LOG_NEVER, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name, + i, h->StrTab+h->SymTab._32[i].st_name, from_ptrv(h->SymTab._32[i].st_value), h->SymTab._32[i].st_size, + h->SymTab._32[i].st_info, h->SymTab._32[i].st_other, h->SymTab._32[i].st_shndx); + printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n"); + } +} + +void DumpDynamicSections32(elfheader_t *h) +{ + if(box64_dump && h->Dynamic._32) { + printf_dump(LOG_NEVER, "ELF Dump Dynamic(%d)=\n", h->numDynamic); + for (int i=0; i<h->numDynamic; ++i) + printf_dump(LOG_NEVER, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic._32+i)); + printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n"); + } +} + +void DumpDynSym32(elfheader_t *h) +{ + if(box64_dump && h->DynSym._32) { + const char* name = ElfName(h); + printf_dump(LOG_NEVER, "ELF Dump DynSym(%d)=\n", h->numDynSym); + for (int i=0; i<h->numDynSym; ++i) { + int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; + printf_dump(LOG_NEVER, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym._32+i, version)); + } + printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n"); + } +} + +void DumpDynamicNeeded32(elfheader_t *h) +{ + if(box64_dump && h->DynStrTab) { + printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n"); + for (int i=0; i<h->numDynamic; ++i) + if(h->Dynamic._32[i].d_tag==DT_NEEDED) { + printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic._32[i].d_un.d_val + h->delta); + } + printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n"); + } +} + +void DumpDynamicRPath32(elfheader_t *h) +{ + if(box64_dump && h->DynStrTab) { + printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n"); + for (int i=0; i<h->numDynamic; ++i) { + if(h->Dynamic._32[i].d_tag==DT_RPATH) { + printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic._32[i].d_un.d_val + h->delta); + } + if(h->Dynamic._32[i].d_tag==DT_RUNPATH) { + printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic._32[i].d_un.d_val + h->delta); + } + } + printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n"); + } +} + +void DumpRelTable32(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name) +{ + if(box64_dump) { + const char* elfname = ElfName(h); + printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel); + for (int i = 0; i<cnt; ++i) + printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%X: %s, sym=0x%0X/%s)\n", elfname, + i, from_ptrv(rel[i].r_offset), rel[i].r_info, DumpRelType32(ELF32_R_TYPE(rel[i].r_info)), + ELF32_R_SYM(rel[i].r_info), IdxSymName(h, ELF32_R_SYM(rel[i].r_info))); + printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name); + } +} + +void DumpRelATable32(elfheader_t *h, int cnt, Elf32_Rela *rela, const char* name) +{ + if(box64_dump && h->rela) { + const char* elfname = ElfName(h); + printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela); + for (int i = 0; i<cnt; ++i) + printf_dump(LOG_NEVER, " %s:RelA[%d] = %p (0x%X: %s, sym=0x%X/%s) Addend=%d\n", elfname, + i, from_ptrv(rela[i].r_offset), rela[i].r_info, DumpRelType32(ELF32_R_TYPE(rela[i].r_info)), + ELF32_R_SYM(rela[i].r_info), IdxSymName(h, ELF32_R_SYM(rela[i].r_info)), + rela[i].r_addend); + printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name); + } +} + +void DumpRelRTable32(elfheader_t *h, int cnt, Elf32_Relr *relr, const char* name) +{ + if(box64_dump && h->relr) { + const char* elfname = ElfName(h); + printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, relr); + for (int i = 0; i<cnt; ++i) + printf_dump(LOG_NEVER, " %s:%s[%d] = %p\n", elfname, name, + i, from_ptrv(relr[i])); + printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name); + } +} + diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 016ae50b..248c4282 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -46,7 +46,7 @@ void* my__IO_2_1_stdin_ = NULL; void* my__IO_2_1_stdout_ = NULL; // return the index of header (-1 if it doesn't exist) -int getElfIndex(box64context_t* ctx, elfheader_t* head) { +static int getElfIndex(box64context_t* ctx, elfheader_t* head) { for (int i=0; i<ctx->elfsize; ++i) if(ctx->elfs[i]==head) return i; @@ -55,7 +55,7 @@ int getElfIndex(box64context_t* ctx, elfheader_t* head) { elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec) { - elfheader_t *h = ParseElfHeader(f, name, exec); + elfheader_t *h = box64_is32bits?ParseElfHeader32(f, name, exec):ParseElfHeader64(f, name, exec); if(!h) return NULL; @@ -80,14 +80,14 @@ void FreeElfHeader(elfheader_t** head) if(my_context) RemoveElfHeader(my_context, h); - box_free(h->PHEntries); - box_free(h->SHEntries); + box_free(h->PHEntries._64); //_64 or _32 doesn't mater for free, it's the same address + box_free(h->SHEntries._64); box_free(h->SHStrTab); box_free(h->StrTab); - box_free(h->Dynamic); + box_free(h->Dynamic._64); box_free(h->DynStr); - box_free(h->SymTab); - box_free(h->DynSym); + box_free(h->SymTab._64); + box_free(h->DynSym._64); FreeElfMemory(h); @@ -105,13 +105,23 @@ int CalcLoadAddr(elfheader_t* head) head->memsz = 0; head->paddr = head->vaddr = ~(uintptr_t)0; head->align = box64_pagesize; - for (size_t i=0; i<head->numPHEntries; ++i) - if(head->PHEntries[i].p_type == PT_LOAD) { - if(head->paddr > (uintptr_t)head->PHEntries[i].p_paddr) - head->paddr = (uintptr_t)head->PHEntries[i].p_paddr; - if(head->vaddr > (uintptr_t)head->PHEntries[i].p_vaddr) - head->vaddr = (uintptr_t)head->PHEntries[i].p_vaddr; - } + if(box64_is32bits) { + for (size_t i=0; i<head->numPHEntries; ++i) + if(head->PHEntries._32[i].p_type == PT_LOAD) { + if(head->paddr > (uintptr_t)head->PHEntries._32[i].p_paddr) + head->paddr = (uintptr_t)head->PHEntries._32[i].p_paddr; + if(head->vaddr > (uintptr_t)head->PHEntries._32[i].p_vaddr) + head->vaddr = (uintptr_t)head->PHEntries._32[i].p_vaddr; + } + } else { + for (size_t i=0; i<head->numPHEntries; ++i) + if(head->PHEntries._64[i].p_type == PT_LOAD) { + if(head->paddr > (uintptr_t)head->PHEntries._64[i].p_paddr) + head->paddr = (uintptr_t)head->PHEntries._64[i].p_paddr; + if(head->vaddr > (uintptr_t)head->PHEntries._64[i].p_vaddr) + head->vaddr = (uintptr_t)head->PHEntries._64[i].p_vaddr; + } + } if(head->vaddr==~(uintptr_t)0 || head->paddr==~(uintptr_t)0) { printf_log(LOG_NONE, "Error: v/p Addr for Elf Load not set\n"); @@ -120,31 +130,58 @@ int CalcLoadAddr(elfheader_t* head) head->stacksz = 1024*1024; //1M stack size default? head->stackalign = 16; // default align for stack - for (size_t i=0; i<head->numPHEntries; ++i) { - if(head->PHEntries[i].p_type == PT_LOAD) { - uintptr_t phend = head->PHEntries[i].p_vaddr - head->vaddr + head->PHEntries[i].p_memsz; - if(phend > head->memsz) - head->memsz = phend; - if(head->PHEntries[i].p_align > head->align) - head->align = head->PHEntries[i].p_align; - } - if(head->PHEntries[i].p_type == PT_GNU_STACK) { - if(head->stacksz < head->PHEntries[i].p_memsz) - head->stacksz = head->PHEntries[i].p_memsz; - if(head->stackalign < head->PHEntries[i].p_align) - head->stackalign = head->PHEntries[i].p_align; + if(box64_is32bits) + for (size_t i=0; i<head->numPHEntries; ++i) { + if(head->PHEntries._32[i].p_type == PT_LOAD) { + uintptr_t phend = head->PHEntries._32[i].p_vaddr - head->vaddr + head->PHEntries._32[i].p_memsz; + if(phend > head->memsz) + head->memsz = phend; + if(head->PHEntries._32[i].p_align > head->align) + head->align = head->PHEntries._32[i].p_align; + } + if(head->PHEntries._32[i].p_type == PT_GNU_STACK) { + if(head->stacksz < head->PHEntries._32[i].p_memsz) + head->stacksz = head->PHEntries._32[i].p_memsz; + if(head->stackalign < head->PHEntries._32[i].p_align) + head->stackalign = head->PHEntries._32[i].p_align; + } + if(head->PHEntries._32[i].p_type == PT_TLS) { + head->tlsaddr = head->PHEntries._32[i].p_vaddr; + head->tlssize = head->PHEntries._32[i].p_memsz; + head->tlsfilesize = head->PHEntries._32[i].p_filesz; + head->tlsalign = head->PHEntries._32[i].p_align; + // force alignement... + if(head->tlsalign>1) + while(head->tlssize&(head->tlsalign-1)) + head->tlssize++; + } } - if(head->PHEntries[i].p_type == PT_TLS) { - head->tlsaddr = head->PHEntries[i].p_vaddr; - head->tlssize = head->PHEntries[i].p_memsz; - head->tlsfilesize = head->PHEntries[i].p_filesz; - head->tlsalign = head->PHEntries[i].p_align; - // force alignement... - if(head->tlsalign>1) - while(head->tlssize&(head->tlsalign-1)) - head->tlssize++; + else + for (size_t i=0; i<head->numPHEntries; ++i) { + if(head->PHEntries._64[i].p_type == PT_LOAD) { + uintptr_t phend = head->PHEntries._64[i].p_vaddr - head->vaddr + head->PHEntries._64[i].p_memsz; + if(phend > head->memsz) + head->memsz = phend; + if(head->PHEntries._64[i].p_align > head->align) + head->align = head->PHEntries._64[i].p_align; + } + if(head->PHEntries._64[i].p_type == PT_GNU_STACK) { + if(head->stacksz < head->PHEntries._64[i].p_memsz) + head->stacksz = head->PHEntries._64[i].p_memsz; + if(head->stackalign < head->PHEntries._64[i].p_align) + head->stackalign = head->PHEntries._64[i].p_align; + } + if(head->PHEntries._64[i].p_type == PT_TLS) { + head->tlsaddr = head->PHEntries._64[i].p_vaddr; + head->tlssize = head->PHEntries._64[i].p_memsz; + head->tlsfilesize = head->PHEntries._64[i].p_filesz; + head->tlsalign = head->PHEntries._64[i].p_align; + // force alignement... + if(head->tlsalign>1) + while(head->tlssize&(head->tlsalign-1)) + head->tlssize++; + } } - } printf_log(LOG_DEBUG, "Elf Addr(v/p)=%p/%p Memsize=0x%zx (align=0x%zx)\n", (void*)head->vaddr, (void*)head->paddr, head->memsz, head->align); printf_log(LOG_DEBUG, "Elf Stack Memsize=%zu (align=%zu)\n", head->stacksz, head->stackalign); printf_log(LOG_DEBUG, "Elf TLS Memsize=%zu (align=%zu)\n", head->tlssize, head->tlsalign); @@ -165,8 +202,16 @@ const char* ElfPath(elfheader_t* head) return head->path; } +int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin) +#ifndef BOX32 +{ return 1; } +#else + ; +#endif int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) { + if(box64_is32bits) + return AllocLoadElfMemory32(context, head, mainbin); uintptr_t offs = 0; loadProtectionFromMap(); int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG; @@ -174,7 +219,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) head->multiblock_n = 0; // count PHEntrie with LOAD uintptr_t max_align = head->align-1; for (size_t i=0; i<head->numPHEntries; ++i) - if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) { + if(head->PHEntries._64[i].p_type == PT_LOAD && head->PHEntries._64[i].p_flags) { ++head->multiblock_n; } @@ -230,8 +275,8 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) head->memory = (char*)0xffffffffffffffff; int n = 0; for (size_t i=0; i<head->numPHEntries; ++i) { - if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) { - Elf64_Phdr * e = &head->PHEntries[i]; + if(head->PHEntries._64[i].p_type == PT_LOAD && head->PHEntries._64[i].p_flags) { + Elf64_Phdr * e = &head->PHEntries._64[i]; head->multiblocks[n].flags = e->p_flags; head->multiblocks[n].offs = e->p_offset; @@ -350,8 +395,8 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) head->memory = (char*)head->multiblocks[n].p; ++n; } - if(head->PHEntries[i].p_type == PT_TLS) { - Elf64_Phdr * e = &head->PHEntries[i]; + if(head->PHEntries._64[i].p_type == PT_TLS) { + Elf64_Phdr * e = &head->PHEntries._64[i]; char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); if(e->p_filesz) { @@ -400,7 +445,7 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne { if(!verneeded || !head) return 1; - if(!head->VerDef || !verneeded->VerNeed) + if(!head->VerDef._64 || !verneeded->VerNeed._64) return 1; int cnt = GetNeededVersionCnt(verneeded, libname); for (int i=0; i<cnt; ++i) { @@ -418,9 +463,9 @@ static int IsSymInElfSpace(const elfheader_t* h, Elf64_Sym* sym) if(!h || !sym) return 0; uintptr_t addr = (uintptr_t)sym; - if(h->SymTab && addr>=(uintptr_t)h->SymTab && addr<(uintptr_t)&h->SymTab[h->numSymTab]) + if(h->SymTab._64 && addr>=(uintptr_t)h->SymTab._64 && addr<(uintptr_t)&h->SymTab._64[h->numSymTab]) return 1; - if(h->DynSym && addr>=(uintptr_t)h->DynSym && addr<(uintptr_t)&h->DynSym[h->numDynSym]) + if(h->DynSym._64 && addr>=(uintptr_t)h->DynSym._64 && addr<(uintptr_t)&h->DynSym._64[h->numDynSym]) return 1; return 0; } @@ -435,7 +480,7 @@ static elfheader_t* FindElfSymbol(box64context_t *context, Elf64_Sym* sym) return NULL; } -int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername, int veropt) +static int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername, int veropt) { if(!h) return 0; @@ -445,8 +490,8 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** int cnt = h->relasz / h->relaent; for (int i=0; i<cnt; ++i) { int t = ELF64_R_TYPE(rela[i].r_info); - Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rela[i].r_info)]; - const char* symname = SymName(h, sym); + Elf64_Sym *sym = &h->DynSym._64[ELF64_R_SYM(rela[i].r_info)]; + const char* symname = SymName64(h, sym); if((t==R_X86_64_COPY) && symname && !strcmp(symname, name) && (sym->st_size==size)) { int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rela[i].r_info)]:-1; if(version2!=-1) version2 &= 0x7fff; @@ -464,7 +509,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** return 0; } -int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rel *rel) +static int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rel *rel) { printf_log(LOG_NONE, "Error: REL type of Relocation unsupported (only RELA)\n"); return 1; @@ -483,7 +528,7 @@ EXPORT uintptr_t my__dl_tlsdesc_undefweak(x64emu_t* emu) return td->arg; } -void GrabX64CopyMainElfReloc(elfheader_t* head) +static void GrabX64CopyMainElfReloc(elfheader_t* head) { if(head->rela) { int cnt = head->relasz / head->relaent; @@ -492,8 +537,8 @@ void GrabX64CopyMainElfReloc(elfheader_t* head) for (int i=0; i<cnt; ++i) { int t = ELF64_R_TYPE(rela[i].r_info); if(t == R_X86_64_COPY) { - Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)]; - const char* symname = SymName(head, sym); + Elf64_Sym *sym = &head->DynSym._64[ELF64_R_SYM(rela[i].r_info)]; + const char* symname = SymName64(head, sym); 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); @@ -505,21 +550,6 @@ void GrabX64CopyMainElfReloc(elfheader_t* head) } } } -void CheckGNUUniqueBindings(elfheader_t* head) -{ - if(head->rela) { - int cnt = head->relasz / head->relaent; - Elf64_Rela* rela = (Elf64_Rela *)(head->rela + head->delta); - printf_dump(LOG_DEBUG, "Checking for symbol with STB_GNU_UNIQUE bindingsfor %s\n", head->name); - for (int i=0; i<cnt; ++i) { - int bind = ELF64_ST_BIND(rela[i].r_info); - if(bind == STB_GNU_UNIQUE) { - head->gnuunique = 1; - return; // can stop searching - } - } - } -} static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib) { @@ -531,15 +561,15 @@ static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib) return h; } -int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv) +static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv) { int ret_ok = 0; 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)]; + Elf64_Sym *sym = &head->DynSym._64[ELF64_R_SYM(rela[i].r_info)]; int bind = ELF64_ST_BIND(sym->st_info); //uint64_t ndx = sym->st_shndx; - const char* symname = SymName(head, sym); + const char* symname = SymName64(head, sym); uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta); uintptr_t offs = 0; uintptr_t end = 0; @@ -554,7 +584,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin Elf64_Sym* elfsym = NULL; int vis = ELF64_ST_VISIBILITY(sym->st_other); if(vis==STV_PROTECTED) { - elfsym = ElfDynSymLookup(head, symname); + elfsym = ElfDynSymLookup64(head, symname); printf_log(LOG_DEBUG, "Symbol %s from %s is PROTECTED\n", symname, head->name); } else { if(bind==STB_GNU_UNIQUE) { @@ -566,7 +596,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin offs = sym->st_value + head->delta; end = offs + sym->st_size; } else { - elfsym = ElfDynSymLookup(head, symname); + elfsym = ElfDynSymLookup64(head, symname); if(elfsym && elfsym->st_shndx) { offs = elfsym->st_value + head->delta; end = offs + elfsym->st_size; @@ -695,7 +725,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin if(offs!=globoffs) { offs = globoffs; sym_elf = my_context->elfs[0]; - elfsym = ElfDynSymLookup(sym_elf, symname); + elfsym = ElfDynSymLookup64(sym_elf, symname); } } if (!offs && !elfsym) { @@ -718,11 +748,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } if(sym_elf) { delta = *(int64_t*)p; - printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", BindSym(bind), DumpRelType(t), symname, p, delta, sym_elf->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs); + printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", BindSym(bind), DumpRelType64(t), symname, p, delta, sym_elf->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs); *p = (uintptr_t)((int64_t)offs + rela[i].r_addend + sym_elf->tlsbase); if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } else { - printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", BindSym(bind), DumpRelType(t), symname, p, (int64_t)offs); + printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", BindSym(bind), DumpRelType64(t), symname, p, (int64_t)offs); } } break; @@ -779,13 +809,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } break; default: - printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), symname); + printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType64(ELF64_R_TYPE(rela[i].r_info)), symname); } } return bindnow?ret_ok:0; } -int RelocateElfRELR(elfheader_t *head, int cnt, Elf64_Relr *relr) { +static int RelocateElfRELR(elfheader_t *head, int cnt, Elf64_Relr *relr) { Elf64_Addr *where = NULL; for (int i = 0; i < cnt; i++) { Elf64_Relr p = relr[i]; @@ -805,7 +835,13 @@ int RelocateElfRELR(elfheader_t *head, int cnt, Elf64_Relr *relr) { return 0; } -int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) +int RelocateElf32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) +#ifndef BOX32 +{ return -1; } +#else + ; +#endif +int RelocateElf64(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { if((head->flags&DF_BIND_NOW) && !bindnow) { bindnow = 1; @@ -813,29 +849,34 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, e } if(head->relr) { int cnt = head->relrsz / head->relrent; - DumpRelRTable(head, cnt, (Elf64_Relr *)(head->relr + head->delta), "RelR"); + DumpRelRTable64(head, cnt, (Elf64_Relr *)(head->relr + head->delta), "RelR"); printf_dump(LOG_DEBUG, "Applying %d Relocation(s) without Addend for %s bindnow=%d, deepbind=%d\n", cnt, head->name, bindnow, deepbind); if(RelocateElfRELR(head, cnt, (Elf64_Relr *)(head->relr + head->delta))) return -1; } if(head->rel) { int cnt = head->relsz / head->relent; - DumpRelTable(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel"); + DumpRelTable64(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel"); printf_dump(LOG_DEBUG, "Applying %d Relocation(s) for %s bindnow=%d, deepbind=%d\n", cnt, head->name, bindnow, deepbind); if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rel *)(head->rel + head->delta))) return -1; } if(head->rela) { int cnt = head->relasz / head->relaent; - DumpRelATable(head, cnt, (Elf64_Rela *)(head->rela + head->delta), "RelA"); + DumpRelATable64(head, cnt, (Elf64_Rela *)(head->rela + head->delta), "RelA"); printf_dump(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s bindnow=%d, deepbind=%d\n", cnt, head->name, bindnow, deepbind); if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL)) return -1; } return 0; } +int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) +{ + return box64_is32bits?RelocateElf32(maplib, local_maplib, bindnow, deepbind, head):RelocateElf64(maplib, local_maplib, bindnow, deepbind, head); +} -int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) +int RelocateElfPlt32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { /* TODO */ return -1; } +int RelocateElfPlt64(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { int need_resolver = 0; if((head->flags&DF_BIND_NOW) && !bindnow) { @@ -845,26 +886,26 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind if(head->pltrel) { int cnt = head->pltsz / head->pltent; if(head->pltrel==DT_REL) { - DumpRelTable(head, cnt, (Elf64_Rel *)(head->jmprel + head->delta), "PLT"); + DumpRelTable64(head, cnt, (Elf64_Rel *)(head->jmprel + head->delta), "PLT"); printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s bindnow=%d, deepbind=%d\n", cnt, head->name, bindnow, deepbind); if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta))) return -1; } else if(head->pltrel==DT_RELA) { - DumpRelATable(head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), "PLT"); + DumpRelATable64(head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), "PLT"); printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s bindnow=%d, deepbind=%d\n", cnt, head->name, bindnow, deepbind); if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver)) return -1; } if(need_resolver) { - if(pltResolver==(uintptr_t)-1) { - pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0, "PltResolver"); + if(pltResolver64==(uintptr_t)-1) { + pltResolver64 = AddBridge(my_context->system, vFE, PltResolver64, 0, "PltResolver"); } if(head->pltgot) { - *(uintptr_t*)(head->pltgot+head->delta+16) = pltResolver; + *(uintptr_t*)(head->pltgot+head->delta+16) = pltResolver64; *(uintptr_t*)(head->pltgot+head->delta+8) = (uintptr_t)head; printf_dump(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16)); } else if(head->got) { - *(uintptr_t*)(head->got+head->delta+16) = pltResolver; + *(uintptr_t*)(head->got+head->delta+16) = pltResolver64; *(uintptr_t*)(head->got+head->delta+8) = (uintptr_t)head; printf_dump(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16)); } @@ -873,6 +914,10 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind return 0; } +int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) +{ + return box64_is32bits?RelocateElfPlt32(maplib, local_maplib, bindnow, deepbind, head):RelocateElfPlt64(maplib, local_maplib, bindnow, deepbind, head); +} void CalcStack(elfheader_t* elf, uint64_t* stacksz, size_t* stackalign) { @@ -882,43 +927,6 @@ void CalcStack(elfheader_t* elf, uint64_t* stacksz, size_t* stackalign) *stackalign = elf->stackalign; } -Elf64_Sym* GetFunction(elfheader_t* h, const char* name) -{ - // TODO: create a hash on named to avoid this loop - for (size_t i=0; i<h->numSymTab; ++i) { - int type = ELF64_ST_TYPE(h->SymTab[i].st_info); - if(type==STT_FUNC) { - const char * symname = h->StrTab+h->SymTab[i].st_name; - if(strcmp(symname, name)==0) { - return h->SymTab+i; - } - } - } - return NULL; -} - -Elf64_Sym* GetElfObject(elfheader_t* h, const char* name) -{ - for (size_t i=0; i<h->numSymTab; ++i) { - int type = ELF64_ST_TYPE(h->SymTab[i].st_info); - if(type==STT_OBJECT) { - const char * symname = h->StrTab+h->SymTab[i].st_name; - if(strcmp(symname, name)==0) { - return h->SymTab+i; - } - } - } - return NULL; -} - - -uintptr_t GetFunctionAddress(elfheader_t* h, const char* name) -{ - Elf64_Sym* sym = GetFunction(h, name); - if(sym) return sym->st_value; - return 0; -} - uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h) { (void)maplib; @@ -945,13 +953,18 @@ 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 AddSymbols(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) DumpDynSym(h); - if(h==my_context->elfs[0]) - GrabX64CopyMainElfReloc(h); + if(box64_is32bits) { + AddSymbols32(maplib, h); + } else { + //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._64) DumpDynSym64(h); + if(h==my_context->elfs[0]) + GrabX64CopyMainElfReloc(h); + } #ifndef STATICBUILD checkHookedSymbols(h); #endif @@ -977,9 +990,10 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de return 0; DumpDynamicRPath(h); // update RPATH first - for (size_t i=0; i<h->numDynamic; ++i) - if(h->Dynamic[i].d_tag==DT_RPATH || h->Dynamic[i].d_tag==DT_RUNPATH) { - char *rpathref = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; + for (size_t i=0; i<h->numDynamic; ++i) { + int tag = box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag; + if(tag==DT_RPATH || tag==DT_RUNPATH) { + char *rpathref = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); char* rpath = rpathref; while(strstr(rpath, "$ORIGIN")) { char* origin = box_strdup(h->path); @@ -1032,23 +1046,24 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de if(rpath!=rpathref) box_free(rpath); } - + } DumpDynamicNeeded(h); int cnt = 0; // count the number of needed libs, and also grab soname for (size_t i=0; i<h->numDynamic; ++i) { - if(h->Dynamic[i].d_tag==DT_NEEDED) + int tag = box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag; + if(tag==DT_NEEDED) ++cnt; - if(h->Dynamic[i].d_tag==DT_SONAME) - h->soname = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; + if(tag==DT_SONAME) + h->soname = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); } h->needed = new_neededlib(cnt); if(h == my_context->elfs[0]) my_context->neededlibs = h->needed; int j=0; for (size_t i=0; i<h->numDynamic; ++i) - if(h->Dynamic[i].d_tag==DT_NEEDED) - h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; + if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) + h->needed->names[j++] = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); if(h==my_context->elfs[0] && box64_addlibs.size) { for(int i=0; i<box64_addlibs.size; ++i) { printf_log(LOG_INFO, "BOX64, Adding %s to needed libs of %s\n", box64_addlibs.paths[i], h->name); @@ -1069,8 +1084,8 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h) if(!h) return 0; for (size_t i=0; i<h->numDynamic; ++i) - if(h->Dynamic[i].d_tag==DT_NEEDED) { - char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; + if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) { + char *needed = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); if(!strcmp(needed, "libtcmalloc_minimal.so.4")) // tcmalloc needs to be the 1st lib loaded return 1; else if(!strcmp(needed, "libtcmalloc_minimal.so.0")) // tcmalloc needs to be the 1st lib loaded @@ -1106,10 +1121,15 @@ 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; @@ -1171,10 +1191,15 @@ 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); @@ -1274,28 +1299,28 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin return ret; for (size_t i=0; i<h->numSymTab && distance!=0; ++i) { - const char * symname = h->StrTab+h->SymTab[i].st_name; - uintptr_t offs = h->SymTab[i].st_value + h->delta; + const char * symname = box64_is32bits?(h->StrTab+h->SymTab._32[i].st_name):(h->StrTab+h->SymTab._64[i].st_name); + uintptr_t offs = (box64_is32bits?h->SymTab._32[i].st_value:h->SymTab._64[i].st_value) + h->delta; if(offs<=addr) { if(distance>addr-offs) { distance = addr-offs; ret = symname; s = offs; - size = h->SymTab[i].st_size; + size = box64_is32bits?h->SymTab._32[i].st_size:h->SymTab._64[i].st_size; } } } for (size_t i=0; i<h->numDynSym && distance!=0; ++i) { - const char * symname = h->DynStr+h->DynSym[i].st_name; - uintptr_t offs = h->DynSym[i].st_value + h->delta; + const char * symname = h->DynStr+(box64_is32bits?h->DynSym._32[i].st_name:h->DynSym._64[i].st_name); + uintptr_t offs = (box64_is32bits?h->DynSym._32[i].st_value:h->DynSym._64[i].st_value) + h->delta; if(offs<=addr) { if(distance>addr-offs) { distance = addr-offs; ret = symname; s = offs; - size = h->DynSym[i].st_size; + size = box64_is32bits?h->DynSym._32[i].st_size:h->DynSym._64[i].st_size; } } } @@ -1376,7 +1401,7 @@ void* GetDynamicSection(elfheader_t* h) { if(!h) return NULL; - return h->Dynamic; + return box64_is32bits?((void*)h->Dynamic._32):((void*)h->Dynamic._64); } #ifdef DYNAREC @@ -1452,6 +1477,7 @@ static void* find_dl_iterate_phdr_Fct(void* fct) #undef SUPER EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) { + if(box64_is32bits) {printf_log(LOG_NONE, "Error, calling unsuppoeted dl_iterate_phdr in 32bits\n"); return 0; } printf_log(LOG_DEBUG, "Call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data); box64context_t *context = GetEmuContext(emu); const char* empty = ""; @@ -1461,7 +1487,7 @@ EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) { my_dl_phdr_info_t info; info.dlpi_addr = GetElfDelta(context->elfs[idx]); info.dlpi_name = idx?context->elfs[idx]->name:empty; //1st elf is program, and this one doesn't get a name - info.dlpi_phdr = context->elfs[idx]->PHEntries; + info.dlpi_phdr = context->elfs[idx]->PHEntries._64; info.dlpi_phnum = context->elfs[idx]->numPHEntries; if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) { return ret; @@ -1473,12 +1499,17 @@ EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) { return ret; } +void ResetSpecialCaseMainElf32(elfheader_t* h) { /* TODO */ } void ResetSpecialCaseMainElf(elfheader_t* h) { + if(box64_is32bits) { + ResetSpecialCaseMainElf32(h); + return; + } Elf64_Sym *sym = NULL; for (size_t i=0; i<h->numDynSym; ++i) { - if(h->DynSym[i].st_info == 17) { - sym = h->DynSym+i; + if(h->DynSym._64[i].st_info == 17) { + sym = h->DynSym._64+i; const char * symname = h->DynStr+sym->st_name; if(strcmp(symname, "_IO_2_1_stderr_")==0 && ((void*)sym->st_value+h->delta)) { memcpy((void*)sym->st_value+h->delta, stderr, sym->st_size); @@ -1564,12 +1595,12 @@ void ElfAttachLib(elfheader_t* head, library_t* lib) head->lib = lib; } -Elf64_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +static Elf64_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { - Elf64_Sym* sym = ElfLookup(head, symname, *ver, *vername, local, *veropt); + Elf64_Sym* sym = ElfLookup64(head, symname, *ver, *vername, local, *veropt); if(!sym) return NULL; if(head->VerSym && !*veropt) { - int idx = ((uintptr_t)sym - (uintptr_t)head->DynSym)/sizeof(Elf64_Sym); + int idx = ((uintptr_t)sym - (uintptr_t)head->DynSym._64)/sizeof(Elf64_Sym); int version = ((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[idx]; if(version!=-1) version &=0x7fff; const char* symvername = GetSymbolVersion(head, version); @@ -1589,7 +1620,8 @@ Elf64_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t *end, c return sym; } -void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +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* 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); if(!sym) return NULL; @@ -1599,7 +1631,13 @@ void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *e if(end) *end = sym->st_value + head->delta + sym->st_size; return sym; } -void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +{ + 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* 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); if(!sym) return NULL; @@ -1609,7 +1647,13 @@ void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t * if(end) *end = sym->st_value + head->delta + sym->st_size; return sym; } -void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +{ + 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* 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); if(!sym) return NULL; @@ -1619,9 +1663,15 @@ void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *en if(end) *end = sym->st_value + head->delta + sym->st_size; return sym; } -int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname) +void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) +{ + 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 ElfGetSymTabStartEnd64(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname) { - Elf64_Sym* sym = ElfSymTabLookup(head, symname); + Elf64_Sym* sym = ElfSymTabLookup64(head, symname); if(!sym) return 0; if(!sym->st_shndx) return 0; if(!sym->st_size) return 0; //needed? @@ -1629,6 +1679,10 @@ int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, con if(end) *end = sym->st_value + head->delta + sym->st_size; return 1; } +int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname) +{ + return box64_is32bits?ElfGetSymTabStartEnd32(head, offs, end, symname):ElfGetSymTabStartEnd64(head, offs, end, symname); +} typedef struct search_symbol_s{ const char* name; @@ -1701,8 +1755,8 @@ void* GetNativeSymbolUnversioned(void* lib, const char* name) return s.addr; } -uintptr_t pltResolver = ~0LL; -EXPORT void PltResolver(x64emu_t* emu) +uintptr_t pltResolver64 = ~0LL; +EXPORT void PltResolver64(x64emu_t* emu) { uintptr_t addr = Pop64(emu); int slot = (int)Pop64(emu); @@ -1710,13 +1764,13 @@ EXPORT void PltResolver(x64emu_t* emu) library_t* lib = h->lib; lib_t* local_maplib = GetMaplib(lib); int deepbind = GetDeepBind(lib); - printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p(%s): elf is %s (VerSym=%p, deepbind=%d, local_maplib=%p) func param: %p, %p...\n", (void*)addr, slot, *(void**)(R_RSP), getAddrFunctionName(*(uintptr_t*)R_RSP),h->name, h->VerSym, deepbind, local_maplib, (void*)R_RDI, (void*)R_RSI); + printf_dump(LOG_DEBUG, "PltResolver64: Addr=%p, Slot=%d Return=%p(%s): elf is %s (VerSym=%p, deepbind=%d, local_maplib=%p) func param: %p, %p...\n", (void*)addr, slot, *(void**)(R_RSP), getAddrFunctionName(*(uintptr_t*)R_RSP),h->name, h->VerSym, deepbind, local_maplib, (void*)R_RDI, (void*)R_RSI); Elf64_Rela * rel = (Elf64_Rela *)(h->jmprel + h->delta) + slot; - Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel->r_info)]; + Elf64_Sym *sym = &h->DynSym._64[ELF64_R_SYM(rel->r_info)]; int bind = ELF64_ST_BIND(sym->st_info); - const char* symname = SymName(h, sym); + const char* symname = SymName64(h, sym); int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel->r_info)]:-1; if(version!=-1) version &= 0x7fff; const char* vername = GetSymbolVersion(h, version); @@ -1728,7 +1782,7 @@ EXPORT void PltResolver(x64emu_t* emu) Elf64_Sym *elfsym = NULL; if(bind==STB_LOCAL) { - elfsym = ElfDynSymLookup(h, symname); + elfsym = ElfDynSymLookup64(h, symname); if(elfsym && elfsym->st_shndx) { offs = elfsym->st_value + h->delta; end = offs + elfsym->st_size; diff --git a/src/elfs/elfloader32.c b/src/elfs/elfloader32.c new file mode 100644 index 00000000..3b30bc07 --- /dev/null +++ b/src/elfs/elfloader32.c @@ -0,0 +1,626 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <sys/types.h> +#include <link.h> +#include <unistd.h> +#include <errno.h> +#ifndef _DLFCN_H +#include <dlfcn.h> +#endif + +#include "custommem.h" +#include "box64version.h" +#include "elfloader.h" +#include "debug.h" +#include "elfload_dump.h" +#include "elfloader_private.h" +#include "librarian.h" +#include "x64run.h" +#include "bridge.h" +#include "wrapper.h" +#include "box64context.h" +#include "library.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "box64stack.h" +#include "wine_tools.h" +#include "dictionnary.h" +#include "symbols.h" +#ifdef DYNAREC +#include "dynablock.h" +#endif +#include "../emu/x64emu_private.h" +#include "../emu/x64run_private.h" +#include "../tools/bridge_private.h" +#include "x64tls.h" +#include "box32.h" + +// 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) + if(ctx->elfs[i]==head) + return i; + return -1; +} + +static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib) +{ + if(h && lib) { + if(!h->needed) + h->needed = new_neededlib(1); + add1libref_neededlib(h->needed, lib); + } + return h; +} + +int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin) +{ + ptr_t offs = 0; + loadProtectionFromMap(); + int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG; + + head->multiblock_n = 0; // count PHEntrie with LOAD + uintptr_t max_align = (box64_pagesize-1); + for (size_t i=0; i<head->numPHEntries; ++i) + if(head->PHEntries._32[i].p_type == PT_LOAD && head->PHEntries._32[i].p_flags) { + ++head->multiblock_n; + } + + if(!head->vaddr && box64_load_addr) { + offs = to_ptrv(find31bitBlockNearHint((void*)box64_load_addr, head->memsz, max_align)); + box64_load_addr = offs + head->memsz; + box64_load_addr = (box64_load_addr+0x10ffffff)&~0xffffff; + } + if(!offs && !head->vaddr) + offs = (uintptr_t)find31bitBlockElf(head->memsz, mainbin, max_align); + // prereserve the whole elf image, without populating + size_t sz = head->memsz; + void* raw = NULL; + void* image = NULL; + if(!head->vaddr) { + sz += head->align; + raw = mmap64(from_ptrv(offs), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + image = (void*)(((uintptr_t)raw+max_align)&~max_align); + } else { + image = raw = mmap64(from_ptrv(head->vaddr), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + } + if(image!=MAP_FAILED && !head->vaddr && image!=from_ptrv(offs)) { + printf_log(LOG_INFO, "%s: Mmap64 for (@%p 0x%zx) for elf \"%s\" returned %p(%p/0x%zx) instead\n", (((uintptr_t)image)&max_align)?"Error":"Warning", from_ptrv(head->vaddr?head->vaddr:offs), head->memsz, head->name, image, raw, head->align); + offs = to_ptrv(image); + if(((uintptr_t)image)&max_align) { + munmap(raw, sz); + return 1; // that's an error, alocated memory is not aligned properly + } + } + if(image==MAP_FAILED || image!=from_ptrv(head->vaddr?head->vaddr:offs)) { + printf_log(LOG_NONE, "%s cannot create memory map (@%p 0x%zx) for elf \"%s\"", (image==MAP_FAILED)?"Error:":"Warning:", from_ptrv(head->vaddr?head->vaddr:offs), head->memsz, head->name); + if(image==MAP_FAILED) { + printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno)); + } else { + printf_log(LOG_NONE, " got %p\n", image); + } + if(image==MAP_FAILED) + return 1; + offs = to_ptrv(image)-head->vaddr; + } + printf_dump(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name); + head->delta = offs; + printf_dump(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", from_ptrv(offs), from_ptrv(head->vaddr), head->name); + + head->image = image; + head->raw = raw; + head->raw_size = sz; + setProtection_elf((uintptr_t)raw, sz, 0); + + head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t)); + head->tlsbase = AddTLSPartition(context, head->tlssize); + // and now, create all individual blocks + head->memory = (char*)0xffffffff; + int n = 0; + for (size_t i=0; i<head->numPHEntries; ++i) { + if(head->PHEntries._32[i].p_type == PT_LOAD && head->PHEntries._32[i].p_flags) { + Elf32_Phdr * e = &head->PHEntries._32[i]; + + head->multiblocks[n].flags = e->p_flags; + head->multiblocks[n].offs = e->p_offset; + head->multiblocks[n].paddr = e->p_paddr + offs; + head->multiblocks[n].size = e->p_filesz; + head->multiblocks[n].align = e->p_align; + uint8_t prot = PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0); + // check if alignment is correct + uintptr_t balign = head->multiblocks[n].align-1; + if(balign<4095) balign = 4095; + head->multiblocks[n].asize = (e->p_memsz+(e->p_paddr&balign)+4095)&~4095; + int try_mmap = 1; + if(e->p_paddr&balign) + try_mmap = 0; + if(e->p_offset&(box64_pagesize-1)) + try_mmap = 0; + if(ALIGN(e->p_memsz)!=ALIGN(e->p_filesz)) + try_mmap = 0; + if(!e->p_filesz) + try_mmap = 0; + if(e->p_align<box64_pagesize) + try_mmap = 0; + if(try_mmap) { + printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name); + void* p = mmap64( + (void*)head->multiblocks[n].paddr, + head->multiblocks[n].size, + prot, + MAP_PRIVATE|MAP_FIXED, //((prot&PROT_WRITE)?MAP_SHARED:MAP_PRIVATE)|MAP_FIXED, + head->fileno, + e->p_offset + ); + if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) { + try_mmap = 0; + printf_dump(log_level, "Mapping failed, using regular mmap+read"); + } else { + if(e->p_memsz>e->p_filesz && (prot&PROT_WRITE)) + memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz); + setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot); + head->multiblocks[n].p = p; + + } + } + if(!try_mmap) { + uintptr_t paddr = head->multiblocks[n].paddr&~balign; + size_t asize = head->multiblocks[n].asize; + void* p = MAP_FAILED; + if(paddr==(paddr&~(box64_pagesize-1)) && (asize==ALIGN(asize))) { + printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); + p = mmap64( + (void*)paddr, + asize, + prot|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, + -1, + 0 + ); + } else { + // difference in pagesize, so need to mmap only what needed to be... + //check startint point + uintptr_t new_addr = paddr; + ssize_t new_size = asize; + while(getProtection(new_addr) && (new_size>0)) { + new_size -= ALIGN(new_addr) - new_addr; + new_addr = ALIGN(new_addr); + } + if(new_size>0) { + printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", ALIGN(new_size), e->p_memsz, (void*)new_addr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); + p = mmap64( + (void*)new_addr, + ALIGN(new_size), + prot|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, + -1, + 0 + ); + if(p==(void*)new_addr) + p = (void*)paddr; + } else { + p = (void*)paddr; + printf_dump(log_level, "Will read 0x%zx @%p for Elf \"%s\"\n", e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); + } + } + if(p==MAP_FAILED || p!=(void*)paddr) { + printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, asize, balign, head->name); + if(p==MAP_FAILED) { + printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno)); + } else { + printf_log(LOG_NONE, " got %p\n", p); + } + return 1; + } + setProtection_elf((uintptr_t)p, asize, prot); + head->multiblocks[n].p = p; + if(e->p_filesz) { + fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET); + if(fread((void*)head->multiblocks[n].paddr, head->multiblocks[n].size, 1, head->file)!=1) { + printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name); + return 1; + } + } + if(!(prot&PROT_WRITE) && (paddr==(paddr&(box64_pagesize-1)) && (asize==ALIGN(asize)))) + mprotect((void*)paddr, asize, prot); + } +#ifdef DYNAREC + if(box64_dynarec && (e->p_flags & PF_X)) { + dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", head->multiblocks[n].p, (void*)head->multiblocks[n].asize); + addDBFromAddressRange((uintptr_t)head->multiblocks[n].p, head->multiblocks[n].asize); + } +#endif + if((uintptr_t)head->memory>(uintptr_t)head->multiblocks[n].p) + head->memory = (char*)head->multiblocks[n].p; + ++n; + } + if(head->PHEntries._32[i].p_type == PT_TLS) { + Elf32_Phdr * e = &head->PHEntries._32[i]; + char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); + printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); + if(e->p_filesz) { + fseeko64(head->file, e->p_offset, SEEK_SET); + if(fread(dest, e->p_filesz, 1, head->file)!=1) { + printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz); + return 1; + } + } + // zero'd difference between filesz and memsz + if(e->p_filesz != e->p_memsz) + memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz); + } + } + + // can close the elf file now! + fclose(head->file); + head->file = NULL; + head->fileno = -1; + + return 0; +} + +static int IsSymInElfSpace(const elfheader_t* h, Elf32_Sym* sym) +{ + if(!h || !sym) + return 0; + uintptr_t addr = (uintptr_t)sym; + if(h->SymTab._32 && addr>=(uintptr_t)h->SymTab._32 && addr<(uintptr_t)&h->SymTab._32[h->numSymTab]) + return 1; + if(h->DynSym._32 && addr>=(uintptr_t)h->DynSym._32 && addr<(uintptr_t)&h->DynSym._32[h->numDynSym]) + return 1; + return 0; +} +static elfheader_t* FindElfSymbol(box64context_t *context, Elf32_Sym* sym) +{ + if(!sym) + return NULL; + for (int i=0; i<context->elfsize; ++i) + if(IsSymInElfSpace(context->elfs[i], sym)) + return context->elfs[i]; + + return NULL; +} + +void GrabR386CopyMainElfReloc(elfheader_t* head) +{ + if(head->rela) { + int cnt = head->relasz / head->relaent; + Elf32_Rel* rel = (Elf32_Rel *)(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(rel[i].r_info); + if(t == R_386_COPY) { + Elf32_Sym *sym = &head->DynSym._32[ELF32_R_SYM(rel[i].r_info)]; + const char* symname = SymName32(head, sym); + int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[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); + } + } + } +} + + +static int FindR386COPYRel(elfheader_t* h, const char* name, ptr_t *offs, uint32_t** p, size_t size, int version, const char* vername, int veropt) +{ + if(!h) + return 0; + if(!h->rel) + return 0; + if(h->relent) { + Elf32_Rel * rel = (Elf32_Rel *)(h->rel + h->delta); + int cnt = h->relsz / h->relent; + for (int i=0; i<cnt; ++i) { + int t = ELF32_R_TYPE(rel[i].r_info); + Elf32_Sym *sym = &h->DynSym._32[ELF32_R_SYM(rel[i].r_info)]; + const char* symname = SymName32(h, sym); + if((t==R_386_COPY) && symname && !strcmp(symname, name) && (sym->st_size==size)) { + int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel[i].r_info)]:-1; + if(version2!=-1) version2 &= 0x7fff; + if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol + const char* vername2 = GetSymbolVersion(h, version2); + Elf32_Half flags = GetSymbolVersionFlag(h, version2); + int veropt2 = flags?0:1; + if(SameVersionedSymbol(name, version, vername, veropt, symname, version2, vername2, veropt2)) { + if(offs) *offs = sym->st_value + h->delta; + if(p) *p = (uint32_t*)(rel[i].r_offset + h->delta); + return 1; + } + } + } + } + return 0; +} + +static int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf32_Rel *rel, int* need_resolv) +{ + int ret_ok = 0; + for (int i=0; i<cnt; ++i) { + int t = ELF32_R_TYPE(rel[i].r_info); + Elf32_Sym *sym = &head->DynSym._32[ELF32_R_SYM(rel[i].r_info)]; + int bind = ELF32_ST_BIND(sym->st_info); + //uint32_t ndx = sym->st_shndx; + const char* symname = SymName32(head, sym); + uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta); + uintptr_t offs = 0; + uintptr_t end = 0; + size_t size = sym->st_size; + elfheader_t* sym_elf = NULL; + elfheader_t* last_elf = NULL; + int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[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; + Elf32_Sym* elfsym = NULL; + int vis = ELF64_ST_VISIBILITY(sym->st_other); + if(vis==STV_PROTECTED) { + elfsym = ElfDynSymLookup32(head, symname); + printf_log(LOG_DEBUG, "Symbol %s from %s is PROTECTED\n", symname, head->name); + } else { + if(bind==STB_GNU_UNIQUE) { + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + if(!offs && !end && local_maplib) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + } else if(bind==STB_LOCAL) { + if(!symname || !symname[0]) { + offs = sym->st_value + head->delta; + end = offs + sym->st_size; + } else { + elfsym = ElfDynSymLookup32(head, symname); + if(elfsym && elfsym->st_shndx) { + offs = elfsym->st_value + head->delta; + end = offs + elfsym->st_size; + } + if(!offs && !end && local_maplib && deepbind) + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + if(!offs && !end) + GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + if(!offs && !end && local_maplib && !deepbind) + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + } + } else { + if(!offs && !end && local_maplib && deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + if(!offs && !end) + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + if(!offs && !end && local_maplib && !deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); + } + } + sym_elf = FindElfSymbol(my_context, elfsym); + if(elfsym && (ELF32_ST_TYPE(elfsym->st_info)==STT_TLS)) + offs = elfsym->st_value; + uintptr_t globoffs, globend; + uint32_t* globp; + uintptr_t tmp = 0; + intptr_t delta; + switch(t) { + case R_386_NONE: + // can be ignored + printf_dump(LOG_NEVER, "Ignoring [%d] %s %p (%p)\n", i, DumpRelType32(t), p, from_ptrv(p?(*p):0)); + break; + case R_386_PC32: + if (!offs) { + printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_PC32 %p (%p) in %s\n", symname, p, from_ptrv(*p), head->name); + ret_ok = 1; + } + if(offs) + printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (ver=%d/%s), (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", from_ptrv(*(ptr_t*)p), from_ptrv(*(ptr_t*)p+(offs-to_ptrv(p))), from_ptrv(offs)); + offs = (offs - to_ptrv(p)); + *p += offs; + break; + case R_386_RELATIVE: + printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, from_ptrv(*p), (void*)((*p)+head->delta)); + *p += head->delta; + break; + case R_386_COPY: + globoffs = offs; + globend = end; + offs = end = 0; + if(!offs && local_maplib && deepbind) + GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, veropt, NULL); + if(!offs) + GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, veropt, NULL); + if(!offs && local_maplib && !deepbind) + GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, veropt, NULL); + if(!offs) {offs = globoffs; end = globend;} + if(offs) { + // add r_addend to p? + printf_dump(LOG_NEVER, "Apply R_386_COPY @%p with sym=%s (%sver=%d/%s), @%p size=%ld\n", p, symname, veropt?"opt":"", version, vername?vername:"(none)", from_ptrv(offs), sym->st_size); + if(p!=from_ptrv(offs)) + memmove(p, from_ptrv(offs), sym->st_size); + sym_elf = FindElfAddress(my_context, offs); + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); + } else { + printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply REL R_386_COPY @%p (%p) in %s\n", symname, p, from_ptrv(*p), head->name); + } + break; + case R_386_GLOB_DAT: + if(GetSymbolStartEnd(my_context->globdata, symname, &globoffs, &globend, version, vername, 1, veropt)) { + globp = (uint32_t*)globoffs; + printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (%sver=%d/%s) \n", + BindSym(bind), p, globp, from_ptrv(p?(*p):0), + from_ptrv(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, veropt?"opt":"", version, vername?vername:"(none)"); + sym_elf = my_context->elfs[0]; + *p = globoffs; + } else { + if (!offs) { + if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load")) + printf_log((bind==STB_WEAK)?LOG_DEBUG:LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name); + } else { + printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (%sver=%d/%s, elf=%s)\n", BindSym(bind), p, from_ptrv(p?(*p):0), from_ptrv(offs), symname, veropt?"opt":"", version, vername?vername:"(none)", sym_elf?sym_elf->name:"(native)"); + *p = offs; + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); + } + } + break; + case R_386_JMP_SLOT: + // apply immediatly for gobject closure marshal or for LOCAL binding. Also, apply immediatly if it doesn't jump in the got + tmp = (uintptr_t)(*p); + if (bind==STB_LOCAL + || ((symname && strstr(symname, "g_cclosure_marshal_")==symname)) + || ((symname && strstr(symname, "__pthread_unwind_next")==symname)) + || !tmp + || !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end)) + || !need_resolv + || bindnow + ) { + if (!offs) { + if(bind==STB_WEAK) { + printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT %p (%p)\n", symname, p, from_ptrv(*p)); + } else { + printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, p, from_ptrv(*p), head->name); + ret_ok = 1; + } + } else { + if(p) { + printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, symname, vername?"@":"", vername?vername:"", from_ptrv(*p), from_ptrv(offs)); + *p = offs; + } else { + printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname); + } + } + } else { + printf_dump(LOG_NEVER, "Preparing (if needed) %s R_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version); + *p += head->delta; + *need_resolv = 1; + } + break; + case R_386_32: + if (!offs) { + if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) { + printf_log(LOG_NONE, "Error: Symbol sym=%s(%s%s%s/version %d) not found, cannot apply R_386_32 %p (%p) in %s\n", symname, symname, vername?"@":"", vername?vername:"", version, p, from_ptrv(*p), head->name); + ret_ok = 1; + } + } else { + printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", from_ptrv(*p), from_ptrv(offs+*p)); + *p += offs; + } + break; + case R_386_TLS_TPOFF: + // Negated offset in static TLS block + { + if(!symname || !symname[0]) { + sym_elf = head; + offs = sym->st_value; + } + if(sym_elf) { + delta = *(int32_t*)p; + printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, delta, sym_elf->tlsbase, (int32_t)offs, end-offs); + *p = (uintptr_t)((int32_t)offs + sym_elf->tlsbase); + } else { + printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, (int32_t)offs); + } + } + break; + case R_386_TLS_TPOFF32: + // Non-negated offset in static TLS block??? + { + if(!symname || !symname[0]) { + sym_elf = head; + offs = sym->st_value; + } + if(sym_elf) { + delta = *(int32_t*)p; + printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, delta, -sym_elf->tlsbase, (int32_t)offs, end-offs); + *p = (uintptr_t)((int32_t)offs - sym_elf->tlsbase); + } else { + printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, (int32_t)offs); + } + } + break; + case R_386_TLS_DTPMOD32: + // ID of module containing symbol + if(!symname || symname[0]=='\0' || bind==STB_LOCAL) { + offs = getElfIndex(my_context, head); + sym_elf = head; + } else { + offs = getElfIndex(my_context, sym_elf); + } + if(p) { + printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, from_ptrv(*p), from_ptrv(offs)); + *p = offs; + } else { + printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname); + } + break; + case R_386_TLS_DTPOFF32: + // Offset in TLS block + if (!offs && !end) { + if(bind==STB_WEAK) { + printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p)\n", symname, p, from_ptrv(*p)); + } else { + printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, from_ptrv(*p), head->name); + } + } else { + if(!symname || !symname[0]) { + offs = (uintptr_t)((intptr_t)(head->tlsaddr + head->delta) - (intptr_t)offs); // negative offset + } + if(p) { + printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (ver=%d/%s) (%zd -> %zd)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", (intptr_t)*p, (intptr_t)offs); + *p = offs; + } else { + printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname); + } + } + break; + default: + printf_log(LOG_INFO, "Warning, don't know of to handle rel #%d %s (%p) for %s\n", i, DumpRelType32(ELF32_R_TYPE(rel[i].r_info)), p, symname?symname:"(nil)"); + } + } + return bindnow?ret_ok:0; +} + +static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf32_Rela *rela, int* need_resolv) +{ + printf_log(LOG_NONE, "Error: RELA type of Relocation unsupported (only REL)\n"); + return 1; +} + +static int RelocateElfRELR(elfheader_t *head, int cnt, Elf32_Relr *relr) +{ + printf_log(LOG_NONE, "Error: RELR type of Relocation unsupported (only REL)\n"); + return 1; +} + +int RelocateElf32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) +{ + 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->relr) { + int cnt = head->relrsz / head->relrent; + DumpRelRTable32(head, cnt, (Elf32_Relr *)(head->relr + head->delta), "RelR"); + printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name); + if(RelocateElfRELR(head, cnt, (Elf32_Relr *)(head->relr + head->delta))) + return -1; + } + if(head->rel) { + int cnt = head->relsz / head->relent; + DumpRelTable32(head, cnt, (Elf32_Rel *)(head->rel + head->delta), "Rel"); + printf_log(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name); + if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf32_Rel *)(head->rel + head->delta), NULL)) + return -1; + } + if(head->rela) { + int cnt = head->relasz / head->relaent; + DumpRelATable32(head, cnt, (Elf32_Rela *)(head->rela + head->delta), "RelA"); + printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name); + if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf32_Rela *)(head->rela + head->delta), NULL)) + return -1; + } + return 0; +} diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index d813488c..6bcf6d82 100644 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -7,6 +7,7 @@ typedef struct cleanup_s cleanup_t; #include <elf.h> #include "elfloader.h" +#include "box32.h" typedef struct multiblock_s { void* p; @@ -22,27 +23,48 @@ typedef struct elfheader_s { char* name; char* path; // Resolved path to file char* soname; // soname of the elf - size_t numPHEntries; - Elf64_Phdr *PHEntries; - size_t numSHEntries; - Elf64_Shdr *SHEntries; + uint16_t numPHEntries; + union { + Elf64_Phdr* _64; + Elf32_Phdr* _32; + } PHEntries; + uint16_t numSHEntries; + union { + Elf64_Shdr* _64; + Elf32_Shdr* _32; + } SHEntries; size_t SHIdx; size_t numSST; char* SHStrTab; char* StrTab; - Elf64_Sym* SymTab; + union { + Elf64_Sym* _64; + Elf32_Sym* _32; + } SymTab; size_t numSymTab; char* DynStr; - Elf64_Sym* DynSym; + union { + Elf64_Sym* _64; + Elf32_Sym* _32; + } DynSym; size_t numDynSym; - Elf64_Dyn* Dynamic; + union { + Elf64_Dyn* _64; + Elf32_Dyn* _32; + } Dynamic; size_t numDynamic; char* DynStrTab; size_t szDynStrTab; - Elf64_Half* VerSym; - Elf64_Verneed* VerNeed; + uint16_t* VerSym; + union { + Elf64_Verneed* _64; + Elf32_Verneed* _32; + } VerNeed; int szVerNeed; - Elf64_Verdef* VerDef; + union { + Elf64_Verdef* _64; + Elf32_Verdef* _32; + } VerDef; int szVerDef; int e_type; uint32_t flags; @@ -176,21 +198,22 @@ typedef struct elfheader_s { #define ELF64_ST_VISIBILITY(o) ((o) & 0x03) #endif -elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec); +elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec); +elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec); const char* BindSym(int bind); -Elf64_Half GetSymbolVersionFlag(elfheader_t* h, int index); +uint16_t GetSymbolVersionFlag(elfheader_t* h, int index); uint32_t old_elf_hash(const char* name); -Elf64_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt); -void old_elf_hash_dump(elfheader_t* h); uint32_t new_elf_hash(const char *name); -Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt); -void new_elf_hash_dump(elfheader_t* h); -Elf64_Sym* ElfLookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt); -Elf64_Sym* ElfSymTabLookup(elfheader_t* h, const char* symname); -Elf64_Sym* ElfDynSymLookup(elfheader_t* h, const char* symname); +Elf32_Sym* ElfLookup32(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt); +Elf32_Sym* ElfSymTabLookup32(elfheader_t* h, const char* symname); +Elf32_Sym* ElfDynSymLookup32(elfheader_t* h, const char* symname); + +Elf64_Sym* ElfLookup64(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt); +Elf64_Sym* ElfSymTabLookup64(elfheader_t* h, const char* symname); +Elf64_Sym* ElfDynSymLookup64(elfheader_t* h, const char* symname); #endif //__ELFLOADER_PRIVATE_H_ diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index 49fea7aa..c9919123 100644 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -17,7 +17,7 @@ #define DT_GNU_HASH 0x6ffffef5 #endif -int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t type) +static int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t type) { if(type && (s->sh_type != type)) { printf_log(LOG_INFO, "Section Header \"%s\" (off=%ld, size=%ld) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type); @@ -36,7 +36,7 @@ int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t type) return 0; } -int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name) +static int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name) { for (int i=0; i<n; ++i) { if(s[i].sh_type!=SHT_NULL) @@ -46,7 +46,7 @@ int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name) return 0; } -void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num) +static void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num) { int n = FindSection(s, size, SHStrTab, name); printf_dump(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n); @@ -61,7 +61,10 @@ void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const ch } } -elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) +#ifndef BOX32 +elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) { return NULL; } +#endif +elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) { Elf64_Ehdr header; int level = (exec)?LOG_INFO:LOG_DEBUG; @@ -145,9 +148,9 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) if(header.e_shentsize && h->numSHEntries) { // now read all section headers printf_dump(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries); - h->SHEntries = (Elf64_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf64_Shdr)); + h->SHEntries._64 = (Elf64_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf64_Shdr)); fseeko64(f, header.e_shoff ,SEEK_SET); - if(fread(h->SHEntries, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) { + if(fread(h->SHEntries._64, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Section Header\n"); return NULL; @@ -156,14 +159,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) if(h->numPHEntries == PN_XNUM) { printf_dump(LOG_DEBUG, "Read number of Program Header in 1st Section\n"); // read 1st section header and grab actual number from here - h->numPHEntries = h->SHEntries[0].sh_info; + h->numPHEntries = h->SHEntries._64[0].sh_info; } } printf_dump(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries); - h->PHEntries = (Elf64_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf64_Phdr)); + h->PHEntries._64 = (Elf64_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf64_Phdr)); fseeko64(f, header.e_phoff ,SEEK_SET); - if(fread(h->PHEntries, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) { + if(fread(h->PHEntries._64, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Program Header\n"); return NULL; @@ -172,7 +175,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) if(header.e_shentsize && header.e_shnum) { if(h->SHIdx == SHN_XINDEX) { printf_dump(LOG_DEBUG, "Read number of String Table in 1st Section\n"); - h->SHIdx = h->SHEntries[0].sh_link; + h->SHIdx = h->SHEntries._64[0].sh_link; } if(h->SHIdx > h->numSHEntries) { printf_log(LOG_INFO, "Incoherent Section String Table Index : %zu / %zu\n", h->SHIdx, h->numSHEntries); @@ -181,23 +184,23 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) } // load Section table printf_dump(LOG_DEBUG, "Loading Sections Table String (idx = %zu)\n", h->SHIdx); - if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) { + if(LoadSH(f, h->SHEntries._64+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) { FreeElfHeader(&h); return NULL; } - if(box64_dump) DumpMainHeader(&header, h); + if(box64_dump) DumpMainHeader64(&header, h); - LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL); - LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab); - if(box64_dump && h->SymTab) DumpSymTab(h); + LoadNamedSection(f, h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL); + LoadNamedSection(f, h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab._64, &h->numSymTab); + if(box64_dump && h->SymTab._64) DumpSymTab64(h); - LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic); - if(box64_dump && h->Dynamic) DumpDynamicSections(h); + LoadNamedSection(f, h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic._64, &h->numDynamic); + if(box64_dump && h->Dynamic._64) DumpDynamicSections64(h); // grab DT_REL & DT_RELA stuffs // also grab the DT_STRTAB string table { for (size_t i=0; i<h->numDynamic; ++i) { - Elf64_Dyn d = h->Dynamic[i]; + Elf64_Dyn d = h->Dynamic._64[i]; Elf64_Word val = d.d_un.d_val; Elf64_Addr ptr = d.d_un.d_ptr; switch (d.d_tag) { @@ -281,7 +284,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) printf_dump(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed); break; case DT_VERNEED: - h->VerNeed = (Elf64_Verneed*)ptr; + h->VerNeed._64 = (Elf64_Verneed*)ptr; printf_dump(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed); break; case DT_VERDEFNUM: @@ -289,7 +292,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) printf_dump(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef); break; case DT_VERDEF: - h->VerDef = (Elf64_Verdef*)ptr; + h->VerDef._64 = (Elf64_Verdef*)ptr; printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef); break; case DT_FLAGS: @@ -340,55 +343,55 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) printf_dump(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%zx/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent); } if(h->DynStrTab && h->szDynStrTab) { - //DumpDynamicNeeded(h); cannot dump now, it's not loaded yet + //DumpDynamicNeeded64(h); cannot dump now, it's not loaded yet } } // look for PLT Offset - int ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got.plt"); + int ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".got.plt"); if(ii) { - h->gotplt = h->SHEntries[ii].sh_addr; - h->gotplt_end = h->gotplt + h->SHEntries[ii].sh_size; + h->gotplt = h->SHEntries._64[ii].sh_addr; + h->gotplt_end = h->gotplt + h->SHEntries._64[ii].sh_size; printf_dump(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt); } - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got"); + ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".got"); if(ii) { - h->got = h->SHEntries[ii].sh_addr; - h->got_end = h->got + h->SHEntries[ii].sh_size; + h->got = h->SHEntries._64[ii].sh_addr; + h->got_end = h->got + h->SHEntries._64[ii].sh_size; printf_dump(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end); } - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".plt"); + ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".plt"); if(ii) { - h->plt = h->SHEntries[ii].sh_addr; - h->plt_end = h->plt + h->SHEntries[ii].sh_size; + h->plt = h->SHEntries._64[ii].sh_addr; + h->plt_end = h->plt + h->SHEntries._64[ii].sh_size; printf_dump(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end); } // grab version of symbols - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version"); + ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".gnu.version"); if(ii) { - h->VerSym = (Elf64_Half*)(h->SHEntries[ii].sh_addr); + h->VerSym = (Elf64_Half*)(h->SHEntries._64[ii].sh_addr); printf_dump(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym); } // grab .text for main code - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text"); + ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".text"); if(ii) { - h->text = (uintptr_t)(h->SHEntries[ii].sh_addr); - h->textsz = h->SHEntries[ii].sh_size; + h->text = (uintptr_t)(h->SHEntries._64[ii].sh_addr); + h->textsz = h->SHEntries._64[ii].sh_size; printf_dump(LOG_DEBUG, "The .text is at address %p, and is %zu big\n", (void*)h->text, h->textsz); } - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame"); + ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".eh_frame"); if(ii) { - h->ehframe = (uintptr_t)(h->SHEntries[ii].sh_addr); - h->ehframe_end = h->ehframe + h->SHEntries[ii].sh_size; + h->ehframe = (uintptr_t)(h->SHEntries._64[ii].sh_addr); + h->ehframe_end = h->ehframe + h->SHEntries._64[ii].sh_size; printf_dump(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end); } - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr"); + ii = FindSection(h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr"); if(ii) { - h->ehframehdr = (uintptr_t)(h->SHEntries[ii].sh_addr); + h->ehframehdr = (uintptr_t)(h->SHEntries._64[ii].sh_addr); printf_dump(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr); } - LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL); - LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym); + LoadNamedSection(f, h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL); + LoadNamedSection(f, h->SHEntries._64, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym); } return h; diff --git a/src/elfs/elfparser32.c b/src/elfs/elfparser32.c new file mode 100755 index 00000000..b4bb78e4 --- /dev/null +++ b/src/elfs/elfparser32.c @@ -0,0 +1,466 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> + +#include "box64version.h" +#include "elfloader.h" +#include "debug.h" +#include "elfload_dump.h" +#include "elfloader_private.h" +#include "box32.h" + +#ifndef PN_XNUM +#define PN_XNUM (0xffff) +#endif + +static int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t type) +{ + if(type && (s->sh_type != type)) { + printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type); + return -1; + } + if (type==SHT_SYMTAB && s->sh_size%sizeof(Elf32_Sym)) { + printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %ld)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym)); + } + *SH = box_calloc(1, s->sh_size); + fseeko64(f, s->sh_offset ,SEEK_SET); + if(fread(*SH, s->sh_size, 1, f)!=1) { + printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size); + return -1; + } + + return 0; +} + +static int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name) +{ + for (int i=0; i<n; ++i) { + if(s[i].sh_type!=SHT_NULL) + if(!strcmp(SHStrTab+s[i].sh_name, name)) + return i; + } + return 0; +} + +static void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num) +{ + int n = FindSection(s, size, SHStrTab, name); + printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n); + if(n) + LoadSH(f, s+n, what, name, type); + if(type==SHT_SYMTAB || type==SHT_DYNSYM) { + if(*what && num) + *num = s[n].sh_size / sizeof(Elf32_Sym); + } else if(type==SHT_DYNAMIC) { + if(*what && num) + *num = s[n].sh_size / sizeof(Elf32_Dyn); + } +} + +elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) +{ + Elf32_Ehdr header; + int level = (exec)?LOG_INFO:LOG_DEBUG; + if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) { + printf_log(level, "Cannot read ELF Header\n"); + return NULL; + } + if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) { + printf_log(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]); + return NULL; + } + if(header.e_ident[EI_CLASS]!=ELFCLASS32) { + if(header.e_ident[EI_CLASS]==ELFCLASS64) { + printf_log(LOG_INFO, "This is a 64bits ELF! box32 can only run 32bits ELF!\n"); + } else { + printf_log(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]); + } + return NULL; + } + if(header.e_ident[EI_DATA]!=ELFDATA2LSB) { + printf_log(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]); + return NULL; + } + if(header.e_ident[EI_VERSION]!=EV_CURRENT) { + printf_log(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]); + return NULL; + } + if(header.e_ident[EI_OSABI]!=ELFOSABI_LINUX && header.e_ident[EI_OSABI]!=ELFOSABI_NONE && header.e_ident[EI_OSABI]!=ELFOSABI_SYSV) { + printf_log(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]); + return NULL; + } + + if(header.e_type != ET_EXEC && header.e_type != ET_DYN) { + printf_log(LOG_INFO, "Not an Executable (%d)\n", header.e_type); + return NULL; + } + + if(header.e_machine != EM_386) { + printf_log(level, "Not an i386 ELF (%d)\n", header.e_machine); + return NULL; + } + + if(header.e_entry == 0 && exec) { + printf_log(LOG_INFO, "No entry point in ELF\n"); + return NULL; + } + if(header.e_phentsize != sizeof(Elf32_Phdr)) { + printf_log(LOG_INFO, "Program Header Entry size incorrect (%d != %ld)\n", header.e_phentsize, sizeof(Elf32_Phdr)); + return NULL; + } + if(header.e_shentsize != sizeof(Elf32_Shdr) && header.e_shentsize != 0) { + printf_log(LOG_INFO, "Section Header Entry size incorrect (%d != %ld)\n", header.e_shentsize, sizeof(Elf32_Shdr)); + return NULL; + } + + elfheader_t *h = box_calloc(1, sizeof(elfheader_t)); + h->name = box_strdup(name); + h->entrypoint = header.e_entry; + h->numPHEntries = header.e_phnum; + h->numSHEntries = header.e_shnum; + h->SHIdx = header.e_shstrndx; + h->e_type = header.e_type; + if(header.e_shentsize && header.e_shnum) { + // special cases for nums + if(h->numSHEntries == 0) { + printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n"); + // read 1st section header and grab actual number from here + fseeko64(f, header.e_shoff, SEEK_SET); + Elf32_Shdr section; + if(fread(§ion, sizeof(Elf32_Shdr), 1, f)!=1) { + box_free(h); + printf_log(LOG_INFO, "Cannot read Initial Section Header\n"); + return NULL; + } + h->numSHEntries = section.sh_size; + } + // now read all section headers + printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries); + h->SHEntries._32 = (Elf32_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf32_Shdr)); + fseeko64(f, header.e_shoff ,SEEK_SET); + if(fread(h->SHEntries._32, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) { + FreeElfHeader(&h); + printf_log(LOG_INFO, "Cannot read all Section Header\n"); + return NULL; + } + + if(h->numPHEntries == PN_XNUM) { + printf_log(LOG_DEBUG, "Read number of Program Header in 1st Section\n"); + // read 1st section header and grab actual number from here + h->numPHEntries = h->SHEntries._32[0].sh_info; + } + } + + printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries); + h->PHEntries._32 = (Elf32_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf32_Phdr)); + fseeko64(f, header.e_phoff ,SEEK_SET); + if(fread(h->PHEntries._32, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) { + FreeElfHeader(&h); + printf_log(LOG_INFO, "Cannot read all Program Header\n"); + return NULL; + } + + if(header.e_shentsize && header.e_shnum) { + if(h->SHIdx == SHN_XINDEX) { + printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n"); + h->SHIdx = h->SHEntries._32[0].sh_link; + } + if(h->SHIdx > h->numSHEntries) { + printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries); + FreeElfHeader(&h); + return NULL; + } + // load Section table + printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx); + if(LoadSH(f, h->SHEntries._32+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) { + FreeElfHeader(&h); + return NULL; + } + if(box64_dump) DumpMainHeader32(&header, h); + + LoadNamedSection(f, h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL); + LoadNamedSection(f, h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab._32, &h->numSymTab); + if(box64_dump && h->SymTab._32) DumpSymTab32(h); + + LoadNamedSection(f, h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic._32, &h->numDynamic); + if(box64_dump && h->Dynamic._32) DumpDynamicSections32(h); + // grab DT_REL & DT_RELA stuffs + // also grab the DT_STRTAB string table + { + for (int i=0; i<h->numDynamic; ++i) { + Elf32_Dyn d = h->Dynamic._32[i]; + Elf32_Word val = d.d_un.d_val; + Elf32_Addr ptr = d.d_un.d_ptr; + switch (d.d_tag) { + case DT_REL: + h->rel = ptr; + break; + case DT_RELSZ: + h->relsz = val; + break; + case DT_RELENT: + h->relent = val; + break; + case DT_RELA: + h->rela = ptr; + break; + case DT_RELASZ: + h->relasz = val; + break; + case DT_RELAENT: + h->relaent = val; + break; + case DT_RELR: + h->relr = ptr; + break; + case DT_RELRSZ: + h->relrsz = val; + break; + case DT_RELRENT: + h->relrent = val; + break; + case DT_PLTGOT: + h->pltgot = ptr; + break; + case DT_PLTREL: + h->pltrel = val; + break; + case DT_PLTRELSZ: + h->pltsz = val; + break; + case DT_JMPREL: + h->jmprel = ptr; + break; + case DT_STRTAB: + h->DynStrTab = (char *)from_ptr(ptr); + break; + case DT_STRSZ: + h->szDynStrTab = val; + break; + case DT_INIT: // Entry point + h->initentry = ptr; + printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", from_ptrv(h->initentry)); + break; + case DT_INIT_ARRAY: + h->initarray = ptr; + printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", from_ptrv(h->initarray)); + break; + case DT_INIT_ARRAYSZ: + h->initarray_sz = val / sizeof(Elf32_Addr); + 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); + break; + case DT_FINI: // Exit hook + h->finientry = ptr; + printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", from_ptrv(h->finientry)); + break; + case DT_FINI_ARRAY: + h->finiarray = ptr; + printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", from_ptrv(h->finiarray)); + break; + case DT_FINI_ARRAYSZ: + h->finiarray_sz = val / sizeof(Elf32_Addr); + printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz); + break; + case DT_VERNEEDNUM: + h->szVerNeed = val; + printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed); + break; + case DT_VERNEED: + h->VerNeed._32 = (Elf32_Verneed*)from_ptr(ptr); + printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed); + break; + case DT_VERDEFNUM: + h->szVerDef = val; + printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef); + break; + case DT_VERDEF: + h->VerDef._32 = (Elf32_Verdef*)from_ptr(ptr); + printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef); + break; + case DT_HASH: + h->hash = ptr; + printf_dump(LOG_DEBUG, "The DT_HASH is at address %p\n", (void*)h->hash); + break; + case DT_GNU_HASH: + h->gnu_hash = ptr; + printf_dump(LOG_DEBUG, "The DT_GNU_HASH is at address %p\n", (void*)h->gnu_hash); + break; + } + } + if(h->rel) { + if(h->relent != sizeof(Elf32_Rel)) { + printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%lx)\n", h->relent, sizeof(Elf32_Rel)); + FreeElfHeader(&h); + return NULL; + } + printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", from_ptrv(h->rel), h->relsz, h->relent); + } + if(h->rela) { + if(h->relaent != sizeof(Elf32_Rela)) { + printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%lx)\n", h->relaent, sizeof(Elf32_Rela)); + FreeElfHeader(&h); + return NULL; + } + printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", from_ptrv(h->rela), h->relasz, h->relaent); + } + if(h->jmprel) { + if(h->pltrel == DT_REL) { + h->pltent = sizeof(Elf32_Rel); + } else if(h->pltrel == DT_RELA) { + h->pltent = sizeof(Elf32_Rela); + } else { + printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\n", h->pltsz, h->pltrel); + FreeElfHeader(&h); + return NULL; + } + if((h->pltsz / h->pltent)*h->pltent != h->pltsz) { + printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%d)\n", h->pltsz, h->pltent, h->pltrel); + FreeElfHeader(&h); + return NULL; + } + printf_log(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/0x%0x)\n", from_ptrv(h->jmprel), h->pltrel, h->pltsz, h->pltent); + } + if(h->DynStrTab && h->szDynStrTab) { + //DumpDynamicNeeded32(h); cannot dump now, it's not loaded yet + } + } + // look for PLT Offset + int ii = FindSection(h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".got.plt"); + if(ii) { + h->gotplt = h->SHEntries._32[ii].sh_addr; + h->gotplt_end = h->gotplt + h->SHEntries._32[ii].sh_size; + printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", from_ptrv(h->gotplt)); + } + ii = FindSection(h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".got"); + if(ii) { + h->got = h->SHEntries._32[ii].sh_addr; + h->got_end = h->got + h->SHEntries._32[ii].sh_size; + printf_log(LOG_DEBUG, "The GOT Table is at address %p..%p\n", from_ptrv(h->got), from_ptrv(h->got_end)); + } + ii = FindSection(h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".plt"); + if(ii) { + h->plt = h->SHEntries._32[ii].sh_addr; + h->plt_end = h->plt + h->SHEntries._32[ii].sh_size; + printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", from_ptrv(h->plt), from_ptrv(h->plt_end)); + } + // grab version of symbols + ii = FindSection(h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".gnu.version"); + if(ii) { + h->VerSym = (Elf32_Half*)from_ptrv(h->SHEntries._32[ii].sh_addr); + printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym); + } + // grab .text for main code + ii = FindSection(h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".text"); + if(ii) { + h->text = (uintptr_t)(h->SHEntries._32[ii].sh_addr); + h->textsz = h->SHEntries._32[ii].sh_size; + printf_log(LOG_DEBUG, "The .text is at address %p, and is %d big\n", from_ptrv(h->text), h->textsz); + } + + LoadNamedSection(f, h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL); + LoadNamedSection(f, h->SHEntries._32, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym); + } + + return h; +} + +const char* GetParentSymbolVersion32(elfheader_t* h, int index) +{ + if(!h->VerDef._32 || (index<1)) + return NULL; + Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef._32 + h->delta); + while(def) { + if(def->vd_ndx==index) { + if(def->vd_cnt<1) + return NULL; + /*if(def->vd_flags&VER_FLG_BASE) + return NULL;*/ + Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux); + return h->DynStr+aux->vda_name; // return Parent, so 1st aux + } + def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL; + } + return NULL; +} + +const char* GetSymbolVersion32(elfheader_t* h, int version) +{ + version&=0x7fff; // remove bit15 that switch between hidden/public + if(!h->VerNeed._32 || (version<2)) + return NULL; + /*if(version==1) + return "*";*/ + 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 h->DynStr+aux->vna_name; + aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + return GetParentSymbolVersion32(h, version); // if symbol is "internal", use Def table instead +} + +int GetVersionIndice32(elfheader_t* h, const char* vername) +{ + if(!vername) + return 0; + if(h->VerDef._32) { + Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef._32 + h->delta); + while(def) { + Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux); + if(!strcmp(h->DynStr+aux->vda_name, vername)) + return def->vd_ndx; + def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL; + } + } + return 0; +} + +int GetNeededVersionCnt32(elfheader_t* h, const char* libname) +{ + if(!libname) + return 0; + if(h->VerNeed._32) { + Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed._32 + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux); + if(!strcmp(filename, libname)) + return ver->vn_cnt; + ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return 0; +} + +const char* GetNeededVersionString32(elfheader_t* h, const char* libname, int idx) +{ + if(!libname) + return 0; + if(h->VerNeed._32) { + Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed._32 + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf32_Vernaux *aux = (Elf32_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 = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + return NULL; // idx out of bound, return NULL... + } + ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return NULL; +} diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c index 2b907c35..dd1b439c 100644 --- a/src/emu/x64int3.c +++ b/src/emu/x64int3.c @@ -127,14 +127,14 @@ void x64Int3(x64emu_t* emu, uintptr_t* addr) const char *s = bridge->name; if(!s) s = GetNativeName((void*)a); - if(a==(uintptr_t)PltResolver) { + if(a==(uintptr_t)PltResolver64) { if(cycle_log) { uintptr_t addr = *((uint64_t*)(R_RSP)); int slot = *((uint64_t*)(R_RSP+8)); elfheader_t *h = (elfheader_t*)addr; Elf64_Rela * rel = (Elf64_Rela *)(h->jmprel + h->delta) + slot; - Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel->r_info)]; - const char* symname = SymName(h, sym); + Elf64_Sym *sym = &h->DynSym._64[ELF64_R_SYM(rel->r_info)]; + const char* symname = SymName64(h, sym); snprintf(buff, 256, "%04d|PltResolver \"%s\"", tid, symname?symname:"???"); } else { snprintf(buff, 256, "%s", " ... "); diff --git a/src/include/box32.h b/src/include/box32.h new file mode 100644 index 00000000..ab8fa184 --- /dev/null +++ b/src/include/box32.h @@ -0,0 +1,112 @@ +#ifndef __BOX32_64__H_ +#define __BOX32_64__H_ + +#include <stdint.h> +#include <stdlib.h> + +#ifndef BOX32_DEF +#define BOX32_DEF +typedef uint32_t ptr_t; +typedef int32_t long_t; +typedef uint32_t ulong_t; +#endif + +#define TEST32 +#define TEST_ABORT + +static inline uintptr_t from_ptr(ptr_t p) { + return (uintptr_t)p; +} +static inline void* from_ptrv(ptr_t p) { + return (void*)(uintptr_t)p; +} +static inline long from_long(long_t l) { + return (long)l; +} +static inline unsigned long from_ulong(ulong_t l) { + return (unsigned long)l; +} +uintptr_t from_hash(ulong_t l); +uintptr_t from_hash_d(ulong_t l); +#ifdef TEST32 +#include "debug.h" + +static inline ptr_t to_ptr(uintptr_t p) { + if(p!=0xffffffffffffffffLL && (p>>32)) { + printf_log(LOG_NONE, "Warning, pointer %p is not a 32bits value\n", (void*)p); + #ifdef TEST_ABORT + abort(); + #endif + } + return (ptr_t)p; +} +static inline ptr_t to_ptrv(void* p2) { + uintptr_t p = (uintptr_t)p2; + if(p!=0xffffffffffffffffLL && (p>>32)) { + printf_log(LOG_NONE, "Warning, pointer %p is not a 32bits value\n", (void*)p); + #ifdef TEST_ABORT + abort(); + #endif + } + return (ptr_t)p; +} +static inline long_t to_long(long l) { + long_t ret = (long_t)l; + if(l!=ret) + printf_log(LOG_NONE, "Warning, long %ld is not a 32bits value\n", l); + return ret; +} +static inline ulong_t to_ulong(unsigned long l) { + if(l!=0xffffffffffffffffLL && (l>>32)) + printf_log(LOG_NONE, "Warning, long 0x%p is not a 32bits value\n", (void*)l); + return (ulong_t)l; +} +#else //TEST32 +static inline ptr_t to_ptr(uintptr_t p) { + return (ptr_t)p; +} +static inline ptr_t to_ptrv(void* p) { + return (ptr_t)(uintptr_t)p; +} +static inline long_t to_long(long l) { + return (long_t)l; +} +static inline ulong_t to_ulong(unsigned long l) { + return (ulong_t)l; +} +#endif //TEST32 + +static inline ptr_t to_ptr_silent(uintptr_t p) { + return (ptr_t)p; +} +static inline ptr_t to_ptrv_silent(void* p) { + return (ptr_t)(uintptr_t)p; +} +// indirect l -> T +#define from_ptri(T, l) *(T*)from_ptr(l) +// indirect l -> void* +static inline void* from_ptriv(ptr_t l) { + return from_ptrv(from_ptri(ptr_t, l)); +} + +ulong_t to_hash(uintptr_t p); +ulong_t to_hash_d(uintptr_t p); +static inline ulong_t to_hashv(void* p) {return to_hash((uintptr_t)p);} +static inline ulong_t to_hashv_d(uintptr_t p) {return to_hash_d((uintptr_t)p);} + +void* from_locale(ptr_t l); +void* from_locale_d(ptr_t l); +ptr_t to_locale(void* p); +ptr_t to_locale_d(void* p); + +void init_hash_helper(); +void fini_hash_helper(); + +typedef struct x86emu_s x86emu_t; + +void* my_mmap(x86emu_t* emu, void* addr, unsigned long length, int prot, int flags, int fd, int offset); +void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset); +int my_munmap(x86emu_t* emu, void* addr, unsigned long length); +int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot); + +#endif //__BOX32_64__H_ diff --git a/src/include/custommem.h b/src/include/custommem.h index dda21053..ba5441d1 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -102,6 +102,7 @@ void* find31bitBlockNearHint(void* hint, size_t size, uintptr_t mask); void* find47bitBlock(size_t size); void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask); // mask can be 0 for default one (0xffff) void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask); +void* find31bitBlockElf(size_t size, int mainbin, uintptr_t mask); int isBlockFree(void* hint, size_t size); // unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex @@ -125,4 +126,6 @@ int checkInHotPage(uintptr_t addr); void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset); int internal_munmap(void* addr, unsigned long length); +void reserveHighMem(); + #endif //__CUSTOM_MEM__H_ diff --git a/src/include/debug.h b/src/include/debug.h index 1e31b437..e0f81c95 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -16,6 +16,7 @@ extern int box64_ignoreint3; extern int box64_rdtsc; extern int box64_rdtsc_1ghz; extern uint8_t box64_rdtsc_shift; +extern int box64_is32bits; #ifdef DYNAREC extern int box64_dynarec_dump; extern int box64_dynarec_trace; diff --git a/src/include/elfload_dump.h b/src/include/elfload_dump.h index ad2ecd71..3fa0a910 100644 --- a/src/include/elfload_dump.h +++ b/src/include/elfload_dump.h @@ -3,22 +3,26 @@ typedef struct elfheader_s elfheader_t; -const char* DumpSection(Elf64_Shdr *s, char* SST); -const char* DumpDynamic(Elf64_Dyn *s); -const char* DumpPHEntry(Elf64_Phdr *e); -const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version); -const char* DumpRelType(int t); -const char* SymName(elfheader_t *h, Elf64_Sym* sym); -const char* IdxSymName(elfheader_t *h, int sym); -void DumpMainHeader(Elf64_Ehdr *header, elfheader_t *h); -void DumpSymTab(elfheader_t *h); -void DumpDynamicSections(elfheader_t *h); +const char* SymName32(elfheader_t *h, Elf32_Sym* sym); +const char* SymName64(elfheader_t *h, Elf64_Sym* sym); +const char* DumpRelType32(int t); +const char* DumpRelType64(int t); +void DumpMainHeader32(Elf32_Ehdr *header, elfheader_t *h); +void DumpMainHeader64(Elf64_Ehdr *header, elfheader_t *h); +void DumpSymTab32(elfheader_t *h); +void DumpSymTab64(elfheader_t *h); +void DumpDynamicSections32(elfheader_t *h); +void DumpDynamicSections64(elfheader_t *h); void DumpDynamicNeeded(elfheader_t *h); void DumpDynamicRPath(elfheader_t *h); -void DumpDynSym(elfheader_t *h); -void DumpRelTable(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name); -void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name); -void DumpRelRTable(elfheader_t *h, int cnt, Elf64_Relr *relr, const char *name); +void DumpDynSym32(elfheader_t *h); +void DumpDynSym64(elfheader_t *h); +void DumpRelTable32(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name); +void DumpRelTable64(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name); +void DumpRelATable32(elfheader_t *h, int cnt, Elf32_Rela *rela, const char* name); +void DumpRelATable64(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name); +void DumpRelRTable32(elfheader_t *h, int cnt, Elf32_Relr *relr, const char *name); +void DumpRelRTable64(elfheader_t *h, int cnt, Elf64_Relr *relr, const char *name); void DumpBinary(char* p, int sz); diff --git a/src/include/elfloader.h b/src/include/elfloader.h index 770709c8..edaf9771 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -45,7 +45,6 @@ int CalcLoadAddr(elfheader_t* head); int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin); void FreeElfMemory(elfheader_t* head); int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded); -void GrabX64CopyMainElfReloc(elfheader_t* head); int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, int deepbind, elfheader_t* head); int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, int deepbind, elfheader_t* head); void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign); @@ -91,7 +90,7 @@ int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver) void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *sz, const char* symname, int* ver, const char** vername, int local, int* veropt); void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *sz, const char* symname, int* ver, const char** vername, int local, int* veropt); void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *sz, const char* symname, int* ver, const char** vername, int local, int* veropt); -int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname); +int ElfGetSymTabStartEnd64(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname); void* GetNativeSymbolUnversioned(void* lib, const char* name); diff --git a/src/include/x64run.h b/src/include/x64run.h index b6c9e960..a5d4528e 100644 --- a/src/include/x64run.h +++ b/src/include/x64run.h @@ -9,8 +9,8 @@ int RunTest(x64test_t *test); void DynaRun(x64emu_t *emu); uint32_t LibSyscall(x64emu_t *emu); -void PltResolver(x64emu_t* emu); -extern uintptr_t pltResolver; +void PltResolver64(x64emu_t* emu); +extern uintptr_t pltResolver64; int GetTID(void); #endif //__X64RUN_H_ \ No newline at end of file diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index 56a0fffa..b836e4ca 100644 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -709,8 +709,12 @@ int GetSymTabStartEnd(lib_t* maplib, const char* name, uintptr_t* start, uintptr return 0; for(int i=0; i<maplib->libsz; ++i) { elfheader_t* h = GetElf(maplib->libraries[i]); - if(h && ElfGetSymTabStartEnd(h, start, end, name)) - return 1; + if(box64_is32bits) { + /* TODO */ + } else { + if(h && ElfGetSymTabStartEnd64(h, start, end, name)) + return 1; + } } return 0; } diff --git a/src/librarian/library.c b/src/librarian/library.c index 350a68a9..69f27d5f 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -232,6 +232,10 @@ int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr } static void initWrappedLib(library_t *lib, box64context_t* context) { + if(box64_is32bits) { + // TODO + return; // nothing wrapped yet + } int nb = sizeof(wrappedlibs) / sizeof(wrappedlib_t); for (int i=0; i<nb; ++i) { if(strcmp(lib->name, wrappedlibs[i].name)==0) { diff --git a/src/mallochook.c b/src/mallochook.c index f63a85bd..abdadc8d 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -776,11 +776,15 @@ void checkHookedSymbols(elfheader_t* h) int hooked_symtab = 0; if(box64_malloc_hack==1) return; + if(box64_is32bits) { + /* TODO? */ + return; + } for (size_t i=0; i<h->numSymTab; ++i) { - int type = ELF64_ST_TYPE(h->SymTab[i].st_info); - int sz = ELF64_ST_TYPE(h->SymTab[i].st_size); - if((type==STT_FUNC) && sz && (h->SymTab[i].st_shndx!=0 && h->SymTab[i].st_shndx<=65521)) { - const char * symname = h->StrTab+h->SymTab[i].st_name; + int type = ELF64_ST_TYPE(h->SymTab._64[i].st_info); + int sz = ELF64_ST_TYPE(h->SymTab._64[i].st_size); + if((type==STT_FUNC) && sz && (h->SymTab._64[i].st_shndx!=0 && h->SymTab._64[i].st_shndx<=65521)) { + const char * symname = h->StrTab+h->SymTab._64[i].st_name; #define GO(A, B) if(!strcmp(symname, #A)) ++hooked; else if(!strcmp(symname, "__libc_" #A)) ++hooked; #define GO2(A, B) SUPER() @@ -790,14 +794,14 @@ void checkHookedSymbols(elfheader_t* h) } if(hooked<2) { for (size_t i=0; i<h->numDynSym && hooked<2; ++i) { - const char * symname = h->DynStr+h->DynSym[i].st_name; - int bind = ELF64_ST_BIND(h->DynSym[i].st_info); - int type = ELF64_ST_TYPE(h->DynSym[i].st_info); - int vis = h->DynSym[i].st_other&0x3; + const char * symname = h->DynStr+h->DynSym._64[i].st_name; + int bind = ELF64_ST_BIND(h->DynSym._64[i].st_info); + int type = ELF64_ST_TYPE(h->DynSym._64[i].st_info); + int vis = h->DynSym._64[i].st_other&0x3; if((type==STT_FUNC) - && (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) { - uintptr_t offs = h->DynSym[i].st_value + h->delta; - size_t sz = h->DynSym[i].st_size; + && (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym._64[i].st_shndx!=0 && h->DynSym._64[i].st_shndx<=65521)) { + uintptr_t offs = h->DynSym._64[i].st_value + h->delta; + size_t sz = h->DynSym._64[i].st_size; if(bind!=STB_LOCAL && bind!=STB_WEAK && sz>=sizeof(reloc_jmp_t)) { #define GO(A, B) if(!strcmp(symname, #A)) ++hooked; else if(!strcmp(symname, "__libc_" #A)) ++hooked; #define GO2(A, B) @@ -814,11 +818,11 @@ void checkHookedSymbols(elfheader_t* h) printf_log(LOG_INFO, "Redirecting overridden malloc%s from %s function for %s\n", malloc_hack_2?" with hack":"", hooked_symtab?"symtab":"dynsym", ElfName(h)); if(hooked_symtab) { for (size_t i=0; i<h->numSymTab; ++i) { - int type = ELF64_ST_TYPE(h->SymTab[i].st_info); + int type = ELF64_ST_TYPE(h->SymTab._64[i].st_info); if(type==STT_FUNC) { - const char * symname = h->StrTab+h->SymTab[i].st_name; - uintptr_t offs = h->SymTab[i].st_value + h->delta; - size_t sz = h->SymTab[i].st_size; + const char * symname = h->StrTab+h->SymTab._64[i].st_name; + uintptr_t offs = h->SymTab._64[i].st_value + h->delta; + size_t sz = h->SymTab._64[i].st_size; #define GO(A, B) if(!strcmp(symname, "__libc_" #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "__libc_" #A, h, NULL);} #define GO2(A, B) SUPER() @@ -833,14 +837,14 @@ void checkHookedSymbols(elfheader_t* h) } } else { for (size_t i=0; i<h->numDynSym; ++i) { - const char * symname = h->DynStr+h->DynSym[i].st_name; - int bind = ELF64_ST_BIND(h->DynSym[i].st_info); - int type = ELF64_ST_TYPE(h->DynSym[i].st_info); - int vis = h->DynSym[i].st_other&0x3; + const char * symname = h->DynStr+h->DynSym._64[i].st_name; + int bind = ELF64_ST_BIND(h->DynSym._64[i].st_info); + int type = ELF64_ST_TYPE(h->DynSym._64[i].st_info); + int vis = h->DynSym._64[i].st_other&0x3; if((type==STT_FUNC) - && (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) { - uintptr_t offs = h->DynSym[i].st_value + h->delta; - size_t sz = h->DynSym[i].st_size; + && (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym._64[i].st_shndx!=0 && h->DynSym._64[i].st_shndx<=65521)) { + uintptr_t offs = h->DynSym._64[i].st_value + h->delta; + size_t sz = h->DynSym._64[i].st_size; if(bind!=STB_LOCAL && bind!=STB_WEAK) { #define GO(A, B) if(!strcmp(symname, "__libc_" #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "__libc_" #A, h, NULL);} #define GO2(A, B) |