diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-07-09 12:38:48 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-07-09 12:38:48 +0200 |
| commit | dabbca767f9de4fc4cf68252037de3061592eae2 (patch) | |
| tree | bfc1dadad814a82a155c0c374097177b94154beb /src/elfs | |
| parent | ca9bc1361943575724eb5152798aa208ed5eed6c (diff) | |
| download | box64-dabbca767f9de4fc4cf68252037de3061592eae2.tar.gz box64-dabbca767f9de4fc4cf68252037de3061592eae2.zip | |
[ELFLOADER] Added a check if lib version is compatible with what the elf loading it wants (helps Linux games on Steam)
Diffstat (limited to 'src/elfs')
| -rwxr-xr-x | src/elfs/elfloader.c | 19 | ||||
| -rwxr-xr-x | src/elfs/elfparser.c | 52 |
2 files changed, 58 insertions, 13 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 4caa07ce..7977b592 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -374,6 +374,23 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) return 0; } +int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded) +{ + if(!verneeded || !head) + return 1; + if(!head->VerDef || !verneeded->VerNeed) + return 1; + int cnt = GetNeededVersionCnt(verneeded, libname); + for (int i=0; i<cnt; ++i) { + const char* vername = GetNeededVersionString(verneeded, libname, i); + if(vername && !GetVersionIndice(head, vername)) { + printf_log(/*LOG_DEBUG*/LOG_INFO, "Discarding %s for missing version %s\n", head->path, vername); + return 0; // missing version + } + } + return 1; +} + int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) { (void)context; @@ -1201,7 +1218,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64c h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; // TODO: Add LD_LIBRARY_PATH and RPATH handling - if(AddNeededLib(maplib, local, bindnow, h->needed, box64, emu)) { + if(AddNeededLib(maplib, local, bindnow, h->needed, h, box64, emu)) { printf_log(LOG_INFO, "Error loading one of needed lib\n"); if(!allow_missing_libs) return 1; //error... diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index 7b83e07e..1701378f 100755 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -416,18 +416,6 @@ int GetVersionIndice(elfheader_t* h, const char* vername) { if(!vername) return 0; - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); - while(ver) { - Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); - for(int j=0; j<ver->vn_cnt; ++j) { - if(!strcmp(h->DynStr+aux->vna_name, vername)) - return aux->vna_other; - aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); - } - ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; - } - } if(h->VerDef) { Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); while(def) { @@ -438,4 +426,44 @@ int GetVersionIndice(elfheader_t* h, const char* vername) } } return 0; +} + +int GetNeededVersionCnt(elfheader_t* h, const char* libname) +{ + if(!libname) + return 0; + if(h->VerNeed) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); + if(!strcmp(filename, libname)) + return ver->vn_cnt; + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return 0; +} + +const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) +{ + if(!libname) + return 0; + if(h->VerNeed) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); + if(!strcmp(filename, libname)) { + for(int j=0; j<ver->vn_cnt; ++j) { + if(j==idx) + return h->DynStr+aux->vna_name; + aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + return NULL; // idx out of bound, return NULL... + } + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return NULL; } \ No newline at end of file |