about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-02-03 18:01:13 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-02-03 18:01:13 +0100
commit121d986b1114990ae69a6834cea6979200e0c39b (patch)
tree6c17cb5f45209c098e3e8f6569550d7a3d191c20 /src
parentf18f5c9b85feecb3b5d1744b2cfaf5a2fe6068b5 (diff)
downloadbox64-121d986b1114990ae69a6834cea6979200e0c39b.tar.gz
box64-121d986b1114990ae69a6834cea6979200e0c39b.zip
[DYNAREC] Reworked a bit the Strange SEGSIGV handling
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c19
-rw-r--r--src/include/custommem.h2
-rw-r--r--src/libtools/signals.c10
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;