about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-01-29 09:57:02 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-01-29 09:57:02 +0100
commit8ee250e9acd463b74e57c677630f8cb3c3c3e78b (patch)
treebe3920e2f8b20b15361fdc7e0afd0ecbba68d7d0 /src
parente485fe1d1855bef0e3e6e25b4ac48a7f8a7c7776 (diff)
downloadbox64-8ee250e9acd463b74e57c677630f8cb3c3c3e78b.tar.gz
box64-8ee250e9acd463b74e57c677630f8cb3c3c3e78b.zip
[DYNAREC] Small improvment in dynablock/protectDB handling
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c39
-rw-r--r--src/dynarec/dynablock.c18
-rw-r--r--src/include/custommem.h1
3 files changed, 47 insertions, 11 deletions
diff --git a/src/custommem.c b/src/custommem.c
index 03d02e24..9882f886 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -992,6 +992,43 @@ uintptr_t getJumpAddress64(uintptr_t addr)
 }
 
 // Remove the Write flag from an adress range, so DB can be executed safely
+void protectDBJumpTable(uintptr_t addr, size_t size, void* jump, void* ref)
+{
+    dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
+
+    uintptr_t cur = addr&~(box64_pagesize-1);
+    uintptr_t end = ALIGN(addr+size);
+
+    mutex_lock(&mutex_prot);
+    while(cur!=end) {
+        uint32_t prot = 0, oprot;
+        uintptr_t bend = 0;
+        rb_get_end(memprot, cur, &prot, &bend);
+        if(bend>end)
+            bend = end;
+        oprot = prot;
+        uint32_t dyn = prot&PROT_DYN;
+        if(!prot)
+            prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+        if(!(dyn&PROT_NOPROT)) {
+            prot&=~PROT_CUSTOM;
+            if(prot&PROT_WRITE) {
+                if(!dyn) 
+                    mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
+                prot |= PROT_DYNAREC;
+            } else 
+                prot |= PROT_DYNAREC_R;
+        }
+        if (prot != oprot) // If the node doesn't exist, then prot != 0
+            rb_set(memprot, cur, bend, prot);
+        cur = bend;
+    }
+    if(jump)
+        setJumpTableIfRef64((void*)addr, jump, ref);
+    mutex_unlock(&mutex_prot);
+}
+
+// Remove the Write flag from an adress range, so DB can be executed safely
 void protectDB(uintptr_t addr, uintptr_t size)
 {
     dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
@@ -1067,8 +1104,8 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
 int isprotectedDB(uintptr_t addr, size_t size)
 {
     dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
-    uintptr_t end = ALIGN(addr+size);
     addr &=~(box64_pagesize-1);
+    uintptr_t end = ALIGN(addr+size);
     mutex_lock(&mutex_prot);
     while (addr < end) {
         uint32_t prot;
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c
index fda14912..11499203 100644
--- a/src/dynarec/dynablock.c
+++ b/src/dynarec/dynablock.c
@@ -291,11 +291,10 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
                 FreeInvalidDynablock(old, need_lock);
         } else {
             dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
-            protectDB((uintptr_t)db->x64_addr, db->x64_size);
-            // fill back jumptable
-            if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
-                setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
-            }
+            if(db->always_test)
+                protectDB((uintptr_t)db->x64_addr, db->x64_size);
+            else
+                protectDBJumpTable((uintptr_t)db->x64_addr, db->x64_size, db->block, db->jmpnext);
         }
         if(!need_lock)
             mutex_unlock(&my_context->mutex_dyndump);
@@ -329,11 +328,10 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr,
             } else
                 FreeInvalidDynablock(old, need_lock);
         } else {
-            protectDB((uintptr_t)db->x64_addr, db->x64_size);
-            // fill back jumptable
-            if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
-                setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
-            }
+            if(db->always_test)
+                protectDB((uintptr_t)db->x64_addr, db->x64_size);
+            else
+                protectDBJumpTable((uintptr_t)db->x64_addr, db->x64_size, db->block, db->jmpnext);
         }
         if(!need_lock)
             mutex_unlock(&my_context->mutex_dyndump);
diff --git a/src/include/custommem.h b/src/include/custommem.h
index d6867a4f..aa0e7f4d 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -88,6 +88,7 @@ int getMmapped(uintptr_t addr);
 void loadProtectionFromMap(void);
 #ifdef DYNAREC
 void protectDB(uintptr_t addr, size_t size);
+void protectDBJumpTable(uintptr_t addr, size_t size, void* jump, void* ref);
 void unprotectDB(uintptr_t addr, size_t size, int mark);    // if mark==0, the blocks are not marked as potentially dirty
 int isprotectedDB(uintptr_t addr, size_t size);
 #endif