diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-05-29 18:05:37 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-05-29 18:05:37 +0200 |
| commit | f8a969d43ed26e64d21238ead0e9512360fb1fdd (patch) | |
| tree | 96dd023f4fef48fe62f8a1d9b7c3a1d61b0c2af4 /src | |
| parent | 55720342adbf22ba318a66b30ed9ea6ec789b032 (diff) | |
| download | box64-f8a969d43ed26e64d21238ead0e9512360fb1fdd.tar.gz box64-f8a969d43ed26e64d21238ead0e9512360fb1fdd.zip | |
Reworked elfloader, handle versionned symbols now
Diffstat (limited to 'src')
| -rwxr-xr-x | src/box64context.c | 2 | ||||
| -rwxr-xr-x | src/elfs/elfload_dump.c | 17 | ||||
| -rwxr-xr-x | src/elfs/elfloader.c | 235 | ||||
| -rwxr-xr-x | src/elfs/elfloader_private.h | 5 | ||||
| -rwxr-xr-x | src/elfs/elfparser.c | 172 | ||||
| -rwxr-xr-x | src/include/box64context.h | 2 | ||||
| -rwxr-xr-x | src/include/dictionnary.h | 13 | ||||
| -rwxr-xr-x | src/include/elfload_dump.h | 2 | ||||
| -rwxr-xr-x | src/include/elfloader.h | 5 | ||||
| -rwxr-xr-x | src/include/librarian.h | 26 | ||||
| -rwxr-xr-x | src/include/library.h | 7 | ||||
| -rw-r--r-- | src/include/symbols.h | 24 | ||||
| -rwxr-xr-x | src/include/wrappedlibs.h | 2 | ||||
| -rwxr-xr-x | src/librarian/dictionnary.c | 48 | ||||
| -rwxr-xr-x | src/librarian/librarian.c | 246 | ||||
| -rwxr-xr-x | src/librarian/librarian_private.h | 11 | ||||
| -rwxr-xr-x | src/librarian/library.c | 125 | ||||
| -rwxr-xr-x | src/librarian/library_private.h | 2 | ||||
| -rw-r--r-- | src/librarian/symbols.c | 233 | ||||
| -rwxr-xr-x | src/main.c | 20 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlib_init.h | 18 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibdl.c | 144 |
22 files changed, 966 insertions, 393 deletions
diff --git a/src/box64context.c b/src/box64context.c index 182a079f..2688b124 100755 --- a/src/box64context.c +++ b/src/box64context.c @@ -158,6 +158,7 @@ box64context_t *NewBox64Context(int argc) context->maplib = NewLibrarian(context, 1); context->local_maplib = NewLibrarian(context, 1); + context->versym = NewDictionnary(); context->system = NewBridge(); // create vsyscall context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL); @@ -197,6 +198,7 @@ void FreeBox64Context(box64context_t** context) FreeLibrarian(&ctx->local_maplib, NULL); if(ctx->maplib) FreeLibrarian(&ctx->maplib, NULL); + FreeDictionnary(&ctx->versym); for(int i=0; i<ctx->elfsize; ++i) { FreeElfHeader(&ctx->elfs[i]); diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c index 58415c44..d7d11e47 100755 --- a/src/elfs/elfload_dump.c +++ b/src/elfs/elfload_dump.c @@ -225,13 +225,14 @@ const char* DumpRelType(int t) return buff; } -const char* DumpSym(elfheader_t *h, Elf64_Sym* sym) +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))); memset(buff, 0, sizeof(buff)); - sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d", + sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (ver=%d/%s)", h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size, - sym->st_info, sym->st_other, sym->st_shndx); + sym->st_info, sym->st_other, sym->st_shndx, version, vername); return buff; } @@ -298,8 +299,10 @@ void DumpDynSym(elfheader_t *h) if(box64_dump && h->DynSym) { const char* name = ElfName(h); printf_dump(LOG_NEVER, "ELF Dump DynSym(%zu)=\n", h->numDynSym); - for (size_t i=0; i<h->numDynSym; ++i) - printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym+i)); + for (size_t i=0; i<h->numDynSym; ++i) { + int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; + printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym+i, version)); + } printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n"); } } @@ -351,11 +354,11 @@ void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name) const char* elfname = ElfName(h); printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela); for (int i = 0; i<cnt; ++i) - printf_dump(LOG_NEVER, " %s:RelA[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname, + printf_dump(LOG_NEVER, " %s:%s[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname, name, i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), ELF64_R_SYM(rela[i].r_info), IdxSymName(h, ELF64_R_SYM(rela[i].r_info)), rela[i].r_addend); - printf_dump(LOG_NEVER, "ELF Dump RelA Table=====\n"); + printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name); } } diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index c49a56ea..15619efc 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -28,6 +28,8 @@ #include "box64stack.h" #include "custommem.h" #include "wine_tools.h" +#include "dictionnary.h" +#include "symbols.h" #ifdef DYNAREC #include "dynablock.h" #endif @@ -353,7 +355,7 @@ int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) return 0; } -int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p) +int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, int version, const char* vername) { if(!h) return 0; @@ -365,7 +367,10 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** int t = ELF64_R_TYPE(rel[i].r_info); Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel[i].r_info)]; const char* symname = SymName(h, sym); - if(!strcmp(symname, name) && t==R_X86_64_COPY) { + int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel[i].r_info)]:-1; + if(version2!=-1) version2 &= 0x7fff; + const char* vername2 = GetSymbolVersion(h, version2); + if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2) && t==R_X86_64_COPY) { *offs = sym->st_value + h->delta; *p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend); return 1; @@ -381,27 +386,30 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn 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 ndx = sym->st_shndx; uint64_t *p = (uint64_t*)(rel[i].r_offset + head->delta); uintptr_t offs = 0; uintptr_t end = 0; //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); if(bind==STB_LOCAL) { offs = sym->st_value + head->delta; end = offs + sym->st_size; } else { // this is probably very very wrong. A proprer way to get reloc need to be writen, 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) { + /*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(!offs && !end) { - if(local_maplib) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end); - if(!offs && !end) - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end); + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername); + if(!offs && !end && local_maplib) { + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername); + } } } uintptr_t globoffs, globend; @@ -421,21 +429,21 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn *p += offs; break; case R_X86_64_GLOB_DAT: - if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp)) { + if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) { // set global offs / size for the symbol offs = sym->st_value + head->delta; end = offs + sym->st_size; if(sym->st_size) { 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, (void*)globoffs, sym->st_size, symname); //memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf - AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size); + AddWeakSymbol(GetGlobalData(maplib), 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 \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname); } *p = globoffs; } else { // Look for same symbol already loaded but not in self (so no need for local_maplib here) - if (GetGlobalNoWeakSymbolStartEnd(maplib, symname, &globoffs, &globend)) { + if (GetGlobalNoWeakSymbolStartEnd(maplib, symname, &globoffs, &globend, version, vername)) { offs = globoffs; end = globend; } @@ -453,12 +461,11 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn uintptr_t old_offs = offs; uintptr_t old_end = end; offs = 0; - GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end); // try globaldata symbols first + GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first if(offs==0) { - if(local_maplib) - GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head); - if(!offs) - GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head); // get original copy if any + GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername); // get original copy if any + if(!offs && local_maplib) + GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername); } if(!offs) { offs = old_offs; @@ -532,29 +539,31 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c int t = ELF64_R_TYPE(rela[i].r_info); Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)]; int bind = ELF64_ST_BIND(sym->st_info); - uint64_t ndx = sym->st_shndx; + //uint64_t ndx = sym->st_shndx; const char* symname = SymName(head, sym); uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta); uintptr_t offs = 0; uintptr_t end = 0; elfheader_t* h_tls = head; + 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); if(bind==STB_LOCAL) { offs = sym->st_value + head->delta; end = offs + sym->st_size; } else { // this is probably very very wrong. A proprer way to get reloc need to be writen, 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) { + /*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(!offs && !end) { - h_tls = NULL; - if(local_maplib) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end); - if(!offs && !end) - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end); + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername); + if(!offs && !end && local_maplib) { + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername); + } } } uintptr_t globoffs, globend; @@ -576,11 +585,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c globoffs = offs; globend = end; offs = end = 0; - GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end); // try globaldata symbols first + GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first if(!offs && local_maplib) - GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head); + GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername); if(!offs) - GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head); + GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername); if(!offs) {offs = globoffs; end = globend;} if(offs) { // add r_addend to p? @@ -592,7 +601,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c } break; case R_X86_64_GLOB_DAT: - if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp)) { + if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) { // set global offs / size for the symbol offs = sym->st_value + head->delta; end = offs + sym->st_size; @@ -601,16 +610,16 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname); //memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf - AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size); + AddWeakSymbol(GetGlobalData(maplib), 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 \n", + 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); + (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname, version, vername?vername:"(none)"); } *p = globoffs; } else { // Look for same symbol already loaded but not in self (so no need for local_maplib here) - if (GetGlobalNoWeakSymbolStartEnd(maplib, symname, &globoffs, &globend)) { + if (GetGlobalNoWeakSymbolStartEnd(maplib, symname, &globoffs, &globend, version, vername)) { offs = globoffs; end = globend; } @@ -661,8 +670,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name); // return -1; } else { - printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s addend=0x%lx (%p -> %p)\n", - (bind==STB_LOCAL)?"Local":"Global", p, symname, 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 (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*/)); *p /*+*/= offs+rela[i].r_addend; } break; @@ -673,9 +682,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c offs = sym->st_value; else { if(local_maplib) - h_tls = GetGlobalSymbolElf(local_maplib, symname); + h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername); if(!h_tls) - h_tls = GetGlobalSymbolElf(maplib, symname); + h_tls = GetGlobalSymbolElf(maplib, symname, version, vername); } if(h_tls) { delta = *(int64_t*)p; @@ -693,9 +702,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c else { if(!h_tls) { if(local_maplib) - h_tls = GetGlobalSymbolElf(local_maplib, symname); + h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername); if(!h_tls) - h_tls = GetGlobalSymbolElf(maplib, symname); + h_tls = GetGlobalSymbolElf(maplib, symname, version, vername); } offs = getElfIndex(my_context, h_tls); } @@ -856,27 +865,51 @@ 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) { + 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; + uint64_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) && (h->SymTab[i].st_shndx!=0)) { - if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname)) - continue; - uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta); - uint64_t sz = h->SymTab[i].st_size; - 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); - else // add in local and global map - if(bind==STB_WEAK) { - AddSymbol(weaksymbols, symname, offs, sz); - } else { - AddSymbol(mapsymbols, symname, offs, sz); - } + if(sz && strstr(symname, "@@")) { + char symnameversionned[strlen(symname)+1]; + strcpy(symnameversionned, symname); + // extact symname@@vername + char* p = strchr(symnameversionned, '@'); + *p=0; + p+=2; + symname = AddDictionnary(my_context->versym, symnameversionned); + const char* vername = AddDictionnary(my_context->versym, p); + 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 Versionned 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 { + if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && 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); + } + } } } @@ -886,21 +919,23 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea 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; - //st_shndx==65521 means ABS value if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE) && (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) { - if((bind==STB_GNU_UNIQUE || (bind==STB_GLOBAL && type==STT_FUNC)) && FindGlobalSymbol(maplib, symname)) - continue; uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta); uint64_t sz = h->DynSym[i].st_size; - 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); + int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1; + if(version!=-1) version &= 0x7fff; + const char* vername = GetSymbolVersion(h, version); + if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, version, vername)) + continue; + printf_dump(LOG_NEVER, "Adding Versionned 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); + AddSymbol(localsymbols, symname, offs, sz, version, vername); else // add in local and global map if(bind==STB_WEAK) { - AddSymbol(weaksymbols, symname, offs, sz); + AddSymbol(weaksymbols, symname, offs, sz, version, vername); } else { - AddSymbol(mapsymbols, symname, offs, sz); + AddSymbol(mapsymbols, symname, offs, sz, version, vername); } } } @@ -971,16 +1006,22 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib h->neededlibs = neededlibs; DumpDynamicNeeded(h); - for (size_t i=0; i<h->numDynamic; ++i) - if(h->Dynamic[i].d_tag==DT_NEEDED) { - char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; - // TODO: Add LD_LIBRARY_PATH and RPATH handling - if(AddNeededLib(maplib, neededlibs, deplib, local, needed, box64, emu)) { - printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed); - if(!allow_missing_libs) - return 1; //error... - } - } + int cnt = 0; + for (int i=0; i<h->numDynamic; ++i) + if(h->Dynamic[i].d_tag==DT_NEEDED) + ++cnt; + const char* nlibs[cnt]; + int j=0; + for (int i=0; i<h->numDynamic; ++i) + if(h->Dynamic[i].d_tag==DT_NEEDED) + nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; + + // TODO: Add LD_LIBRARY_PATH and RPATH handling + if(AddNeededLib(maplib, neededlibs, deplib, local, nlibs, cnt, box64, emu)) { + printf_log(LOG_INFO, "Error loading one of needed lib\n"); + if(!allow_missing_libs) + return 1; //error... + } return 0; } @@ -1163,6 +1204,43 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin return ret; } +const char* VersionnedName(const char* name, int ver, const char* vername) +{ + if(ver==-1) + return name; + const char *v=NULL; + if(ver==0) + v=""; + if(ver==1) + v="*"; + if(!v && !vername) + return name; + if(ver>1) + v = vername; + char buf[strlen(name)+strlen(v)+1+1]; + strcpy(buf, name); + strcat(buf, "@"); + strcat(buf, v); + return AddDictionnary(my_context->versym, buf); +} + +int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2) +{ + if(strcmp(name1, name2)) //name are different, no need to go further + return 0; + if(ver1==-1 || ver2==-1) // don't check version, so ok + return 1; + if(ver1==ver2 && ver1<2) // same ver (local or global), ok + return 1; + if(ver1==0 || ver2==0) // one is local, the other is not, no match + return 0; + if(ver1==1 || ver2==1) // one if global, ok + return 1; + if(!strcmp(vername1, vername2)) // same vername + return 1; + return 0; +} + void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset) { return (void*)((char*)GetTLSPointer(context, context->elfs[index])+offset); @@ -1353,34 +1431,37 @@ 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\n", (void*)addr, slot, *(void**)(R_RSP), h->name); + 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); Elf64_Rela * rel = (Elf64_Rela *)(h->jmprel + h->delta) + slot; Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel->r_info)]; int bind = ELF64_ST_BIND(sym->st_info); const char* symname = SymName(h, sym); + int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel->r_info)]:-1; + if(version!=-1) version &= 0x7fff; + const char* vername = GetSymbolVersion(h, version); 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); - if(local_maplib) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end); - if(!offs && !end) - GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end); + GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername); + if(!offs && !end && local_maplib) { + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername); + } if (!offs) { - printf_log(LOG_NONE, "Error: PltReolver: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, h->name); + printf_log(LOG_NONE, "Error: PltReolver: 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); emu->quit = 1; return; } else { if(p) { - printf_dump(LOG_DEBUG, "PltReolver: Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs))); + 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(FindElfAddress(my_context, offs))); *p = offs; } else { - printf_log(LOG_NONE, "PltReolver: Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname); + printf_log(LOG_NONE, "PltReolver: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:""); } } diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index fa488845..d3d09daa 100755 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -30,6 +30,11 @@ struct elfheader_s { size_t numDynamic; char* DynStrTab; size_t szDynStrTab; + Elf64_Half* VerSym; + Elf64_Verneed* VerNeed; + int szVerNeed; + Elf64_Verdef* VerDef; + int szVerDef; int e_type; intptr_t delta; // should be 0 diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index a5c7f186..453e507e 100755 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -194,30 +194,87 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) // also grab the DT_STRTAB string table { for (size_t i=0; i<h->numDynamic; ++i) { - if(h->Dynamic[i].d_tag == DT_REL) - h->rel = h->Dynamic[i].d_un.d_ptr; - else if(h->Dynamic[i].d_tag == DT_RELSZ) - h->relsz = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_RELENT) - h->relent = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_RELA) - h->rela = h->Dynamic[i].d_un.d_ptr; - else if(h->Dynamic[i].d_tag == DT_RELASZ) - h->relasz = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_RELAENT) - h->relaent = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_PLTGOT) - h->pltgot = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_PLTREL) - h->pltrel = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_PLTRELSZ) - h->pltsz = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_JMPREL) - h->jmprel = h->Dynamic[i].d_un.d_val; - else if(h->Dynamic[i].d_tag == DT_STRTAB) - h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr); - else if(h->Dynamic[i].d_tag == DT_STRSZ) - h->szDynStrTab = h->Dynamic[i].d_un.d_val; + Elf64_Dyn d = h->Dynamic[i]; + Elf64_Word val = d.d_un.d_val; + Elf64_Addr ptr = d.d_un.d_ptr; + switch (d.d_tag) { + case DT_REL: + h->rel = ptr; + break; + case DT_RELSZ: + h->relsz = val; + break; + case DT_RELENT: + h->relent = val; + break; + case DT_RELA: + h->rela = ptr; + break; + case DT_RELASZ: + h->relasz = val; + break; + case DT_RELAENT: + h->relaent = val; + break; + case DT_PLTGOT: + h->pltgot = ptr; + break; + case DT_PLTREL: + h->pltrel = val; + break; + case DT_PLTRELSZ: + h->pltsz = val; + break; + case DT_JMPREL: + h->jmprel = ptr; + break; + case DT_STRTAB: + h->DynStrTab = (char*)(ptr); + break; + case DT_STRSZ: + h->szDynStrTab = val; + break; + case DT_INIT: // Entry point + h->initentry = ptr; + printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry); + break; + case DT_INIT_ARRAY: + h->initarray = ptr; + printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray); + break; + case DT_INIT_ARRAYSZ: + h->initarray_sz = val / sizeof(Elf64_Addr); + printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz); + break; + case DT_FINI: // Exit hook + h->finientry = ptr; + printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry); + break; + case DT_FINI_ARRAY: + h->finiarray = ptr; + printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray); + break; + case DT_FINI_ARRAYSZ: + h->finiarray_sz = val / sizeof(Elf64_Addr); + printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %zu\n", h->finiarray_sz); + break; + case DT_VERNEEDNUM: + h->szVerNeed = val; + printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed); + break; + case DT_VERNEED: + h->VerNeed = (Elf64_Verneed*)ptr; + printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed); + break; + case DT_VERDEFNUM: + h->szVerDef = val; + printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef); + break; + case DT_VERDEF: + h->VerDef = (Elf64_Verdef*)ptr; + printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef); + break; + } } if(h->rel) { if(h->relent != sizeof(Elf64_Rel)) { @@ -275,31 +332,11 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) h->plt_end = h->plt + h->SHEntries[ii].sh_size; printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end); } - // look for .init entry point - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init"); - if(ii) { - h->initentry = h->SHEntries[ii].sh_addr; - printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry); - } - // and .init_array - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init_array"); - if(ii) { - h->initarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr); - h->initarray = (uintptr_t)(h->SHEntries[ii].sh_addr); - printf_log(LOG_DEBUG, "The .init_array is at address %p, and have %zu elements\n", (void*)h->initarray, h->initarray_sz); - } - // look for .fini entry point - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini"); + // grab version of symbols + ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version"); if(ii) { - h->finientry = h->SHEntries[ii].sh_addr; - printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry); - } - // and .fini_array - ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini_array"); - if(ii) { - h->finiarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr); - h->finiarray = (uintptr_t)(h->SHEntries[ii].sh_addr); - printf_log(LOG_DEBUG, "The .fini_array is at address %p, and have %zu elements\n", (void*)h->finiarray, h->finiarray_sz); + h->VerSym = (Elf64_Half*)(h->SHEntries[ii].sh_addr); + printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym); } // grab .text for main code ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text"); @@ -311,8 +348,45 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL); LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym); - if(box64_dump && h->DynSym) DumpDynSym(h); } return h; } + +const char* GetSymbolVersion(elfheader_t* h, int version) +{ + if(!h->VerNeed || (version<2)) + return NULL; + /*if(version==1) + return "*";*/ + 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; +} diff --git a/src/include/box64context.h b/src/include/box64context.h index d5e8b82d..a83d79ec 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -3,6 +3,7 @@ #include <stdint.h> #include <pthread.h> #include "pathcoll.h" +#include "dictionnary.h" typedef struct elfheader_s elfheader_t; typedef struct cleanup_s cleanup_t; @@ -97,6 +98,7 @@ typedef struct box64context_s { lib_t *maplib; // lib and symbols handling lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols) + dic_t *versym; // dictionnary of versionned symbols kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary) bridge_t *system; // other bridges diff --git a/src/include/dictionnary.h b/src/include/dictionnary.h new file mode 100755 index 00000000..e2ec1466 --- /dev/null +++ b/src/include/dictionnary.h @@ -0,0 +1,13 @@ +#ifndef __DICTIONNARY_H_ +#define __DICTIONNARY_H_ +#include <stdint.h> + +typedef void dic_t; + +dic_t *NewDictionnary(); +void FreeDictionnary(dic_t **dic); + +const char* AddDictionnary(dic_t* dic, const char* s); +int ExistDictionnary(dic_t* dic, const char* s); + +#endif //__DICTIONNARY_H_ \ No newline at end of file diff --git a/src/include/elfload_dump.h b/src/include/elfload_dump.h index 251ea3b8..ce0e9c1b 100755 --- a/src/include/elfload_dump.h +++ b/src/include/elfload_dump.h @@ -6,7 +6,7 @@ typedef struct elfheader_s elfheader_t; const char* DumpSection(Elf64_Shdr *s, char* SST); const char* DumpDynamic(Elf64_Dyn *s); const char* DumpPHEntry(Elf64_Phdr *e); -const char* DumpSym(elfheader_t *h, Elf64_Sym* sym); +const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version); const char* DumpRelType(int t); const char* SymName(elfheader_t *h, Elf64_Sym* sym); const char* IdxSymName(elfheader_t *h, int sym); diff --git a/src/include/elfloader.h b/src/include/elfloader.h index aef5ae35..df745aa2 100755 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -55,4 +55,9 @@ void CreateMemorymapFile(box64context_t* context, int fd); int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used +const char* GetSymbolVersion(elfheader_t* h, int version); +const char* GetParentSymbolVersion(elfheader_t* h, int index); +const char* VersionnedName(const char* name, int ver, const char* vername); +int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2); + #endif //__ELF_LOADER_H_ diff --git a/src/include/librarian.h b/src/include/librarian.h index 37eda132..522c98b6 100755 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -24,24 +24,18 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib); kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib); kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib); kh_mapsymbols_t* GetGlobalData(lib_t* maplib); -int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error +int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error library_t* GetLibMapLib(lib_t* maplib, const char* name); library_t* GetLibInternal(const char* name); -uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name); -int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self); -int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self); -int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end); -int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end); -int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self); -int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self); -elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name); -int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name); - -void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint64_t sz); // replace if already there -uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name); -void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint64_t sz); // don't add if already there -int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end); -const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint64_t* sz); +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, int version, const char* vername); +int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername); +int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername); +int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername); +int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername); +int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername); +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* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base); diff --git a/src/include/library.h b/src/include/library.h index 26f395dc..64f376ec 100755 --- a/src/include/library.h +++ b/src/include/library.h @@ -1,6 +1,7 @@ #ifndef __LIBRARY_H_ #define __LIBRARY_H_ #include <stdint.h> +#include "symbols.h" typedef struct library_s library_t; typedef struct lib_s lib_t; @@ -18,9 +19,9 @@ void Free1Library(library_t **lib, x64emu_t* emu); char* GetNameLib(library_t *lib); int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name) -int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end); -int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end); -int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end); +int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local); +int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local); +int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local); void fillGLProcWrapper(box64context_t* context); void freeGLProcWrapper(box64context_t* context); void fillALProcWrapper(box64context_t* context); diff --git a/src/include/symbols.h b/src/include/symbols.h new file mode 100644 index 00000000..49cd40f0 --- /dev/null +++ b/src/include/symbols.h @@ -0,0 +1,24 @@ +#ifndef __SYMBOLS_PRIVATE_H_ +#define __SYMBOLS_PRIVATE_H_ +#include <stdint.h> + +#include "custommem.h" +#include "khash.h" + +typedef struct versymbols_s versymbols_t; + +KHASH_MAP_DECLARE_STR(mapsymbols, versymbols_t) + +kh_mapsymbols_t* NewMapSymbols(); +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); +// don't add if already there + +void AddWeakSymbol(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* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername); + +#endif //__SYMBOLS_PRIVATE_H_ \ No newline at end of file diff --git a/src/include/wrappedlibs.h b/src/include/wrappedlibs.h index 41e27765..f78dcfb2 100755 --- 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); +typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); typedef struct wrappedlib_s { const char* name; diff --git a/src/librarian/dictionnary.c b/src/librarian/dictionnary.c new file mode 100755 index 00000000..9d343e93 --- /dev/null +++ b/src/librarian/dictionnary.c @@ -0,0 +1,48 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "debug.h" +#include "dictionnary.h" +#include "custommem.h" +#include "khash.h" + +KHASH_SET_INIT_STR(dic); + +dic_t *NewDictionnary() +{ + dic_t *dic = kh_init(dic); + return dic; +} + +void FreeDictionnary(dic_t **d) +{ + if(!d || !*d) + return; + kh_dic_t* dic = (kh_dic_t*)*d; + const char* k; + kh_foreach_key(dic, k, free((void*)k)); + kh_destroy(dic, dic); + *d = NULL; +} + +const char* AddDictionnary(dic_t* d, const char* s) +{ + kh_dic_t* dic = (kh_dic_t*)d; + khint_t k = kh_get(dic, dic, s); + if(k!=kh_end(dic)) + return kh_key(dic, k); + char* n = strdup(s); + int ret; + k = kh_put(dic, dic, n, &ret); + return n; +} + +int ExistDictionnary(dic_t* d, const char* s) +{ + kh_dic_t* dic = (kh_dic_t*)d; + khint_t k = kh_get(dic, dic, s); + if(k!=kh_end(dic)) + return 1; + return 0; + +} \ No newline at end of file diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index 9eb191fd..2cec106b 100755 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -14,18 +14,17 @@ #include "bridge.h" -KHASH_MAP_IMPL_STR(mapsymbols, onesymbol_t); KHASH_MAP_IMPL_INT(mapoffsets, cstr_t); lib_t *NewLibrarian(box64context_t* context, int ownlibs) { lib_t *maplib = (lib_t*)calloc(1, sizeof(lib_t)); - maplib->mapsymbols = kh_init(mapsymbols); - maplib->weaksymbols = kh_init(mapsymbols); - maplib->localsymbols = kh_init(mapsymbols); + maplib->mapsymbols = NewMapSymbols(); + maplib->weaksymbols = NewMapSymbols(); + maplib->localsymbols = NewMapSymbols(); maplib->mapoffsets = kh_init(mapoffsets); - maplib->globaldata = kh_init(mapsymbols); + maplib->globaldata = NewMapSymbols(); maplib->bridge = NewBridge(); maplib->context = context; @@ -82,30 +81,21 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu) for (int i=(*maplib)->libsz-1; i>=0; --i) { freeLibraryRecurse(*maplib, emu, i, freed); } - for (int i=0; i<(*maplib)->libsz; ++i) { - (*maplib)->libraries[i] = NULL; - } + memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway + (*maplib)->libsz = 0; free(freed); } } free((*maplib)->libraries); (*maplib)->libraries = NULL; - if((*maplib)->mapsymbols) { - kh_destroy(mapsymbols, (*maplib)->mapsymbols); - } - if((*maplib)->weaksymbols) { - kh_destroy(mapsymbols, (*maplib)->weaksymbols); - } - if((*maplib)->localsymbols) { - kh_destroy(mapsymbols, (*maplib)->localsymbols); - } + FreeMapSymbols(&(*maplib)->mapsymbols); + FreeMapSymbols(&(*maplib)->weaksymbols); + FreeMapSymbols(&(*maplib)->localsymbols); if((*maplib)->mapoffsets) { kh_destroy(mapoffsets, (*maplib)->mapoffsets); } - if((*maplib)->globaldata) { - kh_destroy(mapsymbols, (*maplib)->globaldata); - } + FreeMapSymbols(&(*maplib)->globaldata); (*maplib)->libsz = (*maplib)->libcap = 0; if((*maplib)->bridge) @@ -164,6 +154,8 @@ static int libraryInMapLib(lib_t* maplib, library_t* lib) void MapLibAddLib(lib_t* maplib, library_t* lib) { + if(libraryInMapLib(maplib, lib)) + return; if (maplib->libsz == maplib->libcap) { maplib->libcap += 8; maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*)); @@ -202,8 +194,7 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib) memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx)); } -EXPORTDYN -int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu) +int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu) { printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":""); // first check if lib is already loaded @@ -267,33 +258,38 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in if(!maplib) maplib = (local)?lib->maplib:my_context->maplib; + + if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs + printf_log(LOG_DEBUG, "Failure to Add lib => fail\n"); + return 1; + } + return 0; +} + +int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, library_t* lib, box64context_t* box64, x64emu_t* emu) +{ + if(!maplib) + maplib = (local)?lib->maplib:my_context->maplib; + int mainelf = GetElfIndex(lib); if(mainelf==-1) { - // It's a native libs, just add wrapped symbols to global map - if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs - printf_log(LOG_DEBUG, "Failure to Add lib => fail\n"); - return 1; - } + // It's a native libs, nothing else to do } else { // it's an emulated lib, - // lets load dependancies before adding symbols and launch init sequence + // load dependancies and launch init sequence if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) { printf_log(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")) { - AddNeededLib(maplib, &lib->needed, lib, 0, "libGL.so.1", box64, emu); + const char* libs[] = {"libGL.so.1"}; + AddNeededLib(maplib, &lib->needed, lib, 0, libs, 1, box64, emu); } if(!strcmp(GetNameLib(lib), "libmss.so.6")) { - AddNeededLib(maplib, &lib->needed, lib, 0, "libSDL-1.2.so.0", box64, emu); - AddNeededLib(maplib, &lib->needed, lib, 0, "libdl.so.2", box64, emu); - } - // add symbols - if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs - printf_log(LOG_DEBUG, "Failure to Add lib => fail\n"); - return 1; + const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"}; + AddNeededLib(maplib, &lib->needed, lib, 0, libs, 2, box64, emu); } // finalize the lib @@ -308,6 +304,26 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in return 0; } +EXPORTDYN +int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char** paths, int npath, box64context_t* box64, x64emu_t* emu) +{ + if(!neededlibs) { + neededlibs = alloca(sizeof(needed_libs_t)); + memset(neededlibs, 0, sizeof(needed_libs_t)); + } + int idx = neededlibs->size; + // Add libs and symbol + for(int i=0; i<npath; ++i) { + if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box64, emu)) + return 1; + } + // add dependant libs and init them + for (int i=idx; i<neededlibs->size; ++i) + if(AddNeededLib_init(maplib, neededlibs, deplib, local, neededlibs->libs[i], box64, emu)) + if(!allow_missing_libs) return 1; + return 0; +} + library_t* GetLibMapLib(lib_t* maplib, const char* name) { printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); @@ -323,44 +339,53 @@ library_t* GetLibInternal(const char* name) } EXPORTDYN -uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name) +uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername) { uintptr_t start = 0, end = 0; - if(GetGlobalSymbolStartEnd(maplib, name, &start, &end)) + if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername)) return start; return 0; } -int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self) +static int isLocal(elfheader_t* self, library_t* l) +{ + if(GetElfIndex(l)==-1) + return 1; + if(my_context->elfs[GetElfIndex(l)]==self) + return 1; + return 0; +} + +int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername) { //excude self if defined if(maplib->context->elfs[0]!=self) { - if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 0)) if(*start) return 1; - if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 0)) if(*start) return 1; } for(int i=0; i<maplib->libsz; ++i) { if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self)) - if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 0)) if(*start) return 1; } // if self defined, give it another chance with self... if(self) { if(maplib->context->elfs[0]==self) { - if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1)) if(*start) return 1; - if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 1)) if(*start) return 1; } for(int i=0; i<maplib->libsz; ++i) { if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) - if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1)) if(*start) return 1; } @@ -368,32 +393,32 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u // nope, not found return 0; } -static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end) +static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername) { // search non-weak symbol, from older to newer (first GLOBAL object wins) - if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0)) if(*start) return 1; // TODO: create a temporary map to search lib only 1 time, and in order of needed... // search in needed libs from neededlibs first, in order for(int i=0; i<my_context->neededlibs.size; ++i) - if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end)) + if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, version, vername, isLocal(self, my_context->neededlibs.libs[i]))) if(*start) return 1; // search in global symbols for(int i=0; i<maplib->libsz; ++i) { - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i]))) if(*start) return 1; } // library from newer to older, weak only now for(int i=maplib->libsz-1; i>=0; --i) { - if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) // only weak symbol haven't been found yet + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i]))) // only weak symbol haven't been found yet if(*start) return 1; } - if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0)) if(*start) return 1; // nope, not found @@ -401,15 +426,15 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin } //void** my_GetGTKDisplay(); //void** my_GetGthreadsGotInitialized(); -int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end) +int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername) { - if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end)) { + if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) { 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)) { + if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) { if(end2>*end && start2==end2) *end = end2; } @@ -418,32 +443,32 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u return 1; } // some special case symbol, defined inside box64 itself -// if(!strcmp(name, "gdk_display")) { -// *start = (uintptr_t)my_GetGTKDisplay(); -// *end = *start+sizeof(void*); -// 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); -// printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start); -// return 1; -// } + //if(!strcmp(name, "gdk_display")) { + // *start = (uintptr_t)my_GetGTKDisplay(); + // *end = *start+sizeof(void*); + // 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); + // printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start); + // return 1; + //} // not found... return 0; } -elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name) +elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername) { uintptr_t start = 0; uintptr_t end = 0; - if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end)) + if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end, version, vername, 1)) return maplib->context->elfs[0]; - if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end)) + if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end, version, vername, 1)) return maplib->context->elfs[0]; for(int i=0; i<maplib->libsz; ++i) { - if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end)) { + if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1)) { int idx = GetElfIndex(maplib->libraries[i]); if(idx==-1) { printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i])); @@ -456,26 +481,25 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name) return NULL; } -int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end) +int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername) { - if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1)) if(*start || *end) return 1; for(int i=0; i<maplib->libsz; ++i) - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1)) if(*start || *end) return 1; // nope, not found return 0; } -int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name) +int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername) { - uintptr_t start=0; - uintptr_t end=0; + uintptr_t start, end; for(int i=0; i<maplib->libsz; ++i) if(GetElfIndex(maplib->libraries[i])==-1) - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1)) if(start || end) return 1; // nope, not found @@ -483,10 +507,10 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name) } -int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self) +int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername) { if(maplib->context->elfs[0]==self || !self) { - if(GetSymbolStartEnd(maplib->localsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1)) if(*start || *end) return 1; if(self) @@ -494,7 +518,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui } for(int i=0; i<maplib->libsz; ++i) { if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) { - if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1)) if(*start) return 1; if(self) @@ -504,16 +528,16 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui return 0; } -int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self) +int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername) { if(maplib->context->elfs[0]==self) { - if(GetSymbolStartEnd(maplib->localsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1)) if(*start || *end) return 1; } else { for(int i=0; i<maplib->libsz; ++i) { if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) - if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1)) if(*start || *end) return 1; } @@ -521,72 +545,22 @@ int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uin return 0; } -int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self) +int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername) { if(maplib->context->elfs[0]==self) { - if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end)) + if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1)) if(*start || *end) return 1; } else { for(int i=0; i<maplib->libsz; ++i) { if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1)) if(*start || *end) return 1; } } return 0; } - - -void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint64_t sz) -{ - int ret; - khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret); - kh_value(mapsymbols, k).offs = addr; - kh_value(mapsymbols, k).sz = sz; -} -uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name) -{ - khint_t k = kh_get(mapsymbols, mapsymbols, name); - if(k==kh_end(mapsymbols)) - return 0; - return kh_val(mapsymbols, k).offs; -} -void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint64_t sz) -{ - int ret; - khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret); - if(ret==0) - return; // Symbol already there, don't touch it - kh_value(mapsymbols, k).offs = addr; - kh_value(mapsymbols, k).sz = sz; -} - -int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end) -{ - khint_t k = kh_get(mapsymbols, mapsymbols, name); - if(k==kh_end(mapsymbols)) - return 0; - *start = kh_val(mapsymbols, k).offs; - *end = *start + kh_val(mapsymbols, k).sz; - return 1; -} - -const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start, uint64_t* sz) -{ - uintptr_t addr = (uintptr_t)p; - onesymbol_t *one; - kh_foreach_value_ref(mapsymbols, one, - if((one->offs >= addr) && (one->offs+one->sz<addr)) { - *start = one->offs; - *sz = one->sz; - return kh_key(mapsymbols, __i); - } - ); - return NULL; -} - const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base) { // first, search in self... diff --git a/src/librarian/librarian_private.h b/src/librarian/librarian_private.h index d76157c7..da2b1f0f 100755 --- a/src/librarian/librarian_private.h +++ b/src/librarian/librarian_private.h @@ -6,18 +6,10 @@ #include "khash.h" typedef struct box64context_s box64context_t; - -typedef struct onesymbol_s { - uintptr_t offs; - uint64_t sz; - // need to track type of symbol? - // need to track origin? -} onesymbol_t; +typedef struct kh_mapsymbols_s kh_mapsymbols_t; typedef char* cstr_t; -KHASH_MAP_DECLARE_STR(mapsymbols, onesymbol_t) - KHASH_MAP_DECLARE_INT(mapoffsets, cstr_t); typedef struct lib_s { @@ -30,6 +22,7 @@ typedef struct lib_s { int libsz; int libcap; int ownlibs; + library_t *owner; // in case that maplib is owned by a lib box64context_t* context; diff --git a/src/librarian/library.c b/src/librarian/library.c index 6876045d..68ccf919 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -27,8 +27,8 @@ // create the native lib list #define GO(P, N) int wrapped##N##_init(library_t* lib, box64context_t *box64); \ void wrapped##N##_fini(library_t* lib);\ - int wrapped##N##_get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz); \ - int wrapped##N##_getnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz); + int wrapped##N##_get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); \ + int wrapped##N##_getnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); #include "library_list.h" #undef GO @@ -85,51 +85,51 @@ void EmuLib_Fini(library_t* lib) kh_destroy(mapsymbols, lib->priv.n.localsymbols); } -int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) +int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) { - khint_t k; // symbols... - k = kh_get(mapsymbols, lib->priv.n.mapsymbols, name); - if(k!=kh_end(lib->priv.n.mapsymbols)) { - *offs = kh_value(lib->priv.n.mapsymbols, k).offs; - *sz = kh_value(lib->priv.n.mapsymbols, k).sz; + uintptr_t start, end; + if(GetSymbolStartEnd(lib->priv.n.mapsymbols, name, &start, &end, version, vername, local)) + { + *offs = start; + *sz = end-start; return 1; } // weak symbols... - k = kh_get(mapsymbols, lib->priv.n.weaksymbols, name); - if(k!=kh_end(lib->priv.n.weaksymbols)) { - *offs = kh_value(lib->priv.n.weaksymbols, k).offs; - *sz = kh_value(lib->priv.n.weaksymbols, k).sz; + if(GetSymbolStartEnd(lib->priv.n.weaksymbols, name, &start, &end, version, vername, local)) + { + *offs = start; + *sz = end-start; return 1; } return 0; } -int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) +int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) { - khint_t k; - k = kh_get(mapsymbols, lib->priv.n.mapsymbols, name); - if(k!=kh_end(lib->priv.n.mapsymbols)) { - *offs = kh_value(lib->priv.n.mapsymbols, k).offs; - *sz = kh_value(lib->priv.n.mapsymbols, k).sz; + uintptr_t start, end; + if(GetSymbolStartEnd(lib->priv.n.mapsymbols, name, &start, &end, version, vername, local)) + { + *offs = start; + *sz = end-start; return 1; } return 0; } -int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) +int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) { - khint_t k; - k = kh_get(mapsymbols, lib->priv.n.localsymbols, name); - if(k!=kh_end(lib->priv.n.localsymbols)) { - *offs = kh_value(lib->priv.n.localsymbols, k).offs; - *sz = kh_value(lib->priv.n.localsymbols, k).sz; + uintptr_t start, end; + if(GetSymbolStartEnd(lib->priv.n.localsymbols, name, &start, &end, version, vername, local)) + { + *offs = start; + *sz = end-start; return 1; } return 0; } -int NativeLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) +int NativeLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) { - (void)lib; (void)name; (void)offs; (void)sz; + (void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local; return 0; } @@ -151,11 +151,9 @@ static void initNativeLib(library_t *lib, box64context_t* context) { lib->getlocal = NativeLib_GetLocal; lib->type = 0; // Call librarian to load all dependant elf - for(int j=0; j<lib->priv.w.needed; ++j) { - if(AddNeededLib(context->maplib, &lib->needed, lib, 0, lib->priv.w.neededlibs[j], context, thread_get_emu())) { - printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", lib->priv.w.neededlibs[j]); - return; - } + if(AddNeededLib(context->maplib, &lib->needed, lib, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, NULL)) { // probably all native, not emulated, so that's fine + printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name); + return; } break; } @@ -308,12 +306,12 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu) RelocateElfPlt(my_context->maplib, local_maplib, elf_header); #ifdef HAVE_TRACE if(trace_func) { - if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end)) { + if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) { SetTraceEmu(trace_start, trace_end); printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); free(trace_func); trace_func = NULL; - } else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end)) { + } else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, -1, NULL, 0)) { SetTraceEmu(trace_start, trace_end); printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end); free(trace_func); @@ -323,11 +321,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu) #endif RunElfInit(elf_header, emu); } - if(box64_dynarec && strcmp(lib->name, "libfmod.so")==0) { - if (GetGlobalSymbolStartEnd(lib->maplib?lib->maplib:my_context->maplib, "FSOUND_Mixer_FPU_Ramp", &fmod_smc_start, &fmod_smc_end)) { - printf_log(LOG_INFO, "Detected libfmod with potential SMC part, applying workaround in Dynarec\n"); - } - } return 0; } @@ -451,22 +444,22 @@ int IsSameLib(library_t* lib, const char* path) free(name); return ret; } -int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end) +int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local) { if(!name[0] || !lib->active) return 0; khint_t k; // check first if already in the map - k = kh_get(bridgemap, lib->bridgemap, name); + k = kh_get(bridgemap, lib->bridgemap, VersionnedName(name, version, vername)); if(k!=kh_end(lib->bridgemap)) { *start = kh_value(lib->bridgemap, k).start; *end = kh_value(lib->bridgemap, k).end; return 1; } // get a new symbol - if(lib->get(lib, name, start, end)) { + if(lib->get(lib, name, start, end, version, vername, local)) { *end += *start; // lib->get(...) gives size, not end - char* symbol = strdup(name); + char* symbol = strdup(VersionnedName(name, version, vername)); int ret; k = kh_put(bridgemap, lib->bridgemap, symbol, &ret); kh_value(lib->bridgemap, k).name = symbol; @@ -477,22 +470,22 @@ int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uin // nope return 0; } -int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end) +int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local) { if(!name[0] || !lib->active) return 0; khint_t k; // get a new symbol - if(lib->getnoweak(lib, name, start, end)) { + if(lib->getnoweak(lib, name, start, end, version, vername, local)) { *end += *start; // lib->get(...) gives size, not end // check if already in the map - k = kh_get(bridgemap, lib->bridgemap, name); + k = kh_get(bridgemap, lib->bridgemap, VersionnedName(name, version, vername)); if(k!=kh_end(lib->bridgemap)) { *start = kh_value(lib->bridgemap, k).start; *end = kh_value(lib->bridgemap, k).end; return 1; } - char* symbol = strdup(name); + char* symbol = strdup(VersionnedName(name, version, vername)); int ret; k = kh_put(bridgemap, lib->bridgemap, symbol, &ret); kh_value(lib->bridgemap, k).name = symbol; @@ -503,22 +496,22 @@ int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star // nope return 0; } -int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end) +int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local) { if(!name[0] || !lib->active) return 0; khint_t k; // check first if already in the map - k = kh_get(bridgemap, lib->bridgemap, name); + k = kh_get(bridgemap, lib->bridgemap, VersionnedName(name, version, vername)); if(k!=kh_end(lib->bridgemap)) { *start = kh_value(lib->bridgemap, k).start; *end = kh_value(lib->bridgemap, k).end; return 1; } // get a new symbol - if(lib->getlocal(lib, name, start, end)) { + if(lib->getlocal(lib, name, start, end, version, vername, local)) { *end += *start; // lib->get(...) gives size, not end - char* symbol = strdup(name); + char* symbol = strdup(VersionnedName(name, version, vername)); int ret; k = kh_put(bridgemap, lib->bridgemap, symbol, &ret); kh_value(lib->bridgemap, k).name = symbol; @@ -536,14 +529,10 @@ int GetElfIndex(library_t* lib) return lib->priv.n.elf_index; } -int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size) +static int getSymbolInDataMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size) { - if(!lib->active) - return 0; - khint_t k; void* symbol; - // check in datamap - k = kh_get(datamap, lib->datamap, name); + khint_t k = kh_get(datamap, lib->datamap, name); if (k!=kh_end(lib->datamap)) { symbol = dlsym(lib->priv.w.lib, kh_key(lib->datamap, k)); if(symbol) { @@ -584,8 +573,13 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add return 1; } } + return 0; +} +static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size) +{ + void* symbol; // check in mysymbolmap - k = kh_get(symbolmap, lib->mysymbolmap, name); + khint_t k = kh_get(symbolmap, lib->mysymbolmap, name); if (k!=kh_end(lib->mysymbolmap)) { char buff[200]; if(lib->altmy) @@ -680,6 +674,23 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add return 0; } +int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int version, const char* vername, int local) +{ + if(!lib->active) + return 0; + // check in datamaps (but no version, it's not handled there) + if(getSymbolInDataMaps(lib, name, noweak, addr, size)) + return 1; + + if(getSymbolInSymbolMaps(lib, VersionnedName(name, version, vername), noweak, addr, size)) + return 1; + + if(getSymbolInSymbolMaps(lib, name, noweak, addr, size)) + return 1; + + return 0; +} + int GetNeededLibN(library_t* lib) { return lib->needed.size; } diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h index 7e8aa4d4..606e47f8 100755 --- a/src/librarian/library_private.h +++ b/src/librarian/library_private.h @@ -97,6 +97,6 @@ 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); // Add bridges to functions +int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int version, const char* vername, int local); // Add bridges to functions #endif //__LIBRARY_PRIVATE_H_ diff --git a/src/librarian/symbols.c b/src/librarian/symbols.c new file mode 100644 index 00000000..adf6020a --- /dev/null +++ b/src/librarian/symbols.c @@ -0,0 +1,233 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <pthread.h> + +#include "debug.h" +#include "x64emu.h" +#include "box64context.h" +#include "symbols.h" +#include "dictionnary.h" + +typedef struct onesymbol_s { + uintptr_t offs; + uint32_t sz; + // need to track type of symbol? + // need to track origin? +} onesymbol_t; + +typedef struct versymbol_s { + int version; // -1 = no-version, 0=local, 1=global, X=versionned + const char* vername; // NULL or version name if version=X + onesymbol_t sym; +} versymbol_t; + +typedef struct versymbols_s { + int sz; + int cap; + versymbol_t *syms; +} versymbols_t; + +KHASH_MAP_IMPL_STR(mapsymbols, versymbols_t); + +kh_mapsymbols_t* NewMapSymbols() +{ + kh_mapsymbols_t* map = kh_init(mapsymbols); + return map; +} + +void FreeMapSymbols(kh_mapsymbols_t** map) +{ + if(!map || !(*map)) + return; + versymbols_t *v; + kh_foreach_value_ref(*map, v, free(v->syms);); + + kh_destroy(mapsymbols, *map); + *map = NULL; +} + +// Exact same version (ver<2 or vername if ver>=2) +static int SameVersion(versymbol_t* s, int ver, const char* vername) +{ + if(ver<2) + return (s->version == ver)?1:0; + if(s->vername && !strcmp(s->vername, vername)) + return 1; + return 0; + +} + +static versymbol_t* FindVersionLocal(versymbols_t* s) +{ + if(!s || !s->sz) + return NULL; + for (int i=0; i<s->sz; ++i) + if(s->syms[i].version==0) + return &s->syms[i]; + return NULL; +} +static versymbol_t* FindNoVersion(versymbols_t* s) +{ + if(!s || !s->sz) + return NULL; + for (int i=0; i<s->sz; ++i) + if(s->syms[i].version==-1) + return &s->syms[i]; + return NULL; +} +static versymbol_t* FindVersionGlobal(versymbols_t* s) +{ + if(!s || !s->sz) + return NULL; + for (int i=0; i<s->sz; ++i) + if(s->syms[i].version==1) + return &s->syms[i]; + return NULL; +} +static versymbol_t* FindVersion(versymbols_t* s, const char* vername) +{ + if(!s || !s->sz) + return NULL; + for (int i=0; i<s->sz; ++i) + if(s->syms[i].vername && !strcmp(s->syms[i].vername, vername)) + return &s->syms[i]; + return NULL; +} +static versymbol_t* FindFirstVersion(versymbols_t* s) +{ + if(!s || !s->sz) + return NULL; + for (int i=0; i<s->sz; ++i) + if(s->syms[i].version>1) + return &s->syms[i]; + return NULL; +} + +// 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, int local) +{ + if(!s || !s->sz) + return NULL; + versymbol_t* ret = NULL; + if(ver==0) { + if(local) ret = FindVersionLocal(s); + if(!ret) ret = FindNoVersion(s); + if(!ret) ret = FindVersionGlobal(s); + return ret; + } + if(ver==-1) { + if(local) ret = FindVersionLocal(s); + if(!ret) ret = FindNoVersion(s); + if(!ret) ret = FindVersionGlobal(s); + if(!ret) ret = FindFirstVersion(s); + return ret; + } + if(ver==1) { + if(local) ret = FindVersionLocal(s); + if(!ret) ret = FindVersionGlobal(s); + if(!ret) ret = FindNoVersion(s); + if(!ret) ret = FindFirstVersion(s); + return ret; + } + ret = FindVersion(s, vername); + if(local && !ret) FindVersionLocal(s); + 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) +{ + int ret; + khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret); + versymbols_t * v = &kh_val(mapsymbols, k); + 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)) { + v->syms[i].sym.offs = addr; + v->syms[i].sym.sz = sz; + return; + } + // add a new record + if(v->sz == v->cap) { + v->cap+=4; + v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t)); + } + int idx = v->sz++; + v->syms[idx].version = ver; + v->syms[idx].vername = vername; + v->syms[idx].sym.offs = addr; + v->syms[idx].sym.sz = sz; +} + +uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local) +{ + if(!mapsymbols) + return 0; + khint_t k = kh_get(mapsymbols, mapsymbols, name); + if(k==kh_end(mapsymbols)) + return 0; + versymbols_t * v = &kh_val(mapsymbols, k); + versymbol_t * s = MatchVersion(v, ver, vername, local); + if(s) + return s->sym.offs; + return 0; +} + +void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername) +{ + int ret; + khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret); + versymbols_t * v = &kh_val(mapsymbols, k); + 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)) { + return; + } + // add a new record + if(v->sz == v->cap) { + v->cap+=4; + v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t)); + } + int idx = v->sz++; + v->syms[idx].version = ver; + v->syms[idx].vername = vername; + v->syms[idx].sym.offs = addr; + v->syms[idx].sym.sz = sz; +} + +int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local) +{ + if(!mapsymbols) + return 0; + khint_t k = kh_get(mapsymbols, mapsymbols, name); + if(k==kh_end(mapsymbols)) + return 0; + versymbols_t * v = &kh_val(mapsymbols, k); + versymbol_t* s = MatchVersion(v, ver, vername, local); + if(s) { + *start = s->sym.offs; + *end = *start + s->sym.sz; + return 1; + } + return 0; +} + +const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start, uint32_t* sz, const char** vername) +{ + uintptr_t addr = (uintptr_t)p; + versymbols_t *s; + kh_foreach_value_ref(mapsymbols, s, + for(int i=0; i<s->sz; ++i) + if((s->syms[i].sym.offs >= addr) && (s->syms[i].sym.offs+s->syms[i].sym.sz<addr)) { + *start = s->syms[i].sym.offs; + *sz = s->syms[i].sym.sz; + if(vername) + *vername = s->syms[i].vername; + return kh_key(mapsymbols, __i); + } + ); + return NULL; +} diff --git a/src/main.c b/src/main.c index 623b9ba1..2ef08494 100755 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ #include "x64trace.h" #include "librarian.h" #include "x64run.h" +#include "symbols.h" box64context_t *my_context = NULL; int box64_log = LOG_INFO; //LOG_NONE; @@ -553,7 +554,7 @@ void setupTraceInit() if(s_trace_start || s_trace_end) SetTraceEmu(s_trace_start, s_trace_end); } else { - if (GetSymbolStartEnd(GetMapSymbol(my_context->maplib), p, &s_trace_start, &s_trace_end)) { + if (GetSymbolStartEnd(GetMapSymbol(my_context->maplib), p, &s_trace_start, &s_trace_end, -1, NULL, -1)) { 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 { @@ -594,10 +595,10 @@ void setupTrace() } } } else { - if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end)) { + if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, 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)) { + } else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, 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 { @@ -987,9 +988,9 @@ int main(int argc, const char **argv, const char **env) { // export symbols AddSymbols(my_context->maplib, GetMapSymbol(my_context->maplib), GetWeakSymbol(my_context->maplib), GetLocalSymbol(my_context->maplib), elf_header); if(wine_preloaded) { - uintptr_t wineinfo = FindSymbol(GetMapSymbol(my_context->maplib), "wine_main_preload_info"); - if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbol(my_context->maplib), "wine_main_preload_info"); - if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbol(my_context->maplib), "wine_main_preload_info"); + uintptr_t wineinfo = FindSymbol(GetMapSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1); + if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1); + if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1); if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");} else { *(void**)wineinfo = get_wine_prereserve(); @@ -1001,11 +1002,8 @@ int main(int argc, const char **argv, const char **env) { } // pre-load lib if needed if(ld_preload.size) { - for (int i=0; i<ld_preload.size; ++i) { - if(AddNeededLib(NULL, NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) { - if(!strstr(ld_preload.paths[i], "vgpreload_")) - printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]); - } + if(AddNeededLib(NULL, NULL, NULL, 0, (const char**)ld_preload.paths, ld_preload.size, my_context, emu)) { + printf_log(LOG_INFO, "Warning, cannot pre-load a lib\n"); } } FreeCollection(&ld_preload); diff --git a/src/wrapped/wrappedlib_init.h b/src/wrapped/wrappedlib_init.h index a3a2049c..d991f8a2 100755 --- a/src/wrapped/wrappedlib_init.h +++ b/src/wrapped/wrappedlib_init.h @@ -130,21 +130,29 @@ int FUNC(_init)(library_t* lib, box64context_t* box64) for (int i=0; i<cnt; ++i) { k = kh_put(symbolmap, lib->symbolmap, MAPNAME(symbolmap)[i].name, &ret); kh_value(lib->symbolmap, k) = MAPNAME(symbolmap)[i].w; + if(strchr(MAPNAME(symbolmap)[i].name, '@')) + AddDictionnary(box64->versym, MAPNAME(symbolmap)[i].name); } cnt = sizeof(MAPNAME(wsymbolmap))/sizeof(map_onesymbol_t); for (int i=0; i<cnt; ++i) { k = kh_put(symbolmap, lib->wsymbolmap, MAPNAME(wsymbolmap)[i].name, &ret); kh_value(lib->wsymbolmap, k) = MAPNAME(wsymbolmap)[i].w; + if(strchr(MAPNAME(wsymbolmap)[i].name, '@')) + AddDictionnary(box64->versym, MAPNAME(wsymbolmap)[i].name); } cnt = sizeof(MAPNAME(mysymbolmap))/sizeof(map_onesymbol_t); for (int i=0; i<cnt; ++i) { k = kh_put(symbolmap, lib->mysymbolmap, MAPNAME(mysymbolmap)[i].name, &ret); kh_value(lib->mysymbolmap, k) = MAPNAME(mysymbolmap)[i].w; + if(strchr(MAPNAME(mysymbolmap)[i].name, '@')) + AddDictionnary(box64->versym, MAPNAME(mysymbolmap)[i].name); } cnt = sizeof(MAPNAME(stsymbolmap))/sizeof(map_onesymbol_t); for (int i=0; i<cnt; ++i) { k = kh_put(symbolmap, lib->stsymbolmap, MAPNAME(stsymbolmap)[i].name, &ret); kh_value(lib->stsymbolmap, k) = MAPNAME(stsymbolmap)[i].w; + if(strchr(MAPNAME(stsymbolmap)[i].name, '@')) + AddDictionnary(box64->versym, MAPNAME(stsymbolmap)[i].name); } cnt = sizeof(MAPNAME(symbol2map))/sizeof(map_onesymbol2_t); for (int i=0; i<cnt; ++i) { @@ -152,6 +160,8 @@ int FUNC(_init)(library_t* lib, box64context_t* box64) kh_value(lib->symbol2map, k).name = MAPNAME(symbol2map)[i].name2; kh_value(lib->symbol2map, k).w = MAPNAME(symbol2map)[i].w; kh_value(lib->symbol2map, k).weak = MAPNAME(symbol2map)[i].weak; + if(strchr(MAPNAME(symbol2map)[i].name, '@')) + AddDictionnary(box64->versym, MAPNAME(symbol2map)[i].name); } cnt = sizeof(MAPNAME(datamap))/sizeof(map_onedata_t); for (int i=0; i<cnt; ++i) { @@ -194,7 +204,7 @@ int FUNC(_fini)(library_t* lib) return 1; } -int FUNC(_get)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) +int FUNC(_get)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) { uintptr_t addr = 0; uintptr_t size = 0; @@ -202,7 +212,7 @@ int FUNC(_get)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) void* symbol = NULL; #endif //PRE - if (!getSymbolInMaps(lib, name, 0, &addr, &size)) { + if (!getSymbolInMaps(lib, name, 0, &addr, &size, version, vername, local)) { #ifdef CUSTOM_FAIL CUSTOM_FAIL #else @@ -217,7 +227,7 @@ int FUNC(_get)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) return 1; } -int FUNC(_getnoweak)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz) +int FUNC(_getnoweak)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) { uintptr_t addr = 0; uintptr_t size = 0; @@ -225,7 +235,7 @@ int FUNC(_getnoweak)(library_t* lib, const char* name, uintptr_t *offs, uintptr_ void* symbol = NULL; #endif //PRE - if (!getSymbolInMaps(lib, name, 1, &addr, &size)) { + if (!getSymbolInMaps(lib, name, 1, &addr, &size, version, vername, local)) { #ifdef CUSTOM_FAIL CUSTOM_FAIL #else diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 0d9aa8cb..5655616c 100755 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -42,7 +42,7 @@ char* my_dlerror(x64emu_t* emu) EXPORT; void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) EXPORT; int my_dlclose(x64emu_t* emu, void *handle) EXPORT; int my_dladdr(x64emu_t* emu, void *addr, void *info) EXPORT; -void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, void *version) EXPORT; +void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) EXPORT; int my_dlinfo(x64emu_t* emu, void* handle, int request, void* info) EXPORT; #define LIBNAME libdl @@ -97,7 +97,8 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) } dlopened = (GetLibInternal(rfilename)==NULL); // Then open the lib - if(AddNeededLib(NULL, NULL, NULL, is_local, rfilename, emu->context, emu)) { + const char* libs[] = {rfilename}; + if(AddNeededLib(NULL, NULL, NULL, is_local, libs, 1, emu->context, emu)) { printf_log(LOG_INFO, "Warning: Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag); if(!dl->last_error) dl->last_error = malloc(129); @@ -152,7 +153,7 @@ char* my_dlerror(x64emu_t* emu) KHASH_SET_INIT_INT(libs); -int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end) +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) { if(!lib) return 0; @@ -162,23 +163,23 @@ int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymb int ret; kh_put(libs, collection, (uintptr_t)lib, &ret); // look in the library itself - if(lib->get(lib, rsymbol, start, end)) + if(lib->get(lib, rsymbol, start, end, version, vername, 1)) return 1; // look in other libs int n = GetNeededLibN(lib); for (int i=0; i<n; ++i) { library_t *l = GetNeededLib(lib, i); - if(recursive_dlsym_lib(collection, l, rsymbol, start, end)) + if(recursive_dlsym_lib(collection, l, rsymbol, start, end, version, vername)) return 1; } return 0; } -int my_dlsym_lib(library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end) +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); + int ret = recursive_dlsym_lib(collection, lib, rsymbol, start, end, version, vername); kh_destroy(libs, collection); return ret; @@ -196,7 +197,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) printf_log(LOG_DEBUG, "Call to dlsym(%p, \"%s\")\n", handle, rsymbol); if(handle==NULL) { // special case, look globably - if(GetGlobalSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end)) { + if(GetGlobalSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end, NULL, -1, NULL)) { if(dlsym_error && box64_log<LOG_DEBUG) { printf_log(LOG_NONE, "%p\n", (void*)start); } @@ -212,8 +213,8 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } if(handle==(void*)0xFFFFFFFF) { // special case, look globably but no self (RTLD_NEXT) - elfheader_t *elf = FindElfAddress(emu->context, *(uint32_t*)R_RSP); // use return address to guess "self" - if(GetNoSelfSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end, elf)) { + elfheader_t *elf = FindElfAddress(emu->context, *(uintptr_t*)R_RSP); // use return address to guess "self" + if(GetNoSelfSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end, elf, -1, NULL)) { if(dlsym_error && box64_log<LOG_DEBUG) { printf_log(LOG_NONE, "%p\n", (void*)start); } @@ -249,7 +250,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) return NULL; } if(dl->libs[nlib]) { - if(my_dlsym_lib(dl->libs[nlib], rsymbol, &start, &end)==0) { + if(my_dlsym_lib(dl->libs[nlib], rsymbol, &start, &end, -1, NULL)==0) { // not found if(dlsym_error && box64_log<LOG_DEBUG) { printf_log(LOG_NONE, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->libs[nlib]), rsymbol); @@ -262,19 +263,19 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) } } else { // still usefull? - if(GetSymbolStartEnd(GetLocalSymbol(emu->context->maplib), rsymbol, &start, &end)) { + if(GetSymbolStartEnd(GetLocalSymbol(emu->context->maplib), rsymbol, &start, &end, -1, NULL, 0)) { if(dlsym_error && box64_log<LOG_DEBUG) { printf_log(LOG_NONE, "%p\n", (void*)start); } return (void*)start; } - if(GetSymbolStartEnd(GetWeakSymbol(emu->context->maplib), rsymbol, &start, &end)) { + if(GetSymbolStartEnd(GetWeakSymbol(emu->context->maplib), rsymbol, &start, &end, -1, NULL, 0)) { if(dlsym_error && box64_log<LOG_DEBUG) { printf_log(LOG_NONE, "%p\n", (void*)start); } return (void*)start; } - if(GetSymbolStartEnd(GetMapSymbol(emu->context->maplib), rsymbol, &start, &end)) { + if(GetSymbolStartEnd(GetMapSymbol(emu->context->maplib), rsymbol, &start, &end, -1, NULL, 0)) { if(dlsym_error && box64_log<LOG_DEBUG) { printf_log(LOG_NONE, "%p\n", (void*)start); } @@ -352,16 +353,117 @@ int my_dladdr(x64emu_t* emu, void *addr, void *i) printf_log(LOG_DEBUG, " dladdr return saddr=%p, fname=\"%s\", sname=\"%s\"\n", info->dli_saddr, info->dli_sname?info->dli_sname:"", info->dli_fname?info->dli_fname:""); return (info->dli_sname)?1:0; // success is non-null here... } -void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, void *version) +void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) { dlprivate_t *dl = emu->context->dlprivate; - CLEARERR - //void *dlvsym(void *handle, char *symbol, char *version); + int version = (vername)?2:-1; + uintptr_t start, end; char* rsymbol = (char*)symbol; - char* rversion = (char*)version; - printf_log(LOG_INFO, "Warning: unimplement call to dlvsym(%p, %s, %s), fallback to dlsym\n", handle, rsymbol, rversion); - - return my_dlsym(emu, handle, symbol); + CLEARERR + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "Call to dlvsym(%p, %s, %s) :", handle, rsymbol, vername?vername:"(nil)"); + } + printf_log(LOG_DEBUG, "Call to dlvsym(%p, \"%s\", %s)\n", handle, rsymbol, vername?vername:"(nil)"); + if(handle==NULL) { + // special case, look globably + if(GetGlobalSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end, NULL, version, vername)) { + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)start); + } + return (void*)start; + } + if(!dl->last_error) + dl->last_error = malloc(129); + snprintf(dl->last_error, 129, "Symbol \"%s\" version %s not found in %p)\n", rsymbol, vername?vername:"(nil)", handle); + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", NULL); + } + return NULL; + } + if(handle==(void*)0xFFFFFFFF) { + // special case, look globably but no self (RTLD_NEXT) + elfheader_t *elf = FindElfAddress(emu->context, *(uintptr_t*)R_RSP); // use return address to guess "self" + if(GetNoSelfSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end, elf, version, vername)) { + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)start); + } + return (void*)start; + } + if(!dl->last_error) + dl->last_error = malloc(129); + snprintf(dl->last_error, 129, "Symbol \"%s\" version %s not found in %p)\n", rsymbol, vername?vername:"(nil)", handle); + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", NULL); + } + return NULL; + } + size_t nlib = (size_t)handle; + --nlib; + // size_t is unsigned + if(nlib>=dl->lib_sz) { + if(!dl->last_error) + dl->last_error = malloc(129); + snprintf(dl->last_error, 129, "Bad handle %p)\n", handle); + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", NULL); + } + return NULL; + } + if(dl->count[nlib]==0) { + if(!dl->last_error) + dl->last_error = malloc(129); + snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle); + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)NULL); + } + return NULL; + } + if(dl->libs[nlib]) { + if(my_dlsym_lib(dl->libs[nlib], rsymbol, &start, &end, version, vername)==0) { + // not found + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, GetNameLib(dl->libs[nlib]), rsymbol, vername?vername:"(nil)"); + } + printf_log(LOG_DEBUG, " Symbol not found\n"); + if(!dl->last_error) + dl->last_error = malloc(129); + snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p(%s)", rsymbol, handle, GetNameLib(dl->libs[nlib])); + return NULL; + } + } else { + // still usefull? + if(GetSymbolStartEnd(GetLocalSymbol(emu->context->maplib), rsymbol, &start, &end, version, vername, 1)) { + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)start); + } + return (void*)start; + } + if(GetSymbolStartEnd(GetWeakSymbol(emu->context->maplib), rsymbol, &start, &end, version, vername, 1)) { + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)start); + } + return (void*)start; + } + if(GetSymbolStartEnd(GetMapSymbol(emu->context->maplib), rsymbol, &start, &end, version, vername, 1)) { + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)start); + } + return (void*)start; + } + // not found + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, "Self", rsymbol, vername?vername:"(nil)"); + } + printf_log(LOG_DEBUG, " Symbol not found\n"); + if(!dl->last_error) + dl->last_error = malloc(129); + snprintf(dl->last_error, 129, "Symbol \"%s\" version %s not found in %p)\n", rsymbol, vername?vername:"(nil)", handle); + return NULL; + } + if(dlsym_error && box64_log<LOG_DEBUG) { + printf_log(LOG_NONE, "%p\n", (void*)start); + } + return (void*)start; } typedef struct link_map_s { |