From fa5f4fe94092753dd24cbe02031de40ed0c623bc Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 27 Apr 2021 17:18:27 +0800 Subject: [PATCH] Implement Windows boundary check with hardware trap (#623) --- build-scripts/config_common.cmake | 8 +- core/iwasm/aot/aot_loader.c | 54 ++++++- core/iwasm/aot/aot_runtime.c | 104 ++++++++++++- core/iwasm/aot/aot_runtime.h | 38 +++++ core/iwasm/aot/arch/aot_reloc_x86_64.c | 23 ++- core/iwasm/common/wasm_runtime_common.c | 6 +- .../libc-builtin/libc_builtin_wrapper.c | 8 + core/shared/platform/windows/platform_init.c | 13 ++ .../platform/windows/platform_internal.h | 36 ++++- .../windows/{posix_malloc.c => win_malloc.c} | 0 core/shared/platform/windows/win_memmap.c | 138 ++++++++++++------ core/shared/platform/windows/win_thread.c | 27 +++- wamr-compiler/CMakeLists.txt | 8 +- 13 files changed, 400 insertions(+), 63 deletions(-) rename core/shared/platform/windows/{posix_malloc.c => win_malloc.c} (100%) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 81647163..f6b8e51c 100644 --- a/build-scripts/config_common.cmake +++ b/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") diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index eba9a9df..eed71b68 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/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); diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index c2338897..970e4e92 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/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; } diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index f93e8f0c..a8122435 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/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 diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index af090429..6c61a60b 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/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 diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 5c633360..c9682060 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/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 { diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index b2701bcc..382c7a6d 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/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); } diff --git a/core/shared/platform/windows/platform_init.c b/core/shared/platform/windows/platform_init.c index 17aeb8ba..a723214b 100644 --- a/core/shared/platform/windows/platform_init.c +++ b/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) +{ +} + diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 877336be..34da6fa3 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #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 + +#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 } diff --git a/core/shared/platform/windows/posix_malloc.c b/core/shared/platform/windows/win_malloc.c similarity index 100% rename from core/shared/platform/windows/posix_malloc.c rename to core/shared/platform/windows/win_malloc.c diff --git a/core/shared/platform/windows/win_memmap.c b/core/shared/platform/windows/win_memmap.c index 1e7d7fd8..4d45897d 100644 --- a/core/shared/platform/windows/win_memmap.c +++ b/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 +} + +void * +os_mem_commit(void *addr, size_t size, int flags) +{ + 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 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_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 AllocType = MEM_RESERVE | MEM_COMMIT; - DWORD flProtect = PAGE_NOACCESS; + DWORD protect; + 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 VirtualProtect((LPVOID)addr, size, flProtect, NULL); + 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); } -void -os_dcache_flush(void) -{ - -} diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index ed2b598e..0ce313f4 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/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() +{ +} + diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 440970cf..c1c8c97f 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/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")