diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2022-11-14 21:06:33 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2022-11-14 21:06:33 +0100 |
| commit | ee509f6350a25e42aca3c705bd35ec8ac4e962dd (patch) | |
| tree | bd637d638c5465cdcc01b88a37f033312acf4d40 /src | |
| parent | 6a7c6cba1235729767b16405780c2362ac835278 (diff) | |
| download | box64-ee509f6350a25e42aca3c705bd35ec8ac4e962dd.tar.gz box64-ee509f6350a25e42aca3c705bd35ec8ac4e962dd.zip | |
Small fixes and improvement to memory protection handling
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 62 | ||||
| -rw-r--r-- | src/include/custommem.h | 1 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 11 |
3 files changed, 47 insertions, 27 deletions
diff --git a/src/custommem.c b/src/custommem.c index 0b1b2e98..3aae1b90 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -5,6 +5,7 @@ #include <dlfcn.h> #include <signal.h> #include <pthread.h> +#include <errno.h> #include "box64context.h" #include "elfloader.h" @@ -1111,7 +1112,7 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot) #endif } if(prot || memprot[i].prot!=memprot_default) { - uintptr_t bstart = ((i<<16)<addr)?(addr&0xffff):0; + uintptr_t bstart = ((i<<16)<idx)?(idx&0xffff):0; uintptr_t bend = (((i<<16)+0xffff)>end)?(end&0xffff):0xffff; for (uintptr_t j=bstart; i<=bend; ++i) memprot[i].prot[j] = prot; @@ -1120,6 +1121,18 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot) pthread_mutex_unlock(&mutex_prot); } +void refreshProtection(uintptr_t addr) +{ + pthread_mutex_lock(&mutex_prot); + uintptr_t idx = (addr>>MEMPROT_SHIFT); + if(memprot[idx>>16].prot!=memprot_default) { + int prot = memprot[idx>>16].prot[idx&0xffff]; + int ret = mprotect((void*)(idx<<MEMPROT_SHIFT), box64_pagesize, prot&~PROT_CUSTOM); +printf_log(LOG_INFO, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(idx<<MEMPROT_SHIFT), prot, ret, ret?strerror(errno):"ok"); + } + 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); @@ -1263,24 +1276,10 @@ void freeProtection(uintptr_t addr, size_t size) pthread_mutex_lock(&mutex_prot); for (uintptr_t i=idx; i<=end; ++i) { const uint32_t key = (i>>16); + const uintptr_t start = i&(MEMPROT_SIZE-1); + const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1); if(memprot[key].prot!=memprot_default) { - 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 = memprot[key].prot; - memset(block+start, 0, (finish-start+1)*sizeof(uint8_t)); - // blockempty is quite slow, so disable the free of blocks for now -#if 0 //def ARM64 //disabled for now, not useful with the mutex - if (blockempty(block)) { - block = (void*)native_lock_xchg(&memprot[key], (uintptr_t)memprot_default); - if(!blockempty(block)) { - block = (void*)native_lock_xchg(&memprot[key], (uintptr_t)block); - for (int i = 0; i < 0x10000; ++i) { - memprot[key][i] |= block[i]; - } - } - if (block != memprot_default) box_free(block); - } -#else if(start==0 && finish==MEMPROT_SIZE-1) { memprot[key].prot = memprot_default; box_free(block); @@ -1289,16 +1288,29 @@ void freeProtection(uintptr_t addr, size_t size) memprot[key].hot = NULL; box_free(hot); } - } - /*else if(blockempty(block)) { - memprot[key] = memprot_default; - box_free(block); - }*/ + } else { + memset(block+start, 0, (finish-start+1)*sizeof(uint8_t)); + // blockempty is quite slow, so disable the free of blocks for now +#if 0 //def ARM64 //disabled for now, not useful with the mutex + if (blockempty(block)) { + block = (void*)native_lock_xchg(&memprot[key], (uintptr_t)memprot_default); + if(!blockempty(block)) { + block = (void*)native_lock_xchg(&memprot[key], (uintptr_t)block); + for (int i = 0; i < 0x10000; ++i) { + memprot[key][i] |= block[i]; + } + } + if (block != memprot_default) box_free(block); + } +#else + /*else if(blockempty(block)) { + memprot[key] = memprot_default; + box_free(block); + }*/ #endif - i+=finish-start; // +1 from the "for" loop - } else { - i+=MEMPROT_SIZE-1; + } } + i+=finish-start; // +1 from the "for" loop } pthread_mutex_unlock(&mutex_prot); } diff --git a/src/include/custommem.h b/src/include/custommem.h index 0a8642f4..a33e1377 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -43,6 +43,7 @@ uintptr_t getJumpAddress64(uintptr_t addr); 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); +void refreshProtection(uintptr_t addr); uint32_t getProtection(uintptr_t addr); void loadProtectionFromMap(); #ifdef DYNAREC diff --git a/src/libtools/signals.c b/src/libtools/signals.c index a0ca6c76..a2fdd188 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -934,8 +934,15 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for exit(-1); } else { if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7)) { - relockMutex(Locks); - return; // that's probably just a multi-task glitch, like seen in terraria + static uintptr_t old_addr = 0; + printf_log(/*LOG_DEBUG*/LOG_INFO, "Strange SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x (old_addr=%p)\n", pc, addr, db, prot, (void*)old_addr); + if(old_addr!=(uintptr_t)addr) { + old_addr = (uintptr_t)addr; + refreshProtection(old_addr); + relockMutex(Locks); + return; // that's probably just a multi-task glitch, like seen in terraria + } + old_addr = 0; } old_code = info->si_code; old_pc = pc; |