#include #include #include #include #include "debug.h" #include "librarian.h" #include "librarian_private.h" #include "library.h" #include "library_private.h" #include "x64emu.h" #include "box64context.h" #include "elfloader.h" #ifdef BOX32 #include "box32.h" #endif #include "bridge.h" KHASH_MAP_IMPL_INT(mapoffsets, cstr_t); lib_t *NewLibrarian(box64context_t* context) { lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t)); maplib->mapoffsets = kh_init(mapoffsets); maplib->globaldata = NewMapSymbols(); return maplib; } void FreeLibrarian(lib_t **maplib, x64emu_t *emu) { // should that be in reverse order? if(!maplib || !*maplib) return; library_t* owner = (*maplib)->owner; (*maplib)->owner = NULL; // to avoid recursive free... /*for(int i=0; i<(*maplib)->libsz; ++i) { printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); DecRefCount(&(*maplib)->libraries[i], emu); }*/ box_free((*maplib)->libraries); (*maplib)->libraries = NULL; if((*maplib)->mapoffsets) { kh_destroy(mapoffsets, (*maplib)->mapoffsets); } FreeMapSymbols(&(*maplib)->globaldata); (*maplib)->libsz = (*maplib)->libcap = 0; box_free(*maplib); *maplib = NULL; } box64context_t* GetLibrarianContext(lib_t* maplib) { return my_context; } kh_mapsymbols_t* GetGlobalData(lib_t* maplib) { return maplib->globaldata; } library_t* getLib(lib_t* maplib, const char* path) { for(int i=0; ilibsz; ++i) { library_t *lib = maplib->libraries[i]; if(IsSameLib(lib, path)) { return lib; } } return NULL; } static int libraryInMapLib(lib_t* maplib, library_t* lib) { if(!maplib) return 0; for(int i=0; ilibsz; ++i) if(maplib->libraries[i]==lib) return 1; return 0; } 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**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*)); } maplib->libraries[maplib->libsz] = lib; ++maplib->libsz; } void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref) { if(libraryInMapLib(maplib, lib)) return; if (maplib->libsz == maplib->libcap) { maplib->libcap += 8; maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*)); } // find insersion point int point = ref?maplib->libsz:0; if(ref) for(int i=0; ilibsz; ++i) if(maplib->libraries[i]==ref) { point = i; i = maplib->libsz; } if(pointlibsz) memmove(&maplib->libraries[point+1], &maplib->libraries[point], sizeof(library_t*)*(maplib->libsz-point)); maplib->libraries[point] = lib; ++maplib->libsz; } static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src) { if(!src) return; library_t *owner = src->owner; for(int i=0; ilibsz; ++i) { library_t* lib = src->libraries[i]; if(!lib || libraryInMapLib(dest, lib)) continue; MapLibAddLib(dest, lib); } if(lib_src == owner) FreeLibrarian(&src, NULL); } void MapLibRemoveLib(lib_t* maplib, library_t* lib) { if(!maplib || !lib) return; int idx = 0; while(idxlibsz && maplib->libraries[idx]!=lib) ++idx; if(idx==maplib->libsz) //not found return; --maplib->libsz; if(idx!=(maplib->libsz)) memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx)); maplib->libraries[maplib->libsz] = NULL; } static void MapLibRemoveMapLib(lib_t* dest, lib_t* src) { if(!src) return; //library_t *owner = src->owner; for(int i=0; ilibsz; ++i) { library_t* lib = src->libraries[i]; if(!lib || !libraryInMapLib(dest, lib)) continue; MapLibRemoveLib(dest, lib); if(lib->maplib && src!=lib->maplib && dest!=lib->maplib) { MapLibRemoveMapLib(dest, lib->maplib); if(lib->maplib && src==my_context->local_maplib) lib->maplib = NULL; } } } void promoteLocalLibGlobal(library_t* lib) { if(!lib || !my_context) return; // promote lib from local to global... // for add the depending local libs... if(lib->maplib && !lib->maplib_ref) { lib_t* maplib = lib->maplib; lib->maplib = NULL; MapLibAddMapLib(my_context->maplib, lib, maplib); } lib->maplib = NULL; lib->maplib_ref = 0; if(!libraryInMapLib(my_context->maplib, lib)) MapLibAddLib(my_context->maplib, lib); MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib); } int isLibLocal(library_t* lib) { if(!lib || !my_context) return 0; return libraryInMapLib(my_context->local_maplib, lib); } static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { const char* path = needed->names[n]; printf_dump(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":""); // first check if lib is already loaded library_t *lib = getLib(my_context->maplib, path); if(lib) { IncRefCount(lib, emu); // increment cntref needed->libs[n] = lib; if(local && *maplib) MapLibAddLib(*maplib, lib); printf_dump(LOG_DEBUG, "Already present in maplib => success\n"); return 0; } // check also in the local loaded lib lib = getLib(my_context->local_maplib, path); if(lib) { printf_dump(LOG_DEBUG, "Already present in local_maplib => success\n"); needed->libs[n] = lib; IncRefCount(lib, emu); // increment cntref if(local) { // add lib to maplib... if(*maplib) { MapLibAddLib(*maplib, lib); } } else { // promote lib from local to global... promoteLocalLibGlobal(lib); } return 0; } // load a new one needed->libs[n] = lib = NewLibrary(path, box64, verneeded); if(!lib) { printf_dump(LOG_DEBUG, "Faillure to create lib => fail\n"); return 1; //Error } // add lib now if(local) { MapLibAddLib(my_context->local_maplib, lib); if(*maplib) { MapLibAddLib(*maplib, lib); } else { lib->maplib = NewLibrarian(box64); MapLibAddLib(lib->maplib, lib); } } else { MapLibAddLib(my_context->maplib, lib); } if(!*maplib) *maplib = (local)?lib->maplib:my_context->maplib; if(local && !lib->maplib) { lib->maplib = *maplib; lib->maplib_ref = 1; } if(AddSymbolsLibrary(*maplib, lib, emu)) { // also add needed libs printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n"); return 1; } if (lib->type == LIB_EMULATED) { // Need to add library to the linkmap (put here so the link is ordered) #ifdef BOX32 if(box64_is32bits) { linkmap32_t *lm = addLinkMapLib32(lib); if(!lm) { // Crashed already printf_dump(LOG_DEBUG, "Failure to add lib linkmap\n"); return 1; } lm->l_addr = (Elf32_Addr)to_ptrv(GetElfDelta(lib->e.elf)); lm->l_name = to_cstring(lib->name); lm->l_ld = to_ptrv(GetDynamicSection(lib->e.elf)); } else #endif { linkmap_t *lm = addLinkMapLib(lib); if(!lm) { // Crashed already printf_dump(LOG_DEBUG, "Failure to add lib linkmap\n"); return 1; } lm->l_addr = (Elf64_Addr)GetElfDelta(lib->e.elf); lm->l_name = lib->name; lm->l_ld = GetDynamicSection(lib->e.elf); } //TODO: it seems to never be removed! } IncRefCount(lib, emu); return 0; } int AddNeededLib_init(lib_t* maplib, int local, int bindnow, int deepbind, library_t* lib, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { if(!lib) // no lib, error is already detected, no need to return a new one return 0; if(!maplib) maplib = (local)?lib->maplib:my_context->maplib; elfheader_t* mainelf = GetElf(lib); if(!mainelf) { // It's a native libs, nothing else to do } else { // it's an emulated lib, // load dependancies and launch init sequence if(LoadNeededLibs(mainelf, maplib, local, bindnow, deepbind, box64, emu)) { printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); return 1; } // finalize the lib if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, deepbind, emu)) { printf_dump(LOG_DEBUG, "Failure to finalizing lib => fail\n"); return 1; } } // success printf_dump(LOG_DEBUG, "Created lib and added to maplib => success\n"); return 0; } void AddNeededLib_remove(lib_t* maplib, int local, library_t** lib, box64context_t* box64, x64emu_t* emu) { if(!lib || !*lib) // no lib, error is already detected, no need to return a new one return; if(!maplib) maplib = (local)?(*lib)->maplib:my_context->maplib; DecRefCount(lib, emu); } EXPORTDYN int AddNeededLib(lib_t* maplib, int local, int bindnow, int deepbind, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { if(!needed) // no needed libs, no problems return 0; box64_mapclean = 0; int ret = 0; // Add libs and symbol for(int i=0; isize; ++i) { if(AddNeededLib_add(&maplib, local, needed, i, verneeded, box64, emu)) { printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]); ret = 1; } } // error while loadind lib, unload... if(ret) { return ret; } // add dependant libs and init them int n = needed->size; for (int i=0; ilibs[n-i-1], verneeded, box64, emu)) { printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]); ret = 1; } // all done if(BOX64ENV(allow_missing_libs)) return 0; return ret; } EXPORTDYN void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu) { if(!needed) // no needed libs, no problems return; for(int i=0; isize; ++i) { if (BOX64ENV(log)>=LOG_DEBUG && needed->libs[i]) printf_dump(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]); AddNeededLib_remove(maplib, local, &needed->libs[i], box64, emu); } } library_t* GetLibMapLib(lib_t* maplib, const char* name) { printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); return getLib(maplib, name); } library_t* GetLibInternal(const char* name) { printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name); library_t* lib = getLib(my_context->maplib, name); if(!lib) lib = getLib(my_context->local_maplib, name); return lib; } EXPORTDYN uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername, int veropt) { uintptr_t start = 0, end = 0; if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, veropt, NULL)) return start; return 0; } static int isLocal(elfheader_t* self, library_t* l) { if(GetElf(l)==self) return 1; return 0; } static void CheckNeededLibs(needed_libs_t* needed) { while(needed->nb_donesize) { library_t* lib = needed->libs[needed->nb_done++]; if(lib) { int n = GetNeededLibsN(lib); char** names = GetNeededLibsNames(lib); for (int i=0; ipreload) for(int i=0; ipreload->size; ++i) if(self!=GetElf(my_context->preload->libs[i]) && GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { return 1; } if(maplib==my_context->maplib) { // search non-weak symbol if(self!=my_context->elfs[0] && (sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) { if(elfsym) *elfsym = sym; return 1; } } // search in global symbols if(maplib) { for(int i=0; ilibsz; ++i) { if(self!=GetElf(maplib->libraries[i]) && GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) return 1; } } // GetSymbolStartEnd should not change start/end if symbol is not found if(self!=my_context->elfs[0] && (sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) { if(elfsym) *elfsym = sym; weak = 1; } if(maplib) for(int i=0; ilibsz; ++i) { if(self!=GetElf(maplib->libraries[i]) && GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { weak = 1; } } // nope, not found return weak; } static int isLibPreloaded(library_t* lib) { if(my_context->preload) for(int i=0; ipreload->size; ++i) if(my_context->preload->libs[i] == lib) return 1; return 0; } int GetNextSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym) { assert(self); // need self for this one int weak = 0; int next = 0; void* sym; // search in needed libs from preloaded first, in order if(my_context->preload) for(int i=0; ipreload->size; ++i) { if(next) { if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { return 1; } if(GetLibWeakSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { return 1; } } if(self==GetElf(my_context->preload->libs[i])) { next = 1; } } if(maplib==my_context->maplib) { if(next) { if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) { if(elfsym) *elfsym = sym; return 1; } if((sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) { if(elfsym) *elfsym = sym; return 1; } } if(self==my_context->elfs[0]) { next = 1; } } // search in global symbols if(maplib) { for(int i=0; ilibsz; ++i) if(!isLibPreloaded(maplib->libraries[i])) { if(next) { if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { return 1; } if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) { return 1; } } if(self==GetElf(maplib->libraries[i])) next = 1; } } return 0; } static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym) { int weak = 0; size_t size = 0; void* sym; // search in needed libs from preloaded first, in order if(my_context->preload) for(int i=0; ipreload->size; ++i) if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), veropt, elfsym)) { return 1; } if(maplib==my_context->maplib) { // search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self) if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { if(elfsym) *elfsym = sym; return 1; } } // search in global symbols if(maplib) { for(int i=0; ilibsz; ++i) { if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) return 1; } } // GetSymbolStartEnd should not change start/end if symbol is not found if((sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { if(elfsym) *elfsym = sym; weak = 1; } if(maplib) for(int i=0; ilibsz; ++i) { if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) { weak = 1; } } // nope, not found return weak; } #ifndef STATICBUILD void** my_GetGTKDisplay(); void** my_GetGthreadsGotInitialized(); #endif int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym) { if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, &version, &vername, &veropt, elfsym)) { if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size uintptr_t start2, end2; char* buff = (char*)box_malloc(strlen(name) + strlen("_END") + 1); strcpy(buff, name); strcat(buff, "_END"); if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, &version, &vername, &veropt, elfsym)) { if(end2>*end && start2==end2) *end = end2; } box_free(buff); } return 1; } #ifndef STATICBUILD // some special case symbol, defined inside box64 itself if(!strcmp(name, "gdk_display") && !BOX64ENV(nogtk)) { *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") && !BOX64ENV(nogtk)) { *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; } #endif // not found... return 0; } static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym) { int weak = 0; size_t size = 0; void* sym; // search in needed libs from preloaded first, in order if(my_context->preload) for(int i=0; ipreload->size; ++i) if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), veropt, elfsym)) return 1; // search non-weak symbol, from older to newer (first GLOBAL object wins) if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { if(elfsym) *elfsym = sym; return 1; } if(maplib) for(int i=0; ilibsz; ++i) { if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) return 1; } // check with default version... int ok = 0; // GetSymbolStartEnd should not change start/end if symbol is not found if(( sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) { if(elfsym) *elfsym = sym; ok = 1; } if(maplib) for(int i=0; ilibsz; ++i) { if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) ok = 1; } // nope, not found return ok; } int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym) { if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, &version, &vername, &veropt, elfsym)) { if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size uintptr_t start2, end2; char* buff = (char*)box_malloc(strlen(name) + strlen("_END") + 1); strcpy(buff, name); strcat(buff, "_END"); if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, &version, &vername, &veropt, elfsym)) { if(end2>*end && start2==end2) *end = end2; } box_free(buff); } return 1; } #ifndef STATICBUILD // some special case symbol, defined inside box64 itself if(!strcmp(name, "gdk_display") && !BOX64ENV(nogtk)) { *start = (uintptr_t)my_GetGTKDisplay(); *end = *start+sizeof(void*); if(elfsym) *elfsym = NULL; printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start); return 1; } if(!strcmp(name, "g_threads_got_initialized") && !BOX64ENV(nogtk)) { *start = (uintptr_t)my_GetGthreadsGotInitialized(); *end = *start+sizeof(int); if(elfsym) *elfsym = NULL; printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start); return 1; } #endif // not found... return 0; } elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername, int veropt) { uintptr_t start = 0; uintptr_t end = 0; size_t size = 0; int weak = 0; elfheader_t* ret = NULL; // check with default version... if(ElfGetGlobalSymbolStartEnd(my_context->elfs[0], &start, &end, name, &version, &vername, 1, &veropt)) return my_context->elfs[0]; for(int i=0; ilibsz; ++i) { if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) { elfheader_t* h = GetElf(maplib->libraries[i]); if(!h) { printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i])); return NULL; } if(weak) ret = h; else return h; } } if(ElfGetWeakSymbolStartEnd(my_context->elfs[0], &start, &end, name, &version, &vername, 1, &veropt)) ret = my_context->elfs[0]; for(int i=0; ilibsz; ++i) { if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) { elfheader_t* h = GetElf(maplib->libraries[i]); if(!h) { printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i])); return NULL; } if(weak) ret = h; else return h; } } // return what has been found (maybe nothing) return ret; } int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt, void** elfsym) { int weak = 0; size_t size = 0; void* sym; // check global GLOB_DAT kind of symbols if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, veropt)) { if(elfsym) *elfsym = NULL; return 1; } // check with default version... if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 1, &veropt))) { if(elfsym) *elfsym = sym; return 1; } for(int i=0; ilibsz; ++i) if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 1, &veropt, elfsym)) return 1; // nope, not found return 0; } int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, int veropt) { uintptr_t start, end; size_t size = 0; int weak; // check with default version... for(int i=0; ilibsz; ++i) if(GetElfIndex(maplib->libraries[i])==-1) if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) return 1; // nope, not found return 0; } int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym) { // check with default version... int weak; size_t size = 0; void* sym; if(my_context->elfs[0]==self || !self) { if((sym = ElfGetLocalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 1, &veropt))) { if(elfsym) *elfsym = sym; return 1; } if(self) return 0; } for(int i=0; ilibsz; ++i) { if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) { if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 1, &veropt, elfsym)) return 1; if(self) return 0; } } return 0; } int GetAnySymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt) { if(!maplib) return 0; for(int i=0; ilibsz; ++i) { elfheader_t* h = GetElf(maplib->libraries[i]); if(h && ElfGetSymbolStartEnd(h, start, end, name, &version, &vername, 1, &veropt)) return 1; } return 0; } int GetSymTabStartEnd(lib_t* maplib, const char* name, uintptr_t* start, uintptr_t* end) { if(!maplib) return 0; for(int i=0; ilibsz; ++i) { elfheader_t* h = GetElf(maplib->libraries[i]); if(box64_is32bits) { if(h && ElfGetSymTabStartEnd32(h, start, end, name)) return 1; } else { if(h && ElfGetSymTabStartEnd64(h, start, end, name)) return 1; } } return 0; } const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib) { // first, search in self... const char* ret = NULL; uintptr_t offs = 0; uint64_t size = 0; elfheader_t* h = FindElfAddress(my_context, (uintptr_t)p); if(h) { ret = FindNearestSymbolName(h, p, &offs, &size); if(start) *start = (void*)offs; if(sz) *sz = size; if(libname) *libname = ElfName(h); if(base) *base = GetBaseAddress(h); if(lib) { if(h == my_context->elfs[0]) *lib = NULL; // main elf else { for(int i=0; imaplib->libsz; ++i) { elfheader_t* head = GetElf(my_context->maplib->libraries[i]); if((head) && (head==h)) { *lib = my_context->maplib->libraries[i]; return ret; } } for(int i=0; ilocal_maplib->libsz; ++i) { elfheader_t* head = GetElf(my_context->local_maplib->libraries[i]); if((head) && (head==h)) { *lib = my_context->local_maplib->libraries[i]; return ret; } } } } return ret; } // TODO: find if cyclic references exists (should also fix MapLibAddMapLib) /* for (int i = 0; i < maplib->libsz; ++i) { // if (maplib == maplib->libraries[i]->maplib) continue; const char *nameInLib = FindSymbolName(maplib->libraries[i]->maplib, p, start, sz, libname, base); if (nameInLib) return nameInLib; } */ return NULL; } void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name) { int ret; khint_t k = kh_put(mapoffsets, maplib->mapoffsets, (uintptr_t)offs, &ret); kh_value(maplib->mapoffsets, k) = (cstr_t)name; } const char* GetNameOffset(lib_t *maplib, void* offs) { if(!maplib || !maplib->mapoffsets) return NULL; khint_t k = kh_get(mapoffsets, maplib->mapoffsets, (uintptr_t)offs); if (k!=kh_end(maplib->mapoffsets)) return kh_value(maplib->mapoffsets, k); return NULL; }