about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-04-09 01:12:55 +0800
committerGitHub <noreply@github.com>2025-04-08 19:12:55 +0200
commitd592c1996d74e9e6e728026486cdab6a75f43aaa (patch)
tree935f142dff05d4640f2cd5865f8d63f8c3ca8cf9 /src
parent8b3d4404d77bcc806631e17038f046d409cb6b69 (diff)
downloadbox64-d592c1996d74e9e6e728026486cdab6a75f43aaa.tar.gz
box64-d592c1996d74e9e6e728026486cdab6a75f43aaa.zip
[WOW64] Add wow64 PE build scaffolding (#2513)
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c99
-rw-r--r--src/custommmap.c8
-rw-r--r--src/dynarec/dynablock.c2
-rw-r--r--src/include/custommem.h8
-rw-r--r--src/include/debug.h20
-rw-r--r--src/include/os.h33
-rw-r--r--src/libtools/threads.c12
-rw-r--r--src/os/os_linux.c38
-rw-r--r--src/os/os_wine.c90
9 files changed, 227 insertions, 83 deletions
diff --git a/src/custommem.c b/src/custommem.c
index a35aab57..f74666e7 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -2,16 +2,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <dlfcn.h>
-#include <signal.h>
 #include <pthread.h>
 #include <errno.h>
-#include <syscall.h>
-#include <sys/personality.h>
 
 #include "os.h"
 #include "box64context.h"
-#include "elfloader.h"
 #include "debug.h"
 #include "x64trace.h"
 #include "x64emu.h"
@@ -19,7 +14,6 @@
 #include "bridge.h"
 #include "library.h"
 #include "callback.h"
-#include "wrapper.h"
 #include "threads.h"
 #include "x64trace.h"
 #include "signals.h"
@@ -538,8 +532,8 @@ void* map128_customMalloc(size_t size, int is32bits)
     if(is32bits)    // unlocking, because mmap might use it
     mutex_unlock(&mutex_blocks);
     void* p = is32bits
-    ?box_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, -1, 0)
-    :(box64_is32bits?box32_dynarec_mmap(allocsize):internal_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
+        ? box_mmap(NULL, allocsize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0)
+        : (box64_is32bits ? box32_dynarec_mmap(allocsize) : InternalMmap(NULL, allocsize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
     if(is32bits)
     mutex_lock(&mutex_blocks);
     #ifdef TRACE_MEMSTAT
@@ -644,8 +638,8 @@ void* internal_customMalloc(size_t size, int is32bits)
     if(is32bits)    // unlocking, because mmap might use it
         mutex_unlock(&mutex_blocks);
     void* p = is32bits
-                ?box_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, -1, 0)
-                :(box64_is32bits?box32_dynarec_mmap(allocsize):internal_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
+        ? box_mmap(NULL, allocsize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0)
+        : (box64_is32bits ? box32_dynarec_mmap(allocsize) : InternalMmap(NULL, allocsize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
     if(is32bits)
         mutex_lock(&mutex_blocks);
 #ifdef TRACE_MEMSTAT
@@ -902,8 +896,8 @@ void* internal_customMemAligned(size_t align, size_t size, int is32bits)
     if(is32bits)
         mutex_unlock(&mutex_blocks);
     void* p = is32bits
-                ?mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, -1, 0)
-                :internal_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+        ? mmap(NULL, allocsize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0)
+        : InternalMmap(NULL, allocsize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     if(is32bits)
         mutex_lock(&mutex_blocks);
 #ifdef TRACE_MEMSTAT
@@ -988,7 +982,7 @@ void* box32_dynarec_mmap(size_t size)
     while(bend<0x800000000000LL) {
         if(rb_get_end(mapallmem, cur, &flag, &bend)) {
             if(flag==2 && bend-cur>=size) {
-                void* ret = internal_mmap((void*)cur, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+                void* ret = InternalMmap((void*)cur, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
                 if(ret!=MAP_FAILED)
                     rb_set(mapallmem, cur, cur+size, 1);    // mark as allocated
                 else
@@ -1001,7 +995,8 @@ void* box32_dynarec_mmap(size_t size)
     }
 #endif
     //printf_log(LOG_INFO, "BOX32: Error allocating Dynarec memory: %s\n", "fallback to internal mmap");
-    return internal_mmap((void*)0x100000000LL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);;
+    return InternalMmap((void*)0x100000000LL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+    ;
 }
 
 #ifdef DYNAREC
@@ -1075,13 +1070,13 @@ uintptr_t AllocDynarecMap(size_t size)
             // At least with a 2M allocation, transparent huge page should kick-in
             #if 0//def MAP_HUGETLB
             if(p==MAP_FAILED && allocsize==DYNMMAPSZ) {
-                p = internal_mmap(NULL, allocsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, -1, 0);
+                p = InternalMmap(NULL, allocsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, -1, 0);
                 if(p!=MAP_FAILED) printf_log(LOG_INFO, "Allocated a dynarec memory block with HugeTLB\n");
                 else printf_log(LOG_INFO, "Failled to allocated a dynarec memory block with HugeTLB (%s)\n", strerror(errno));
             }
             #endif
             if(p==MAP_FAILED)
-                p = internal_mmap(NULL, allocsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+                p = InternalMmap(NULL, allocsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
             if(p==MAP_FAILED) {
                 dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes (%s)\n", allocsize, strerror(errno));
                 return 0;
@@ -2085,10 +2080,10 @@ void relockCustommemMutex(int locks)
 
 static void init_mutexes(void)
 {
-    #ifdef USE_CUSTOM_MUTEX
+#ifdef USE_CUSTOM_MUTEX
     native_lock_store(&mutex_blocks, 0);
     native_lock_store(&mutex_prot, 0);
-    #else
+#else
     pthread_mutexattr_t attr;
     pthread_mutexattr_init(&attr);
     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
@@ -2096,7 +2091,7 @@ static void init_mutexes(void)
     pthread_mutex_init(&mutex_prot, &attr);
 
     pthread_mutexattr_destroy(&attr);
-    #endif
+#endif
 }
 
 static void atfork_child_custommem(void)
@@ -2111,11 +2106,11 @@ void reverveHigMem32(void)
     uintptr_t cur_size = 1024LL*1024*1024*1024; // start with 1TB check
     void* cur;
     while(cur_size>=65536) {
-        cur = internal_mmap(NULL, cur_size, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+        cur = InternalMmap(NULL, cur_size, 0, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
         if((cur==MAP_FAILED) || (cur<(void*)0x100000000LL)) {
             if(cur!=MAP_FAILED) {
                 //printf_log(LOG_INFO, " Failed to reserve high %p (%zx)\n", cur, cur_size);
-                internal_munmap(cur, cur_size);
+                InternalMunmap(cur, cur_size);
             } //else 
                 //printf_log(LOG_INFO, " Failed to reserve %zx sized block\n", cur_size);
             cur_size>>=1;
@@ -2136,7 +2131,7 @@ void reverveHigMem32(void)
             start = bend;
         }
     }
-    personality(ADDR_LIMIT_32BIT);
+    PersonalityAddrLimit32Bit();
 }
 #endif
 void my_reserveHighMem()
@@ -2165,7 +2160,7 @@ void my_reserveHighMem()
             // create a border at 48bits
             if(cur<(1ULL<<48) && bend>(1ULL<<48))
                 bend = 1ULL<<48;
-            void* ret = internal_mmap((void*)cur, bend-cur, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+            void* ret = InternalMmap((void*)cur, bend - cur, 0, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
             printf_log(LOG_DEBUG, "Reserve %p-%p => %p (%s)\n", (void*)cur, bend, ret, (ret==MAP_FAILED)?strerror(errno):"ok");
             if(ret!=(void*)-1) {
                 rb_set(mapallmem, cur, bend, 1);
@@ -2189,7 +2184,10 @@ void init_custommem_helper(box64context_t* ctx)
     if(inited) // already initialized
         return;
     inited = 1;
+
+#ifndef _WIN32 // TODO: better wow64 support?
     cur_brk = dlsym(RTLD_NEXT, "__curbrk");
+#endif
     blockstree = rbtree_init("blockstree");
     // if there is some blocks already
     if(n_blocks)
@@ -2219,7 +2217,9 @@ void init_custommem_helper(box64context_t* ctx)
     lockaddress = kh_init(lockaddress);
     rbt_dynmem = rbtree_init("rbt_dynmem");
 #endif
+#ifndef _WIN32 // TODO: better wow64 support?
     pthread_atfork(NULL, NULL, atfork_child_custommem);
+#endif
     // init mapallmem list
     mapallmem = rbtree_init("mapallmem");
     // init mmapmem list
@@ -2275,7 +2275,7 @@ void fini_custommem_helper(box64context_t *ctx)
         while(head) {
             for (int i=0; i<NCHUNK; ++i) {
                 if(head->chunks[i].chunk.block)
-                    internal_munmap(head->chunks[i].chunk.block, head->chunks[i].chunk.size);
+                    InternalMunmap(head->chunks[i].chunk.block, head->chunks[i].chunk.size);
                 if(head->chunks[i].tree)
                     rbtree_delete(head->chunks[i].tree);
             }
@@ -2323,12 +2323,12 @@ void fini_custommem_helper(box64context_t *ctx)
     blockstree = NULL;
 
     for(int i=0; i<n_blocks; ++i)
-        internal_munmap(p_blocks[i].block, p_blocks[i].size);
+        InternalMunmap(p_blocks[i].block, p_blocks[i].size);
     box_free(p_blocks);
-    #ifndef USE_CUSTOM_MUTEX
+#if !defined(USE_CUSTOM_MUTEX) && !defined(_WIN32) // TODO: better wow64 support?
     pthread_mutex_destroy(&mutex_prot);
     pthread_mutex_destroy(&mutex_blocks);
-    #endif
+#endif
 }
 
 #ifdef DYNAREC
@@ -2348,37 +2348,6 @@ int isLockAddress(uintptr_t addr)
 
 #endif
 
-void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset)
-{
-    #if 1//def STATICBUILD
-    void* ret = (void*)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
-    #else
-    static int grab = 1;
-    typedef void*(*pFpLiiiL_t)(void*, unsigned long, int, int, int, size_t);
-    static pFpLiiiL_t libc_mmap64 = NULL;
-    if(grab) {
-        libc_mmap64 = dlsym(RTLD_NEXT, "mmap64");
-    }
-    void* ret = libc_mmap64(addr, length, prot, flags, fd, offset);
-    #endif
-    return ret;
-}
-int internal_munmap(void* addr, unsigned long length)
-{
-    #if 1//def STATICBUILD
-    int ret = syscall(__NR_munmap, addr, length);
-    #else
-    static int grab = 1;
-    typedef int(*iFpL_t)(void*, unsigned long);
-    static iFpL_t libc_munmap = NULL;
-    if(grab) {
-        libc_munmap = dlsym(RTLD_NEXT, "munmap");
-    }
-    int ret = libc_munmap(addr, length);
-    #endif
-    return ret;
-}
-
 #ifndef MAP_FIXED_NOREPLACE
 #define MAP_FIXED_NOREPLACE 0x200000
 #endif
@@ -2401,28 +2370,28 @@ EXPORT void* box_mmap(void *addr, size_t length, int prot, int flags, int fd, ss
             addr = find47bitBlock(length);
     }
     #endif
-    void* ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
-    #if !defined(NOALIGN)
+    void* ret = InternalMmap(addr, length, prot, new_flags, fd, offset);
+#if !defined(NOALIGN)
     if((ret!=MAP_FAILED) && (flags&MAP_32BIT) &&
       (((uintptr_t)ret>0xffffffffLL) || ((box64_wine) && ((uintptr_t)ret&0xffff) && (ret!=addr)))) {
         int olderr = errno;
-        internal_munmap(ret, length);
+        InternalMunmap(ret, length);
         loadProtectionFromMap();    // reload map, because something went wrong previously
         addr = find31bitBlockNearHint(old_addr, length, 0); // is this the best way?
         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 = internal_mmap(addr, length, prot, new_flags, fd, offset);
+        ret = InternalMmap(addr, length, prot, new_flags, fd, offset);
         if(old_addr && ret!=old_addr && ret!=MAP_FAILED)
             errno = olderr;
     } else if((ret!=MAP_FAILED) && !(flags&MAP_FIXED) && ((box64_wine)) && (addr && (addr!=ret)) &&
              (((uintptr_t)ret>0x7fffffffffffLL) || ((uintptr_t)ret&~0xffff))) {
         int olderr = errno;
-        internal_munmap(ret, length);
+        InternalMunmap(ret, length);
         loadProtectionFromMap();    // reload map, because something went wrong previously
         addr = find47bitBlockNearHint(old_addr, length, 0); // is this the best way?
         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 = internal_mmap(addr, length, prot, new_flags, fd, offset);
+        ret = InternalMmap(addr, length, prot, new_flags, fd, offset);
         if(old_addr && ret!=old_addr && ret!=MAP_FAILED) {
             errno = olderr;
             if(old_addr>(void*)0x7fffffffff && !have48bits)
@@ -2435,6 +2404,6 @@ EXPORT void* box_mmap(void *addr, size_t length, int prot, int flags, int fd, ss
 
 EXPORT int box_munmap(void* addr, size_t length)
 {
-    int ret = internal_munmap(addr, length);
+    int ret = InternalMunmap(addr, length);
     return ret;
 }
diff --git a/src/custommmap.c b/src/custommmap.c
index 4f506f32..45e88fb5 100644
--- a/src/custommmap.c
+++ b/src/custommmap.c
@@ -24,8 +24,8 @@ extern void* mapallmem;
 extern int box64_is32bits;
 void setProtection(uintptr_t addr, size_t size, uint32_t prot);
 void freeProtection(uintptr_t addr, size_t size);
-void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
-int internal_munmap(void* addr, unsigned long length);
+void* InternalMmap(void* addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
+int InternalMunmap(void* addr, unsigned long length);
 void* box_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
 
 void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
@@ -39,7 +39,7 @@ EXPORT void* mmap64(void *addr, unsigned long length, int prot, int flags, int f
     if(!addr && ((running32bits && BOX64ENV(mmap32)) || (flags&MAP_32BIT) || box64_is32bits))
         ret = box_mmap(addr, length, prot, flags | MAP_32BIT, fd, offset);
     else
-        ret = internal_mmap(addr, length, prot, flags, fd, offset);
+        ret = InternalMmap(addr, length, prot, flags, fd, offset);
     if(ret!=MAP_FAILED && mapallmem)
         setProtection((uintptr_t)ret, length, prot);
     return ret;
@@ -48,7 +48,7 @@ EXPORT void* mmap(void *addr, unsigned long length, int prot, int flags, int fd,
 
 EXPORT int munmap(void* addr, unsigned long length)
 {
-    int ret = internal_munmap(addr, length);
+    int ret = InternalMunmap(addr, length);
     if(!ret && mapallmem) {
         freeProtection((uintptr_t)addr, length);
     }
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c
index 28f726f1..c12210b5 100644
--- a/src/dynarec/dynablock.c
+++ b/src/dynarec/dynablock.c
@@ -15,8 +15,6 @@
 #include "dynablock.h"
 #include "dynablock_private.h"
 #include "dynarec_private.h"
-#include "elfloader.h"
-#include "signals.h"
 #include "alternate.h"
 
 #include "dynarec_native.h"
diff --git a/src/include/custommem.h b/src/include/custommem.h
index b17eff99..5e883570 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -138,13 +138,9 @@ int checkInHotPage(uintptr_t addr);
 #endif
 
 // this will simulate an x86_64 version of the function (no tracking will done, but tracking will be used)
-void* box_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
+void* box_mmap(void* addr, size_t length, int prot, int flags, int fd, ssize_t offset);
 // this will simulate an x86_64 version of the function (no tracking will done)
-int box_munmap(void* addr, unsigned long length);
-// this will call the syscall directly
-void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
-// this will call the syscall directly
-int internal_munmap(void* addr, unsigned long length);
+int box_munmap(void* addr, size_t length);
 
 void reserveHighMem();
 
diff --git a/src/include/debug.h b/src/include/debug.h
index 631e35d7..93268420 100644
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -68,6 +68,7 @@ extern int box64_tcmalloc_minimal;  // when using tcmalloc_minimal
 #define LOG_NEVER 3
 #define LOG_VERBOSE 3
 
+#ifndef _WIN32 // TODO: better wow64 support?
 void printf_ftrace(int prefix, const char* fmt, ...);
 
 #define printf_log_prefix(prefix, L, ...)                                                               \
@@ -98,6 +99,18 @@ void printf_ftrace(int prefix, const char* fmt, ...);
 
 #define dynarec_log(L, ...) dynarec_log_prefix(1, L, __VA_ARGS__)
 
+#else
+#define printf_log_prefix(prefix, L, ...)
+#define printf_log(L, ...)
+#define printf_dump_prefix(prefix, L, ...)
+#define printf_dump(L, ...)
+#define printf_dlsym_prefix(prefix, L, ...)
+#define printf_dlsym(L, ...)
+#define dynarec_log_prefix(prefix, L, ...)
+#define dynarec_log(L, ...)
+#endif
+
+
 #define EXPORT __attribute__((visibility("default")))
 #ifdef BUILD_DYNAMIC
 #define EXPORTDYN __attribute__((visibility("default")))
@@ -105,6 +118,7 @@ void printf_ftrace(int prefix, const char* fmt, ...);
 #define EXPORTDYN
 #endif
 
+#ifndef _WIN32 // TODO: better wow64 support?
 #ifndef STATICBUILD
 void init_malloc_hook(void);
 #endif
@@ -131,6 +145,12 @@ extern void* __libc_memalign(size_t, size_t);
 extern char* box_strdup(const char* s);
 extern char* box_realpath(const char* path, char* ret);
 #endif
+#else
+#define box_malloc  WinMalloc
+#define box_realloc WinRealloc
+#define box_calloc  WinCalloc
+#define box_free    WinFree
+#endif
 
 //use actual_XXXX for internal memory that should be in 32bits space when box32 is active
 //use box_XXX for internal memory that doesn't need anything special
diff --git a/src/include/os.h b/src/include/os.h
index 6968df19..2ab70722 100644
--- a/src/include/os.h
+++ b/src/include/os.h
@@ -2,6 +2,37 @@
 #define __OS_H_
 
 #include <stdint.h>
+#include <sys/types.h>
+
+#ifndef _WIN32
+#include <dlfcn.h>
+#include <sys/mman.h>
+#else
+typedef __int64 ssize_t;
+
+#define PROT_READ  0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC  0x4
+
+#define MAP_FAILED    ((void*)-1)
+#define MAP_PRIVATE   0x02
+#define MAP_FIXED     0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_32BIT     0x40
+#define MAP_NORESERVE 0
+
+void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
+int munmap(void* addr, size_t length);
+int mprotect(void* addr, size_t len, int prot);
+
+void* WinMalloc(size_t size);
+void* WinRealloc(void* ptr, size_t size);
+void* WinCalloc(size_t nmemb, size_t size);
+void WinFree(void* ptr);
+#endif
+
+void* InternalMmap(void* addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
+int InternalMunmap(void* addr, unsigned long length);
 
 int GetTID(void);
 int SchedYield(void);
@@ -17,6 +48,8 @@ int IsBridgeSignature(char s, char c);
 int IsNativeCall(uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn);
 void EmuInt3(void* emu, void* addr);
 void* EmuFork(void* emu, int forktype);
+
+void PersonalityAddrLimit32Bit(void);
 // ----------------------------------------------------------------
 
 #ifndef _WIN32
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index 2454f929..02ada9ca 100644
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -206,8 +206,8 @@ x64emu_t* thread_get_emu()
 		if(box64_is32bits)
 			stack = mmap64(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0);
 		else
-			stack = internal_mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
-		if(stack!=MAP_FAILED)
+            stack = InternalMmap(NULL, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
+                if(stack!=MAP_FAILED)
 			setProtection((uintptr_t)stack, stacksize, PROT_READ|PROT_WRITE);
 		x64emu_t *emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stacksize, 1);
 		SetupX64Emu(emu, NULL);
@@ -523,8 +523,8 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
 		stacksize = attr_stacksize;
 		own = 0;
 	} else {
-		stack = internal_mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
-		if(stack!=MAP_FAILED)
+        stack = InternalMmap(NULL, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
+        if(stack!=MAP_FAILED)
 	        setProtection((uintptr_t)stack, stacksize, PROT_READ|PROT_WRITE);
 		own = 1;
 	}
@@ -552,8 +552,8 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
 void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet)
 {
 	int stacksize = (ssize)?ssize:(2*1024*1024);	//default stack size is 2Mo
-	void* stack = internal_mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
-	if(stack!=MAP_FAILED)
+    void* stack = InternalMmap(NULL, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
+    if(stack!=MAP_FAILED)
 		setProtection((uintptr_t)stack, stacksize, PROT_READ|PROT_WRITE);
 	emuthread_t *et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t));
 	x64emu_t *emuthread = NewX64Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1);
diff --git a/src/os/os_linux.c b/src/os/os_linux.c
index 46a0434b..e11a41a2 100644
--- a/src/os/os_linux.c
+++ b/src/os/os_linux.c
@@ -2,6 +2,7 @@
 #include <sched.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <sys/personality.h>
 
 #include "os.h"
 #include "signals.h"
@@ -62,3 +63,40 @@ void EmuX86Syscall(void* emu)
 {
     x86Syscall((x64emu_t*)emu);
 }
+
+void PersonalityAddrLimit32Bit(void)
+{
+    personality(ADDR_LIMIT_32BIT);
+}
+
+void* InternalMmap(void* addr, unsigned long length, int prot, int flags, int fd, ssize_t offset)
+{
+#if 1 // def STATICBUILD
+    void* ret = (void*)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
+#else
+    static int grab = 1;
+    typedef void* (*pFpLiiiL_t)(void*, unsigned long, int, int, int, size_t);
+    static pFpLiiiL_t libc_mmap64 = NULL;
+    if (grab) {
+        libc_mmap64 = dlsym(RTLD_NEXT, "mmap64");
+    }
+    void* ret = libc_mmap64(addr, length, prot, flags, fd, offset);
+#endif
+    return ret;
+}
+
+int InternalMunmap(void* addr, unsigned long length)
+{
+#if 1 // def STATICBUILD
+    int ret = syscall(__NR_munmap, addr, length);
+#else
+    static int grab = 1;
+    typedef int (*iFpL_t)(void*, unsigned long);
+    static iFpL_t libc_munmap = NULL;
+    if (grab) {
+        libc_munmap = dlsym(RTLD_NEXT, "munmap");
+    }
+    int ret = libc_munmap(addr, length);
+#endif
+    return ret;
+}
\ No newline at end of file
diff --git a/src/os/os_wine.c b/src/os/os_wine.c
new file mode 100644
index 00000000..e5bc47b5
--- /dev/null
+++ b/src/os/os_wine.c
@@ -0,0 +1,90 @@
+#include <windows.h>
+
+#include "os.h"
+
+int GetTID(void)
+{
+    return GetCurrentThreadId();
+}
+
+void PersonalityAddrLimit32Bit(void) { }
+
+ULONG_PTR default_zero_bits32 = 0x7fffffff;
+
+static uint32_t prot_unix_to_win32(uint32_t unx)
+{
+    if ((unx & (PROT_READ | PROT_WRITE | PROT_EXEC)) == (PROT_READ | PROT_WRITE | PROT_EXEC))
+        return PAGE_EXECUTE_READWRITE;
+    if ((unx & (PROT_READ | PROT_EXEC)) == (PROT_READ | PROT_EXEC))
+        return PAGE_EXECUTE_READ;
+    if ((unx & PROT_EXEC) == PROT_EXEC)
+        return PAGE_EXECUTE_READ;
+    if ((unx & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE))
+        return PAGE_READWRITE;
+    if ((unx & PROT_READ) == PROT_READ)
+        return PAGE_READONLY;
+    return 0;
+}
+
+int mprotect(void* addr, size_t len, int prot)
+{
+    ULONG old_prot;
+    if (VirtualProtect(&addr, len, prot_unix_to_win32(prot), &old_prot))
+        return 0;
+    return -1;
+}
+
+void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset)
+{
+    if (fd && fd != -1) {
+        return MAP_FAILED;
+    }
+    if (offset) {
+        return MAP_FAILED;
+    }
+    return VirtualAlloc(addr, length, MEM_COMMIT | MEM_RESERVE, prot_unix_to_win32(prot));
+}
+
+int munmap(void* addr, size_t length)
+{
+    if (VirtualFree(addr, length, MEM_RELEASE))
+        return 0;
+    return -1;
+}
+
+void* InternalMmap(void* addr, unsigned long length, int prot, int flags, int fd, ssize_t offset)
+{
+    return mmap(addr, length, prot, flags, fd, offset);
+}
+
+int InternalMunmap(void* addr, unsigned long length)
+{
+    return munmap(addr, length);
+}
+
+void* WinMalloc(size_t size)
+{
+    void* ret;
+    ret = HeapAlloc(GetProcessHeap(), 0, size);
+    return ret;
+}
+
+void* WinRealloc(void* ptr, size_t size)
+{
+    void* ret;
+    if (!ptr) return WinMalloc(size);
+    ret = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, size);
+    return ret;
+}
+
+void* WinCalloc(size_t nmemb, size_t size)
+{
+    void* ret;
+    ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nmemb * size);
+    return ret;
+}
+
+void WinFree(void* ptr)
+{
+    HeapFree(GetProcessHeap(), 0, ptr);
+}
\ No newline at end of file