diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-07-01 17:09:03 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-07-01 17:09:03 +0200 |
| commit | 56401f667525063eac16081d19395527d3403e60 (patch) | |
| tree | 996b917a9d139eaa26e3d313fe3672a8abc6d010 /src | |
| parent | 99ba7707f63d906f5e22a44ae2cbbc8dbd5e3f3e (diff) | |
| download | box64-56401f667525063eac16081d19395527d3403e60.tar.gz box64-56401f667525063eac16081d19395527d3403e60.zip | |
Improved low memory pre-allocation and added 47bits pre-allocation for Wine64
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 169 | ||||
| -rwxr-xr-x | src/elfs/elfloader.c | 2 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 8 | ||||
| -rw-r--r-- | src/include/custommem.h | 3 | ||||
| -rwxr-xr-x | src/include/debug.h | 1 | ||||
| -rwxr-xr-x | src/main.c | 17 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 5 |
7 files changed, 168 insertions, 37 deletions
diff --git a/src/custommem.c b/src/custommem.c index e1413157..0794353c 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -826,6 +826,51 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot) pthread_mutex_unlock(&mutex_prot); } +void allocProtection(uintptr_t addr, size_t size, uint32_t prot) +{ + dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot); + uintptr_t idx = (addr>>MEMPROT_SHIFT); + uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT); + int ret; + pthread_mutex_lock(&mutex_prot); + for (uintptr_t i=idx; i<=end; ++i) { + const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff; + khint_t k = kh_put(memprot, memprot, key, &ret); + if(ret) { + uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE); + kh_value(memprot, k) = m; + } + const uintptr_t start = i&(MEMPROT_SIZE-1); + const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1); + uint8_t* block = kh_value(memprot, k); + for(uintptr_t ii = start; ii<=finish; ++ii) { + if(!block[ii]) + block[ii] = prot; + } + i+=finish-start; // +1 from the "for" loop + } + pthread_mutex_unlock(&mutex_prot); +} + +void loadProtectionFromMap() +{ + char buf[500]; + FILE *f = fopen("/proc/self/maps", "r"); + if(!f) + return; + while(!feof(f)) { + char* ret = fgets(buf, sizeof(buf), f); + (void)ret; + char r, w, x; + uintptr_t s, e; + 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); + } + } + fclose(f); +} + static int blockempty(uint8_t* mem) { for (int i=0; i<(MEMPROT_SIZE); ++i) @@ -881,52 +926,112 @@ int availableBlock(uint8_t* p, size_t n) return 0; return 1; } +static uintptr_t nextFree(uintptr_t addr) +{ + do { + const uint32_t key = (addr>>32)&0xffffffff; + khint_t k = kh_get(memprot, memprot, key); + if(k==kh_end(memprot)) { + return addr; + } + uint8_t *block = kh_value(memprot, k); + for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i) + if(!block[i]) { + return addr+(i<<MEMPROT_SHIFT); + } + addr += 0x100000000LL; + addr &= ~0xffffffffLL; + } while(1); +} +static uintptr_t maxFree(uintptr_t addr, uintptr_t sz) +{ + uintptr_t mfree = 0; + do { + const uint32_t key = (addr>>32)&0xffffffff; + khint_t k = kh_get(memprot, memprot, key); + if(k==kh_end(memprot)) { + mfree+=0x100000000LL; + if(mfree>sz) { + return addr; + } + } else { + uint8_t *block = kh_value(memprot, k); + for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i) + if(!block[i]) { + mfree+=1<<MEMPROT_SHIFT; + } else + return mfree; + } + addr += 0x100000000LL; + addr &= ~0xffffffffLL; + } while(1); +} void* find32bitBlock(size_t size) { + return findBlockNearHint(LOWEST, size); +} +void* find47bitBlock(size_t size) +{ // slow iterative search... Would need something better one day - const uint32_t key = 0; // upper value is 0 by request + uintptr_t addr = 0x100000000LL; pthread_mutex_lock(&mutex_prot); - khint_t k = kh_get(memprot, memprot, key); - if(k==kh_end(memprot)) { - pthread_mutex_unlock(&mutex_prot); - return LOWEST; - } - uint8_t *prot = kh_val(memprot, k); + do { + addr = nextFree(addr); + uintptr_t sz = maxFree(addr, size); + if(sz>=size) { + pthread_mutex_unlock(&mutex_prot); + return (void*)addr; + } + addr += sz; + } while(addr<0x800000000000LL); + // search in 32bits as a backup + addr = (uintptr_t)LOWEST; + do { + addr = nextFree(addr); + uintptr_t sz = maxFree(addr, size); + if(sz>=size) { + pthread_mutex_unlock(&mutex_prot); + return (void*)addr; + } + addr += sz; + } while(addr<0x100000000LL); pthread_mutex_unlock(&mutex_prot); - void* p = (void*)LOWEST; - int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT; + printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 47bits address space\n", size); + return NULL; +} +void* find47bitBlockNearHint(void* hint, size_t size) +{ + // slow iterative search... Would need something better one day + uintptr_t addr = (uintptr_t)hint; + pthread_mutex_lock(&mutex_prot); do { - const uintptr_t idx = ((uintptr_t)p)>>MEMPROT_SHIFT; - if(availableBlock(prot+idx, pages)) - return p; - p += 0x10000; - } while(p!=(void*)0xffff0000); + addr = nextFree(addr); + uintptr_t sz = maxFree(addr, size); + if(sz>=size) { + pthread_mutex_unlock(&mutex_prot); + return (void*)addr; + } + addr += sz; + } while(addr<0x800000000000LL); + pthread_mutex_unlock(&mutex_prot); printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size); return NULL; } void* findBlockNearHint(void* hint, size_t size) { // slow iterative search... Would need something better one day - if(!hint) hint=LOWEST; - const uint32_t key = (((uintptr_t)hint)>>32)&0xffffffff; + uintptr_t addr = (uintptr_t)hint; pthread_mutex_lock(&mutex_prot); - khint_t k = kh_get(memprot, memprot, key); - if(k==kh_end(memprot)) { - pthread_mutex_unlock(&mutex_prot); - return hint; - } - uint8_t *prot = kh_val(memprot, k); - pthread_mutex_unlock(&mutex_prot); - void* p = hint; - void* end = (void*)((uintptr_t)hint+0x100000000LL); - uintptr_t step = (size+0xfff)&~0xfff; - int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT; do { - const uintptr_t idx = (((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT; - if(availableBlock(prot+idx, pages)) - return p; - p += step; - } while(p!=end); + addr = nextFree(addr); + uintptr_t sz = maxFree(addr, size); + if(sz>=size) { + pthread_mutex_unlock(&mutex_prot); + return (void*)addr; + } + addr += sz; + } while(addr<0x100000000LL); + pthread_mutex_unlock(&mutex_prot); printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size); return NULL; } diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index b2ba5aac..6bac1c18 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -235,6 +235,8 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin) } } else { // vaddr is 0, load everything has a One block + if(!offs && box64_wine) + offs = (uintptr_t)find47bitBlock(head->memsz); // limit to 47bits... printf_log(LOG_DEBUG, "Allocating 0x%lx 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 diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 792cc06e..2e01e28c 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1051,6 +1051,14 @@ x64emurun: if(emu->quit) goto fini; break; + case 0xCF: /* IRET */ + R_RIP = Pop(emu); + emu->segs[_CS] = Pop(emu); + emu->segs_serial[_CS] = 0; + emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1 + RESET_FLAGS(emu); + goto fini; // exit, to recompute CS if needed + break; case 0xD0: /* GRP2 Eb,1 */ case 0xD2: /* GRP2 Eb,CL */ nextop = F8; diff --git a/src/include/custommem.h b/src/include/custommem.h index 14a8248c..4e4ff6b4 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -42,6 +42,7 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot); void setProtection(uintptr_t addr, size_t size, uint32_t prot); void freeProtection(uintptr_t addr, size_t size); uint32_t getProtection(uintptr_t addr); +void loadProtectionFromMap(); #ifdef DYNAREC void protectDB(uintptr_t addr, size_t size); void protectDBnolock(uintptr_t addr, size_t size); @@ -51,6 +52,8 @@ void unlockDB(); #endif void* find32bitBlock(size_t size); void* findBlockNearHint(void* hint, size_t size); +void* find47bitBlock(size_t size); +void* find47bitBlockNearHint(void* hint, size_t size); // unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex int unlockCustommemMutex(); diff --git a/src/include/debug.h b/src/include/debug.h index 1b6ae3c8..5341435f 100755 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -24,6 +24,7 @@ extern char* trace_func; #endif extern int allow_missing_libs; extern int box64_steam; +extern int box64_wine; extern int box64_nopulse; // disabling the use of wrapped pulseaudio extern int box64_nogtk; // disabling the use of wrapped gtk extern int box64_novulkan; // disabling the use of wrapped vulkan diff --git a/src/main.c b/src/main.c index 4c03f525..ce924c94 100755 --- a/src/main.c +++ b/src/main.c @@ -8,6 +8,7 @@ #include <dirent.h> #include <signal.h> #include <sys/syscall.h> +#include <sys/mman.h> #include "build_info.h" #include "debug.h" @@ -52,12 +53,13 @@ char* trace_func = NULL; int box64_dynarec_trace = 0; #endif #endif -int box64_zoom = 0; int x11threads = 0; int x11glx = 1; int allow_missing_libs = 0; int fix_64bit_inodes = 0; +int box64_zoom = 0; int box64_steam = 0; +int box64_wine = 0; int box64_nopulse = 0; int box64_nogtk = 0; int box64_novulkan = 0; @@ -731,7 +733,8 @@ int main(int argc, const char **argv, const char **env) { if(!box64_nobanner) PrintBox64Version(); // precheck, for win-preload - if(strstr(prog, "wine-preloader")==(prog+strlen(prog)-strlen("wine-preloader"))) { + if(strstr(prog, "wine-preloader")==(prog+strlen(prog)-strlen("wine-preloader")) + || strstr(prog, "wine64-preloader")==(prog+strlen(prog)-strlen("wine64-preloader"))) { // wine-preloader detecter, skipping it if next arg exist and is an x86 binary int x64 = (nextarg<argc)?FileIsX64ELF(argv[nextarg]):0; if(x64) { @@ -741,9 +744,9 @@ int main(int argc, const char **argv, const char **env) { } } // check if this is wine - if(!strcmp(prog, "wine") || (strlen(prog)>5 && !strcmp(prog+strlen(prog)-strlen("/wine"), "/wine"))) { + if(!strcmp(prog, "wine64") || (strlen(prog)>5 && !strcmp(prog+strlen(prog)-strlen("/wine64"), "/wine64"))) { const char* prereserve = getenv("WINEPRELOADRESERVE"); - printf_log(LOG_INFO, "BOX64: Wine detected, WINEPRELOADRESERVE=\"%s\"\n", prereserve?prereserve:""); + printf_log(LOG_INFO, "BOX64: Wine64 detected, WINEPRELOADRESERVE=\"%s\"\n", prereserve?prereserve:""); if(wine_preloaded) wine_prereserve(prereserve); // special case for winedbg, doesn't work anyway @@ -751,6 +754,11 @@ int main(int argc, const char **argv, const char **env) { printf_log(LOG_NONE, "winedbg detected, not launching it!\n"); exit(0); // exiting, it doesn't work anyway } + box64_wine = 1; + } + // check if this is wineserver + if(!strcmp(prog, "wineserver") || !strcmp(prog, "wineserver64") || (strlen(prog)>9 && !strcmp(prog+strlen(prog)-strlen("/wineserver"), "/wineserver"))) { + box64_wine = 1; } // Create a new context my_context = NewBox64Context(argc - nextarg); @@ -1045,6 +1053,7 @@ int main(int argc, const char **argv, const char **env) { #endif atexit(endBox64); + loadProtectionFromMap(); // emulate! printf_log(LOG_DEBUG, "Start x64emu on Main\n"); diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 94d7d761..f27c15e4 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1958,7 +1958,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) {dynarec_log(LOG_DEBUG, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) =>", addr, length, prot, flags, fd, offset);} + if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) => ", addr, length, prot, flags, fd, offset);} #ifndef NOALIGN if(flags&0x40) { // 0x40 is MAP_32BIT, wich only exist on x86_64! @@ -1967,6 +1967,9 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot addr = find32bitBlock(length); else addr = findBlockNearHint(addr, length); + } else if (box64_wine) { + if(!addr) + addr = find47bitBlock(length); } #endif void* ret = mmap64(addr, length, prot, flags, fd, offset); |