diff --git a/core/iwasm/lib/native-interface/wasm_export.h b/core/iwasm/lib/native-interface/wasm_export.h new file mode 100644 index 00000000..ed9d570f --- /dev/null +++ b/core/iwasm/lib/native-interface/wasm_export.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WASM_EXPORT_H +#define _WASM_EXPORT_H + +#include +#include + +/** + * API exported to WASM application + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get current WASM module instance of the current native thread + * + * @return current WASM module instance of the current native thread, 0 + * if not found + * Note: the return type is uint64_t but not pointer type, because that + * the we only supports WASM-32, in which the pointer type is + * compiled to WASM i32 type, but the pointer type in native can be + * 32-bit and 64-bit. And if the native pointer is 64-bit, data loss + * occurs after converting it to WASM i32 type. + */ +uint64_t +wasm_runtime_get_current_module_inst(); + +/** + * Validate the app address, check whether it belongs to WASM module + * instance's address space, or in its heap space or memory space. + * + * @param module_inst the WASM module instance + * @param app_offset the app address to validate, which is a relative address + * @param size the size bytes of the app address + * + * @return true if success, false otherwise. + */ +bool +wasm_runtime_validate_app_addr(uint64_t module_inst, + int32_t app_offset, uint32_t size); + +/** + * Validate the native address, check whether it belongs to WASM module + * instance's address space, or in its heap space or memory space. + * + * @param module_inst the WASM module instance + * @param native_ptr the native address to validate, which is an absolute + * address + * @param size the size bytes of the app address + * + * @return true if success, false otherwise. + */ +bool +wasm_runtime_validate_native_addr(uint64_t module_inst, + uint64_t native_ptr, uint32_t size); + +/** + * Convert app address(relative address) to native address(absolute address) + * + * @param module_inst the WASM module instance + * @param app_offset the app adress + * + * @return the native address converted + */ +uint64_t +wasm_runtime_addr_app_to_native(uint64_t module_inst, + int32_t app_offset); + +/** + * Convert native address(absolute address) to app address(relative address) + * + * @param module_inst the WASM module instance + * @param native_ptr the native address + * + * @return the app address converted + */ +int32_t +wasm_runtime_addr_native_to_app(uint64_t module_inst, + uint64_t native_ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_EXPORT_H */ diff --git a/core/iwasm/lib/native/base/base_lib_export.c b/core/iwasm/lib/native/base/base_lib_export.c index 4392a7ba..353871b6 100644 --- a/core/iwasm/lib/native/base/base_lib_export.c +++ b/core/iwasm/lib/native/base/base_lib_export.c @@ -18,11 +18,116 @@ #include #include #include "lib_export.h" +#include "bh_platform.h" +#include "wasm_export.h" #ifdef WASM_ENABLE_BASE_LIB #include "base_lib_export.h" #endif +static uint64 +wasm_runtime_get_current_module_inst_wrapper() +{ + return (uint64)(uintptr_t) + wasm_runtime_get_current_module_inst(); +} + +static bool +wasm_runtime_validate_app_addr_wrapper(uint32 inst_part0, uint32 inst_part1, + int32 app_offset, uint32 size) +{ + bool ret; + wasm_module_inst_t module_inst = + wasm_runtime_get_current_module_inst(); + union { uint64 u64; uint32 parts[2]; } inst; + + inst.parts[0] = inst_part0; + inst.parts[1] = inst_part1; + + if (inst.u64 != (uint64)(uintptr_t)module_inst) { + printf("Invalid module instance\n"); + return false; + } + + ret = wasm_runtime_validate_app_addr(module_inst, app_offset, size); + if (!ret) + wasm_runtime_clear_exception(module_inst); + return ret; +} + +static bool +wasm_runtime_validate_native_addr_wrapper(uint32 inst_part0, uint32 inst_part1, + uint32 native_ptr_part0, + uint32 native_ptr_part1, + uint32 size) +{ + bool ret; + wasm_module_inst_t module_inst = + wasm_runtime_get_current_module_inst(); + union { uint64 u64; uint32 parts[2]; } inst; + union { uint64 u64; uint32 parts[2]; } native_ptr; + + inst.parts[0] = inst_part0; + inst.parts[1] = inst_part1; + + if (inst.u64 != (uint64)(uintptr_t)module_inst) { + printf("Invalid module instance\n"); + return false; + } + + native_ptr.parts[0] = native_ptr_part0; + native_ptr.parts[1] = native_ptr_part1; + ret = wasm_runtime_validate_native_addr(module_inst, + (void*)(uintptr_t)native_ptr.u64, + size); + if (!ret) + wasm_runtime_clear_exception(module_inst); + return ret; +} + +static uint64 +wasm_runtime_addr_app_to_native_wrapper(uint32 inst_part0, uint32 inst_part1, + int32 app_offset) +{ + wasm_module_inst_t module_inst = + wasm_runtime_get_current_module_inst(); + union { uint64 u64; uint32 parts[2]; } inst; + + inst.parts[0] = inst_part0; + inst.parts[1] = inst_part1; + + if (inst.u64 != (uint64)(uintptr_t)module_inst) { + printf("Invalid module instance\n"); + return 0; + } + return (uint64)(uintptr_t) + wasm_runtime_addr_app_to_native(module_inst, app_offset); +} + +static int32 +wasm_runtime_addr_native_to_app_wrapper(uint32 inst_part0, uint32 inst_part1, + uint32 native_ptr_part0, + uint32 native_ptr_part1) +{ + wasm_module_inst_t module_inst = + wasm_runtime_get_current_module_inst(); + union { uint64 u64; uint32 parts[2]; } inst; + union { uint64 u64; uint32 parts[2]; } native_ptr; + + inst.parts[0] = inst_part0; + inst.parts[1] = inst_part1; + + if (inst.u64 != (uint64)(uintptr_t)module_inst) { + printf("Invalid module instance\n"); + return 0; + } + + native_ptr.parts[0] = native_ptr_part0; + native_ptr.parts[1] = native_ptr_part1; + return wasm_runtime_addr_native_to_app(module_inst, + (void*)(uintptr_t)native_ptr.u64); +} + static NativeSymbol extended_native_symbol_defs[] = { /* TODO: use macro EXPORT_WASM_API() or EXPORT_WASM_API2() to add functions to register. */ @@ -38,6 +143,11 @@ static NativeSymbol extended_native_symbol_defs[] = { EXPORT_WASM_API(wasm_timer_restart), EXPORT_WASM_API(wasm_get_sys_tick_ms), #endif + EXPORT_WASM_API2(wasm_runtime_get_current_module_inst), + EXPORT_WASM_API2(wasm_runtime_validate_app_addr), + EXPORT_WASM_API2(wasm_runtime_validate_native_addr), + EXPORT_WASM_API2(wasm_runtime_addr_app_to_native), + EXPORT_WASM_API2(wasm_runtime_addr_native_to_app), }; int get_base_lib_export_apis(NativeSymbol **p_base_lib_apis) diff --git a/core/iwasm/products/alios-things/src/main.c b/core/iwasm/products/alios-things/src/main.c index 395c9b85..33624785 100644 --- a/core/iwasm/products/alios-things/src/main.c +++ b/core/iwasm/products/alios-things/src/main.c @@ -29,6 +29,20 @@ static int app_argc; static char **app_argv; +/** + * Find the unique main function from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the main function is called, false otherwise. + */ +bool +wasm_application_execute_main(wasm_module_inst_t module_inst, + int argc, char *argv[]); + static void* app_instance_main(wasm_module_inst_t module_inst) { diff --git a/core/iwasm/products/linux/main.c b/core/iwasm/products/linux/main.c index e415de7d..86c6e5e7 100644 --- a/core/iwasm/products/linux/main.c +++ b/core/iwasm/products/linux/main.c @@ -46,6 +46,35 @@ static int print_help() return 1; } +/** + * Find the unique main function from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the main function is called, false otherwise. + */ +bool +wasm_application_execute_main(wasm_module_inst_t module_inst, + int argc, char *argv[]); + +/** + * Find the specified function in argv[0] from WASM module of current instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param name the name of the function to execute + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the specified function is called, false otherwise. + */ +bool +wasm_application_execute_func(wasm_module_inst_t module_inst, + const char *name, int argc, char *argv[]); + static void* app_instance_main(wasm_module_inst_t module_inst) { diff --git a/core/iwasm/products/vxworks/main.c b/core/iwasm/products/vxworks/main.c index dc263042..a1a503f3 100644 --- a/core/iwasm/products/vxworks/main.c +++ b/core/iwasm/products/vxworks/main.c @@ -46,6 +46,35 @@ static int print_help() return 1; } +/** + * Find the unique main function from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the main function is called, false otherwise. + */ +bool +wasm_application_execute_main(wasm_module_inst_t module_inst, + int argc, char *argv[]); + +/** + * Find the specified function in argv[0] from WASM module of current instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param name the name of the function to execute + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the specified function is called, false otherwise. + */ +bool +wasm_application_execute_func(wasm_module_inst_t module_inst, + const char *name, int argc, char *argv[]); + static void* app_instance_main(wasm_module_inst_t module_inst) { diff --git a/core/iwasm/products/zephyr/simple/src/main.c b/core/iwasm/products/zephyr/simple/src/main.c index a6a9260a..fee58f9d 100644 --- a/core/iwasm/products/zephyr/simple/src/main.c +++ b/core/iwasm/products/zephyr/simple/src/main.c @@ -29,6 +29,20 @@ static int app_argc; static char **app_argv; +/** + * Find the unique main function from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the main function is called, false otherwise. + */ +bool +wasm_application_execute_main(wasm_module_inst_t module_inst, + int argc, char *argv[]); + static void* app_instance_main(wasm_module_inst_t module_inst) { diff --git a/core/iwasm/runtime/include/wasm_export.h b/core/iwasm/runtime/include/wasm_export.h index 0492fcb4..61de0967 100644 --- a/core/iwasm/runtime/include/wasm_export.h +++ b/core/iwasm/runtime/include/wasm_export.h @@ -152,6 +152,13 @@ wasm_runtime_instantiate(const wasm_module_t module, void wasm_runtime_deinstantiate(wasm_module_inst_t module_inst); +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 +bool +wasm_runtime_set_ext_memory(wasm_module_inst_t module_inst, + uint8_t *ext_mem_data, uint32_t ext_mem_size, + char *error_buf, uint32_t error_buf_size); +#endif + /** * Load WASM module instance from AOT file. * @@ -384,36 +391,6 @@ int32_t wasm_runtime_addr_native_to_app(wasm_module_inst_t module_inst, void *native_ptr); -/** - * Find the unique main function from a WASM module instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the main function is called, false otherwise. - */ -bool -wasm_application_execute_main(wasm_module_inst_t module_inst, - int argc, char *argv[]); - -/** - * Find the specified function in argv[0] from WASM module of current instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param name the name of the function to execute - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the specified function is called, false otherwise. - */ -bool -wasm_application_execute_func(wasm_module_inst_t module_inst, - const char *name, int argc, char *argv[]); - - #ifdef __cplusplus } #endif diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c index 490306db..f0b0beba 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c @@ -74,6 +74,24 @@ GET_F64_FROM_ADDR (uint32 *addr) } #endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 +#define CHECK_EXT_MEMORY_SPACE() \ + else if (module->ext_mem_data \ + && module->ext_mem_base_offset <= offset1 \ + && offset1 < module->ext_mem_base_offset \ + + module->ext_mem_size) { \ + maddr = module->ext_mem_data \ + + (offset1 - module->ext_mem_base_offset); \ + if (maddr < module->ext_mem_data) \ + goto out_of_bounds; \ + maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \ + if (maddr1 > module->ext_mem_data_end) \ + goto out_of_bounds; \ + } +#else +#define CHECK_EXT_MEMORY_SPACE() +#endif + #define CHECK_MEMORY_OVERFLOW() do { \ uint32 offset1 = offset + addr; \ uint8 *maddr1; \ @@ -89,7 +107,8 @@ GET_F64_FROM_ADDR (uint32 *addr) if (maddr1 > memory->end_addr) \ goto out_of_bounds; \ } \ - else { \ + else if (offset1 < memory->heap_base_offset \ + + (memory->heap_data_end - memory->heap_data)) { \ maddr = memory->heap_data + offset1 - memory->heap_base_offset; \ if (maddr < memory->heap_data) \ goto out_of_bounds; \ @@ -97,6 +116,9 @@ GET_F64_FROM_ADDR (uint32 *addr) if (maddr1 > memory->heap_data_end) \ goto out_of_bounds; \ } \ + CHECK_EXT_MEMORY_SPACE() \ + else \ + goto out_of_bounds; \ } while (0) static inline uint32 diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c index a7a9a874..35efd7a9 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c @@ -992,6 +992,37 @@ wasm_runtime_deinstantiate(WASMModuleInstance *module_inst) wasm_free(module_inst); } +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 +bool +wasm_runtime_set_ext_memory(WASMModuleInstance *module_inst, + uint8 *ext_mem_data, uint32 ext_mem_size, + char *error_buf, uint32 error_buf_size) +{ + if (module_inst->ext_mem_data) { + set_error_buf(error_buf, error_buf_size, + "Set external memory failed: " + "an external memory has been set."); + return false; + } + + if (!ext_mem_data + || ext_mem_size > 1 * BH_GB + || ext_mem_data + ext_mem_size < ext_mem_data) { + set_error_buf(error_buf, error_buf_size, + "Set external memory failed: " + "invalid input."); + return false; + } + + module_inst->ext_mem_data = ext_mem_data; + module_inst->ext_mem_data_end = ext_mem_data + ext_mem_size; + module_inst->ext_mem_size = ext_mem_size; + module_inst->ext_mem_base_offset = DEFAULT_EXT_MEM_BASE_OFFSET; + + return true; +} +#endif + bool wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count) { @@ -1166,24 +1197,40 @@ wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst, uint8 *addr; /* integer overflow check */ - if(app_offset < 0 || - app_offset + size < app_offset) { + if(app_offset + size < app_offset) { goto fail; } memory = module_inst->default_memory; - if (app_offset < memory->heap_base_offset) { + if (0 <= app_offset + && app_offset < memory->heap_base_offset) { addr = memory->memory_data + app_offset; if (!(memory->base_addr <= addr && addr + size <= memory->end_addr)) goto fail; return true; } - else { + else if (memory->heap_base_offset < app_offset + && app_offset < memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data)) { addr = memory->heap_data + (app_offset - memory->heap_base_offset); if (!(memory->heap_data <= addr && addr + size <= memory->heap_data_end)) goto fail; return true; } +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + else if (module_inst->ext_mem_data + && module_inst->ext_mem_base_offset <= app_offset + && app_offset < module_inst->ext_mem_base_offset + + module_inst->ext_mem_size) { + addr = module_inst->ext_mem_data + + (app_offset - module_inst->ext_mem_base_offset); + if (!(module_inst->ext_mem_data <= addr + && addr + size <= module_inst->ext_mem_data_end)) + goto fail; + + return true; + } +#endif fail: wasm_runtime_set_exception(module_inst, "out of bounds memory access"); @@ -1202,7 +1249,13 @@ wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst, } if ((memory->base_addr <= addr && addr + size <= memory->end_addr) - || (memory->heap_data <= addr && addr + size <= memory->heap_data_end)) + || (memory->heap_data <= addr && addr + size <= memory->heap_data_end) +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + || (module_inst->ext_mem_data + && module_inst->ext_mem_data <= addr + && addr + size <= module_inst->ext_mem_data_end) +#endif + ) return true; fail: @@ -1215,10 +1268,22 @@ wasm_runtime_addr_app_to_native(WASMModuleInstance *module_inst, int32 app_offset) { WASMMemoryInstance *memory = module_inst->default_memory; - if (app_offset < memory->heap_base_offset) + if (0 <= app_offset && app_offset < memory->heap_base_offset) return memory->memory_data + app_offset; - else + else if (memory->heap_base_offset < app_offset + && app_offset < memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data)) return memory->heap_data + (app_offset - memory->heap_base_offset); +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + else if (module_inst->ext_mem_data + && module_inst->ext_mem_base_offset <= app_offset + && app_offset < module_inst->ext_mem_base_offset + + module_inst->ext_mem_size) + return module_inst->ext_mem_data + + (app_offset - module_inst->ext_mem_base_offset); +#endif + else + return NULL; } int32 @@ -1229,9 +1294,19 @@ wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst, if (memory->base_addr <= (uint8*)native_ptr && (uint8*)native_ptr < memory->end_addr) return (uint8*)native_ptr - memory->memory_data; - else + else if (memory->heap_data <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->heap_data_end) return memory->heap_base_offset + ((uint8*)native_ptr - memory->heap_data); +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + else if (module_inst->ext_mem_data + && module_inst->ext_mem_data <= (uint8*)native_ptr + && (uint8*)native_ptr < module_inst->ext_mem_data_end) + return module_inst->ext_mem_base_offset + + ((uint8*)native_ptr - module_inst->ext_mem_data); +#endif + else + return 0; } uint32 diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h index 56e806b9..30ef58c3 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h @@ -148,6 +148,13 @@ typedef struct WASMModuleInstance { uint32 temp_ret; uint32 llvm_stack; +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + int32 ext_mem_base_offset; + uint8 *ext_mem_data; + uint8 *ext_mem_data_end; + uint32 ext_mem_size; +#endif + /* Default WASM stack size of threads of this Module instance. */ uint32 wasm_stack_size; diff --git a/core/shared-lib/include/config.h b/core/shared-lib/include/config.h index 0cf7bd4f..b36753c1 100644 --- a/core/shared-lib/include/config.h +++ b/core/shared-lib/include/config.h @@ -115,3 +115,13 @@ #define APP_THREAD_STACK_SIZE_MAX (256 * 1024) #endif #endif + +/* External memory space provided by user, + but not wasm memory space and app heap space */ +#ifndef WASM_ENABLE_EXT_MEMORY_SPACE +#define WASM_ENABLE_EXT_MEMORY_SPACE 0 +#endif + +/* Default base offset of external memory space */ +#define DEFAULT_EXT_MEM_BASE_OFFSET (-2 * BH_GB) +