about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-10-18 10:52:07 +0200
committerptitSeb <sebastien.chev@gmail.com>2025-10-18 10:52:07 +0200
commitf568ae48444679fac8e0433ed8c80e1f1b10320a (patch)
tree87e10e7ef85e88cdcfbb4d19e8295196bfb3fe4f /src
parent4edbdc005b60c048c7229e1cafc203f0b92e65ec (diff)
downloadbox64-f568ae48444679fac8e0433ed8c80e1f1b10320a.tar.gz
box64-f568ae48444679fac8e0433ed8c80e1f1b10320a.zip
[RV64_DYNAREC] Small refactor on SIGBUS special case handling
Diffstat (limited to 'src')
-rw-r--r--src/include/threads.h2
-rw-r--r--src/libtools/signals.c81
-rw-r--r--src/libtools/threads.c13
3 files changed, 67 insertions, 29 deletions
diff --git a/src/include/threads.h b/src/include/threads.h
index 7a77657f..d4b1b9df 100644
--- a/src/include/threads.h
+++ b/src/include/threads.h
@@ -31,5 +31,7 @@ void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet
 
 //check and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
 int checkUnlockMutex(void* m);
+//check if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
+int checkNolockMutex(void* m);
 
 #endif //_THREADS_H_
\ No newline at end of file
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 527d9510..4bb29eaa 100644
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -304,7 +304,7 @@ void adjustregs(x64emu_t* emu, void* pc) {
         }
         ++idx;
     }
-    dynarec_log(LOG_INFO, "Checking opcode: rex=%02hhx is32bits=%d, rep=%d is66=%d %02hhX %02hhX %02hhX %02hhX\n", rex.rex, rex.is32bits, rep, is66, mem[idx+0], mem[idx+1], mem[idx+2], mem[idx+3]);
+    dynarec_log(LOG_INFO, "Checking opcode: at %p rex=%02hhx is32bits=%d, rep=%d is66=%d %02hhX %02hhX %02hhX %02hhX\n", (void*)R_RIP, rex.rex, rex.is32bits, rep, is66, mem[idx+0], mem[idx+1], mem[idx+2], mem[idx+3]);
 #ifdef DYNAREC
 #ifdef ARM64
     if(mem[idx+0]==0xA4 || mem[idx+0]==0xA5) {
@@ -415,6 +415,13 @@ if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address
 }
 #endif
 
+#ifdef DYNAREC
+#ifdef ARM64
+#include "dynarec/arm64/arm64_printer.h"
+#elif RV64
+#include "dynarec/rv64/rv64_printer.h"
+#endif
+#endif
 int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, dynablock_t* db, uintptr_t x64pc, int is32bits)
 {
     if((uintptr_t)pc<0x10000)
@@ -769,6 +776,8 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd,
         p->uc_mcontext.regs[src] += offset;
         p->uc_mcontext.pc+=4;   // go to next opcode
         return 1;
+    } else {
+        printf_log(LOG_INFO, "Unsupported SIGBUS special cases with pc=%p, opcode=%x (%s)\n", pc, opcode, arm64_print(opcode, (uintptr_t)pc));
     }
 #elif RV64
 #define GET_FIELD(v, high, low) (((v) >> low) & ((1ULL << (high - low + 1)) - 1))
@@ -793,7 +802,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd,
         p->uc_mcontext.__gregs[0] += 4; // pc += 4
         return 1;
     } else {
-        printf_log(LOG_NONE, "Unsupported SIGBUS special cases with pc=%p, opcode=%x\n", pc, inst);
+        printf_log(LOG_NONE, "Unsupported SIGBUS special cases with pc=%p, opcode=%x (%s)\n", pc, inst, rv64_print(inst, (uintptr_t)pc));
     }
 
 #undef GET_FIELD
@@ -847,6 +856,41 @@ int unlockMutex()
 
     return ret;
 }
+int checkMutex(uint32_t mask)
+{
+    int ret = 0;
+    int i;
+    #ifdef USE_CUSTOM_MUTEX
+    uint32_t tid = (uint32_t)GetTID();
+    #define GO(A, B)                                    \
+    if(mask&(1<<B) i = (A == tid); else i = 0;          \
+    if (i) {                                            \
+        ret |= (1 << B);                                \
+    }
+    #else
+    #define GO(A, B)                            \
+    i = (mask&(1<<B))?checkNolockMutex(&A):0;   \
+    if (i) {                                    \
+        ret |= (1 << B);                        \
+    }
+    #endif
+
+    GO(mutex_blocks, 0)
+    GO(mutex_prot, 1)
+
+    GO(my_context->mutex_trace, 7)
+    #ifdef DYNAREC
+    GO(my_context->mutex_dyndump, 8)
+    #else
+    GO(my_context->mutex_lock, 8)
+    #endif
+    GO(my_context->mutex_tls, 9)
+    GO(my_context->mutex_thread, 10)
+    GO(my_context->mutex_bridge, 11)
+    #undef GO
+
+    return ret;
+}
 
 #ifdef BOX32
 void my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db);
@@ -1383,7 +1427,12 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
     int db_searched = 0;
     uintptr_t x64pc = (uintptr_t)-1;
     x64pc = R_RIP;
-    if((sig==X64_SIGBUS) && (addr!=pc) || ((sig==X64_SIGSEGV)) && emu->segs[_CS]==0x23 && ((uintptr_t)addr>>32)==0xffffffff) {
+    if(((sig==X64_SIGBUS) && ((addr!=pc) || ((sig==X64_SIGSEGV)) && emu->segs[_CS]==0x23 && ((uintptr_t)addr>>32)==0xffffffff))
+#ifdef RV64
+    || ((sig==X64_SIGSEGV) && (addr==pc) && (info->si_code==2) && (!checkMutex(is_memprot_locked) && getProtection_fast((uintptr_t)addr)==(PROT_READ|PROT_WRITE|PROT_EXEC)))
+#endif
+    )
+    {
         db = FindDynablockFromNativeAddress(pc);
         if(db)
             x64pc = getX64Address(db, (uintptr_t)pc);
@@ -1483,32 +1532,6 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
         info->si_code = 2;
     }
     #endif
-#ifdef RV64
-    if((sig==X64_SIGSEGV) && (addr==pc) && (info->si_code==2) && (prot==(PROT_READ|PROT_WRITE|PROT_EXEC))) {
-        if(!db_searched) {
-            db = FindDynablockFromNativeAddress(pc);
-            if(db)
-                x64pc = getX64Address(db, (uintptr_t)pc);
-            db_searched = 1;
-        }
-        int fixed = 0;
-        if((fixed = sigbus_specialcases(info, ucntx, pc, fpsimd, db, x64pc, emu->segs[_CS]==0x23))) {
-            // special case fixed, restore everything and just continues
-            if (BOX64ENV(log) >= LOG_DEBUG || BOX64ENV(showsegv)) {
-                static void*  old_pc[2] = {0};
-                static int old_pc_i = 0;
-                if(old_pc[0]!=pc && old_pc[1]!=pc) {
-                    old_pc[old_pc_i++] = pc;
-                    if(old_pc_i==2)
-                        old_pc_i = 0;
-                    printf_log(LOG_NONE, "Special unalinged cased fixed @%p, opcode=%08x (addr=%p)\n", pc, *(uint32_t *)pc, addr);
-                }
-            }
-            relockMutex(Locks);
-            return;
-        }
-    }
-#endif
 #ifdef DYNAREC
     if((Locks & is_dyndump_locked) && ((sig==X64_SIGSEGV) || (sig==X64_SIGBUS)) && current_helper) {
         printf_log(LOG_INFO, "FillBlock triggered a %s at %p from %p\n", (sig==X64_SIGSEGV)?"segfault":"bus error", addr, pc);
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index 1076b3e2..4fd26bf9 100644
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -1281,3 +1281,16 @@ int checkUnlockMutex(void* m)
 	}
 	return 0;
 }
+
+int checkNolockMutex(void* m)
+{
+	pthread_mutex_t* mutex = (pthread_mutex_t*)m;
+	int ret = pthread_mutex_trylock(mutex);
+	if(ret==0) {
+		pthread_mutex_unlock(mutex);
+		return 0;
+	}
+	if(ret == EDEADLK)
+		return 1;
+	return 0;
+}