about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-10-27 19:42:01 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-10-27 19:42:01 +0200
commita7c0c01bf4812402cf025a651ab30b37782431e3 (patch)
tree19a4838571af31a48d188ba8ab6cf9cd6a3c0fc8 /src
parentd80226ec618917cfe41857a5fd24fcc7faf0c18b (diff)
downloadbox64-a7c0c01bf4812402cf025a651ab30b37782431e3.tar.gz
box64-a7c0c01bf4812402cf025a651ab30b37782431e3.zip
[DYNAREC] Cancel a dynablock if a segfault occurs while building it
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c4
-rwxr-xr-xsrc/dynarec/dynablock.c13
-rwxr-xr-xsrc/include/dynablock.h3
-rwxr-xr-xsrc/libtools/signals.c2
4 files changed, 20 insertions, 2 deletions
diff --git a/src/custommem.c b/src/custommem.c
index 92d6a4f4..171855e4 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -377,7 +377,7 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
                 mmaplist[i].locked = 0;
                 return ret;
             } else {
-                printf_log(LOG_INFO, "BOX64: Warning, sub not found, corrupted mmaplist[%d] info?\n", i);
+                printf_log(LOG_INFO, "BOX64: Warning, sub not found, corrupted mmaplist[%zu] info?\n", i);
                 if(box64_log >= LOG_DEBUG)
                     printBlock(mmaplist[i].block, mmaplist[i].first);
             }
@@ -460,7 +460,7 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
                 memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
             }
             if(mmaplist[i].locked) {
-                printf_log(LOG_INFO, "BOX64: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
+                printf_log(LOG_INFO, "BOX64: Warning, Free a chunk in a locked mmaplist[%zu]\n", i);
                 ++mmaplist[i].locked;
             }
             return;
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c
index 5df4979d..321bd25d 100755
--- a/src/dynarec/dynablock.c
+++ b/src/dynarec/dynablock.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <pthread.h>
 #include <errno.h>
+#include <setjmp.h>
 
 #include "debug.h"
 #include "box64context.h"
@@ -290,6 +291,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
     return block;
 }
 
+//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
+static __thread struct __jmp_buf_tag dynarec_jmpbuf;
+
+void cancelFillBlock()
+{
+    longjmp(&dynarec_jmpbuf, 1);
+}
+
 /* 
     return NULL if block is not found / cannot be created. 
     Don't create if create==0
@@ -330,6 +339,10 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
     // fill the block
     block->x64_addr = (void*)addr;
     pthread_mutex_lock(&my_context->mutex_dyndump);
+    if(sigsetjmp(&dynarec_jmpbuf, 1)) {
+        printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
+        return NULL;
+    }
     void* ret = FillBlock64(block, filladdr);
     pthread_mutex_unlock(&my_context->mutex_dyndump);
     if(!ret) {
diff --git a/src/include/dynablock.h b/src/include/dynablock.h
index 618a3651..d6424c4f 100755
--- a/src/include/dynablock.h
+++ b/src/include/dynablock.h
@@ -29,4 +29,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
 // Create and Add an new dynablock in the list, handling direct/map
 dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
 
+// for use in signal handler
+void cancelFillBlock();
+
 #endif //__DYNABLOCK_H_
\ No newline at end of file
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 1ac0dd4f..191267c4 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -736,6 +736,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
     int Locks = unlockMutex();
     uint32_t prot = getProtection((uintptr_t)addr);
 #ifdef DYNAREC
+    if((Locks & (1<<8)) && (sig==SIGSEGV)) //1<<8 is mutex_dyndump
+        cancelFillBlock();  // Segfault inside a Fillblock, just cancel it's creation, don't relock mutex
     dynablock_t* db = NULL;
     int db_searched = 0;
     if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {