about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c62
-rw-r--r--src/include/custommem.h1
-rwxr-xr-xsrc/libtools/signals.c11
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;