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 | |
| 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')
| -rwxr-xr-x | src/box64context.c | 38 | ||||
| -rwxr-xr-x | src/elfs/elfloader.c | 36 | ||||
| -rwxr-xr-x | src/include/box64context.h | 2 | ||||
| -rwxr-xr-x | src/include/librarian.h | 2 | ||||
| -rwxr-xr-x | src/include/library.h | 6 | ||||
| -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 | ||||
| -rwxr-xr-x | src/tools/bridge.c | 3 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibdl.c | 4 |
10 files changed, 172 insertions, 84 deletions
diff --git a/src/box64context.c b/src/box64context.c index 082831f3..f6ca346a 100755 --- a/src/box64context.c +++ b/src/box64context.c @@ -338,20 +338,44 @@ void FreeBox64Context(box64context_t** context) } int AddElfHeader(box64context_t* ctx, elfheader_t* head) { - int idx = ctx->elfsize; - if(idx==ctx->elfcap) { - // resize... - ctx->elfcap += 16; - ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap); + int idx = 0; + while(idx<ctx->elfsize && ctx->elfs[idx]) idx++; + if(idx == ctx->elfsize) { + if(idx==ctx->elfcap) { + // resize... + ctx->elfcap += 16; + ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap); + } + ctx->elfs[idx] = head; + ctx->elfsize++; + } else { + ctx->elfs[idx] = head; } - ctx->elfs[idx] = head; - ctx->elfsize++; printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx); return idx; } +void RemoveElfHeader(box64context_t* ctx, elfheader_t* head) { + if(GetTLSBase(head)) { + // should remove the tls info + int tlsbase = GetTLSBase(head); + if(tlsbase == -ctx->tlssize) { + // not really correct, but will do for now + ctx->tlssize -= GetTLSSize(head); + if(!(++ctx->sel_serial)) + ++ctx->sel_serial; + } + } + for(int i=0; i<ctx->elfsize; ++i) + if(ctx->elfs[i] == head) { + ctx->elfs[i] = NULL; + return; + } +} + int AddTLSPartition(box64context_t* context, int tlssize) { int oldsize = context->tlssize; + // should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities context->tlssize += tlssize; context->tlsdata = box_realloc(context->tlsdata, context->tlssize); memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 22045a8c..10db2c86 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -77,12 +77,9 @@ void FreeElfHeader(elfheader_t** head) if(!head || !*head) return; elfheader_t *h = *head; -#ifdef DYNAREC - /*if(h->text) { - dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path); - cleanDBFromAddressRange(my_context, h->text, h->textsz, 1); - }*/ // will be free at the end, no need to free it now -#endif + if(my_context) + RemoveElfHeader(my_context, h); + box_free(h->name); box_free(h->path); box_free(h->PHEntries); @@ -311,6 +308,7 @@ void FreeElfMemory(elfheader_t* head) if(head->multiblock_n) { for(int i=0; i<head->multiblock_n; ++i) { #ifdef DYNAREC + dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path); cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1); #endif munmap(head->multiblock[i], head->multiblock_size[i]); @@ -1333,7 +1331,7 @@ void RunDeferredElfInit(x64emu_t *emu) void RunElfFini(elfheader_t* h, x64emu_t *emu) { - if(!h || h->fini_done) + if(!h || h->fini_done || !h->init_done) return; h->fini_done = 1; // first check fini array @@ -1350,7 +1348,7 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu) } h->init_done = 0; // can be re-inited again... for(int i=0; i<h->needed->size; ++i) - FiniLibrary(h->needed->libs[i], emu); + DecRefCount(&h->needed->libs[i], emu); return; } @@ -1506,17 +1504,17 @@ void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned l int32_t GetTLSBase(elfheader_t* h) { - return h->tlsbase; + return h?h->tlsbase:0; } uint32_t GetTLSSize(elfheader_t* h) { - return h->tlssize; + return h?h->tlssize:0; } void* GetTLSPointer(box64context_t* context, elfheader_t* h) { - if(!h->tlssize) + if(!h || !h->tlssize) return NULL; tlsdatasize_t* ptr = getTLSData(context); return ptr->data+h->tlsbase; @@ -1607,13 +1605,15 @@ EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) { const char* empty = ""; int ret = 0; for (int idx=0; idx<context->elfsize; ++idx) { - my_dl_phdr_info_t info; - info.dlpi_addr = GetElfDelta(context->elfs[idx]); - info.dlpi_name = idx?context->elfs[idx]->name:empty; //1st elf is program, and this one doesn't get a name - info.dlpi_phdr = context->elfs[idx]->PHEntries; - info.dlpi_phnum = context->elfs[idx]->numPHEntries; - if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) { - return ret; + if(context->elfs[idx]) { + my_dl_phdr_info_t info; + info.dlpi_addr = GetElfDelta(context->elfs[idx]); + info.dlpi_name = idx?context->elfs[idx]->name:empty; //1st elf is program, and this one doesn't get a name + info.dlpi_phdr = context->elfs[idx]->PHEntries; + info.dlpi_phnum = context->elfs[idx]->numPHEntries; + if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) { + return ret; + } } } // and now, go on native version diff --git a/src/include/box64context.h b/src/include/box64context.h index c4e88a83..2424c130 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -213,6 +213,8 @@ void print_cycle_log(int loglevel); // return the index of the added header int AddElfHeader(box64context_t* ctx, elfheader_t* head); +// remove an elf from list (but list is never reduced, so there can be holes) +void RemoveElfHeader(box64context_t* ctx, elfheader_t* head); // return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context) int AddTLSPartition(box64context_t* context, int tlssize); diff --git a/src/include/librarian.h b/src/include/librarian.h index d374ae93..b7a46880 100755 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -32,6 +32,8 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername); int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver); +void MapLibRemoveLib(lib_t* maplib, library_t* lib); + const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname); const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib); diff --git a/src/include/library.h b/src/include/library.h index 29c7061d..35d1d40a 100755 --- a/src/include/library.h +++ b/src/include/library.h @@ -18,10 +18,6 @@ typedef struct elfheader_s elfheader_t; library_t *NewLibrary(const char* path, box64context_t* box64); int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu); int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu); -int ReloadLibrary(library_t* lib, x64emu_t* emu); -int FiniLibrary(library_t* lib, x64emu_t* emu); -void InactiveLibrary(library_t* lib); -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) @@ -37,5 +33,7 @@ int GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped) elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped) void* GetHandle(library_t* lib); // NULL if not wrapped void IncRefCount(library_t* lib, x64emu_t* emu); +int DecRefCount(library_t** lib, x64emu_t* emu); // might unload the lib! +int GetRefCount(library_t* lib); #endif //__LIBRARY_H_ 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_ diff --git a/src/tools/bridge.c b/src/tools/bridge.c index 16aaaf74..54c380b1 100755 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -61,7 +61,7 @@ brick_t* NewBrick(void* old) printf_log(LOG_NONE, "Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t)); } #ifdef DYNAREC - setProtection((uintptr_t)ptr, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NOPROT); + setProtection((uintptr_t)ptr, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NOPROT | PROT_MMAP); #endif dynarec_log(LOG_INFO, "New Bridge brick at %p (size 0x%zx)\n", ptr, NBRICK*sizeof(onebridge_t)); ret->b = ptr; @@ -85,6 +85,7 @@ void FreeBridge(bridge_t** bridge) x64emu_t* emu = thread_get_emu(); while(b) { brick_t *n = b->next; + dynarec_log(LOG_INFO, "FreeBridge brick at %p (size 0x%zx)\n", b->b, NBRICK*sizeof(onebridge_t)); my_munmap(emu, b->b, NBRICK*sizeof(onebridge_t)); box_free(b); b = n; diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 952de79d..2089a12c 100755 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -339,7 +339,9 @@ int my_dlclose(x64emu_t* emu, void *handle) return -1; } dl->count[nlib] = dl->count[nlib]-1; - FiniLibrary(dl->libs[nlib], emu); + if(!DecRefCount(&dl->libs[nlib], emu)) { + dl->count[nlib] = 0; + } return 0; } int my_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags) |