diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-07-26 10:11:55 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-07-26 10:11:55 +0200 |
| commit | 32e2112ab04d968b13ca6561bbcb8130d9cdc7d1 (patch) | |
| tree | 7de322b37b11a42414a2aaec76af9c7460cdd035 | |
| parent | f0866438fc98e6debf85b8fc7aeff0e60c6fcfd7 (diff) | |
| download | box64-32e2112ab04d968b13ca6561bbcb8130d9cdc7d1.tar.gz box64-32e2112ab04d968b13ca6561bbcb8130d9cdc7d1.zip | |
[DYNAREC] Fixed an issue introduced with 48ae536d95390b98add016866948e91522943730 and properly address the underlying issue
| -rw-r--r-- | src/dynarec/dynablock.c | 60 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native.c | 12 |
2 files changed, 49 insertions, 23 deletions
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 13693204..28906f96 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -1,6 +1,7 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <signal.h> #include "os.h" #include "debug.h" @@ -236,18 +237,38 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t return block; } + #ifndef WIN32 + static int critical_filled = 0; + static sigset_t critical_prot = {0}; + sigset_t old_sig = {0}; + if(!critical_filled) { + critical_filled = 1; + sigfillset(&critical_prot); + sigdelset(&critical_prot, SIGSEGV); + sigdelset(&critical_prot, SIGILL); + sigdelset(&critical_prot, SIGBUS); + sigdelset(&critical_prot, SIGINT); + sigdelset(&critical_prot, SIGABRT); + sigdelset(&critical_prot, SIGFPE); + } + #endif + + pthread_sigmask(SIG_BLOCK, &critical_prot, &old_sig); if(need_lock) { if(BOX64ENV(dynarec_wait)) { mutex_lock(&my_context->mutex_dyndump); } else { - if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now + if(mutex_trylock(&my_context->mutex_dyndump)) { // FillBlock not available for now + pthread_sigmask(SIG_SETMASK, &old_sig, NULL); return NULL; + } } block = getDB(addr); // just in case if(block) { if(block && getNeedTest(addr) && (getProtection_fast(addr)&req_prot)!=req_prot) block = NULL; mutex_unlock(&my_context->mutex_dyndump); + pthread_sigmask(SIG_SETMASK, &old_sig, NULL); return block; } } @@ -255,6 +276,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t if((getProtection_fast(addr)&req_prot)!=req_prot) {// cannot be run, get out of the Dynarec if(need_lock) mutex_unlock(&my_context->mutex_dyndump); + pthread_sigmask(SIG_SETMASK, &old_sig, NULL); return NULL; } #endif @@ -262,6 +284,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, canceling\n", (void*)addr); if(need_lock) mutex_unlock(&my_context->mutex_dyndump); + pthread_sigmask(SIG_SETMASK, &old_sig, NULL); return NULL; } block = FillBlock64(filladdr, (addr==filladdr)?0:1, is32bits, MAX_INSTS, is_new); @@ -290,6 +313,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t } if(need_lock) mutex_unlock(&my_context->mutex_dyndump); + pthread_sigmask(SIG_SETMASK, &old_sig, NULL); dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block %p created @%p:%p (%p, 0x%x bytes)\n", GetTID(), block, (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0); @@ -305,37 +329,35 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) if(db && db->done && db->block && getNeedTest(addr)) { //if (db->always_test) SchedYield(); // just calm down... uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size); - int need_lock = mutex_trylock(&my_context->mutex_dyndump); + mutex_lock(&my_context->mutex_dyndump)?1:0; if(hash!=db->hash) { if(is_inhotpage && db->previous) { // check alternate if(db->previous && !db->dirty && X31_hash_code(db->previous->x64_addr, db->previous->x64_size)==db->previous->hash) { - db = SwitchDynablock(db, need_lock); + db = SwitchDynablock(db, 0); if(!addJumpTableIfDefault64(db->x64_addr, (db->always_test)?db->jmpnext:db->block)) { FreeDynablock(db, 0, 0); db = getDB(addr); MarkDynablock(db); // just in case... } - if(!need_lock) - mutex_unlock(&my_context->mutex_dyndump); + mutex_unlock(&my_context->mutex_dyndump); return db; } - if(!need_lock) - mutex_unlock(&my_context->mutex_dyndump); + mutex_unlock(&my_context->mutex_dyndump); return NULL; // will be handle when hotpage is over } db->done = 0; // invalidating the block dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X, always_test:%d, previous=%p/hash=%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, db->always_test,db->previous, db->previous?db->previous->hash:0,(void*)addr); // Free db, it's now invalid! - dynablock_t* old = InvalidDynablock(db, need_lock); + dynablock_t* old = InvalidDynablock(db, 0); // start again... (will create a new block) - db = internalDBGetBlock(emu, addr, addr, create, need_lock, is32bits, 0); + db = internalDBGetBlock(emu, addr, addr, create, 0, is32bits, 0); if(db) { if(db->previous) - FreeInvalidDynablock(db->previous, need_lock); + FreeInvalidDynablock(db->previous, 0); db->previous = old; } else - FreeInvalidDynablock(old, need_lock); + FreeInvalidDynablock(old, 0); } else { if(is_inhotpage) { db->always_test = 2; @@ -359,8 +381,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) } } } - if(!need_lock) - mutex_unlock(&my_context->mutex_dyndump); + mutex_unlock(&my_context->mutex_dyndump); } if(!db || !db->block || !db->done) emu->test.test = 0; @@ -374,21 +395,21 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1, is32bits, 1); if(db && db->done && db->block && (db->dirty || getNeedTest(filladdr))) { if (db->always_test) SchedYield(); // just calm down... - int need_lock = mutex_trylock(&my_context->mutex_dyndump); + mutex_lock(&my_context->mutex_dyndump); uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size); if(hash!=db->hash) { db->done = 0; // invalidating the block dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, hash, db->hash, (void*)addr); // Free db, it's now invalid! - dynablock_t* old = InvalidDynablock(db, need_lock); + dynablock_t* old = InvalidDynablock(db, 0); // start again... (will create a new block) - db = internalDBGetBlock(emu, addr, filladdr, create, need_lock, is32bits, 0); + db = internalDBGetBlock(emu, addr, filladdr, create, 0, is32bits, 0); if(db) { if(db->previous) - FreeInvalidDynablock(db->previous, need_lock); + FreeInvalidDynablock(db->previous, 0); db->previous = old; } else - FreeInvalidDynablock(old, need_lock); + FreeInvalidDynablock(old, 0); } else { if(db->always_test) protectDB((uintptr_t)db->x64_addr, db->x64_size); @@ -404,8 +425,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, protectDBJumpTable((uintptr_t)db->x64_addr, db->x64_size, db->block, db->jmpnext); } } - if(!need_lock) - mutex_unlock(&my_context->mutex_dyndump); + mutex_unlock(&my_context->mutex_dyndump); } if(!db || !db->block || !db->done) emu->test.test = 0; diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index cab79830..c92f251f 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -530,6 +530,7 @@ static int static_jmps[MAX_INSTS+2]; static uintptr_t static_next[MAX_INSTS+2]; static instruction_native_t static_insts[MAX_INSTS+2] = {0}; static callret_t static_callrets[MAX_INSTS+2] = {0}; +void* redundant_helper = NULL; // TODO: ninst could be a uint16_t instead of an int, that could same some temp. memory void ClearCache(void* start, size_t len) @@ -575,6 +576,7 @@ void CancelBlock64(int need_lock) } } current_helper = NULL; + redundant_helper = NULL; if(need_lock) mutex_unlock(&my_context->mutex_dyndump); } @@ -636,7 +638,11 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m return NULL; } if(current_helper) { - dynarec_log(LOG_INFO, "Warning: previous FillBlock did not cleaned up correctly\n"); + if(current_helper==redundant_helper) { + dynarec_log(LOG_INFO, "%04d|Warning: previous FillBlock did not cleaned up correctly (helper=%p, x64addr=%p, db=%p)\n", GetTID(), current_helper, (void*)((dynarec_native_t*)current_helper)->start, ((dynarec_native_t*)current_helper)->dynablock); + return NULL; + } + dynarec_log(LOG_INFO, "Warning: some static area curruption appeared (current=%p, redundant=%p)\n", current_helper, redundant_helper); } // protect the 1st page protectDB(addr, 1); @@ -646,7 +652,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m #ifdef GDBJIT helper.gdbjit_block = box_calloc(1, sizeof(gdbjit_block_t)); #endif - current_helper = &helper; + redundant_helper = current_helper = &helper; helper.dynablock = NULL; helper.start = addr; uintptr_t start = addr; @@ -1003,7 +1009,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m *(uint32_t*)(block->block+block->callrets[i].offs) = ARCH_UDF; #endif } - current_helper = NULL; + redundant_helper = current_helper = NULL; //block->done = 1; return block; } |