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/librarian | |
| parent | 55720342adbf22ba318a66b30ed9ea6ec789b032 (diff) | |
| download | box64-f8a969d43ed26e64d21238ead0e9512360fb1fdd.tar.gz box64-f8a969d43ed26e64d21238ead0e9512360fb1fdd.zip | |
Reworked elfloader, handle versionned symbols now
Diffstat (limited to 'src/librarian')
| -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 |
6 files changed, 462 insertions, 203 deletions
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; +} |