about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-10-07 09:25:04 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-10-07 09:25:04 +0200
commitf81677278f6bbe387e20f7b9f642f8dcbef12387 (patch)
tree36b13e609477329ba3736f27931c408eb1f0f486 /src
parent2ef6011c7aebe44870795e1faaae9dde462cb7af (diff)
downloadbox64-f81677278f6bbe387e20f7b9f642f8dcbef12387.tar.gz
box64-f81677278f6bbe387e20f7b9f642f8dcbef12387.zip
Reworked mmap allocator and wine prereserve handling ([BOX32] fix handling of wine prereserve)
Diffstat (limited to 'src')
-rw-r--r--src/core.c33
-rw-r--r--src/custommem.c4
-rw-r--r--src/tools/wine_tools.c40
-rw-r--r--src/wrapped/wrappedlibc.c8
4 files changed, 59 insertions, 26 deletions
diff --git a/src/core.c b/src/core.c
index 58acfd30..a07b1aff 100644
--- a/src/core.c
+++ b/src/core.c
@@ -2388,22 +2388,6 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
 
     // export symbols
     AddSymbols(my_context->maplib, elf_header);
-    if(wine_preloaded) {
-        uintptr_t wineinfo = 0;
-        int ver = -1, veropt = 0;
-        const char* vername = NULL;
-        if(!ElfGetGlobalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
-            if(!ElfGetWeakSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
-                ElfGetLocalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt);
-        if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");}
-        else {
-            *(void**)wineinfo = get_wine_prereserve();
-            printf_log(LOG_DEBUG, "WINE wine_main_preload_info found and updated %p -> %p\n", get_wine_prereserve(), *(void**)wineinfo);
-        }
-        #ifdef DYNAREC
-        dynarec_wine_prereserve();
-        #endif
-    }
     AddMainElfToLinkmap(elf_header);
     // pre-load lib if needed
     if(ld_preload.size) {
@@ -2437,6 +2421,23 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
     }
     // and handle PLT
     RelocateElfPlt(my_context->maplib, NULL, 0, 0, elf_header);
+    // wine preload special case
+    if(wine_preloaded) {
+        uintptr_t wineinfo = 0;
+        int ver = -1, veropt = 0;
+        const char* vername = NULL;
+        if(!ElfGetGlobalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
+            if(!ElfGetWeakSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
+                ElfGetLocalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt);
+        if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");}
+        else {
+            printf_log(LOG_INFO, "WINE wine_main_preload_info found and updated %p -> %p\n", (void**)wineinfo, get_wine_prereserve());
+            *(void**)wineinfo = get_wine_prereserve();
+        }
+        #ifdef DYNAREC
+        dynarec_wine_prereserve();
+        #endif
+    }
     // deferred init
     setupTraceInit();
     RunDeferredElfInit(emu);
diff --git a/src/custommem.c b/src/custommem.c
index 5e3de17a..4243b2f2 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -1656,7 +1656,9 @@ void* find47bitBlock(size_t size)
 {
     void* ret = find47bitBlockNearHint(HIGH, size, 0);
     if(!ret)
-        ret = find32bitBlock(size);
+        ret = find31bitBlockNearHint(MEDIUM, size, 0);
+    if(!ret)
+        ret = find31bitBlockNearHint(LOWEST, size, 0);
     return ret;
 }
 void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c
index 17f5bc8d..32106154 100644
--- a/src/tools/wine_tools.c
+++ b/src/tools/wine_tools.c
@@ -15,7 +15,14 @@ typedef struct wine_prereserve_s
     void*   addr;
     size_t  size;
 } wine_prereserve_t;
-
+#ifdef BOX32
+typedef struct wine_prereserve_32_s
+{
+    ptr_t   addr;
+    ulong_t  size;
+} wine_prereserve_32_t;
+#include "box32.h"
+#endif
 // only the prereseve argument is reserved, not the other zone that wine-preloader reserve
 static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00008000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}};
 
@@ -57,6 +64,15 @@ static void add_no_overlap(void* addr, size_t size)
     my_wine_reserve[idx].size = size;
 }
 
+static void remove_prereserve(int idx)
+{
+    while(my_wine_reserve[idx].size) {
+        my_wine_reserve[idx].addr = my_wine_reserve[idx+1].addr;
+        my_wine_reserve[idx].size = my_wine_reserve[idx+1].size;
+        ++idx;
+    }
+}
+
 void wine_prereserve(const char* reserve)
 {
     init_custommem_helper(my_context);
@@ -70,12 +86,14 @@ void wine_prereserve(const char* reserve)
     int idx = 0;
     while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) {
         void* ret = NULL;
-        if(!isBlockFree(my_wine_reserve[idx].addr, my_wine_reserve[idx].size) && ((ret=mmap(my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 0, MAP_ANONYMOUS|MAP_NORESERVE, -1, 0))==my_wine_reserve[idx].addr)) {
-            printf_log(LOG_NONE, "Warning, prereserve of %p:0x%lx is not free\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
+        int isfree = isBlockFree(my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
+        if(isfree) ret=mmap(my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 0, MAP_FIXED|MAP_PRIVATE|MAP_ANON|MAP_NORESERVE, -1, 0); else ret = NULL;
+        if(!isfree || (ret!=my_wine_reserve[idx].addr)) {
+            if(addr>=(void*)0x10000LL)
+                printf_log(LOG_NONE, "Warning, prereserve of %p:0x%lx is not free\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
             if(ret)
                 munmap(ret, my_wine_reserve[idx].size);
-            my_wine_reserve[idx].addr = NULL;
-            my_wine_reserve[idx].size = 0;
+            remove_prereserve(idx);
         } else {
             setProtection_mmap((uintptr_t)my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 0);
             printf_log(/*LOG_DEBUG*/LOG_INFO, "WINE prereserve of %p:0x%lx done\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
@@ -90,7 +108,17 @@ void* get_wine_prereserve()
 {
     if(!wine_preloaded)
         wine_prereserve(NULL);
-    return (void*)my_wine_reserve;
+    #ifdef BOX32
+    if(box64_is32bits) {
+        static wine_prereserve_32_t my_wine_reserve_32[5];
+        for(int i=0; i<5; ++i) {
+            my_wine_reserve_32[i].addr = to_ptrv(my_wine_reserve[i].addr);
+            my_wine_reserve_32[i].size = to_ulong(my_wine_reserve[i].size);
+        }
+        return &my_wine_reserve_32;
+    } else
+    #endif
+        return &my_wine_reserve;
 }
 
 extern int box64_quit;
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 1482d9d9..db57e446 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2928,9 +2928,10 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, size_t length, int prot, int f
     new_flags&=~MAP_32BIT;   // remove MAP_32BIT
     if((flags&MAP_32BIT) && !(flags&MAP_FIXED)) {
         // MAP_32BIT only exist on x86_64!
-        addr = find31bitBlockNearHint(old_addr, length, 0);
+        if(!(flags&MAP_FIXED) && (!old_addr || !isBlockFree(old_addr, length)))
+            addr = find31bitBlockNearHint(old_addr, length, 0);
     } else if (box64_wine || 1) {   // other mmap should be restricted to 47bits
-        if(!addr)
+        if(!(flags&MAP_FIXED) && (!addr || !isBlockFree(addr, length)))
             addr = find47bitBlock(length);
     }
     #endif
@@ -2972,7 +2973,8 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, size_t length, int prot, int f
         errno = EEXIST;
         return MAP_FAILED;
     }
-    if((emu || box64_is32bits) && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);}
+    if((ret==MAP_FAILED && (emu || box64_is32bits)) && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%s (%d)\n", strerror(errno), errno);}
+    if(((ret!=MAP_FAILED) && (emu || box64_is32bits)) && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);}
     #ifdef DYNAREC
     if(box64_dynarec && ret!=MAP_FAILED) {
         /*if(flags&0x100000 && addr!=ret)