diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/elfs/elfloader.c | 43 | ||||
| -rw-r--r-- | src/include/box64context.h | 2 | ||||
| -rw-r--r-- | src/librarian/library.c | 33 |
3 files changed, 63 insertions, 15 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 8845444a..9f01f75b 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -500,6 +500,16 @@ void GrabX64CopyMainElfReloc(elfheader_t* head) } } +static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib) +{ + if(h && lib) { + if(!h->needed) + h->needed = new_neededlib(1); + add1libref_neededlib(h->needed, lib); + } + return h; +} + int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv) { int ret_ok = 0; @@ -514,6 +524,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin uintptr_t end = 0; size_t size = sym->st_size; elfheader_t* sym_elf = NULL; + elfheader_t* last_elf = NULL; int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1; if(version!=-1) version &=0x7fff; const char* vername = GetSymbolVersion(head, version); @@ -597,6 +608,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin printf_dump(LOG_NEVER, "Apply R_X86_64_COPY @%p with sym=%s (%sver=%d/%s), @%p+0x%lx size=%ld\n", p, symname, veropt?"opt":"", version, vername?vername:"(none)", (void*)offs, rela[i].r_addend, sym->st_size); if(p!=(void*)(offs+rela[i].r_addend)) memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size); + sym_elf = FindElfAddress(my_context, offs); + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } else { printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name); } @@ -616,6 +629,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } else { printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (%sver=%d/%s, elf=%s)\n", BindSym(bind), p, (void*)(p?(*p):0), (void*)(offs + rela[i].r_addend), symname, veropt?"opt":"", version, vername?vername:"(none)", sym_elf?sym_elf->name:"(native)"); *p = offs + rela[i].r_addend; + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } } break; @@ -640,10 +654,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin // return -1; } else { if(p) { - elfheader_t* sym_elf = FindElfAddress(my_context, offs); printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s (%sver=%d / %s))\n", BindSym(bind), p, symname, *(void**)p, (void*)(offs+rela[i].r_addend), sym_elf?sym_elf->name:"native", veropt?"opt":"", version, vername?vername:"(none)"); *p = offs + rela[i].r_addend; + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } else { printf_log(LOG_INFO, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname); } @@ -669,6 +683,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%sver=%d/%s) addend=0x%lx (%p -> %p)\n", BindSym(bind), p, symname, veropt?"opt":"", version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/)); *p /*+*/= offs+rela[i].r_addend; + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } break; case R_X86_64_TPOFF64: @@ -682,6 +697,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin delta = *(int64_t*)p; printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", BindSym(bind), DumpRelType(t), symname, p, delta, sym_elf->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs); *p = (uintptr_t)((int64_t)offs + rela[i].r_addend + sym_elf->tlsbase); + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } else { printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", BindSym(bind), DumpRelType(t), symname, p, (int64_t)offs); } @@ -689,14 +705,16 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin break; case R_X86_64_DTPMOD64: // ID of module containing symbol - if(!symname || symname[0]=='\0' || bind==STB_LOCAL) + if(!symname || symname[0]=='\0' || bind==STB_LOCAL) { offs = getElfIndex(my_context, head); - else { + sym_elf = head; + } else { offs = getElfIndex(my_context, sym_elf); } if(p) { printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", BindSym(bind), "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs); *p = offs; + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } else { printf_log(LOG_INFO, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname); } @@ -711,12 +729,15 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } // return -1; } else { - if(!symname || symname[0]=='\0') + if(!symname || symname[0]=='\0') { offs = sym->st_value; + sym_elf = head; + } if(p) { int64_t tlsoffset = (int64_t)offs; // it's not an offset in elf memory printf_dump(LOG_NEVER, "Apply %s R_X86_64_DTPOFF64 @%p with sym=%s (%p -> %p)\n", BindSym(bind), p, symname, (void*)tlsoffset, (void*)offs); *p = tlsoffset; + if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib); } else { printf_log(LOG_INFO, "Warning, Symbol %s found, but R_X86_64_DTPOFF64 Slot Offset is NULL \n", symname); } @@ -1042,12 +1063,13 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu) return; } h->init_done = 1; - for(int i=0; i<h->needed->size; ++i) { - library_t *lib = h->needed->libs[i]; - elfheader_t *lib_elf = GetElf(lib); - if(lib_elf) - RunElfInit(lib_elf, emu); - } + if(h->needed) + for(int i=0; i<h->needed->init_size; ++i) { + library_t *lib = h->needed->libs[i]; + elfheader_t *lib_elf = GetElf(lib); + if(lib_elf) + RunElfInit(lib_elf, emu); + } printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p); if(h->initentry) RunFunctionWithEmu(emu, 0, p, 3, my_context->argc, my_context->argv, my_context->envv); @@ -1681,6 +1703,7 @@ EXPORT void PltResolver(x64emu_t* emu) if(p) { printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(%sver %d: %s%s%s) (%p -> %p / %s)\n", BindSym(bind), p, symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(sym_elf)); *p = offs; + if(sym_elf && sym_elf!=h) checkElfLib(h, sym_elf->lib); } else { printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(%sver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:""); } diff --git a/src/include/box64context.h b/src/include/box64context.h index efe84223..52a512fa 100644 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -58,6 +58,7 @@ void free_tlsdatasize(void* p); typedef struct needed_libs_s { int cap; int size; + int init_size; char** names; library_t** libs; int nb_done; @@ -68,6 +69,7 @@ needed_libs_t* new_neededlib(int n); needed_libs_t* copy_neededlib(needed_libs_t* needed); void add1_neededlib(needed_libs_t* needed); void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name); +void add1libref_neededlib(needed_libs_t* needed, library_t* lib); typedef struct base_segment_s { uintptr_t base; diff --git a/src/librarian/library.c b/src/librarian/library.c index e7ca6bd5..6d888fdc 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -1056,6 +1056,7 @@ needed_libs_t* new_neededlib(int n) { needed_libs_t* ret = (needed_libs_t*)calloc(1, sizeof(needed_libs_t)); ret->cap = ret->size = n; + ret->init_size = n; ret->libs = (library_t**)calloc(n, sizeof(library_t*)); ret->names = (char**)calloc(n, sizeof(char*)); return ret; @@ -1081,6 +1082,7 @@ void add1_neededlib(needed_libs_t* needed) needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*)); needed->size++; + needed->init_size++; } void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name) { @@ -1091,14 +1093,34 @@ void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name) if(needed->libs[i]==lib) return; // add it - if(needed->size+1<=needed->cap) - return; - needed->cap = needed->size+1; - needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); - needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*)); + if(needed->size==needed->cap) { + needed->cap = needed->size+1; + needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); + needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*)); + } needed->libs[needed->size] = lib; needed->names[needed->size] = (char*)name; needed->size++; + needed->init_size++; +} +void add1libref_neededlib(needed_libs_t* needed, library_t* lib) +{ + if(!needed || !lib) + return; + // check if lib is already present + for (int i=0; i<needed->size; ++i) + if(needed->libs[i]==lib) + return; + // add it + if(needed->size==needed->cap) { + needed->cap = needed->size+4; + needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*)); + needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*)); + } + needed->libs[needed->size] = lib; + needed->names[needed->size] = (char*)lib->name; + needed->size++; + IncRefCount(lib, NULL); } needed_libs_t* copy_neededlib(needed_libs_t* needed) { @@ -1107,6 +1129,7 @@ needed_libs_t* copy_neededlib(needed_libs_t* needed) needed_libs_t* ret = (needed_libs_t*)calloc(1, sizeof(needed_libs_t)); ret->cap = needed->cap; ret->size = needed->size; + ret->init_size = needed->init_size; ret->libs = (library_t**)calloc(ret->cap, sizeof(library_t*)); ret->names = (char**)calloc(ret->cap, sizeof(char*)); memcpy(ret->libs, needed->libs, ret->size*sizeof(library_t*)); |