diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-08-17 15:59:09 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-08-17 15:59:09 +0200 |
| commit | c845d0cf81a259e0d21be46841dc41a0f0ba5b0e (patch) | |
| tree | 4c34964f41a1e28c1c833266463b55c4ff7c1a3c /src | |
| parent | d47b1b0e5679652e6b5fb5fd4cee52b775229a63 (diff) | |
| download | box64-c845d0cf81a259e0d21be46841dc41a0f0ba5b0e.tar.gz box64-c845d0cf81a259e0d21be46841dc41a0f0ba5b0e.zip | |
[BOX32] Added 32bits elf alloc and load
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.c | 4 | ||||
| -rw-r--r-- | src/custommem.c | 26 | ||||
| -rw-r--r-- | src/custommmap.c | 3 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 7 | ||||
| -rw-r--r-- | src/elfs/elfloader32.c | 249 | ||||
| -rw-r--r-- | src/include/custommem.h | 3 | ||||
| -rw-r--r-- | src/librarian/library.c | 4 |
7 files changed, 288 insertions, 8 deletions
diff --git a/src/core.c b/src/core.c index bfba08f8..eae05d67 100644 --- a/src/core.c +++ b/src/core.c @@ -2087,8 +2087,10 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf } #ifdef BOX32 box64_is32bits = FileIsX86ELF(my_context->fullpath); - if(box64_is32bits) + if(box64_is32bits) { printf_log(LOG_INFO, "BOX64: Using Box32 to load 32bits elf\n"); + reserveHighMem(); + } #endif elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->fullpath, 1); if(!elf_header) { diff --git a/src/custommem.c b/src/custommem.c index da11885f..06b48328 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -1438,6 +1438,21 @@ void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask) return ret; } +void* find31bitBlockElf(size_t size, int mainbin, uintptr_t mask) +{ + static void* startingpoint = NULL; + if(!startingpoint) { + startingpoint = (void*)WINE_LOWEST; + } + void* mainaddr = (void*)0x1000000; + void* ret = find31bitBlockNearHint(MEDIUM, size, mask); + if(!ret) + ret = find31bitBlockNearHint(LOWEST, size, mask); + if(!mainbin) + startingpoint = (void*)(((uintptr_t)startingpoint+size+0x1000000)&~0xffffff); + return ret; +} + int isBlockFree(void* hint, size_t size) { uint32_t prot; @@ -1510,10 +1525,10 @@ static void atfork_child_custommem(void) void my_reserveHighMem() { static int reserved = 0; - if(reserved || !have48bits) + if(reserved || (!have48bits && !box64_is32bits)) return; reserved = 1; - uintptr_t cur = 1ULL<<47; + uintptr_t cur = box64_is32bits?(1ULL<<32):(1ULL<<47); uintptr_t bend = 0; uint32_t prot; while (bend!=0xffffffffffffffffLL) { @@ -1533,12 +1548,13 @@ void my_reserveHighMem() void reserveHighMem() { char* p = getenv("BOX64_RESERVE_HIGH"); + if(!box64_is32bits) #if 0//def ADLINK - if(p && p[0]=='0') + if(p && p[0]=='0') #else - if(!p || p[0]=='0') + if(!p || p[0]=='0') #endif - return; // don't reserve by default + return; // don't reserve by default my_reserveHighMem(); } diff --git a/src/custommmap.c b/src/custommmap.c index 93173098..7ad26b7d 100644 --- a/src/custommmap.c +++ b/src/custommmap.c @@ -15,6 +15,7 @@ typedef void x64emu_t; extern void* mapallmem; +extern int box64_is32bits; void setProtection(uintptr_t addr, size_t size, uint32_t prot); void freeProtection(uintptr_t addr, size_t size); void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset); @@ -28,7 +29,7 @@ extern int box64_mmap32; EXPORT void* mmap64(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset) { void* ret; - if(!addr && ((running32bits && box64_mmap32) || (flags&0x40))) + if(!addr && ((running32bits && box64_mmap32) || (flags&0x40) || box64_is32bits)) ret = my_mmap64(NULL, addr, length, prot, flags | 0x40, fd, offset); else ret = internal_mmap(addr, length, prot, flags, fd, offset); diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index beeacbfb..e206fcc6 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -202,7 +202,12 @@ const char* ElfPath(elfheader_t* head) return head->path; } -int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin) { /*TODO*/ return 1; } +int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin) +#ifndef BOX32 +{ return 1; } +#else + ; +#endif int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) { if(box64_is32bits) diff --git a/src/elfs/elfloader32.c b/src/elfs/elfloader32.c new file mode 100644 index 00000000..1da3fc3b --- /dev/null +++ b/src/elfs/elfloader32.c @@ -0,0 +1,249 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <sys/types.h> +#include <link.h> +#include <unistd.h> +#include <errno.h> +#ifndef _DLFCN_H +#include <dlfcn.h> +#endif + +#include "custommem.h" +#include "box64version.h" +#include "elfloader.h" +#include "debug.h" +#include "elfload_dump.h" +#include "elfloader_private.h" +#include "librarian.h" +#include "x64run.h" +#include "bridge.h" +#include "wrapper.h" +#include "box64context.h" +#include "library.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "box64stack.h" +#include "wine_tools.h" +#include "dictionnary.h" +#include "symbols.h" +#ifdef DYNAREC +#include "dynablock.h" +#endif +#include "../emu/x64emu_private.h" +#include "../emu/x64run_private.h" +#include "../tools/bridge_private.h" +#include "x64tls.h" +#include "box32.h" + +int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin) +{ + ptr_t offs = 0; + loadProtectionFromMap(); + int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG; + + head->multiblock_n = 0; // count PHEntrie with LOAD + uintptr_t max_align = (box64_pagesize-1); + for (size_t i=0; i<head->numPHEntries; ++i) + if(head->PHEntries._32[i].p_type == PT_LOAD && head->PHEntries._32[i].p_flags) { + ++head->multiblock_n; + } + + if(!head->vaddr && box64_load_addr) { + offs = to_ptrv(find31bitBlockNearHint((void*)box64_load_addr, head->memsz, max_align)); + box64_load_addr = offs + head->memsz; + box64_load_addr = (box64_load_addr+0x10ffffff)&~0xffffff; + } + if(!offs && !head->vaddr) + offs = (uintptr_t)find31bitBlockElf(head->memsz, mainbin, max_align); + // prereserve the whole elf image, without populating + size_t sz = head->memsz; + void* raw = NULL; + void* image = NULL; + if(!head->vaddr) { + sz += head->align; + raw = mmap64(from_ptrv(offs), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + image = (void*)(((uintptr_t)raw+max_align)&~max_align); + } else { + image = raw = mmap64(from_ptrv(head->vaddr), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + } + if(image!=MAP_FAILED && !head->vaddr && image!=from_ptrv(offs)) { + printf_log(LOG_INFO, "%s: Mmap64 for (@%p 0x%zx) for elf \"%s\" returned %p(%p/0x%zx) instead\n", (((uintptr_t)image)&max_align)?"Error":"Warning", from_ptrv(head->vaddr?head->vaddr:offs), head->memsz, head->name, image, raw, head->align); + offs = to_ptrv(image); + if(((uintptr_t)image)&max_align) { + munmap(raw, sz); + return 1; // that's an error, alocated memory is not aligned properly + } + } + if(image==MAP_FAILED || image!=from_ptrv(head->vaddr?head->vaddr:offs)) { + printf_log(LOG_NONE, "%s cannot create memory map (@%p 0x%zx) for elf \"%s\"", (image==MAP_FAILED)?"Error:":"Warning:", from_ptrv(head->vaddr?head->vaddr:offs), head->memsz, head->name); + if(image==MAP_FAILED) { + printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno)); + } else { + printf_log(LOG_NONE, " got %p\n", image); + } + if(image==MAP_FAILED) + return 1; + offs = to_ptrv(image)-head->vaddr; + } + printf_dump(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name); + head->delta = offs; + printf_dump(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", from_ptrv(offs), from_ptrv(head->vaddr), head->name); + + head->image = image; + head->raw = raw; + head->raw_size = sz; + setProtection_elf((uintptr_t)raw, sz, 0); + + 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*)0xffffffff; + int n = 0; + for (size_t i=0; i<head->numPHEntries; ++i) { + if(head->PHEntries._32[i].p_type == PT_LOAD && head->PHEntries._32[i].p_flags) { + Elf32_Phdr * e = &head->PHEntries._32[i]; + + 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; + uint8_t prot = PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0); + // check if alignment is correct + uintptr_t balign = head->multiblocks[n].align-1; + if(balign<4095) balign = 4095; + head->multiblocks[n].asize = (e->p_memsz+(e->p_paddr&balign)+4095)&~4095; + int try_mmap = 1; + if(e->p_paddr&balign) + try_mmap = 0; + if(e->p_offset&(box64_pagesize-1)) + try_mmap = 0; + if(ALIGN(e->p_memsz)!=ALIGN(e->p_filesz)) + try_mmap = 0; + if(!e->p_filesz) + try_mmap = 0; + if(e->p_align<box64_pagesize) + try_mmap = 0; + if(try_mmap) { + printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name); + void* p = mmap64( + (void*)head->multiblocks[n].paddr, + head->multiblocks[n].size, + prot, + MAP_PRIVATE|MAP_FIXED, //((prot&PROT_WRITE)?MAP_SHARED:MAP_PRIVATE)|MAP_FIXED, + head->fileno, + e->p_offset + ); + if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) { + try_mmap = 0; + printf_dump(log_level, "Mapping failed, using regular mmap+read"); + } else { + if(e->p_memsz>e->p_filesz && (prot&PROT_WRITE)) + memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz); + setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot); + head->multiblocks[n].p = p; + + } + } + if(!try_mmap) { + uintptr_t paddr = head->multiblocks[n].paddr&~balign; + size_t asize = head->multiblocks[n].asize; + void* p = MAP_FAILED; + if(paddr==(paddr&~(box64_pagesize-1)) && (asize==ALIGN(asize))) { + printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); + p = mmap64( + (void*)paddr, + asize, + prot|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, + -1, + 0 + ); + } else { + // difference in pagesize, so need to mmap only what needed to be... + //check startint point + uintptr_t new_addr = paddr; + ssize_t new_size = asize; + while(getProtection(new_addr) && (new_size>0)) { + new_size -= ALIGN(new_addr) - new_addr; + new_addr = ALIGN(new_addr); + } + if(new_size>0) { + printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", ALIGN(new_size), e->p_memsz, (void*)new_addr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); + p = mmap64( + (void*)new_addr, + ALIGN(new_size), + prot|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, + -1, + 0 + ); + if(p==(void*)new_addr) + p = (void*)paddr; + } else { + p = (void*)paddr; + printf_dump(log_level, "Will read 0x%zx @%p for Elf \"%s\"\n", e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); + } + } + if(p==MAP_FAILED || p!=(void*)paddr) { + printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, asize, balign, head->name); + if(p==MAP_FAILED) { + printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno)); + } else { + printf_log(LOG_NONE, " got %p\n", p); + } + return 1; + } + setProtection_elf((uintptr_t)p, asize, prot); + head->multiblocks[n].p = p; + if(e->p_filesz) { + 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; + } + } + if(!(prot&PROT_WRITE) && (paddr==(paddr&(box64_pagesize-1)) && (asize==ALIGN(asize)))) + mprotect((void*)paddr, asize, prot); + } +#ifdef DYNAREC + if(box64_dynarec && (e->p_flags & PF_X)) { + 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 + if((uintptr_t)head->memory>(uintptr_t)head->multiblocks[n].p) + head->memory = (char*)head->multiblocks[n].p; + ++n; + } + if(head->PHEntries._32[i].p_type == PT_TLS) { + Elf32_Phdr * e = &head->PHEntries._32[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(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; + } + } + // 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); + } + } + + // can close the elf file now! + fclose(head->file); + head->file = NULL; + head->fileno = -1; + + return 0; +} diff --git a/src/include/custommem.h b/src/include/custommem.h index dda21053..ba5441d1 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -102,6 +102,7 @@ void* find31bitBlockNearHint(void* hint, size_t size, uintptr_t mask); void* find47bitBlock(size_t size); void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask); // mask can be 0 for default one (0xffff) void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask); +void* find31bitBlockElf(size_t size, int mainbin, uintptr_t mask); int isBlockFree(void* hint, size_t size); // unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex @@ -125,4 +126,6 @@ int checkInHotPage(uintptr_t addr); void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset); int internal_munmap(void* addr, unsigned long length); +void reserveHighMem(); + #endif //__CUSTOM_MEM__H_ diff --git a/src/librarian/library.c b/src/librarian/library.c index 350a68a9..69f27d5f 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -232,6 +232,10 @@ int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr } static void initWrappedLib(library_t *lib, box64context_t* context) { + if(box64_is32bits) { + // TODO + return; // nothing wrapped yet + } int nb = sizeof(wrappedlibs) / sizeof(wrappedlib_t); for (int i=0; i<nb; ++i) { if(strcmp(lib->name, wrappedlibs[i].name)==0) { |