about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-10-28 10:16:55 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-10-28 10:16:55 +0200
commitc71035530a982ac940aa5c71233edf2e21445c92 (patch)
tree07253a5ddffbe0c9e47db95a15fdb2068bcb85dc
parentacaf23fcb84d7a7e30b4fc5824f242ea1e1b4cde (diff)
downloadbox64-c71035530a982ac940aa5c71233edf2e21445c92.tar.gz
box64-c71035530a982ac940aa5c71233edf2e21445c92.zip
More small improvment to wrapped mmap64
-rw-r--r--src/wrapped/wrappedlibc.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index d78b6ecb..d44d3ad2 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2545,49 +2545,62 @@ EXPORT int my_readlinkat(x64emu_t* emu, int fd, void* path, void* buf, size_t bu
     }
     return readlinkat(fd, path, buf, bufsize);
 }
-
+#ifndef MAP_FIXED_NOREPLACE
+#define MAP_FIXED_NOREPLACE	0x200000
+#endif
+#ifndef MAP_32BIT
+#define MAP_32BIT 0x40
+#endif
 EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset)
 {
     (void)emu;
     if(prot&PROT_WRITE)
         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);}
+    int new_flags = flags;
     #ifndef NOALIGN
     void* old_addr = addr;
-    if(flags&0x40) {
-        // 0x40 is MAP_32BIT, wich only exist on x86_64!
-        //flags &= ~0x40;   // let the flags in?
+    new_flags&=~MAP_32BIT;   // remove MAP_32BIT
+    if(flags&MAP_32BIT) {
+        // MAP_32BIT only exist on x86_64!
         addr = find31bitBlockNearHint(addr, length);
     } else if (box64_wine || 1) {   // other mmap should be restricted to 47bits
         if(!addr)
             addr = find47bitBlock(length);
     }
     #endif
-    void* ret = mmap64(addr, length, prot, flags, fd, offset);
+    void* ret = mmap64(addr, length, prot, new_flags, fd, offset);
     #ifndef NOALIGN
-    if((ret!=(void*)-1) && (flags&0x40) &&
+    if((ret!=MAP_FAILED) && (flags&MAP_32BIT) &&
       (((uintptr_t)ret>0xffffffffLL) || (box64_wine && ((uintptr_t)ret&0xffff)))) {
         printf_log(LOG_DEBUG, "Warning, mmap on 32bits didn't worked, ask %p, got %p ", addr, ret);
         munmap(ret, length);
         loadProtectionFromMap();    // reload map, because something went wrong previously
         addr = find31bitBlockNearHint(old_addr, length); // is this the best way?
-        uint32_t new_flags = (addr && isBlockFree(addr, length) )? (flags|MAP_FIXED) : flags;
+        new_flags = (addr && isBlockFree(addr, length) )? (new_flags|MAP_FIXED) : new_flags;
+        if(new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE)==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
         ret = mmap64(addr, length, prot, new_flags, fd, offset);
         printf_log(LOG_DEBUG, " tried again with %p, got %p\n", addr, ret);
-    } else if((ret!=(void*)-1) && !(flags&MAP_FIXED) && (box64_wine) && (old_addr) && (addr!=ret) &&
+    } else if((ret!=MAP_FAILED) && !(flags&MAP_FIXED) && (box64_wine) && (old_addr) && (addr!=ret) &&
              (((uintptr_t)ret>0x7fffffffffffLL) || ((uintptr_t)ret&~0xffff))) {
         printf_log(LOG_DEBUG, "Warning, mmap on 47bits didn't worked, ask %p, got %p ", addr, ret);
         munmap(ret, length);
         loadProtectionFromMap();    // reload map, because something went wrong previously
         addr = find47bitBlockNearHint(old_addr, length); // is this the best way?
-        uint32_t new_flags = (addr && isBlockFree(addr, length)) ? (flags|MAP_FIXED) : flags;
+        new_flags = (addr && isBlockFree(addr, length)) ? (new_flags|MAP_FIXED) : new_flags;
+        if(new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE)==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
         ret = mmap64(addr, length, prot, new_flags, fd, offset);
         printf_log(LOG_DEBUG, " tried again with %p, got %p\n", addr, ret);
     }
     #endif
+    if((ret!=MAP_FAILED) && (flags&MAP_FIXED_NOREPLACE) && (ret!=addr)) {
+        munmap(ret, length);
+        errno = EEXIST;
+        return MAP_FAILED;
+    }
     if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
     #ifdef DYNAREC
-    if(box64_dynarec && ret!=(void*)-1) {
+    if(box64_dynarec && ret!=MAP_FAILED) {
         /*if(flags&0x100000 && addr!=ret)
         {
             // program used MAP_FIXED_NOREPLACE but the host linux didn't support it
@@ -2600,7 +2613,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
         }
     }
     #endif
-    if(ret!=(void*)-1) {
+    if(ret!=MAP_FAILED) {
         setProtection_mmap((uintptr_t)ret, length, prot);
     }
     return ret;
@@ -2661,12 +2674,12 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
 {
     (void)emu;
     dynarec_log(LOG_DEBUG, "munmap(%p, %lu)\n", addr, length);
+    int ret = munmap(addr, length);
     #ifdef DYNAREC
-    if(box64_dynarec && length) {
+    if(!ret && box64_dynarec && length) {
         cleanDBFromAddressRange((uintptr_t)addr, length, 1);
     }
     #endif
-    int ret = munmap(addr, length);
     if(!ret) {
         freeProtection((uintptr_t)addr, length);
     }