diff options
| author | ptitSeb <seebastien.chev@gmail.com> | 2023-08-19 16:35:57 +0200 |
|---|---|---|
| committer | ptitSeb <seebastien.chev@gmail.com> | 2023-08-19 16:35:57 +0200 |
| commit | 9e7225be3698bbb970ef0674ebb282dada8fec45 (patch) | |
| tree | 42674381cd2d6a0501eef54daa96f3d60b4412fb /src | |
| parent | 154acbef72706a72787f56083bae72689808c3b1 (diff) | |
| download | box64-9e7225be3698bbb970ef0674ebb282dada8fec45.tar.gz box64-9e7225be3698bbb970ef0674ebb282dada8fec45.zip | |
[ELFLOADER] Adjusted fetching of symbol (help Steam Unity3d linux games, like Canabalt)
Diffstat (limited to 'src')
| -rw-r--r-- | src/elfs/elfloader.c | 42 | ||||
| -rw-r--r-- | src/include/librarian.h | 1 | ||||
| -rw-r--r-- | src/librarian/librarian.c | 94 |
3 files changed, 121 insertions, 16 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 265a6241..6a516601 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -490,11 +490,20 @@ 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(!offs && !end) { - if(!offs && !end && local_maplib) - GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); - if(!offs && !end && local_maplib) - GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(bind==STB_WEAK) { + if(!offs && !end) { + if(!offs && !end && local_maplib) + GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib) + GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + } + } else { + if(!offs && !end) { + if(!offs && !end && local_maplib) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + if(!offs && !end && local_maplib) + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver); + } } } uintptr_t globoffs, globend; @@ -692,13 +701,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 80e108ca..6fc89320 100644 --- 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 8d4c6cbb..072ef811 100644 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -451,6 +451,91 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin 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; i<my_context->neededlibs->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; i<maplib->libsz; ++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; + + if(maplib) + for(int i=0; i<maplib->libsz; ++i) { + if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver)) + if(*start) + 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 box64 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; + // search in needed libs from preloaded first, in order + if(my_context->preload) + for(int i=0; i<my_context->preload->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) if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver)) if(*start) @@ -486,17 +571,16 @@ 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; } |