From 630f42e9e221858399bedd1f9e8a9f48b766dadd Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sat, 19 Aug 2023 16:36:15 +0200 Subject: [PATCH] [ELFLOADER] Adjusted fetching of symbol --- src/elfs/elfloader.c | 46 ++++++++++++++----- src/include/librarian.h | 1 + src/librarian/librarian.c | 96 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 17 deletions(-) diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 4f3c7cdc0..b71cb2fbd 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -521,13 +521,24 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* end = offs + sym->st_size; }*/ // so weak symbol are the one left - if(old_version==version && old_bind==bind && old_symname==symname) { - offs = old_offs; - end = old_end; + if(bind==STB_WEAK) { + if(old_version==version && old_bind==bind && old_symname==symname) { + offs = old_offs; + end = old_end; + } else { + GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + } } else { - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(old_version==version && old_bind==bind && old_symname==symname) { + offs = old_offs; + end = old_end; + } else { + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + } } } old_bind = bind; @@ -799,13 +810,24 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t end = offs + sym->st_size; }*/ // so weak symbol are the one left - if(old_version==version && old_bind==bind && old_symname==symname) { - offs = old_offs; - end = old_end; + if(bind==STB_WEAK) { + if(old_version==version && old_bind==bind && old_symname==symname) { + offs = old_offs; + end = old_end; + } else { + GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + } } else { - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(old_version==version && old_bind==bind && old_symname==symname) { + offs = old_offs; + end = old_end; + } else { + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + } } } old_bind = bind; diff --git a/src/include/librarian.h b/src/include/librarian.h index d801ef338..4e2728bb9 100755 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -30,6 +30,7 @@ int isLibLocal(library_t* lib); uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername); int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver); int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver); +int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver); int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver); int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver); elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername); diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index e8d7ddd2c..909333ac1 100755 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -443,6 +443,94 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u 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, const char* globdefver, const char* weakdefver) +{ + int weak = 0; + size_t size = 0; + // 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]), globdefver)) + if(*start) + return 1; + // search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self) + if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver)) + 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 + if(my_context->neededlibs) + for(int i=0; ineededlibs->size; ++i) + if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver)) + if(*start) { + return 1; + } + // search in global symbols + if(maplib) { + if(self && self!=my_context->elfs[0] && self!=(void*)1) + if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver)) + if(*start) + return 1; + for(int i=0; ilibsz; ++i) { + if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver)) + if(*start) { + return 1; + } + } + } + + // check with default version... + int ok = 0; + // GetSymbolStartEnd should not change start/end if symbol is not found + if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver)) + if(*start) + ok = 1; + + for(int i=0; ilibsz; ++i) { + if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver)) + if(*start) { +printf_log(LOG_INFO, "\t\t found weak one in %s\n", maplib->libraries[i]->name); + ok = 1; + } + } + // nope, not found + return (ok && *start)?1:0; +} +void** my_GetGTKDisplay(); +void** my_GetGthreadsGotInitialized(); +int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) +{ + if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) { + 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, self, version, vername, globdefver, weakdefver)) { + if(end2>*end && start2==end2) + *end = end2; + } + box_free(buff); + } + return 1; + } + // some special case symbol, defined inside box86 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; + } + // 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, const char* globdefver, const char* weakdefver) { int weak = 0; size_t size = 0; @@ -485,17 +573,15 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin // nope, not found return (ok && *start)?1:0; } -void** my_GetGTKDisplay(); -void** my_GetGthreadsGotInitialized(); -int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) +int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver) { - if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) { + if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) { 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, self, version, vername, globdefver, weakdefver)) { + if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) { if(end2>*end && start2==end2) *end = end2; }