From 34b85b3560385d4aef73c64548e200f6bb0e264e Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 16 Aug 2024 10:52:31 +0200 Subject: Detect 32bits elf before loading --- src/core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/core.c') diff --git a/src/core.c b/src/core.c index aca52b47..bfba08f8 100644 --- a/src/core.c +++ b/src/core.c @@ -58,6 +58,7 @@ int box64_dynarec_test = 0; path_collection_t box64_addlibs = {0}; int box64_maxcpu = 0; int box64_maxcpu_immutable = 0; +int box64_is32bits = 0; #if defined(SD845) || defined(SD888) || defined(SD8G2) || defined(TEGRAX1) int box64_mmap32 = 1; #else @@ -2084,6 +2085,11 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf FreeCollection(&ld_preload); return -1; } + #ifdef BOX32 + box64_is32bits = FileIsX86ELF(my_context->fullpath); + if(box64_is32bits) + printf_log(LOG_INFO, "BOX64: Using Box32 to load 32bits elf\n"); + #endif elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->fullpath, 1); if(!elf_header) { int x86 = my_context->box86path?FileIsX86ELF(my_context->fullpath):0; -- cgit 1.4.1 From c845d0cf81a259e0d21be46841dc41a0f0ba5b0e Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sat, 17 Aug 2024 15:59:09 +0200 Subject: [BOX32] Added 32bits elf alloc and load --- CMakeLists.txt | 1 + src/core.c | 4 +- src/custommem.c | 26 ++++- src/custommmap.c | 3 +- src/elfs/elfloader.c | 7 +- src/elfs/elfloader32.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++ src/include/custommem.h | 3 + src/librarian/library.c | 4 + 8 files changed, 289 insertions(+), 8 deletions(-) create mode 100644 src/elfs/elfloader32.c (limited to 'src/core.c') diff --git a/CMakeLists.txt b/CMakeLists.txt index 4430a3c2..62ee961c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,6 +365,7 @@ if(NOT STATICBUILD) endif() if(BOX32) list(APPEND ELFLOADER_SRC + "${BOX64_ROOT}/src/elfs/elfloader32.c" "${BOX64_ROOT}/src/elfs/elfparser32.c" "${BOX64_ROOT}/src/elfs/elfload_dump32.c" ) 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _DLFCN_H +#include +#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; inumPHEntries; ++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; inumPHEntries; ++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_alignmultiblocks[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; iname, wrappedlibs[i].name)==0) { -- cgit 1.4.1 From dead2003fa59cbfa6a2fd8ba285bdf28aac953f3 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sun, 18 Aug 2024 10:16:38 +0200 Subject: [HACK] Patch Heroic 2.15.1 to avoid some internal memory manager test, until a better solution is found (heroic is still a bit unstable) --- src/core.c | 12 ++++++++++++ system/box64.box64rc | 1 - 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/core.c') diff --git a/src/core.c b/src/core.c index eae05d67..3283a6c2 100644 --- a/src/core.c +++ b/src/core.c @@ -2145,6 +2145,18 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf FreeCollection(&ld_preload); return -1; } + if(!strcmp(prgname, "heroic")) { + // check if heroic needs patching (for the 2.15.1 version) + uint8_t* address = GetBaseAddress(elf_header); + if(address[0x422f6e1]==0x72 && address[0x422f6e2]==0x44 && address[0x422f6e0]==0xF8 && address[0x422f727]==0xcc) { + printf_log(LOG_INFO, "Patched heroic!\n"); + uintptr_t page = ((uintptr_t)&address[0x422f6e1])&~(box64_pagesize-1); + int prot = getProtection(page); + mprotect((void*)page, box64_pagesize, PROT_READ|PROT_WRITE|PROT_EXEC); + address[0x422f6e1]=0x90; address[0x422f6e2]=0x90; + mprotect((void*)page, box64_pagesize, prot); + } + } if(ElfCheckIfUseTCMallocMinimal(elf_header)) { if(!box64_tcmalloc_minimal) { // need to reload with tcmalloc_minimal as a LD_PRELOAD! diff --git a/system/box64.box64rc b/system/box64.box64rc index 383c01d7..dc4a2fc6 100644 --- a/system/box64.box64rc +++ b/system/box64.box64rc @@ -117,7 +117,6 @@ BOX64_MAXCPU=16 BOX64_NOSANDBOX=1 BOX64_INPROCESSGPU=1 BOX64_MALLOC_HACK=2 -BOX64_DYNAREC_BIGBLOCK=0 BOX64_DYNAREC_CALLRET=1 BOX64_DYNAREC_ALIGNED_ATOMICS=1 BOX64_DYNAREC_STRONGMEM=1 -- cgit 1.4.1