diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-04-10 18:51:07 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-04-10 18:51:16 +0200 |
| commit | 5d6307184941f6f2171153df6a5bb0105fcbce9e (patch) | |
| tree | c0c31a50eac0c58725ba8418154ca48a3c4ae2a9 /src/librarian | |
| parent | 8c98c7b67580b2807d37fa03f59416f4526df770 (diff) | |
| download | box64-5d6307184941f6f2171153df6a5bb0105fcbce9e.tar.gz box64-5d6307184941f6f2171153df6a5bb0105fcbce9e.zip | |
[ELFLOADER] Improved handling of Failed-to-load library (and unloading of libs too)
Diffstat (limited to 'src/librarian')
| -rwxr-xr-x | src/librarian/librarian.c | 80 | ||||
| -rwxr-xr-x | src/librarian/library.c | 81 | ||||
| -rwxr-xr-x | src/librarian/library_private.h | 4 |
3 files changed, 112 insertions, 53 deletions
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index e3cca3de..f704239d 100755 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -39,13 +39,10 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu) library_t* owner = (*maplib)->owner; (*maplib)->owner = NULL; // to avoid recursive free... - // free the memory only. All the uninit logic is elsewhere - - if((*maplib)->ownlibs && (*maplib)->libsz) { for(int i=0; i<(*maplib)->libsz; ++i) { printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); - Free1Library(&(*maplib)->libraries[i], emu); + DecRefCount(&(*maplib)->libraries[i], emu); } } box_free((*maplib)->libraries); @@ -108,8 +105,6 @@ void MapLibAddLib(lib_t* maplib, library_t* lib) ++maplib->libsz; } -static void MapLibRemoveLib(lib_t* maplib, library_t* lib); - static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src) { if(!src) @@ -130,7 +125,7 @@ static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src) FreeLibrarian(&src, NULL); } -static void MapLibRemoveLib(lib_t* maplib, library_t* lib) +void MapLibRemoveLib(lib_t* maplib, library_t* lib) { if(!maplib || !lib) return; @@ -240,9 +235,9 @@ int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, box printf_log(LOG_DEBUG, "Failure to add lib linkmap\n"); return 1; } - lm->l_addr = (Elf64_Addr)GetElfDelta(my_context->elfs[lib->e.elf_index]); + lm->l_addr = (Elf64_Addr)GetElfDelta(lib->e.elf); lm->l_name = lib->name; - lm->l_ld = GetDynamicSection(my_context->elfs[lib->e.elf_index]); + lm->l_ld = GetDynamicSection(lib->e.elf); } return 0; } @@ -254,14 +249,14 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box if(!maplib) maplib = (local)?lib->maplib:my_context->maplib; - int mainelf = GetElfIndex(lib); + elfheader_t* mainelf = GetElf(lib); - if(mainelf==-1) { + 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(box64->elfs[mainelf], maplib, 0, bindnow, box64, emu)) { + if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box64, emu)) { printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n"); return 1; } @@ -296,6 +291,16 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box 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, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu) @@ -311,12 +316,29 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, b ret = 1; } } + // error while loadind lib, unload... + if(ret) { + for(int i=0; i<needed->size; ++i) { + if(box64_log>=LOG_DEBUG && needed->libs[i]) + printf_log(LOG_DEBUG, "Will decref after failed load %s\n", needed->names[i]); + AddNeededLib_remove(maplib, local, &needed->libs[i], box64, emu); + } + return ret; + } // add dependant libs and init them for (int i=0; i<needed->size; ++i) if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], box64, emu)) { printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]); if(!allow_missing_libs) ret = 1; } + // error while loadind lib, unload... + if(ret) { + for(int i=0; i<needed->size; ++i) { + if(box64_log>=LOG_DEBUG && needed->libs[i]) + printf_log(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]); + AddNeededLib_remove(maplib, local, &needed->libs[i], box64, emu); + } + } return ret; } @@ -365,13 +387,13 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u if(go<0) go = 0; // not found... for(int i=go; i<maplib->libsz; ++i) { - if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self)) + if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, globdefver)) if(*start) return 1; } for(int i=go; i<maplib->libsz; ++i) - if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self)) + if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, weakdefver); // loop done, weak symbol found if(weak && *start) @@ -387,13 +409,13 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u weak = 1; } for(int i=0; i<go; ++i) { - if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self)) + if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, globdefver)) if(*start) return 1; } for(int i=0; i<go; ++i) { - if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self)) + if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self)) GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, weakdefver); } if(weak && *start) @@ -518,15 +540,15 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co return my_context->elfs[0]; for(int i=0; i<maplib->libsz; ++i) { if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) { - int idx = GetElfIndex(maplib->libraries[i]); - if(idx==-1) { + 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 = my_context->elfs[idx]; + ret = h; else - return my_context->elfs[idx]; + return h; } } @@ -535,15 +557,15 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co ret = my_context->elfs[0]; for(int i=0; i<maplib->libsz; ++i) { if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) { - int idx = GetElfIndex(maplib->libraries[i]); - if(idx==-1) { + 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 = my_context->elfs[idx]; + ret = h; else - return my_context->elfs[idx]; + return h; } } // return what has been found (maybe nothing) @@ -597,7 +619,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui return 0; } for(int i=0; i<maplib->libsz; ++i) { - if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || my_context->elfs[GetElfIndex(maplib->libraries[i])]==self)) { + if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) { if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver)) if(*start || *end) return 1; @@ -633,15 +655,15 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, c *lib = NULL; // main elf else { for(int i=0; i<my_context->maplib->libsz; ++i) { - int idx = GetElfIndex(my_context->maplib->libraries[i]); - if((idx!=-1) && (my_context->elfs[idx]==h)) { + 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; i<my_context->local_maplib->libsz; ++i) { - int idx = GetElfIndex(my_context->local_maplib->libraries[i]); - if((idx!=-1) && (my_context->elfs[idx]==h)) { + elfheader_t* head = GetElf(my_context->local_maplib->libraries[i]); + if((head) && (head==h)) { *lib = my_context->local_maplib->libraries[i]; return ret; } diff --git a/src/librarian/library.c b/src/librarian/library.c index 6a88b5c2..20b663db 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -416,7 +416,6 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu) { (void)emu; - lib->active = 1; if(lib->type==LIB_EMULATED) { elfheader_t *elf_header = lib->e.elf; // add symbols @@ -465,7 +464,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* int ReloadLibrary(library_t* lib, x64emu_t* emu) { - lib->active = 1; if(lib->type==LIB_EMULATED) { elfheader_t *elf_header = lib->e.elf; // reload image in memory and re-run the mapping @@ -510,33 +508,31 @@ int ReloadLibrary(library_t* lib, x64emu_t* emu) int FiniLibrary(library_t* lib, x64emu_t* emu) { - if(!lib->active) - return 0; // nothing to do switch (lib->type) { case LIB_WRAPPED: - if(!--lib->w.refcnt) - lib->active = 0; return 0; case LIB_EMULATED: - if(!--lib->e.elf->refcnt) { - if(emu) - RunElfFini(lib->e.elf, emu); - lib->active = 0; - } + RunElfFini(lib->e.elf, emu); return 0; } return 1; // bad type } -void InactiveLibrary(library_t* lib) -{ - lib->active = 0; -} - void Free1Library(library_t **lib, x64emu_t* emu) { if(!(*lib)) return; + printf_log(LOG_DEBUG, "Free1Library %s\n", (*lib)->name); + // remove lib from maplib/local_maplib... + if(my_context) { + MapLibRemoveLib(my_context->maplib, *lib); + MapLibRemoveLib(my_context->local_maplib, *lib); + } + // free elf is relevant + if((*lib)->type==LIB_EMULATED) { + FreeElfHeader(&(*lib)->e.elf); + } + // No "Fini" logic here, only memory handling if((*lib)->maplib) FreeLibrarian(&(*lib)->maplib, emu); @@ -624,7 +620,7 @@ int IsSameLib(library_t* lib, const char* path) } int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) { - if(!name[0] || !lib->active) + if(!name[0]) return 0; khint_t k; // get a new symbol @@ -651,7 +647,7 @@ int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, } int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) { - if(!name[0] || !lib || !lib->active) + if(!name[0] || !lib) return 0; khint_t k; // get a new symbol @@ -678,7 +674,7 @@ int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star } int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver) { - if(!name[0] || !lib->active) + if(!name[0]) return 0; khint_t k; // get a new symbol @@ -907,8 +903,6 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int* weak, int version, const char* vername, int local) { - if(!lib->active) - return 0; if(version==-2) // don't send global native symbol for a version==-2 search return 0; // check in datamaps (but no version, it's not handled there) @@ -1063,8 +1057,6 @@ void IncRefCount(library_t* lib, x64emu_t* emu) { if(lib->type==LIB_UNNKNOW) return; - if(!lib->active) - ReloadLibrary(lib, emu); switch (lib->type) { case LIB_WRAPPED: ++lib->w.refcnt; @@ -1072,4 +1064,47 @@ void IncRefCount(library_t* lib, x64emu_t* emu) case LIB_EMULATED: ++lib->e.elf->refcnt; } +} + +int DecRefCount(library_t** lib, x64emu_t* emu) +{ + if(!lib || !*lib) + return 0; + if((*lib)->type==LIB_UNNKNOW) + return 0; + int ret = 0; + switch ((*lib)->type) { + case LIB_WRAPPED: + if(!(ret=--(*lib)->w.refcnt)) { + if((*lib)->w.needed) + for(int i=0; i<(*lib)->w.needed->size; ++i) + DecRefCount(&(*lib)->w.needed->libs[i], emu); + Free1Library(lib, emu); + } + break; + case LIB_EMULATED: + if(!(ret=--(*lib)->e.elf->refcnt)) { + if((*lib)->e.elf->needed) + for(int i=0; i<(*lib)->e.elf->needed->size; ++i) + DecRefCount(&(*lib)->e.elf->needed->libs[i], emu); + removeLinkMapLib(*lib); + FiniLibrary(*lib, emu); + Free1Library(lib, emu); + } + break; + } + return ret; +} + +int GetRefCount(library_t* lib) +{ + switch (lib->type) { + case LIB_WRAPPED: + return lib->w.refcnt; + break; + case LIB_EMULATED: + return lib->e.elf->refcnt; + default: + return 0; + } } \ No newline at end of file diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h index 2b2c5eff..bb8188d8 100755 --- a/src/librarian/library_private.h +++ b/src/librarian/library_private.h @@ -62,7 +62,6 @@ typedef struct library_s { char* path; // original path int nbdot; // nombre of "." after .so int type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined - int active; wrappedlib_fini_t fini; wrappedlib_get_t getglobal; // get global (non-weak) wrappedlib_get_t getweak; // get weak symbol @@ -112,4 +111,7 @@ linkmap_t* getLinkMapLib(library_t* lib); linkmap_t* addLinkMapLib(library_t* lib); void removeLinkMapLib(library_t* lib); +int FiniLibrary(library_t* lib, x64emu_t* emu); +void Free1Library(library_t **lib, x64emu_t* emu); + #endif //__LIBRARY_PRIVATE_H_ |