diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-04-04 10:19:47 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-04-04 10:19:47 +0200 |
| commit | 29f65bb6beff6457db6f00315c1395f944ec93ed (patch) | |
| tree | 814655902322d3ef9b614bf9267bd9fcc0bcdf97 /src | |
| parent | cce929341312896c0e03ee0380d14aa3cc473964 (diff) | |
| download | box64-29f65bb6beff6457db6f00315c1395f944ec93ed.tar.gz box64-29f65bb6beff6457db6f00315c1395f944ec93ed.zip | |
More work on mmap and the MAP_32BIT flag
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 55 | ||||
| -rwxr-xr-x | src/emu/x64int3.c | 2 | ||||
| -rw-r--r-- | src/include/custommem.h | 9 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 4 | ||||
| -rwxr-xr-x | src/libtools/threads.c | 2 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 15 |
6 files changed, 70 insertions, 17 deletions
diff --git a/src/custommem.c b/src/custommem.c index d1921b83..0358543d 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -763,7 +763,7 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot) uint32_t dyn = kh_value(memprot, k)[ii]&PROT_DYNAREC; if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC); - kh_value(memprot, k)[ii] = prot|dyn; + kh_value(memprot, k)[ii] = prot|dyn|PROT_ALLOC; } pthread_mutex_unlock(&mutex_prot); } @@ -783,7 +783,27 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot) kh_value(memprot, k) = m; } const uintptr_t ii = i&(MEMPROT_SIZE-1); - kh_value(memprot, k)[ii] = prot; + kh_value(memprot, k)[ii] = prot|PROT_ALLOC; + } + pthread_mutex_unlock(&mutex_prot); +} + +void freeProtection(uintptr_t addr, uintptr_t size) +{ + dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1)); + 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 ii = i&(MEMPROT_SIZE-1); + kh_value(memprot, k)[ii] = 0; } pthread_mutex_unlock(&mutex_prot); } @@ -803,7 +823,6 @@ uint32_t getProtection(uintptr_t addr) return ret; } -#ifndef NOALIGN #define LOWEST (void*)0x20000 int availableBlock(uint8_t* p, size_t n) { @@ -827,15 +846,41 @@ void* find32bitBlock(size_t size) void* p = (void*)LOWEST; int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT; do { - const uintptr_t idx = ((((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT); + const uintptr_t idx = ((uintptr_t)p)>>MEMPROT_SHIFT; if(availableBlock(prot+idx, pages)) return p; p += 0x10000; } while(p!=(void*)0xffff0000); + printf_log(LOG_NONE, "Warning: cannot find a 0x%lx 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; + 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); + printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size); return NULL; } #undef LOWEST -#endif void init_custommem_helper(box64context_t* ctx) diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c index 8b967ff9..73d57deb 100755 --- a/src/emu/x64int3.c +++ b/src/emu/x64int3.c @@ -117,7 +117,7 @@ void x64Int3(x64emu_t* emu) } else if(strstr(s, "my___printf_chk")) { tmp = (char*)(R_RSI); snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX)); - } else if(strstr(s, "mmap64")) { + } else if(!strcmp(s, "mmap64") || !strcmp(s, "mmap")) { snprintf(buff, 255, "%04d|%p: Calling %s(%p, %lu, 0x%x, 0x%x, %d, %ld)", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, (int)(R_RDX), (int)R_RCX, (int)R_R8, R_R9); } else if(!strcmp(s, "sscanf")) { diff --git a/src/include/custommem.h b/src/include/custommem.h index 551063d1..15f38596 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -34,9 +34,13 @@ uintptr_t getJumpTable64(); uintptr_t getJumpTableAddress64(uintptr_t addr); #endif -#define PROT_DYNAREC 0x80 +#define PROT_DYNAREC 0x80 +#define PROT_ALLOC 0x40 +#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC) + void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot); void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot); +void freeProtection(uintptr_t addr, uintptr_t size); uint32_t getProtection(uintptr_t addr); #ifdef DYNAREC void protectDB(uintptr_t addr, uintptr_t size); @@ -45,9 +49,8 @@ void unprotectDB(uintptr_t addr, uintptr_t size); void lockDB(); void unlockDB(); #endif -#ifndef NOALIGN void* find32bitBlock(size_t size); -#endif +void* findBlockNearHint(void* hint, size_t size); void init_custommem_helper(box64context_t* ctx); diff --git a/src/libtools/signals.c b/src/libtools/signals.c index eb533b0d..d6014c19 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -700,8 +700,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) void * pc = NULL; // unknow arch... #warning Unhandled architecture #endif -#ifdef DYNAREC uint32_t prot = getProtection((uintptr_t)addr); +#ifdef DYNAREC dynablock_t* db = NULL; int db_searched = 0; if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) { @@ -834,6 +834,8 @@ exit(-1); else printf_log(log_minimum, "\n"); } + if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7)) + return; // that's probably just a multi-task glitch, like seen in terraria if(my_context->signals[sig] && my_context->signals[sig]!=1) { if(my_context->is_sigaction[sig]) my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db); diff --git a/src/libtools/threads.c b/src/libtools/threads.c index ed37ca2c..567fb76f 100755 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -306,7 +306,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou et->fnc = (uintptr_t)start_routine; et->arg = arg; #ifdef DYNAREC - if(box64_dynarec) { + if(0 && box64_dynarec) { // disable for now // pre-creation of the JIT code for the entry point of the thread dynablock_t *current = NULL; DBGetBlock(emu, (uintptr_t)start_routine, 1, ¤t); diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 2490dcb0..9c437226 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1896,10 +1896,13 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot 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);} #ifndef NOALIGN - if(!addr && (flags&0x40)) { + if(flags&0x40) { // 0x40 is MAP_32BIT, wich only exist on x86_64! //flags &= ~0x40; // let the flags in? - addr = find32bitBlock(length); + if(!addr) + addr = find32bitBlock(length); + else + addr = findBlockNearHint(addr, length); } #endif void* ret = mmap64(addr, length, prot, flags, fd, offset); @@ -1931,7 +1934,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne dynarec_log(LOG_DEBUG, "%p\n", ret); if(ret==(void*)-1) return ret; // failed... - uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_DYNAREC; + uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM; if(ret==old_addr) { if(old_size && old_size<new_size) { setProtection((uintptr_t)ret+old_size, new_size-old_size, prot); @@ -1940,7 +1943,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne addDBFromAddressRange((uintptr_t)ret+old_size, new_size-old_size); #endif } else if(old_size && new_size<old_size) { - setProtection((uintptr_t)ret+new_size, old_size-new_size, 0); + freeProtection((uintptr_t)ret+new_size, old_size-new_size); #ifdef DYNAREC if(box64_dynarec) cleanDBFromAddressRange((uintptr_t)ret+new_size, new_size-old_size, 1); @@ -1958,7 +1961,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne && flags&MREMAP_DONTUNMAP==0 #endif ) { - setProtection((uintptr_t)old_addr, old_size, 0); + freeProtection((uintptr_t)old_addr, old_size); #ifdef DYNAREC if(box64_dynarec) cleanDBFromAddressRange((uintptr_t)old_addr, old_size, 1); @@ -1983,7 +1986,7 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length) #endif int ret = munmap(addr, length); if(!ret) - setProtection((uintptr_t)addr, length, 0); + freeProtection((uintptr_t)addr, length); return ret; } |