diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-10-18 10:52:07 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-10-18 10:52:07 +0200 |
| commit | f568ae48444679fac8e0433ed8c80e1f1b10320a (patch) | |
| tree | 87e10e7ef85e88cdcfbb4d19e8295196bfb3fe4f | |
| parent | 4edbdc005b60c048c7229e1cafc203f0b92e65ec (diff) | |
| download | box64-f568ae48444679fac8e0433ed8c80e1f1b10320a.tar.gz box64-f568ae48444679fac8e0433ed8c80e1f1b10320a.zip | |
[RV64_DYNAREC] Small refactor on SIGBUS special case handling
| -rw-r--r-- | src/include/threads.h | 2 | ||||
| -rw-r--r-- | src/libtools/signals.c | 81 | ||||
| -rw-r--r-- | src/libtools/threads.c | 13 |
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; +} |