diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-02-03 18:01:13 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-02-03 18:01:13 +0100 |
| commit | 121d986b1114990ae69a6834cea6979200e0c39b (patch) | |
| tree | 6c17cb5f45209c098e3e8f6569550d7a3d191c20 /src | |
| parent | f18f5c9b85feecb3b5d1744b2cfaf5a2fe6068b5 (diff) | |
| download | box64-121d986b1114990ae69a6834cea6979200e0c39b.tar.gz box64-121d986b1114990ae69a6834cea6979200e0c39b.zip | |
[DYNAREC] Reworked a bit the Strange SEGSIGV handling
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 19 | ||||
| -rw-r--r-- | src/include/custommem.h | 2 | ||||
| -rw-r--r-- | src/libtools/signals.c | 10 |
3 files changed, 29 insertions, 2 deletions
diff --git a/src/custommem.c b/src/custommem.c index 478e5950..faac9740 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -729,6 +729,25 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy) } } +// Will return 1 if at least 1 db in the address range +int isDBFromAddressRange(uintptr_t addr, size_t size) +{ + uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr; + dynarec_log(LOG_DEBUG, "isDBFromAddressRange %p/%p -> %p => ", (void*)addr, (void*)start_addr, (void*)(addr+size-1)); + dynablock_t* db = NULL; + uintptr_t end = addr+size; + while (start_addr<end) { + start_addr = getDBSize(start_addr, end-start_addr, &db); + if(db) { + dynarec_log(LOG_DEBUG, "1\n"); + return 1; + } + } + dynarec_log(LOG_DEBUG, "0\n"); + return 0; +} + + #ifdef JMPTABL_SHIFT4 static uintptr_t *create_jmptbl(uintptr_t idx0, uintptr_t idx1, uintptr_t idx2, uintptr_t idx3, uintptr_t idx4) { diff --git a/src/include/custommem.h b/src/include/custommem.h index 71ed1b0c..b80eba47 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -26,6 +26,8 @@ void FreeDynarecMap(uintptr_t addr); void addDBFromAddressRange(uintptr_t addr, size_t size); void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy); +// Will return 1 if at least 1 db in the address range +int isDBFromAddressRange(uintptr_t addr, size_t size); dynablock_t* getDB(uintptr_t idx); int getNeedTest(uintptr_t idx); diff --git a/src/libtools/signals.c b/src/libtools/signals.c index edc27587..a8e8a83e 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1451,10 +1451,16 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for } else { if((sig==SIGSEGV) && (info->si_code == SEGV_ACCERR) && ((prot&~PROT_CUSTOM)==(PROT_READ|PROT_WRITE) || (prot&~PROT_CUSTOM)==(PROT_READ|PROT_WRITE|PROT_EXEC))) { static uintptr_t old_addr = 0; - printf_log(/*LOG_DEBUG*/LOG_INFO, "%04d| Strange SIGSEGV with Access error on %p for %p%s, db=%p, prot=0x%x (old_addr=%p)\n", tid, pc, addr, mapped?" mapped":"", db, prot, (void*)old_addr); #ifdef DYNAREC - cleanDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize, 0); + if((prot==PROT_READ|PROT_WRITE|PROT_EXEC) && isDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize)) { + printf_log(/*LOG_DEBUG*/LOG_INFO, "%04d| Strange SIGSEGV with Access error on %p for %p with DynaBlock(s) in range, db=%p, Lock=0x%x)\n", tid, pc, addr, db, Locks); + cleanDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize, 0); + refreshProtection((uintptr_t)addr); + relockMutex(Locks); + return; + } #endif + printf_log(/*LOG_DEBUG*/LOG_INFO, "%04d| Strange SIGSEGV with Access error on %p for %p%s, db=%p, prot=0x%x (old_addr=%p, Lock=0x%x)\n", tid, pc, addr, mapped?" mapped":"", db, prot, (void*)old_addr, Locks); if(!(old_addr==(uintptr_t)addr && old_prot==prot) || mapped) { old_addr = (uintptr_t)addr; old_prot = prot; |