mirror of
https://github.com/ptitSeb/box86.git
synced 2024-11-27 00:40:24 +00:00
[DYNAREC] Handling of memfd_create backed mmap on dynarec (backported from box64)
This commit is contained in:
parent
a8babcba8d
commit
984da28f40
@ -804,7 +804,7 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
uint32_t dyn = prot&PROT_DYN;
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
if(!(dyn&PROT_NOPROT)) {
|
||||
if(!(dyn&PROT_NEVERPROT)) {
|
||||
prot&=~PROT_CUSTOM;
|
||||
if(prot&PROT_WRITE) {
|
||||
if(!dyn)
|
||||
@ -843,7 +843,7 @@ void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
|
||||
oprot = prot;
|
||||
if(bend>end)
|
||||
bend = end;
|
||||
if(!(prot&PROT_NOPROT)) {
|
||||
if(!(prot&PROT_NEVERPROT)) {
|
||||
if(prot&PROT_DYNAREC) {
|
||||
prot&=~PROT_DYN;
|
||||
if(mark)
|
||||
@ -915,7 +915,7 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
uint32_t oprot;
|
||||
rb_get_end(memprot, cur, &oprot, &bend);
|
||||
uint32_t dyn=(oprot&PROT_DYN);
|
||||
if(!(dyn&PROT_NOPROT)) {
|
||||
if(!(dyn&PROT_NEVERPROT)) {
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
dyn = PROT_DYNAREC;
|
||||
mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
|
||||
|
@ -272,7 +272,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
|
||||
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
|
||||
if(hash!=db->hash) {
|
||||
db->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X, always_test:%d) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, db->always_test, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
dynablock_t* old = InvalidDynablock(db, need_lock);
|
||||
// start again... (will create a new block)
|
||||
@ -284,7 +284,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
|
||||
} else
|
||||
FreeInvalidDynablock(old, need_lock);
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X, always_test:%d) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, db->always_test, (void*)addr);
|
||||
protectDB((uintptr_t)db->x86_addr, db->x86_size);
|
||||
// fill back jumptable
|
||||
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
|
||||
|
@ -665,6 +665,13 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
block->dirty = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
if(getProtection(addr)&PROT_NEVERCLEAN) {
|
||||
block->dirty = 1;
|
||||
block->always_test = 1;
|
||||
}
|
||||
if(block->always_test) {
|
||||
dynarec_log(LOG_DEBUG, "Note: block marked as always dirty %p:%ld\n", block->x86_addr, block->x86_size);
|
||||
}
|
||||
current_helper = NULL;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
|
@ -39,11 +39,13 @@ uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||
uintptr_t getJumpAddress(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#define PROT_NEVERCLEAN 0x100
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#define PROT_NOPROT 0x20
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT | PROT_NEVERCLEAN)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT | PROT_NEVERCLEAN)
|
||||
#define PROT_NEVERPROT (PROT_NOPROT | PROT_NEVERCLEAN)
|
||||
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
|
@ -2991,33 +2991,33 @@ EXPORT void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot,
|
||||
#endif
|
||||
void* ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
#ifndef NOALIGN
|
||||
if(!addr && ret!=new_addr && ret!=(void*)-1) {
|
||||
if(!addr && ret!=new_addr && ret!=MAP_FAILED) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(addr, length, 0);
|
||||
ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
} else if(addr && ret!=(void*)-1 && ret!=new_addr &&
|
||||
} else if(addr && ret!=MAP_FAILED && ret!=new_addr &&
|
||||
((uintptr_t)ret&0xffff) && !(flags&MAP_FIXED) && box86_wine) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(addr, length, 0);
|
||||
ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
if(ret!=MAP_FAILED && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
// addr is probably too high, start again with a low address
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(NULL, length, 0); // is this the best way?
|
||||
ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && (uintptr_t)ret&0xffff) {
|
||||
if(ret!=MAP_FAILED && (uintptr_t)ret&0xffff) {
|
||||
munmap(ret, length);
|
||||
ret = (void*)-1;
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(box86_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec && ret!=(void*)-1) {
|
||||
if(box86_dynarec && ret!=MAP_FAILED) {
|
||||
/*if(flags&0x100000 && addr!=ret)
|
||||
{
|
||||
// program used MAP_FIXED_NOREPLACE but the host linux didn't support it
|
||||
@ -3030,8 +3030,19 @@ EXPORT void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ret!=(void*)-1 && emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
if(ret!=MAP_FAILED) {
|
||||
if((flags&MAP_SHARED) && (fd>0)) {
|
||||
uint32_t flags = fcntl(fd, F_GETFL);
|
||||
if((flags&O_ACCMODE)==O_RDWR) {
|
||||
if((box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "Note: Marking the region (%p-%p prot=%x) as NEVERCLEAN because fd have O_RDWR attribute\n", ret, ret+length, prot);}
|
||||
prot |= PROT_NEVERCLEAN;
|
||||
}
|
||||
}
|
||||
if(emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
else
|
||||
setProtection((uintptr_t)ret, length, prot);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3048,34 +3059,34 @@ EXPORT void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot
|
||||
#endif
|
||||
void* ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
#ifndef NOALIGN
|
||||
if(!addr && ret!=new_addr && ret!=(void*)-1) {
|
||||
if(!addr && ret!=new_addr && ret!=MAP_FAILED) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = (flags&MAP_FIXED)?addr:(addr?findBlockNearHint(addr, length, 0):find32bitBlock(length));
|
||||
ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
} else if(addr && ret!=(void*)-1 && ret!=new_addr &&
|
||||
} else if(addr && ret!=MAP_FAILED && ret!=new_addr &&
|
||||
((uintptr_t)ret&0xffff) && !(flags&MAP_FIXED) && box86_wine) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(addr, length, 0);
|
||||
ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
if(ret!=MAP_FAILED && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
// addr is probably too high, start again with a low address
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(NULL, length, 0); // is this the best way?
|
||||
ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && (uintptr_t)ret&0xffff) {
|
||||
if(ret!=MAP_FAILED && (uintptr_t)ret&0xffff) {
|
||||
munmap(ret, length);
|
||||
errno = EEXIST;
|
||||
ret = (void*)-1;
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(box86_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec && ret!=(void*)-1) {
|
||||
if(box86_dynarec && ret!=MAP_FAILED) {
|
||||
/*if(flags&0x100000 && addr!=ret)
|
||||
{
|
||||
// program used MAP_FIXED_NOREPLACE but the host linux didn't support it
|
||||
@ -3088,8 +3099,19 @@ EXPORT void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ret!=(void*)-1 && emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
if(ret!=MAP_FAILED) {
|
||||
if((flags&MAP_SHARED) && (fd>0)) {
|
||||
uint32_t flags = fcntl(fd, F_GETFL);
|
||||
if((flags&O_ACCMODE)==O_RDWR) {
|
||||
if((box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "Note: Marking the region (%p-%p prot=%x) as NEVERCLEAN because fd have O_RDWR attribute\n", ret, ret+length, prot);}
|
||||
prot |= PROT_NEVERCLEAN;
|
||||
}
|
||||
}
|
||||
if(emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
else
|
||||
setProtection((uintptr_t)ret, length, prot);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3099,7 +3121,7 @@ EXPORT void* my_mremap(x86emu_t* emu, void* old_addr, size_t old_size, size_t ne
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_NONE, "mremap(%p, 0x%x, 0x%x, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);
|
||||
void* ret = mremap(old_addr, old_size, new_size, flags, new_addr);
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_NONE, "%p\n", ret);
|
||||
if(ret==(void*)-1)
|
||||
if(ret==MAP_FAILED)
|
||||
return ret; // failed...
|
||||
uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM;
|
||||
if(ret==old_addr) {
|
||||
|
Loading…
Reference in New Issue
Block a user