diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-10-31 15:38:31 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-10-31 15:38:31 +0100 |
| commit | 362a3fde10a3bb2738fcf30ae2e2eaf4a53df042 (patch) | |
| tree | ff6233f6cba44c0326cbe366d79fb7a46e1b8d60 /src | |
| parent | 5c13f8f10ac82ca642a6c930585989cc0d75a664 (diff) | |
| download | box64-362a3fde10a3bb2738fcf30ae2e2eaf4a53df042.tar.gz box64-362a3fde10a3bb2738fcf30ae2e2eaf4a53df042.zip | |
[ELFLOADER] Changed how memory is managed in elfloader
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 17 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 313 | ||||
| -rw-r--r-- | src/elfs/elfloader_private.h | 21 | ||||
| -rw-r--r-- | src/include/custommem.h | 1 | ||||
| -rw-r--r-- | src/include/elfloader.h | 5 | ||||
| -rw-r--r-- | src/librarian/library.c | 60 | ||||
| -rw-r--r-- | src/main.c | 21 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 12 |
8 files changed, 159 insertions, 291 deletions
diff --git a/src/custommem.c b/src/custommem.c index 51359bd4..b85b2257 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -85,6 +85,7 @@ static uint64_t memprot_allocated = 0, memprot_max_allocated = 0; #endif static memprot_t memprot[1<<MEMPROT_SIZE0]; // x86_64 mem is 48bits, page is 12bits, so memory is tracked as [20][16][page protection] static uint8_t memprot_default[MEMPROT_SIZE]; +static int have48bits = 0; static int inited = 0; typedef struct mapmem_s { @@ -1410,6 +1411,8 @@ void loadProtectionFromMap() if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) { int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0); allocProtection(s, e-s, prot); + if(s>0x7fff00000000LL) + have48bits = 1; } } fclose(f); @@ -1570,6 +1573,20 @@ void* find47bitBlockNearHint(void* hint, size_t size) } return NULL; } +void* find47bitBlockElf(size_t size, int mainbin) +{ + static void* startingpoint = NULL; + if(!startingpoint) { + startingpoint = (void*)(have48bits?0x7fff00000000LL:0x7f00000000LL); + } + void* mainaddr = (void*)0x100000000LL; + void* ret = find47bitBlockNearHint(mainbin?mainaddr:startingpoint, size); + if(!ret) + ret = find32bitBlock(size); + if(!mainbin) + startingpoint = (void*)(((uintptr_t)startingpoint+size+0x1000000LL)&~0xffffffLL); + return ret; +} int isBlockFree(void* hint, size_t size) { diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 818d7d5f..a7d6e5b3 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -69,6 +69,9 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec) h->globaldefver = NewDefaultVersion(); h->weakdefver = NewDefaultVersion(); h->refcnt = 1; + + h->file = f; + h->fileno = fileno(f); return h; } @@ -100,6 +103,8 @@ void FreeElfHeader(elfheader_t** head) box_free(h->name); box_free(h->path); + if(h->file) + fclose(h->file); box_free(h); *head = NULL; @@ -169,201 +174,112 @@ const char* ElfPath(elfheader_t* head) return NULL; return head->path; } -int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin) +int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) { uintptr_t offs = 0; + loadProtectionFromMap(); if(!head->vaddr && box64_load_addr) { offs = (uintptr_t)find47bitBlockNearHint((void*)box64_load_addr, head->memsz); box64_load_addr += head->memsz; box64_load_addr = (box64_load_addr+0x10ffffffLL)&~0xffffffLL; } int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG; - if(!offs) - offs = head->vaddr; - if(head->vaddr) { - head->multiblock_n = 0; // count PHEntrie with LOAD - for (size_t i=0; i<head->numPHEntries; ++i) - if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) - ++head->multiblock_n; - head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t)); - head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t)); - head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*)); - // and now, create all individual blocks - head->memory = (char*)0xffffffffffffffff; - int n = 0; - for (size_t i=0; i<head->numPHEntries; ++i) - if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) { - Elf64_Phdr * e = &head->PHEntries[i]; - uintptr_t bstart = e->p_vaddr; - uint64_t bsize = e->p_memsz; - uintptr_t balign = e->p_align; - if (balign) balign = balign-1; else balign = 1; - if(balign<4095) balign = 4095; - uintptr_t bend = (bstart + bsize + balign)&(~balign); - bstart &= ~balign; - int ok = 0; - for (int j=0; !ok && j<n; ++j) { - uintptr_t start = head->multiblock_offs[j]; - uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j]; - start &= ~balign; - if( (head->e_type == ET_DYN) || - (((bstart>=start) && (bstart<=end+0x1000)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end)))) - { - // merge - ok = 1; - if(bstart<start) - head->multiblock_offs[j] = bstart; - head->multiblock_size[j] = ((bend>end)?bend:end) - head->multiblock_offs[j]; - --head->multiblock_n; - } - } - if(!ok) { - head->multiblock_offs[n] = bstart; - head->multiblock_size[n] = bend - head->multiblock_offs[n]; - ++n; - } - } - head->multiblock_n = n; // might be less in fact - for (int i=0; i<head->multiblock_n; ++i) { - printf_log(log_level, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name); - void* p = mmap((void*)head->multiblock_offs[i], head->multiblock_size[i] - , PROT_READ | PROT_WRITE | PROT_EXEC - , MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/ - , -1, 0); - if(p==MAP_FAILED) { - printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name); - return 1; - } - if(head->multiblock_offs[i] &&( p!=(void*)head->multiblock_offs[i])) { - if((head->e_type!=ET_DYN)) { - printf_log(LOG_NONE, "Error, memory map (@%p 0x%zx/0x%zx) for elf \"%s\" allocated @%p\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name, p); - return 1; - } else { - printf_log(LOG_INFO, "Allocated memory is not at hinted %p but %p (size %lx) \"%s\"\n", (void*)head->multiblock_offs[i], p, head->multiblock_size[i], head->name); - // need to adjust vaddr! - for (size_t j=0; j<head->numPHEntries; ++j) - if(head->PHEntries[j].p_type == PT_LOAD) { - Elf64_Phdr * e = &head->PHEntries[j]; - if(e->p_vaddr>=head->multiblock_offs[j] && e->p_vaddr<(head->multiblock_offs[j]+head->multiblock_size[j])) { - e->p_vaddr = e->p_vaddr - head->multiblock_offs[j] + (uintptr_t)p; - if(!head->delta) head->delta = (intptr_t)p - (intptr_t)head->multiblock_offs[j]; - } - } - } - } - setProtection((uintptr_t)p, head->multiblock_size[i], PROT_READ | PROT_WRITE | PROT_EXEC); - head->multiblock[i] = p; - if(p<(void*)head->memory) - head->memory = (char*)p; - } - } else { - // vaddr is 0, load everything has a One block - uintptr_t old_offs = offs; - if(!offs /*&& box64_wine*/) - offs = (uintptr_t)find47bitBlock(head->memsz); // limit to 47bits... - printf_log(log_level, "Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name); - void* p = mmap((void*)offs, head->memsz - , PROT_READ | PROT_WRITE | PROT_EXEC - , MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/ - , -1, 0); - if(offs &&!old_offs && p!=MAP_FAILED && offs!=(uintptr_t)p) { - // try again - munmap(p, head->memsz); - loadProtectionFromMap(); - offs = (uintptr_t)find47bitBlock(head->memsz); - printf_log(log_level, "New, try. Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name); - p = mmap((void*)offs, head->memsz - , PROT_READ | PROT_WRITE | PROT_EXEC - , MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/ - , -1, 0); - } - if(p==MAP_FAILED) { - printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name); - return 1; - } - if(offs && (p!=(void*)offs) && (head->e_type!=ET_DYN)) { - printf_log(LOG_NONE, "Error, memory map (@%p 0x%zx/0x%zx) for elf \"%s\" allocated @%p\n", (void*)offs, head->memsz, head->align, head->name, p); - return 1; - } - setProtection((uintptr_t)p, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC); - head->memory = p; - memset(p, 0, head->memsz); - head->delta = (intptr_t)p - (intptr_t)head->vaddr; - printf_log(log_level, "Got %p (delta=%p)\n", p, (void*)head->delta); - - head->multiblock_n = 1; - head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t)); - head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t)); - head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*)); - head->multiblock_size[0] = head->memsz; - head->multiblock_offs[0] = (uintptr_t)p; - head->multiblock[0] = p; - } + if(!offs && !head->vaddr) + offs = (uintptr_t)find47bitBlockElf(head->memsz, mainbin); // limit to 47bits... - head->tlsbase = AddTLSPartition(context, head->tlssize); - - return 0; -} - -void FreeElfMemory(elfheader_t* head) -{ - if(head->multiblock_n) { - for(int i=0; i<head->multiblock_n; ++i) { -#ifdef DYNAREC - dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path); - if(box64_dynarec) { - cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1); - freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]); - } -#endif - munmap(head->multiblock[i], head->multiblock_size[i]); - } - box_free(head->multiblock); - box_free(head->multiblock_size); - box_free(head->multiblock_offs); - } -} + head->delta = offs; + printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name); -int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) -{ + head->multiblock_n = 0; // count PHEntrie with LOAD + for (size_t i=0; i<head->numPHEntries; ++i) + if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) + ++head->multiblock_n; + head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t)); + head->tlsbase = AddTLSPartition(context, head->tlssize); + // and now, create all individual blocks + head->memory = (char*)0xffffffffffffffff; + int n = 0; for (size_t i=0; i<head->numPHEntries; ++i) { if(head->PHEntries[i].p_type == PT_LOAD) { Elf64_Phdr * e = &head->PHEntries[i]; - char* dest = (char*)e->p_paddr + head->delta; - printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz); - void* p = (void*)-1; - if(e->p_memsz==e->p_filesz && !(e->p_align&(box64_pagesize-1))) { - printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags); - p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset); + + head->multiblocks[n].flags = e->p_flags; + head->multiblocks[n].offs = e->p_offset; + head->multiblocks[n].paddr = e->p_paddr + offs; + head->multiblocks[n].size = e->p_filesz; + head->multiblocks[n].align = e->p_align; + // check if alignment is correct + uintptr_t balign = head->multiblocks[n].align-1; + if(balign<(box64_pagesize-1)) balign = (box64_pagesize-1); + head->multiblocks[n].asize = e->p_memsz+(head->multiblocks[n].paddr&balign); + int try_mmap = 1; + if(e->p_offset&balign) + try_mmap = 0; + if(e->p_memsz-e->p_filesz>balign) + try_mmap = 0; + if(head->multiblocks[n].asize != head->multiblocks[n].size) + try_mmap = 0; + if(!e->p_flags) + try_mmap = 0; + uint8_t prot = e->p_flags?(PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0)):0; + if(try_mmap) { + printf_log(log_level, "Mmaping 0x%lx memory @%p for Elf \"%s\"\n", head->multiblocks[n].size, (void*)head->multiblocks[n].paddr, head->name); + void* p = mmap64( + (void*)head->multiblocks[n].paddr, + head->multiblocks[n].asize, + prot, + MAP_PRIVATE, + head->fileno, + e->p_offset + ); + if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) { + try_mmap = 0; + printf_log(log_level, "Mapping failed, using regular mmap+read"); + } else { + setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot); + head->multiblocks[n].p = p; + + } } - if(p!=dest) { - printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz); - fseeko64(f, e->p_offset, SEEK_SET); - if(e->p_filesz) { - if(fread(dest, e->p_filesz, 1, f)!=1) { - printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%zd)\n", i, e->p_filesz); - return 1; - } + if(!try_mmap) { + uintptr_t paddr = head->multiblocks[n].paddr&~balign; + printf_log(log_level, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblocks[n].asize, (void*)paddr, head->name); + void* p = mmap64( + (void*)paddr, + head->multiblocks[n].asize, + prot, + MAP_PRIVATE|MAP_ANONYMOUS|(e->p_flags?MAP_NORESERVE:0), + -1, + 0 + ); + if(p==MAP_FAILED || p!=(void*)paddr) { + printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name); + return 1; + } + setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot); + fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET); + if(fread((void*)head->multiblocks[n].paddr, head->multiblocks[n].size, 1, head->file)!=1) { + printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name); + return 1; } } #ifdef DYNAREC if(box64_dynarec && (e->p_flags & PF_X)) { - dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz); - addDBFromAddressRange((uintptr_t)dest, e->p_memsz); + dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", head->multiblocks[n].p, (void*)head->multiblocks[n].asize); + addDBFromAddressRange((uintptr_t)head->multiblocks[n].p, head->multiblocks[n].asize); } #endif - - // zero'd difference between filesz and memsz - /*if(e->p_filesz != e->p_memsz) - memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/ //block is already 0'd at creation + if((uintptr_t)head->memory>(uintptr_t)head->multiblocks[n].p) + head->memory = (char*)head->multiblocks[n].p; + ++n; } if(head->PHEntries[i].p_type == PT_TLS) { Elf64_Phdr * e = &head->PHEntries[i]; char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); if(e->p_filesz) { - fseeko64(f, e->p_offset, SEEK_SET); - if(fread(dest, e->p_filesz, 1, f)!=1) { + fseeko64(head->file, e->p_offset, SEEK_SET); + if(fread(dest, e->p_filesz, 1, head->file)!=1) { printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz); return 1; } @@ -373,9 +289,31 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz); } } + + // can close the elf file now! + fclose(head->file); + head->file = NULL; + head->fileno = -1; + return 0; } +void FreeElfMemory(elfheader_t* head) +{ + if(head->multiblock_n) { + for(int i=0; i<head->multiblock_n; ++i) { +#ifdef DYNAREC + dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path); + if(box64_dynarec) + cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].size, 1); +#endif + munmap(head->multiblocks[i].p, head->multiblocks[i].asize); + freeProtection((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize); + } + box_free(head->multiblocks); + } +} + int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded) { if(!verneeded || !head) @@ -393,39 +331,6 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne return 1; } -int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) -{ - (void)context; - - for (size_t i=0; i<head->numPHEntries; ++i) { - if(head->PHEntries[i].p_type == PT_LOAD) { - Elf64_Phdr * e = &head->PHEntries[i]; - char* dest = (char*)e->p_paddr + head->delta; - printf_log(LOG_DEBUG, "Re-loading block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); - int ret = fseeko64(f, e->p_offset, SEEK_SET); - if(ret==-1) {printf_log(LOG_NONE, "Fail to (re)seek PT_LOAD part #%zu (offset=%ld, errno=%d/%s)\n", i, e->p_offset, errno, strerror(errno)); return 1;} - #ifdef DYNAREC - cleanDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0); - #endif - uint32_t page_offset = (uintptr_t)dest & (box64_pagesize - 1); - mprotect(dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC); - setProtection((uintptr_t)dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC); - if(e->p_filesz) { - ssize_t r = -1; - if((r=fread(dest, e->p_filesz, 1, f))!=1) { - printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%zu (dest=%p, size=%zd, return=%zd, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f))); - return 1; - } - } - // zero'd difference between filesz and memsz - if(e->p_filesz != e->p_memsz) - memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz); - } - } - // TLS data are just a copy, no need to re-load it - return 0; -} - int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername) { if(!h) @@ -1444,8 +1349,8 @@ int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr) if(!h) return 0; for(int i=0; i<h->multiblock_n; ++i) { - uintptr_t base = h->multiblock_offs[i]; - uintptr_t end = h->multiblock_offs[i] + h->multiblock_size[i] - 1; + uintptr_t base = h->multiblocks[i].paddr; + uintptr_t end = h->multiblocks[i].paddr + h->multiblocks[i].size - 1; if(addr>=base && addr<=end) return 1; diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index d2bc2559..b80c87db 100644 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -9,7 +9,17 @@ typedef struct kh_defaultversion_s kh_defaultversion_t; #include <elf.h> #include "elfloader.h" -struct elfheader_s { +typedef struct multiblock_s { + void* p; + uintptr_t offs; + uintptr_t paddr; + uintptr_t align; + uint64_t size; + uint64_t asize; + uint8_t flags; +} multiblock_t; + +typedef struct elfheader_s { char* name; char* path; // Resolved path to file char* soname; // soname of the elf @@ -90,20 +100,21 @@ struct elfheader_s { int malloc_hook_2; // this elf hook malloc, hacking it char* memory; // char* and not void* to allow math on memory pointer - void** multiblock; - uintptr_t* multiblock_offs; - uint64_t* multiblock_size; + multiblock_t* multiblocks; int multiblock_n; library_t *lib; // attached lib (exept on main elf) needed_libs_t* needed; + FILE* file; + int fileno; + kh_mapsymbols_t *mapsymbols; kh_mapsymbols_t *weaksymbols; kh_mapsymbols_t *localsymbols; kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols) kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols) -}; +} elfheader_t; #define R_X86_64_NONE 0 /* No reloc */ #define R_X86_64_64 1 /* Direct 64 bit */ diff --git a/src/include/custommem.h b/src/include/custommem.h index 31b3f30e..ffd20af6 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -96,6 +96,7 @@ void* find32bitBlock(size_t size); void* find31bitBlockNearHint(void* hint, size_t size); void* find47bitBlock(size_t size); void* find47bitBlockNearHint(void* hint, size_t size); +void* find47bitBlockElf(size_t size, int mainbin); int isBlockFree(void* hint, size_t size); // unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex diff --git a/src/include/elfloader.h b/src/include/elfloader.h index d9d7f152..bc09ad31 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -14,6 +14,7 @@ typedef struct kh_defaultversion_s kh_defaultversion_t; typedef struct dynablock_s dynablock_t; #endif +// Open an elfheader. Transfert control of f to elfheader also! elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec void FreeElfHeader(elfheader_t** head); const char* ElfName(elfheader_t* head); @@ -22,11 +23,9 @@ void ElfAttachLib(elfheader_t* head, library_t* lib); // return 0 if OK int CalcLoadAddr(elfheader_t* head); -int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin); +int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin); void FreeElfMemory(elfheader_t* head); -int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head); int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded); -int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head); int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head); int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head); void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign); diff --git a/src/librarian/library.c b/src/librarian/library.c index a64ea596..896c6d0d 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -261,25 +261,15 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* if(CalcLoadAddr(elf_header)) { printf_log(LOG_NONE, "Error: reading elf header of %s\n", libname); FreeElfHeader(&elf_header); - fclose(f); return 0; } - // allocate memory - if(AllocElfMemory(context, elf_header, 0)) { - printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", libname); + // allocate and load elf + if(AllocLoadElfMemory(context, elf_header, 0)) { + printf_log(LOG_NONE, "Error: loading for elf %s\n", libname); FreeElfHeader(&elf_header); - fclose(f); - return 0; - } - // Load elf into memory - if(LoadElfMemory(f, context, elf_header)) { - printf_log(LOG_NONE, "Error: loading in memory elf %s\n", libname); - FreeElfHeader(&elf_header); - fclose(f); return 0; } // can close the file now - fclose(f); if(verneeded && !isElfHasNeededVer(elf_header, lib->name, verneeded)) { // incompatible, discard and continue the search FreeElfHeader(&elf_header); @@ -488,50 +478,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* return 0; } -int ReloadLibrary(library_t* lib, x64emu_t* emu) -{ - if(lib->type==LIB_EMULATED) { - elfheader_t *elf_header = lib->e.elf; - // reload image in memory and re-run the mapping - char libname[MAX_PATH]; - strcpy(libname, lib->path); - int found = FileExist(libname, IS_FILE); - if(!found && !strchr(lib->path, '/')) - for(int i=0; i<my_context->box64_ld_lib.size; ++i) - { - strcpy(libname, my_context->box64_ld_lib.paths[i]); - strcat(libname, lib->path); - if(FileExist(libname, IS_FILE)) - break; - } - if(!FileExist(libname, IS_FILE)) { - printf_log(LOG_NONE, "Error: open file to re-load elf %s\n", libname); - return 1; // failed to reload... - } - FILE *f = fopen(libname, "rb"); - if(!f) { - printf_log(LOG_NONE, "Error: cannot open file to re-load elf %s (errno=%d/%s)\n", libname, errno, strerror(errno)); - return 1; // failed to reload... - } - if(ReloadElfMemory(f, my_context, elf_header)) { - printf_log(LOG_NONE, "Error: re-loading in memory elf %s\n", libname); - fclose(f); - return 1; - } - // can close the file now - fclose(f); - // should bindnow be store in a per/library basis? - if(RelocateElf(my_context->maplib, lib->maplib, 0, elf_header)) { - printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name); - return 1; - } - RelocateElfPlt(my_context->maplib, lib->maplib, 0, elf_header); - // init (will use PltRelocator... because some other libs are not yet resolved) - RunElfInit(elf_header, emu); - } - return 0; -} - int FiniLibrary(library_t* lib, x64emu_t* emu) { switch (lib->type) { diff --git a/src/main.c b/src/main.c index eb185c66..0d0a61cf 100644 --- a/src/main.c +++ b/src/main.c @@ -1728,32 +1728,21 @@ int main(int argc, const char **argv, char **env) { if(CalcLoadAddr(elf_header)) { printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->fullpath); - fclose(f); - free_contextargv(); - FreeBox64Context(&my_context); - FreeCollection(&ld_preload); - return -1; - } - // allocate memory - if(AllocElfMemory(my_context, elf_header, 1)) { - printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->fullpath); - fclose(f); + FreeElfHeader(&elf_header); free_contextargv(); FreeBox64Context(&my_context); FreeCollection(&ld_preload); return -1; } - // Load elf into memory - if(LoadElfMemory(f, my_context, elf_header)) { - printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->fullpath); - fclose(f); + // allocate memory and load elf + if(AllocLoadElfMemory(my_context, elf_header, 1)) { + printf_log(LOG_NONE, "Error: loading elf %s\n", my_context->fullpath); + FreeElfHeader(&elf_header); free_contextargv(); FreeBox64Context(&my_context); FreeCollection(&ld_preload); return -1; } - // can close the file now - fclose(f); if(ElfCheckIfUseTCMallocMinimal(elf_header)) { if(!box64_tcmalloc_minimal) { // need to reload with tcmalloc_minimal as a LD_PRELOAD! diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index b9ed9c42..ce284a8d 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -2556,7 +2556,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot (void)emu; if(prot&PROT_WRITE) prot|=PROT_READ; // PROT_READ is implicit with PROT_WRITE on i386 - if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) => ", addr, length, prot, flags, fd, offset);} + if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) => ", addr, length, prot, flags, fd, offset);} int new_flags = flags; #ifndef NOALIGN void* old_addr = addr; @@ -2598,7 +2598,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot errno = EEXIST; return MAP_FAILED; } - if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "%p\n", ret);} + if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);} #ifdef DYNAREC if(box64_dynarec && ret!=MAP_FAILED) { /*if(flags&0x100000 && addr!=ret) @@ -2623,9 +2623,9 @@ EXPORT void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr) { (void)emu; - if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "mremap(%p, %lu, %lu, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);} + if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mremap(%p, %lu, %lu, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);} void* ret = mremap(old_addr, old_size, new_size, flags, new_addr); - if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "%p\n", ret);} + if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);} if(ret!=(void*)-1) { uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM; if(ret==old_addr) { @@ -2673,7 +2673,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length) { (void)emu; - if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "munmap(%p, %lu)\n", addr, length);} + if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "munmap(%p, %lu)\n", addr, length);} int ret = munmap(addr, length); #ifdef DYNAREC if(!ret && box64_dynarec && length) { @@ -2689,7 +2689,7 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length) EXPORT int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot) { (void)emu; - if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "mprotect(%p, %lu, 0x%x)\n", addr, len, prot);} + if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mprotect(%p, %lu, 0x%x)\n", addr, len, prot);} if(prot&PROT_WRITE) prot|=PROT_READ; // PROT_READ is implicit with PROT_WRITE on x86_64 int ret = mprotect(addr, len, prot); |