Просмотр исходного кода

Implement Windows boundary check with hardware trap (#623)

Wenyong Huang 4 лет назад
Родитель
Сommit
fa5f4fe940

+ 5 - 3
build-scripts/config_common.cmake

@@ -52,9 +52,11 @@ endif ()
 
 if (CMAKE_SIZEOF_VOID_P EQUAL 8)
   if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" OR WAMR_BUILD_TARGET MATCHES "RISCV64.*")
-    # Add -fPIC flag if build as 64-bit
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-    set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+    if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
+      # Add -fPIC flag if build as 64-bit
+      set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+      set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+    endif ()
   else ()
     add_definitions (-m32)
     set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")

+ 53 - 1
core/iwasm/aot/aot_loader.c

@@ -1042,7 +1042,8 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end,
         read_uint32(buf, buf_end, data_sections[i].size);
 
         /* Allocate memory for data */
-        if (!(data_sections[i].data =
+        if (data_sections[i].size > 0
+            && !(data_sections[i].data =
                     os_mmap(NULL, data_sections[i].size, map_prot, map_flags))) {
             set_error_buf(error_buf, error_buf_size,
                           "allocate memory failed");
@@ -1179,6 +1180,27 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
     const uint8 *p = buf, *p_end = buf_end;
     uint32 i;
     uint64 size, text_offset;
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    RUNTIME_FUNCTION *rtl_func_table;
+    AOTUnwindInfo *unwind_info;
+    uint32 unwind_info_offset = module->code_size - sizeof(AOTUnwindInfo);
+    uint32 unwind_code_offset = unwind_info_offset - PLT_ITEM_SIZE;
+#endif
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    unwind_info= (AOTUnwindInfo *)((uint8*)module->code + module->code_size
+                                   - sizeof(AOTUnwindInfo));
+    unwind_info->Version = 1;
+    unwind_info->Flags = UNW_FLAG_EHANDLER;
+    *(uint32*)&unwind_info->UnwindCode[0] = unwind_code_offset;
+
+    size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count;
+    if (size > 0
+        && !(rtl_func_table = module->rtl_func_table =
+                loader_malloc(size, error_buf, error_buf_size))) {
+        return false;
+    }
+#endif
 
     size = sizeof(void*) * (uint64)module->func_count;
     if (size > 0
@@ -1205,9 +1227,31 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
 #if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP)
         /* bits[0] of thumb function address must be 1 */
         module->func_ptrs[i] = (void*)((uintptr_t)module->func_ptrs[i] | 1);
+#endif
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+        rtl_func_table[i].BeginAddress = (DWORD)text_offset;
+        if (i > 0) {
+            rtl_func_table[i].EndAddress = rtl_func_table[i - 1].BeginAddress;
+        }
+        rtl_func_table[i].UnwindInfoAddress = (DWORD)unwind_info_offset;
 #endif
     }
 
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    if (module->func_count > 0) {
+        rtl_func_table[module->func_count - 1].EndAddress =
+                    (DWORD)(module->code_size - get_plt_table_size());
+
+        if (!RtlAddFunctionTable(rtl_func_table, module->func_count,
+                                 (DWORD64)(uintptr_t)module->code)) {
+            set_error_buf(error_buf, error_buf_size,
+                          "add dynamic function table failed");
+            return false;
+        }
+        module->rtl_func_table_registered = true;
+    }
+#endif
+
     /* Set start function when function pointers are resolved */
     if (module->start_func_index != (uint32)-1) {
         if (module->start_func_index >= module->import_func_count)
@@ -2621,6 +2665,14 @@ aot_unload(AOTModule *module)
     }
 #endif
 
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    if (module->rtl_func_table) {
+        if (module->rtl_func_table_registered)
+            RtlDeleteFunctionTable(module->rtl_func_table);
+        wasm_runtime_free(module->rtl_func_table);
+    }
+#endif
+
     if (module->data_sections)
         destroy_object_data_sections(module->data_sections,
                                      module->data_section_count);

+ 103 - 1
core/iwasm/aot/aot_runtime.c

@@ -339,6 +339,11 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
 #ifndef OS_ENABLE_HW_BOUND_CHECK
                 wasm_runtime_free(memory_inst->memory_data.ptr);
 #else
+#ifdef BH_PLATFORM_WINDOWS
+                os_mem_decommit(memory_inst->memory_data.ptr,
+                                memory_inst->num_bytes_per_page
+                                * memory_inst->cur_page_count);
+#endif
                 os_munmap((uint8*)memory_inst->memory_data.ptr,
                           8 * (uint64)BH_GB);
 #endif
@@ -499,8 +504,19 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
         return NULL;
     }
 
+#ifdef BH_PLATFORM_WINDOWS
+    if (!os_mem_commit(p, total_size, MMAP_PROT_READ | MMAP_PROT_WRITE)) {
+        set_error_buf(error_buf, error_buf_size, "commit memory failed");
+        os_munmap(mapped_mem, map_size);
+        return NULL;
+    }
+#endif
+
     if (os_mprotect(p, total_size, MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) {
         set_error_buf(error_buf, error_buf_size, "mprotec memory failed");
+#ifdef BH_PLATFORM_WINDOWS
+        os_mem_decommit(p, total_size);
+#endif
         os_munmap(mapped_mem, map_size);
         return NULL;
     }
@@ -583,6 +599,10 @@ fail1:
     if (memory_inst->memory_data.ptr)
         wasm_runtime_free(memory_inst->memory_data.ptr);
 #else
+#ifdef BH_PLATFORM_WINDOWS
+    if (memory_inst->memory_data.ptr)
+        os_mem_decommit(p, total_size);
+#endif
     os_munmap(mapped_mem, map_size);
 #endif
     memory_inst->memory_data.ptr = NULL;
@@ -1129,8 +1149,16 @@ aot_lookup_function(const AOTModuleInstance *module_inst,
 
 static os_thread_local_attribute WASMExecEnv *aot_exec_env = NULL;
 
+#ifndef BH_PLATFORM_WINDOWS
 static void
 aot_signal_handler(void *sig_addr)
+#else
+EXCEPTION_DISPOSITION
+aot_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
+                      ULONG64 EstablisherFrame,
+                      PCONTEXT ContextRecord,
+                      PDISPATCHER_CONTEXT DispatcherContext)
+#endif
 {
     AOTModuleInstance *module_inst;
     AOTMemoryInstance *memory_inst;
@@ -1140,11 +1168,18 @@ aot_signal_handler(void *sig_addr)
     uint8 *stack_min_addr;
     uint32 page_size;
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+#ifdef BH_PLATFORM_WINDOWS
+    uint8 *sig_addr = (uint8*)ExceptionRecord->ExceptionInformation[1];
+#endif
 
     /* Check whether current thread is running aot function */
     if (aot_exec_env
         && aot_exec_env->handle == os_self_thread()
-        && (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)) {
+        && (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)
+#ifdef BH_PLATFORM_WINDOWS
+        && ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
+#endif
+        ) {
         /* Get mapped mem info of current instance */
         module_inst = (AOTModuleInstance *)aot_exec_env->module_inst;
         /* Get the default memory instance */
@@ -1176,18 +1211,60 @@ aot_signal_handler(void *sig_addr)
             os_longjmp(jmpbuf_node->jmpbuf, 1);
         }
     }
+
+#ifdef BH_PLATFORM_WINDOWS
+    ContextRecord->Rip += 3;
+    return EXCEPTION_CONTINUE_SEARCH;
+    (void)EstablisherFrame;
+    (void)ContextRecord;
+    (void)DispatcherContext;
+#endif
 }
 
+#ifdef BH_PLATFORM_WINDOWS
+static LONG
+stack_overflow_handler(EXCEPTION_POINTERS *exce_info)
+{
+    AOTModuleInstance* module_inst;
+    WASMJmpBuf* jmpbuf_node;
+
+    /* Check whether it is stack overflow exception and
+       current thread is running aot function */
+    if (exce_info->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW
+        && aot_exec_env
+        && aot_exec_env->handle == os_self_thread()
+        && (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)) {
+        /* Set stack overflow exception and let the aot func continue
+           to run, when the aot func returns, the caller will check
+           whether the exception is thrown and return to runtime, and
+           the damaged stack will be recovered by _resetstkoflw(). */
+        module_inst = (AOTModuleInstance*)aot_exec_env->module_inst;
+        aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
+        return EXCEPTION_CONTINUE_EXECUTION;
+    }
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
 bool
 aot_signal_init()
 {
+#ifndef BH_PLATFORM_WINDOWS
     return os_signal_init(aot_signal_handler) == 0 ? true : false;
+#else
+    return AddVectoredExceptionHandler(1, stack_overflow_handler)
+           ? true : false;
+#endif
 }
 
 void
 aot_signal_destroy()
 {
+#ifndef BH_PLATFORM_WINDOWS
     os_signal_destroy();
+#else
+    RemoveVectoredExceptionHandler(stack_overflow_handler);
+#endif
 }
 
 static bool
@@ -1201,6 +1278,10 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
     WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
     uint32 page_size = os_getpagesize();
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+#if BH_PLATFORM_WINDOWS
+    const char *exce;
+    int result;
+#endif
     bool ret;
 
     /* Check native stack overflow firstly to ensure we have enough
@@ -1226,6 +1307,15 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
         ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
                                          signature, attachment,
                                          argv, argc, argv_ret);
+#ifdef BH_PLATFORM_WINDOWS
+        if ((exce = aot_get_exception(module_inst))
+            && strstr(exce, "native stack overflow")) {
+            /* After a stack overflow, the stack was left
+               in a damaged state, let the CRT repair it */
+            result = _resetstkoflw();
+            bh_assert(result != 0);
+        }
+#endif
     }
     else {
         /* Exception has been set in signal handler before calling longjmp */
@@ -1992,9 +2082,21 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
         return false;
     }
 
+#ifdef BH_PLATFORM_WINDOWS
+    if (!os_mem_commit(memory_inst->memory_data_end.ptr,
+                       num_bytes_per_page * inc_page_count,
+                       MMAP_PROT_READ | MMAP_PROT_WRITE)) {
+        return false;
+    }
+#endif
+
     if (os_mprotect(memory_inst->memory_data_end.ptr,
                     num_bytes_per_page * inc_page_count,
                     MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) {
+#ifdef BH_PLATFORM_WINDOWS
+        os_mem_decommit(memory_inst->memory_data_end.ptr,
+                        num_bytes_per_page * inc_page_count);
+#endif
         return false;
     }
 

+ 38 - 0
core/iwasm/aot/aot_runtime.h

@@ -88,6 +88,28 @@ typedef struct AOTFunctionInstance {
     } u;
 } AOTFunctionInstance;
 
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+typedef struct AOTUnwindInfo {
+    uint8 Version       : 3;
+    uint8 Flags         : 5;
+    uint8 SizeOfProlog;
+    uint8 CountOfCodes;
+    uint8 FrameRegister : 4;
+    uint8 FrameOffset   : 4;
+    struct {
+        struct {
+            uint8 CodeOffset;
+            uint8 UnwindOp : 4;
+            uint8 OpInfo   : 4;
+        };
+        uint16 FrameOffset;
+    } UnwindCode[1];
+} AOTUnwindInfo;
+
+/* size of mov instruction and jmp instruction */
+#define PLT_ITEM_SIZE 12
+#endif
+
 typedef struct AOTModule {
     uint32 module_type;
 
@@ -173,6 +195,14 @@ typedef struct AOTModule {
     uint32 float_plt_count;
 #endif
 
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    /* dynamic function table to be added by RtlAddFunctionTable(),
+       used to unwind the call stack and register exception handler
+       for AOT functions */
+    RUNTIME_FUNCTION *rtl_func_table;
+    bool rtl_func_table_registered;
+#endif
+
     /* data sections in AOT object file, including .data, .rodata
      * and .rodata.cstN. NULL for JIT mode. */
     AOTObjectDataSection *data_sections;
@@ -629,6 +659,14 @@ aot_signal_init();
 
 void
 aot_signal_destroy();
+
+#ifdef BH_PLATFORM_WINDOWS
+EXCEPTION_DISPOSITION
+aot_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
+                      ULONG64 EstablisherFrame,
+                      PCONTEXT ContextRecord,
+                      PDISPATCHER_CONTEXT DispatcherContext);
+#endif
 #endif
 
 void

+ 21 - 2
core/iwasm/aot/arch/aot_reloc_x86_64.c

@@ -61,15 +61,22 @@ get_plt_item_size()
 uint32
 get_plt_table_size()
 {
-    return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+    uint32 size = get_plt_item_size()
+                  * (sizeof(target_sym_map) / sizeof(SymbolMap));
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    size += get_plt_item_size() + sizeof(AOTUnwindInfo);
+#endif
+    return size;
 }
 
 void
 init_plt_table(uint8 *plt)
 {
     uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+    uint8 *p;
+
     for (i = 0; i < num; i++) {
-        uint8 *p = plt;
+        p = plt;
         /* mov symbol_addr, rax */
         *p++ = 0x48;
         *p++ = 0xB8;
@@ -80,6 +87,18 @@ init_plt_table(uint8 *plt)
         *p++ = 0xE0;
         plt += get_plt_item_size();
     }
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    p = plt;
+    /* mov exception_handler, rax */
+    *p++ = 0x48;
+	*p++ = 0xB8;
+    *(uint64*)p = (uint64)(uintptr_t)aot_exception_handler;
+    p += sizeof(uint64);
+    /* jmp rax */
+	*p++ = 0xFF;
+	*p++ = 0xE0;
+#endif
 }
 
 static bool

+ 4 - 2
core/iwasm/common/wasm_runtime_common.c

@@ -2707,7 +2707,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
 #if WASM_ENABLE_REF_TYPES != 0
             case VALUE_TYPE_FUNCREF:
             {
-                if (strncasecmp(argv[i], "null", 4) == 0) {
+                if (strncmp(argv[i], "null", 4) == 0
+                    || strncmp(argv[i], "NULL", 4) == 0) {
                     argv1[p++] = NULL_REF;
                 }
                 else {
@@ -2717,7 +2718,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
             }
             case VALUE_TYPE_EXTERNREF:
             {
-                if (strncasecmp(argv[i], "null", 4) == 0) {
+                if (strncmp(argv[i], "null", 4) == 0
+                    || strncmp(argv[i], "NULL", 4) == 0) {
                     argv1[p++] = NULL_REF;
                 }
                 else {

+ 8 - 0
core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c

@@ -657,7 +657,11 @@ strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src)
     if (!validate_native_addr(dst, len))
         return 0;
 
+#ifndef BH_PLATFORM_WINDOWS
     strncpy(dst, src, len);
+#else
+    strncpy_s(dst, len, src, len);
+#endif
     return addr_native_to_app(dst);
 }
 
@@ -671,7 +675,11 @@ strncpy_wrapper(wasm_exec_env_t exec_env,
     if (!validate_native_addr(dst, size))
         return 0;
 
+#ifndef BH_PLATFORM_WINDOWS
     strncpy(dst, src, size);
+#else
+    strncpy_s(dst, size, src, size);
+#endif
     return addr_native_to_app(dst);
 }
 

+ 13 - 0
core/shared/platform/windows/platform_init.c

@@ -43,3 +43,16 @@ os_vprintf(const char *format, va_list ap)
 #endif
 }
 
+unsigned
+os_getpagesize()
+{
+    SYSTEM_INFO sys_info;
+    GetNativeSystemInfo(&sys_info);
+    return (unsigned)sys_info.dwPageSize;
+}
+
+void
+os_dcache_flush(void)
+{
+}
+

+ 29 - 7
core/shared/platform/windows/platform_internal.h

@@ -23,6 +23,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdint.h>
+#include <malloc.h>
 #include <Windows.h>
 
 #ifdef __cplusplus
@@ -49,13 +50,34 @@ typedef struct {
     unsigned int waiting_count;
 } korp_cond;
 
-static inline size_t
-getpagesize()
-{
-    SYSTEM_INFO S;
-    GetNativeSystemInfo(&S);
-    return S.dwPageSize;
-}
+unsigned os_getpagesize();
+void *os_mem_commit(void *ptr, size_t size, int flags);
+void os_mem_decommit(void *ptr, size_t size);
+
+#define os_thread_local_attribute __declspec(thread)
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) \
+    || defined(BUILD_TARGET_AMD_64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+
+bool os_thread_init_stack_guard_pages();
+
+void os_thread_destroy_stack_guard_pages();
+
+#define os_signal_unmask() (void)0
+#define os_sigreturn() (void)0
+
+#endif /* end of BUILD_TARGET_X86_64/AMD_64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
 #ifdef __cplusplus
 }

+ 0 - 0
core/shared/platform/windows/posix_malloc.c → core/shared/platform/windows/win_malloc.c


+ 94 - 42
core/shared/platform/windows/win_memmap.c

@@ -5,81 +5,133 @@
 
 #include "platform_api_vmcore.h"
 
-void * os_mmap(void *hint, size_t size, int prot, int flags)
+#define TRACE_MEMMAP 0
+
+static DWORD
+access_to_win32_flags(int prot)
 {
-    DWORD AllocType = MEM_RESERVE | MEM_COMMIT;
-    DWORD flProtect = PAGE_NOACCESS;
+    DWORD protect = PAGE_NOACCESS;
+
+    if (prot & MMAP_PROT_EXEC) {
+        if (prot & MMAP_PROT_WRITE)
+            protect = PAGE_EXECUTE_READWRITE;
+        else
+            protect = PAGE_EXECUTE_READ;
+    }
+    else if (prot & MMAP_PROT_WRITE) {
+        protect = PAGE_READWRITE;
+    }
+    else if (prot & MMAP_PROT_READ) {
+        protect = PAGE_READONLY;
+    }
+
+    return protect;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+    DWORD alloc_type = MEM_RESERVE;
+    DWORD protect;
     size_t request_size, page_size;
     void *addr;
 
-    page_size = getpagesize();
+    page_size = os_getpagesize();
     request_size = (size + page_size - 1) & ~(page_size - 1);
 
     if (request_size < size)
         /* integer overflow */
         return NULL;
 
-    if (request_size == 0)
-        request_size = page_size;
-
-    if (prot & MMAP_PROT_EXEC) {
-        if (prot & MMAP_PROT_WRITE)
-            flProtect = PAGE_EXECUTE_READWRITE;
-        else
-            flProtect = PAGE_EXECUTE_READ;
+    protect = access_to_win32_flags(prot);
+    if (protect != PAGE_NOACCESS) {
+        alloc_type |= MEM_COMMIT;
     }
-    else if (prot & MMAP_PROT_WRITE)
-        flProtect = PAGE_READWRITE;
-    else if (prot & MMAP_PROT_READ)
-        flProtect = PAGE_READONLY;
 
+    addr = VirtualAlloc((LPVOID)hint, request_size, alloc_type, protect);
 
-    addr = VirtualAlloc((LPVOID)hint, request_size, AllocType,
-                        flProtect);
+#if TRACE_MEMMAP != 0
+    printf("Map memory, request_size: %zu, alloc_type: 0x%x, "
+           "protect: 0x%x, ret: %p\n",
+           request_size, alloc_type, protect, addr);
+#endif
     return addr;
 }
 
 void
 os_munmap(void *addr, size_t size)
 {
-    size_t page_size = getpagesize();
+    size_t page_size = os_getpagesize();
     size_t request_size = (size + page_size - 1) & ~(page_size - 1);
 
     if (addr) {
-        if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
-            if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
-                os_printf("os_munmap error addr:%p, size:0x%lx, errno:%d\n",
-                          addr, request_size, errno);
-            }
+        if (!VirtualFree(addr, request_size, MEM_DECOMMIT)) {
+            printf("warning: os_munmap decommit pages failed, "
+                   "addr: %p, request_size: %zu, errno: %d\n",
+                   addr, request_size, errno);
+            return;
+        }
+
+        if (!VirtualFree(addr, 0, MEM_RELEASE)) {
+            printf("warning: os_munmap release pages failed, "
+                   "addr: %p, size: %zu, errno:%d\n",
+                   addr, request_size, errno);
         }
     }
+#if TRACE_MEMMAP != 0
+    printf("Unmap memory, addr: %p, request_size: %zu\n",
+           addr, request_size);
+#endif
 }
 
-int
-os_mprotect(void *addr, size_t size, int prot)
+void *
+os_mem_commit(void *addr, size_t size, int flags)
 {
-    DWORD AllocType = MEM_RESERVE | MEM_COMMIT;
-    DWORD flProtect = PAGE_NOACCESS;
+    DWORD protect = access_to_win32_flags(flags);
+    size_t page_size = os_getpagesize();
+    size_t request_size = (size + page_size - 1) & ~(page_size - 1);
 
     if (!addr)
-        return 0;
-
-    if (prot & MMAP_PROT_EXEC) {
-        if (prot & MMAP_PROT_WRITE)
-            flProtect = PAGE_EXECUTE_READWRITE;
-        else
-            flProtect = PAGE_EXECUTE_READ;
-    }
-    else if (prot & MMAP_PROT_WRITE)
-        flProtect = PAGE_READWRITE;
-    else if (prot & MMAP_PROT_READ)
-        flProtect = PAGE_READONLY;
+        return NULL;
 
-    return VirtualProtect((LPVOID)addr, size, flProtect, NULL);
+#if TRACE_MEMMAP != 0
+    printf("Commit memory, addr: %p, request_size: %zu, protect: 0x%x\n",
+           addr, request_size, protect);
+#endif
+    return VirtualAlloc((LPVOID)addr, request_size, MEM_COMMIT, protect);
 }
 
 void
-os_dcache_flush(void)
+os_mem_decommit(void *addr, size_t size)
 {
+    size_t page_size = os_getpagesize();
+    size_t request_size = (size + page_size - 1) & ~(page_size - 1);
 
+    if (!addr)
+        return;
+
+#if TRACE_MEMMAP != 0
+    printf("Decommit memory, addr: %p, request_size: %zu\n",
+           addr, request_size);
+#endif
+    VirtualFree((LPVOID)addr, request_size, MEM_DECOMMIT);
 }
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+    DWORD protect;
+    size_t page_size = os_getpagesize();
+    size_t request_size = (size + page_size - 1) & ~(page_size - 1);
+
+    if (!addr)
+        return 0;
+
+    protect = access_to_win32_flags(prot);
+#if TRACE_MEMMAP != 0
+    printf("Mprotect memory, addr: %p, request_size: %zu, protect: 0x%x\n",
+           addr, request_size, protect);
+#endif
+    return VirtualProtect((LPVOID)addr, request_size, protect, NULL);
+}
+

+ 26 - 1
core/shared/platform/windows/win_thread.c

@@ -149,7 +149,32 @@ void os_thread_exit(void *retval)
 {
 }
 
+static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
+
 uint8 *os_thread_get_stack_boundary()
 {
-    return NULL;
+    ULONG_PTR low_limit = 0, high_limit = 0;
+    uint32 page_size;
+
+    if (thread_stack_boundary)
+        return thread_stack_boundary;
+
+    page_size = os_getpagesize();
+    GetCurrentThreadStackLimits(&low_limit, &high_limit);
+    /* 4 pages are set unaccessible by system, we reserved
+       one more page at least for safety */
+    thread_stack_boundary = (uint8*)(uintptr_t)low_limit + page_size * 5;
+    return thread_stack_boundary;
 }
+
+bool
+os_thread_init_stack_guard_pages()
+{
+    return true;
+}
+
+void
+os_thread_destroy_stack_guard_pages()
+{
+}
+

+ 5 - 3
wamr-compiler/CMakeLists.txt

@@ -76,9 +76,11 @@ message ("-- Build as target ${WAMR_BUILD_TARGET}")
 
 if (CMAKE_SIZEOF_VOID_P EQUAL 8)
   if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
-    # Add -fPIC flag if build as 64-bit
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-    set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+    if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
+      # Add -fPIC flag if build as 64-bit
+      set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+      set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+    endif ()
   else ()
     add_definitions (-m32)
     set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")