diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-28 15:08:55 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-28 15:08:55 +0200 |
| commit | ba1493857f16f8d8e9eec8f3d421e49784761e8d (patch) | |
| tree | 5a26df7bf3ab0bc6dd6505a0dc21890f5deddf25 /src | |
| parent | fb7a0318a0e93b099cf781ea5bb285b97092d277 (diff) | |
| download | box64-ba1493857f16f8d8e9eec8f3d421e49784761e8d.tar.gz box64-ba1493857f16f8d8e9eec8f3d421e49784761e8d.zip | |
[DYNAREC] Improved Dynablock construction, stopping when overlaping block is detected
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 19 | ||||
| -rwxr-xr-x | src/dynarec/dynablock.c | 1 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64.c | 27 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_pass.c | 20 | ||||
| -rw-r--r-- | src/include/custommem.h | 1 | ||||
| -rwxr-xr-x | src/tools/bridge.c | 7 |
6 files changed, 61 insertions, 14 deletions
diff --git a/src/custommem.c b/src/custommem.c index 6b245112..eeba5f97 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -470,6 +470,8 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size) void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size) { + if(!addr || !size) + return; if(size>MMAPSIZE-2*sizeof(blockmark_t)) { #ifndef USE_MMAP free((void*)addr); @@ -594,6 +596,23 @@ void setJumpTableDefault64(void* addr) return; box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)arm64_next; } +int isJumpTableDefault64(void* addr) +{ + uintptr_t idx3, idx2, idx1, idx0; + idx3 = (((uintptr_t)addr)>>48)&0xffff; + idx2 = (((uintptr_t)addr)>>32)&0xffff; + idx1 = (((uintptr_t)addr)>>16)&0xffff; + idx0 = (((uintptr_t)addr) )&0xffff; + if(box64_jmptbl3[idx3] == box64_jmptbldefault2) + return 1; + if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) + return 1; + if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) + return 1; + if(box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next) + return 1; + return (box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)?1:0; +} uintptr_t getJumpTable64() { return (uintptr_t)box64_jmptbl3; diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 836d7eb0..c5e2d24b 100755 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -330,6 +330,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t // fill the block block->x64_addr = (void*)addr; if(!FillBlock64(block, filladdr)) { + dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr); void* old = (void*)arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], 0); if(old!=block && old) {// put it back in place, strange things are happening here! dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old); diff --git a/src/dynarec/dynarec_arm64.c b/src/dynarec/dynarec_arm64.c index 679bc1e1..7641a573 100755 --- a/src/dynarec/dynarec_arm64.c +++ b/src/dynarec/dynarec_arm64.c @@ -325,10 +325,10 @@ int Table64(dynarec_arm_t *dyn, uint64_t val) } -void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr); -void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr); -void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr); -void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr); +uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr); +uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr); +uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr); +uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr); void* FillBlock64(dynablock_t* block, uintptr_t addr) { if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) @@ -336,7 +336,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { // init the helper dynarec_arm_t helper = {0}; helper.start = addr; - arm_pass0(&helper, addr); + uintptr_t start = addr; + uintptr_t end = arm_pass0(&helper, addr); if(!helper.size) { dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr); block->done = 1; @@ -344,11 +345,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { } helper.cap = helper.size+3; // needs epilog handling helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t)); + // already protect the block and compute hash signature + protectDB(addr, end-addr+1); + uint32_t hash = X31_hash_code((void*)addr, end-addr+1); // pass 1, addresses, x64 jump addresses, flags arm_pass1(&helper, addr); // calculate barriers - uintptr_t start = helper.insts[0].x64.addr; - uintptr_t end = helper.insts[helper.size].x64.addr+helper.insts[helper.size].x64.size; for(int i=0; i<helper.size; ++i) if(helper.insts[i].x64.jmp) { uintptr_t j = helper.insts[i].x64.jmp; @@ -440,11 +442,18 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { block->block = p; block->need_test = 0; //block->x64_addr = (void*)start; - block->x64_size = end-start; + block->x64_size = end-start+1; if(box64_dynarec_largest<block->x64_size) box64_dynarec_largest = block->x64_size; block->hash = X31_hash_code(block->x64_addr, block->x64_size); - // fill sons if any + // Check if something changed, to abbort if it as + if(block->hash != hash) { + dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash); + free(helper.sons_x64); + free(helper.sons_arm); + FreeDynarecMap(block, (uintptr_t)p, sz); + return NULL; + } // fill sons if any dynablock_t** sons = NULL; int sons_size = 0; if(helper.sons_size) { diff --git a/src/dynarec/dynarec_arm64_pass.c b/src/dynarec/dynarec_arm64_pass.c index 97404224..9abeaf6a 100755 --- a/src/dynarec/dynarec_arm64_pass.c +++ b/src/dynarec/dynarec_arm64_pass.c @@ -25,11 +25,12 @@ #error No STEP defined #endif -void arm_pass(dynarec_arm_t* dyn, uintptr_t addr) +uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr) { int ok = 1; int ninst = 0; uintptr_t ip = addr; + uintptr_t init_addr = addr; rex_t rex; int rep; // 0 none, 1=F2 prefix, 2=F3 prefix int need_epilog = 1; @@ -38,11 +39,11 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr) dyn->state_flags = 0; dyn->dfnone = 0; dyn->last_ip = ip; // RIP is always set at start of block! + MAYUSE(init_addr); fpu_reset(dyn, ninst); // ok, go now INIT; while(ok) { - if(dyn->insts && (ninst>dyn->size)) {dynarec_log(LOG_NONE, "Warning, too many inst treated (%d / %d)\n",ninst, dyn->size);} ip = addr; if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) { dyn->last_ip = 0; @@ -110,6 +111,20 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr) } if(ok<0) {ok = 0; need_epilog=1;} ++ninst; + #if STEP == 0 + if(ok && !isJumpTableDefault64((void*)addr)) + #else + if(ok && dyn->insts && (ninst==dyn->size)) + #endif + { + #if STEP == 3 + dynarec_log(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size); + #endif + BARRIER(2); + fpu_purgecache(dyn, ninst, x1, x2, x3); + jump_to_next(dyn, addr, 0, ninst); + ok=0; need_epilog=0; + } } if(need_epilog) { fpu_purgecache(dyn, ninst, x1, x2, x3); @@ -117,4 +132,5 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr) } FINI; MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size); + return addr; } \ No newline at end of file diff --git a/src/include/custommem.h b/src/include/custommem.h index d5e8a09a..c1de067f 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -29,6 +29,7 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy); dynablocklist_t* getDB(uintptr_t idx); void addJumpTableIfDefault64(void* addr, void* jmp); void setJumpTableDefault64(void* addr); +int isJumpTableDefault64(void* addr); uintptr_t getJumpTable64(); uintptr_t getJumpTableAddress64(uintptr_t addr); #endif diff --git a/src/tools/bridge.c b/src/tools/bridge.c index a5aecc89..3a3e6768 100755 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -91,14 +91,15 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* b = b->next; bridge->last = b; } - sz = b->sz; + sz = b->sz; #ifdef DYNAREC pthread_mutex_unlock(&bridge->mutex); if(box64_dynarec) { prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0; if(prot) unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t)); - addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t)); + else // only add DB if there is no protection + addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t)); } } while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment pthread_mutex_lock(&bridge->mutex); @@ -116,7 +117,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC; pthread_mutex_unlock(&bridge->mutex); #ifdef DYNAREC - if(box64_dynarec && prot) + if(box64_dynarec) protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t)); #endif #ifdef HAVE_TRACE |