about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-04-04 10:19:47 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-04-04 10:19:47 +0200
commit29f65bb6beff6457db6f00315c1395f944ec93ed (patch)
tree814655902322d3ef9b614bf9267bd9fcc0bcdf97 /src
parentcce929341312896c0e03ee0380d14aa3cc473964 (diff)
downloadbox64-29f65bb6beff6457db6f00315c1395f944ec93ed.tar.gz
box64-29f65bb6beff6457db6f00315c1395f944ec93ed.zip
More work on mmap and the MAP_32BIT flag
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c55
-rwxr-xr-xsrc/emu/x64int3.c2
-rw-r--r--src/include/custommem.h9
-rwxr-xr-xsrc/libtools/signals.c4
-rwxr-xr-xsrc/libtools/threads.c2
-rwxr-xr-xsrc/wrapped/wrappedlibc.c15
6 files changed, 70 insertions, 17 deletions
diff --git a/src/custommem.c b/src/custommem.c
index d1921b83..0358543d 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -763,7 +763,7 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
         uint32_t dyn = kh_value(memprot, k)[ii]&PROT_DYNAREC;
         if(dyn && (prot&PROT_WRITE))    // need to remove the write protection from this block
             mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
-        kh_value(memprot, k)[ii] = prot|dyn;
+        kh_value(memprot, k)[ii] = prot|dyn|PROT_ALLOC;
     }
     pthread_mutex_unlock(&mutex_prot);
 }
@@ -783,7 +783,27 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
             kh_value(memprot, k) = m;
         }
         const uintptr_t ii = i&(MEMPROT_SIZE-1);
-        kh_value(memprot, k)[ii] = prot;
+        kh_value(memprot, k)[ii] = prot|PROT_ALLOC;
+    }
+    pthread_mutex_unlock(&mutex_prot);
+}
+
+void freeProtection(uintptr_t addr, uintptr_t size)
+{
+    dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
+    uintptr_t idx = (addr>>MEMPROT_SHIFT);
+    uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
+    int ret;
+    pthread_mutex_lock(&mutex_prot);
+    for (uintptr_t i=idx; i<=end; ++i) {
+        const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
+        khint_t k = kh_put(memprot, memprot, key, &ret);
+        if(ret) {
+            uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
+            kh_value(memprot, k) = m;
+        }
+        const uintptr_t ii = i&(MEMPROT_SIZE-1);
+        kh_value(memprot, k)[ii] = 0;
     }
     pthread_mutex_unlock(&mutex_prot);
 }
@@ -803,7 +823,6 @@ uint32_t getProtection(uintptr_t addr)
     return ret;
 }
 
-#ifndef NOALIGN
 #define LOWEST (void*)0x20000
 int availableBlock(uint8_t* p, size_t n)
 {
@@ -827,15 +846,41 @@ void* find32bitBlock(size_t size)
     void* p = (void*)LOWEST;
     int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
     do {
-        const uintptr_t idx = ((((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT);
+        const uintptr_t idx = ((uintptr_t)p)>>MEMPROT_SHIFT;
         if(availableBlock(prot+idx, pages))
             return p;
         p += 0x10000;
     } while(p!=(void*)0xffff0000);
+    printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
+    return NULL;
+}
+void* findBlockNearHint(void* hint, size_t size)
+{
+    // slow iterative search... Would need something better one day
+    if(!hint) hint=LOWEST;
+    const uint32_t key = (((uintptr_t)hint)>>32)&0xffffffff;
+    pthread_mutex_lock(&mutex_prot);
+    khint_t k = kh_get(memprot, memprot, key);
+    if(k==kh_end(memprot)) {
+        pthread_mutex_unlock(&mutex_prot);
+        return hint;
+    }
+    uint8_t *prot = kh_val(memprot, k);
+    pthread_mutex_unlock(&mutex_prot);
+    void* p = hint;
+    void* end = (void*)((uintptr_t)hint+0x100000000LL);
+    uintptr_t step = (size+0xfff)&~0xfff;
+    int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
+    do {
+        const uintptr_t idx = (((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT;
+        if(availableBlock(prot+idx, pages))
+            return p;
+        p += step;
+    } while(p!=end);
+    printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
     return NULL;
 }
 #undef LOWEST
-#endif
 
 
 void init_custommem_helper(box64context_t* ctx)
diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c
index 8b967ff9..73d57deb 100755
--- a/src/emu/x64int3.c
+++ b/src/emu/x64int3.c
@@ -117,7 +117,7 @@ void x64Int3(x64emu_t* emu)
                 } else  if(strstr(s, "my___printf_chk")) {
                     tmp = (char*)(R_RSI);
                     snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
-                } else  if(strstr(s, "mmap64")) {
+                } else  if(!strcmp(s, "mmap64") || !strcmp(s, "mmap")) {
                     snprintf(buff, 255, "%04d|%p: Calling %s(%p, %lu, 0x%x, 0x%x, %d, %ld)", tid, *(void**)(R_RSP), s, 
                         (void*)R_RDI, R_RSI, (int)(R_RDX), (int)R_RCX, (int)R_R8, R_R9);
                 } else  if(!strcmp(s, "sscanf")) {
diff --git a/src/include/custommem.h b/src/include/custommem.h
index 551063d1..15f38596 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -34,9 +34,13 @@ uintptr_t getJumpTable64();
 uintptr_t getJumpTableAddress64(uintptr_t addr);
 #endif
 
-#define PROT_DYNAREC 0x80
+#define PROT_DYNAREC    0x80
+#define PROT_ALLOC      0x40
+#define PROT_CUSTOM     (PROT_DYNAREC|PROT_ALLOC)
+
 void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
 void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
+void freeProtection(uintptr_t addr, uintptr_t size);
 uint32_t getProtection(uintptr_t addr);
 #ifdef DYNAREC
 void protectDB(uintptr_t addr, uintptr_t size);
@@ -45,9 +49,8 @@ void unprotectDB(uintptr_t addr, uintptr_t size);
 void lockDB();
 void unlockDB();
 #endif
-#ifndef NOALIGN
 void* find32bitBlock(size_t size);
-#endif
+void* findBlockNearHint(void* hint, size_t size);
 
 
 void init_custommem_helper(box64context_t* ctx);
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index eb533b0d..d6014c19 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -700,8 +700,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
     void * pc = NULL;    // unknow arch...
     #warning Unhandled architecture
 #endif
-#ifdef DYNAREC
     uint32_t prot = getProtection((uintptr_t)addr);
+#ifdef DYNAREC
     dynablock_t* db = NULL;
     int db_searched = 0;
     if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
@@ -834,6 +834,8 @@ exit(-1);
         else
             printf_log(log_minimum, "\n");
     }
+    if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7))
+        return; // that's probably just a multi-task glitch, like seen in terraria
     if(my_context->signals[sig] && my_context->signals[sig]!=1) {
         if(my_context->is_sigaction[sig])
             my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db);
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index ed37ca2c..567fb76f 100755
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -306,7 +306,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
 	et->fnc = (uintptr_t)start_routine;
 	et->arg = arg;
 	#ifdef DYNAREC
-	if(box64_dynarec) {
+	if(0 && box64_dynarec) {	// disable for now
 		// pre-creation of the JIT code for the entry point of the thread
 		dynablock_t *current = NULL;
 		DBGetBlock(emu, (uintptr_t)start_routine, 1, &current);
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 2490dcb0..9c437226 100755
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -1896,10 +1896,13 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
         prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on i386
     if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) =>", addr, length, prot, flags, fd, offset);}
     #ifndef NOALIGN
-    if(!addr && (flags&0x40)) {
+    if(flags&0x40) {
         // 0x40 is MAP_32BIT, wich only exist on x86_64!
         //flags &= ~0x40;   // let the flags in?
-        addr = find32bitBlock(length);
+        if(!addr)
+            addr = find32bitBlock(length);
+        else
+            addr = findBlockNearHint(addr, length);
     }
     #endif
     void* ret = mmap64(addr, length, prot, flags, fd, offset);
@@ -1931,7 +1934,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne
     dynarec_log(LOG_DEBUG, "%p\n", ret);
     if(ret==(void*)-1)
         return ret; // failed...
-    uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_DYNAREC;
+    uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM;
     if(ret==old_addr) {
         if(old_size && old_size<new_size) {
             setProtection((uintptr_t)ret+old_size, new_size-old_size, prot);
@@ -1940,7 +1943,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne
                 addDBFromAddressRange((uintptr_t)ret+old_size, new_size-old_size);
             #endif
         } else if(old_size && new_size<old_size) {
-            setProtection((uintptr_t)ret+new_size, old_size-new_size, 0);
+            freeProtection((uintptr_t)ret+new_size, old_size-new_size);
             #ifdef DYNAREC
             if(box64_dynarec)
                 cleanDBFromAddressRange((uintptr_t)ret+new_size, new_size-old_size, 1);
@@ -1958,7 +1961,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne
         && flags&MREMAP_DONTUNMAP==0
         #endif
         ) {
-            setProtection((uintptr_t)old_addr, old_size, 0);
+            freeProtection((uintptr_t)old_addr, old_size);
             #ifdef DYNAREC
             if(box64_dynarec)
                 cleanDBFromAddressRange((uintptr_t)old_addr, old_size, 1);
@@ -1983,7 +1986,7 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
     #endif
     int ret = munmap(addr, length);
     if(!ret)
-        setProtection((uintptr_t)addr, length, 0);
+        freeProtection((uintptr_t)addr, length);
     return ret;
 }