diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/box64context.c | 6 | ||||
| -rw-r--r-- | src/elfs/elfhash.c | 354 | ||||
| -rw-r--r-- | src/elfs/elfload_dump.c | 5 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 706 | ||||
| -rw-r--r-- | src/elfs/elfloader_private.h | 24 | ||||
| -rw-r--r-- | src/elfs/elfparser.c | 128 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 2 | ||||
| -rw-r--r-- | src/include/box64context.h | 1 | ||||
| -rw-r--r-- | src/include/elfloader.h | 14 | ||||
| -rw-r--r-- | src/include/librarian.h | 22 | ||||
| -rw-r--r-- | src/include/library.h | 6 | ||||
| -rw-r--r-- | src/include/symbols.h | 18 | ||||
| -rw-r--r-- | src/include/wrappedlibs.h | 2 | ||||
| -rw-r--r-- | src/librarian/globalsymbols.c | 10 | ||||
| -rw-r--r-- | src/librarian/librarian.c | 369 | ||||
| -rw-r--r-- | src/librarian/librarian_private.h | 1 | ||||
| -rw-r--r-- | src/librarian/library.c | 189 | ||||
| -rw-r--r-- | src/librarian/library_private.h | 7 | ||||
| -rw-r--r-- | src/librarian/symbols.c | 78 | ||||
| -rw-r--r-- | src/libtools/sdl2rwops.c | 4 | ||||
| -rw-r--r-- | src/libtools/signals.c | 9 | ||||
| -rw-r--r-- | src/main.c | 68 | ||||
| -rw-r--r-- | src/mallochook.c | 7 | ||||
| -rw-r--r-- | src/tools/bridge.c | 2 | ||||
| -rw-r--r-- | src/wrapped/wrappedgtk3.c | 2 | ||||
| -rw-r--r-- | src/wrapped/wrappedgtkx112.c | 2 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibdl.c | 47 |
27 files changed, 981 insertions, 1102 deletions
diff --git a/src/box64context.c b/src/box64context.c index 679ee108..208a9fa2 100644 --- a/src/box64context.c +++ b/src/box64context.c @@ -212,8 +212,8 @@ box64context_t *NewBox64Context(int argc) init_custommem_helper(context); - context->maplib = NewLibrarian(context, 1); - context->local_maplib = NewLibrarian(context, 1); + context->maplib = NewLibrarian(context); + context->local_maplib = NewLibrarian(context); context->versym = NewDictionnary(); context->system = NewBridge(); // Cannot use Bridge name as the map is not initialized yet @@ -263,6 +263,7 @@ box64context_t *NewBox64Context(int argc) context->segtls[4].is32bits = 1; context->globdata = NewMapSymbols(); + context->uniques = NewMapSymbols(); initAllHelpers(context); @@ -363,6 +364,7 @@ void FreeBox64Context(box64context_t** context) FreeX64Emu(&ctx->emu_sig); FreeMapSymbols(&ctx->globdata); + FreeMapSymbols(&ctx->uniques); #ifdef DYNAREC //dynarec_log(LOG_INFO, "BOX64 Dynarec at exit: Max DB=%d, righter=%d\n", ctx->max_db_size, rb_get_righter(ctx->db_sizes)); diff --git a/src/elfs/elfhash.c b/src/elfs/elfhash.c new file mode 100644 index 00000000..6c602617 --- /dev/null +++ b/src/elfs/elfhash.c @@ -0,0 +1,354 @@ +#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" + +const char* GetSymbolVersion(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); + while(ver) { + Elf64_Vernaux *aux = (Elf64_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 = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead +} + +const char* GetParentSymbolVersion(elfheader_t* h, int index) +{ + if(!h->VerDef || (index<1)) + return NULL; + Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + 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;*/ + Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux); + return h->DynStr+aux->vda_name; // return Parent, so 1st aux + } + def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL; + } + return NULL; +} + +Elf64_Half GetParentSymbolVersionFlag(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); + 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; +} +Elf64_Half GetSymbolVersionFlag(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); + while(ver) { + Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); + for(int j=0; j<ver->vn_cnt; ++j) { + if(aux->vna_other==version) + return aux->vna_flags; + aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return GetParentSymbolVersionFlag(h, version); // if symbol is "internal", use Def table instead +} + + +int GetVersionIndice(elfheader_t* h, const char* vername) +{ + if(!vername) + return 0; + if(h->VerDef) { + Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); + while(def) { + Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux); + if(!strcmp(h->DynStr+aux->vda_name, vername)) + return def->vd_ndx; + def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL; + } + } + return 0; +} + +int GetNeededVersionCnt(elfheader_t* h, const char* libname) +{ + if(!libname) + return 0; + if(h->VerNeed) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + if(!strcmp(filename, libname)) + return ver->vn_cnt; + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return 0; +} + +const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) +{ + if(!libname) + return 0; + if(h->VerNeed) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); + if(!strcmp(filename, libname)) { + for(int j=0; j<ver->vn_cnt; ++j) { + if(j==idx) + return h->DynStr+aux->vna_name; + aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + return NULL; // idx out of bound, return NULL... + } + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return NULL; +} + +int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver) +{ + if(!libname || !ver) + return 0; + int n = GetNeededVersionCnt(h, libname); + if(!n) + return 0; + for(int i=0; i<n; ++i) { + const char* vername = GetNeededVersionString(h, libname, i); + if(vername && !strcmp(ver, vername)) + return 1; + } + return 0; +} + +static int SymbolMatch(elfheader_t* h, uint32_t i, int ver, const char* vername, int local, int veropt) +{ + int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; + if(version!=-1) version &=0x7fff; + const char* symvername = GetSymbolVersion(h, version); + Elf64_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>2 && flags==0) // flag is not WEAK, so global works + return 1; + if(ver<2 || !symvername) + return 0; + return strcmp(vername, symvername)?0:1; +} + +uint32_t old_elf_hash(const char* name) +{ + uint32_t h = 0, g; + for (unsigned char c = *name; c; c = *++name) { + h = (h << 4) + c; + if (g = h & 0xf0000000) { + h ^= g >> 24; + } + h &= ~g; + } + return h; +} + +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); + 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[i].st_name; + if (!strcmp(symname, name) && SymbolMatch(h, i, ver, vername, local, veropt)) { + return &h->DynSym[i]; + } + } + return NULL; +} + + +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[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"); +} + +uint32_t new_elf_hash(const char *name) +{ + uint32_t h = 5381; + for (unsigned char c = *name; c; c = *++name) + h = h * 33 + c; + return h; +} + +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); + 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[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]; + } + if(symhash&1) + return NULL; + symidx++; + } +} + +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[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"); +} + +Elf64_Sym* ElfLookup(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) +{ + if(!h->SymTab) + return 0; + for(int i=0; i<h->numSymTab; ++i) { + Elf64_Sym* sym = &h->SymTab[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; + if(name && !strcmp(symname, name)) + return sym; + } + } + return NULL; +} + +Elf64_Sym* ElfDynSymLookup(elfheader_t* h, const char* symname) +{ + if(!h->DynSym) + return 0; + for(int i=0; i<h->numDynSym; ++i) { + Elf64_Sym* sym = &h->DynSym[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; + if(name && !strcmp(symname, name)) + return sym; + } + } + return NULL; +} diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c index 1730967f..4c9cf228 100644 --- a/src/elfs/elfload_dump.c +++ b/src/elfs/elfload_dump.c @@ -231,10 +231,11 @@ 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))); + int veropt = GetSymbolVersionFlag(h, version)?0:1; memset(buff, 0, sizeof(buff)); - sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (ver=%d/%s)", + sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (%sver=%d/%s)", h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size, - sym->st_info, sym->st_other, sym->st_shndx, version, vername); + sym->st_info, sym->st_other, sym->st_shndx, veropt?"opt":"", version, vername); return buff; } diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 8d8500d7..8845444a 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -64,11 +64,6 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec) h->path[0] = '\0'; } - h->mapsymbols = NewMapSymbols(); - h->weaksymbols = NewMapSymbols(); - h->localsymbols = NewMapSymbols(); - h->globaldefver = NewDefaultVersion(); - h->weakdefver = NewDefaultVersion(); h->refcnt = 1; h->file = f; @@ -94,12 +89,6 @@ void FreeElfHeader(elfheader_t** head) box_free(h->SymTab); box_free(h->DynSym); - FreeMapSymbols(&h->mapsymbols); - FreeMapSymbols(&h->weaksymbols); - FreeMapSymbols(&h->localsymbols); - FreeDefaultVersion(&h->globaldefver); - FreeDefaultVersion(&h->weakdefver); - FreeElfMemory(h); box_free(h->name); @@ -259,7 +248,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) try_mmap = 0; if(e->p_offset&(box64_pagesize-1)) try_mmap = 0; - if(e->p_memsz-e->p_filesz>(box64_pagesize-1)) + if(ALIGN(e->p_memsz)!=ALIGN(e->p_filesz)) try_mmap = 0; if(!e->p_filesz) try_mmap = 0; @@ -279,8 +268,8 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) try_mmap = 0; printf_dump(log_level, "Mapping failed, using regular mmap+read"); } else { - /*if(e->p_memsz>e->p_filesz) - memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz);*/ // already zero'd by the mmap + 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; @@ -418,7 +407,29 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne return 1; } -int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername) +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]) + return 1; + if(h->DynSym && addr>=(uintptr_t)h->DynSym && addr<(uintptr_t)&h->DynSym[h->numDynSym]) + return 1; + return 0; +} +static elfheader_t* FindElfSymbol(box64context_t *context, Elf64_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; +} + +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; @@ -435,7 +446,9 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** if(version2!=-1) version2 &= 0x7fff; if(version && !version2) version2=-1; // match a versioned symbol against a global "local" symbol const char* vername2 = GetSymbolVersion(h, version2); - if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) { + Elf64_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 = (uint64_t*)(rela[i].r_offset + h->delta + rela[i].r_addend); return 1; @@ -447,184 +460,8 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rel *rel) { - int ret_ok = 0; - for (int i=0; i<cnt; ++i) { - int t = ELF64_R_TYPE(rel[i].r_info); - Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rel[i].r_info)]; - int bind = ELF64_ST_BIND(sym->st_info); - const char* symname = SymName(head, sym); - //uint64_t ndx = sym->st_shndx; - uint64_t *p = (uint64_t*)(rel[i].r_offset + head->delta); - uintptr_t offs = 0; - uintptr_t end = 0; - size_t size = sym->st_size; - //uintptr_t tmp = 0; - int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rel[i].r_info)]:-1; - if(version!=-1) version &=0x7fff; - const char* vername = GetSymbolVersion(head, version); - const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, deepbind, symname); - const char* weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, deepbind, symname):NULL; - if(bind==STB_LOCAL) { - if(!symname || !symname[0]) { - offs = sym->st_value + head->delta; - end = offs + sym->st_size; - } else { - if(!offs && !end && local_maplib && deepbind) - GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end) - GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib && !deepbind) - GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - } - } else { - // this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now - // at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight... - /*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_X86_64_GLOB_DAT) { - offs = sym->st_value + head->delta; - end = offs + sym->st_size; - }*/ - // so weak symbol are the one left - if(bind==STB_WEAK) { - if(!offs && !end) { - if(!offs && !end && local_maplib && deepbind) - GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end) - GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib && !deepbind) - GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - } - } else { - if(!offs && !end) { - if(!offs && !end && local_maplib && deepbind) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end) - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib && !deepbind) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - } - } - } - uintptr_t globoffs, globend; - uint64_t* globp; - switch(t) { - case R_X86_64_NONE: - // can be ignored - printf_dump(LOG_NEVER, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0)); - break; - case R_X86_64_PC32: - if (!offs) { - printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name); - ret_ok = 1; - } - offs = (offs - (uintptr_t)p); - if(!offs) - printf_dump(LOG_NEVER, "Apply %s R_X86_64_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs)); - *p += offs; - break; - case R_X86_64_GLOB_DAT: - if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) { - // set global offs / size for the symbol - offs = sym->st_value; - end = offs + sym->st_size; - if(sym->st_size && offs) { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname); - memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf - AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername); - AddUniqueSymbol(my_context->globdata, symname, offs + head->delta, sym->st_size, version, vername); - } else { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname); - } - *p = globoffs; - } else { - if((size==0) && GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) { - offs = globoffs; - } - if (!offs) { - if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load")) - printf_log(LOG_NONE, "%s: Global Symbol %s (ver=%d/%s) not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, version, vername?vername:"(none)", p, *(void**)p, head->name); - } else { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)"); - *p = offs; - } - } - break; - case R_X86_64_COPY: - if(offs) { - uintptr_t old_offs = offs; - uintptr_t old_end = end; - offs = 0; - GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first - if(offs==0) { - GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver); // get original copy if any - if(!offs && local_maplib) - GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver); - } - if(!offs) { - offs = old_offs; - end = old_end; - } - printf_dump(LOG_NEVER, "Apply %s R_X86_64_COPY @%p with sym=%s, @%p size=%ld (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size); - memmove(p, (void*)offs, sym->st_size); - if(box64_dump) { - uint64_t *k = (uint64_t*)p; - for (unsigned j=0; j<((sym->st_size>128u)?128u:sym->st_size); j+=8, ++k) - printf_dump(LOG_NEVER, "%s0x%016lX", j?" ":"", *k); - printf_dump(LOG_NEVER, "%s)\n", (sym->st_size>128u)?" ...":""); - } - } else { - printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name); - } - break; - case R_X86_64_RELATIVE: - printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta)); - *p += head->delta; - break; - case R_X86_64_64: - if (!offs) { - printf_log(LOG_NONE, "%s: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", (bind==STB_GLOBAL)?"Error":"Warning", symname, p, *(void**)p, head->name); - if(bind==STB_GLOBAL) - ret_ok = 1; - // return -1; - } else { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint64_t*)p)); - *p += offs; - } - break; - #if 0 - case R_X86_64_JUMP_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)) - || !tmp - || !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end)) - ) { - if (!offs) { - if(bind==STB_WEAK) { - printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p)\n", symname, p, *(void**)p); - } else { - printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name); - } - // return -1; - } else { - if(p) { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)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_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname); - *p += head->delta; - } - break; - #endif - default: - printf_log(LOG_INFO, "Warning, don't know how to handle rel #%d %s (%p)\n", i, DumpRelType(ELF64_R_TYPE(rel[i].r_info)), p); - } - } - return bindnow?ret_ok:0; + printf_log(LOG_NONE, "Error: REL type of Relocation unsupported (only RELA)\n"); + return 1; } struct tlsdesc @@ -640,17 +477,32 @@ EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu) return td->arg; } +void GrabX64CopyMainElfReloc(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, "Grabbing R_X86_64_COPY Relocation(s) in advance for %s\n", head->name); + 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); + 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); + Elf64_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); + } + } + } +} 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; - const char* old_globdefver = NULL; - const char* old_weakdefver = NULL; - int old_bind = -1; - const char* old_symname = NULL; - uintptr_t old_offs = 0; - uintptr_t old_end = 0; - int old_version = -1; for (int i=0; i<cnt; ++i) { int t = ELF64_R_TYPE(rela[i].r_info); Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)]; @@ -661,74 +513,51 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin uintptr_t offs = 0; uintptr_t end = 0; size_t size = sym->st_size; - elfheader_t* h_tls = NULL;//head; + elfheader_t* sym_elf = NULL; int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1; if(version!=-1) version &=0x7fff; const char* vername = GetSymbolVersion(head, version); - const char* globdefver = NULL; - const char* weakdefver = NULL; - if(old_bind==bind && old_symname==symname) { - globdefver = old_globdefver; - weakdefver = old_weakdefver; + Elf64_Half flags = GetSymbolVersionFlag(head, version); + int veropt = flags?0:1; + Elf64_Sym* elfsym = NULL; + int vis = ELF64_ST_VISIBILITY(sym->st_other); + if(vis==STV_PROTECTED) { + elfsym = ElfDynSymLookup(head, symname); + printf_log(LOG_INFO, "Symbol %s from %s is PROTECTED\n", symname, head); } else { - old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, deepbind, symname); - old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, deepbind, symname):NULL; - } - if(bind==STB_LOCAL) { - if(!symname || !symname[0]) { - offs = sym->st_value + head->delta; - end = offs + sym->st_size; - } else { - if(old_version==version && old_bind==bind && old_symname==symname) { - offs = old_offs; - end = old_end; - } else { - if(local_maplib && deepbind) - GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end) - GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib && !deepbind) - GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - } - } - } else { - // this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now - // at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight... - /*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_X86_64_GLOB_DAT) { - offs = sym->st_value + head->delta; - end = offs + sym->st_size; - }*/ - // so weak symbol are the one left - if(bind==STB_WEAK) { - if(old_version==version && old_bind==bind && old_symname==symname) { - offs = old_offs; - end = old_end; - } else { - if(local_maplib && deepbind) - GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - else - GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib && !deepbind) - GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - } - } else { - if(old_version==version && old_bind==bind && old_symname==symname) { - offs = old_offs; - end = old_end; + 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 = ElfDynSymLookup(head, symname); + if(elfsym && elfsym->st_shndx) { + offs = elfsym->st_value + head->delta; + end = offs + elfsym->st_size; + } if(!offs && !end && local_maplib && deepbind) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym); if(!offs && !end) - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + GetLocalSymbolStartEnd(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, globdefver, weakdefver); + 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); } } - old_bind = bind; - old_symname = symname; - old_offs = offs; - old_end = end; + sym_elf = FindElfSymbol(my_context, elfsym); + if(elfsym && (ELF64_ST_TYPE(elfsym->st_info)==STT_TLS)) + offs = elfsym->st_value; uintptr_t globoffs, globend; uint64_t* globp; uintptr_t tmp = 0; @@ -741,14 +570,14 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin // can be ignored break; case R_X86_64_RELATIVE: - printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend)); + printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", BindSym(bind), p, *(void**)p, (void*)(head->delta+ rela[i].r_addend)); *p = head->delta+ rela[i].r_addend; break; case R_X86_64_IRELATIVE: { x64emu_t* emu = thread_get_emu(); EmuCall(emu, head->delta+rela[i].r_addend); - printf_dump(LOG_NEVER, "Apply %s R_X86_64_IRELATIVE @%p (%p -> %p()=%p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend), (void*)(R_RAX)); + printf_dump(LOG_NEVER, "Apply %s R_X86_64_IRELATIVE @%p (%p -> %p()=%p)\n", BindSym(bind), p, *(void**)p, (void*)(head->delta+ rela[i].r_addend), (void*)(R_RAX)); *p = R_RAX; } break; @@ -756,15 +585,16 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin globoffs = offs; globend = end; offs = end = 0; - GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first - if(!offs && local_maplib) - GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver); + 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, globdefver, weakdefver); + 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_X86_64_COPY @%p with sym=%s (ver=%d/%s), @%p+0x%lx size=%ld\n", p, symname, version, vername?vername:"(none)", (void*)offs, rela[i].r_addend, sym->st_size); + printf_dump(LOG_NEVER, "Apply R_X86_64_COPY @%p with sym=%s (%sver=%d/%s), @%p+0x%lx size=%ld\n", p, symname, veropt?"opt":"", version, vername?vername:"(none)", (void*)offs, rela[i].r_addend, sym->st_size); if(p!=(void*)(offs+rela[i].r_addend)) memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size); } else { @@ -772,33 +602,20 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } break; case R_X86_64_GLOB_DAT: - if((head!=my_context->elfs[0]) && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) { - // set global offs / size for the symbol - offs = sym->st_value + head->delta; - end = offs + sym->st_size; - if(sym->st_size && offs) { - 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 (ver=%d/%s) \n", - (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), - (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)"); - //memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf - AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername); - AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername); - } else { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n", - (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), - (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname, version, vername?vername:"(none)"); - } + if(GetSymbolStartEnd(my_context->globdata, symname, &globoffs, &globend, version, vername, 1, veropt)) { + globp = (uint64_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, (void*)(p?(*p):0), + (void*)(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((size==0) && GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) { - offs = globoffs; - } 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_INFO: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); + 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 (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)"); - *p = offs/* + rela[i].r_addend*/; // not addend it seems + 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, (void*)(p?(*p):0), (void*)(offs + rela[i].r_addend), symname, veropt?"opt":"", version, vername?vername:"(none)", sym_elf?sym_elf->name:"(native)"); + *p = offs + rela[i].r_addend; } } break; @@ -823,8 +640,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin // return -1; } else { if(p) { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n", - (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend)); + elfheader_t* sym_elf = FindElfAddress(my_context, offs); + printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s (%sver=%d / %s))\n", + BindSym(bind), p, symname, *(void**)p, (void*)(offs+rela[i].r_addend), sym_elf?sym_elf->name:"native", veropt?"opt":"", version, vername?vername:"(none)"); *p = offs + rela[i].r_addend; } else { printf_log(LOG_INFO, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname); @@ -832,13 +650,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } } else { printf_dump(LOG_NEVER, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n", - (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, rela[i].r_addend); + BindSym(bind), p, *p, *p+head->delta, symname, rela[i].r_addend); *p += head->delta; *need_resolv = 1; } break; case R_X86_64_64: - if (!offs) { + if (!offs && !elfsym) { if(symname && !strcmp(symname, "__gxx_personality_v0")) { printf_dump(LOG_NEVER, "Warning: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name); } else { @@ -848,8 +666,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin // return -1; } } else { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (ver=%d/%s) addend=0x%lx (%p -> %p)\n", - (bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/)); + printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%sver=%d/%s) addend=0x%lx (%p -> %p)\n", + BindSym(bind), p, symname, veropt?"opt":"", version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/)); *p /*+*/= offs+rela[i].r_addend; } break; @@ -857,21 +675,15 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin // Negated offset in static TLS block { if(!symname || !symname[0]) { - h_tls = head; + sym_elf = head; offs = sym->st_value; - } else { - h_tls = NULL; - if(local_maplib) - h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername); - if(!h_tls) - h_tls = GetGlobalSymbolElf(maplib, symname, version, vername); } - if(h_tls) { + if(sym_elf) { delta = *(int64_t*)p; - printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs); - *p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase); + 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); + *p = (uintptr_t)((int64_t)offs + rela[i].r_addend + sym_elf->tlsbase); } else { - printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", 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), DumpRelType(t), symname, p, (int64_t)offs); } } break; @@ -880,16 +692,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin if(!symname || symname[0]=='\0' || bind==STB_LOCAL) offs = getElfIndex(my_context, head); else { - if(!h_tls) { - if(local_maplib) - h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername); - if(!h_tls) - h_tls = GetGlobalSymbolElf(maplib, symname, version, vername); - } - offs = getElfIndex(my_context, h_tls); + offs = getElfIndex(my_context, sym_elf); } if(p) { - printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs); + printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", BindSym(bind), "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs); *p = offs; } else { printf_log(LOG_INFO, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname); @@ -897,7 +703,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin break; case R_X86_64_DTPOFF64: // Offset in TLS block - if (!offs && !end) { + if (!offs && !sym_elf) { if(bind==STB_WEAK) { printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_DTPOFF64 @%p (%p)\n", symname, p, *(void**)p); } else { @@ -908,8 +714,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin if(!symname || symname[0]=='\0') offs = sym->st_value; if(p) { - int64_t tlsoffset = offs; // it's not an offset in elf memory - printf_dump(LOG_NEVER, "Apply %s R_X86_64_DTPOFF64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs); + int64_t tlsoffset = (int64_t)offs; // it's not an offset in elf memory + printf_dump(LOG_NEVER, "Apply %s R_X86_64_DTPOFF64 @%p with sym=%s (%p -> %p)\n", BindSym(bind), p, symname, (void*)tlsoffset, (void*)offs); *p = tlsoffset; } else { printf_log(LOG_INFO, "Warning, Symbol %s found, but R_X86_64_DTPOFF64 Slot Offset is NULL \n", symname); @@ -918,7 +724,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin break; case R_X86_64_TLSDESC: if(!symname || !symname[0]) { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_TLSDESC @%p with addend=%zu\n", (bind==STB_LOCAL)?"Local":"Global", p, rela[i].r_addend); + printf_dump(LOG_NEVER, "Apply %s R_X86_64_TLSDESC @%p with addend=%zu\n", BindSym(bind), p, rela[i].r_addend); struct tlsdesc volatile *td = (struct tlsdesc volatile *)p; if(!tlsdescUndefweak) tlsdescUndefweak = AddBridge(my_context->system, pFE, _dl_tlsdesc_undefweak, 0, "_dl_tlsdesc_undefweak"); @@ -1067,93 +873,13 @@ uintptr_t GetLastByte(elfheader_t* h) #endif void checkHookedSymbols(elfheader_t* h); // in mallochook.c -void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h) +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); - printf_dump(LOG_NEVER, "Will look for Symbol to add in SymTable(%zu)\n", h->numSymTab); - for (size_t i=0; i<h->numSymTab; ++i) { - const char * symname = h->StrTab+h->SymTab[i].st_name; - int bind = ELF64_ST_BIND(h->SymTab[i].st_info); - int type = ELF64_ST_TYPE(h->SymTab[i].st_info); - int vis = h->SymTab[i].st_other&0x3; - size_t sz = h->SymTab[i].st_size; - if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE) - && (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) { - if(sz && strstr(symname, "@@")) { - char symnameversioned[strlen(symname)+1]; - strcpy(symnameversioned, symname); - // extact symname@@vername - char* p = strchr(symnameversioned, '@'); - *p=0; - p+=2; - symname = AddDictionnary(my_context->versym, symnameversioned); - const char* vername = AddDictionnary(my_context->versym, p); - AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername); - if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p)) - continue; - uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta); - printf_dump(LOG_NEVER, "Adding Default Versioned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz); - if(bind==STB_LOCAL) - AddSymbol(localsymbols, symname, offs, sz, 2, vername); - else // add in local and global map - if(bind==STB_WEAK) { - AddSymbol(weaksymbols, symname, offs, sz, 2, vername); - } else { - AddSymbol(mapsymbols, symname, offs, sz, 2, vername); - } - } else { - int to_add = 1; - if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, -1, NULL))) - continue; - uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta); - printf_dump(LOG_NEVER, "Adding Symbol(bind=%s) \"%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, (void*)offs, sz); - if(bind==STB_LOCAL) - AddSymbol(localsymbols, symname, offs, sz, 1, NULL); - else // add in local and global map - if(bind==STB_WEAK) { - AddSymbol(weaksymbols, symname, offs, sz, 1, NULL); - } else { - AddSymbol(mapsymbols, symname, offs, sz, 1, NULL); - } - } - } - } - - int deepbind = 0; - if(h && h->lib) - deepbind = GetDeepBind(h->lib); - printf_dump(LOG_NEVER, "Will look for Symbol to add in DynSym (%zu)\n", h->numDynSym); - 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; - if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE) - && (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) { - uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta); - size_t sz = h->DynSym[i].st_size; - int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; - int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetMaplibDefaultVersion(my_context->maplib, (maplib==my_context->maplib)?NULL:maplib, (bind==STB_WEAK)?1:0, deepbind, symname))?1:0; - if(version!=-1) version &= 0x7fff; - const char* vername = GetSymbolVersion(h, version); - if(add_default) { - AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername); - printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname); - } - int to_add = 1; - if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, version, vername))) - continue; - printf_dump(LOG_NEVER, "Adding Versioned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz); - if(bind==STB_LOCAL) - AddSymbol(localsymbols, symname, offs, sz, version, vername); - else // add in local and global map - if(bind==STB_WEAK) { - AddSymbol(weaksymbols, symname, offs, sz, version, vername); - } else { - AddSymbol(mapsymbols, symname, offs, sz, version?version:1, vername); - } - } - } + if(h==my_context->elfs[0]) + GrabX64CopyMainElfReloc(h); checkHookedSymbols(h); } @@ -1297,39 +1023,6 @@ void MarkElfInitDone(elfheader_t* h) h->init_done = 1; } void startMallocHook(); -void RunElfInitPltResolver(elfheader_t* h, x64emu_t *emu) -{ - if(!h || h->init_done) - return; - uintptr_t p = h->initentry + h->delta; - h->init_done = 1; - for(int i=0; i<h->needed->size; ++i) { - library_t *lib = h->needed->libs[i]; - elfheader_t *lib_elf = GetElf(lib); - if(lib_elf) - RunElfInitPltResolver(lib_elf, emu); - } - printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p); - if(h->initentry) - RunSafeFunction(p, 3, my_context->argc, my_context->argv, my_context->envv); - printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h)); - // and check init array now - Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta); - for (size_t i=0; i<h->initarray_sz; ++i) { - if(addr[i]) { - printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]); - RunSafeFunction((uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv); - } - } - - if(h->malloc_hook_2) - startMallocHook(); - - h->fini_done = 0; // can be fini'd now (in case it was re-inited) - printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h)); - return; -} - void RunElfInit(elfheader_t* h, x64emu_t *emu) { if(!h || h->init_done) @@ -1551,7 +1244,7 @@ const char* VersionedName(const char* name, int ver, const char* vername) return AddDictionnary(my_context->versym, buf); } -int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2) +int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, int veropt1, const char* name2, int ver2, const char* vername2, int veropt2) { if(strcmp(name1, name2)) //name are different, no need to go further return 0; @@ -1563,6 +1256,10 @@ int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const return 0; if(ver1==1 || ver2==1) // one if global, ok return 1; + if(ver1<2 && ver2>1 && veropt2) + return 1; + if(ver2<2 && ver1>1 && veropt1) + return 1; if(!strcmp(vername1, vername2)) // same vername return 1; return 0; @@ -1783,23 +1480,70 @@ void ElfAttachLib(elfheader_t* head, library_t* lib) head->lib = lib; } -kh_mapsymbols_t* GetMapSymbols(elfheader_t* h) +Elf64_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { - if(!h) + Elf64_Sym* sym = ElfLookup(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 version = ((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[idx]; + if(version!=-1) version &=0x7fff; + const char* symvername = GetSymbolVersion(head, version); + Elf64_Half flags = GetSymbolVersionFlag(head, version); + if(version>1 && *ver<2 && (flags==0)) { + *ver = version; + *vername = symvername; + *veropt = 1; + } else if(flags==0 && !*veropt && version>1 && *ver>1 && !strcmp(symvername, *vername)) { + *veropt = 1; + } + } + if(!sym->st_shndx) return NULL; + int vis = ELF64_ST_VISIBILITY(sym->st_other); + if(vis==STV_HIDDEN && !local) return NULL; - return h->mapsymbols; + return sym; } -kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h) + +void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { - if(!h) - return NULL; - return h->weaksymbols; + Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt); + if(!sym) return NULL; + int bind = ELF64_ST_BIND(sym->st_info); + if(bind!=STB_LOCAL) return 0; + if(offs) *offs = sym->st_value + head->delta; + if(end) *end = sym->st_value + head->delta + sym->st_size; + return sym; } -kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h) +void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt) { - if(!h) - return NULL; - return h->localsymbols; + Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt); + if(!sym) return NULL; + int bind = ELF64_ST_BIND(sym->st_info); + if(bind!=STB_GLOBAL && bind!=STB_GNU_UNIQUE) return 0; + if(offs) *offs = sym->st_value + head->delta; + if(end) *end = sym->st_value + head->delta + sym->st_size; + return sym; +} +void* ElfGetWeakSymbolStartEnd(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; + int bind = ELF64_ST_BIND(sym->st_info); + if(bind!=STB_WEAK) return 0; + if(offs) *offs = sym->st_value + head->delta; + if(end) *end = sym->st_value + head->delta + sym->st_size; + return sym; +} +int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname) +{ + Elf64_Sym* sym = ElfSymTabLookup(head, symname); + if(!sym) return 0; + if(!sym->st_shndx) return 0; + if(!sym->st_size) return 0; //needed? + if(offs) *offs = sym->st_value + head->delta; + if(end) *end = sym->st_value + head->delta + sym->st_size; + return 1; } typedef struct search_symbol_s{ @@ -1873,23 +1617,16 @@ void* GetNativeSymbolUnversioned(void* lib, const char* name) return s.addr; } -kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h) -{ - return h?h->globaldefver:NULL; -} -kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h) -{ - return h?h->weakdefver:NULL; -} - - uintptr_t pltResolver = ~0LL; EXPORT void PltResolver(x64emu_t* emu) { uintptr_t addr = Pop64(emu); int slot = (int)Pop64(emu); elfheader_t *h = (elfheader_t*)addr; - printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", (void*)addr, slot, *(void**)(R_RSP), h->name, h->VerSym); + 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); Elf64_Rela * rel = (Elf64_Rela *)(h->jmprel + h->delta) + slot; @@ -1899,42 +1636,53 @@ EXPORT void PltResolver(x64emu_t* emu) 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); + Elf64_Half flags = GetSymbolVersionFlag(h, version); + int veropt = flags?0:1; uint64_t *p = (uint64_t*)(rel->r_offset + h->delta); uintptr_t offs = 0; uintptr_t end = 0; - library_t* lib = h->lib; - lib_t* local_maplib = GetMaplib(lib); - int deepbind = GetDeepBind(lib); - const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 0, deepbind, symname); - const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 1, deepbind, symname):NULL; - if(!offs && !end && local_maplib && deepbind) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); - else - GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib && !deepbind) { - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver); + Elf64_Sym *elfsym = NULL; + if(bind==STB_LOCAL) { + elfsym = ElfDynSymLookup(h, symname); + if(elfsym && elfsym->st_shndx) { + offs = elfsym->st_value + h->delta; + end = offs + elfsym->st_size; + } + if(!offs && !end && local_maplib && deepbind) + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + if(!offs && !end) + GetLocalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + if(!offs && !end && local_maplib && !deepbind) + GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + } else if(bind==STB_WEAK) { + if(local_maplib && deepbind) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + else + GetGlobalWeakSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + if(!offs && !end && local_maplib && !deepbind) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + } else { + if(!offs && !end && local_maplib && deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + if(!offs && !end) + GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); + if(!offs && !end && local_maplib && !deepbind) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym); } - if(!offs && !end && !version) - GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL, globdefver, weakdefver); - if (!offs) { - printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(ver %d: %s%s%s) not found, cannot apply R_X86_64_JUMP_SLOT %p (%p) in %s\n", symname, version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name); + printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(%sver %d: %s%s%s) not found, cannot apply R_X86_64_JUMP_SLOT %p (%p) in %s\n", symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name); emu->quit = 1; return; } else { - elfheader_t* sym_elf = FindElfAddress(my_context, offs); - if(sym_elf && sym_elf!=my_context->elfs[0] && !sym_elf->init_done) { - printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h)); - RunElfInitPltResolver(sym_elf, emu); - } + elfheader_t* sym_elf = FindElfSymbol(my_context, elfsym); offs = (uintptr_t)getAlternate((void*)offs); if(p) { - printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(sym_elf)); + printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(%sver %d: %s%s%s) (%p -> %p / %s)\n", BindSym(bind), p, symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(sym_elf)); *p = offs; } else { - printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:""); + printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(%sver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:""); } } diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index f13be551..7da8d6e5 100644 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -3,8 +3,6 @@ typedef struct library_s library_t; typedef struct needed_libs_s needed_libs_t; -typedef struct kh_mapsymbols_s kh_mapsymbols_t; -typedef struct kh_defaultversion_s kh_defaultversion_t; typedef struct cleanup_s cleanup_t; #include <elf.h> @@ -48,6 +46,8 @@ typedef struct elfheader_s { int szVerDef; int e_type; uint32_t flags; + uintptr_t hash; + uintptr_t gnu_hash; intptr_t delta; // should be 0 void* image; // base of the elf image @@ -117,11 +117,6 @@ typedef struct elfheader_s { int clean_sz; int clean_cap; - kh_mapsymbols_t *mapsymbols; - kh_mapsymbols_t *weaksymbols; - kh_mapsymbols_t *localsymbols; - kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols) - kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols) } elfheader_t; #define R_X86_64_NONE 0 /* No reloc */ @@ -171,4 +166,19 @@ typedef struct elfheader_s { elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec); +const char* BindSym(int bind); + +Elf64_Half 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); + #endif //__ELFLOADER_PRIVATE_H_ diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index f9a3e844..803f7dce 100644 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -13,6 +13,9 @@ #ifndef PN_XNUM #define PN_XNUM (0xffff) #endif +#ifndef DT_GNU_HASH +#define DT_GNU_HASH 0x6ffffef5 +#endif int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t type) { @@ -284,6 +287,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) h->flags = val; printf_dump(LOG_DEBUG, "The DT_FLAGS is 0x%x\n", h->flags); 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) { @@ -374,112 +385,15 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) return h; } -const char* GetSymbolVersion(elfheader_t* h, int version) +const char* BindSym(int bind) { - if(version<2) - return NULL; - /*if(version==1) - return "*";*/ - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); - while(ver) { - Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); - for(int j=0; j<ver->vn_cnt; ++j) { - if(aux->vna_other==version) - return h->DynStr+aux->vna_name; - aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); - } - ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; - } + switch(bind) { + case STB_GLOBAL: return "STB_GLOBAL"; + case STB_WEAK: return "STB_WEAK"; + case STB_LOCAL: return "STB_LOCAL"; + case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE"; } - return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead -} - -const char* GetParentSymbolVersion(elfheader_t* h, int index) -{ - if(!h->VerDef || (index<1)) - return NULL; - Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + 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;*/ - Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux); - return h->DynStr+aux->vda_name; // return Parent, so 1st aux - } - def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL; - } - return NULL; -} - -int GetVersionIndice(elfheader_t* h, const char* vername) -{ - if(!vername) - return 0; - if(h->VerDef) { - Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); - while(def) { - Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux); - if(!strcmp(h->DynStr+aux->vda_name, vername)) - return def->vd_ndx; - def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL; - } - } - return 0; -} - -int GetNeededVersionCnt(elfheader_t* h, const char* libname) -{ - if(!libname) - return 0; - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); - while(ver) { - char *filename = h->DynStr + ver->vn_file; - if(!strcmp(filename, libname)) - return ver->vn_cnt; - ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; - } - } - return 0; -} - -const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) -{ - if(!libname) - return 0; - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); - while(ver) { - char *filename = h->DynStr + ver->vn_file; - Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); - if(!strcmp(filename, libname)) { - for(int j=0; j<ver->vn_cnt; ++j) { - if(j==idx) - return h->DynStr+aux->vna_name; - aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); - } - return NULL; // idx out of bound, return NULL... - } - ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; - } - } - return NULL; -} - -int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver) -{ - if(!libname || !ver) - return 0; - int n = GetNeededVersionCnt(h, libname); - if(!n) - return 0; - for(int i=0; i<n; ++i) { - const char* vername = GetNeededVersionString(h, libname, i); - if(vername && !strcmp(ver, vername)) - return 1; - } - return 0; -} + static char tmp[50]; + sprintf(tmp, "??? 0x%x", bind); + return tmp; +} \ No newline at end of file diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 4d8753e4..8d7ff9b9 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1227,7 +1227,7 @@ const char* getAddrFunctionName(uintptr_t addr) else if(addr==start) sprintf(ret, "%s/%s", ElfName(elf), symbname); else - sprintf(ret, "%s/%s + %ld", ElfName(elf), symbname, addr - start); + sprintf(ret, "%s/%s + 0x%lx", ElfName(elf), symbname, addr - start); } else { if(elf) { sprintf(ret, "%s + 0x%lx", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf)); diff --git a/src/include/box64context.h b/src/include/box64context.h index da09bc49..efe84223 100644 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -121,6 +121,7 @@ typedef struct box64context_s { lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols) dic_t *versym; // dictionnary of versioned symbols kh_mapsymbols_t *globdata; // GLOBAL_DAT relocation for COPY mapping in main elf + kh_mapsymbols_t *uniques; // symbols with STB_GNU_UNIQUE bindings kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary) bridge_t *system; // other bridges diff --git a/src/include/elfloader.h b/src/include/elfloader.h index 80289c5c..ea0928b1 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -26,12 +26,13 @@ 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); uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h); uintptr_t GetLastByte(elfheader_t* h); -void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h); +void AddSymbols(lib_t *maplib, elfheader_t* h); int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu); uintptr_t GetElfInit(elfheader_t* h); uintptr_t GetElfFini(elfheader_t* h); @@ -62,17 +63,16 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is u const char* GetSymbolVersion(elfheader_t* h, int version); const char* GetParentSymbolVersion(elfheader_t* h, int index); const char* VersionedName(const char* name, int ver, const char* vername); -int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2); +int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, int veropt1, const char* name2, int ver2, const char* vername2, int veropt2); int GetVersionIndice(elfheader_t* h, const char* vername); int GetNeededVersionCnt(elfheader_t* h, const char* libname); const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx); int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver); -kh_mapsymbols_t* GetMapSymbols(elfheader_t* h); -kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h); -kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h); -kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h); -kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h); +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); void* GetNativeSymbolUnversioned(void* lib, const char* name); diff --git a/src/include/librarian.h b/src/include/librarian.h index 2864f246..74a94373 100644 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -12,9 +12,10 @@ typedef struct x64emu_s x64emu_t; typedef struct elfheader_s elfheader_t; typedef struct needed_libs_s needed_libs_t; typedef struct kh_mapoffsets_s kh_mapoffsets_t; +typedef enum symbol_type_s symbol_type_t; typedef char* cstr_t; -lib_t *NewLibrarian(box64context_t* context, int ownlibs); +lib_t *NewLibrarian(box64context_t* context); void FreeLibrarian(lib_t **maplib, x64emu_t* emu); dlprivate_t *NewDLPrivate(void); void FreeDLPrivate(dlprivate_t **lib); @@ -27,20 +28,19 @@ library_t* GetLibMapLib(lib_t* maplib, const char* name); library_t* GetLibInternal(const char* name); void promoteLocalLibGlobal(library_t* lib); int isLibLocal(library_t* lib); -uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername); -int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver); -int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver); -int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver); -int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver); -int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver); -elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername); -int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver); +uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername, int veropt); +int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym); +int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym); +int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym); +int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt, void** elfsym); +int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym); +elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername, int veropt); +int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, int veropt); +int GetSymTabStartEnd(lib_t* maplib, const char* name, uintptr_t* start, uintptr_t* end); void MapLibRemoveLib(lib_t* maplib, library_t* lib); void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref); -const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, int deepbind, const char* symname); - const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib); void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name); diff --git a/src/include/library.h b/src/include/library.h index 4cc1012f..4e7ba0d1 100644 --- a/src/include/library.h +++ b/src/include/library.h @@ -21,9 +21,9 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, int deepbi char* GetNameLib(library_t *lib); int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name) -int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver); -int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver); -int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver); +int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym); +int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym); +int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym); char** GetNeededLibsNames(library_t* lib); int GetNeededLibsN(library_t* lib); library_t* GetNeededLib(library_t* lib, int idx); diff --git a/src/include/symbols.h b/src/include/symbols.h index 32e54b20..367c274b 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -13,22 +13,14 @@ kh_mapsymbols_t* NewMapSymbols(void); void FreeMapSymbols(kh_mapsymbols_t** map); // replace if already there -void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername); -uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver); +void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt); +uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, int veropt); // Update addr and sz of existing symbols void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // don't add if already there -void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername); -int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver); -int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver); +void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt); +int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, int veropt); +int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, int veropt); const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername); -// default version handling -KHASH_MAP_DECLARE_STR(defaultversion, const char*) -kh_defaultversion_t* NewDefaultVersion(void); -void FreeDefaultVersion(kh_defaultversion_t** def); - -void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername); -const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname); - #endif //__SYMBOLS_PRIVATE_H_ \ No newline at end of file diff --git a/src/include/wrappedlibs.h b/src/include/wrappedlibs.h index afe997cb..9379a905 100644 --- a/src/include/wrappedlibs.h +++ b/src/include/wrappedlibs.h @@ -7,7 +7,7 @@ typedef struct box64context_s box64context_t; typedef int (*wrappedlib_init_t)(library_t * lib, box64context_t* box64); // 0 = success typedef void (*wrappedlib_fini_t)(library_t * lib); -typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t size, int* weak, int version, const char* vername, int local, const char* defver); +typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym); void setNeededLibs(library_t* lib, int n, ...); #define SETALT0(v) #v diff --git a/src/librarian/globalsymbols.c b/src/librarian/globalsymbols.c index 462af7fb..8da444ad 100644 --- a/src/librarian/globalsymbols.c +++ b/src/librarian/globalsymbols.c @@ -17,21 +17,21 @@ // workaround for Globals symbols #define GLOB(A, B) \ - if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \ + if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, 0, NULL)) { \ printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \ memcpy((void*)globoffs, &A, sizeof(A)); \ } \ - if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \ + if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, 2, B, 1, NULL)) { \ printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \ memcpy((void*)globoffs, &A, sizeof(A)); \ } #define TOGLOB(A, B) \ - if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \ + if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, 0, NULL)) { \ printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \ memcpy(&A, (void*)globoffs, sizeof(A)); \ } \ - if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \ + if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, 2, B, 1, NULL)) { \ printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \ memcpy(&A, (void*)globoffs, sizeof(A)); \ } @@ -50,7 +50,7 @@ void my_setGlobalGThreadsInit() { int val = 1; uintptr_t globoffs, globend; - if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL, NULL)) { + if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL, 0, NULL)) { printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %d\n", (void*)globoffs, val); memcpy((void*)globoffs, &val, sizeof(val)); } diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index cc8c746c..93034ed1 100644 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -17,15 +17,13 @@ KHASH_MAP_IMPL_INT(mapoffsets, cstr_t); -lib_t *NewLibrarian(box64context_t* context, int ownlibs) +lib_t *NewLibrarian(box64context_t* context) { lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t)); maplib->mapoffsets = kh_init(mapoffsets); maplib->globaldata = NewMapSymbols(); - maplib->ownlibs = ownlibs; - return maplib; } @@ -37,11 +35,9 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu) library_t* owner = (*maplib)->owner; (*maplib)->owner = NULL; // to avoid recursive free... - if((*maplib)->ownlibs && (*maplib)->libsz) { - for(int i=0; i<(*maplib)->libsz; ++i) { - printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); - DecRefCount(&(*maplib)->libraries[i], emu); - } + for(int i=0; i<(*maplib)->libsz; ++i) { + printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); + DecRefCount(&(*maplib)->libraries[i], emu); } box_free((*maplib)->libraries); (*maplib)->libraries = NULL; @@ -131,12 +127,6 @@ static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src) library_t* lib = src->libraries[i]; if(!lib || libraryInMapLib(dest, lib)) continue; MapLibAddLib(dest, lib); - if(lib->maplib && src!=lib->maplib && dest!=lib->maplib) { - MapLibAddMapLib(dest, lib, lib->maplib); - MapLibRemoveLib(src, lib); - if(lib->maplib) - lib->maplib = (dest==my_context->maplib)?NULL:dest; - } } if(lib_src == owner) FreeLibrarian(&src, NULL); @@ -179,9 +169,13 @@ void promoteLocalLibGlobal(library_t* lib) return; // promote lib from local to global... // for add the depending local libs... - if(lib->maplib) { - MapLibAddMapLib(my_context->maplib, lib, lib->maplib); + if(lib->maplib && !lib->maplib_ref) { + lib_t* maplib = lib->maplib; + lib->maplib = NULL; + MapLibAddMapLib(my_context->maplib, lib, maplib); } + lib->maplib = NULL; + lib->maplib_ref = 0; if(!libraryInMapLib(my_context->maplib, lib)) MapLibAddLib(my_context->maplib, lib); MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib); @@ -203,6 +197,8 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in if(lib) { IncRefCount(lib, emu); // increment cntref needed->libs[n] = lib; + if(local && *maplib) + MapLibAddLib(*maplib, lib); printf_dump(LOG_DEBUG, "Already present in maplib => success\n"); return 0; } @@ -215,10 +211,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in if(local) { // add lib to maplib... if(*maplib) { - if(!libraryInMapLib(*maplib, lib)) - MapLibPrependLib(*maplib, lib, NULL); // todo: Also insert libs needed by lib, after lib? But current lib->maplib is probably not the solution - if((*maplib)->ownlibs) - MapLibRemoveMapLib(my_context->local_maplib, *maplib); + MapLibAddLib(*maplib, lib); } } else { // promote lib from local to global... @@ -239,7 +232,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in if(*maplib) { MapLibAddLib(*maplib, lib); } else { - lib->maplib = NewLibrarian(box64, 0); + lib->maplib = NewLibrarian(box64); MapLibAddLib(lib->maplib, lib); } } else { @@ -249,6 +242,11 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in if(!*maplib) *maplib = (local)?lib->maplib:my_context->maplib; + if(local && !lib->maplib) { + lib->maplib = *maplib; + lib->maplib_ref = 1; + } + if(AddSymbolsLibrary(*maplib, lib, emu)) { // also add needed libs printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n"); return 1; @@ -266,6 +264,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in lm->l_name = lib->name; lm->l_ld = GetDynamicSection(lib->e.elf); } + IncRefCount(lib, emu); return 0; } @@ -283,29 +282,10 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, int deepbind, libra } else { // it's an emulated lib, // load dependancies and launch init sequence - if(LoadNeededLibs(mainelf, maplib, 0, bindnow, deepbind, box64, emu)) { + if(LoadNeededLibs(mainelf, maplib, local, bindnow, deepbind, box64, emu)) { printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); return 1; } - // some special case, where dependancies may not be correct - if(!strcmp(GetNameLib(lib), "libCgGL.so")) { - char* names[] = {"libGL.so.1"}; // TODO: it will never be uninit... - library_t* libs[] = { NULL }; - needed_libs_t tmp = {0}; - tmp.size = tmp.cap = 1; - tmp.names = names; - tmp.libs = libs; - AddNeededLib(maplib, 0, 0, deepbind, &tmp, verneeded, box64, emu); - } - if(!strcmp(GetNameLib(lib), "libmss.so.6")) { - char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit... - library_t* libs[] = { NULL, NULL }; - needed_libs_t tmp = {0}; - tmp.size = tmp.cap = 2; - tmp.names = names; - tmp.libs = libs; - AddNeededLib(maplib, 0, 0, deepbind, &tmp, verneeded, box64, emu); - } // finalize the lib if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, deepbind, emu)) { @@ -347,9 +327,11 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, int deepbind, needed_lib if(ret) { return ret; } + // add dependant libs and init them - for (int i=0; i<needed->size; ++i) - if(AddNeededLib_init(maplib, local, bindnow, deepbind, needed->libs[i], verneeded, box64, emu)) { + int n = needed->size; + for (int i=0; i<n; ++i) + if(AddNeededLib_init(maplib, local, bindnow, deepbind, needed->libs[n-i-1], verneeded, box64, emu)) { printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]); if(!allow_missing_libs) ret = 1; } @@ -383,12 +365,10 @@ library_t* GetLibInternal(const char* name) } EXPORTDYN -uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername) +uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername, int veropt) { uintptr_t start = 0, end = 0; - const char *globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, 0, name); - const char *weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, 0, name); - if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, globdefver, weakdefver)) + if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, veropt, NULL)) return start; return 0; } @@ -414,139 +394,99 @@ static void CheckNeededLibs(needed_libs_t* needed) } } -int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver) +int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym) { assert(self); // need self for this one - //search for the self, to start "next" - int go = -1; int weak = 0; - for(int i=0; i<maplib->libsz && (go==-1); ++i) { - if(GetElfIndex(maplib->libraries[i])!=-1 && (GetElf(maplib->libraries[i])==self)) - go = i+1; + void* sym; + // search in needed libs from preloaded first, in order + if(my_context->preload) + for(int i=0; i<my_context->preload->size; ++i) + if(self!=GetElf(my_context->preload->libs[i]) && GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { + return 1; + } + if(maplib==my_context->maplib) { + // search non-weak symbol + if(self!=my_context->elfs[0] && (sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) { + if(elfsym) *elfsym = sym; + return 1; + } } - if(go<0) - go = 0; // not found... - if(maplib) - for(int i=go; i<maplib->libsz; ++i) { - if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, globdefver)) - if(*start) - return 1; + // search in global symbols + if(maplib) { + for(int i=0; i<maplib->libsz; ++i) { + if(self!=GetElf(maplib->libraries[i]) && GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) + return 1; + } } + + // GetSymbolStartEnd should not change start/end if symbol is not found + if(self!=my_context->elfs[0] && (sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) { + if(elfsym) *elfsym = sym; + weak = 1; + } + if(maplib) - for(int i=go; i<maplib->libsz; ++i) - if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) - GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, weakdefver); - // loop done, weak symbol found - if(weak && *start) - return 1; - // if self defined, give it another chance with self... - if(self) { - if(my_context->elfs[0]!=self) { - if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, globdefver)) - if(*start) - return 1; - if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, weakdefver)) - if(*start) - weak = 1; - } - for(int i=0; i<go; ++i) { - if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, globdefver)) - if(*start) - return 1; - } - if(maplib) - for(int i=0; i<go; ++i) { - if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) - GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, weakdefver); + for(int i=0; i<maplib->libsz; ++i) { + if(self!=GetElf(maplib->libraries[i]) && GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { + weak = 1; } - if(weak && *start) - return 1; } + // nope, not found - return 0; + return weak; } -static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) +static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym) { int weak = 0; size_t size = 0; + void* sym; // search in needed libs from preloaded first, in order if(my_context->preload) for(int i=0; i<my_context->preload->size; ++i) - if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver)) - if(*start) { - return 1; - } - if(maplib==my_context->maplib) { - // search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self) - if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver)) - if(*start) { + if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), veropt, elfsym)) { return 1; } - // This kind-of create a map to search lib only 1 time, and in order of needed... - if(my_context->neededlibs) - CheckNeededLibs(my_context->neededlibs); - // search in needed libs from neededlibs first, in order - if(my_context->neededlibs) - for(int i=0; i<my_context->neededlibs->size; ++i) - if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver)) - if(*start) { - return 1; - } + if(maplib==my_context->maplib) { + // search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self) + if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { + if(elfsym) *elfsym = sym; + return 1; + } } // search in global symbols if(maplib) { - if((maplib==my_context->maplib) && self && self!=my_context->elfs[0] && self!=(void*)1) - if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver)) - if(*start) { - return 1; - } for(int i=0; i<maplib->libsz; ++i) { - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver)) - if(*start) { - return 1; - } + if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) + return 1; } } - // check with default version... - int ok = 0; // GetSymbolStartEnd should not change start/end if symbol is not found - if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver)) - if(*start) { - ok = 1; - } - - // search in needed libs from neededlibs first, in order - if(my_context->neededlibs) - for(int i=0; i<my_context->neededlibs->size; ++i) - if(GetLibWeakSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), weakdefver)) - if(*start) { - return 1; - } - + if((sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { + if(elfsym) *elfsym = sym; + weak = 1; + } if(maplib) for(int i=0; i<maplib->libsz; ++i) { - if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver)) - if(*start) { - ok = 1; - } + if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) { + weak = 1; + } } // nope, not found - return (ok && *start)?1:0; + return weak; } void** my_GetGTKDisplay(); void** my_GetGthreadsGotInitialized(); -int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) +int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym) { - if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) { + if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, &version, &vername, &veropt, elfsym)) { if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size uintptr_t start2, end2; char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1); strcpy(buff, name); strcat(buff, "_END"); - if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) { + if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, &version, &vername, &veropt, elfsym)) { if(end2>*end && start2==end2) *end = end2; } @@ -571,63 +511,53 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u return 0; } -static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) +static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym) { int weak = 0; size_t size = 0; + void* sym; // search in needed libs from preloaded first, in order if(my_context->preload) for(int i=0; i<my_context->preload->size; ++i) - if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver)) - if(*start) - return 1; + if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), veropt, elfsym)) + return 1; // search non-weak symbol, from older to newer (first GLOBAL object wins) - if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver)) - if(*start) - return 1; - // This kind-of create a map to search lib only 1 time, and in order of needed... - if(my_context->neededlibs) - CheckNeededLibs(my_context->neededlibs); - // search in needed libs from neededlibs first, in order - if(my_context->neededlibs) - for(int i=0; i<my_context->neededlibs->size; ++i) - if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver)) - if(*start) - return 1; - // search in global symbols + if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { + if(elfsym) *elfsym = sym; + return 1; + } if(maplib) for(int i=0; i<maplib->libsz; ++i) { - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver)) - if(*start) - return 1; + if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) + return 1; } // check with default version... int ok = 0; // GetSymbolStartEnd should not change start/end if symbol is not found - if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver)) - if(*start) - ok = 1; + if(( sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { + if(elfsym) *elfsym = sym; + ok = 1; + } if(maplib) for(int i=0; i<maplib->libsz; ++i) { - if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver)) - if(*start) - ok = 1; + if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) + ok = 1; } // nope, not found - return (ok && *start)?1:0; + return ok; } -int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) +int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym) { - if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) { + if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, &version, &vername, &veropt, elfsym)) { if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size uintptr_t start2, end2; char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1); strcpy(buff, name); strcat(buff, "_END"); - if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) { + if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, &version, &vername, &veropt, elfsym)) { if(end2>*end && start2==end2) *end = end2; } @@ -639,12 +569,14 @@ int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* star if(!strcmp(name, "gdk_display")) { *start = (uintptr_t)my_GetGTKDisplay(); *end = *start+sizeof(void*); + if(elfsym) *elfsym = NULL; printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start); return 1; } if(!strcmp(name, "g_threads_got_initialized")) { *start = (uintptr_t)my_GetGthreadsGotInitialized(); *end = *start+sizeof(int); + if(elfsym) *elfsym = NULL; printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start); return 1; } @@ -652,31 +584,7 @@ int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* star return 0; } -static const char* internal_GetMaplibDefaultVersion(lib_t* maplib, int isweak, const char* symname) -{ - const char* ret = NULL; - for(int i=0; maplib && i<maplib->libsz; ++i) { - elfheader_t *h = GetElf(maplib->libraries[i]); - if(h) - ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname); - if(ret) - return ret; - } - return ret; -} -const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t* local_maplib, int isweak, int deepbind, const char* symname) -{ - const char* ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(my_context->elfs[0]):GetGlobalDefaultVersion(my_context->elfs[0]), symname); - if(ret) - return ret; - ret = internal_GetMaplibDefaultVersion(deepbind?local_maplib:maplib, isweak, symname); - if(ret) - return ret; - ret = internal_GetMaplibDefaultVersion(deepbind?maplib:local_maplib, isweak, symname); - return ret; -} - -elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername) +elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername, int veropt) { uintptr_t start = 0; uintptr_t end = 0; @@ -684,12 +592,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co int weak = 0; elfheader_t* ret = NULL; // check with default version... - const char* defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, 0, name); - - if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver)) + if(ElfGetGlobalSymbolStartEnd(my_context->elfs[0], &start, &end, name, &version, &vername, 1, &veropt)) return my_context->elfs[0]; for(int i=0; i<maplib->libsz; ++i) { - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) { + if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) { elfheader_t* h = GetElf(maplib->libraries[i]); if(!h) { printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i])); @@ -702,11 +608,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co } } - defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, 0, name); - if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver)) + if(ElfGetWeakSymbolStartEnd(my_context->elfs[0], &start, &end, name, &version, &vername, 1, &veropt)) ret = my_context->elfs[0]; for(int i=0; i<maplib->libsz; ++i) { - if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) { + if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) { elfheader_t* h = GetElf(maplib->libraries[i]); if(!h) { printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i])); @@ -722,27 +627,29 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co return ret; } -int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver) +int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt, void** elfsym) { int weak = 0; size_t size = 0; + void* sym; // check global GLOB_DAT kind of symbols - if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, defver)) - if(*start || *end) - return 1; + if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, veropt)) { + if(elfsym) *elfsym = NULL; + return 1; + } // check with default version... - if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver)) - if(*start || *end) - return 1; + if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 1, &veropt))) { + if(elfsym) *elfsym = sym; + return 1; + } for(int i=0; i<maplib->libsz; ++i) - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver)) - if(*start || *end) - return 1; + if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 1, &veropt, elfsym)) + return 1; // nope, not found return 0; } -int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver) +int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, int veropt) { uintptr_t start, end; size_t size = 0; @@ -750,33 +657,31 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c // check with default version... for(int i=0; i<maplib->libsz; ++i) if(GetElfIndex(maplib->libraries[i])==-1) - if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) - if(start || end) - return 1; + if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) + return 1; // nope, not found return 0; } -int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver) +int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym) { // check with default version... int weak; size_t size = 0; - const char* defver = globdefver?globdefver:weakdefver; - + void* sym; if(my_context->elfs[0]==self || !self) { - if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver)) - if(*start || *end) - return 1; + if((sym = ElfGetLocalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 1, &veropt))) { + if(elfsym) *elfsym = sym; + return 1; + } if(self) return 0; } for(int i=0; i<maplib->libsz; ++i) { if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) { - if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver)) - if(*start || *end) - return 1; + if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 1, &veropt, elfsym)) + return 1; if(self) return 0; } @@ -785,6 +690,18 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui return 0; } +int GetSymTabStartEnd(lib_t* maplib, const char* name, uintptr_t* start, uintptr_t* end) +{ + if(!maplib) + 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; + } + return 0; +} + const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib) { diff --git a/src/librarian/librarian_private.h b/src/librarian/librarian_private.h index 2991eb32..b36ed21a 100644 --- a/src/librarian/librarian_private.h +++ b/src/librarian/librarian_private.h @@ -18,7 +18,6 @@ typedef struct lib_s { library_t **libraries; int libsz; int libcap; - int ownlibs; library_t *owner; // in case that maplib is owned by a lib } lib_t; diff --git a/src/librarian/library.c b/src/librarian/library.c index cb5862ee..e7ca6bd5 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -43,14 +43,6 @@ wrappedlib_t wrappedlibs[] = { }; #undef GO -typedef struct bridged_s { - char* name; - uintptr_t start; - uintptr_t end; -} bridged_t; - -KHASH_MAP_INIT_STR(bridgemap, bridged_t) - KHASH_MAP_IMPL_STR(symbolmap, symbol1_t) KHASH_MAP_IMPL_STR(symbol2map, symbol2_t) KHASH_MAP_IMPL_STR(datamap, uint64_t) @@ -123,13 +115,13 @@ void DummyLib_Fini(library_t* lib) { } -int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { // ignoring asked size on wrapped libs uintptr_t addr = 0; uintptr_t size = 0; int wk = 0; - if (!getSymbolInMaps(lib, name, 0, &addr, &size, &wk, version, vername, local)) { + if (!getSymbolInMaps(lib, name, 0, &addr, &size, &wk, *version, *vername, local, *veropt)) { return 0; } if(!addr && !size) @@ -139,34 +131,37 @@ int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintpt *offs = addr; *sz = size; *weak = wk; + if(elfsym) *elfsym = NULL; return 1; } -int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int*weak, int version, const char* vername, int local, const char* defver) +int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { // symbols... uintptr_t start, end; // weak symbols... - if(GetSizedSymbolStartEnd(GetWeakSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver)) + void* sym; + if((sym = ElfGetWeakSymbolStartEnd(lib->e.elf, &start, &end, name, version, vername, local, veropt))) { *offs = start; *sz = end-start; *weak = 1; + if(elfsym) *elfsym = sym; return 1; } return 0; } -int DummyLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int DummyLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { return 0; } -int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { // ignoring asked size on wrapped libs uintptr_t addr = 0; uintptr_t size = 0; int wk = 0; - if (!getSymbolInMaps(lib, name, 1, &addr, &size, &wk, version, vername, local)) { + if (!getSymbolInMaps(lib, name, 1, &addr, &size, &wk, *version, *vername, local, *veropt)) { return 0; } if(!addr && !size) @@ -176,44 +171,49 @@ int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint *offs = addr; *sz = size; *weak = 0; + if(elfsym) *elfsym = NULL; return 1; } -int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { uintptr_t start, end; - if(GetSizedSymbolStartEnd(GetMapSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver)) + void* sym; + if((sym = ElfGetGlobalSymbolStartEnd(lib->e.elf, &start, &end, name, version, vername, local, veropt))) { *offs = start; *sz = end-start; *weak = 0; + if(elfsym) *elfsym = sym; return 1; } return 0; } -int DummyLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int DummyLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { return 0; } -int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { // ignoring asked size on wrapped libs uintptr_t start, end; - if(GetSymbolStartEnd(GetLocalSymbols(lib->e.elf), name, &start, &end, version, vername, local, defver)) + void* sym; + if((sym = ElfGetLocalSymbolStartEnd(lib->e.elf, &start, &end, name, version, vername, local, veropt))) { *offs = start; *sz = end-start; *weak = 0; + if(elfsym) *elfsym = sym; return 1; } return 0; } -int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { (void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local; return 0; } -int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver) +int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { (void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local; return 0; @@ -483,9 +483,6 @@ library_t *NewLibrary(const char* path, box64context_t* context, elfheader_t* ve //box_free(lib); return NULL; } - lib->gbridgemap = kh_init(bridgemap); - lib->wbridgemap = kh_init(bridgemap); - lib->lbridgemap = kh_init(bridgemap); return lib; } @@ -496,7 +493,7 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu) if(lib->type==LIB_EMULATED) { elfheader_t *elf_header = lib->e.elf; // add symbols - AddSymbols(maplib, GetMapSymbols(lib->e.elf), GetWeakSymbols(lib->e.elf), GetLocalSymbols(lib->e.elf), elf_header); + AddSymbols(maplib, elf_header); } return 0; } @@ -522,12 +519,14 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, int deepbi #ifdef HAVE_TRACE if(trace_func) { int weak; - if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL, NULL, NULL)) { + int ver = -1, veropt = 0; + const char* vername = NULL; + if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, ver, vername, veropt, NULL)) { SetTraceEmu(trace_start, trace_end); printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); box_free(trace_func); trace_func = NULL; - } else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, -1, NULL, 0, NULL)) { + } else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, &ver, &vername, 0, &veropt, NULL)) { SetTraceEmu(trace_start, trace_end); printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); box_free(trace_func); @@ -565,42 +564,33 @@ void Free1Library(library_t **the_lib, x64emu_t* emu) MapLibRemoveLib(my_context->local_maplib, lib); } // free elf is relevant - if(lib->type==LIB_EMULATED) { + int lib_type = lib->type; + // Handle needed for cleaning + needed_libs_t* needed = (lib_type==LIB_EMULATED && lib->e.elf)?lib->e.elf->needed:((lib_type==LIB_WRAPPED)?lib->w.needed:NULL); + // handle needed libs now + if(needed) + for(int i=0; i<needed->size; ++i) + DecRefCount(&needed->libs[i], emu); + // free elf + if(lib_type==LIB_EMULATED) { FreeElfHeader(&lib->e.elf); } // No "Fini" logic here, only memory handling - if(lib->maplib) - FreeLibrarian(&lib->maplib, emu); - - if(lib->type!=LIB_UNNKNOW && lib->fini) { + if(lib->maplib && !lib->maplib_ref) { + lib_t* maplib = lib->maplib; + lib->maplib = NULL; + FreeLibrarian(&maplib, emu); + } + lib->maplib = NULL; + lib->maplib_ref = 0; + if(lib_type!=LIB_UNNKNOW && lib->fini) { lib->fini(lib); } box_free(lib->name); box_free(lib->path); - if(lib->gbridgemap) { - bridged_t *br; - kh_foreach_value_ref(lib->gbridgemap, br, - box_free(br->name); - ); - kh_destroy(bridgemap, lib->gbridgemap); - } - if(lib->wbridgemap) { - bridged_t *br; - kh_foreach_value_ref(lib->wbridgemap, br, - box_free(br->name); - ); - kh_destroy(bridgemap, lib->wbridgemap); - } - if(lib->lbridgemap) { - bridged_t *br; - kh_foreach_value_ref(lib->lbridgemap, br, - box_free(br->name); - ); - kh_destroy(bridgemap, lib->lbridgemap); - } - if(lib->type == LIB_WRAPPED) { + if(lib_type == LIB_WRAPPED) { if(lib->w.symbolmap) kh_destroy(symbolmap, lib->w.symbolmap); if(lib->w.wsymbolmap) @@ -671,81 +661,37 @@ int IsSameLib(library_t* lib, const char* path) box_free(name); return ret; } -int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) +int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { if(!name[0] || !lib || (lib->type==LIB_UNNKNOW)) return 0; - khint_t k; - kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap); - // check first if already in the map - k = kh_get(bridgemap, map, VersionedName(name, version, vername)); - if(k!=kh_end(map)) { - *start = kh_value(map, k).start; - *end = kh_value(map, k).end; - return 1; - } // get a new symbol - if(lib->getweak(lib, name, start, end, size, weak, version, vername, local, defver)) { + if(lib->getweak(lib, name, start, end, size, weak, version, vername, local, veropt, elfsym)) { *end += *start; // lib->get(...) gives size, not end - char* symbol = box_strdup(VersionedName(name, version, vername)); - int ret; - k = kh_put(bridgemap, map, symbol, &ret); - kh_value(map, k).name = symbol; - kh_value(map, k).start = *start; - kh_value(map, k).end = *end; return 1; } // nope return 0; } -int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) +int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { if(!name[0] || !lib || (lib->type==LIB_UNNKNOW)) return 0; - khint_t k; - kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap); - // check if already in the map - k = kh_get(bridgemap, map, VersionedName(name, version, vername)); - if(k!=kh_end(map)) { - *start = kh_value(map, k).start; - *end = kh_value(map, k).end; - return 1; - } // get a new symbol - if(lib->getglobal(lib, name, start, end, size, weak, version, vername, local, defver)) { + if(lib->getglobal(lib, name, start, end, size, weak, version, vername, local, veropt, elfsym)) { *end += *start; // lib->get(...) gives size, not end - char* symbol = box_strdup(VersionedName(name, version, vername)); - int ret; - k = kh_put(bridgemap, map, symbol, &ret); - kh_value(map, k).name = symbol; - kh_value(map, k).start = *start; - kh_value(map, k).end = *end; return 1; } // nope return 0; } -int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) +int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym) { if(!name[0] || !lib || (lib->type==LIB_UNNKNOW)) return 0; - khint_t k; - // check first if already in the map - k = kh_get(bridgemap, lib->lbridgemap, VersionedName(name, version, vername)); - if(k!=kh_end(lib->lbridgemap)) { - *start = kh_value(lib->lbridgemap, k).start; - *end = kh_value(lib->lbridgemap, k).end; - return 1; - } // get a new symbol - if(lib->getlocal(lib, name, start, end, size, weak, version, vername, local, defver)) { + if(lib->getlocal(lib, name, start, end, size, weak, version, vername, local, veropt, elfsym)) { *end += *start; // lib->get(...) gives size, not end - char* symbol = box_strdup(VersionedName(name, version, vername)); - int ret; - k = kh_put(bridgemap, lib->lbridgemap, symbol, &ret); - kh_value(lib->lbridgemap, k).name = symbol; - kh_value(lib->lbridgemap, k).start = *start; - kh_value(lib->lbridgemap, k).end = *end; return 1; } // nope @@ -981,7 +927,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui return 0; } -int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int* weak, int version, const char* vername, int local) +int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int* weak, int version, const char* vername, int local, int veropt) { if(version==-2) // don't send global native symbol for a version==-2 search return 0; @@ -1191,18 +1137,11 @@ void IncRefCount(library_t* lib, x64emu_t* emu) if(lib->w.refcnt==LIB_MAXCNT) return; ++lib->w.refcnt; - if(lib->w.needed) - for(int i=0; i<lib->w.needed->size; ++i) { - IncRefCount(lib->w.needed->libs[i], emu); - } break; case LIB_EMULATED: if(lib->e.elf->refcnt==LIB_MAXCNT) return; ++lib->e.elf->refcnt; - if(lib->e.elf->needed) - for(int i=0; i<lib->e.elf->needed->size; ++i) // some libs may not be loaded yet - IncRefCount(lib->e.elf->needed->libs[i], emu); } } @@ -1215,39 +1154,29 @@ int DecRefCount(library_t** lib, x64emu_t* emu) return 0; } int ret = 1; - needed_libs_t* needed = NULL; - int freed = 0; switch ((*lib)->type) { case LIB_WRAPPED: if((*lib)->w.refcnt==LIB_MAXCNT) return ret; - needed = (*lib)->w.needed; ret=--(*lib)->w.refcnt; if(!ret) { - needed = copy_neededlib(needed); - freed=1; Free1Library(lib, emu); } break; case LIB_EMULATED: - if((*lib)->e.elf->refcnt==LIB_MAXCNT) - return ret; - needed = (*lib)->e.elf->needed; - ret=--(*lib)->e.elf->refcnt; + if(!(*lib)->e.elf) + ret = 0; + else { + if((*lib)->e.elf->refcnt==LIB_MAXCNT) + return ret; + ret=--(*lib)->e.elf->refcnt; + } if(!ret) { - needed = copy_neededlib(needed); - freed=1; - removeLinkMapLib(*lib); FiniLibrary(*lib, emu); Free1Library(lib, emu); } break; } - if(needed) - for(int i=0; i<needed->size; ++i) - DecRefCount(&needed->libs[i], emu); - if(freed) - free_neededlib(needed); return ret; } diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h index b7e1e45d..1da4c264 100644 --- a/src/librarian/library_private.h +++ b/src/librarian/library_private.h @@ -11,7 +11,6 @@ typedef struct lib_s lib_t; typedef struct bridge_s bridge_t; typedef struct elfheader_s elfheader_t; -typedef struct kh_bridgemap_s kh_bridgemap_t; typedef struct kh_mapsymbols_s kh_mapsymbols_t; typedef struct x64emu_s x64emu_t; @@ -80,9 +79,7 @@ typedef struct library_s { elib_t e; }; // private lib data lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen) - kh_bridgemap_t *gbridgemap; // global symbol bridgemap - kh_bridgemap_t *wbridgemap; // weak symbol bridgemap - kh_bridgemap_t *lbridgemap; // local symbol bridgemap + int maplib_ref; // ref to maplib (not owned) size_t dlopen; // idx to the dlopen idx (or 0 if not dlopen) } library_t; @@ -104,7 +101,7 @@ typedef struct map_onedata_s { int weak; } map_onedata_t; -int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int *weak, int version, const char* vername, int local); // Add bridges to functions +int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int *weak, int version, const char* vername, int local, int veropt); // Add bridges to functions typedef struct linkmap_s { // actual struct link_map diff --git a/src/librarian/symbols.c b/src/librarian/symbols.c index ddebbe75..d8cbdb31 100644 --- a/src/librarian/symbols.c +++ b/src/librarian/symbols.c @@ -18,6 +18,7 @@ typedef struct onesymbol_s { typedef struct versymbol_s { int version; // -1 = no-version, 0=local, 1=global, X=versioned + int veropt; const char* vername; // NULL or version name if version=X onesymbol_t sym; } versymbol_t; @@ -48,10 +49,14 @@ void FreeMapSymbols(kh_mapsymbols_t** map) } // Exact same version (ver<2 or vername if ver>=2) -static int SameVersion(versymbol_t* s, int ver, const char* vername) +static int SameVersion(versymbol_t* s, int ver, const char* vername, int veropt) { + if(ver<2 && s->veropt) + return 1; if(ver<2) return (s->version == ver)?1:0; + if(ver>1 && veropt && s->version<2) + return 1; if(s->vername && !strcmp(s->vername, vername)) return 1; return 0; @@ -80,9 +85,12 @@ static versymbol_t* FindVersionGlobal(versymbols_t* s, size_t size) { if(!s || !s->sz) return NULL; - for (int i=0; i<s->sz; ++i) + for (int i=0; i<s->sz; ++i) { if(s->syms[i].version==1 && (!size || (size==s->syms[i].sym.sz))) return &s->syms[i]; + if(s->syms[i].version>1 && s->syms[i].veropt && (!size || (size==s->syms[i].sym.sz))) + return &s->syms[i]; + } return NULL; } static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vername) @@ -105,7 +113,7 @@ static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size) } // Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name") -static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, const char* defver) +static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, int veropt) { if(!s || !s->sz) return NULL; @@ -114,14 +122,12 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, if(local) ret = FindVersionLocal(s, size); if(!ret) ret = FindNoVersion(s, size); if(!ret) ret = FindVersionGlobal(s, size); - if(!ret && defver) ret = FindVersion(s, size, defver); return ret; } if(ver==-1) { if(local) ret = FindVersionLocal(s, size); if(!ret) ret = FindNoVersion(s, size); if(!ret) ret = FindVersionGlobal(s, size); - if(!ret && defver) ret = FindVersion(s, size, defver); //if(!ret) ret = FindFirstVersion(s, size); return ret; } @@ -134,18 +140,20 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, if(local) ret = FindVersionLocal(s, size); if(!ret) ret = FindVersionGlobal(s, size); if(!ret) ret = FindNoVersion(s, size); - if(!ret && defver) ret = FindVersion(s, size, defver); //if(!ret) ret = FindFirstVersion(s); return ret; } + if(veropt && ver>1) { + ret = FindVersionGlobal(s, size); + if(ret) return ret; + } ret = FindVersion(s, size, vername); if(local && !ret) ret = FindVersionLocal(s, size); - if(!ret && defver && vername && !strcmp(defver, vername)) ret = FindVersionGlobal(s, size); //if(!ret) return FindVersionGlobal(s); return ret; } -void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername) +void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt) { int ret; khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret); @@ -153,7 +161,7 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui if(ret) {v->sz = v->cap = 0; v->syms = NULL;} // now check if that version already exist, and update record and exit if yes for(int i=0; i<v->sz; ++i) - if(SameVersion(&v->syms[i], ver, vername)) { + if(SameVersion(&v->syms[i], ver, vername, veropt)) { v->syms[i].sym.offs = addr; v->syms[i].sym.sz = sz; return; @@ -183,7 +191,7 @@ void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t } } -uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver) +uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, int veropt) { if(!mapsymbols) return 0; @@ -191,13 +199,13 @@ uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, con if(k==kh_end(mapsymbols)) return 0; versymbols_t * v = &kh_val(mapsymbols, k); - versymbol_t * s = MatchVersion(v, ver, vername, 0, local, defver); + versymbol_t * s = MatchVersion(v, ver, vername, 0, local, veropt); if(s) return s->sym.offs; return 0; } -void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername) +void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt) { int ret; khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret); @@ -205,7 +213,7 @@ void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t ad if(ret) {v->sz = v->cap = 0; v->syms = NULL;} // now check if that version already exist, and exit if yes for(int i=0; i<v->sz; ++i) - if(SameVersion(&v->syms[i], ver, vername)) { + if(SameVersion(&v->syms[i], ver, vername, veropt)) { return; } // add a new record @@ -218,9 +226,10 @@ void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t ad v->syms[idx].vername = vername; v->syms[idx].sym.offs = addr; v->syms[idx].sym.sz = sz; + v->syms[idx].veropt = veropt; } -int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver) +int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, int veropt) { if(!mapsymbols) return 0; @@ -228,7 +237,7 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* if(k==kh_end(mapsymbols)) return 0; versymbols_t * v = &kh_val(mapsymbols, k); - versymbol_t* s = MatchVersion(v, ver, vername, 0, local, defver); + versymbol_t* s = MatchVersion(v, ver, vername, 0, local, veropt); if(s) { if(start) *start = s->sym.offs; if(end) *end = *start + s->sym.sz; @@ -237,7 +246,7 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* return 0; } -int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver) +int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, int veropt) { if(!mapsymbols) return 0; @@ -245,7 +254,7 @@ int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintpt if(k==kh_end(mapsymbols)) return 0; versymbols_t * v = &kh_val(mapsymbols, k); - versymbol_t* s = MatchVersion(v, ver, vername, size, local, defver); + versymbol_t* s = MatchVersion(v, ver, vername, size, local, veropt); if(s) { *start = s->sym.offs; *end = *start + s->sym.sz; @@ -270,38 +279,3 @@ const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start ); return NULL; } - - -KHASH_MAP_IMPL_STR(defaultversion, const char*) -kh_defaultversion_t* NewDefaultVersion() -{ - kh_defaultversion_t* ret = kh_init(defaultversion); - return ret; -} - -void FreeDefaultVersion(kh_defaultversion_t** def) -{ - if(!def || !*def) - return; - const char* v; - kh_foreach_value(*def, v, box_free((char*)v);); - - kh_destroy(defaultversion, *def); - *def = NULL; -} - -void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername) -{ - int ret; - khint_t k = kh_put(defaultversion, def, symname, &ret); - if(!ret) return; // already set! - kh_value(def, k) = box_strdup(vername); -} -const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname) -{ - khint_t k = kh_get(defaultversion, def, symname); - if(k==kh_end(def)) - return NULL; - else - return kh_value(def, k); -} diff --git a/src/libtools/sdl2rwops.c b/src/libtools/sdl2rwops.c index 085c7837..1273d36c 100644 --- a/src/libtools/sdl2rwops.c +++ b/src/libtools/sdl2rwops.c @@ -121,8 +121,8 @@ static void checkSDL2isNative() { if(my_context->sdl2allocrw) return; - emulated_sdl2allocrw = FindGlobalSymbol(my_context->maplib, "SDL_AllocRW", -1, NULL); - emulated_sdl2freerw = FindGlobalSymbol(my_context->maplib, "SDL_FreeRW", -1, NULL); + emulated_sdl2allocrw = FindGlobalSymbol(my_context->maplib, "SDL_AllocRW", -1, NULL, 0); + emulated_sdl2freerw = FindGlobalSymbol(my_context->maplib, "SDL_FreeRW", -1, NULL, 0); if(emulated_sdl2allocrw && emulated_sdl2freerw) { my_context->sdl2allocrw = my_wrapped_sdl2allocrw; my_context->sdl2freerw = my_wrapped_sdl2freerw; diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 079a5780..8a3294f5 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1386,7 +1386,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n"); } // mark stuff as unclean - cleanDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize, 0); + if(box64_dynarec) + cleanDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize, 0); static void* glitch_pc = NULL; static void* glitch_addr = NULL; static uint32_t glitch_prot = 0; @@ -1511,7 +1512,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for #error Unsupported Architecture #endif //arch #endif //DYNAREC - if(!db && (sig==SIGSEGV) && ((uintptr_t)addr==x64pc-1)) + if(!db && (sig==SIGSEGV) && ((uintptr_t)addr==(x64pc-1))) x64pc--; if(log_minimum<=box64_log) { signal_jmpbuf_active = 1; @@ -1632,7 +1633,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for if(db) hash = X31_hash_code(db->x64_addr, db->x64_size); printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p, stack=%p:%p own=%p fp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x) handler=%p", - GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, + GetTID(), signame, pc, name, (void*)x64pc, elfname?:"???", x64name?:"???", rsp, emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_RBP, addr, info->si_code, prot, db, db?db->block:0, db?(db->block+db->size):0, @@ -1674,7 +1675,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for #warning TODO #endif #else - printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code); + printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?:"???", x64name?:"???", rsp, addr, info->si_code); #endif if(!shown_regs) { for (int i=0; i<16; ++i) { diff --git a/src/main.c b/src/main.c index 7c74bc5a..b3363338 100644 --- a/src/main.c +++ b/src/main.c @@ -1221,6 +1221,7 @@ void LoadEnvVars(box64context_t *context) AddPath("libpng12.so.0", &context->box64_emulated_libs, 0); AddPath("libcurl.so.4", &context->box64_emulated_libs, 0); AddPath("libtbbmalloc.so.2", &context->box64_emulated_libs, 0); + AddPath("libtbbmalloc_proxy.so.2", &context->box64_emulated_libs, 0); if(getenv("BOX64_SSE_FLUSHTO0")) { if (strcmp(getenv("BOX64_SSE_FLUSHTO0"), "1")==0) { @@ -1312,10 +1313,10 @@ void setupTraceInit() if(s_trace_start || s_trace_end) SetTraceEmu(s_trace_start, s_trace_end); } else { - if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) { + if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { SetTraceEmu(s_trace_start, s_trace_end); printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); - } else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) { + } else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { SetTraceEmu(s_trace_start, s_trace_end); printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); } else { @@ -1332,6 +1333,54 @@ void setupTraceInit() #endif } +void setupTraceMapLib(lib_t* maplib) +{ + if(!trace_func) + return; + char* p = trace_func; + uintptr_t s_trace_start=0, s_trace_end=0; + if(maplib) { + if (GetGlobalSymbolStartEnd(maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { + SetTraceEmu(s_trace_start, s_trace_end); + printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); + box_free(trace_func); + trace_func = NULL; + return; + } else if(GetLocalSymbolStartEnd(maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { + SetTraceEmu(s_trace_start, s_trace_end); + printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); + box_free(trace_func); + trace_func = NULL; + return; + } else if(GetSymTabStartEnd(maplib, p, &s_trace_start, &s_trace_end)) { + SetTraceEmu(s_trace_start, s_trace_end); + printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); + box_free(trace_func); + trace_func = NULL; + return; + } + } + if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { + SetTraceEmu(s_trace_start, s_trace_end); + printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); + box_free(trace_func); + trace_func = NULL; + } else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { + SetTraceEmu(s_trace_start, s_trace_end); + printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); + box_free(trace_func); + trace_func = NULL; + } else if(GetSymTabStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end)) { + SetTraceEmu(s_trace_start, s_trace_end); + printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); + box_free(trace_func); + trace_func = NULL; + } else { + printf_log(LOG_NONE, "Warning, Symbol to trace (\"%s\") not found. Trying to set trace later\n", p); + SetTraceEmu(0, 1); // disabling trace, mostly + } +} + EXPORTDYN void setupTrace() { @@ -1356,10 +1405,10 @@ void setupTrace() } } } else { - if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) { + if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { SetTraceEmu(s_trace_start, s_trace_end); printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); - } else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) { + } else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) { SetTraceEmu(s_trace_start, s_trace_end); printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end); } else { @@ -1981,11 +2030,14 @@ int main(int argc, const char **argv, char **env) { thread_set_emu(emu); // export symbols - AddSymbols(my_context->maplib, GetMapSymbols(elf_header), GetWeakSymbols(elf_header), GetLocalSymbols(elf_header), elf_header); + AddSymbols(my_context->maplib, elf_header); if(wine_preloaded) { - uintptr_t wineinfo = FindSymbol(GetMapSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL); - if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL); - if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL); + uintptr_t wineinfo = 0; + int ver = -1, veropt = 0; + const char* vername = NULL; + if(!ElfGetGlobalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt)) + if(!ElfGetWeakSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt)) + if(!ElfGetLocalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt)) if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");} else { *(void**)wineinfo = get_wine_prereserve(); diff --git a/src/mallochook.c b/src/mallochook.c index 3d50d219..4c636dd4 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -778,7 +778,8 @@ void checkHookedSymbols(elfheader_t* h) return; for (size_t i=0; i<h->numSymTab; ++i) { int type = ELF64_ST_TYPE(h->SymTab[i].st_info); - if(type==STT_FUNC) { + int sz = ELF64_ST_TYPE(h->SymTab[i].st_size); + if(type==STT_FUNC && sz) { const char * symname = h->StrTab+h->SymTab[i].st_name; #define GO(A, B) if(!strcmp(symname, #A)) ++hooked; else if(!strcmp(symname, "__libc_" #A)) ++hooked; #define GO2(A, B) @@ -824,7 +825,7 @@ void checkHookedSymbols(elfheader_t* h) #undef GO #undef GO2 #define GO(A, B) if(!strcmp(symname, #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, #A, h, &real_##A);} - #define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);} + #define GO2(A, B) if(!strcmp(symname, #A) && (box64_malloc_hack>1)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);} SUPER() #undef GO #undef GO2 @@ -847,7 +848,7 @@ void checkHookedSymbols(elfheader_t* h) #undef GO #undef GO2 #define GO(A, B) if(!strcmp(symname, #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, #A, h, &real_##A);} - #define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);} + #define GO2(A, B) if(!strcmp(symname, #A) && (box64_malloc_hack>1)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);} SUPER() #undef GO #undef GO2 diff --git a/src/tools/bridge.c b/src/tools/bridge.c index c12bc706..fd53c255 100644 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -229,7 +229,7 @@ uintptr_t AddVSyscall(bridge_t* bridge, int num) const char* getBridgeName(void* addr) { - onebridge_t* one = (onebridge_t*)(((uintptr_t)addr/sizeof(onebridge_t))*sizeof(onebridge_t)); // align to start of bridge + onebridge_t* one = (onebridge_t*)(((uintptr_t)addr&~(sizeof(onebridge_t)-1))); // align to start of bridge if(one->C3==0xC3 && one->S=='S' && one->C=='C') return one->name; return NULL; diff --git a/src/wrapped/wrappedgtk3.c b/src/wrapped/wrappedgtk3.c index 92192fcb..77611a34 100644 --- a/src/wrapped/wrappedgtk3.c +++ b/src/wrapped/wrappedgtk3.c @@ -685,7 +685,7 @@ static void my3_gtk_builder_connect_signals_default(void* builder, void* object, } // Mixing Native and emulated code... the my_g_signal_* function will handle that (GetNativeFnc does) if(!func) - func = (void*)FindGlobalSymbol(my_context->maplib, handler_name, 0, NULL); + func = (void*)FindGlobalSymbol(my_context->maplib, handler_name, 0, NULL, 0); if(!func) { my->g_log("Gtk", 1<<4, "Could not find signal handler '%s'.", handler_name); diff --git a/src/wrapped/wrappedgtkx112.c b/src/wrapped/wrappedgtkx112.c index 4b069d16..39f1b08a 100644 --- a/src/wrapped/wrappedgtkx112.c +++ b/src/wrapped/wrappedgtkx112.c @@ -1034,7 +1034,7 @@ static void my_gtk_builder_connect_signals_custom(void* builder, uintptr_t offs = 0; uintptr_t end = 0; - GetGlobalSymbolStartEnd(my_context->maplib, handler_name, &offs, &end, NULL, -1, NULL, NULL, NULL); + GetGlobalSymbolStartEnd(my_context->maplib, handler_name, &offs, &end, NULL, -1, NULL, 0, NULL); if(!offs) { if (args->module == NULL) args->my->g_log("Gtk", 1<<2 ,"gtk_builder_connect_signals() requires working GModule"); diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 48b56e46..f85b007d 100644 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -80,6 +80,7 @@ void RemoveDlopen(library_t** lib, size_t idx) } extern int box64_zoom; +void setupTraceMapLib(lib_t* maplib); // Implementation void* my_dlopen(x64emu_t* emu, void *filename, int flag) { @@ -204,6 +205,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) my_context->deferredInitCap = old_deferredInitCap; return NULL; } + setupTraceMapLib(tmp->libs[0]->maplib); free_neededlib(tmp); lib = GetLibInternal(rfilename); RunDeferredElfInit(emu); @@ -258,7 +260,7 @@ char* my_dlerror(x64emu_t* emu) KHASH_SET_INIT_INT(libs); // TODO: deepbind is probably not followed correctly here -int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername, const char* globdefver, const char* weakdefver) +int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int* version, const char** vername, int* veropt) { if(!lib) return 0; @@ -270,25 +272,26 @@ int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymb // TODO: should use librarian functions instead! int weak; // look in the library itself - if(lib->getglobal(lib, rsymbol, start, end, 0, &weak, version, vername, 1, globdefver)) + if(lib->getglobal(lib, rsymbol, start, end, 0, &weak, version, vername, 1, veropt, NULL)) return 1; - if(lib->getweak(lib, rsymbol, start, end, 0, &weak, version, vername, 1, weakdefver)) + if(lib->getweak(lib, rsymbol, start, end, 0, &weak, version, vername, 1, veropt, NULL)) return 1; // look in other libs int n = GetNeededLibsN(lib); for (int i=0; i<n; ++i) { library_t *l = GetNeededLib(lib, i); - if(recursive_dlsym_lib(collection, l, rsymbol, start, end, version, vername, globdefver, weakdefver)) + if(recursive_dlsym_lib(collection, l, rsymbol, start, end, version, vername, veropt)) return 1; } return 0; } -int my_dlsym_lib(library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername, const char* globdefver, const char* weakdefver) +int my_dlsym_lib(library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername) { kh_libs_t *collection = kh_init(libs); - int ret = recursive_dlsym_lib(collection, lib, rsymbol, start, end, version, vername, globdefver, weakdefver); + int veropt = 0; + int ret = recursive_dlsym_lib(collection, lib, rsymbol, start, end, &version, &vername, &veropt); kh_destroy(libs, collection); return ret; @@ -306,9 +309,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) printf_dlsym(LOG_DEBUG, "%04d|Call to dlsym(%p, \"%s\")%s", GetTID(), handle, rsymbol, dlsym_error?"":"\n"); if(handle==NULL) { // special case, look globably - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); - if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) { + if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, 0, NULL)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); pthread_mutex_unlock(&mutex); return (void*)start; @@ -322,10 +323,8 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } if(handle==(void*)~0LL) { // special case, look globably but no self (RTLD_NEXT) - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); elfheader_t *elf = FindElfAddress(my_context, *(uintptr_t*)R_RSP); // use return address to guess "self" - if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, globdefver, weakdefver)) { + if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, 0, NULL)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); pthread_mutex_unlock(&mutex); return (void*)start; @@ -358,9 +357,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } if(dl->dllibs[nlib].lib) { int deepbind = GetDeepBind(dl->dllibs[nlib].lib); - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, deepbind, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, deepbind, rsymbol); - if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, -1, NULL, globdefver, weakdefver)==0) { + if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, -1, NULL)==0) { // not found printf_dlsym(LOG_NEVER, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol); printf_log(LOG_DEBUG, " Symbol not found\n"); @@ -373,9 +370,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } else { // still usefull? // => look globably - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); - if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) { + if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, 0, NULL)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); pthread_mutex_unlock(&mutex); return (void*)start; @@ -463,9 +458,7 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) printf_dlsym(LOG_DEBUG, "Call to dlvsym(%p, \"%s\", %s)%s", handle, rsymbol, vername?vername:"(nil)", dlsym_error?"":"\n"); if(handle==NULL) { // special case, look globably - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); - if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, version, vername, globdefver, weakdefver)) { + if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, version, vername, 0, NULL)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); return (void*)start; } @@ -477,10 +470,8 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) } if(handle==(void*)~0LL) { // special case, look globably but no self (RTLD_NEXT) - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); elfheader_t *elf = FindElfAddress(my_context, *(uintptr_t*)R_RSP); // use return address to guess "self" - if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, version, vername, globdefver, weakdefver)) { + if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, version, vername, 0, NULL)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); return (void*)start; } @@ -509,9 +500,7 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) } if(dl->dllibs[nlib].lib) { int deepbind = GetDeepBind(dl->dllibs[nlib].lib); - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, deepbind, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, deepbind, rsymbol); - if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, version, vername, globdefver, weakdefver)==0) { + if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, version, vername)==0) { // not found printf_dlsym(LOG_NEVER, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol, vername?vername:"(nil)"); printf_log(LOG_DEBUG, " Symbol not found\n"); @@ -522,9 +511,7 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) } } else { // still usefull? - const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol); - const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol); - if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) { + if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, 0, NULL)) { printf_dlsym(LOG_NEVER, "%p\n", (void*)start); return (void*)start; } |