mirror of
https://github.com/ptitSeb/box86.git
synced 2024-11-23 18:04:10 +08:00
[DYNAREC] Remove dynarec linker mecanism and use generic TableJump instead (also all memory that have a dynablock is protected now, should improve compatibility with C# and program taht use SelfModifyCode)
This commit is contained in:
parent
8209cf8398
commit
911b95a505
@ -406,8 +406,7 @@ if(ARM_DYNAREC)
|
|||||||
|
|
||||||
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
|
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
|
||||||
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
|
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
|
||||||
"${BOX86_ROOT}/src/dynarec/arm_linker.S"
|
"${BOX86_ROOT}/src/dynarec/arm_next.S"
|
||||||
"${BOX86_ROOT}/src/dynarec/arm_table.S"
|
|
||||||
"${BOX86_ROOT}/src/dynarec/arm_lock_helper.S"
|
"${BOX86_ROOT}/src/dynarec/arm_lock_helper.S"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
10
USAGE.md
10
USAGE.md
@ -100,16 +100,6 @@ Enables/Disables Box86's Dynarec.
|
|||||||
* 0 : Disables Dynarec.
|
* 0 : Disables Dynarec.
|
||||||
* 1 : Enable Dynarec. (Default.)
|
* 1 : Enable Dynarec. (Default.)
|
||||||
|
|
||||||
#### BOX86_DYNAREC_LINKER
|
|
||||||
Enables/Disables Box86's Dynarec linker.
|
|
||||||
* 0 : Disables the Dynarec Linker. (Very useful for debugging when combined with BOX86_DYNAREC__LOG >= 2. This is to have details on which block gets executed.)
|
|
||||||
* 1 : Enables the Dynarec Linker. (Default.)
|
|
||||||
|
|
||||||
#### BOX86_DYNAREC_SAFEMMAP
|
|
||||||
Enables/Disables Box86's Dynarec's SAFEMMAP mecanism.
|
|
||||||
* 0 : Some mmp/mmap64 blocks are considered unsafe (This depends on the program ran). (Default.)
|
|
||||||
* 1 : Consider all mmap/mmap64 blocks safe to use linker (potential speedup, but potential crash for apps using JIT/Dynarec)
|
|
||||||
|
|
||||||
#### BOX86_DYNAREC_TRACE
|
#### BOX86_DYNAREC_TRACE
|
||||||
Enables/Disables trace for generated code.
|
Enables/Disables trace for generated code.
|
||||||
* 0 : Disable trace for generated code. (Default.)
|
* 0 : Disable trace for generated code. (Default.)
|
||||||
|
@ -27,71 +27,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef DYNAREC
|
|
||||||
// Remove the Write flag from an adress range, so DB can be executed
|
|
||||||
// no log, as it can be executed inside a signal handler
|
|
||||||
void protectDB(uintptr_t addr, uintptr_t size)
|
|
||||||
{
|
|
||||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
|
||||||
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
|
||||||
for (uintptr_t i=idx; i<=end; ++i) {
|
|
||||||
uint32_t prot;
|
|
||||||
do {
|
|
||||||
prot=arm_lock_read_d(&my_context->memprot[i]);
|
|
||||||
if(!prot)
|
|
||||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
|
||||||
} while(arm_lock_write_d(&my_context->memprot[i], prot|PROT_DYNAREC));
|
|
||||||
if(!(prot&PROT_DYNAREC))
|
|
||||||
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the Write flag from an adress range, and mark all block as dirty
|
|
||||||
// no log, as it can be executed inside a signal handler
|
|
||||||
void unprotectDB(uintptr_t addr, uintptr_t size)
|
|
||||||
{
|
|
||||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
|
||||||
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
|
||||||
for (uintptr_t i=idx; i<=end; ++i) {
|
|
||||||
uint32_t prot;
|
|
||||||
do {
|
|
||||||
prot=arm_lock_read_d(&my_context->memprot[i]);
|
|
||||||
} while(arm_lock_write_d(&my_context->memprot[i], prot&~PROT_DYNAREC));
|
|
||||||
if(prot&PROT_DYNAREC) {
|
|
||||||
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_DYNAREC);
|
|
||||||
cleanDBFromAddressRange((i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
|
||||||
{
|
|
||||||
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
|
||||||
const uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
|
||||||
for (uintptr_t i=idx; i<=end; ++i) {
|
|
||||||
#ifdef DYNAREC
|
|
||||||
uint32_t dyn;
|
|
||||||
do {
|
|
||||||
dyn=arm_lock_read_d(&my_context->memprot[i])&PROT_DYNAREC;
|
|
||||||
} while(arm_lock_write_d(&my_context->memprot[i], prot|dyn));
|
|
||||||
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
|
||||||
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
|
|
||||||
#else
|
|
||||||
uint32_t dyn=(my_context->memprot[i]&PROT_DYNAREC);
|
|
||||||
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
|
||||||
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
|
|
||||||
my_context->memprot[i] = prot|dyn;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getProtection(uintptr_t addr)
|
|
||||||
{
|
|
||||||
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
|
||||||
return my_context->memprot[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORTDYN
|
EXPORTDYN
|
||||||
void initAllHelpers(box86context_t* context)
|
void initAllHelpers(box86context_t* context)
|
||||||
@ -102,10 +37,6 @@ void initAllHelpers(box86context_t* context)
|
|||||||
my_context = context;
|
my_context = context;
|
||||||
init_pthread_helper();
|
init_pthread_helper();
|
||||||
init_signal_helper(context);
|
init_signal_helper(context);
|
||||||
#ifdef DYNAREC
|
|
||||||
if(box86_dynarec)
|
|
||||||
DynablockEmuMarker(context);
|
|
||||||
#endif
|
|
||||||
inited = 1;
|
inited = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +97,6 @@ box86context_t *NewBox86Context(int argc)
|
|||||||
|
|
||||||
init_custommem_helper(context);
|
init_custommem_helper(context);
|
||||||
|
|
||||||
context->memprot = (uint32_t*)calloc(DYNAMAP_SIZE, sizeof(uint32_t));
|
|
||||||
|
|
||||||
context->maplib = NewLibrarian(context, 1);
|
context->maplib = NewLibrarian(context, 1);
|
||||||
context->local_maplib = NewLibrarian(context, 1);
|
context->local_maplib = NewLibrarian(context, 1);
|
||||||
context->system = NewBridge();
|
context->system = NewBridge();
|
||||||
@ -310,8 +239,6 @@ void FreeBox86Context(box86context_t** context)
|
|||||||
#endif
|
#endif
|
||||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||||
free(ctx->memprot);
|
|
||||||
ctx->memprot = NULL;
|
|
||||||
|
|
||||||
free_neededlib(&ctx->neededlibs);
|
free_neededlib(&ctx->neededlibs);
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ static kh_dynablocks_t *dblist_oversized; // store the list of oversize
|
|||||||
static uintptr_t **box86_jumptable = NULL;
|
static uintptr_t **box86_jumptable = NULL;
|
||||||
static uintptr_t *box86_jmptbl_default = NULL;
|
static uintptr_t *box86_jmptbl_default = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
static uint32_t* memprot; // protection flags by 4K block
|
||||||
|
|
||||||
typedef struct blocklist_s {
|
typedef struct blocklist_s {
|
||||||
void* block;
|
void* block;
|
||||||
@ -443,14 +444,14 @@ dynablocklist_t* getDB(uintptr_t idx)
|
|||||||
|
|
||||||
// each dynmap is 64k of size
|
// each dynmap is 64k of size
|
||||||
|
|
||||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker)
|
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||||
{
|
{
|
||||||
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||||
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||||
for (uintptr_t i=idx; i<=end; ++i) {
|
for (uintptr_t i=idx; i<=end; ++i) {
|
||||||
if(!dynmap[i]) {
|
if(!dynmap[i]) {
|
||||||
dynmap[i] = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, nolinker, 0);
|
dynmap[i] = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -476,13 +477,10 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DYNAREC
|
|
||||||
#ifdef ARM
|
#ifdef ARM
|
||||||
void arm_next(void);
|
void arm_next(void);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
void addJumpTableIfDefault(void* addr, void* jmp)
|
void addJumpTableIfDefault(void* addr, void* jmp)
|
||||||
{
|
{
|
||||||
@ -511,8 +509,89 @@ uintptr_t getJumpTable()
|
|||||||
return (uintptr_t)box86_jumptable;
|
return (uintptr_t)box86_jumptable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t getJumpTableAddress(uintptr_t addr)
|
||||||
|
{
|
||||||
|
const uintptr_t idx = ((uintptr_t)addr>>DYNAMAP_SHIFT);
|
||||||
|
if(box86_jumptable[idx] == box86_jmptbl_default) {
|
||||||
|
uintptr_t* tbl = (uintptr_t*)malloc((1<<DYNAMAP_SHIFT)*sizeof(uintptr_t));
|
||||||
|
for(int i=0; i<(1<<DYNAMAP_SHIFT); ++i)
|
||||||
|
tbl[i] = (uintptr_t)arm_next;
|
||||||
|
box86_jumptable[idx] = tbl;
|
||||||
|
}
|
||||||
|
const uintptr_t off = (uintptr_t)addr&((1<<DYNAMAP_SHIFT)-1);
|
||||||
|
return (uintptr_t)&box86_jumptable[idx][off];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the Write flag from an adress range, so DB can be executed
|
||||||
|
// no log, as it can be executed inside a signal handler
|
||||||
|
void protectDB(uintptr_t addr, uintptr_t size)
|
||||||
|
{
|
||||||
|
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||||
|
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||||
|
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||||
|
for (uintptr_t i=idx; i<=end; ++i) {
|
||||||
|
uint32_t prot;
|
||||||
|
do {
|
||||||
|
prot=arm_lock_read_d(&memprot[i]);
|
||||||
|
if(!prot)
|
||||||
|
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||||
|
} while(arm_lock_write_d(&memprot[i], prot|PROT_DYNAREC));
|
||||||
|
if(!(prot&PROT_DYNAREC))
|
||||||
|
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the Write flag from an adress range, and mark all block as dirty
|
||||||
|
// no log, as it can be executed inside a signal handler
|
||||||
|
void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||||
|
{
|
||||||
|
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||||
|
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||||
|
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||||
|
for (uintptr_t i=idx; i<=end; ++i) {
|
||||||
|
uint32_t prot;
|
||||||
|
do {
|
||||||
|
prot=arm_lock_read_d(&memprot[i]);
|
||||||
|
} while(arm_lock_write_d(&memprot[i], prot&~PROT_DYNAREC));
|
||||||
|
if(prot&PROT_DYNAREC) {
|
||||||
|
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_DYNAREC);
|
||||||
|
cleanDBFromAddressRange((i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||||
|
{
|
||||||
|
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||||
|
const uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||||
|
for (uintptr_t i=idx; i<=end; ++i) {
|
||||||
|
#ifdef DYNAREC
|
||||||
|
uint32_t dyn;
|
||||||
|
do {
|
||||||
|
dyn=arm_lock_read_d(&memprot[i])&PROT_DYNAREC;
|
||||||
|
} while(arm_lock_write_d(&memprot[i], prot|dyn));
|
||||||
|
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
||||||
|
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
|
||||||
|
#else
|
||||||
|
uint32_t dyn=(memprot[i]&PROT_DYNAREC);
|
||||||
|
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
||||||
|
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
|
||||||
|
memprot[i] = prot|dyn;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getProtection(uintptr_t addr)
|
||||||
|
{
|
||||||
|
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||||
|
return memprot[idx];
|
||||||
|
}
|
||||||
|
|
||||||
void init_custommem_helper(box86context_t* ctx)
|
void init_custommem_helper(box86context_t* ctx)
|
||||||
{
|
{
|
||||||
|
memprot = (uint32_t*)calloc(DYNAMAP_SIZE, sizeof(uint32_t));
|
||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
if(dynmap) // already initialized
|
if(dynmap) // already initialized
|
||||||
return;
|
return;
|
||||||
@ -567,11 +646,16 @@ void fini_custommem_helper(box86context_t *ctx)
|
|||||||
free(mmaplist);
|
free(mmaplist);
|
||||||
free(dynmap);
|
free(dynmap);
|
||||||
dynmap = NULL;
|
dynmap = NULL;
|
||||||
|
for (int i=0; i<DYNAMAP_SIZE; ++i)
|
||||||
|
if(box86_jumptable[i]!=box86_jmptbl_default)
|
||||||
|
free(box86_jumptable[i]);
|
||||||
free(box86_jumptable);
|
free(box86_jumptable);
|
||||||
free(box86_jmptbl_default);
|
free(box86_jmptbl_default);
|
||||||
box86_jumptable = NULL;
|
box86_jumptable = NULL;
|
||||||
box86_jmptbl_default = NULL;
|
box86_jmptbl_default = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
free(memprot);
|
||||||
|
memprot = NULL;
|
||||||
for(int i=0; i<n_blocks; ++i)
|
for(int i=0; i<n_blocks; ++i)
|
||||||
free(p_blocks[i].block);
|
free(p_blocks[i].block);
|
||||||
free(p_blocks);
|
free(p_blocks);
|
||||||
|
@ -6,24 +6,8 @@
|
|||||||
.text
|
.text
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
.extern UpdateLinkTable
|
|
||||||
.extern LinkNext
|
.extern LinkNext
|
||||||
|
|
||||||
.global arm_linker
|
|
||||||
arm_linker:
|
|
||||||
// emu is r0
|
|
||||||
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (easier debugging, and safer)
|
|
||||||
// table offset is r1
|
|
||||||
// IP address is r14
|
|
||||||
push {r0, r1, r12, r14}
|
|
||||||
mov r2, r14
|
|
||||||
// call the function
|
|
||||||
bl UpdateLinkTable
|
|
||||||
// return offset is jump address
|
|
||||||
mov r3, r0
|
|
||||||
pop {r0, r1, r12, r14}
|
|
||||||
bx r3
|
|
||||||
|
|
||||||
.global arm_next
|
.global arm_next
|
||||||
arm_next:
|
arm_next:
|
||||||
// emu is r0
|
// emu is r0
|
@ -1,19 +0,0 @@
|
|||||||
//arm try to update linker table for dynarec
|
|
||||||
//and address of table to as 1st parameter
|
|
||||||
//jump addres as second and ip as third
|
|
||||||
// don't retry if failed to write...
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
.global arm_tableupdate
|
|
||||||
arm_tableupdate:
|
|
||||||
// jump address is r0 and IP address is r1
|
|
||||||
// table offset is r2
|
|
||||||
push {r4, r5}
|
|
||||||
ldrexd r4, r5, [r2]
|
|
||||||
strexd r3, r0, r1, [r2]
|
|
||||||
pop {r4, r5}
|
|
||||||
mov r0, r3
|
|
||||||
bx lr
|
|
||||||
|
|
@ -38,7 +38,7 @@ uint32_t X31_hash_code(void* addr, int len)
|
|||||||
return (uint32_t)h;
|
return (uint32_t)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int nolinker, int direct)
|
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||||
{
|
{
|
||||||
if(!textsz) {
|
if(!textsz) {
|
||||||
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
|
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
|
||||||
@ -47,7 +47,6 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int nolinker, int
|
|||||||
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
|
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
|
||||||
ret->text = text;
|
ret->text = text;
|
||||||
ret->textsz = textsz;
|
ret->textsz = textsz;
|
||||||
ret->nolinker = nolinker;
|
|
||||||
if(direct && textsz) {
|
if(direct && textsz) {
|
||||||
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
|
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
|
||||||
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
|
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
|
||||||
@ -58,7 +57,7 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int nolinker, int
|
|||||||
void FreeDynablock(dynablock_t* db)
|
void FreeDynablock(dynablock_t* db)
|
||||||
{
|
{
|
||||||
if(db) {
|
if(db) {
|
||||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, tablesz=%d, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->tablesz, db->sons_size, db->gone);
|
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
|
||||||
if(db->gone)
|
if(db->gone)
|
||||||
return; // already in the process of deletion!
|
return; // already in the process of deletion!
|
||||||
db->done = 0;
|
db->done = 0;
|
||||||
@ -84,7 +83,6 @@ void FreeDynablock(dynablock_t* db)
|
|||||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||||
}
|
}
|
||||||
free(db->sons);
|
free(db->sons);
|
||||||
free(db->table);
|
|
||||||
free(db->instsize);
|
free(db->instsize);
|
||||||
free(db);
|
free(db);
|
||||||
}
|
}
|
||||||
@ -96,7 +94,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
|
|||||||
return;
|
return;
|
||||||
if(!*dynablocks)
|
if(!*dynablocks)
|
||||||
return;
|
return;
|
||||||
dynarec_log(LOG_DEBUG, "Free Direct Blocks %p from Dynablocklist nolinker=%d\n", (*dynablocks)->direct, (*dynablocks)->nolinker);
|
dynarec_log(LOG_DEBUG, "Free Direct Blocks %p from Dynablocklist\n", (*dynablocks)->direct);
|
||||||
if((*dynablocks)->direct) {
|
if((*dynablocks)->direct) {
|
||||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||||
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
|
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
|
||||||
@ -115,12 +113,10 @@ void MarkDynablock(dynablock_t* db)
|
|||||||
if(db) {
|
if(db) {
|
||||||
if(db->father)
|
if(db->father)
|
||||||
db = db->father; // mark only father
|
db = db->father; // mark only father
|
||||||
if(db->nolinker) {
|
db->need_test = 1; // test only blocks that can be marked (and so deleted)
|
||||||
db->need_test = 1; // test only blocks that can be marked (and so deleted)
|
setJumpTableDefault(db->x86_addr);
|
||||||
setJumpTableDefault(db->x86_addr);
|
for(int i=0; i<db->sons_size; ++i)
|
||||||
for(int i=0; i<db->sons_size; ++i)
|
setJumpTableDefault(db->sons[i]->x86_addr);
|
||||||
setJumpTableDefault(db->sons[i]->x86_addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,9 +135,7 @@ void MarkDynablockList(dynablocklist_t** dynablocks)
|
|||||||
return;
|
return;
|
||||||
if(!*dynablocks)
|
if(!*dynablocks)
|
||||||
return;
|
return;
|
||||||
if(!(*dynablocks)->nolinker)
|
dynarec_log(LOG_DEBUG, "Marked Blocks from Dynablocklist %p:0x%x\n", (void*)(*dynablocks)->text, (*dynablocks)->textsz);
|
||||||
return;
|
|
||||||
dynarec_log(LOG_DEBUG, "Marked Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
|
|
||||||
dynablock_t* db;
|
dynablock_t* db;
|
||||||
if((*dynablocks)->direct) {
|
if((*dynablocks)->direct) {
|
||||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||||
@ -158,7 +152,7 @@ void ProtectDynablockList(dynablocklist_t** dynablocks)
|
|||||||
return;
|
return;
|
||||||
if(!*dynablocks)
|
if(!*dynablocks)
|
||||||
return;
|
return;
|
||||||
dynarec_log(LOG_DEBUG, "Protect Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
|
dynarec_log(LOG_DEBUG, "Protect Blocks from Dynablocklist %p:0x%x\n", (void*)(*dynablocks)->text, (*dynablocks)->textsz);
|
||||||
dynablock_t* db;
|
dynablock_t* db;
|
||||||
if((*dynablocks)->direct) {
|
if((*dynablocks)->direct) {
|
||||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||||
@ -193,7 +187,7 @@ void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t
|
|||||||
{
|
{
|
||||||
if(!dynablocks)
|
if(!dynablocks)
|
||||||
return;
|
return;
|
||||||
if(!dynablocks->nolinker || !dynablocks->direct)
|
if(!dynablocks->direct)
|
||||||
return;
|
return;
|
||||||
uintptr_t startdb = dynablocks->text;
|
uintptr_t startdb = dynablocks->text;
|
||||||
uintptr_t enddb = startdb + dynablocks->textsz -1;
|
uintptr_t enddb = startdb + dynablocks->textsz -1;
|
||||||
@ -272,8 +266,6 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
|||||||
{
|
{
|
||||||
if(!dynablocks)
|
if(!dynablocks)
|
||||||
return;
|
return;
|
||||||
if(!dynablocks->nolinker)
|
|
||||||
return;
|
|
||||||
if(dynablocks->direct) {
|
if(dynablocks->direct) {
|
||||||
MarkDirectDynablock(dynablocks, addr, size);
|
MarkDirectDynablock(dynablocks, addr, size);
|
||||||
// the blocks check before
|
// the blocks check before
|
||||||
@ -337,6 +329,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
|||||||
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||||
|
|
||||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||||
|
block->parent = dynablocks;
|
||||||
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
||||||
if(tmp != block) {
|
if(tmp != block) {
|
||||||
// a block appeard!
|
// a block appeard!
|
||||||
@ -345,8 +338,6 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
block->parent = dynablocks;
|
|
||||||
|
|
||||||
*created = 1;
|
*created = 1;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
@ -411,8 +402,7 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
|||||||
dblist->maxsz = blocksz;
|
dblist->maxsz = blocksz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(block->parent->nolinker)
|
protectDB((uintptr_t)block->x86_addr, block->x86_size);
|
||||||
protectDB((uintptr_t)block->x86_addr, block->x86_size);
|
|
||||||
// fill-in jumptable
|
// fill-in jumptable
|
||||||
addJumpTableIfDefault(block->x86_addr, block->block);
|
addJumpTableIfDefault(block->x86_addr, block->block);
|
||||||
for(int i=0; i<block->sons_size; ++i)
|
for(int i=0; i<block->sons_size; ++i)
|
||||||
@ -429,7 +419,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
|||||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
|
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||||
if(db && (db->need_test || (db->father && db->father->need_test))) {
|
if(db && (db->need_test || (db->father && db->father->need_test))) {
|
||||||
dynablock_t *father = db->father?db->father:db;
|
dynablock_t *father = db->father?db->father:db;
|
||||||
uint32_t hash = father->nolinker?X31_hash_code(father->x86_addr, father->x86_size):0;
|
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
|
||||||
if(hash!=father->hash) {
|
if(hash!=father->hash) {
|
||||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||||
// no more current if it gets invalidated too
|
// no more current if it gets invalidated too
|
||||||
@ -441,8 +431,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
|||||||
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||||
} else {
|
} else {
|
||||||
father->need_test = 0;
|
father->need_test = 0;
|
||||||
if(father->nolinker)
|
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return db;
|
return db;
|
||||||
@ -455,7 +444,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
|||||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||||
if(db && (db->need_test || (db->father && db->father->need_test))) {
|
if(db && (db->need_test || (db->father && db->father->need_test))) {
|
||||||
dynablock_t *father = db->father?db->father:db;
|
dynablock_t *father = db->father?db->father:db;
|
||||||
uint32_t hash = father->nolinker?X31_hash_code(father->x86_addr, father->x86_size):0;
|
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
|
||||||
if(hash!=father->hash) {
|
if(hash!=father->hash) {
|
||||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||||
// Free father, it's now invalid!
|
// Free father, it's now invalid!
|
||||||
@ -464,8 +453,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
|||||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||||
} else {
|
} else {
|
||||||
father->need_test = 0;
|
father->need_test = 0;
|
||||||
if(father->nolinker)
|
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return db;
|
return db;
|
||||||
|
@ -15,12 +15,10 @@ typedef struct dynablock_s {
|
|||||||
void* x86_addr;
|
void* x86_addr;
|
||||||
uintptr_t x86_size;
|
uintptr_t x86_size;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
uintptr_t* table;
|
|
||||||
int tablesz;
|
|
||||||
uint8_t need_test;
|
uint8_t need_test;
|
||||||
uint8_t done;
|
uint8_t done;
|
||||||
uint8_t gone;
|
uint8_t gone;
|
||||||
uint8_t nolinker;
|
uint8_t dummy;
|
||||||
int isize;
|
int isize;
|
||||||
dynablock_t** sons; // sons (kind-of dummy dynablock...)
|
dynablock_t** sons; // sons (kind-of dummy dynablock...)
|
||||||
int sons_size;
|
int sons_size;
|
||||||
@ -32,7 +30,6 @@ typedef struct dynablocklist_s {
|
|||||||
uintptr_t text;
|
uintptr_t text;
|
||||||
int textsz;
|
int textsz;
|
||||||
int maxsz; // maxblock size (for this block or previous block)
|
int maxsz; // maxblock size (for this block or previous block)
|
||||||
int nolinker; // in case this dynablock can be deleted
|
|
||||||
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
|
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
|
||||||
} dynablocklist_t;
|
} dynablocklist_t;
|
||||||
|
|
||||||
|
@ -25,66 +25,9 @@
|
|||||||
void arm_prolog(x86emu_t* emu, void* addr) EXPORTDYN;
|
void arm_prolog(x86emu_t* emu, void* addr) EXPORTDYN;
|
||||||
void arm_epilog() EXPORTDYN;
|
void arm_epilog() EXPORTDYN;
|
||||||
void arm_epilog_fast() EXPORTDYN;
|
void arm_epilog_fast() EXPORTDYN;
|
||||||
void arm_linker() EXPORTDYN;
|
|
||||||
int arm_tableupdate(void* jump, uintptr_t addr, void** table) EXPORTDYN;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void tableupdate(void* jumpto, uintptr_t ref, void** table)
|
|
||||||
{
|
|
||||||
#ifdef ARM
|
|
||||||
if(arm_tableupdate(jumpto, ref, table))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
table[0] = jumpto;
|
|
||||||
table[1] = (void*)ref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resettable(void** table)
|
|
||||||
{
|
|
||||||
void* p = table[1];
|
|
||||||
#ifdef ARM
|
|
||||||
tableupdate(arm_linker, (uintptr_t)p, table);
|
|
||||||
#endif
|
|
||||||
//table[2] = own_dynablock // unchanged
|
|
||||||
table[3] = NULL; // removed "linked" information
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
|
|
||||||
{
|
|
||||||
dynablock_t* current = (dynablock_t*)table[2];
|
|
||||||
if(current->father)
|
|
||||||
current = current->father;
|
|
||||||
void * jblock;
|
|
||||||
dynablock_t* block = DBGetBlock(emu, addr, 1, ¤t);
|
|
||||||
if(!current) { // current has been invalidated, stop running it...
|
|
||||||
//dynarec_log(LOG_DEBUG, "--- Current invalidated while linking.\n");
|
|
||||||
return arm_epilog_fast;
|
|
||||||
}
|
|
||||||
if(!block) {
|
|
||||||
// no block, let link table as is...
|
|
||||||
//tableupdate(arm_epilog, addr, table);
|
|
||||||
return arm_epilog_fast;
|
|
||||||
}
|
|
||||||
if(!block->done) {
|
|
||||||
// not finished yet... leave linker
|
|
||||||
//tableupdate(arm_linker, addr, table);
|
|
||||||
return arm_epilog_fast;
|
|
||||||
}
|
|
||||||
if(!(jblock=block->block)) {
|
|
||||||
// null block, but done: go to epilog, no linker here
|
|
||||||
tableupdate(arm_epilog, addr, table);
|
|
||||||
return arm_epilog_fast;
|
|
||||||
}
|
|
||||||
//dynablock_t *father = block->father?block->father:block;
|
|
||||||
if(!block->parent->nolinker) {
|
|
||||||
//dynarec_log(LOG_DEBUG, "--- Linking %p/%p to %p (table=%p[%p/%p/%p/%p])\n", block, block->block, current, table, table[0], table[1], table[2], table[3]);
|
|
||||||
// only update block if linker is allowed
|
|
||||||
tableupdate(jblock, addr, table);
|
|
||||||
}
|
|
||||||
return jblock;
|
|
||||||
}
|
|
||||||
void* LinkNext(x86emu_t* emu, uintptr_t addr)
|
void* LinkNext(x86emu_t* emu, uintptr_t addr)
|
||||||
{
|
{
|
||||||
dynablock_t* current = NULL;
|
dynablock_t* current = NULL;
|
||||||
@ -145,14 +88,14 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
|||||||
dynablock_t* current = NULL;
|
dynablock_t* current = NULL;
|
||||||
while(!emu->quit) {
|
while(!emu->quit) {
|
||||||
block = DBGetBlock(emu, R_EIP, 1, ¤t);
|
block = DBGetBlock(emu, R_EIP, 1, ¤t);
|
||||||
current = (block && !block->parent->nolinker)?block:NULL;
|
current = block;
|
||||||
if(!block || !block->block || !block->done) {
|
if(!block || !block->block || !block->done) {
|
||||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||||
// Use interpreter (should use single instruction step...)
|
// Use interpreter (should use single instruction step...)
|
||||||
dynarec_log(LOG_DEBUG, "Calling Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
|
dynarec_log(LOG_DEBUG, "Calling Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
|
||||||
Run(emu, 1);
|
Run(emu, 1);
|
||||||
} else {
|
} else {
|
||||||
dynarec_log(LOG_DEBUG, "Calling DynaRec Block @%p (%p) of %d x86 instructions (nolinker=%d, father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize ,block->parent->nolinker, block->father, emu);
|
dynarec_log(LOG_DEBUG, "Calling DynaRec Block @%p (%p) of %d x86 instructions (father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize ,block->father, emu);
|
||||||
CHECK_FLAGS(emu);
|
CHECK_FLAGS(emu);
|
||||||
// block is here, let's run it!
|
// block is here, let's run it!
|
||||||
#ifdef ARM
|
#ifdef ARM
|
||||||
@ -220,14 +163,14 @@ int DynaRun(x86emu_t* emu)
|
|||||||
dynablock_t* current = NULL;
|
dynablock_t* current = NULL;
|
||||||
while(!emu->quit) {
|
while(!emu->quit) {
|
||||||
block = DBGetBlock(emu, R_EIP, 1, ¤t);
|
block = DBGetBlock(emu, R_EIP, 1, ¤t);
|
||||||
current = (block && !block->parent->nolinker)?block:NULL;
|
current = block;
|
||||||
if(!block || !block->block || !block->done) {
|
if(!block || !block->block || !block->done) {
|
||||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||||
// Use interpreter (should use single instruction step...)
|
// Use interpreter (should use single instruction step...)
|
||||||
dynarec_log(LOG_DEBUG, "Running Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
|
dynarec_log(LOG_DEBUG, "Running Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
|
||||||
Run(emu, 1);
|
Run(emu, 1);
|
||||||
} else {
|
} else {
|
||||||
dynarec_log(LOG_DEBUG, "Running DynaRec Block @%p (%p) of %d x86 insts (nolinker=%d, father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize, block->parent->nolinker, block->father, emu);
|
dynarec_log(LOG_DEBUG, "Running DynaRec Block @%p (%p) of %d x86 insts (father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize, block->father, emu);
|
||||||
// block is here, let's run it!
|
// block is here, let's run it!
|
||||||
#ifdef ARM
|
#ifdef ARM
|
||||||
arm_prolog(emu, block->block);
|
arm_prolog(emu, block->block);
|
||||||
|
@ -313,7 +313,6 @@ void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
|||||||
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||||
// init the helper
|
// init the helper
|
||||||
dynarec_arm_t helper = {0};
|
dynarec_arm_t helper = {0};
|
||||||
helper.nolinker = box86_dynarec_linker?(block->parent->nolinker):1;
|
|
||||||
helper.start = addr;
|
helper.start = addr;
|
||||||
arm_pass0(&helper, addr);
|
arm_pass0(&helper, addr);
|
||||||
if(!helper.size) {
|
if(!helper.size) {
|
||||||
@ -366,9 +365,6 @@ void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
|||||||
}
|
}
|
||||||
helper.block = p;
|
helper.block = p;
|
||||||
helper.arm_start = (uintptr_t)p;
|
helper.arm_start = (uintptr_t)p;
|
||||||
helper.tablesz = helper.tablei;
|
|
||||||
if(helper.tablesz)
|
|
||||||
helper.table = (uintptr_t*)calloc(helper.tablesz, sizeof(uintptr_t));
|
|
||||||
if(helper.sons_size) {
|
if(helper.sons_size) {
|
||||||
helper.sons_x86 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
|
helper.sons_x86 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
|
||||||
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
|
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
|
||||||
@ -409,20 +405,15 @@ void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
|||||||
// ok, free the helper now
|
// ok, free the helper now
|
||||||
free(helper.insts);
|
free(helper.insts);
|
||||||
free(helper.next);
|
free(helper.next);
|
||||||
block->table = helper.table;
|
|
||||||
block->tablesz = helper.tablesz;
|
|
||||||
for (int i=0; i<helper.tablesz/4; ++i)
|
|
||||||
block->table[i*4+2] = (uintptr_t)block;
|
|
||||||
block->size = sz;
|
block->size = sz;
|
||||||
block->isize = helper.size;
|
block->isize = helper.size;
|
||||||
block->block = p;
|
block->block = p;
|
||||||
block->nolinker = helper.nolinker;
|
|
||||||
block->need_test = 0;
|
block->need_test = 0;
|
||||||
//block->x86_addr = (void*)start;
|
//block->x86_addr = (void*)start;
|
||||||
block->x86_size = end-start;
|
block->x86_size = end-start;
|
||||||
if(box86_dynarec_largest<block->x86_size)
|
if(box86_dynarec_largest<block->x86_size)
|
||||||
box86_dynarec_largest = block->x86_size;
|
box86_dynarec_largest = block->x86_size;
|
||||||
block->hash = (helper.nolinker)?X31_hash_code(block->x86_addr, block->x86_size):0;
|
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
|
||||||
// fill sons if any
|
// fill sons if any
|
||||||
dynablock_t** sons = NULL;
|
dynablock_t** sons = NULL;
|
||||||
int sons_size = 0;
|
int sons_size = 0;
|
||||||
|
@ -696,7 +696,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
/* out of the block */ \
|
/* out of the block */ \
|
||||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
||||||
Bcond(NO, i32); \
|
Bcond(NO, i32); \
|
||||||
jump_to_linker(dyn, addr+i8, 0, ninst); \
|
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||||
} else { \
|
} else { \
|
||||||
/* inside the block */ \
|
/* inside the block */ \
|
||||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
||||||
@ -1982,7 +1982,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
/* out of the block */ \
|
/* out of the block */ \
|
||||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
||||||
Bcond(NO, i32); \
|
Bcond(NO, i32); \
|
||||||
jump_to_linker(dyn, addr+i8, 0, ninst); \
|
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||||
} else { \
|
} else { \
|
||||||
/* inside the block */ \
|
/* inside the block */ \
|
||||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
||||||
@ -2103,9 +2103,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
// regular call
|
// regular call
|
||||||
BARRIER(1);
|
BARRIER(1);
|
||||||
BARRIER_NEXT(1);
|
BARRIER_NEXT(1);
|
||||||
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
|
if(!dyn->insts || ninst==dyn->size-1) {
|
||||||
//cstatck_push put addr in x2, don't need to put it again
|
|
||||||
} else {
|
|
||||||
*need_epilog = 0;
|
*need_epilog = 0;
|
||||||
*ok = 0;
|
*ok = 0;
|
||||||
}
|
}
|
||||||
@ -2116,7 +2114,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
LDR_IMM9(x14, x14, 0);
|
LDR_IMM9(x14, x14, 0);
|
||||||
jump_to_next(dyn, 0, x14, ninst);
|
jump_to_next(dyn, 0, x14, ninst);
|
||||||
} else
|
} else
|
||||||
jump_to_linker(dyn, addr+i32, 0, ninst);
|
jump_to_next(dyn, addr+i32, 0, ninst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2134,7 +2132,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
if(dyn->insts) {
|
if(dyn->insts) {
|
||||||
PASS2IF(dyn->insts[ninst].x86.jmp_insts==-1, 1) {
|
PASS2IF(dyn->insts[ninst].x86.jmp_insts==-1, 1) {
|
||||||
// out of the block
|
// out of the block
|
||||||
jump_to_linker(dyn, addr+i32, 0, ninst);
|
jump_to_next(dyn, addr+i32, 0, ninst);
|
||||||
} else {
|
} else {
|
||||||
// inside the block
|
// inside the block
|
||||||
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
|
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
|
||||||
@ -2637,8 +2635,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
GETEDH(xEIP);
|
GETEDH(xEIP);
|
||||||
BARRIER(1);
|
BARRIER(1);
|
||||||
BARRIER_NEXT(1);
|
BARRIER_NEXT(1);
|
||||||
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
|
if(!dyn->insts || ninst==dyn->size-1) {
|
||||||
} else {
|
|
||||||
*need_epilog = 0;
|
*need_epilog = 0;
|
||||||
*ok = 0;
|
*ok = 0;
|
||||||
}
|
}
|
||||||
|
@ -1140,7 +1140,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
/* out of the block */ \
|
/* out of the block */ \
|
||||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
||||||
Bcond(NO, i32); \
|
Bcond(NO, i32); \
|
||||||
jump_to_linker(dyn, addr+i32_, 0, ninst); \
|
jump_to_next(dyn, addr+i32_, 0, ninst); \
|
||||||
} else { \
|
} else { \
|
||||||
/* inside the block */ \
|
/* inside the block */ \
|
||||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
||||||
|
@ -291,14 +291,14 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
}
|
}
|
||||||
BARRIER(1);
|
BARRIER(1);
|
||||||
BARRIER_NEXT(1);
|
BARRIER_NEXT(1);
|
||||||
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
|
if(!dyn->insts || ninst!=dyn->size-1) {
|
||||||
} else {
|
} else {
|
||||||
*need_epilog = 0;
|
*need_epilog = 0;
|
||||||
*ok = 0;
|
*ok = 0;
|
||||||
}
|
}
|
||||||
MOV32(x2, addr);
|
MOV32(x2, addr);
|
||||||
PUSH1(x2);
|
PUSH1(x2);
|
||||||
jump_to_linker(dyn, 0, xEIP, ninst); // smart linker
|
jump_to_next(dyn, 0, xEIP, ninst);
|
||||||
break;
|
break;
|
||||||
case 6: // Push Ed
|
case 6: // Push Ed
|
||||||
INST_NAME("PUSH FS:Ed");
|
INST_NAME("PUSH FS:Ed");
|
||||||
|
@ -140,7 +140,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
|||||||
/* out of the block */ \
|
/* out of the block */ \
|
||||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
|
||||||
Bcond(NO, i32); \
|
Bcond(NO, i32); \
|
||||||
jump_to_linker(dyn, addr+i8, 0, ninst); \
|
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||||
} else { \
|
} else { \
|
||||||
/* inside the block */ \
|
/* inside the block */ \
|
||||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
|
||||||
|
@ -244,86 +244,27 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
|||||||
BX(2);
|
BX(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
|
||||||
{
|
|
||||||
MESSAGE(LOG_DUMP, "Jump to linker (#%d) nolinker=%d\n", dyn->tablei, dyn->nolinker);
|
|
||||||
#if 0
|
|
||||||
int j32;
|
|
||||||
MAYUSE(j32);
|
|
||||||
#endif
|
|
||||||
if(dyn->nolinker==2) {
|
|
||||||
jump_to_epilog(dyn, ip, reg, ninst);
|
|
||||||
} else {
|
|
||||||
if(reg) {
|
|
||||||
if(reg!=xEIP) {
|
|
||||||
MOV_REG(xEIP, reg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MOV32_(xEIP, ip);
|
|
||||||
}
|
|
||||||
uintptr_t* table = 0;
|
|
||||||
if(dyn->tablesz) {
|
|
||||||
table = &dyn->table[dyn->tablei];
|
|
||||||
table[0] = (uintptr_t)arm_linker;
|
|
||||||
table[1] = ip;
|
|
||||||
}
|
|
||||||
dyn->tablei+=4; // smart linker or not, we keep table correctly alligned for LDREXD/STREXD access
|
|
||||||
MOV32_(x1, (uintptr_t)table);
|
|
||||||
// TODO: This is not thread safe.
|
|
||||||
if(!ip) { // no IP, jump address in a reg, so need smart linker
|
|
||||||
#if 0
|
|
||||||
//version thread safe
|
|
||||||
MARK;
|
|
||||||
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
|
|
||||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
|
||||||
BXcond(cEQ, x2);
|
|
||||||
MOV32_(x2, (uintptr_t)arm_linker);
|
|
||||||
MOV_REG(x3, x14);
|
|
||||||
STREXD(x14, x2, x1); // nope, putting back linker & IP in place
|
|
||||||
// x14 now contain success / falure for write
|
|
||||||
CMPS_IMM8(x14, 1);
|
|
||||||
MOV_REG(x14, x3); // put back IP in place...
|
|
||||||
B_MARK(cEQ);
|
|
||||||
BX(x2); // go to linker
|
|
||||||
#else
|
|
||||||
// not thread safe, is that still ok?
|
|
||||||
LDRD_IMM8(x2, x1, 0);
|
|
||||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
|
||||||
BXcond(cEQ, x2);
|
|
||||||
MOV32_(x2, (uintptr_t)arm_linker);
|
|
||||||
MOV_REG(x3, x14);
|
|
||||||
STRD_IMM8(x2, x1, 0);
|
|
||||||
BX(x2);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
LDR_IMM9(x2, x1, 0);
|
|
||||||
BX(x2); // jump
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||||
{
|
{
|
||||||
MESSAGE(LOG_DUMP, "Jump to next nolinker=%d\n", dyn->nolinker);
|
MESSAGE(LOG_DUMP, "Jump to next\n");
|
||||||
|
|
||||||
if(dyn->nolinker==2) {
|
if(reg) {
|
||||||
jump_to_epilog(dyn, ip, reg, ninst);
|
if(reg!=xEIP) {
|
||||||
} else {
|
MOV_REG(xEIP, reg);
|
||||||
if(reg) {
|
|
||||||
if(reg!=xEIP) {
|
|
||||||
MOV_REG(xEIP, reg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MOV32_(xEIP, ip);
|
|
||||||
}
|
}
|
||||||
MOV32(x2, getJumpTable());
|
MOV32(x2, getJumpTable());
|
||||||
MOV_REG_LSR_IMM5(x3, xEIP, DYNAMAP_SHIFT);
|
MOV_REG_LSR_IMM5(x3, xEIP, DYNAMAP_SHIFT);
|
||||||
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||||
UBFX(x3, xEIP, 0, DYNAMAP_SHIFT);
|
UBFX(x3, xEIP, 0, DYNAMAP_SHIFT);
|
||||||
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||||
MOV_REG(x1, xEIP);
|
} else {
|
||||||
BX(x2);
|
uintptr_t p = getJumpTableAddress(ip);
|
||||||
|
MOV32(x2, p);
|
||||||
|
MOV32_(xEIP, ip);
|
||||||
|
LDR_IMM9(x2, x2, 0);
|
||||||
}
|
}
|
||||||
|
MOV_REG(x1, xEIP);
|
||||||
|
BX(x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||||
|
@ -331,7 +331,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void arm_epilog();
|
void arm_epilog();
|
||||||
void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
|
|
||||||
void* arm_next(x86emu_t* emu, uintptr_t addr);
|
void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||||
|
|
||||||
#ifndef STEPNAME
|
#ifndef STEPNAME
|
||||||
@ -364,7 +363,6 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
|||||||
#define geted STEPNAME(geted_)
|
#define geted STEPNAME(geted_)
|
||||||
#define geted16 STEPNAME(geted16_)
|
#define geted16 STEPNAME(geted16_)
|
||||||
#define jump_to_epilog STEPNAME(jump_to_epilog_)
|
#define jump_to_epilog STEPNAME(jump_to_epilog_)
|
||||||
#define jump_to_linker STEPNAME(jump_to_linker_)
|
|
||||||
#define jump_to_next STEPNAME(jump_to_next_)
|
#define jump_to_next STEPNAME(jump_to_next_)
|
||||||
#define ret_to_epilog STEPNAME(ret_to_epilog_)
|
#define ret_to_epilog STEPNAME(ret_to_epilog_)
|
||||||
#define retn_to_epilog STEPNAME(retn_to_epilog_)
|
#define retn_to_epilog STEPNAME(retn_to_epilog_)
|
||||||
@ -478,7 +476,6 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
|||||||
|
|
||||||
// generic x86 helper
|
// generic x86 helper
|
||||||
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||||
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
|
||||||
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
|
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "arm_printer.h"
|
#include "arm_printer.h"
|
||||||
#include "dynarec_arm_functions.h"
|
#include "dynarec_arm_functions.h"
|
||||||
#include "dynarec_arm_helper.h"
|
#include "dynarec_arm_helper.h"
|
||||||
|
#include "custommem.h"
|
||||||
|
|
||||||
#ifndef STEP
|
#ifndef STEP
|
||||||
#error No STEP defined
|
#error No STEP defined
|
||||||
@ -30,7 +31,6 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
|||||||
int ninst = 0;
|
int ninst = 0;
|
||||||
uintptr_t ip = addr;
|
uintptr_t ip = addr;
|
||||||
int need_epilog = 1;
|
int need_epilog = 1;
|
||||||
dyn->tablei = 0;
|
|
||||||
dyn->sons_size = 0;
|
dyn->sons_size = 0;
|
||||||
// Clean up (because there are multiple passes)
|
// Clean up (because there are multiple passes)
|
||||||
dyn->state_flags = 0;
|
dyn->state_flags = 0;
|
||||||
@ -76,18 +76,19 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
|||||||
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
|
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
if(!ok && !need_epilog && !dyn->insts) { // check if need to continue
|
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3))
|
||||||
uintptr_t next = get_closest_next(dyn, addr);
|
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||||
if(next && (
|
uintptr_t next = get_closest_next(dyn, addr);
|
||||||
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
if(next && (
|
||||||
||(((next-addr)<30) && is_instructions(dyn, addr, next-addr)) ))
|
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
||||||
{
|
||(((next-addr)<30) && is_instructions(dyn, addr, next-addr)) ))
|
||||||
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
|
{
|
||||||
ok = 1;
|
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
|
||||||
} else if(next && (next-addr)<30) {
|
ok = 1;
|
||||||
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
|
} else if(next && (next-addr)<30) {
|
||||||
|
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(ok<0) {ok = 0; need_epilog=1;}
|
if(ok<0) {ok = 0; need_epilog=1;}
|
||||||
++ninst;
|
++ninst;
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,6 @@ typedef struct dynarec_arm_s {
|
|||||||
void* block; // memory pointer where next instruction is emited
|
void* block; // memory pointer where next instruction is emited
|
||||||
uintptr_t arm_start; // start of the arm code
|
uintptr_t arm_start; // start of the arm code
|
||||||
int arm_size; // size of emitted arm code
|
int arm_size; // size of emitted arm code
|
||||||
uintptr_t* table; // jump table
|
|
||||||
int tablesz; // size of the jump table
|
|
||||||
int tablei; // index
|
|
||||||
int state_flags;// actual state for on-demand flags
|
int state_flags;// actual state for on-demand flags
|
||||||
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
|
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
|
||||||
int x87reg[8]; // reg used for x87cache entry
|
int x87reg[8]; // reg used for x87cache entry
|
||||||
@ -42,7 +39,6 @@ typedef struct dynarec_arm_s {
|
|||||||
int fpu_scratch;// scratch counter
|
int fpu_scratch;// scratch counter
|
||||||
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
|
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
|
||||||
int fpu_reg; // x87/sse/mmx reg counter
|
int fpu_reg; // x87/sse/mmx reg counter
|
||||||
int nolinker; // disable use of (smart) linker in the block
|
|
||||||
int dfnone; // if defered flags is already set to df_none
|
int dfnone; // if defered flags is already set to df_none
|
||||||
uintptr_t* next; // variable array of "next" jump address
|
uintptr_t* next; // variable array of "next" jump address
|
||||||
int next_sz;
|
int next_sz;
|
||||||
|
@ -31,7 +31,5 @@ typedef struct instruction_x86_s {
|
|||||||
} instruction_x86_t;
|
} instruction_x86_t;
|
||||||
|
|
||||||
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
|
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
|
||||||
void tableupdate(void* jumpto, uintptr_t ref, void** table);
|
|
||||||
void resettable(void** table);
|
|
||||||
|
|
||||||
#endif //__DYNAREC_PRIVATE_H_
|
#endif //__DYNAREC_PRIVATE_H_
|
||||||
|
@ -271,7 +271,7 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
|||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
if(e->p_flags & PF_X) {
|
if(e->p_flags & PF_X) {
|
||||||
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
|
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
|
||||||
addDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
|
addDBFromAddressRange((uintptr_t)dest, e->p_memsz);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1011,7 +1011,7 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
|
|||||||
return ret;
|
return ret;
|
||||||
}*/
|
}*/
|
||||||
if(box86_dynarec_forced) {
|
if(box86_dynarec_forced) {
|
||||||
addDBFromAddressRange(addr, 1, 1);
|
addDBFromAddressRange(addr, 1);
|
||||||
return getDB(addr>>DYNAMAP_SHIFT);
|
return getDB(addr>>DYNAMAP_SHIFT);
|
||||||
}
|
}
|
||||||
//check if address is in an elf... if yes, grant a block (should I warn)
|
//check if address is in an elf... if yes, grant a block (should I warn)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "x86run.h"
|
#include "x86run.h"
|
||||||
#include "x86run_private.h"
|
#include "x86run_private.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
|
#include "bridge.h"
|
||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
#include "custommem.h"
|
#include "custommem.h"
|
||||||
#endif
|
#endif
|
||||||
@ -37,22 +38,15 @@ static uint32_t x86emu_parity_tab[8] =
|
|||||||
0x69969669,
|
0x69969669,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t EndEmuMarker[] = {0xcc, 'S', 'C', 0, 0, 0, 0};
|
|
||||||
#ifdef DYNAREC
|
|
||||||
void DynablockEmuMarker(box86context_t* context)
|
|
||||||
{
|
|
||||||
dynarec_log(LOG_DUMP, "Create bridge memory map for PushExit\n");
|
|
||||||
addDBFromAddressRange((uintptr_t)&EndEmuMarker[0], sizeof(EndEmuMarker), 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
void PushExit(x86emu_t* emu)
|
void PushExit(x86emu_t* emu)
|
||||||
{
|
{
|
||||||
Push(emu, (uint32_t)&EndEmuMarker);
|
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
|
||||||
|
Push(emu, endMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GetExit()
|
void* GetExit()
|
||||||
{
|
{
|
||||||
return &EndEmuMarker;
|
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
||||||
|
@ -61,7 +61,6 @@ typedef struct base_segment_s {
|
|||||||
} base_segment_t;
|
} base_segment_t;
|
||||||
|
|
||||||
typedef struct box86context_s {
|
typedef struct box86context_s {
|
||||||
uint32_t* memprot; // protection flags by 4K block
|
|
||||||
path_collection_t box86_path; // PATH env. variable
|
path_collection_t box86_path; // PATH env. variable
|
||||||
path_collection_t box86_ld_lib; // LD_LIBRARY_PATH env. variable
|
path_collection_t box86_ld_lib; // LD_LIBRARY_PATH env. variable
|
||||||
|
|
||||||
@ -206,14 +205,6 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head);
|
|||||||
// return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context)
|
// return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context)
|
||||||
int AddTLSPartition(box86context_t* context, int tlssize);
|
int AddTLSPartition(box86context_t* context, int tlssize);
|
||||||
|
|
||||||
#define PROT_DYNAREC 0x10000
|
|
||||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
|
||||||
uint32_t getProtection(uintptr_t addr);
|
|
||||||
#ifdef DYNAREC
|
|
||||||
void protectDB(uintptr_t addr, uintptr_t size);
|
|
||||||
void unprotectDB(uintptr_t addr, uintptr_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// defined in fact in threads.c
|
// defined in fact in threads.c
|
||||||
void thread_set_emu(x86emu_t* emu);
|
void thread_set_emu(x86emu_t* emu);
|
||||||
x86emu_t* thread_get_emu();
|
x86emu_t* thread_get_emu();
|
||||||
|
@ -23,15 +23,25 @@ typedef struct dynablocklist_s dynablocklist_t;
|
|||||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
|
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
|
||||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
|
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
|
||||||
|
|
||||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker);
|
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
|
||||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||||
|
|
||||||
dynablocklist_t* getDB(uintptr_t idx);
|
dynablocklist_t* getDB(uintptr_t idx);
|
||||||
void addJumpTableIfDefault(void* addr, void* jmp);
|
void addJumpTableIfDefault(void* addr, void* jmp);
|
||||||
void setJumpTableDefault(void* addr);
|
void setJumpTableDefault(void* addr);
|
||||||
uintptr_t getJumpTable();
|
uintptr_t getJumpTable();
|
||||||
|
uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PROT_DYNAREC 0x10000
|
||||||
|
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||||
|
uint32_t getProtection(uintptr_t addr);
|
||||||
|
#ifdef DYNAREC
|
||||||
|
void protectDB(uintptr_t addr, uintptr_t size);
|
||||||
|
void unprotectDB(uintptr_t addr, uintptr_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void init_custommem_helper(box86context_t* ctx);
|
void init_custommem_helper(box86context_t* ctx);
|
||||||
void fini_custommem_helper(box86context_t* ctx);
|
void fini_custommem_helper(box86context_t* ctx);
|
||||||
|
|
||||||
|
@ -9,12 +9,10 @@ extern int box86_dynarec;
|
|||||||
extern int box86_pagesize;
|
extern int box86_pagesize;
|
||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
extern int box86_dynarec_dump;
|
extern int box86_dynarec_dump;
|
||||||
extern int box86_dynarec_linker;
|
|
||||||
extern int box86_dynarec_trace;
|
extern int box86_dynarec_trace;
|
||||||
extern int box86_dynarec_forced;
|
extern int box86_dynarec_forced;
|
||||||
extern int box86_dynarec_largest;
|
extern int box86_dynarec_largest;
|
||||||
extern int box86_dynarec_smc;
|
extern int box86_dynarec_smc;
|
||||||
extern int box86_dynarec_safemmap;
|
|
||||||
#ifdef ARM
|
#ifdef ARM
|
||||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||||
extern int arm_swap;
|
extern int arm_swap;
|
||||||
|
@ -7,7 +7,7 @@ typedef struct dynablocklist_s dynablocklist_t;
|
|||||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||||
|
|
||||||
uint32_t X31_hash_code(void* addr, int len);
|
uint32_t X31_hash_code(void* addr, int len);
|
||||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int nolinker, int direct);
|
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||||
void FreeDynablock(dynablock_t* db);
|
void FreeDynablock(dynablock_t* db);
|
||||||
void MarkDynablock(dynablock_t* db);
|
void MarkDynablock(dynablock_t* db);
|
||||||
|
@ -33,9 +33,6 @@ void ResetSegmentsCache(x86emu_t *emu);
|
|||||||
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip);
|
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip);
|
||||||
|
|
||||||
void StopEmu(x86emu_t* emu, const char* reason);
|
void StopEmu(x86emu_t* emu, const char* reason);
|
||||||
#ifdef DYNAREC
|
|
||||||
void DynablockEmuMarker(box86context_t* context);
|
|
||||||
#endif
|
|
||||||
void PushExit(x86emu_t* emu);
|
void PushExit(x86emu_t* emu);
|
||||||
void* GetExit();
|
void* GetExit();
|
||||||
void EmuCall(x86emu_t* emu, uintptr_t addr);
|
void EmuCall(x86emu_t* emu, uintptr_t addr);
|
||||||
|
@ -618,9 +618,6 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
|||||||
dynarec_log(LOG_NONE, "Warning: Access to protected %p from %p, inside same dynablock\n", addr, pc);
|
dynarec_log(LOG_NONE, "Warning: Access to protected %p from %p, inside same dynablock\n", addr, pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(db_addr && !db_addr->nolinker) {
|
|
||||||
dynarec_log(LOG_NONE, "Warning: Access to protected %p from %p, inside a dynablock with linker\n", addr, pc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dynarec_log(LOG_DEBUG, "Access to protected %p from %p, unprotecting memory (prot=%x)\n", addr, pc, prot);
|
dynarec_log(LOG_DEBUG, "Access to protected %p from %p, unprotecting memory (prot=%x)\n", addr, pc, prot);
|
||||||
// access error, unprotect the block (and mark them dirty)
|
// access error, unprotect the block (and mark them dirty)
|
||||||
|
19
src/main.c
19
src/main.c
@ -49,11 +49,9 @@ int box86_pagesize;
|
|||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
int box86_dynarec = 1;
|
int box86_dynarec = 1;
|
||||||
int box86_dynarec_dump = 0;
|
int box86_dynarec_dump = 0;
|
||||||
int box86_dynarec_linker = 1;
|
|
||||||
int box86_dynarec_forced = 0;
|
int box86_dynarec_forced = 0;
|
||||||
int box86_dynarec_largest = 0;
|
int box86_dynarec_largest = 0;
|
||||||
int box86_dynarec_smc = 0;
|
int box86_dynarec_smc = 0;
|
||||||
int box86_dynarec_safemmap = 0;
|
|
||||||
#ifdef ARM
|
#ifdef ARM
|
||||||
int arm_vfp = 0; // vfp version (3 or 4), with 32 registers is mendatory
|
int arm_vfp = 0; // vfp version (3 or 4), with 32 registers is mendatory
|
||||||
int arm_swap = 0;
|
int arm_swap = 0;
|
||||||
@ -257,14 +255,6 @@ void LoadLogEnv()
|
|||||||
}
|
}
|
||||||
printf_log(LOG_INFO, "Dynarec is %s\n", box86_dynarec?"On":"Off");
|
printf_log(LOG_INFO, "Dynarec is %s\n", box86_dynarec?"On":"Off");
|
||||||
}
|
}
|
||||||
p = getenv("BOX86_DYNAREC_LINKER");
|
|
||||||
if(p) {
|
|
||||||
if(strlen(p)==1) {
|
|
||||||
if(p[0]>='0' && p[1]<='1')
|
|
||||||
box86_dynarec_linker = p[0]-'0';
|
|
||||||
}
|
|
||||||
printf_log(LOG_INFO, "Dynarec Linker is %s\n", box86_dynarec_linker?"On":"Off");
|
|
||||||
}
|
|
||||||
p = getenv("BOX86_DYNAREC_FORCED");
|
p = getenv("BOX86_DYNAREC_FORCED");
|
||||||
if(p) {
|
if(p) {
|
||||||
if(strlen(p)==1) {
|
if(strlen(p)==1) {
|
||||||
@ -283,14 +273,6 @@ void LoadLogEnv()
|
|||||||
if(box86_dynarec_smc)
|
if(box86_dynarec_smc)
|
||||||
printf_log(LOG_INFO, "Dynarec is trying to detect SMC in same dynablock\n");
|
printf_log(LOG_INFO, "Dynarec is trying to detect SMC in same dynablock\n");
|
||||||
}
|
}
|
||||||
p = getenv("BOX86_DYNAREC_SAFEMMAP");
|
|
||||||
if(p) {
|
|
||||||
if(strlen(p)==1) {
|
|
||||||
if(p[0]>='0' && p[1]<='1')
|
|
||||||
box86_dynarec_safemmap = p[0]-'0';
|
|
||||||
}
|
|
||||||
printf_log(LOG_INFO, "Dynarec Safe mmap is %s\n", box86_dynarec_safemmap?"On":"Off");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_TRACE
|
#ifdef HAVE_TRACE
|
||||||
p = getenv("BOX86_TRACE_XMM");
|
p = getenv("BOX86_TRACE_XMM");
|
||||||
@ -536,7 +518,6 @@ void PrintHelp() {
|
|||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
printf(" BOX86_DYNAREC_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed dynarec info\n");
|
printf(" BOX86_DYNAREC_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed dynarec info\n");
|
||||||
printf(" BOX86_DYNAREC with 0/1 to disable or enable Dynarec (On by default)\n");
|
printf(" BOX86_DYNAREC with 0/1 to disable or enable Dynarec (On by default)\n");
|
||||||
printf(" BOX86_DYNAREC_LINKER with 0/1 to disable or enable Dynarec Linker (On by default, use 0 only for easier debug)\n");
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_TRACE
|
#ifdef HAVE_TRACE
|
||||||
printf(" BOX86_TRACE with 1 to enable x86 execution trace\n");
|
printf(" BOX86_TRACE with 1 to enable x86 execution trace\n");
|
||||||
|
@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
KHASH_MAP_INIT_INT(bridgemap, uintptr_t)
|
KHASH_MAP_INIT_INT(bridgemap, uintptr_t)
|
||||||
|
|
||||||
#define NBRICK 64
|
//onebrigde is 16 bytes
|
||||||
|
#define NBRICK 4096/16
|
||||||
typedef struct brick_s brick_t;
|
typedef struct brick_s brick_t;
|
||||||
typedef struct brick_s {
|
typedef struct brick_s {
|
||||||
onebridge_t b[NBRICK];
|
onebridge_t *b;
|
||||||
int sz;
|
int sz;
|
||||||
brick_t *next;
|
brick_t *next;
|
||||||
} brick_t;
|
} brick_t;
|
||||||
@ -32,11 +33,17 @@ typedef struct bridge_s {
|
|||||||
kh_bridgemap_t *bridgemap;
|
kh_bridgemap_t *bridgemap;
|
||||||
} bridge_t;
|
} bridge_t;
|
||||||
|
|
||||||
|
brick_t* NewBrick()
|
||||||
|
{
|
||||||
|
brick_t* ret = (brick_t*)calloc(1, sizeof(brick_t));
|
||||||
|
posix_memalign((void**)&ret->b, box86_pagesize, NBRICK*sizeof(onebridge_t));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bridge_t *NewBridge()
|
bridge_t *NewBridge()
|
||||||
{
|
{
|
||||||
bridge_t *b = (bridge_t*)calloc(1, sizeof(bridge_t));
|
bridge_t *b = (bridge_t*)calloc(1, sizeof(bridge_t));
|
||||||
b->head = (brick_t*)calloc(1, sizeof(brick_t));
|
b->head = NewBrick();
|
||||||
b->last = b->head;
|
b->last = b->head;
|
||||||
b->bridgemap = kh_init(bridgemap);
|
b->bridgemap = kh_init(bridgemap);
|
||||||
|
|
||||||
@ -47,6 +54,11 @@ void FreeBridge(bridge_t** bridge)
|
|||||||
brick_t *b = (*bridge)->head;
|
brick_t *b = (*bridge)->head;
|
||||||
while(b) {
|
while(b) {
|
||||||
brick_t *n = b->next;
|
brick_t *n = b->next;
|
||||||
|
#ifdef DYNAREC
|
||||||
|
if(getProtection((uintptr_t)b->b)&PROT_DYNAREC)
|
||||||
|
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||||
|
#endif
|
||||||
|
free(b->b);
|
||||||
free(b);
|
free(b);
|
||||||
b = n;
|
b = n;
|
||||||
}
|
}
|
||||||
@ -59,24 +71,33 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N)
|
|||||||
{
|
{
|
||||||
brick_t *b = bridge->last;
|
brick_t *b = bridge->last;
|
||||||
if(b->sz == NBRICK) {
|
if(b->sz == NBRICK) {
|
||||||
b->next = (brick_t*)calloc(1, sizeof(brick_t));
|
b->next = NewBrick();
|
||||||
b = b->next;
|
b = b->next;
|
||||||
bridge->last = b;
|
bridge->last = b;
|
||||||
}
|
}
|
||||||
|
#ifdef DYNAREC
|
||||||
|
int prot = 0;
|
||||||
|
if(box86_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));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
b->b[b->sz].CC = 0xCC;
|
b->b[b->sz].CC = 0xCC;
|
||||||
b->b[b->sz].S = 'S'; b->b[b->sz].C='C';
|
b->b[b->sz].S = 'S'; b->b[b->sz].C='C';
|
||||||
b->b[b->sz].w = w;
|
b->b[b->sz].w = w;
|
||||||
b->b[b->sz].f = (uintptr_t)fnc;
|
b->b[b->sz].f = (uintptr_t)fnc;
|
||||||
b->b[b->sz].C3 = N?0xC2:0xC3;
|
b->b[b->sz].C3 = N?0xC2:0xC3;
|
||||||
b->b[b->sz].N = N;
|
b->b[b->sz].N = N;
|
||||||
|
#ifdef DYNAREC
|
||||||
|
if(box86_dynarec && prot)
|
||||||
|
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||||
|
#endif
|
||||||
// add bridge to map, for fast recovery
|
// add bridge to map, for fast recovery
|
||||||
int ret;
|
int ret;
|
||||||
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
|
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
|
||||||
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[b->sz].CC;
|
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[b->sz].CC;
|
||||||
#ifdef DYNAREC
|
|
||||||
if(box86_dynarec)
|
|
||||||
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t), 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (uintptr_t)&b->b[b->sz++].CC;
|
return (uintptr_t)&b->b[b->sz++].CC;
|
||||||
}
|
}
|
||||||
@ -92,7 +113,7 @@ uintptr_t CheckBridged(bridge_t* bridge, void* fnc)
|
|||||||
|
|
||||||
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N)
|
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N)
|
||||||
{
|
{
|
||||||
if(!fnc)
|
if(!fnc && w)
|
||||||
return 0;
|
return 0;
|
||||||
uintptr_t ret = CheckBridged(bridge, fnc);
|
uintptr_t ret = CheckBridged(bridge, fnc);
|
||||||
if(!ret)
|
if(!ret)
|
||||||
|
@ -6,14 +6,16 @@
|
|||||||
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct onebridge_s {
|
typedef union onebridge_s {
|
||||||
|
struct {
|
||||||
uint8_t CC; // CC int 0x3
|
uint8_t CC; // CC int 0x3
|
||||||
uint8_t S, C; // 'S' 'C', just a signature
|
uint8_t S, C; // 'S' 'C', just a signature
|
||||||
wrapper_t w; // wrapper
|
wrapper_t w; // wrapper
|
||||||
uintptr_t f; // the function for the wrapper
|
uintptr_t f; // the function for the wrapper
|
||||||
uint8_t C3; // C2 or C3 ret
|
uint8_t C3; // C2 or C3 ret
|
||||||
uint16_t N; // N in case of C2 ret
|
uint16_t N; // N in case of C2 ret
|
||||||
uint8_t dummy[1+2]; // to get 4*32bits size
|
};
|
||||||
|
uint32_t dummy[4];
|
||||||
} onebridge_t;
|
} onebridge_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
@ -2302,14 +2302,11 @@ EXPORT void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot,
|
|||||||
// and responded with a different address, so ignore it
|
// and responded with a different address, so ignore it
|
||||||
} else {
|
} else {
|
||||||
if(prot& PROT_EXEC)
|
if(prot& PROT_EXEC)
|
||||||
addDBFromAddressRange((uintptr_t)ret, length, ((flags&MAP_ANONYMOUS) && !box86_dynarec_safemmap)?1:0);
|
addDBFromAddressRange((uintptr_t)ret, length);
|
||||||
else
|
else
|
||||||
cleanDBFromAddressRange((uintptr_t)ret, length, 0);
|
cleanDBFromAddressRange((uintptr_t)ret, length, 0);
|
||||||
}
|
}
|
||||||
} else if(box86_dynarec && ret==(void*)-1 && !((flags&MAP_ANONYMOUS) && !box86_dynarec_safemmap) && addr) {
|
}
|
||||||
// hack, the programs wanted to map a file, but system didn't want. Still, mark the memory as ok with linker
|
|
||||||
addDBFromAddressRange((uintptr_t)addr, length, 0);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if(ret!=(void*)-1)
|
if(ret!=(void*)-1)
|
||||||
updateProtection((uintptr_t)ret, length, prot);
|
updateProtection((uintptr_t)ret, length, prot);
|
||||||
@ -2331,13 +2328,10 @@ EXPORT void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot
|
|||||||
// and responded with a different address, so ignore it
|
// and responded with a different address, so ignore it
|
||||||
} else {
|
} else {
|
||||||
if(prot& PROT_EXEC)
|
if(prot& PROT_EXEC)
|
||||||
addDBFromAddressRange((uintptr_t)ret, length, ((flags&MAP_ANONYMOUS) && !box86_dynarec_safemmap)?1:0);
|
addDBFromAddressRange((uintptr_t)ret, length);
|
||||||
else
|
else
|
||||||
cleanDBFromAddressRange((uintptr_t)ret, length, 0);
|
cleanDBFromAddressRange((uintptr_t)ret, length, 0);
|
||||||
}
|
}
|
||||||
} else if(box86_dynarec && ret==(void*)-1 && !((flags&MAP_ANONYMOUS) && !box86_dynarec_safemmap) && addr) {
|
|
||||||
// hack, the programs wanted to map a file, but system didn't want. Still, mark the memory as ok with linker
|
|
||||||
addDBFromAddressRange((uintptr_t)addr, length, 0);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(ret!=(void*)-1)
|
if(ret!=(void*)-1)
|
||||||
@ -2368,7 +2362,7 @@ EXPORT int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot)
|
|||||||
#ifdef DYNAREC
|
#ifdef DYNAREC
|
||||||
if(box86_dynarec) {
|
if(box86_dynarec) {
|
||||||
if(prot& PROT_EXEC)
|
if(prot& PROT_EXEC)
|
||||||
addDBFromAddressRange((uintptr_t)addr, len, 1);
|
addDBFromAddressRange((uintptr_t)addr, len);
|
||||||
else
|
else
|
||||||
cleanDBFromAddressRange((uintptr_t)addr, len, 0);
|
cleanDBFromAddressRange((uintptr_t)addr, len, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user