From e1140c04016b9e2be40c1456256d9b099c3b3dea Mon Sep 17 00:00:00 2001 From: rajdakin Date: Wed, 14 Apr 2021 20:06:21 +0200 Subject: [PATCH 1/2] (Hopefully) fixed the library freeing ordering (avoid crash) --- src/box86context.c | 22 ------ src/elfs/elfloader.c | 8 +- src/include/box86context.h | 6 +- src/include/elfloader.h | 20 ++--- src/include/librarian.h | 4 +- src/librarian/librarian.c | 120 ++++++++++++++++++++---------- src/librarian/librarian_private.h | 7 +- src/librarian/library.c | 46 +++++++++++- src/librarian/library_private.h | 7 +- src/main.c | 4 +- src/wrapped/wrappedlibdl.c | 2 +- 11 files changed, 153 insertions(+), 93 deletions(-) diff --git a/src/box86context.c b/src/box86context.c index c62160eafe..681db3cb65 100755 --- a/src/box86context.c +++ b/src/box86context.c @@ -342,25 +342,3 @@ int AddTLSPartition(box86context_t* context, int tlssize) { return -context->tlssize; // negative offset } - -void add_neededlib(needed_libs_t* needed, library_t* lib) -{ - if(!needed) - return; - if(needed->size == needed->cap) { - needed->cap += 8; - needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); - } - needed->libs[needed->size++] = lib; -} - -void free_neededlib(needed_libs_t* needed) -{ - if(!needed) - return; - needed->cap = 0; - needed->size = 0; - if(needed->libs) - free(needed->libs); - needed->libs = NULL; -} diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 12a4baeb1a..30b049fa79 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -814,7 +814,7 @@ page description of the -r option). For more details of this token expansion, se uname(1) man page description of the -i option). For more details of this token expansion, see “System Specific Shared Objects” */ -int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box86context_t *box86, x86emu_t* emu) +int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, box86context_t* box86, x86emu_t* emu) { DumpDynamicRPath(h); // update RPATH first @@ -867,8 +867,8 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int for (int i=0; inumDynamic; ++i) if(h->Dynamic[i].d_tag==DT_NEEDED) { char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; - // TODO: Add LD_LIBRARY_PATH and RPATH Handling - if(AddNeededLib(maplib, neededlibs, local, needed, box86, emu)) { + // TODO: Add LD_LIBRARY_PATH and RPATH handling + if(AddNeededLib(maplib, neededlibs, deplib, local, needed, box86, emu)) { printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed); if(!allow_missing_libs) return 1; //error... @@ -952,7 +952,7 @@ void RunElfFini(elfheader_t* h, x86emu_t *emu) #else // first check fini array Elf32_Addr *addr = (Elf32_Addr*)(h->finiarray + h->delta); - for (int i=0; ifiniarray_sz; ++i) { + for (int i=h->finiarray_sz-1; i>=0; ++i) { printf_log(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]); RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0); } diff --git a/src/include/box86context.h b/src/include/box86context.h index 9ea1d414d2..03e75a4d8f 100755 --- a/src/include/box86context.h +++ b/src/include/box86context.h @@ -50,9 +50,7 @@ typedef struct needed_libs_s { int size; library_t **libs; } needed_libs_t; - -void add_neededlib(needed_libs_t* needed, library_t* lib); -void free_neededlib(needed_libs_t* needed); +void free_neededlib(needed_libs_t* needed); // defined in library.c typedef struct base_segment_s { uintptr_t base; @@ -209,4 +207,4 @@ int unlockMutex(); // relock the muxtex that were unlocked void relockMutex(int locks); -#endif //__BOX86CONTEXT_H_ \ No newline at end of file +#endif //__BOX86CONTEXT_H_ diff --git a/src/include/elfloader.h b/src/include/elfloader.h index f6bde696f2..4a0a9c9ea4 100755 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -24,30 +24,30 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin); void FreeElfMemory(elfheader_t* head); int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head); int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head); -int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head); -int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head); +int RelocateElf(lib_t* maplib, lib_t* local_maplib, elfheader_t* head); +int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, elfheader_t* head); void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign); uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h); uintptr_t GetLastByte(elfheader_t* h); -void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h); -int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box86context_t *box86, x86emu_t* emu); +void AddSymbols(lib_t* maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h); +int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, box86context_t* box86, x86emu_t* emu); uintptr_t GetElfInit(elfheader_t* h); uintptr_t GetElfFini(elfheader_t* h); -void RunElfInit(elfheader_t* h, x86emu_t *emu); -void RunElfFini(elfheader_t* h, x86emu_t *emu); -void RunDeferedElfInit(x86emu_t *emu); +void RunElfInit(elfheader_t* h, x86emu_t* emu); +void RunElfFini(elfheader_t* h, x86emu_t* emu); +void RunDeferedElfInit(x86emu_t* emu); void* GetBaseAddress(elfheader_t* h); void* GetElfDelta(elfheader_t* h); uint32_t GetBaseSize(elfheader_t* h); int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr); -elfheader_t* FindElfAddress(box86context_t *context, uintptr_t addr); +elfheader_t* FindElfAddress(box86context_t* context, uintptr_t addr); const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz); int32_t GetTLSBase(elfheader_t* h); uint32_t GetTLSSize(elfheader_t* h); void* GetTLSPointer(box86context_t* context, elfheader_t* h); void* GetDTatOffset(box86context_t* context, int index, int offset); #ifdef DYNAREC -dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr); +dynablocklist_t* GetDynablocksFromAddress(box86context_t* context, uintptr_t addr); dynablocklist_t* GetDynablocksFromElf(elfheader_t* h); #endif void ResetSpecialCaseMainElf(elfheader_t* h); @@ -56,4 +56,4 @@ void CreateMemorymapFile(box86context_t* context, int fd); int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used -#endif //__ELF_LOADER_H_ \ No newline at end of file +#endif //__ELF_LOADER_H_ diff --git a/src/include/librarian.h b/src/include/librarian.h index dea577734e..a378b2d740 100755 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -25,7 +25,7 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib); kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib); kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib); kh_mapsymbols_t* GetGlobalData(lib_t* maplib); -int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error +int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error library_t* GetLibMapLib(lib_t* maplib, const char* name); library_t* GetLibInternal(const char* name); uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name); @@ -49,4 +49,4 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name); const char* GetNameOffset(lib_t *maplib, void* offs); -#endif //__LIBRARIAN_H_ \ No newline at end of file +#endif //__LIBRARIAN_H_ diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index efd0095b46..d50f6969f0 100755 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -34,18 +34,59 @@ lib_t *NewLibrarian(box86context_t* context, int ownlibs) return maplib; } +static void freeLibraryRecurse(lib_t *maplib, x86emu_t *emu, int idx, char *freed) { + if (freed[idx]) return; // Already freed + + freed[idx] = 1; // Avoid infinite loops + library_t *lib = maplib->libraries[idx]; + printf_log(LOG_DEBUG, "Unloading %s\n", lib->name); + for (int i = lib->dependedby.size - 1; i >= 0; --i) { + int j; + for (j = 0; j < maplib->libsz; ++j) { + if (lib->dependedby.libs[i] == maplib->libraries[j]) break; + } + if (j == maplib->libsz) { + // We cannot access the 'name' field, since we ncan't be sure it hasn't been freed somewhere else... + printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->dependedby.libs[i]); + continue; + } + if (freed[j] == 1) { + printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->dependedby.libs[i]->name); + continue; + } + freeLibraryRecurse(maplib, emu, j, freed); + if (freed[idx] != 1) { + printf_log(LOG_DEBUG, "Note: library already freed (cyclic dependancy break)\n"); + return; + } + } + + library_t *ptr = maplib->libraries[idx]; + Free1Library(&ptr, emu); + freed[idx] = 2; +} void FreeLibrarian(lib_t **maplib, x86emu_t *emu) { // should that be in reverse order? if(!maplib || !*maplib) return; - if((*maplib)->ownlibs) { + if((*maplib)->ownlibs && (*maplib)->libsz) { printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib); - for (int i=(*maplib)->libsz-1; i>=0; --i) { - printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name); - Free1Library(&(*maplib)->libraries[i].lib, emu); + char *freed = (char*)calloc((*maplib)->libsz, sizeof(char)); + if (!freed) { + printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n"); + for (int i=(*maplib)->libsz-1; i>=0; --i) { + printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name); + Free1Library(&(*maplib)->libraries[i], emu); + } + } else { + for (int i=(*maplib)->libsz-1; i>=0; --i) { + Free1Library(&(*maplib)->libraries[i], emu); + } + memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway } + free(freed); } free((*maplib)->libraries); (*maplib)->libraries = NULL; @@ -103,9 +144,9 @@ kh_mapsymbols_t* GetGlobalData(lib_t* maplib) library_t* getLib(lib_t* maplib, const char* path) { for(int i=0; ilibsz; ++i) { - onelib_t *onelib = &maplib->libraries[i]; - if(IsSameLib(onelib->lib, path)) { - return onelib->lib; + library_t *lib = maplib->libraries[i]; + if(IsSameLib(lib, path)) { + return lib; } } return NULL; @@ -116,7 +157,7 @@ static int libraryInMapLib(lib_t* maplib, library_t* lib) if(!maplib) return 0; for(int i=0; ilibsz; ++i) - if(maplib->libraries[i].lib==lib) + if(maplib->libraries[i]==lib) return 1; return 0; } @@ -125,10 +166,9 @@ void MapLibAddLib(lib_t* maplib, library_t* lib) { if (maplib->libsz == maplib->libcap) { maplib->libcap += 8; - maplib->libraries = (onelib_t*)realloc(maplib->libraries, maplib->libcap*sizeof(onelib_t)); + maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*)); } - maplib->libraries[maplib->libsz].lib = lib; - maplib->libraries[maplib->libsz].name = GetNameLib(lib); + maplib->libraries[maplib->libsz] = lib; ++maplib->libsz; } @@ -137,7 +177,7 @@ void MapLibAddMapLib(lib_t* dest, lib_t* src) if(!src) return; for(int i=0; ilibsz; ++i) { - library_t* lib = src->libraries[i].lib; + library_t* lib = src->libraries[i]; if(!lib) continue; if(lib->maplib && src!=lib->maplib) { //TODO: find why is src!=lib->maplib needed MapLibAddMapLib(dest, lib->maplib); @@ -154,24 +194,24 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib) if(!maplib || !lib) return; int idx = 0; - while(idxlibsz && maplib->libraries[idx].lib!=lib) ++idx; + 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(onelib_t)*(maplib->libsz-idx)); - maplib->libraries[maplib->libsz].lib = NULL; - maplib->libraries[maplib->libsz].name = NULL; + memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx)); + maplib->libraries[maplib->libsz] = NULL; } EXPORTDYN -int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box86context_t* box86, x86emu_t* emu) +int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box86context_t* box86, x86emu_t* emu) { printf_log(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) { add_neededlib(neededlibs, lib); + if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib); printf_log(LOG_DEBUG, "Already present in maplib => success\n"); return 0; } @@ -201,6 +241,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char MapLibRemoveLib(my_context->local_maplib, lib); } add_neededlib(neededlibs, lib); + if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib); return 0; } // load a new one @@ -211,6 +252,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char } add_neededlib(neededlibs, lib); + if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib); // add lib now if(local) { @@ -237,17 +279,17 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char } else { // it's an emulated lib, // lets load dependancies before adding symbols and launch init sequence - if(LoadNeededLibs(box86->elfs[mainelf], maplib, &lib->needed, 0, box86, emu)) { + if(LoadNeededLibs(box86->elfs[mainelf], maplib, &lib->needed, lib, 0, box86, 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, 0, "libGL.so.1", box86, emu); + AddNeededLib(maplib, &lib->needed, lib, 0, "libGL.so.1", box86, emu); } if(!strcmp(GetNameLib(lib), "libmss.so.6")) { - AddNeededLib(maplib, &lib->needed, 0, "libSDL-1.2.so.0", box86, emu); - AddNeededLib(maplib, &lib->needed, 0, "libdl.so.2", box86, emu); + AddNeededLib(maplib, &lib->needed, lib, 0, "libSDL-1.2.so.0", box86, emu); + AddNeededLib(maplib, &lib->needed, lib, 0, "libdl.so.2", box86, emu); } // add symbols if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs @@ -302,8 +344,8 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u return 1; } for(int i=0; ilibsz; ++i) { - if(GetElfIndex(maplib->libraries[i].lib)==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]!=self)) - if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self)) + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) if(*start) return 1; } @@ -318,8 +360,8 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u return 1; } for(int i=0; ilibsz; ++i) { - if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) - if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) if(*start) return 1; } @@ -341,14 +383,14 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin return 1; // search in global symbols for(int i=0; ilibsz; ++i) { - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end)) 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].lib, name, start, end)) // only weak symbol haven't been found yet + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) // only weak symbol haven't been found yet if(*start) return 1; } @@ -402,10 +444,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name) if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end)) return maplib->context->elfs[0]; for(int i=0; ilibsz; ++i) { - if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) { - int idx = GetElfIndex(maplib->libraries[i].lib); + if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end)) { + 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].lib)); + printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i])); return NULL; } return maplib->context->elfs[idx]; @@ -421,7 +463,7 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st if(*start || *end) return 1; for(int i=0; ilibsz; ++i) - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end)) if(*start || *end) return 1; // nope, not found @@ -432,8 +474,8 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name) { uintptr_t start, end; for(int i=0; ilibsz; ++i) - if(GetElfIndex(maplib->libraries[i].lib)==-1) - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) + if(GetElfIndex(maplib->libraries[i])==-1) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end)) if(start || end) return 1; // nope, not found @@ -451,8 +493,8 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui return 0; } for(int i=0; ilibsz; ++i) { - if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) { - if(GetLibLocalSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) { + if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end)) if(*start) return 1; if(self) @@ -470,8 +512,8 @@ int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uin return 1; } else { for(int i=0; ilibsz; ++i) { - if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) - if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) + if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) if(*start || *end) return 1; } @@ -487,8 +529,8 @@ int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u return 1; } else { for(int i=0; ilibsz; ++i) { - if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) - if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) + if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) + if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end)) if(*start || *end) return 1; } diff --git a/src/librarian/librarian_private.h b/src/librarian/librarian_private.h index 938489739f..093a69e85d 100755 --- a/src/librarian/librarian_private.h +++ b/src/librarian/librarian_private.h @@ -14,11 +14,6 @@ typedef struct onesymbol_s { // need to track origin? } onesymbol_t; -typedef struct { - char *name; - library_t *lib; -} onelib_t; - typedef char* cstr_t; KHASH_MAP_DECLARE_STR(mapsymbols, onesymbol_t) @@ -31,7 +26,7 @@ typedef struct lib_s { khash_t(mapsymbols) *localsymbols; khash_t(mapoffsets) *mapoffsets; khash_t(mapsymbols) *globaldata; - onelib_t *libraries; + library_t **libraries; int libsz; int libcap; int ownlibs; diff --git a/src/librarian/library.c b/src/librarian/library.c index 411a6a493e..96318ddb0c 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -151,7 +151,7 @@ static void initNativeLib(library_t *lib, box86context_t* context) { lib->type = 0; // Call librarian to load all dependant elf for(int i=0; ipriv.w.needed; ++i) { - if(AddNeededLib(context->maplib, &lib->needed, 0, lib->priv.w.neededlibs[i], context, NULL)) { // probably all native, not emulated, so that's fine + if(AddNeededLib(context->maplib, &lib->needed, lib, 0, lib->priv.w.neededlibs[i], context, NULL)) { // probably all native, not emulated, so that's fine printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", lib->priv.w.neededlibs[i]); return; } @@ -413,6 +413,7 @@ void Free1Library(library_t **lib, x86emu_t* emu) if((*lib)->symbol2map) kh_destroy(symbol2map, (*lib)->symbol2map); free_neededlib(&(*lib)->needed); + free_neededlib(&(*lib)->dependedby); free(*lib); *lib = NULL; @@ -697,4 +698,45 @@ lib_t* GetMaplib(library_t* lib) if(!lib) return NULL; return lib->maplib; -} \ No newline at end of file +} + +void add_neededlib(needed_libs_t* needed, library_t* lib) +{ + if(!needed) + return; + if(needed->size == needed->cap) { + needed->cap += 8; + needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); + } + needed->libs[needed->size++] = lib; +} +void free_neededlib(needed_libs_t* needed) +{ + if(!needed) + return; + needed->cap = 0; + needed->size = 0; + if(needed->libs) + free(needed->libs); + needed->libs = NULL; +} +void add_dependedbylib(needed_libs_t* dependedby, library_t* lib) +{ + if(!dependedby) + return; + if(dependedby->size == dependedby->cap) { + dependedby->cap += 8; + dependedby->libs = (library_t**)realloc(dependedby->libs, dependedby->cap*sizeof(library_t*)); + } + dependedby->libs[dependedby->size++] = lib; +} +void free_dependedbylib(needed_libs_t* dependedby) +{ + if(!dependedby) + return; + dependedby->cap = 0; + dependedby->size = 0; + if(dependedby->libs) + free(dependedby->libs); + dependedby->libs = NULL; +} diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h index c978f98d42..11d452978b 100755 --- a/src/librarian/library_private.h +++ b/src/librarian/library_private.h @@ -75,8 +75,13 @@ typedef struct library_s { kh_datamap_t *mydatamap; char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2 needed_libs_t needed; + needed_libs_t dependedby; lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen) } library_t; +void add_neededlib(needed_libs_t* needed, library_t* lib); +void free_neededlib(needed_libs_t* needed); +void add_dependedbylib(needed_libs_t* dependedby, library_t* lib); +void free_dependedbylib(needed_libs_t* dependedby); // type for map elements typedef struct map_onesymbol_s { @@ -98,4 +103,4 @@ typedef struct map_onedata_s { int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size); // Add bridges to functions -#endif //__LIBRARY_PRIVATE_H_ \ No newline at end of file +#endif //__LIBRARY_PRIVATE_H_ diff --git a/src/main.c b/src/main.c index 6b97d67405..96f4019e26 100755 --- a/src/main.c +++ b/src/main.c @@ -1145,14 +1145,14 @@ int main(int argc, const char **argv, const char **env) { // pre-load lib if needed if(ld_preload.size) { for (int i=0; imaplib, &my_context->neededlibs, 0, my_context, emu)) { + if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, my_context, emu)) { printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]); FreeBox86Context(&my_context); return -1; diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index b8726dfe85..feeba7532c 100755 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -103,7 +103,7 @@ void* my_dlopen(x86emu_t* emu, void *filename, int flag) } dlopened = (GetLibInternal(rfilename)==NULL); // Then open the lib - if(AddNeededLib(NULL, NULL, is_local, rfilename, emu->context, emu)) { + if(AddNeededLib(NULL, NULL, NULL, is_local, rfilename, emu->context, emu)) { printf_log(LOG_INFO, "Warning: Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag); if(!dl->last_error) dl->last_error = malloc(129); From 9d7505a61c211bc5e2d0530b1ab3365f329da496 Mon Sep 17 00:00:00 2001 From: rajdakin Date: Wed, 14 Apr 2021 20:12:09 +0200 Subject: [PATCH 2/2] Fixed the exit crash... --- src/elfs/elfloader.c | 2 +- src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 30b049fa79..f6eafa860c 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -952,7 +952,7 @@ void RunElfFini(elfheader_t* h, x86emu_t *emu) #else // first check fini array Elf32_Addr *addr = (Elf32_Addr*)(h->finiarray + h->delta); - for (int i=h->finiarray_sz-1; i>=0; ++i) { + for (int i=h->finiarray_sz-1; i>=0; --i) { printf_log(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]); RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0); } diff --git a/src/main.c b/src/main.c index 96f4019e26..d3651ea5e0 100755 --- a/src/main.c +++ b/src/main.c @@ -708,7 +708,7 @@ void endBox86() //atexit first printf_log(LOG_DEBUG, "Calling atexit registered functions\n"); CallAllCleanup(emu); - // than call all the Fini (some "smart" ordering of the fini may be needed, but for now, callign in this order should be good enough) + // then call all the fini printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n"); RunElfFini(my_context->elfs[0], emu); FreeLibrarian(&my_context->maplib, emu); // unload all libs