diff options
| -rwxr-xr-x | src/elfs/elfloader.c | 38 | ||||
| -rwxr-xr-x | src/elfs/elfloader_private.h | 2 | ||||
| -rwxr-xr-x | src/wrapped/wrappedldlinux.c | 3 | ||||
| -rwxr-xr-x | src/wrapped/wrappedldlinux_private.h | 1 |
4 files changed, 32 insertions, 12 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 23f9f93c..4b5e76c1 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -124,7 +124,9 @@ int CalcLoadAddr(elfheader_t* head) head->stackalign = head->PHEntries[i].p_align; } if(head->PHEntries[i].p_type == PT_TLS) { + head->tlsaddr = head->PHEntries[i].p_vaddr; head->tlssize = head->PHEntries[i].p_memsz; + head->tlsfilesize = head->PHEntries[i].p_filesz; head->tlsalign = head->PHEntries[i].p_align; // force alignement... if(head->tlsalign>1) @@ -696,9 +698,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c case R_X86_64_TPOFF64: // Negated offset in static TLS block { - if(h_tls) - offs = sym->st_value; - else { + //if(h_tls) { + // offs = sym->st_value; + //} else + { + h_tls = NULL; if(local_maplib) h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername); if(!h_tls) @@ -706,7 +710,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c } if(h_tls) { delta = *(int64_t*)p; - printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int64_t)offs + rela[i].r_addend + h_tls->tlsbase); + printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs); *p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase); } else { printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int64_t)offs); @@ -777,14 +781,14 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, elfheader_t* head) if(head->rel) { int cnt = head->relsz / head->relent; DumpRelTable(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel"); - printf_log(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name); + printf_dump(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name); if(RelocateElfREL(maplib, local_maplib, head, cnt, (Elf64_Rel *)(head->rel + head->delta))) return -1; } if(head->rela) { int cnt = head->relasz / head->relaent; DumpRelATable(head, cnt, (Elf64_Rela *)(head->rela + head->delta), "RelA"); - printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name); + printf_dump(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name); if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL)) return -1; } @@ -799,12 +803,12 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head) int cnt = head->pltsz / head->pltent; if(head->pltrel==DT_REL) { DumpRelTable(head, cnt, (Elf64_Rel *)(head->jmprel + head->delta), "PLT"); - printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name); + printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name); if(RelocateElfREL(maplib, local_maplib, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta))) return -1; } else if(head->pltrel==DT_RELA) { DumpRelATable(head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), "PLT"); - printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name); + printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name); if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver)) return -1; } @@ -815,11 +819,11 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head) if(head->pltgot) { *(uintptr_t*)(head->pltgot+head->delta+16) = pltResolver; *(uintptr_t*)(head->pltgot+head->delta+8) = (uintptr_t)head; - printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16)); + printf_dump(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16)); } else if(head->got) { *(uintptr_t*)(head->got+head->delta+16) = pltResolver; *(uintptr_t*)(head->got+head->delta+8) = (uintptr_t)head; - printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16)); + printf_dump(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16)); } } } @@ -1118,6 +1122,20 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu) context->deferedInitList[context->deferedInitSz++] = h; return; } + // Refresh no-file part of TLS in case default value changed + if(h->tlsfilesize) { + char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase); + printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlsfilesize); + memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize); + tlsdatasize_t* ptr; + if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL) + if(ptr->tlssize==my_context->tlssize) { + // refresh in tlsdata too + dest = (char*)(ptr->tlsdata+ptr->tlssize+h->tlsbase); + printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize); + memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize); + } + } printf_log(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p); if(h->initentry) RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv); diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index d3d09daa..18671d75 100755 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -73,7 +73,9 @@ struct elfheader_s { uint64_t memsz; uint64_t stacksz; size_t stackalign; + uintptr_t tlsaddr; uint64_t tlssize; + uint64_t tlsfilesize; size_t tlsalign; int64_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative) diff --git a/src/wrapped/wrappedldlinux.c b/src/wrapped/wrappedldlinux.c index eaea93d8..e8c56bc0 100755 --- a/src/wrapped/wrappedldlinux.c +++ b/src/wrapped/wrappedldlinux.c @@ -23,7 +23,8 @@ typedef struct my_tls_s { EXPORT void* my___tls_get_addr(x64emu_t* emu, void* p) { my_tls_t *t = (my_tls_t*)p; - return GetDTatOffset(emu->context, t->i, t->o); + void* ret = GetDTatOffset(emu->context, t->i, t->o); + return ret; } // don't try to load the actual ld-linux (because name is variable), just use box64 itself, as it's linked to ld-linux diff --git a/src/wrapped/wrappedldlinux_private.h b/src/wrapped/wrappedldlinux_private.h index 45e234db..76827e8c 100755 --- a/src/wrapped/wrappedldlinux_private.h +++ b/src/wrapped/wrappedldlinux_private.h @@ -20,5 +20,4 @@ DATA(__pointer_chk_guard, sizeof(void*)) DATA(_rtld_global, sizeof(void*)) DATA(_rtld_global_ro, sizeof(void*)) DATA(__stack_chk_guard, sizeof(void*)) -// defined in glibc/sysdeps/i386/dl-tls.h GOM(__tls_get_addr, pFEp) |