diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 8ac519b771..75c690ef8b 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -122,6 +122,17 @@ if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) set (WAMR_BUILD_SHARED_MEMORY 1) endif () +if (WAMR_BUILD_LIBC_WALI EQUAL 1) + include (${IWASM_DIR}/libraries/libc-wali/libc_wali.cmake) + # Enable the dependent feature if lib wali is enabled + set (WAMR_BUILD_THREAD_MGR 1) + set (WAMR_BUILD_BULK_MEMORY 1) + set (WAMR_BUILD_SHARED_MEMORY 1) + # Currently these settings are required + set (WAMR_BUILD_FAST_INTERP 1) + set (WAMR_BUILD_MULTI_MODULE 1) +endif () + if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) set (WAMR_BUILD_THREAD_MGR 1) include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake) @@ -194,6 +205,7 @@ set (source_all ${LIBC_EMCC_SOURCE} ${LIB_RATS_SOURCE} ${DEBUG_ENGINE_SOURCE} + ${LIBC_WALI_SOURCE} ) set (WAMR_RUNTIME_LIB_SOURCE ${source_all}) diff --git a/core/config.h b/core/config.h index 4bbb102340..157ad6d808 100644 --- a/core/config.h +++ b/core/config.h @@ -180,6 +180,10 @@ #error "Heap aux stack allocation must be enabled for WASI threads" #endif +#ifndef WASM_ENABLE_LIBC_WALI +#define WASM_ENABLE_LIBC_WALI 0 +#endif + #ifndef WASM_ENABLE_BASE_LIB #define WASM_ENABLE_BASE_LIB 0 #endif @@ -392,7 +396,7 @@ #define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) #define APP_THREAD_STACK_SIZE_MIN (48 * 1024) #else -#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) +#define APP_THREAD_STACK_SIZE_DEFAULT (128 * 1024) #define APP_THREAD_STACK_SIZE_MIN (24 * 1024) #endif #endif /* end of !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \ diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 98df09cb4f..a779d2befd 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -21,6 +21,9 @@ typedef struct { /* clang-format off */ #define REG_SYM(symbol) { #symbol, (void *)symbol } +#define REG_WALI_SYM() \ + REG_SYM(aot_poll_pending_signal), + #if WASM_ENABLE_BULK_MEMORY != 0 #define REG_BULK_MEMORY_SYM() \ REG_SYM(aot_memory_init), \ @@ -159,6 +162,7 @@ typedef struct { REG_AOT_TRACE_SYM() \ REG_INTRINSIC_SYM() \ REG_LLVM_PGO_SYM() \ + REG_WALI_SYM() \ #define CHECK_RELOC_OFFSET(data_size) do { \ if (!check_reloc_offset(target_section_size, \ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 0799d625f5..9b38e381df 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -14,6 +14,7 @@ #if WASM_ENABLE_THREAD_MGR != 0 #include "../libraries/thread-mgr/thread_manager.h" #endif +#include "../interpreter/sigtable.h" /* * Note: These offsets need to match the values hardcoded in @@ -42,7 +43,7 @@ bh_static_assert(offsetof(AOTModuleInstance, cur_exception) bh_static_assert(offsetof(AOTModuleInstance, global_table_data) == 13 * sizeof(uint64) + 128 + 11 * sizeof(uint64)); -bh_static_assert(sizeof(AOTMemoryInstance) == 104); +bh_static_assert(sizeof(AOTMemoryInstance) == 112); bh_static_assert(offsetof(AOTTableInstance, elems) == 8); bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0); @@ -551,6 +552,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, memory_inst->module_type = Wasm_Module_AoT; memory_inst->num_bytes_per_page = num_bytes_per_page; memory_inst->cur_page_count = init_page_count; + memory_inst->base_page_count = init_page_count; memory_inst->max_page_count = max_page_count; memory_inst->memory_data_size = (uint32)total_size; @@ -855,6 +857,48 @@ create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module, return true; } +static bool +create_export_globals(AOTModuleInstance *module_inst, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + AOTExport *exports = module->exports; + AOTGlobalInstance *export_global; + uint64 size; + uint32 i, global_index; + + if (module_inst->export_global_count > 0) { + /* Allocate memory */ + size = sizeof(AOTGlobalInstance) + * (uint64)module_inst->export_global_count; + if (!(export_global = runtime_malloc(size, error_buf, error_buf_size))) { + return false; + } + module_inst->export_globals = (void *)export_global; + + for (i = 0; i < module->export_count; i++) { + if (exports[i].kind == EXPORT_KIND_GLOBAL) { + export_global->name = exports[i].name; + export_global->index = exports[i].index; + if (export_global->index < module->import_global_count) { + export_global->is_import_global = true; + export_global->u.glob_import = + &module->import_globals[export_global->index]; + } + else { + export_global->is_import_global = false; + global_index = + export_global->index - module->import_global_count; + export_global->u.glob = + &module->globals[global_index]; + } + export_global++; + } + } + } + + return true; +} + static bool create_exports(AOTModuleInstance *module_inst, AOTModule *module, char *error_buf, uint32 error_buf_size) @@ -881,7 +925,8 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, } } - return create_export_funcs(module_inst, module, error_buf, error_buf_size); + return create_export_funcs(module_inst, module, error_buf, error_buf_size) + && create_export_globals(module_inst, module, error_buf, error_buf_size); } static AOTFunctionInstance * @@ -1285,6 +1330,9 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (module_inst->export_functions) wasm_runtime_free(module_inst->export_functions); + if (module_inst->export_globals) + wasm_runtime_free(module_inst->export_globals); + if (module_inst->func_ptrs) wasm_runtime_free(module_inst->func_ptrs); @@ -1320,6 +1368,19 @@ aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, return NULL; } +AOTGlobalInstance* +aot_lookup_global(const AOTModuleInstance *module_inst, const char *name) +{ + uint32 i; + AOTGlobalInstance *export_globs = + (AOTGlobalInstance*)module_inst->export_globals; + + for (i = 0; i < module_inst->export_global_count; i++) + if (!strcmp(export_globs[i].name, name)) + return &export_globs[i]; + return NULL; +} + #ifdef OS_ENABLE_HW_BOUND_CHECK static bool @@ -1647,6 +1708,25 @@ aot_copy_exception(AOTModuleInstance *module_inst, char *exception_buf) return wasm_copy_exception(module_inst, exception_buf); } +void +aot_poll_pending_signal(WASMExecEnv *exec_env) +{ + int signo; + if ((signo = get_pending_signal()) != -1) { + pthread_mutex_lock(&sigtable_mut); + AOTModuleInstance *module_inst = (AOTModuleInstance*) wasm_runtime_get_module_inst(exec_env); + AOTFunctionInstance* sigfn = wali_sigtable[signo].function; + /* Patch function pointer in case of reassignment */ + uint32 func_idx = wali_sigtable[signo].func_idx; + uint32 func_type_idx = module_inst->func_type_indexes[func_idx]; + sigfn->u.func.func_type = ((AOTModule*)module_inst->module)->func_types[func_type_idx]; + sigfn->u.func.func_ptr = module_inst->func_ptrs[func_idx]; + /* */ + pthread_mutex_unlock(&sigtable_mut); + wasm_runtime_call_wasm(exec_env, sigfn, 1, (uint32_t*)&signo); + } +} + static bool execute_malloc_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, AOTFunctionInstance *malloc_func, @@ -1962,10 +2042,16 @@ aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, return buffer_offset; } +bool +aot_can_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) +{ + return wasm_can_enlarge_memory(module_inst, inc_page_count); +} + bool aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) { - return wasm_enlarge_memory(module_inst, inc_page_count); + return wasm_enlarge_memory(module_inst, inc_page_count, false); } bool @@ -2059,6 +2145,50 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, return ret; } + +bool +aot_get_indirect_function (AOTModuleInstance *module_inst, uint32 tbl_idx, + uint32 table_elem_idx, void **func_ptr_addr, + uint32* func_idx_addr, AOTFuncType **func_type_addr) { + + AOTModule *aot_module = (AOTModule *)module_inst->module; + AOTTableInstance *tbl_inst = NULL; + uint32 func_idx = NULL_REF; + uint32 *func_type_indexes = module_inst->func_type_indexes; + uint32 func_type_idx; + void **func_ptrs = module_inst->func_ptrs; + + tbl_inst = module_inst->tables[tbl_idx]; + bh_assert(tbl_inst); + if (table_elem_idx >= tbl_inst->cur_size) { + aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT); + goto fail; + } + + func_idx = tbl_inst->elems[table_elem_idx]; + if (func_idx == NULL_REF) { + aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); + goto fail; + } + + func_type_idx = func_type_indexes[func_idx]; + *func_type_addr = aot_module->func_types[func_type_idx]; + + if (func_idx >= aot_module->import_func_count) { + /* func pointer was looked up previously */ + bh_assert(func_ptrs[func_idx] != NULL); + } + + *func_ptr_addr = func_ptrs[func_idx]; + *func_idx_addr = func_idx; + return true; + +fail: + *func_ptr_addr = NULL; + *func_idx_addr = 0; + return false; +} + bool aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, uint32 argc, uint32 *argv) @@ -2066,11 +2196,9 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, AOTModuleInstance *module_inst = (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env); AOTModule *aot_module = (AOTModule *)module_inst->module; - uint32 *func_type_indexes = module_inst->func_type_indexes; - AOTTableInstance *tbl_inst; AOTFuncType *func_type; - void **func_ptrs = module_inst->func_ptrs, *func_ptr; - uint32 func_type_idx, func_idx, ext_ret_count; + void *func_ptr; + uint32 func_idx, ext_ret_count; AOTImportFunc *import_func; const char *signature = NULL; void *attachment = NULL; @@ -2087,29 +2215,13 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, goto fail; } - tbl_inst = module_inst->tables[tbl_idx]; - bh_assert(tbl_inst); - - if (table_elem_idx >= tbl_inst->cur_size) { - aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT); - goto fail; - } - - func_idx = tbl_inst->elems[table_elem_idx]; - if (func_idx == NULL_REF) { - aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); - goto fail; - } - - func_type_idx = func_type_indexes[func_idx]; - func_type = aot_module->func_types[func_type_idx]; - - if (func_idx >= aot_module->import_func_count) { - /* func pointer was looked up previously */ - bh_assert(func_ptrs[func_idx] != NULL); + bool success = aot_get_indirect_function(module_inst, tbl_idx, table_elem_idx, + &func_ptr, &func_idx, &func_type); + if (!success) { + goto fail; } - if (!(func_ptr = func_ptrs[func_idx])) { + if (!func_ptr) { bh_assert(func_idx < aot_module->import_func_count); import_func = aot_module->import_funcs + func_idx; snprintf(buf, sizeof(buf), diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 35c78bfa08..eae912ec57 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -87,6 +87,17 @@ typedef struct AOTFunctionInstance { } u; } AOTFunctionInstance; +/* AOT global instance */ +typedef struct AOTGlobalInstance { + char *name; + uint32 index; + bool is_import_global; + union { + AOTGlobal *glob; + AOTImportGlobal *glob_import; + } u; +} AOTGlobalInstance; + typedef struct AOTModuleInstanceExtra { DefPointer(const uint32 *, stack_sizes); WASMModuleInstanceExtraCommon common; @@ -421,6 +432,18 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst); AOTFunctionInstance * aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, const char *signature); + +/** + * Lookup an exported global in the AOT module instance. + * + * @param module_inst the module instance + * @param name the name of the global + * + * @return the global instance found + */ +AOTGlobalInstance* +aot_lookup_global(const AOTModuleInstance *module_inst, const char *name); + /** * Call the given AOT function of a AOT module instance with * arguments. @@ -472,6 +495,13 @@ aot_get_exception(AOTModuleInstance *module_inst); bool aot_copy_exception(AOTModuleInstance *module_inst, char *exception_buf); +/** + * Poll for pending signals in WALI + * @param exec_env the execution environment + * @return none + */ +void aot_poll_pending_signal(WASMExecEnv *exec_env); + uint32 aot_module_malloc_internal(AOTModuleInstance *module_inst, WASMExecEnv *env, uint32 size, void **p_native_addr); @@ -499,6 +529,9 @@ uint32 aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, uint32 size); +bool +aot_can_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); + bool aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); @@ -509,6 +542,14 @@ bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, uint32 *argv); +/** +* Get indirect function and return func_ptr, func_idx, func_type +*/ +bool +aot_get_indirect_function (AOTModuleInstance *module_inst, uint32 tbl_idx, + uint32 table_elem_idx, void **func_ptr_addr, + uint32* func_idx_addr, AOTFuncType **func_type_addr); + bool aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, uint32 argc, uint32 *argv); diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 02999584f6..37feb07d13 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -13,6 +13,9 @@ #if WASM_ENABLE_THREAD_MGR != 0 #include "../libraries/thread-mgr/thread_manager.h" #endif +#if WASM_ENABLE_LIBC_WALI != 0 +#include "../libraries/libc-wali/wali_defs.h" +#endif static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -101,13 +104,14 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) return false; } -#if WASM_ENABLE_LIBC_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_LIBC_WALI != 0 /* In wasi mode, we should call the function named "_start" which initializes the wasi envrionment and then calls the actual main function. Directly calling main function may cause exception thrown. */ if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) { const char *wasi_proc_exit_exception = "wasi proc exit"; + const char *wali_proc_exit_exception = "wali proc exit"; ret = wasm_runtime_call_wasm(exec_env, func, 0, NULL); #if WASM_ENABLE_THREAD_MGR != 0 @@ -122,15 +126,18 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) returns w/o calling `proc_exit`. - A process termination should terminate threads in the process. */ - - wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception); + if (invoked_wali) + wasm_runtime_set_exception(module_inst, wali_proc_exit_exception); + else + wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception); /* exit_code is zero-initialized */ ret = false; } #endif /* report wasm proc exit as a success */ WASMModuleInstance *inst = (WASMModuleInstance *)module_inst; - if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) { + if (!ret && (strstr(inst->cur_exception, wasi_proc_exit_exception) + || strstr(inst->cur_exception, wali_proc_exit_exception)) ) { inst->cur_exception[0] = 0; ret = true; } @@ -235,6 +242,13 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, WASMExecEnv *exec_env; #endif +#if WASM_ENABLE_LIBC_WALI != 0 + wali_app_argc = argc; + wali_app_argv = argv; + /* Set by internal WALI state */ + invoked_wali = false; +#endif + ret = execute_main(module_inst, argc, argv); #if WASM_ENABLE_MEMORY_PROFILING != 0 diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 622bcd71ee..1a99de3c18 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include + #include "wasm_exec_env.h" #include "wasm_runtime_common.h" #if WASM_ENABLE_INTERP != 0 @@ -22,6 +24,8 @@ #include "../libraries/debug-engine/debug_engine.h" #endif #endif +#include "../interpreter/sigtable.h" + WASMExecEnv * wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, @@ -62,6 +66,10 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, goto fail5; #endif + static _Atomic uint64 uid = 1; + exec_env->uid = uid++; + exec_env->sigpending_ptr = &wali_sigpending; + exec_env->module_inst = module_inst; exec_env->wasm_stack_size = stack_size; exec_env->wasm_stack.s.top_boundary = diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index bf9892080d..cffa33d82a 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -84,6 +84,8 @@ typedef struct WASMExecEnv { */ uint8 *native_stack_top_min; + uint64_t *sigpending_ptr; + #if WASM_ENABLE_FAST_JIT != 0 /** * Cache for @@ -145,6 +147,9 @@ typedef struct WASMExecEnv { uint32 max_wasm_stack_used; #endif + /* Custom addition for dynamic thread creating tracking */ + uint64 uid; + /* The WASM stack size */ uint32 wasm_stack_size; diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 05635ef51c..cff6d94c8f 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -42,6 +42,32 @@ static void (*free_func)(void *ptr) = NULL; static unsigned int global_pool_size; +/* Custom methods */ +uint32 +wasm_runtime_get_base_memory_size(WASMModuleInstanceCommon *module_inst_comm) +{ + WASMModuleInstance *mod_inst = (WASMModuleInstance *)module_inst_comm; + WASMMemoryInstance *memory_inst = wasm_get_default_memory(mod_inst); + return memory_inst->base_page_count * memory_inst->num_bytes_per_page; +} + +uint32 +wasm_runtime_get_memory_size(WASMModuleInstanceCommon *module_inst_comm) +{ + WASMModuleInstance *mod_inst = (WASMModuleInstance *)module_inst_comm; + WASMMemoryInstance *memory_inst = wasm_get_default_memory(mod_inst); + return memory_inst->memory_data_size; +} + +uint32 +wasm_runtime_get_max_memory_size(WASMModuleInstanceCommon *module_inst_comm) +{ + WASMModuleInstance *mod_inst = (WASMModuleInstance *)module_inst_comm; + WASMMemoryInstance *memory_inst = wasm_get_default_memory(mod_inst); + return memory_inst->max_page_count * memory_inst->num_bytes_per_page; +} + + static bool wasm_memory_init_with_pool(void *mem, unsigned int bytes) { @@ -568,6 +594,19 @@ wasm_get_default_memory(WASMModuleInstance *module_inst) return NULL; } +bool +wasm_can_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) +{ + WASMMemoryInstance *memory = wasm_get_default_memory(module); + if (!memory) + return false; + + if (memory->cur_page_count + inc_page_count > memory->max_page_count) + return false; + + return true; +} + #ifndef OS_ENABLE_HW_BOUND_CHECK bool wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) @@ -585,6 +624,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) goto return_func; } + heap_data_old = memory->heap_data; heap_size = (uint32)(memory->heap_data_end - memory->heap_data); @@ -725,7 +765,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) } #else bool -wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) +wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count, bool is_mmap) { WASMMemoryInstance *memory = wasm_get_default_memory(module); uint32 num_bytes_per_page, total_size_old = 0; @@ -769,6 +809,20 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) total_size_new = UINT32_MAX; } + if (is_mmap) { + LOG_VERBOSE("NOTE: Enlarging memory with mmap syscall by %d pages", inc_page_count); + /*** Added for WALI ***/ + uint32 inc_bytes = num_bytes_per_page * inc_page_count; + memory->num_bytes_per_page = num_bytes_per_page; + memory->cur_page_count += inc_page_count; + memory->max_page_count = max_page_count; + memory->memory_data_size += inc_bytes; + memory->memory_data_end += inc_bytes; + return true; + /* */ + } + LOG_ERROR("NOTE: Enlarging memory without mmap... There might be errors here.."); + #ifdef BH_PLATFORM_WINDOWS if (!os_mem_commit(memory->memory_data_end, (uint32)total_size_new - total_size_old, @@ -841,7 +895,7 @@ wasm_runtime_set_enlarge_mem_error_callback( } bool -wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) +wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count, bool is_mmap) { bool ret = false; @@ -849,7 +903,7 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) if (module->memory_count > 0) shared_memory_lock(module->memories[0]); #endif - ret = wasm_enlarge_memory_internal(module, inc_page_count); + ret = wasm_enlarge_memory_internal(module, inc_page_count, is_mmap); #if WASM_ENABLE_SHARED_MEMORY != 0 if (module->memory_count > 0) shared_memory_unlock(module->memories[0]); diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 0a5851349a..e274ca3dce 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -46,6 +46,9 @@ get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis); uint32 get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis); +uint32 +get_libc_wali_export_apis(NativeSymbol **p_libc_wali_apis); + uint32_t get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis); @@ -595,6 +598,13 @@ wasm_native_init() goto fail; #endif +#if WASM_ENABLE_LIBC_WALI != 0 + n_native_symbols = get_libc_wali_export_apis(&native_symbols); + if (!wasm_native_register_natives("wali", native_symbols, + n_native_symbols)) + goto fail; +#endif + #if WASM_ENABLE_BASE_LIB != 0 n_native_symbols = get_base_lib_export_apis(&native_symbols); if (n_native_symbols > 0 diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8faa5e444f..df2f4a131c 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -36,6 +36,9 @@ #endif #include "../common/wasm_c_api_internal.h" #include "../../version.h" +#if WASM_ENABLE_LIBC_WALI != 0 +#include "../libraries/libc-wali/wali_init.h" +#endif /** * For runtime build, BH_MALLOC/BH_FREE should be defined as @@ -1145,6 +1148,8 @@ wasm_runtime_is_built_in_module(const char *module_name) { return (!strcmp("env", module_name) || !strcmp("wasi_unstable", module_name) || !strcmp("wasi_snapshot_preview1", module_name) + || !strcmp("instrument", module_name) + || !strcmp("wali", module_name) #if WASM_ENABLE_SPEC_TEST != 0 || !strcmp("spectest", module_name) #endif @@ -1349,8 +1354,12 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) { - return wasm_runtime_instantiate_internal( + WASMModuleInstanceCommon *module_inst = wasm_runtime_instantiate_internal( module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size); +#if WASM_ENABLE_LIBC_WALI != 0 + wali_init_native(module_inst); +#endif + return module_inst; } void @@ -1425,6 +1434,12 @@ wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst, return wasm_exec_env_create(module_inst, stack_size); } +uint64 +wasm_runtime_get_exec_env_uid(WASMExecEnv *exec_env) +{ + return exec_env->uid; +} + void wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env) { @@ -1689,6 +1704,21 @@ wasm_runtime_set_module_inst(WASMExecEnv *exec_env, wasm_exec_env_set_module_inst(exec_env, module_inst); } +uint32 +wasm_runtime_get_function_idx(WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *func) { +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + return (WASMFunctionInstance*)(func) - ((WASMModuleInstance*)(module_inst))->e->functions; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + return ((AOTFunctionInstance*)func)->func_index; + } +#endif + return -1; +} + void * wasm_runtime_get_function_attachment(WASMExecEnv *exec_env) { @@ -1759,6 +1789,50 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst, return NULL; } + +WASMFunctionInstanceCommon * +wasm_runtime_get_indirect_function(WASMModuleInstanceCommon *module_inst, + uint32 tbl_idx, uint32 elem_idx) { +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + return (WASMFunctionInstanceCommon *)wasm_get_indirect_function( + (WASMModuleInstance *)module_inst, tbl_idx, elem_idx); + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst; + void *func_ptr; + uint32 func_idx; + AOTFuncType *func_type; + bool success = aot_get_indirect_function(aot_inst, tbl_idx, elem_idx, + &func_ptr, &func_idx, &func_type); + + if (!success) { + return NULL; + } + + /* Create a custom function instance since this is discarded + * by the compiler. Caller implementation is responsible for freeing */ + AOTFunctionInstance *func_inst = + (AOTFunctionInstance*) runtime_malloc( + sizeof(AOTFunctionInstance), module_inst, NULL, 0); + if (!func_inst) { + return NULL; + } + func_inst->func_name = ""; + func_inst->func_index = func_idx; + func_inst->is_import_func = false; + func_inst->u.func.func_type = func_type; + func_inst->u.func.func_ptr = func_ptr; + + return (WASMFunctionInstanceCommon *)func_inst; + } +#endif + return NULL; + +} + uint32 wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst, WASMModuleInstanceCommon *const module_inst) @@ -3362,6 +3436,41 @@ wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst) } #endif /* end of WASM_ENABLE_LIBC_WASI */ +#if WASM_ENABLE_LIBC_WALI + +WALIContext * +wasm_runtime_get_wali_ctx(WASMModuleInstanceCommon *module_inst_comm) +{ + WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; + + bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode + || module_inst_comm->module_type == Wasm_Module_AoT); + return &module_inst->wali_ctx; +} + +uint32_t +wasm_runtime_get_wali_exit_code(WASMModuleInstanceCommon *module_inst) +{ + WALIContext *wali_ctx = wasm_runtime_get_wali_ctx(module_inst); +#if WASM_ENABLE_THREAD_MGR != 0 + WASMCluster *cluster; + WASMExecEnv *exec_env; + + exec_env = wasm_runtime_get_exec_env_singleton(module_inst); + if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) { + /** + * The main thread may exit earlier than other threads, and + * the exit_code of wasi_ctx may be changed by other thread + * when it runs into wasi_proc_exit, here we wait until all + * other threads exit to avoid getting invalid exit_code. + */ + wasm_cluster_wait_for_all_except_self(cluster, exec_env); + } +#endif + return wali_ctx->exit_code; +} +#endif /* end of WASM_ENABLE_LIBC_WALI */ + WASMModuleCommon * wasm_exec_env_get_module(WASMExecEnv *exec_env) { diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index a834d67f2a..999adba08f 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -382,6 +382,14 @@ typedef struct WASIContext { #endif #endif +#if WASM_ENABLE_LIBC_WALI != 0 +typedef struct WALIContext { + uint32_t exit_code; + /* Currently unused */ + char *env_filepath; +} WALIContext; +#endif + #if WASM_ENABLE_MULTI_MODULE != 0 typedef struct WASMRegisteredModule { bh_list_link l; @@ -458,6 +466,15 @@ LLVMJITOptions wasm_runtime_get_llvm_jit_options(void); #endif +/* Custom methods */ +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN uint32 +wasm_runtime_get_base_memory_size(WASMModuleInstanceCommon *module_inst); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN uint32 +wasm_runtime_get_memory_size(WASMModuleInstanceCommon *module_inst); + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_full_init(RuntimeInitArgs *init_args); @@ -582,6 +599,10 @@ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_module_inst(WASMExecEnv *exec_env, WASMModuleInstanceCommon *const module_inst); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN uint32 +wasm_runtime_get_function_idx(WASMModuleInstanceCommon *const module_inst, WASMFunctionInstanceCommon *func); + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_function_attachment(WASMExecEnv *exec_env); @@ -904,6 +925,16 @@ wasm_runtime_set_wasi_ns_lookup_pool(wasm_module_t module, uint32 ns_lookup_pool_size); #endif /* end of WASM_ENABLE_LIBC_WASI */ +#if WASM_ENABLE_LIBC_WALI +WALIContext * +wasm_runtime_get_wali_ctx(WASMModuleInstanceCommon *module_inst_comm); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_runtime_get_wali_exit_code(WASMModuleInstanceCommon *module_inst); +#endif /* end of WASM_ENABLE_LIBC_WASI */ + + #if WASM_ENABLE_REF_TYPES != 0 /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 464ca61f32..bbf196b5b1 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -30,6 +30,7 @@ #include "simd/simd_sat_int_arith.h" #include "../aot/aot_runtime.h" #include "../interpreter/wasm_opcode.h" +#include "aot_emit_sigpoll.h" #include #if WASM_ENABLE_DEBUG_AOT != 0 @@ -189,6 +190,13 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) LLVMPositionBuilderAtEnd( comp_ctx->builder, func_ctx->block_stack.block_list_head->llvm_entry_block); + +#if WALI_ENABLE_FUNC_SIGPOLL + if (!aot_emit_sigpoll(comp_ctx, func_ctx)) { + return false; + } +#endif + while (frame_ip < frame_ip_end) { opcode = *frame_ip++; @@ -198,7 +206,11 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) (frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code); LLVMSetCurrentDebugLocation2(comp_ctx->builder, location); #endif - +#if WALI_ENABLE_ALL_SIGPOLL + if (!aot_emit_sigpoll(comp_ctx, func_ctx)) { + return false; + } +#endif switch (opcode) { case WASM_OP_UNREACHABLE: if (!aot_compile_op_unreachable(comp_ctx, func_ctx, &frame_ip)) diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index b6347c89d7..a930430860 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -267,6 +267,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type) #define I32_SEVEN LLVM_CONST(i32_seven) #define I32_EIGHT LLVM_CONST(i32_eight) #define I32_NINE LLVM_CONST(i32_nine) +#define I32_TEN LLVM_CONST(i32_ten) #define I32_NEG_ONE LLVM_CONST(i32_neg_one) #define I64_NEG_ONE LLVM_CONST(i64_neg_one) #define I32_MIN LLVM_CONST(i32_min) diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 446ca5ea64..f2ddf25cb4 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -6,6 +6,7 @@ #include "aot_emit_control.h" #include "aot_compiler.h" #include "aot_emit_exception.h" +#include "aot_emit_sigpoll.h" #include "../aot/aot_runtime.h" #include "../interpreter/wasm_loader.h" @@ -457,8 +458,16 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Start to translate the block */ SET_BUILDER_POS(block->llvm_entry_block); - if (label_type == LABEL_TYPE_LOOP) + + if (label_type == LABEL_TYPE_LOOP) { aot_checked_addr_list_destroy(func_ctx); + /* Insert Signal Polling for WALI here for Loops*/ +#if WALI_ENABLE_LOOP_SIGPOLL + if (!aot_emit_sigpoll(comp_ctx, func_ctx)) { + goto fail; + } +#endif + } } else if (label_type == LABEL_TYPE_IF) { POP_COND(value); diff --git a/core/iwasm/compilation/aot_emit_sigpoll.c b/core/iwasm/compilation/aot_emit_sigpoll.c new file mode 100644 index 0000000000..5f806056bd --- /dev/null +++ b/core/iwasm/compilation/aot_emit_sigpoll.c @@ -0,0 +1,113 @@ +/* WALI compilation support for signal polling */ + +#include "aot_emit_sigpoll.h" +#include "../aot/aot_runtime.h" + +#define CREATE_BLOCK(new_llvm_block, name) \ + do { \ + if (!(new_llvm_block = LLVMAppendBasicBlockInContext( \ + comp_ctx->context, func_ctx->func, name))) { \ + aot_set_last_error("add LLVM basic block failed."); \ + return false; \ + } \ + } while (0) + +#define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder) + +#define MOVE_BLOCK_AFTER(llvm_block, llvm_block_after) \ + LLVMMoveBasicBlockAfter(llvm_block, llvm_block_after) + +#define MOVE_BLOCK_AFTER_CURR(llvm_block) \ + LLVMMoveBasicBlockAfter(llvm_block, CURR_BLOCK()) + +#define SET_BUILDER_POS(llvm_block) \ + LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block) + +#define BUILD_COND_BR(value_if, block_then, block_else) \ + do { \ + if (!LLVMBuildCondBr(comp_ctx->builder, value_if, block_then, \ + block_else)) { \ + aot_set_last_error("llvm build cond br failed."); \ + return false; \ + } \ + } while (0) + +#define BUILD_BR(llvm_block) \ + do { \ + if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \ + aot_set_last_error("llvm build br failed."); \ + return false; \ + } \ + } while (0) + +#define BUILD_ICMP(op, left, right, res, name) \ + do { \ + if (!(res = \ + LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \ + aot_set_last_error("llvm build icmp failed."); \ + return false; \ + } \ + } while (0) + +bool +aot_emit_sigpoll(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { +#if WALI_ENABLE_SIGNAL_HANDLING + /* For WALI Signal Poll handling */ + LLVMValueRef func; + LLVMTypeRef func_type, ret_type, param_types[1]; + LLVMValueRef param_values[1]; + + LLVMValueRef sigpoll_value, take_sigpoll; + LLVMBasicBlockRef sigpoll_block, contpoll_block; + + /* Get sigpoll_value */ + if (!(sigpoll_value = + LLVMBuildLoad2(comp_ctx->builder, I64_TYPE, func_ctx->sigpoll_ptr, + "sigpoll_value"))) { + aot_set_last_error("llvm build LOAD failed"); + return false; + } + + CREATE_BLOCK(sigpoll_block, "sigpoll_block"); + MOVE_BLOCK_AFTER_CURR(sigpoll_block); + + CREATE_BLOCK(contpoll_block, "contpoll"); + MOVE_BLOCK_AFTER_CURR(contpoll_block); + + /* Test whether to invoke call or continue */ + BUILD_ICMP(LLVMIntEQ, sigpoll_value, I64_ZERO, take_sigpoll, "sigpoll_flag"); + BUILD_COND_BR(take_sigpoll, contpoll_block, sigpoll_block); + + /* Sigpolling */ + SET_BUILDER_POS(sigpoll_block); + + /* Create sigpoll function type */ + ret_type = VOID_TYPE; + param_types[0] = comp_ctx->exec_env_type; + if (!(func_type = LLVMFunctionType(ret_type, param_types, 1, false))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + + /* External function pointer to 'aot_poll_pending_signal' */ + if (!(func = LLVMGetNamedFunction(func_ctx->module, + "aot_poll_pending_signal")) + && !(func = LLVMAddFunction(func_ctx->module, + "aot_poll_pending_signal", + func_type))) { + aot_set_last_error("add LLVM function failed."); + return false; + } + + param_values[0] = func_ctx->exec_env; + if (!LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 1, "")) { + aot_set_last_error("llvm build call failed."); + return false; + } + + BUILD_BR(contpoll_block); + + SET_BUILDER_POS(contpoll_block); +#endif /* WALI_ENABLE_SIGNAL_HANDLING */ + return true; +} diff --git a/core/iwasm/compilation/aot_emit_sigpoll.h b/core/iwasm/compilation/aot_emit_sigpoll.h new file mode 100644 index 0000000000..da535e372d --- /dev/null +++ b/core/iwasm/compilation/aot_emit_sigpoll.h @@ -0,0 +1,35 @@ +#ifndef _AOT_EMIT_SIGPOLL_H_ +#define _AOT_EMIT_SIGPOLL_H_ + +#include "aot_compiler.h" + + +#if WALI_ENABLE_SIGNAL_HANDLING + +#if WALI_ENABLE_ALL_SIGPOLL +#undef WALI_ENABLE_LOOP_SIGPOLL +#undef WALI_ENABLE_FUNC_SIGPOLL + +#elif WALI_ENABLE_FUNC_SIGPOLL +#undef WALI_ENABLE_LOOP_SIGPOLL + +#elif !WALI_ENABLE_LOOP_SIGPOLL +#ifndef WALI_ENABLE_LOOP_SIGPOLL +#define WALI_ENABLE_LOOP_SIGPOLL 1 /* default */ +#endif +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_emit_sigpoll(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_SIGPOLL_H_ */ diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 6dc3a0f7d3..5f6445b0f7 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -116,6 +116,27 @@ create_basic_func_context(const AOTCompContext *comp_ctx, goto fail; } + LLVMValueRef offset, sigpoll_addr; + offset = I32_TEN; + if (!(sigpoll_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1, + "sigpoll_addr_ptr"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(sigpoll_addr = + LLVMBuildBitCast(comp_ctx->builder, sigpoll_addr, + INT64_PTR_TYPE, "sigpoll_addr_ptr_cast"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!(func_ctx->sigpoll_ptr = + LLVMBuildLoad2(comp_ctx->builder, INT64_PTR_TYPE, sigpoll_addr, + "sigpoll_addr"))) { + aot_set_last_error("llvm build LOAD failed"); + return false; + } + return true; fail: return false; diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index b46ac3bd09..4268856f26 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -170,6 +170,7 @@ typedef struct AOTFuncContext { LLVMValueRef aux_stack_bottom; LLVMValueRef native_symbol; LLVMValueRef func_ptrs; + LLVMValueRef sigpoll_ptr; AOTMemInfo *mem_info; diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2a30ddc935..dd0d1dac31 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -203,6 +203,44 @@ typedef struct wasm_val_t { } wasm_val_t; #endif +/* Custom WALI methods */ +WASM_RUNTIME_API_EXTERN wasm_function_inst_t +wasm_runtime_get_indirect_function(wasm_module_inst_t module_inst, + uint32_t tbl_idx, uint32_t elem_idx); + +WASM_RUNTIME_API_EXTERN uint32_t +wasm_runtime_get_function_idx(wasm_module_inst_t module_inst, wasm_function_inst_t func); + +/** + * WALI: Get the size of the base memory (without mmaped data) + * + * @param module_inst the module instance + * + * @return size of base memory + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_runtime_get_base_memory_size(wasm_module_inst_t module_inst); + +/** + * Get the current size of memory + * + * @param module_inst the module instance + * + * @return size of memory + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_runtime_get_memory_size(wasm_module_inst_t module_inst); + +/** + * Get the max size of memory + * + * @param module_inst the module instance + * + * @return size of memory + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_runtime_get_max_memory_size(wasm_module_inst_t module_inst); + /** * Initialize the WASM runtime environment, and also initialize * the memory allocator with system allocator, which calls os_malloc @@ -568,6 +606,7 @@ WASM_RUNTIME_API_EXTERN wasm_function_inst_t wasm_runtime_lookup_function(wasm_module_inst_t const module_inst, const char *name, const char *signature); + /** * Get parameter count of the function instance * @@ -629,6 +668,16 @@ WASM_RUNTIME_API_EXTERN wasm_exec_env_t wasm_runtime_create_exec_env(wasm_module_inst_t module_inst, uint32_t stack_size); +/** + * Get the unique (dynamic) id of WASM execution env + * + * @param exec_env the execution environment + * + * @return the unique id + */ +WASM_RUNTIME_API_EXTERN uint64_t +wasm_runtime_get_exec_env_uid(wasm_exec_env_t exec_env); + /** * Destroy the execution environment. * @@ -1005,6 +1054,7 @@ WASM_RUNTIME_API_EXTERN uint32_t wasm_runtime_module_dup_data(wasm_module_inst_t module_inst, const char *src, uint32_t size); + /** * Validate the app address, check whether it belongs to WASM module * instance's address space, or in its heap space or memory space. @@ -1298,6 +1348,18 @@ wasm_runtime_spawn_thread(wasm_exec_env_t exec_env, wasm_thread_t *tid, WASM_RUNTIME_API_EXTERN int32_t wasm_runtime_join_thread(wasm_thread_t tid, void **retval); +/** + * Get WALI exit code. + * + * After a WALI bytecode completed its execution, an embedder can + * call this function to get its exit code + * + * @param module_inst the module instance + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_runtime_get_wali_exit_code(wasm_module_inst_t module_inst); + + /** * Map external object to an internal externref index: if the index * has been created, return it, otherwise create the index. diff --git a/core/iwasm/interpreter/iwasm_interp.cmake b/core/iwasm/interpreter/iwasm_interp.cmake index e6e52e42c8..0d08d89bc0 100644 --- a/core/iwasm/interpreter/iwasm_interp.cmake +++ b/core/iwasm/interpreter/iwasm_interp.cmake @@ -23,6 +23,7 @@ file (GLOB_RECURSE source_all ${IWASM_INTERP_DIR}/${LOADER} ${IWASM_INTERP_DIR}/wasm_runtime.c ${IWASM_INTERP_DIR}/${INTERPRETER} + ${IWASM_INTERP_DIR}/sigtable.c ) set (IWASM_INTERP_SOURCE ${source_all}) diff --git a/core/iwasm/interpreter/sigtable.c b/core/iwasm/interpreter/sigtable.c new file mode 100644 index 0000000000..503f770bbd --- /dev/null +++ b/core/iwasm/interpreter/sigtable.c @@ -0,0 +1,8 @@ +#include "sigtable.h" + +pthread_mutex_t sigtable_mut = PTHREAD_MUTEX_INITIALIZER; +wali_sigentry wali_sigtable[NSIG] = {0}; + +pthread_mutex_t sigpending_mut = PTHREAD_MUTEX_INITIALIZER; +uint64_t wali_sigpending = 0; + diff --git a/core/iwasm/interpreter/sigtable.h b/core/iwasm/interpreter/sigtable.h new file mode 100644 index 0000000000..9bda7dac7a --- /dev/null +++ b/core/iwasm/interpreter/sigtable.h @@ -0,0 +1,42 @@ +#ifndef _WALI_SIGTABLE_H_ +#define _WALI_SIGTABLE_H_ + +#include +#include +#include +#include + +#include "wasm_export.h" + +typedef struct { + wasm_function_inst_t function; + /* Index in the table, required to return back to old_sigaction */ + uint32_t func_table_idx; + /* Index in function space of the handler */ + uint32_t func_idx; +} wali_sigentry; + +extern pthread_mutex_t sigtable_mut; +extern wali_sigentry wali_sigtable[]; + +extern pthread_mutex_t sigpending_mut; +extern uint64_t wali_sigpending; + +/* Return -1 if no pending signal, else signal index */ +static inline int get_pending_signal(void) { + /* Don't need an atomic read here on the outermost check since + * inconsistent reads are filtered by the mutex inside + * This allows signal-free code to run significantly faster + */ + if (wali_sigpending) { + pthread_mutex_lock(&sigpending_mut); + int idx = __builtin_ffsll(wali_sigpending); + wali_sigpending &= ~(((uint64_t)1 << idx) - 1); + pthread_mutex_unlock(&sigpending_mut); + return idx - 1; + } else { + return -1; + } +} + +#endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 50860d3a31..40e1746231 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -2137,7 +2137,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, read_leb_uint32(frame_ip, frame_ip_end, reserved); delta = (uint32)POP_I32(); - if (!wasm_enlarge_memory(module, delta)) { + if (!wasm_enlarge_memory(module, delta, false)) { /* failed to memory.grow, return -1 */ PUSH_I32(-1); } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index e565c2c89c..d80a55d9e3 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -13,6 +13,7 @@ #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" #endif +#include "sigtable.h" typedef int32 CellType_I32; typedef int64 CellType_I64; @@ -1112,13 +1113,30 @@ wasm_interp_dump_op_count() } #endif +#define HANDLE_WALI_SIGNAL() \ + int signo; \ + if ((signo = get_pending_signal()) != -1) { \ + pthread_mutex_lock(&sigtable_mut); \ + WASMFunctionInstance* sigfn = module->e->functions + wali_sigtable[signo].func_idx; \ + pthread_mutex_unlock(&sigtable_mut); \ + wasm_runtime_call_wasm(exec_env, sigfn, 1, (uint32_t*)&signo); \ + } \ + #if WASM_ENABLE_LABELS_AS_VALUES != 0 /* #define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n"); */ #if WASM_ENABLE_OPCODE_COUNTER != 0 -#define HANDLE_OP(opcode) HANDLE_##opcode : opcode_table[opcode].count++; +#define HANDLE_OP(opcode) HANDLE_##opcode : \ + { \ + /* opcode_table[opcode].count++; */ \ + module->e->opcode_table[opcode]++; \ + HANDLE_WALI_SIGNAL(); \ + }; #else -#define HANDLE_OP(opcode) HANDLE_##opcode: +#define HANDLE_OP(opcode) HANDLE_##opcode: \ + { \ + HANDLE_WALI_SIGNAL(); \ + }; #endif #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 #define FETCH_OPCODE_AND_DISPATCH() \ @@ -1407,7 +1425,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, cur_func_type = cur_func->u.func->func_type; if (cur_type != cur_func_type) { - wasm_set_exception(module, "indirect call type mismatch"); + char except_msg[100]; + sprintf(except_msg, "indirect call type mismatch | Fn[%d]", fidx); + wasm_set_exception(module, except_msg); goto got_exception; } @@ -1890,7 +1910,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr_ret = GET_OFFSET(); delta = (uint32)frame_lp[addr1]; - if (!wasm_enlarge_memory(module, delta)) { + if (!wasm_enlarge_memory(module, delta, false)) { /* failed to memory.grow, return -1 */ frame_lp[addr_ret] = -1; } @@ -4034,6 +4054,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_exec_env_set_cur_frame(exec_env, prev_frame); FREE_FRAME(exec_env, frame); #if WASM_ENABLE_OPCODE_COUNTER != 0 - wasm_interp_dump_op_count(); + //wasm_interp_dump_op_count(); #endif } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 8fb19d52e8..a8fe376efb 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -294,7 +294,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, #ifndef OS_ENABLE_HW_BOUND_CHECK if (memory_data_size > 0 && !(memory->memory_data = - runtime_malloc(memory_data_size, error_buf, error_buf_size))) { + runtime_malloc(memory_data_size, error_buf, error_buf_size))) { goto fail1; } #else @@ -336,6 +336,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, memory->module_type = Wasm_Module_Bytecode; memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = init_page_count; + memory->base_page_count = init_page_count; memory->max_page_count = max_page_count; memory->memory_data_size = (uint32)memory_data_size; @@ -2569,18 +2570,14 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx, } #endif /* WASM_ENABLE_REF_TYPES != 0 */ -static bool -call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, - uint32 argc, uint32 argv[], bool check_type_idx, uint32 type_idx) -{ - WASMModuleInstance *module_inst = NULL; + +WASMFunctionInstance* +wasm_get_indirect_function (WASMModuleInstance *module_inst, uint32 tbl_idx, + uint32 elem_idx) { WASMTableInstance *table_inst = NULL; uint32 func_idx = 0; WASMFunctionInstance *func_inst = NULL; - module_inst = (WASMModuleInstance *)exec_env->module_inst; - bh_assert(module_inst); - table_inst = module_inst->tables[tbl_idx]; if (!table_inst) { wasm_set_exception(module_inst, "unknown table"); @@ -2608,6 +2605,28 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, func_inst = module_inst->e->functions + func_idx; + return func_inst; + +got_exception: + return NULL; +} + +static bool +call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, + uint32 argc, uint32 argv[], bool check_type_idx, uint32 type_idx) +{ + + WASMModuleInstance *module_inst = NULL; + module_inst = (WASMModuleInstance *)exec_env->module_inst; + bh_assert(module_inst); + + WASMFunctionInstance *func_inst = + wasm_get_indirect_function(module_inst, tbl_idx, elem_idx); + + if (!func_inst) { + goto got_exception; + } + if (check_type_idx) { WASMType *cur_type = module_inst->module->types[type_idx]; WASMType *cur_func_type; diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index d6661fa0fe..aa91e6a84f 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -86,6 +86,8 @@ struct WASMMemoryInstance { uint32 num_bytes_per_page; /* Current page count */ uint32 cur_page_count; + /* Base page count (without mmap memory) */ + uint32 base_page_count; /* Maximum page count */ uint32 max_page_count; /* Memory data size */ @@ -255,6 +257,14 @@ typedef struct WASMModuleInstanceExtra { && WASM_ENABLE_LAZY_JIT != 0) WASMModuleInstance *next; #endif + +#if WASM_ENABLE_WASI_NN != 0 + WASINNContext *wasi_nn_ctx; +#endif + +#if WASM_ENABLE_OPCODE_COUNTER != 0 + uint64 opcode_table[256]; +#endif } WASMModuleInstanceExtra; struct AOTFuncPerfProfInfo; @@ -344,6 +354,11 @@ struct WASMModuleInstance { WASMMemoryInstance memory_instances[1]; uint8 bytes[1]; } global_table_data; + +#if WASM_ENABLE_LIBC_WALI + WALIContext wali_ctx; +#endif + }; struct WASMInterpFrame; @@ -503,7 +518,14 @@ WASMMemoryInstance * wasm_get_default_memory(WASMModuleInstance *module_inst); bool -wasm_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count); +wasm_can_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count); + +bool +wasm_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count, bool is_mmap); + +WASMFunctionInstance* +wasm_get_indirect_function (WASMModuleInstance *module_inst, uint32 tbl_idx, + uint32 elem_idx); bool wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, diff --git a/core/iwasm/libraries/libc-wali/copy.h b/core/iwasm/libraries/libc-wali/copy.h new file mode 100644 index 0000000000..0dbe662d93 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/copy.h @@ -0,0 +1,253 @@ +/* + MIT License + + Copyright (c) [2023] [Arjun Ramesh] + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef WALI_COPY_H +#define WALI_COPY_H + +#include +#include +#include +#include +#include +#include + +#include "wali.h" +#include "../interpreter/sigtable.h" + +/** Memory Copy Macros **/ +#define WR_FIELD(wptr, val, ty) ({ \ + memcpy(wptr, &val, sizeof(ty)); \ + wptr += sizeof(ty); \ +}) + +#define WR_FIELD_ADDR(wptr, nptr) ({ \ + uint32_t wasm_addr = WADDR(nptr); \ + if (!wasm_addr) { VB("NULL Wasm Address generated"); } \ + WR_FIELD(wptr, wasm_addr, uint32_t); \ +}) + +#define WR_FIELD_ARRAY(wptr, narr, ty, num) ({ \ + memcpy(wptr, narr, sizeof(ty) * num); \ + wptr += (sizeof(ty) * num); \ +}) + +#define RD_FIELD(ptr, ty) ({ \ + ty val; \ + memcpy(&val, ptr, sizeof(ty)); \ + ptr += sizeof(ty); \ + val; \ +}) + +#define RD_FIELD_ADDR(ptr) ({ \ + uint32_t field = RD_FIELD(ptr, uint32_t); \ + MADDR (field); \ +}) + +#define RD_FIELD_ARRAY(dest, ptr, ty, num) ({ \ + memcpy(&dest, ptr, sizeof(ty) * num); \ + ptr += (sizeof(ty) * num); \ +}) +/** **/ + +/** Debug Macro **/ +#define PRINT_BYTES(var, num) { \ + printf(#var " bytes: "); \ + char* v = (char*) var; \ + for (int i = 0; i < num; i++) { \ + printf("%02X ", v[i]); \ + } \ + printf("\n"); \ +} + +/* Copy pselect6 sigmask structure */ +extern inline void* copy_pselect6_sigmask(wasm_exec_env_t exec_env, Addr wasm_psel_sm, long* sm_struct) { + /* Libc stores the address in a long (64-bit). Cannot use RD_FIELD_ADDR since + * it reads 32-bit values */ + long sigmask_addr = RD_FIELD(wasm_psel_sm, long); + sm_struct[0] = (long) MADDR(sigmask_addr); + sm_struct[1] = RD_FIELD(wasm_psel_sm, long); + return sm_struct; +} + +/* Copy iovec structure */ +extern inline struct iovec* copy_iovec(wasm_exec_env_t exec_env, Addr wasm_iov, int iov_cnt) { + if (wasm_iov == NULL) { return NULL; } + struct iovec *new_iov = (struct iovec*) malloc(iov_cnt * sizeof(struct iovec)); + for (int i = 0; i < iov_cnt; i++) { + new_iov[i].iov_base = RD_FIELD_ADDR(wasm_iov); + new_iov[i].iov_len = RD_FIELD(wasm_iov, int32_t); + } + return new_iov; +} + +/* Copy epoll_event structure */ +extern inline struct epoll_event* copy_epoll_event(wasm_exec_env_t exec_env, Addr wasm_epoll, struct epoll_event *n_epoll) { + if (wasm_epoll == NULL) { return NULL; } + n_epoll->events = RD_FIELD(wasm_epoll, uint32_t); + n_epoll->data.u64 = RD_FIELD(wasm_epoll, uint64_t); + return n_epoll; +} + +extern inline void copy2wasm_epoll_event(wasm_exec_env_t exec_env, Addr wasm_epoll, struct epoll_event *n_epoll) { + if (n_epoll == NULL) { return; } + WR_FIELD(wasm_epoll, n_epoll->events, uint32_t); + WR_FIELD(wasm_epoll, n_epoll->data.u64, uint64_t); + return; +} + +/* Copy msghdr structure */ +extern inline struct msghdr* copy_msghdr(wasm_exec_env_t exec_env, Addr wasm_msghdr) { + if (wasm_msghdr == NULL) { return NULL; } + struct msghdr *msg = (struct msghdr*) malloc(sizeof(struct msghdr)); + msg->msg_name = RD_FIELD_ADDR(wasm_msghdr); + msg->msg_namelen = RD_FIELD(wasm_msghdr, unsigned); + + Addr wasm_iov = RD_FIELD_ADDR(wasm_msghdr); + msg->msg_iovlen = RD_FIELD(wasm_msghdr, int); + + RD_FIELD(wasm_msghdr, int); // pad1 + + msg->msg_control = RD_FIELD_ADDR(wasm_msghdr); + msg->msg_controllen = RD_FIELD(wasm_msghdr, unsigned); + + RD_FIELD(wasm_msghdr, int); // pad2 + msg->msg_flags = RD_FIELD(wasm_msghdr, int); + + msg->msg_iov = copy_iovec(exec_env, wasm_iov, msg->msg_iovlen); + return msg; +} + + +// ASM restorer function '__libc_restore_rt'. +extern void __libc_restore_rt(); + +/* Copy sigaction back to WASM */ +extern inline void copy2wasm_old_ksigaction (int signo, Addr wasm_act, struct k_sigaction *act) { + FuncPtr_t old_wasm_funcptr; + if (act->handler == SIG_DFL) { + old_wasm_funcptr = WASM_SIG_DFL; + } else if (act->handler == SIG_IGN) { + old_wasm_funcptr = WASM_SIG_IGN; + } else if (act->handler == SIG_ERR) { + old_wasm_funcptr = WASM_SIG_ERR; + } else { + old_wasm_funcptr = wali_sigtable[signo].func_table_idx; + VB("Save old sigaction handler -- Tbl[%d]", old_wasm_funcptr); + } + WR_FIELD(wasm_act, old_wasm_funcptr, FuncPtr_t); + WR_FIELD(wasm_act, act->flags, unsigned long); + WR_FIELD(wasm_act, act->restorer, FuncPtr_t); + WR_FIELD_ARRAY(wasm_act, act->mask, unsigned, 2); +} + +/* Copy sigaction to native: Function pointers are padded */ +extern inline struct k_sigaction* copy_ksigaction (wasm_exec_env_t exec_env, Addr wasm_act, + struct k_sigaction *act, void (*common_handler)(int), + FuncPtr_t *target_wasm_funcptr, char* debug_str) { + if (wasm_act == NULL) { return NULL; } + + FuncPtr_t wasm_handler_funcptr = RD_FIELD(wasm_act, FuncPtr_t); + if ( wasm_handler_funcptr == (FuncPtr_t)(WASM_SIG_DFL) ) { + act->handler = SIG_DFL; + strcpy(debug_str, "SIG_DFL"); + } else if (wasm_handler_funcptr == (FuncPtr_t)(WASM_SIG_IGN)) { + act->handler = SIG_IGN; + strcpy(debug_str, "SIG_IGN"); + } else if (wasm_handler_funcptr == (FuncPtr_t)(WASM_SIG_ERR)) { + act->handler = SIG_ERR; + strcpy(debug_str, "SIG_ERR"); + } else { + /* Setup common handler */ + act->handler = common_handler; + *target_wasm_funcptr = wasm_handler_funcptr; + strcpy(debug_str, "Wasm SIG"); + } + + act->flags = RD_FIELD(wasm_act, unsigned long); + + RD_FIELD(wasm_act, FuncPtr_t); + act->restorer = __libc_restore_rt; + + RD_FIELD_ARRAY(act->mask, wasm_act, unsigned, 2); + return act; +} + +/* Copy sigstack structure */ +extern inline stack_t* copy_sigstack (wasm_exec_env_t exec_env, Addr wasm_sigstack, + stack_t* ss) { + if (!wasm_sigstack) { return NULL; } + ss->ss_sp = RD_FIELD_ADDR(wasm_sigstack); + ss->ss_flags = RD_FIELD(wasm_sigstack, int); + ss->ss_size = RD_FIELD(wasm_sigstack, uint32_t); + return ss; +} + +/* Copy array of strings (strings are not malloced)*/ +extern inline char** copy_stringarr (wasm_exec_env_t exec_env, Addr wasm_arr) { + if (!wasm_arr) { return NULL; } + int num_strings = 0; + /* Find num elems */ + Addr arr_it = wasm_arr; + char *str; + while ((str = (char*)RD_FIELD_ADDR(arr_it))) { + num_strings++; + } + char **stringarr = (char**) malloc((num_strings+1) * sizeof(char*)); + for (int i = 0; i < num_strings; i++) { + stringarr[i] = (char*)RD_FIELD_ADDR(wasm_arr); + } + stringarr[num_strings] = NULL; + return stringarr; +} + + +extern _Noreturn void __libc_longjmp_asm(__libc_sigjmp_buf, int); +extern int __libc_sigsetjmp_asm(__libc_sigjmp_buf, int); +#define __libc_siglongjmp __libc_longjmp_asm + +/* Copy jmpbuf struct to WASM for setjmp */ +extern inline void copy2wasm_jmp_buf (wasm_exec_env_t exec_env, Addr wasm_buf, struct __libc_jmp_buf_tag* buf) { + WR_FIELD_ARRAY(wasm_buf, buf->__jb, unsigned long, 8); + WR_FIELD(wasm_buf, buf->__fl, unsigned long); + WR_FIELD_ARRAY(wasm_buf, buf->__ss, unsigned long, (128/sizeof(long))); +} + +/* Copy jmpbuf struct to native for setjmp */ +extern inline struct __libc_jmp_buf_tag* copy_jmp_buf (wasm_exec_env_t exec_env, Addr wasm_jmp_buf) { + if (!wasm_jmp_buf) { return NULL; } + struct __libc_jmp_buf_tag* buf = (struct __libc_jmp_buf_tag *) malloc(sizeof(struct __libc_jmp_buf_tag)); + RD_FIELD_ARRAY(buf->__jb, wasm_jmp_buf, unsigned long, 8); + buf->__fl = RD_FIELD(wasm_jmp_buf, unsigned long); + RD_FIELD_ARRAY(buf->__ss, wasm_jmp_buf, unsigned long, (128/sizeof(long))); + return buf; +} + + + +/** Architecture-specific copies **/ +#if __has_include("copy_arch.h") +#include "copy_arch.h" +#endif + +#endif diff --git a/core/iwasm/libraries/libc-wali/libc_wali.cmake b/core/iwasm/libraries/libc-wali/libc_wali.cmake new file mode 100644 index 0000000000..9041387e59 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/libc_wali.cmake @@ -0,0 +1,19 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (LIBC_WALI_DIR ${CMAKE_CURRENT_LIST_DIR}) +set (ARCH ${CMAKE_SYSTEM_PROCESSOR}) + +add_definitions (-DWASM_ENABLE_LIBC_WALI=1) + +include_directories(${LIBC_WALI_DIR}/wali_arch/${ARCH}) + +# Compile flags +add_compile_definitions(WALI_ENABLE_SYSCALL_PROFILE=0) +add_compile_definitions(WALI_ENABLE_NATIVE_SYSCALL_PROFILE=0) + +# Setup files to compile +file (GLOB_RECURSE wali_arch_sources ${LIBC_WALI_DIR}/wali_arch/${ARCH}/*.s ${LIBC_WALI_DIR}/wali_arch/*.c) +set (WALI_SOURCES ${LIBC_WALI_DIR}/wali.c ${wali_arch_sources}) + +set (LIBC_WALI_SOURCE ${WALI_SOURCES}) diff --git a/core/iwasm/libraries/libc-wali/wali.c b/core/iwasm/libraries/libc-wali/wali.c new file mode 100644 index 0000000000..96ff4c75fa --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali.c @@ -0,0 +1,1901 @@ +/* + MIT License + + Copyright (c) [2023] [Arjun Ramesh] + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include + +#include "wali.h" +#include "copy.h" +#include "../interpreter/wasm_runtime.h" +#include "thread_manager.h" + +#include "syscall.h" + + +/* For startup environment */ +int wali_app_argc; +char **wali_app_argv; +char *wali_app_env_file; +bool invoked_wali; + + +/* For WALI syscall stats */ +#define MAX_SYSCALLS 500 +typedef struct { + int64_t vt_count; + int64_t vt_time; + int64_t nt_count; + int64_t nt_time; +} sysmetric_t; + +int64_t total_wali_time = 0; +int64_t total_native_time = 0; + +static pthread_mutex_t metrics_lock = PTHREAD_MUTEX_INITIALIZER; +sysmetric_t syscall_metrics[MAX_SYSCALLS] = {{0}}; + +/* For thread cloning TID synchronization */ +static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mmap_lock = PTHREAD_MUTEX_INITIALIZER; +static sem_t tid_sem; + +volatile int signalled_tid = -1; + + +/* WALI State */ +uint32_t NATIVE_PAGESIZE = 0; +int MMAP_PAGELEN = 0; +int WASM_PAGELEN = 0; +int WASM_TO_NATIVE_PAGE = 0; +uint32_t BASE_MEMSIZE = 0; +uint32_t THREAD_ID = 0; // unused irl + + +inline void gettime(struct timespec *ts) { + clock_gettime(CLOCK_MONOTONIC_RAW, ts); +} +inline void gettimethread(struct timespec *ts) { + clock_gettime(CLOCK_THREAD_CPUTIME_ID, ts); +} +inline int64_t timediff(struct timespec *tstart, struct timespec *tend) { + int64_t timed = ((int64_t)tend->tv_sec - (int64_t)tstart->tv_sec) * 1000000000ull + \ + ((int64_t)tend->tv_nsec - (int64_t)tstart->tv_nsec); + return timed; +} + +/** Miscellaneous Callbacks **/ +wasm_module_inst_t main_mod_inst = NULL; + +void wali_memory_profile_dump(int signo) { + wasm_runtime_dump_mem_consumption(wasm_runtime_get_exec_env_singleton(main_mod_inst)); +} +void wali_syscall_profile_dump(int signo) { + printf("Save WALI syscall metrics\n"); + pthread_mutex_lock(&metrics_lock); + FILE *f = fopen("wali_syscalls.profile", "w"); + for (int i = 0; i < (MAX_SYSCALLS-1); i++) { + fprintf(f, "%ld:%ld/%ld,", syscall_metrics[i].vt_count, syscall_metrics[i].nt_time, syscall_metrics[i].vt_time); + } + fprintf(f, "%d:%d/%d", 0, 0, 0); + pthread_mutex_unlock(&metrics_lock); +} + +/* Dummy callback to be invoked after termination flags are set +* for all threads in process */ +void wali_terminate_process_sighandler(int signo) { + VB("WALI termination handler called by process %d", getpid()); +} +/** **/ + + +/* Startup init */ +void wali_init_native(wasm_module_inst_t module_inst) { + if (sem_init(&tid_sem, 0, 0)) { + perror("sem_init"); + } + + main_mod_inst = module_inst; + + // Register signals for profiling / termination + struct sigaction act = {0}; +#if WASM_ENABLE_MEMORY_PROFILING + act.sa_handler = wali_memory_profile_dump; + sigemptyset (&act.sa_mask); + if (sigaction(SIG_MEM_PROF, &act, NULL) == -1) { + perror("Could not install WALI memory prof signal\n"); + exit(1); + } +#endif +#if WALI_ENABLE_SYSCALL_PROFILE + act.sa_handler = wali_syscall_profile_dump; + if (sigaction(SIG_SYSCALL_PROF, &act, NULL) == -1) { + perror("Could not install WALI syscall prof signal\n"); + exit(1); + } +#endif + + act.sa_handler = wali_terminate_process_sighandler; + if (sigaction(SIG_WASM_THREAD_TERM, &act, NULL) == -1) { + perror("Could not install WALI termination signal\n"); + exit(1); + } + + + NATIVE_PAGESIZE = sysconf(_SC_PAGE_SIZE); + MMAP_PAGELEN = 0; + WASM_PAGELEN = 0; + WASM_TO_NATIVE_PAGE = WASM_PAGESIZE / NATIVE_PAGESIZE; + // Set in mmap + BASE_MEMSIZE = 0; + THREAD_ID = 1; +} + + + +/* Get page aligned address after memory to mmap; since base is mapped it's already aligned, +* and memory data size is a multiple of 64kB but rounding added for safety */ +#define PA_ALIGN_MMAP_ADDR() ({ \ + Addr base = BASE_ADDR(); \ + Addr punalign = base + wasm_runtime_get_base_memory_size(get_module_inst(exec_env)); \ + long pageoff = (long)(punalign) & (NATIVE_PAGESIZE - 1); \ + Addr palign = punalign - pageoff; \ + if (pageoff) { palign += NATIVE_PAGESIZE; } \ + palign; \ +}) + + + +static __thread volatile int64_t nsys_exectime = 0; +#if WALI_ENABLE_SYSCALL_PROFILE +#if WALI_ENABLE_NATIVE_SYSCALL_PROFILE +#define NATIVE_TIME(code) ({ \ + struct timespec nt_tstart={0,0}; \ + struct timespec nt_tend={0,0}; \ + gettime(&nt_tstart); \ + long rv = code; \ + gettime(&nt_tend); \ + nsys_exectime = timediff(&nt_tstart, &nt_tend); \ + rv; \ +}) +#else /* WALI_ENABLE_NATIVE_SYSCALL_PROFILE = 0 */ +#define NATIVE_TIME(code) code +#endif +#else /* WALI_ENABLE_SYSCALL_PROFILE = 0 */ +#define NATIVE_TIME(code) code +#endif + + +#define __syscall0(n) NATIVE_TIME(__syscall0(n)) +#define __syscall1(n, a1) NATIVE_TIME(__syscall1(n, (long)a1)) +#define __syscall2(n, a1, a2) NATIVE_TIME(__syscall2(n, (long)a1, (long)a2)) +#define __syscall3(n, a1, a2, a3) NATIVE_TIME(__syscall3(n, (long)a1, (long)a2, (long)a3)) +#define __syscall4(n, a1, a2, a3, a4) NATIVE_TIME(__syscall4(n, (long)a1, (long)a2, (long)a3, (long)a4)) +#define __syscall5(n, a1, a2, a3, a4, a5) NATIVE_TIME(__syscall5(n, (long)a1, (long)a2, (long)a3, (long)a4, (long)a5)) +#define __syscall6(n, a1, a2, a3, a4, a5, a6) NATIVE_TIME(__syscall6(n, (long)a1, (long)a2, (long)a3, (long)a4, (long)a5, (long)a6)) + + +#define PC(f) LOG_VERBOSE("[%d] WALI: | " # f, gettid()) + +#if WALI_ENABLE_SYSCALL_PROFILE + +#define SC(nr, f) \ + int scno = nr; \ + struct timespec vt_tstart={0,0}; \ + gettime(&vt_tstart); + +#define RETURN(v) { \ + long frv = v; \ + struct timespec vt_tend={0,0}; \ + gettime(&vt_tend); \ + int64_t virtsys_exectime = timediff(&vt_tstart, &vt_tend); \ + pthread_mutex_lock(&metrics_lock); \ + syscall_metrics[scno].vt_time += ((virtsys_exectime - syscall_metrics[scno].vt_time) / (syscall_metrics[scno].vt_count+1)); \ + syscall_metrics[scno].vt_count++; \ + syscall_metrics[scno].nt_time += ((nsys_exectime - syscall_metrics[scno].nt_time) / (syscall_metrics[scno].nt_count+1)); \ + syscall_metrics[scno].nt_count++; \ + total_native_time += nsys_exectime; \ + total_wali_time += (virtsys_exectime - nsys_exectime); \ + pthread_mutex_unlock(&metrics_lock); \ + return frv; \ + } + +#define FIN_TIME() { \ + struct timespec vt_tend={0,0}; \ + gettime(&vt_tend); \ + int64_t virtsys_exectime = timediff(&vt_tstart, &vt_tend); \ + pthread_mutex_lock(&metrics_lock); \ + syscall_metrics[scno].vt_time += ((virtsys_exectime - syscall_metrics[scno].vt_time) / (syscall_metrics[scno].vt_count+1)); \ + syscall_metrics[scno].vt_count++; \ + syscall_metrics[scno].nt_time += ((nsys_exectime - syscall_metrics[scno].nt_time) / (syscall_metrics[scno].nt_count+1)); \ + syscall_metrics[scno].nt_count++; \ + pthread_mutex_unlock(&metrics_lock); \ + } + +#else /* WALI_ENABLE_SYSCALL_PROFILE = 0 */ +#define SC(nr, f) LOG_VERBOSE("[%d] WALI: SC | " # f, gettid()); +#define RETURN(v) return v; +#endif + +#define ERRSC(f,...) { \ + LOG_ERROR("[%d] WALI: SC \"" # f "\" not implemented correctly yet! " __VA_ARGS__, gettid()); \ +} +#define FATALSC(f,...) { \ + LOG_FATAL("[%d] WALI: SC \"" # f "\" fatal error! " __VA_ARGS__, gettid()); \ +} +#define MISSC(f,...) { \ + LOG_FATAL("[%d] WALI: SC \"" # f "\" fatal error! No such syscall on platform", gettid()); \ +} + +static void wali_thread_exit (wasm_exec_env_t exec_env, long v); + +/***** WALI Methods *******/ +// 0 +long wali_syscall_read (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(0,read); + RETURN(__syscall3(SYS_read, a1, MADDR(a2), a3)); +} + +// 1 +long wali_syscall_write (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(1,write); + RETURN(__syscall3(SYS_write, a1, MADDR(a2), a3)); +} + +// 2 +long wali_syscall_open (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(2,open); + #if __x86_64__ + RETURN(__syscall3(SYS_open, MADDR(a1), a2, a3)); + #elif __aarch64__ + RETURN(wali_syscall_openat(exec_env, AT_FDCWD, a1, a2, a3)); + #elif __riscv64__ + RETURN(wali_syscall_openat(exec_env, AT_FDCWD, a1, a2, a3)); + #endif +} + +// 3 +long wali_syscall_close (wasm_exec_env_t exec_env, long a1) { + SC(3,close); + RETURN(__syscall1(SYS_close, a1)); +} + +// 4 +long wali_syscall_stat (wasm_exec_env_t exec_env, long a1, long a2) { + SC(4 ,stat); + #if __x86_64__ + RETURN(__syscall2(SYS_stat, MADDR(a1), MADDR(a2))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_fstatat(exec_env, AT_FDCWD, a1, a2, 0)); + #endif +} + +// 5 +long wali_syscall_fstat (wasm_exec_env_t exec_env, long a1, long a2) { + SC(5 ,fstat); + RETURN(__syscall2(SYS_fstat, a1, MADDR(a2))); +} + +// 6 +long wali_syscall_lstat (wasm_exec_env_t exec_env, long a1, long a2) { + SC(6 ,lstat); + #if __x86_64__ + RETURN(__syscall2(SYS_lstat, MADDR(a1), MADDR(a2))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_fstatat (exec_env, AT_FDCWD, a1, a2, AT_SYMLINK_NOFOLLOW)); + #endif +} + +#define CONV_TIME_TO_TS(x) ( (x>=0) ? &((struct timespec){.tv_sec = x/1000, .tv_nsec = (x%1000)*1000000}) : 0 ) +// 7 +long wali_syscall_poll (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(7 ,poll); + #if __x86_64__ + RETURN(__syscall3(SYS_poll, MADDR(a1), a2, a3)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_ppoll_aliased(exec_env, a1, a2, (long)CONV_TIME_TO_TS(a3), 0, _NSIG/8)); + #endif +} + +// 8 +long wali_syscall_lseek (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(8 ,lseek); + RETURN(__syscall3(SYS_lseek, a1, a2, a3)); +} + + +// 9 +long wali_syscall_mmap (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6) { + SC(9 ,mmap); + VB("mmap args | a1: %ld, a2: 0x%x, a3: %ld, a4: %ld, a5: %ld, a6: %ld | MMAP_PAGELEN: %d", a1, a2, a3, a4, a5, a6, MMAP_PAGELEN); + pthread_mutex_lock(&mmap_lock); + Addr base_addr = BASE_ADDR(); + Addr pa_aligned_addr = PA_ALIGN_MMAP_ADDR(); + Addr mmap_addr = pa_aligned_addr + MMAP_PAGELEN * NATIVE_PAGESIZE; + + uint32 mem_size = wasm_runtime_get_memory_size(get_module_inst(exec_env)); + VB("Mem Base: %p | Mem End: %p | Mem Size: 0x%x | Mmap Addr: %p", base_addr, base_addr + mem_size, mem_size, mmap_addr); + + wasm_module_inst_t module = get_module_inst(exec_env); + int inc_wasm_pages = 0; + int num_pages = ((a2 + NATIVE_PAGESIZE - 1) / NATIVE_PAGESIZE); + int extended_mmap_pagelen = MMAP_PAGELEN + num_pages; + /* Check if wasm memory needs to be expanded and it is safe */ + if (extended_mmap_pagelen > WASM_PAGELEN * WASM_TO_NATIVE_PAGE) { + int new_wasm_pagelen = ((extended_mmap_pagelen + WASM_TO_NATIVE_PAGE - 1) / WASM_TO_NATIVE_PAGE); + inc_wasm_pages = new_wasm_pagelen - WASM_PAGELEN; + if (!wasm_can_enlarge_memory((WASMModuleInstance*)module, inc_wasm_pages)) { + FATALSC(mmap, "Out of memory!\n"); + goto mmap_fail; + } + } + + Addr mem_addr = (Addr) __syscall6(SYS_mmap, mmap_addr, a2, a3, MAP_FIXED|a4, a5, a6); + /* Sometimes mmap returns -9 instead of MAP_FAILED? */ + if ((mem_addr == MAP_FAILED) || (mem_addr == (void*)(-9))) { + FATALSC(mmap, "Failed to mmap!\n"); + goto mmap_fail; + } + /* On success */ + else { + MMAP_PAGELEN += num_pages; + /* Expand wasm memory if needed */ + if (inc_wasm_pages) { + wasm_enlarge_memory((WASMModuleInstance*)module, inc_wasm_pages, true); + WASM_PAGELEN += inc_wasm_pages; + } + } + long retval = WADDR(mem_addr); + VB("New MMAP Pagelen: %d\n", MMAP_PAGELEN); + pthread_mutex_unlock(&mmap_lock); + VB("Ret Addr: 0x%x", retval); + RETURN(retval); + +mmap_fail: + pthread_mutex_unlock(&mmap_lock); + RETURN((long) MAP_FAILED); +} + +// 10 +long wali_syscall_mprotect (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(10,mprotect); + RETURN(__syscall3(SYS_mprotect, MADDR(a1), a2, a3)); +} + +// 11 +long wali_syscall_munmap (wasm_exec_env_t exec_env, long a1, long a2) { + SC(11 ,munmap); + pthread_mutex_lock(&mmap_lock); + Addr mmap_addr = MADDR(a1); + Addr mmap_addr_end = (Addr)(mmap_addr + a2); + /* Reclaim some mmap space if end region is unmapped */ + Addr pa_aligned_addr = PA_ALIGN_MMAP_ADDR(); + int end_page = (mmap_addr_end - pa_aligned_addr + NATIVE_PAGESIZE - 1) / NATIVE_PAGESIZE; + VB("End page: %d | MMAP_PAGELEN: %d", end_page, MMAP_PAGELEN); + if (end_page == MMAP_PAGELEN) { + MMAP_PAGELEN -= ((a2 + NATIVE_PAGESIZE - 1) / NATIVE_PAGESIZE); + VB("End page unmapped | New MMAP_PAGELEN: %d", MMAP_PAGELEN); + } + pthread_mutex_unlock(&mmap_lock); + RETURN(__syscall2(SYS_munmap, mmap_addr, a2)); +} + +// 12 +long wali_syscall_brk (wasm_exec_env_t exec_env, long a1) { + SC(12 ,brk); + VB("brk syscall is a NOP in WASM right now"); + return 0; + RETURN(0); +} + + +void sa_handler_wali(int signo) { + /* Mark pending signal */ + pthread_mutex_lock(&sigpending_mut); + wali_sigpending |= ((uint64_t)1 << signo); + pthread_mutex_unlock(&sigpending_mut); +} +// 13 +long wali_syscall_rt_sigaction (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(13 ,rt_sigaction); + VB("rt_sigaction args | a1: %ld, a2: %ld, a3: %ld, a4: %ld", a1, a2, a3, a4); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + int signo = a1; + Addr wasm_act = MADDR(a2); + Addr wasm_oldact = MADDR(a3); + struct k_sigaction act = {0}; + struct k_sigaction oldact = {0}; + + /* Block signal manipulation while setting up synchronized wali table */ + pthread_mutex_lock(&sigtable_mut); + FuncPtr_t target_wasm_funcptr = 0; + char sigtype[30]; + + /* Prepare for native signal syscall */ + struct k_sigaction *act_pt = + copy_ksigaction(exec_env, wasm_act, &act, sa_handler_wali, &target_wasm_funcptr, sigtype); + struct k_sigaction *oldact_pt = + wasm_oldact ? &oldact : NULL; + long retval = __syscall4(SYS_rt_sigaction, a1, act_pt, oldact_pt, a4); + + VB("Signal Registration -- \'%s\'(%d) | Sigtype: %s", strsignal(a1), signo, sigtype); + + /* Register virtual signal in WALI sigtable + * --------------------------------------------------------------- + * | Handler value | WALI sigtable (set) | Old Action (get) | + * --------------------------------------------------------------- + * | SIG_DFL | No register | WASM_SIG_DFL | + * | SIG_IGN | No register | WASM_SIG_IGN | + * | SIG_ERR | - | WASM_SIG_ERR | + * | FuncPtr_t | Table[FuncPtr_t] | Table[FuncPtr_t] | + * --------------------------------------------------------------- + * */ + if (!retval && (signo < NSIG)) { + /* Save old sigaction to WASM */ + if (oldact_pt) { + copy2wasm_old_ksigaction (signo, wasm_oldact, oldact_pt); + } + /* Set WALI table */ + if (act_pt && (act_pt->handler != SIG_DFL) && (act_pt->handler != SIG_IGN) && (act_pt->handler != SIG_ERR)) { + wasm_function_inst_t target_wasm_handler = wasm_runtime_get_indirect_function( + module_inst, 0, target_wasm_funcptr); + uint32_t old_fn_idx = wali_sigtable[signo].function ? FUNC_IDX(wali_sigtable[signo].function) : 0; + uint32_t new_fn_idx = target_wasm_handler ? FUNC_IDX(target_wasm_handler) : 0; + VB("Replacing target handler: Fn[%u] -> Fn[%u]\n", old_fn_idx, new_fn_idx); + FUNC_FREE(wali_sigtable[signo].function); + wali_sigtable[signo].function = target_wasm_handler; + wali_sigtable[signo].func_table_idx = target_wasm_funcptr; + wali_sigtable[signo].func_idx = new_fn_idx; + } + } + /* Reset block signals */ + pthread_mutex_unlock(&sigtable_mut); + + RETURN(retval); +} + +// 14 +long wali_syscall_rt_sigprocmask (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(14 ,rt_sigprocmask); + RETURN(__syscall4(SYS_rt_sigprocmask, a1, MADDR(a2), MADDR(a3), a4)); +} + +// 15: Never directly called; __libc_restore_rt is called by OS +long wali_syscall_rt_sigreturn (wasm_exec_env_t exec_env, long a1) { + SC(15,rt_sigreturn); + ERRSC(rt_sigreturn, "rt_sigreturn should never be called by the user!"); + RETURN(-1); +} + +// 16 +long wali_syscall_ioctl (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(16 ,ioctl); + RETURN(__syscall3(SYS_ioctl, a1, a2, MADDR(a3))); +} + +// 17 TODO +long wali_syscall_pread64 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(17 ,pread64); + ERRSC(pread64); + RETURN(__syscall4(SYS_pread64, a1, MADDR(a2), a3, a4)); +} + +// 18 TODO +long wali_syscall_pwrite64 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(18 ,pwrite64); + ERRSC(pwrite64); + RETURN(__syscall4(SYS_pwrite64, a1, MADDR(a2), a3, a4)); +} + +// 19 +long wali_syscall_readv (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(19 ,readv); + Addr wasm_iov = MADDR(a2); + int iov_cnt = a3; + + struct iovec *native_iov = copy_iovec(exec_env, wasm_iov, iov_cnt); + long retval = __syscall3(SYS_readv, a1, native_iov, a3); + free(native_iov); + + RETURN(retval); +} + +// 20 +long wali_syscall_writev (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(20 ,writev); + Addr wasm_iov = MADDR(a2); + int iov_cnt = a3; + + struct iovec *native_iov = copy_iovec(exec_env, wasm_iov, iov_cnt); + long retval = __syscall3(SYS_writev, a1, native_iov, a3); + free(native_iov); + RETURN(retval); +} + +// 21 +long wali_syscall_access (wasm_exec_env_t exec_env, long a1, long a2) { + SC(21 ,access); + #if __x86_64__ + RETURN(__syscall2(SYS_access, MADDR(a1), a2)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_faccessat(exec_env, AT_FDCWD, a1, a2, 0)); + #endif +} + +// 22 +long wali_syscall_pipe (wasm_exec_env_t exec_env, long a1) { + SC(22 ,pipe); + #if __x86_64__ + RETURN(__syscall1(SYS_pipe, MADDR(a1))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_pipe2(exec_env, a1, 0)); + #endif +} + +// 23 +long wali_syscall_select (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(23 ,select); + #if __x86_64__ + RETURN(__syscall5(SYS_select, a1, MADDR(a2), MADDR(a3), MADDR(a4), MADDR(a5))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_pselect6(exec_env, a1, a2, a3, a4, a5, (long)((long[]){0, _NSIG/8}))); + #endif +} + +// 24 +long wali_syscall_sched_yield (wasm_exec_env_t exec_env) { + SC(24 ,sched_yield); + RETURN(__syscall0(SYS_sched_yield)); +} + +// 25 +long wali_syscall_mremap (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(25 ,mremap); + VB("mremap args | a1: %ld, a2: 0x%x, a3: 0x%x, a4: %ld, a5: %ld | MMAP_PAGELEN: %d", a1, a2, a3, a4, a5, MMAP_PAGELEN); + /* Remap pages to the end of the wasm memory, like mmap */ + pthread_mutex_lock(&mmap_lock); + Addr base_addr = BASE_ADDR(); + Addr pa_aligned_addr = PA_ALIGN_MMAP_ADDR(); + Addr mmap_addr = pa_aligned_addr + MMAP_PAGELEN * NATIVE_PAGESIZE; + + uint32 mem_size = wasm_runtime_get_memory_size(get_module_inst(exec_env)); + VB("Mem Base: %p | Mem End: %p | Mem Size: 0x%x | Mmap Addr: %p", base_addr, base_addr + mem_size, mem_size, mmap_addr); + + wasm_module_inst_t module = get_module_inst(exec_env); + int inc_wasm_pages = 0; + int num_pages = ((a3 + NATIVE_PAGESIZE - 1) / NATIVE_PAGESIZE); + int extended_mmap_pagelen = MMAP_PAGELEN + num_pages; + /* Check if wasm memory needs to be expanded and it is safe */ + if (extended_mmap_pagelen > WASM_PAGELEN * WASM_TO_NATIVE_PAGE) { + int new_wasm_pagelen = ((extended_mmap_pagelen + WASM_TO_NATIVE_PAGE - 1) / WASM_TO_NATIVE_PAGE); + inc_wasm_pages = new_wasm_pagelen - WASM_PAGELEN; + if (!wasm_can_enlarge_memory((WASMModuleInstance*)module, inc_wasm_pages)) { + FATALSC(mremap, "Out of memory!\n"); + goto mremap_fail; + } + } + + Addr mem_addr = (Addr) __syscall5(SYS_mremap, MADDR(a1), a2, a3, MREMAP_MAYMOVE|MREMAP_FIXED, mmap_addr); + VB("Mem Addr: %p\n", mem_addr); + /* Sometimes mremap returns -9 instead of MAP_FAILED? */ + if ((mem_addr == MAP_FAILED) || (mem_addr == (void*)(-9))) { + FATALSC(mremap, "Failed to mremap!\n"); + goto mremap_fail; + } + /* On success */ + else { + MMAP_PAGELEN += num_pages; + /* Expand wasm memory if needed */ + if (inc_wasm_pages) { + wasm_enlarge_memory((WASMModuleInstance*)module, inc_wasm_pages, true); + WASM_PAGELEN += inc_wasm_pages; + } + } + long retval = WADDR(mem_addr); + VB("New MMAP Pagelen: %d\n", MMAP_PAGELEN); + pthread_mutex_unlock(&mmap_lock); + VB("Ret Addr: 0x%x", retval); + RETURN(retval); + +mremap_fail: + pthread_mutex_unlock(&mmap_lock); + RETURN((long) MAP_FAILED); +} + +// 26 +long wali_syscall_msync (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(26 ,msync); + RETURN(__syscall3(SYS_msync, MADDR(a1), a2, a3)); +} + +// 28 +long wali_syscall_madvise (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(28 ,madvise); + RETURN(__syscall3(SYS_madvise, MADDR(a1), a2, a3)); +} + +// 32 +long wali_syscall_dup (wasm_exec_env_t exec_env, long a1) { + SC(32 ,dup); + RETURN(__syscall1(SYS_dup, a1)); +} + +// 33 +long wali_syscall_dup2 (wasm_exec_env_t exec_env, long a1, long a2) { + SC(33 ,dup2); + #if __x86_64__ + RETURN(__syscall2(SYS_dup2, a1, a2)); + #elif __aarch64__ || __riscv64__ + /* Dup2 returns newfd while dup3 throws error, handle with case below */ + if (a1 == a2) { + long r = wali_syscall_fcntl(exec_env, a1, F_GETFD, 0); + RETURN((r >= 0) ? a2 : r); + } else { + RETURN(wali_syscall_dup3(exec_env, a1, a2, 0)); + } + #endif +} + +// 35 +long wali_syscall_nanosleep (wasm_exec_env_t exec_env, long a1, long a2) { + SC(35,nanosleep); + RETURN(__syscall2(SYS_nanosleep, MADDR(a1), MADDR(a2))); +} + +// 37 +long wali_syscall_alarm (wasm_exec_env_t exec_env, long a1) { + SC(37 ,alarm); + #if __x86_64__ + RETURN(__syscall1(SYS_alarm, a1)); + #elif __aarch64__ || __riscv64__ + MISSC(alarm); + wali_proc_exit(exec_env, 1); + #endif +} + +// 38 +long wali_syscall_setitimer (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(38 ,setitimer); + RETURN(__syscall3(SYS_setitimer, a1, MADDR(a2), MADDR(a3))); +} + +// 39 +long wali_syscall_getpid (wasm_exec_env_t exec_env) { + SC(39 ,getpid); + RETURN(__syscall0(SYS_getpid)); +} + +// 41 +long wali_syscall_socket (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(41 ,socket); + RETURN(__syscall3(SYS_socket, a1, a2, a3)); +} + +// 42 +long wali_syscall_connect (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(42 ,connect); + RETURN(__syscall3(SYS_connect, a1, MADDR(a2), a3)); +} + +// 43 +long wali_syscall_accept (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(43 ,accept); + RETURN(__syscall3(SYS_accept, a1, MADDR(a2), MADDR(a3))); +} + +// 44 +long wali_syscall_sendto (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6) { + SC(44 ,sendto); + RETURN(__syscall6(SYS_sendto, a1, MADDR(a2), a3, a4, MADDR(a5), a6)); +} + +// 45 +long wali_syscall_recvfrom (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6) { + SC(45 ,recvfrom); + RETURN(__syscall6(SYS_recvfrom, a1, MADDR(a2), a3, a4, MADDR(a5), MADDR(a6))); +} + +// 46 +long wali_syscall_sendmsg (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(46 ,sendmsg); + Addr wasm_msghdr = MADDR(a2); + struct msghdr *native_msghdr = copy_msghdr(exec_env, wasm_msghdr); + long retval = __syscall3(SYS_sendmsg, a1, native_msghdr, a3); + free(native_msghdr); + RETURN(retval); +} + +// 47 +long wali_syscall_recvmsg (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(47 ,recvmsg); + Addr wasm_msghdr = MADDR(a2); + struct msghdr *native_msghdr = copy_msghdr(exec_env, wasm_msghdr); + long retval = __syscall3(SYS_recvmsg, a1, native_msghdr, a3); + free(native_msghdr); + RETURN(retval); +} + +// 48 +long wali_syscall_shutdown (wasm_exec_env_t exec_env, long a1, long a2) { + SC(48 ,shutdown); + RETURN(__syscall2(SYS_shutdown, a1, a2)); +} + +// 49 +long wali_syscall_bind (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(49 ,bind); + RETURN(__syscall3(SYS_bind, a1, MADDR(a2), a3)); +} + +// 50 +long wali_syscall_listen (wasm_exec_env_t exec_env, long a1, long a2) { + SC(50 ,listen); + RETURN(__syscall2(SYS_listen, a1, a2)); +} + +// 51 +long wali_syscall_getsockname (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(51 ,getsockname); + RETURN(__syscall3(SYS_getsockname, a1, MADDR(a2), MADDR(a3))); +} + +// 52 +long wali_syscall_getpeername (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(52 ,getpeername); + RETURN(__syscall3(SYS_getpeername, a1, MADDR(a2), MADDR(a3))); +} + +// 53 +long wali_syscall_socketpair (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(53 ,socketpair); + RETURN(__syscall4(SYS_socketpair, a1, a2, a3, MADDR(a4))); +} + +// 54 +long wali_syscall_setsockopt (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(54 ,setsockopt); + RETURN(__syscall5(SYS_setsockopt, a1, a2, a3, MADDR(a4), a5)); +} + +// 55 +long wali_syscall_getsockopt (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(55 ,getsockopt); + RETURN(__syscall5(SYS_getsockopt, a1, a2, a3, MADDR(a4), MADDR(a5))); +} + +// 57 +long wali_syscall_fork (wasm_exec_env_t exec_env) { + SC(57,fork); + #if __x86_64__ + RETURN(__syscall0(SYS_fork)); + #elif __aarch64__ || __riscv64__ + RETURN(__syscall2(SYS_clone, SIGCHLD, 0)); + #endif +} + +void create_pass_env_file(char **envp) { + char filename[100]; + sprintf(filename, "/tmp/wali_env.%d", getpid()); + FILE *fp = fopen(filename, "w"); + for (char **e = envp; *e; e++) { + fprintf(fp, "%s\n", *e); + } + fclose(fp); +} +// 59 +long wali_syscall_execve (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(59 ,execve); + VB("Execve string: %s\n", MADDR(a1)); + char** argv = copy_stringarr (exec_env, MADDR(a2)); + char** argpt = argv; + int i = 0; + while (*argpt != NULL) { + VB("Argv[%d] : %s\n", i, *argpt); + argpt++; + i++; + } + char** envp = copy_stringarr (exec_env, MADDR(a3)); + /* For child WALI processes: Pass env through temporary file-descriptor that is read on init + * For child native processes: envp is passed through the syscall invocation */ + if (envp) { + create_pass_env_file(envp); + } + long retval = __syscall3(SYS_execve, MADDR(a1), argv, envp); + free(argv); + free(envp); + RETURN(retval); +} + +// 60 TODO +long wali_syscall_exit (wasm_exec_env_t exec_env, long a1) { + SC(60 ,exit); + ERRSC(exit); + wali_thread_exit(exec_env, a1); + return 0; +} + +// 61 +long wali_syscall_wait4 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(61 ,wait4); + RETURN(__syscall4(SYS_wait4, a1, MADDR(a2), a3, MADDR(a4))); +} + +// 62 +long wali_syscall_kill (wasm_exec_env_t exec_env, long a1, long a2) { + SC(62 ,kill); + RETURN(__syscall2(SYS_kill, a1, a2)); +} + +// 63 +long wali_syscall_uname (wasm_exec_env_t exec_env, long a1) { + SC(63 ,uname); + RETURN(__syscall1(SYS_uname, MADDR(a1))); +} + +// 72 +long wali_syscall_fcntl (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(72 ,fcntl); + /* Swap open flags only on F_GETFL and F_SETFL mode for aarch64 */ + #if __aarch64__ + switch (a2) { + case F_GETFL: RETURN(swap_open_flags(__syscall3(SYS_fcntl, a1, a2, a3)); break); + case F_SETFL: RETURN(__syscall3(SYS_fcntl, a1, a2, swap_open_flags(a3)); break); + default: RETURN(__syscall3(SYS_fcntl, a1, a2, a3)); + } + #else + RETURN(__syscall3(SYS_fcntl, a1, a2, a3)); + #endif +} + +// 73 +long wali_syscall_flock (wasm_exec_env_t exec_env, long a1, long a2) { + SC(73 ,flock); + RETURN(__syscall2(SYS_flock, a1, a2)); +} + +// 74 +long wali_syscall_fsync (wasm_exec_env_t exec_env, long a1) { + SC(74 ,fsync); + RETURN(__syscall1(SYS_fsync, a1)); +} + +// 75 +long wali_syscall_fdatasync (wasm_exec_env_t exec_env, long a1) { + SC(75 ,fdatasync); + RETURN(__syscall1(SYS_fdatasync, a1)); +} + +// 77 +long wali_syscall_ftruncate (wasm_exec_env_t exec_env, long a1, long a2) { + SC(77 ,ftruncate); + RETURN(__syscall2(SYS_ftruncate, a1, a2)); +} + +// 78 +long wali_syscall_getdents (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(78 ,getdents); + FATALSC(getdents, "Not going to support this legacy call; use getdents64"); + #if __x86_64__ + RETURN(__syscall3(SYS_getdents, a1, MADDR(a2), a3)); + #elif __aarch64__ || __riscv64__ + RETURN(-1); + #endif +} + +// 79 +long wali_syscall_getcwd (wasm_exec_env_t exec_env, long a1, long a2) { + SC(79,getcwd); + RETURN(__syscall2(SYS_getcwd, MADDR(a1), a2)); +} + +// 80 +long wali_syscall_chdir (wasm_exec_env_t exec_env, long a1) { + SC(80,chdir); + RETURN(__syscall1(SYS_chdir, MADDR(a1))); +} + +// 81 +long wali_syscall_fchdir (wasm_exec_env_t exec_env, long a1) { + SC(81 ,fchdir); + RETURN(__syscall1(SYS_fchdir, a1)); +} + +// 82 +long wali_syscall_rename (wasm_exec_env_t exec_env, long a1, long a2) { + SC(82,rename); + #if __x86_64__ + RETURN(__syscall2(SYS_rename, MADDR(a1), MADDR(a2))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_renameat2(exec_env, AT_FDCWD, a1, AT_FDCWD, a2, 0)); + #endif +} + +// 83 +long wali_syscall_mkdir (wasm_exec_env_t exec_env, long a1, long a2) { + SC(83,mkdir); + #if __x86_64__ + RETURN(__syscall2(SYS_mkdir, MADDR(a1), a2)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_mkdirat(exec_env, AT_FDCWD, a1, a2)); + #endif +} + +// 84 +long wali_syscall_rmdir (wasm_exec_env_t exec_env, long a1) { + SC(84 ,rmdir); + #if __x86_64__ + RETURN(__syscall1(SYS_rmdir, MADDR(a1))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_unlinkat(exec_env, AT_FDCWD, a1, AT_REMOVEDIR)); + #endif +} + +// 86 +long wali_syscall_link (wasm_exec_env_t exec_env, long a1, long a2) { + SC(86 ,link); + #if __x86_64__ + RETURN(__syscall2(SYS_link, MADDR(a1), MADDR(a2))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_linkat(exec_env, AT_FDCWD, a1, AT_FDCWD, a2, 0)); + #endif +} + +// 87 +long wali_syscall_unlink (wasm_exec_env_t exec_env, long a1) { + SC(87 ,unlink); + #if __x86_64__ + RETURN(__syscall1(SYS_unlink, MADDR(a1))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_unlinkat(exec_env, AT_FDCWD, a1, 0)); + #endif +} + +// 88 +long wali_syscall_symlink (wasm_exec_env_t exec_env, long a1, long a2) { + SC(88 ,symlink); + #if __x86_64__ + RETURN(__syscall2(SYS_symlink, MADDR(a1), MADDR(a2))); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_symlinkat(exec_env, a1, AT_FDCWD, a2)); + #endif +} + +// 89 +long wali_syscall_readlink (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(89 ,readlink); + #if __x86_64__ + RETURN(__syscall3(SYS_readlink, MADDR(a1), MADDR(a2), a3)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_readlinkat(exec_env, AT_FDCWD, a1, a2, a3)); + #endif +} + +// 90 +long wali_syscall_chmod (wasm_exec_env_t exec_env, long a1, long a2) { + SC(90 ,chmod); + #if __x86_64__ + RETURN(__syscall2(SYS_chmod, MADDR(a1), a2)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_fchmodat(exec_env, AT_FDCWD, a1, a2, 0)); + #endif +} + +// 91 +long wali_syscall_fchmod (wasm_exec_env_t exec_env, long a1, long a2) { + SC(91 ,fchmod); + RETURN(__syscall2(SYS_fchmod, a1, a2)); +} + +// 92 +long wali_syscall_chown (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(92 ,chown); + #if __x86_64__ + RETURN(__syscall3(SYS_chown, MADDR(a1), a2, a3)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_fchownat(exec_env, AT_FDCWD, a1, a2, a3, 0)); + #endif +} + +// 93 +long wali_syscall_fchown (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(93 ,fchown); + RETURN(__syscall3(SYS_fchown, a1, a2, a3)); +} + +// 95 +long wali_syscall_umask (wasm_exec_env_t exec_env, long a1) { + SC(95 ,umask); + RETURN(__syscall1(SYS_umask, a1)); +} + +// 97 +long wali_syscall_getrlimit (wasm_exec_env_t exec_env, long a1, long a2) { + SC(97 ,getrlimit); + RETURN(__syscall2(SYS_getrlimit, a1, MADDR(a2))); +} + +// 98 +long wali_syscall_getrusage (wasm_exec_env_t exec_env, long a1, long a2) { + SC(98 ,getrusage); + RETURN(__syscall2(SYS_getrusage, a1, MADDR(a2))); +} + +// 99 +long wali_syscall_sysinfo (wasm_exec_env_t exec_env, long a1) { + SC(99 ,sysinfo); + RETURN(__syscall1(SYS_sysinfo, MADDR(a1))); +} + +// 102 +long wali_syscall_getuid (wasm_exec_env_t exec_env) { + SC(102 ,getuid); + RETURN(__syscall0(SYS_getuid)); +} + +// 104 +long wali_syscall_getgid (wasm_exec_env_t exec_env) { + SC(104 ,getgid); + RETURN(__syscall0(SYS_getgid)); +} + +// 105 +long wali_syscall_setuid (wasm_exec_env_t exec_env, long a1) { + SC(105 ,setuid); + RETURN(__syscall1(SYS_setuid, a1)); +} + +// 106 +long wali_syscall_setgid (wasm_exec_env_t exec_env, long a1) { + SC(106 ,setgid); + RETURN(__syscall1(SYS_setgid, a1)); +} + +// 107 +long wali_syscall_geteuid (wasm_exec_env_t exec_env) { + SC(107 ,geteuid); + RETURN(__syscall0(SYS_geteuid)); +} + +// 108 +long wali_syscall_getegid (wasm_exec_env_t exec_env) { + SC(108 ,getegid); + RETURN(__syscall0(SYS_getegid)); +} + +// 109 +long wali_syscall_setpgid (wasm_exec_env_t exec_env, long a1, long a2) { + SC(109 ,setpgid); + RETURN(__syscall2(SYS_setpgid, a1, a2)); +} + +// 110 +long wali_syscall_getppid (wasm_exec_env_t exec_env) { + SC(110 ,getppid); + RETURN(__syscall0(SYS_getppid)); +} + +// 112 +long wali_syscall_setsid (wasm_exec_env_t exec_env) { + SC(112 ,setsid); + RETURN(__syscall0(SYS_setsid)); +} + +// 115 +long wali_syscall_getgroups (wasm_exec_env_t exec_env, long a1, long a2) { + SC(115 ,getgroups); + RETURN(__syscall2(SYS_getgroups, a1, MADDR(a2))); +} + +// 116 +long wali_syscall_setgroups (wasm_exec_env_t exec_env, long a1, long a2) { + SC(116 ,setgroups); + RETURN(__syscall2(SYS_setgroups, a1, MADDR(a2))); +} + +// 117 +long wali_syscall_setresuid (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(117 ,setresuid); + RETURN(__syscall3(SYS_setresuid, a1, a2, a3)); +} + +// 119 +long wali_syscall_setresgid (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(119 ,setresgid); + RETURN(__syscall3(SYS_setresgid, a1, a2, a3)); +} + +// 121 +long wali_syscall_getpgid (wasm_exec_env_t exec_env, long a1) { + SC(121 ,getpgid); + RETURN(__syscall1(SYS_getpgid, a1)); +} + +// 124 +long wali_syscall_getsid (wasm_exec_env_t exec_env, long a1) { + SC(124 ,getsid); + RETURN(__syscall1(SYS_getsid, a1)); +} + +// 127 +long wali_syscall_rt_sigpending (wasm_exec_env_t exec_env, long a1, long a2) { + SC(127 ,rt_sigpending); + RETURN(__syscall2(SYS_rt_sigpending, MADDR(a1), a2)); +} + +// 130 +long wali_syscall_rt_sigsuspend (wasm_exec_env_t exec_env, long a1, long a2) { + SC(130 ,rt_sigsuspend); + RETURN(__syscall2(SYS_rt_sigsuspend, MADDR(a1), a2)); +} + +// 131 +long wali_syscall_sigaltstack (wasm_exec_env_t exec_env, long a1, long a2) { + SC(131 ,sigaltstack); + Addr wasm_ss = MADDR(a1), wasm_old_ss = MADDR(a2); + + stack_t ss = {0}, old_ss = {0}; + stack_t* ss_ptr = copy_sigstack(exec_env, wasm_ss, &ss); + stack_t* old_ss_ptr = copy_sigstack(exec_env, wasm_old_ss, &old_ss); + + RETURN(__syscall2(SYS_sigaltstack, ss_ptr, old_ss_ptr)); +} + +// 132 +long wali_syscall_utime (wasm_exec_env_t exec_env, long a1, long a2) { + SC(132 ,utime); + FATALSC(utime, "Obsolete -- Use \'utimesnsat\' instead"); + #if __x86_64__ + #elif __aarch64__ || __riscv64__ + #endif + RETURN(-1); +} + +// 137 +long wali_syscall_statfs (wasm_exec_env_t exec_env, long a1, long a2) { + SC(137 ,statfs); + RETURN(__syscall2(SYS_statfs, MADDR(a1), MADDR(a2))); +} + +// 138 +long wali_syscall_fstatfs (wasm_exec_env_t exec_env, long a1, long a2) { + SC(138 ,fstatfs); + RETURN(__syscall2(SYS_fstatfs, a1, MADDR(a2))); +} + +// 160 +long wali_syscall_setrlimit (wasm_exec_env_t exec_env, long a1, long a2) { + SC(160 ,setrlimit); + RETURN(__syscall2(SYS_setrlimit, a1, MADDR(a2))); +} + +// 161 +long wali_syscall_chroot (wasm_exec_env_t exec_env, long a1) { + SC(161 ,chroot); + RETURN(__syscall1(SYS_chroot, MADDR(a1))); +} + +// 186 +long wali_syscall_gettid (wasm_exec_env_t exec_env) { + SC(186 ,gettid); + RETURN(__syscall0(SYS_gettid)); +} + +// 200 +long wali_syscall_tkill (wasm_exec_env_t exec_env, long a1, long a2) { + SC(200 ,tkill); + RETURN(__syscall2(SYS_tkill, a1, a2)); +} + +// 202 +long wali_syscall_futex (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6) { + SC(202 ,futex); + RETURN(__syscall6(SYS_futex, MADDR(a1), a2, a3, MADDR(a4), MADDR(a5), a6)); +} + +// 217 +long wali_syscall_getdents64 (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(217 ,getdents64); + RETURN(__syscall3(SYS_getdents64, a1, MADDR(a2), a3)); +} + +// 218 +long wali_syscall_set_tid_address (wasm_exec_env_t exec_env, long a1) { + SC(218 ,set_tid_address); + RETURN(__syscall1(SYS_set_tid_address, MADDR(a1))); +} + +// 221 TODO +long wali_syscall_fadvise (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(221 ,fadvise); + ERRSC(fadvise); + RETURN(__syscall4(SYS_fadvise64, a1, a2, a3, a4)); +} + +// 228 +long wali_syscall_clock_gettime (wasm_exec_env_t exec_env, long a1, long a2) { + SC(228 ,clock_gettime); + RETURN(__syscall2(SYS_clock_gettime, a1, MADDR(a2))); +} + +// 229 +long wali_syscall_clock_getres (wasm_exec_env_t exec_env, long a1, long a2) { + SC(229 ,clock_getres); + RETURN(__syscall2(SYS_clock_getres, a1, MADDR(a2))); +} + +// 230 +long wali_syscall_clock_nanosleep (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(230 ,clock_nanosleep); + RETURN(__syscall4(SYS_clock_nanosleep, a1, a2, MADDR(a3), MADDR(a4))); +} + +// 231 TODO +long wali_syscall_exit_group (wasm_exec_env_t exec_env, long a1) { + SC(231 ,exit_group); + ERRSC(exit_group); + wali_proc_exit(exec_env, a1); + RETURN(-1); +} + +// 233 +long wali_syscall_epoll_ctl (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(233 ,epoll_ctl); + struct epoll_event *nev = copy_epoll_event(exec_env, MADDR(a4), &(struct epoll_event){0}); + RETURN(__syscall4(SYS_epoll_ctl, a1, a2, a3, nev)); +} + +// 257 +long wali_syscall_openat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(257 ,openat); + #if __aarch64__ + RETURN(__syscall4(SYS_openat, a1, MADDR(a2), swap_open_flags(a3), a4)); + #else + RETURN(__syscall4(SYS_openat, a1, MADDR(a2), a3, a4)); + #endif +} + +// 258 +long wali_syscall_mkdirat (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(258 ,mkdirat); + RETURN(__syscall3(SYS_mkdirat, a1, MADDR(a2), a3)); +} + +// 260 +long wali_syscall_fchownat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(260 ,fchownat); + RETURN(__syscall5(SYS_fchownat, a1, MADDR(a2), a3, a4, a5)); +} + +// 262 +long wali_syscall_fstatat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(262 ,fstatat); + #if __x86_64__ + RETURN(__syscall4(SYS_newfstatat, a1, MADDR(a2), MADDR(a3), a4)); + #elif __aarch64__ || __riscv64__ + Addr wasm_stat = MADDR(a3); + struct stat sb; + long retval = __syscall4(SYS_newfstatat, a1, MADDR(a2), &sb, a4); + copy2wasm_stat_struct (exec_env, wasm_stat, &sb); + RETURN(retval); + #endif +} + +// 263 +long wali_syscall_unlinkat (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(263 ,unlinkat); + RETURN(__syscall3(SYS_unlinkat, a1, MADDR(a2), a3)); +} + +// 265 +long wali_syscall_linkat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(265 ,linkat); + RETURN(__syscall5(SYS_linkat, a1, MADDR(a2), a3, MADDR(a4), a5)); +} + +// 266 +long wali_syscall_symlinkat (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(266 ,symlinkat); + RETURN(__syscall3(SYS_symlinkat, MADDR(a1), a2, MADDR(a3))); +} + +// 267 +long wali_syscall_readlinkat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(267 ,readlinkat); + RETURN(__syscall4(SYS_readlinkat, a1, MADDR(a2), MADDR(a3), a4)); +} + +// 268 +long wali_syscall_fchmodat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(268 ,fchmodat); + RETURN(__syscall4(SYS_fchmodat, a1, MADDR(a2), a3, a4)); +} + +// 269 +long wali_syscall_faccessat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(269 ,faccessat); + RETURN(__syscall4(SYS_faccessat, a1, MADDR(a2), a3, a4)); +} + +// 270 +long wali_syscall_pselect6 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6) { + SC(270 ,pselect6); + VB("pselect args | a1: %ld, a2: %ld, a3: %ld, a4: %ld, a5: %ld, a6: %ld", a1, a2, a3, a4, a5, a6); + Addr wasm_psel_sm = MADDR(a6); + long sm_struct[2]; + long* sm_struct_ptr = copy_pselect6_sigmask(exec_env, wasm_psel_sm, sm_struct); + RETURN(__syscall6(SYS_pselect6, a1, MADDR(a2), MADDR(a3), MADDR(a4), MADDR(a5), sm_struct_ptr)); +} + +// 271 +long wali_syscall_ppoll (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(271 ,ppoll); + RETURN(__syscall5(SYS_ppoll, MADDR(a1), a2, MADDR(a3), MADDR(a4), a5)); +} +/* Since poll needs a time conversion on pointer, need to use a different alias call */ +long wali_syscall_ppoll_aliased (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(271 ,ppoll-alias); + RETURN(__syscall5(SYS_ppoll, MADDR(a1), a2, a3, MADDR(a4), a5)); +} + +// 280 +long wali_syscall_utimensat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(280 ,utimensat); + RETURN(__syscall4(SYS_utimensat, a1, MADDR(a2), MADDR(a3), a4)); +} + +// 281 +long wali_syscall_epoll_pwait (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6) { + SC(281 ,epoll_pwait); + Addr wasm_epoll = MADDR(a2); + struct epoll_event *nev = copy_epoll_event(exec_env, wasm_epoll, &(struct epoll_event){0}); + long retval = __syscall6(SYS_epoll_pwait, a1, nev, a3, a4, MADDR(a5), a6); + copy2wasm_epoll_event(exec_env, wasm_epoll, nev); + RETURN(retval); +} + +// 284 +long wali_syscall_eventfd (wasm_exec_env_t exec_env, long a1) { + SC(284 ,eventfd); + #if __x86_64__ + RETURN(__syscall1(SYS_eventfd, a1)); + #elif __aarch64__ || __riscv64__ + RETURN(wali_syscall_eventfd2(exec_env, a1, 0)); + #endif +} + +// 288 +long wali_syscall_accept4 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(288 ,accept4); + RETURN(__syscall4(SYS_accept4, a1, MADDR(a2), MADDR(a3), a4)); +} + +// 290 TODO +long wali_syscall_eventfd2 (wasm_exec_env_t exec_env, long a1, long a2) { + SC(290 ,eventfd2); + ERRSC(eventfd2); + RETURN(__syscall2(SYS_eventfd2, a1, a2)); +} + +// 291 +long wali_syscall_epoll_create1 (wasm_exec_env_t exec_env, long a1) { + SC(291 ,epoll_create1); + RETURN(__syscall1(SYS_epoll_create1, a1)); +} + +// 292 +long wali_syscall_dup3 (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(292 ,dup3); + #if __aarch64__ + RETURN(__syscall3(SYS_dup3, a1, a2, swap_open_flags(a3))); + #else + RETURN(__syscall3(SYS_dup3, a1, a2, a3)); + #endif +} + +// 293 +long wali_syscall_pipe2 (wasm_exec_env_t exec_env, long a1, long a2) { + SC(293 ,pipe2); + #if __aarch64__ + RETURN(__syscall2(SYS_pipe2, MADDR(a1), swap_open_flags(a2))); + #else + RETURN(__syscall2(SYS_pipe2, MADDR(a1), a2)); + #endif +} + +// 302 +long wali_syscall_prlimit64 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(302 ,prlimit64); + RETURN(__syscall4(SYS_prlimit64, a1, a2, MADDR(a3), MADDR(a4))); +} + +// 316 +long wali_syscall_renameat2 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(316 ,renameat2); + RETURN(__syscall5(SYS_renameat2, a1, MADDR(a2), a3, MADDR(a4), a5)); +} + +// 318 +long wali_syscall_getrandom (wasm_exec_env_t exec_env, long a1, long a2, long a3) { + SC(318 ,getrandom); + RETURN(__syscall3(SYS_getrandom, MADDR(a1), a2, a3)); +} + +// 332 +long wali_syscall_statx (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5) { + SC(332,statx); + RETURN(__syscall5(SYS_statx, a1, MADDR(a2), a3, a4, MADDR(a5))); +} + +// 439 +long wali_syscall_faccessat2 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4) { + SC(439 ,faccessat2); + RETURN(__syscall4(439, a1, MADDR(a2), a3, a4)); +} + +/***** Non-syscall methods *****/ +int wali_sigsetjmp (wasm_exec_env_t exec_env, int sigjmp_buf_addr, int savesigs) { + PC(sigsetjmp); + Addr wasm_sigjmp_buf = MADDR(sigjmp_buf_addr); + struct __libc_jmp_buf_tag* jmpenv = copy_jmp_buf(exec_env, wasm_sigjmp_buf); + int retval = __libc_sigsetjmp_asm(jmpenv, savesigs); + ERRSC(sigsetjmp, "Unsupported in WALI right now, continuing execution with " + "flag on siglongjmp"); + if (retval == 0) { + copy2wasm_jmp_buf(exec_env, wasm_sigjmp_buf, jmpenv); + free(jmpenv); + } + return retval; +} + +int wali_setjmp (wasm_exec_env_t exec_env, int jmp_buf_addr) { + PC(setjmp); + ERRSC(setjmp, "Unsupported in WALI right now, continuing execution with flag on longjmp"); + return 0; +} + +_Noreturn void wali_siglongjmp (wasm_exec_env_t exec_env, int sigjmp_buf_addr, int val) { + PC(siglongjmp); + //struct __libc_jmp_buf_tag* env = copy_jmp_buf(exec_env, MADDR(sigjmp_buf_addr)); + FATALSC(siglongjmp, "Not supported in WALI yet, exiting code..."); + wali_proc_exit(exec_env, 1); + // __libc_siglongjmp(env, val); + /* Should not reach here */ + exit(-1); +} + + +/***** Startup *****/ +static bool dtor_called = false; +void wali_call_ctors(wasm_exec_env_t exec_env) { + PC(wali_call_ctors); + invoked_wali = true; +} + +void wali_call_dtors(wasm_exec_env_t exec_env) { + PC(wali_call_dtors); + dtor_called = true; +} + +void wali_proc_exit(wasm_exec_env_t exec_env, long v) { + PC(proc_exit); +#if WALI_ENABLE_SYSCALL_PROFILE + wali_syscall_profile_dump(0); +#endif + wasm_module_inst_t module_inst = get_module_inst(exec_env); + WALIContext *wali_ctx = wasm_runtime_get_wali_ctx(module_inst); + /* if destructor is invoked, main ended successfully, do + * not set exception */ + if (!dtor_called || v) { + VB("WALI process exit called prematurely"); + wasm_runtime_set_exception(module_inst, "wali proc exit"); + } else { + VB("Main ended successfully"); + } + wali_ctx->exit_code = v; +} + +static void wali_thread_exit(wasm_exec_env_t exec_env, long v) { + PC(thread_exit); + /* Have to use cancel thread as opposed to exit thread + * so that it is caught after native functions (WALI) returns */ + wasm_cluster_cancel_thread(exec_env); +} + +/** +* Returns the number of arguments that were provided to the module +* +* @return The number of arguments that were provided to the module +*/ +int wali_cl_get_argc (wasm_exec_env_t exec_env) { + PC(cl_get_argc); + return wali_app_argc; +} + +/** +* Returns the length of the specified argument +* +* @param arg_idx The index of the specified argument (the first argument has the index 0) +* +* @return The length of the specified argument (the number of bytes that the argument will +* occupy in the module memory when represented as a C string). Returns -1 on error. +*/ +int wali_cl_get_argv_len (wasm_exec_env_t exec_env, int arg_idx) { + PC(cl_get_argc_len); + return strlen(wali_app_argv[arg_idx]); +} + +/** +* Copies the specified argument to the specified location in the (shared) memory of the calling module +* +* @param argv_addr The location in the (shared) module memory, specified as the offset from the start +* @param arg_idx The index of the specified argument (the first argument has the index 0) +* +* @return The number of bytes which were written into the memory. Returns -1 on error +*/ +int wali_cl_copy_argv (wasm_exec_env_t exec_env, int argv_addr, int arg_idx) { + PC(cl_copy_argv); + Addr argv = MADDR(argv_addr); + strcpy((char*)argv, wali_app_argv[arg_idx]); + return 0; +} + +int wali_get_init_envfile (wasm_exec_env_t exec_env, int faddr, int fsize) { + PC(get_init_envfile); + Addr fbuf = MADDR(faddr); + + /* Check for passthrough env from an execve call */ + char pass_filename[100]; + sprintf(pass_filename, "/tmp/wali_env.%d", getpid()); + int execve_invoked = !access(pass_filename, R_OK); + + char *envfile = execve_invoked ? pass_filename : wali_app_env_file; + + if (!envfile) { + ERR("No WALI environment file provided\n"); + return 0; + } + + if ((int)(strlen(envfile) + 1) > fsize) { + ERR("WALI env initialization filepath too large (max length: %d)." + "Defaulting to NULL\n", fsize); + ((char*)fbuf)[0] = 0; + } else { + strcpy((char*)fbuf, envfile); + ERR("WALI init env file: \'%s\'\n", fbuf); + } + return 1; +} + +/***** Threads *****/ +typedef struct { + /* Initial function */ + wasm_function_inst_t start_fn; + /* Wasm address for args */ + int arg; + /* Wasm Thread ID */ + int tid; +} WasmThreadStartArg; + +/* Thread dispatcher function calls into WASM */ +static void* +wali_dispatch_thread_libc(void *exec_env_ptr) { + wasm_exec_env_t exec_env = (wasm_exec_env_t) exec_env_ptr; + WasmThreadStartArg *thread_arg = (WasmThreadStartArg*) exec_env->thread_arg; + + wasm_exec_env_set_thread_info(exec_env); + int tid = gettid(); + /* Libc start fn: (int thread_id, void *arg) */ + uint32_t wasm_argv[2]; + // Dispatcher is part of child thread; can get tid using syscall + wasm_argv[0] = tid; //thread_arg->tid; + wasm_argv[1] = thread_arg->arg; + + VB("Dispatcher | Child TID: %d\n", wasm_argv[0]); + /* Send parent our TID */ + signalled_tid = tid; + if (sem_post(&tid_sem)) { + perror("sem_post"); + } + + if (!wasm_runtime_call_wasm(exec_env, thread_arg->start_fn, 2, wasm_argv)) { + /* Exception has already been spread during throwing */ + } + + VB("================ Thread [%d] exiting ==============\n", gettid()); + // Cleanup + wasm_runtime_free(thread_arg); + exec_env->thread_arg = NULL; + + return NULL; +} + +int wali_wasm_thread_spawn (wasm_exec_env_t exec_env, int setup_fnptr, int arg_wasm) { + SC(56 ,wasm_thread_spawn (clone)); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasm_module_t module = wasm_runtime_get_module(module_inst); + bh_assert(module); + bh_assert(module_inst); + + wasm_module_inst_t new_module_inst = NULL; + WasmThreadStartArg *thread_start_arg = NULL; + uint32_t stack_size = 8192; + int thread_id = -1; + int ret = -1; + + /* Table 0 is only supported currently */ + wasm_function_inst_t setup_wasm_fn = + wasm_runtime_get_indirect_function(module_inst, 0, setup_fnptr); + + stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size; + + /* New module instance -- custom data, import function registration, etc. */ + if (!(new_module_inst = wasm_runtime_instantiate_internal( + module, module_inst, exec_env, stack_size, 0, NULL, 0))) + return -1; + + wasm_runtime_set_custom_data_internal( + new_module_inst, wasm_runtime_get_custom_data(module_inst)); + + if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst))) + goto thread_spawn_fail; + /** **/ + + /** Setup args to pass to startup dispatcher **/ + if (!(thread_start_arg = wasm_runtime_malloc(sizeof(WasmThreadStartArg)))) { + FATALSC(wasm_thread_spawn, "Runtime args allocation failed"); + goto thread_spawn_fail; + } + + thread_start_arg->tid = thread_id = THREAD_ID++; + + thread_start_arg->start_fn = setup_wasm_fn; + thread_start_arg->arg = arg_wasm; + /** **/ + + + /** Create and dispatch the thread (language-independent: currently just C); + * Thread ID of the created thread is sent back to parent */ + volatile int child_tid = -1; + pthread_mutex_lock(&clone_lock); + ret = wasm_cluster_create_thread(exec_env, new_module_inst, false, + wali_dispatch_thread_libc, thread_start_arg); + if (ret != 0) { + FATALSC(wasm_thread_spawn, "Failed to spawn a new thread"); + goto thread_spawn_fail_post_clone; + } + + /* Get the thread-id of spawned child. Wait for timeout (5 sec) for signal */ + struct timespec dtime; + if (clock_gettime(CLOCK_REALTIME, &dtime) == -1) { + perror("clock_gettime"); + goto thread_spawn_fail_post_clone; + } + dtime.tv_sec += 5; + if ( sem_timedwait(&tid_sem, &dtime) ) { + perror("sem_timedwait"); + FATALSC(wasm_thread_spawn, "TID signalling error"); + goto thread_spawn_fail_post_clone; + } + + child_tid = signalled_tid; + VB("Parent of Dispatcher | Child TID: %d\n", child_tid); + pthread_mutex_unlock(&clone_lock); + + FUNC_FREE(setup_wasm_fn); + + RETURN(child_tid); + +thread_spawn_fail_post_clone: + pthread_mutex_unlock(&clone_lock); +thread_spawn_fail: + if (new_module_inst) + wasm_runtime_deinstantiate_internal(new_module_inst, true); + if (thread_start_arg) + wasm_runtime_free(thread_start_arg); + + RETURN(-1); +} + + +/* Native WALI Symbols */ +#define NSYMBOL(symbol, fn, sign) \ + { #symbol, (void*)fn, sign, NULL } + +static NativeSymbol wali_native_symbols[] = { + // Syscalls + NSYMBOL ( SYS_read, wali_syscall_read, "(iii)I" ), + NSYMBOL ( SYS_write, wali_syscall_write, "(iii)I" ), + NSYMBOL ( SYS_open, wali_syscall_open, "(iii)I" ), + NSYMBOL ( SYS_close, wali_syscall_close, "(i)I" ), + NSYMBOL ( SYS_stat, wali_syscall_stat, "(ii)I" ), + NSYMBOL ( SYS_fstat, wali_syscall_fstat, "(ii)I" ), + NSYMBOL ( SYS_lstat, wali_syscall_lstat, "(ii)I" ), + NSYMBOL ( SYS_poll, wali_syscall_poll, "(iii)I" ), + NSYMBOL ( SYS_lseek, wali_syscall_lseek, "(iIi)I" ), + NSYMBOL ( SYS_mmap, wali_syscall_mmap, "(iiiiiI)I" ), + NSYMBOL ( SYS_mprotect, wali_syscall_mprotect, "(iii)I" ), + NSYMBOL ( SYS_munmap, wali_syscall_munmap, "(ii)I" ), + NSYMBOL ( SYS_brk, wali_syscall_brk, "(i)I" ), + NSYMBOL ( SYS_rt_sigaction, wali_syscall_rt_sigaction, "(iiii)I" ), + NSYMBOL ( SYS_rt_sigprocmask, wali_syscall_rt_sigprocmask, "(iiii)I" ), + NSYMBOL ( SYS_rt_sigreturn, wali_syscall_rt_sigreturn, "(I)I" ), + NSYMBOL ( SYS_ioctl, wali_syscall_ioctl, "(iii)I" ), + NSYMBOL ( SYS_pread64, wali_syscall_pread64, "(iiiI)I" ), + NSYMBOL ( SYS_pwrite64, wali_syscall_pwrite64, "(iiiI)I" ), + NSYMBOL ( SYS_readv, wali_syscall_readv, "(iii)I" ), + NSYMBOL ( SYS_writev, wali_syscall_writev, "(iii)I" ), + NSYMBOL ( SYS_access, wali_syscall_access, "(ii)I" ), + NSYMBOL ( SYS_pipe, wali_syscall_pipe, "(i)I" ), + NSYMBOL ( SYS_select, wali_syscall_select, "(iiiii)I" ), + NSYMBOL ( SYS_sched_yield, wali_syscall_sched_yield, "()I" ), + NSYMBOL ( SYS_mremap, wali_syscall_mremap, "(iiiii)I" ), + NSYMBOL ( SYS_msync, wali_syscall_msync, "(iii)I" ), + NSYMBOL ( SYS_madvise, wali_syscall_madvise, "(iii)I" ), + NSYMBOL ( SYS_dup, wali_syscall_dup, "(i)I" ), + NSYMBOL ( SYS_dup2, wali_syscall_dup2, "(ii)I" ), + NSYMBOL ( SYS_nanosleep, wali_syscall_nanosleep, "(ii)I" ), + NSYMBOL ( SYS_alarm, wali_syscall_alarm, "(i)I" ), + NSYMBOL ( SYS_setitimer, wali_syscall_setitimer, "(iii)I" ), + NSYMBOL ( SYS_getpid, wali_syscall_getpid, "()I" ), + NSYMBOL ( SYS_socket, wali_syscall_socket, "(iii)I" ), + NSYMBOL ( SYS_connect, wali_syscall_connect, "(iii)I" ), + NSYMBOL ( SYS_accept, wali_syscall_accept, "(iii)I" ), + NSYMBOL ( SYS_sendto, wali_syscall_sendto, "(iiiiii)I" ), + NSYMBOL ( SYS_recvfrom, wali_syscall_recvfrom, "(iiiiii)I" ), + NSYMBOL ( SYS_sendmsg, wali_syscall_sendmsg, "(iii)I" ), + NSYMBOL ( SYS_recvmsg, wali_syscall_recvmsg, "(iii)I" ), + NSYMBOL ( SYS_shutdown, wali_syscall_shutdown, "(ii)I" ), + NSYMBOL ( SYS_bind, wali_syscall_bind, "(iii)I" ), + NSYMBOL ( SYS_listen, wali_syscall_listen, "(ii)I" ), + NSYMBOL ( SYS_getsockname, wali_syscall_getsockname, "(iii)I" ), + NSYMBOL ( SYS_getpeername, wali_syscall_getpeername, "(iii)I" ), + NSYMBOL ( SYS_socketpair, wali_syscall_socketpair, "(iiii)I" ), + NSYMBOL ( SYS_setsockopt, wali_syscall_setsockopt, "(iiiii)I" ), + NSYMBOL ( SYS_getsockopt, wali_syscall_getsockopt, "(iiiii)I" ), + NSYMBOL ( SYS_fork, wali_syscall_fork, "()I" ), + NSYMBOL ( SYS_execve, wali_syscall_execve, "(iii)I" ), + NSYMBOL ( SYS_exit, wali_syscall_exit, "(i)I" ), + NSYMBOL ( SYS_wait4, wali_syscall_wait4, "(iiii)I" ), + NSYMBOL ( SYS_kill, wali_syscall_kill, "(ii)I" ), + NSYMBOL ( SYS_uname, wali_syscall_uname, "(i)I" ), + NSYMBOL ( SYS_fcntl, wali_syscall_fcntl, "(iii)I" ), + NSYMBOL ( SYS_flock, wali_syscall_flock, "(ii)I" ), + NSYMBOL ( SYS_fsync, wali_syscall_fsync, "(i)I" ), + NSYMBOL ( SYS_fdatasync, wali_syscall_fdatasync, "(i)I" ), + NSYMBOL ( SYS_ftruncate, wali_syscall_ftruncate, "(iI)I" ), + NSYMBOL ( SYS_getdents, wali_syscall_getdents, "(iii)I" ), + NSYMBOL ( SYS_getcwd, wali_syscall_getcwd, "(ii)I" ), + NSYMBOL ( SYS_chdir, wali_syscall_chdir, "(i)I" ), + NSYMBOL ( SYS_fchdir, wali_syscall_fchdir, "(i)I" ), + NSYMBOL ( SYS_rename, wali_syscall_rename, "(ii)I" ), + NSYMBOL ( SYS_mkdir, wali_syscall_mkdir, "(ii)I" ), + NSYMBOL ( SYS_rmdir, wali_syscall_rmdir, "(i)I" ), + NSYMBOL ( SYS_link, wali_syscall_link, "(ii)I" ), + NSYMBOL ( SYS_unlink, wali_syscall_unlink, "(i)I" ), + NSYMBOL ( SYS_symlink, wali_syscall_symlink, "(ii)I" ), + NSYMBOL ( SYS_readlink, wali_syscall_readlink, "(iii)I" ), + NSYMBOL ( SYS_chmod, wali_syscall_chmod, "(ii)I" ), + NSYMBOL ( SYS_fchmod, wali_syscall_fchmod, "(ii)I" ), + NSYMBOL ( SYS_chown, wali_syscall_chown, "(iii)I" ), + NSYMBOL ( SYS_fchown, wali_syscall_fchown, "(iii)I" ), + NSYMBOL ( SYS_umask, wali_syscall_umask, "(i)I" ), + NSYMBOL ( SYS_getrlimit, wali_syscall_getrlimit, "(ii)I" ), + NSYMBOL ( SYS_getrusage, wali_syscall_getrusage, "(ii)I" ), + NSYMBOL ( SYS_sysinfo, wali_syscall_sysinfo, "(i)I" ), + NSYMBOL ( SYS_getuid, wali_syscall_getuid, "()I" ), + NSYMBOL ( SYS_getgid, wali_syscall_getgid, "()I" ), + NSYMBOL ( SYS_setuid, wali_syscall_setuid, "(i)I" ), + NSYMBOL ( SYS_setgid, wali_syscall_setgid, "(i)I" ), + NSYMBOL ( SYS_geteuid, wali_syscall_geteuid, "()I" ), + NSYMBOL ( SYS_getegid, wali_syscall_getegid, "()I" ), + NSYMBOL ( SYS_setpgid, wali_syscall_setpgid, "(ii)I" ), + NSYMBOL ( SYS_getppid, wali_syscall_getppid, "()I" ), + NSYMBOL ( SYS_setsid, wali_syscall_setsid, "()I" ), + NSYMBOL ( SYS_getgroups, wali_syscall_getgroups, "(ii)I" ), + NSYMBOL ( SYS_setgroups, wali_syscall_setgroups, "(ii)I" ), + NSYMBOL ( SYS_setresuid, wali_syscall_setresuid, "(iii)I" ), + NSYMBOL ( SYS_setresgid, wali_syscall_setresgid, "(iii)I" ), + NSYMBOL ( SYS_getpgid, wali_syscall_getpgid, "(i)I" ), + NSYMBOL ( SYS_getsid, wali_syscall_getsid, "(i)I" ), + NSYMBOL ( SYS_rt_sigpending, wali_syscall_rt_sigpending, "(ii)I" ), + NSYMBOL ( SYS_rt_sigsuspend, wali_syscall_rt_sigsuspend, "(ii)I" ), + NSYMBOL ( SYS_sigaltstack, wali_syscall_sigaltstack, "(ii)I" ), + NSYMBOL ( SYS_utime, wali_syscall_utime, "(ii)I" ), + NSYMBOL ( SYS_statfs, wali_syscall_statfs, "(ii)I" ), + NSYMBOL ( SYS_fstatfs, wali_syscall_fstatfs, "(ii)I" ), + NSYMBOL ( SYS_setrlimit, wali_syscall_setrlimit, "(ii)I" ), + NSYMBOL ( SYS_chroot, wali_syscall_chroot, "(i)I" ), + NSYMBOL ( SYS_gettid, wali_syscall_gettid, "()I" ), + NSYMBOL ( SYS_tkill, wali_syscall_tkill, "(ii)I" ), + NSYMBOL ( SYS_futex, wali_syscall_futex, "(iiiiii)I" ), + NSYMBOL ( SYS_getdents64, wali_syscall_getdents64, "(iii)I" ), + NSYMBOL ( SYS_set_tid_address, wali_syscall_set_tid_address, "(i)I" ), + NSYMBOL ( SYS_fadvise, wali_syscall_fadvise, "(iIIi)I" ), + NSYMBOL ( SYS_clock_gettime, wali_syscall_clock_gettime, "(ii)I" ), + NSYMBOL ( SYS_clock_getres, wali_syscall_clock_getres, "(ii)I" ), + NSYMBOL ( SYS_clock_nanosleep, wali_syscall_clock_nanosleep, "(iiii)I" ), + NSYMBOL ( SYS_exit_group, wali_syscall_exit_group, "(i)I" ), + NSYMBOL ( SYS_epoll_ctl, wali_syscall_epoll_ctl, "(iiii)I" ), + NSYMBOL ( SYS_openat, wali_syscall_openat, "(iiii)I" ), + NSYMBOL ( SYS_mkdirat, wali_syscall_mkdirat, "(iii)I" ), + NSYMBOL ( SYS_fchownat, wali_syscall_fchownat, "(iiiii)I" ), + NSYMBOL ( SYS_fstatat, wali_syscall_fstatat, "(iiii)I" ), + NSYMBOL ( SYS_unlinkat, wali_syscall_unlinkat, "(iii)I" ), + NSYMBOL ( SYS_linkat, wali_syscall_linkat, "(iiiii)I" ), + NSYMBOL ( SYS_symlinkat, wali_syscall_symlinkat, "(iii)I" ), + NSYMBOL ( SYS_readlinkat, wali_syscall_readlinkat, "(iiii)I" ), + NSYMBOL ( SYS_fchmodat, wali_syscall_fchmodat, "(iiii)I" ), + NSYMBOL ( SYS_faccessat, wali_syscall_faccessat, "(iiii)I" ), + NSYMBOL ( SYS_pselect6, wali_syscall_pselect6, "(iiiiii)I" ), + NSYMBOL ( SYS_ppoll, wali_syscall_ppoll, "(iiiii)I" ), + NSYMBOL ( SYS_utimensat, wali_syscall_utimensat, "(iiii)I" ), + NSYMBOL ( SYS_epoll_pwait, wali_syscall_epoll_pwait, "(iiiiii)I" ), + NSYMBOL ( SYS_eventfd, wali_syscall_eventfd, "(i)I" ), + NSYMBOL ( SYS_accept4, wali_syscall_accept4, "(iiii)I" ), + NSYMBOL ( SYS_eventfd2, wali_syscall_eventfd2, "(ii)I" ), + NSYMBOL ( SYS_epoll_create1, wali_syscall_epoll_create1, "(i)I" ), + NSYMBOL ( SYS_dup3, wali_syscall_dup3, "(iii)I" ), + NSYMBOL ( SYS_pipe2, wali_syscall_pipe2, "(ii)I" ), + NSYMBOL ( SYS_prlimit64, wali_syscall_prlimit64, "(iiii)I" ), + NSYMBOL ( SYS_renameat2, wali_syscall_renameat2, "(iiiii)I" ), + NSYMBOL ( SYS_getrandom, wali_syscall_getrandom, "(iii)I" ), + NSYMBOL ( SYS_statx, wali_syscall_statx, "(iiiii)I" ), + NSYMBOL ( SYS_faccessat2, wali_syscall_faccessat2, "(iiii)I" ), + + /* Libc imports */ + // Threads + // thread_spawn is the substitute for syscall(clone) + NSYMBOL ( __wasm_thread_spawn, wali_wasm_thread_spawn, "(ii)i" ), + + // Startup + NSYMBOL ( __call_ctors, wali_call_ctors, "()" ), + NSYMBOL ( __call_dtors, wali_call_dtors, "()" ), + NSYMBOL ( __proc_exit, wali_proc_exit, "(i)" ), + NSYMBOL ( __cl_get_argc, wali_cl_get_argc, "()i" ), + NSYMBOL ( __cl_get_argv_len, wali_cl_get_argv_len, "(i)i" ), + NSYMBOL ( __cl_copy_argv, wali_cl_copy_argv, "(ii)i" ), + NSYMBOL ( __get_init_envfile, wali_get_init_envfile, "(ii)i" ), + + // Signal + NSYMBOL ( sigsetjmp, wali_sigsetjmp, "(ii)i" ), + NSYMBOL ( setjmp, wali_setjmp, "(i)i" ), + NSYMBOL ( longjmp, wali_siglongjmp, "(ii)" ), + +}; + + +uint32 +get_libc_wali_export_apis(NativeSymbol **p_libc_wali_apis) +{ + *p_libc_wali_apis = wali_native_symbols; + return sizeof(wali_native_symbols) / sizeof(NativeSymbol); +} + + diff --git a/core/iwasm/libraries/libc-wali/wali.h b/core/iwasm/libraries/libc-wali/wali.h new file mode 100644 index 0000000000..83127e09d4 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali.h @@ -0,0 +1,440 @@ +#ifndef WALI_H +#define WALI_H + +#include "wasm_export.h" +#include "bh_platform.h" +#include "aot_export.h" +#include "wali_defs.h" + +#if !__x86_64__ && !__aarch64__ && !__riscv64__ +#error "Unsupported architecture for WALI -- Only supports [x86_64, aarch64, riscv64]" +#endif + +/** Logging: Disable when profiling **/ +#if WALI_ENABLE_SYSCALL_PROFILE +#define VB(fmt, ...) +#define WARN(fmt, ...) +#define ERR(fmt, ...) +#else +#define VB(fmt, ...) LOG_VERBOSE("[%d] WALI: " fmt, gettid(), ## __VA_ARGS__) +#define WARN(fmt, ...) LOG_WARNING("[%d] WALI: " fmt, gettid(), ## __VA_ARGS__) +#define ERR(fmt, ...) LOG_ERROR("[%d] WALI: " fmt, gettid(), ## __VA_ARGS__) +#endif + + +/** Memory defines/translations **/ +typedef uint8_t* Addr; +typedef uint32_t FuncPtr_t; + +#define BASE_ADDR() ({ \ + (Addr) wasm_runtime_addr_app_to_native(get_module_inst(exec_env), 0); \ +}) + +#define MADDR(wasm_addr) ({ \ + Addr addr = wasm_addr ? (Addr) wasm_runtime_addr_app_to_native(get_module_inst(exec_env), wasm_addr) : NULL; \ + if (addr == NULL) { } \ + addr; \ +}) + +#define WADDR(mem_addr) ({ \ + wasm_runtime_addr_native_to_app(get_module_inst(exec_env), mem_addr); \ +}) +/** **/ + + +/** Function translations **/ +#define FUNC_IDX(func) ({ wasm_runtime_get_function_idx(module_inst, func); }) + +/* Needs to be called only for AoT when using wasm_runtime_get_indirect_function */ +#define FUNC_FREE(func) { \ + if (func && (get_module_inst(exec_env)->module_type == Wasm_Module_AoT)) { \ + wasm_runtime_free(func); \ + } \ +} + + + +/** Some internal structs for syscalls **/ + +/* This is the structure used for the rt_sigaction syscall on most archs, + * but it can be overridden by a file with the same name in the top-level + * arch dir for a given arch, if necessary. */ +struct k_sigaction { + void (*handler)(int); + unsigned long flags; + void (*restorer)(void); + unsigned mask[2]; +}; + +/* Setjmp/longjmp with signal handling */ +typedef unsigned long __libc_jmp_buf_internal[8]; + +typedef struct __libc_jmp_buf_tag { + __libc_jmp_buf_internal __jb; + unsigned long __fl; + unsigned long __ss[128/sizeof(long)]; +} __libc_jmp_buf[1]; + +typedef __libc_jmp_buf __libc_sigjmp_buf; + +/** **/ + + +/** Syscalls **/ +long wali_syscall_read (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_write (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_open (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_close (wasm_exec_env_t exec_env, long a1); +long wali_syscall_stat (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_fstat (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_lstat (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_poll (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_lseek (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_mmap (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6); +long wali_syscall_mprotect (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_munmap (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_brk (wasm_exec_env_t exec_env, long a1); +long wali_syscall_rt_sigaction (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_rt_sigprocmask (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_rt_sigreturn (wasm_exec_env_t exec_env, long a1); +long wali_syscall_ioctl (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_pread64 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_pwrite64 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_readv (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_writev (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_access (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_pipe (wasm_exec_env_t exec_env, long a1); +long wali_syscall_select (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_sched_yield (wasm_exec_env_t exec_env); +long wali_syscall_mremap (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_msync (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_mincore (wasm_exec_env_t exec_env); +long wali_syscall_madvise (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_shmget (wasm_exec_env_t exec_env); +long wali_syscall_shmat (wasm_exec_env_t exec_env); +long wali_syscall_shmctl (wasm_exec_env_t exec_env); +long wali_syscall_dup (wasm_exec_env_t exec_env, long a1); +long wali_syscall_dup2 (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_pause (wasm_exec_env_t exec_env); +long wali_syscall_nanosleep (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_getitimer (wasm_exec_env_t exec_env); +long wali_syscall_alarm (wasm_exec_env_t exec_env, long a1); +long wali_syscall_setitimer (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_getpid (wasm_exec_env_t exec_env); +long wali_syscall_sendfile (wasm_exec_env_t exec_env); +long wali_syscall_socket (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_connect (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_accept (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_sendto (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6); +long wali_syscall_recvfrom (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6); +long wali_syscall_sendmsg (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_recvmsg (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_shutdown (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_bind (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_listen (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_getsockname (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_getpeername (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_socketpair (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_setsockopt (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_getsockopt (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_clone (wasm_exec_env_t exec_env); +long wali_syscall_fork (wasm_exec_env_t exec_env); +long wali_syscall_vfork (wasm_exec_env_t exec_env); +long wali_syscall_execve (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_exit (wasm_exec_env_t exec_env, long a1); +long wali_syscall_wait4 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_kill (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_uname (wasm_exec_env_t exec_env, long a1); +long wali_syscall_semget (wasm_exec_env_t exec_env); +long wali_syscall_semop (wasm_exec_env_t exec_env); +long wali_syscall_semctl (wasm_exec_env_t exec_env); +long wali_syscall_shmdt (wasm_exec_env_t exec_env); +long wali_syscall_msgget (wasm_exec_env_t exec_env); +long wali_syscall_msgsnd (wasm_exec_env_t exec_env); +long wali_syscall_msgrcv (wasm_exec_env_t exec_env); +long wali_syscall_msgctl (wasm_exec_env_t exec_env); +long wali_syscall_fcntl (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_flock (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_fsync (wasm_exec_env_t exec_env, long a1); +long wali_syscall_fdatasync (wasm_exec_env_t exec_env, long a1); +long wali_syscall_truncate (wasm_exec_env_t exec_env); +long wali_syscall_ftruncate (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_getdents (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_getcwd (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_chdir (wasm_exec_env_t exec_env, long a1); +long wali_syscall_fchdir (wasm_exec_env_t exec_env, long a1); +long wali_syscall_rename (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_mkdir (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_rmdir (wasm_exec_env_t exec_env, long a1); +long wali_syscall_creat (wasm_exec_env_t exec_env); +long wali_syscall_link (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_unlink (wasm_exec_env_t exec_env, long a1); +long wali_syscall_symlink (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_readlink (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_chmod (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_fchmod (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_chown (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_fchown (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_lchown (wasm_exec_env_t exec_env); +long wali_syscall_umask (wasm_exec_env_t exec_env, long a1); +long wali_syscall_gettimeofday (wasm_exec_env_t exec_env); +long wali_syscall_getrlimit (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_getrusage (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_sysinfo (wasm_exec_env_t exec_env, long a1); +long wali_syscall_times (wasm_exec_env_t exec_env); +long wali_syscall_ptrace (wasm_exec_env_t exec_env); +long wali_syscall_getuid (wasm_exec_env_t exec_env); +long wali_syscall_syslog (wasm_exec_env_t exec_env); +long wali_syscall_getgid (wasm_exec_env_t exec_env); +long wali_syscall_setuid (wasm_exec_env_t exec_env, long a1); +long wali_syscall_setgid (wasm_exec_env_t exec_env, long a1); +long wali_syscall_geteuid (wasm_exec_env_t exec_env); +long wali_syscall_getegid (wasm_exec_env_t exec_env); +long wali_syscall_setpgid (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_getppid (wasm_exec_env_t exec_env); +long wali_syscall_getpgrp (wasm_exec_env_t exec_env); +long wali_syscall_setsid (wasm_exec_env_t exec_env); +long wali_syscall_setreuid (wasm_exec_env_t exec_env); +long wali_syscall_setregid (wasm_exec_env_t exec_env); +long wali_syscall_getgroups (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_setgroups (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_setresuid (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_getresuid (wasm_exec_env_t exec_env); +long wali_syscall_setresgid (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_getresgid (wasm_exec_env_t exec_env); +long wali_syscall_getpgid (wasm_exec_env_t exec_env, long a1); +long wali_syscall_setfsuid (wasm_exec_env_t exec_env); +long wali_syscall_setfsgid (wasm_exec_env_t exec_env); +long wali_syscall_getsid (wasm_exec_env_t exec_env, long a1); +long wali_syscall_capget (wasm_exec_env_t exec_env); +long wali_syscall_capset (wasm_exec_env_t exec_env); +long wali_syscall_rt_sigpending (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_rt_sigtimedwait (wasm_exec_env_t exec_env); +long wali_syscall_rt_sigqueueinfo (wasm_exec_env_t exec_env); +long wali_syscall_rt_sigsuspend (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_sigaltstack (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_utime (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_mknod (wasm_exec_env_t exec_env); +long wali_syscall_uselib (wasm_exec_env_t exec_env); +long wali_syscall_personality (wasm_exec_env_t exec_env); +long wali_syscall_ustat (wasm_exec_env_t exec_env); +long wali_syscall_statfs (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_fstatfs (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_sysfs (wasm_exec_env_t exec_env); +long wali_syscall_getpriority (wasm_exec_env_t exec_env); +long wali_syscall_setpriority (wasm_exec_env_t exec_env); +long wali_syscall_sched_setparam (wasm_exec_env_t exec_env); +long wali_syscall_sched_getparam (wasm_exec_env_t exec_env); +long wali_syscall_sched_setscheduler (wasm_exec_env_t exec_env); +long wali_syscall_sched_getscheduler (wasm_exec_env_t exec_env); +long wali_syscall_sched_get_priority_max (wasm_exec_env_t exec_env); +long wali_syscall_sched_get_priority_min (wasm_exec_env_t exec_env); +long wali_syscall_sched_rr_get_interval (wasm_exec_env_t exec_env); +long wali_syscall_mlock (wasm_exec_env_t exec_env); +long wali_syscall_munlock (wasm_exec_env_t exec_env); +long wali_syscall_mlockall (wasm_exec_env_t exec_env); +long wali_syscall_munlockall (wasm_exec_env_t exec_env); +long wali_syscall_vhangup (wasm_exec_env_t exec_env); +long wali_syscall_modify_ldt (wasm_exec_env_t exec_env); +long wali_syscall_pivot_root (wasm_exec_env_t exec_env); +long wali_syscall__sysctl (wasm_exec_env_t exec_env); +long wali_syscall_prctl (wasm_exec_env_t exec_env); +long wali_syscall_arch_prctl (wasm_exec_env_t exec_env); +long wali_syscall_adjtimex (wasm_exec_env_t exec_env); +long wali_syscall_setrlimit (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_chroot (wasm_exec_env_t exec_env, long a1); +long wali_syscall_sync (wasm_exec_env_t exec_env); +long wali_syscall_acct (wasm_exec_env_t exec_env); +long wali_syscall_settimeofday (wasm_exec_env_t exec_env); +long wali_syscall_mount (wasm_exec_env_t exec_env); +long wali_syscall_umount2 (wasm_exec_env_t exec_env); +long wali_syscall_swapon (wasm_exec_env_t exec_env); +long wali_syscall_swapoff (wasm_exec_env_t exec_env); +long wali_syscall_reboot (wasm_exec_env_t exec_env); +long wali_syscall_sethostname (wasm_exec_env_t exec_env); +long wali_syscall_setdomainname (wasm_exec_env_t exec_env); +long wali_syscall_iopl (wasm_exec_env_t exec_env); +long wali_syscall_ioperm (wasm_exec_env_t exec_env); +long wali_syscall_create_module (wasm_exec_env_t exec_env); +long wali_syscall_init_module (wasm_exec_env_t exec_env); +long wali_syscall_delete_module (wasm_exec_env_t exec_env); +long wali_syscall_get_kernel_syms (wasm_exec_env_t exec_env); +long wali_syscall_query_module (wasm_exec_env_t exec_env); +long wali_syscall_quotactl (wasm_exec_env_t exec_env); +long wali_syscall_nfsservctl (wasm_exec_env_t exec_env); +long wali_syscall_getpmsg (wasm_exec_env_t exec_env); +long wali_syscall_putpmsg (wasm_exec_env_t exec_env); +long wali_syscall_afs_syscall (wasm_exec_env_t exec_env); +long wali_syscall_tuxcall (wasm_exec_env_t exec_env); +long wali_syscall_security (wasm_exec_env_t exec_env); +long wali_syscall_gettid (wasm_exec_env_t exec_env); +long wali_syscall_readahead (wasm_exec_env_t exec_env); +long wali_syscall_setxattr (wasm_exec_env_t exec_env); +long wali_syscall_lsetxattr (wasm_exec_env_t exec_env); +long wali_syscall_fsetxattr (wasm_exec_env_t exec_env); +long wali_syscall_getxattr (wasm_exec_env_t exec_env); +long wali_syscall_lgetxattr (wasm_exec_env_t exec_env); +long wali_syscall_fgetxattr (wasm_exec_env_t exec_env); +long wali_syscall_listxattr (wasm_exec_env_t exec_env); +long wali_syscall_llistxattr (wasm_exec_env_t exec_env); +long wali_syscall_flistxattr (wasm_exec_env_t exec_env); +long wali_syscall_removexattr (wasm_exec_env_t exec_env); +long wali_syscall_lremovexattr (wasm_exec_env_t exec_env); +long wali_syscall_fremovexattr (wasm_exec_env_t exec_env); +long wali_syscall_tkill (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_time (wasm_exec_env_t exec_env); +long wali_syscall_futex (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6); +long wali_syscall_sched_setaffinity (wasm_exec_env_t exec_env); +long wali_syscall_sched_getaffinity (wasm_exec_env_t exec_env); +long wali_syscall_set_thread_area (wasm_exec_env_t exec_env); +long wali_syscall_io_setup (wasm_exec_env_t exec_env); +long wali_syscall_io_destroy (wasm_exec_env_t exec_env); +long wali_syscall_io_getevents (wasm_exec_env_t exec_env); +long wali_syscall_io_submit (wasm_exec_env_t exec_env); +long wali_syscall_io_cancel (wasm_exec_env_t exec_env); +long wali_syscall_get_thread_area (wasm_exec_env_t exec_env); +long wali_syscall_lookup_dcookie (wasm_exec_env_t exec_env); +long wali_syscall_epoll_create (wasm_exec_env_t exec_env); +long wali_syscall_epoll_ctl_old (wasm_exec_env_t exec_env); +long wali_syscall_epoll_wait_old (wasm_exec_env_t exec_env); +long wali_syscall_remap_file_pages (wasm_exec_env_t exec_env); +long wali_syscall_getdents64 (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_set_tid_address (wasm_exec_env_t exec_env, long a1); +long wali_syscall_restart_syscall (wasm_exec_env_t exec_env); +long wali_syscall_semtimedop (wasm_exec_env_t exec_env); +long wali_syscall_fadvise (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_timer_create (wasm_exec_env_t exec_env); +long wali_syscall_timer_settime (wasm_exec_env_t exec_env); +long wali_syscall_timer_gettime (wasm_exec_env_t exec_env); +long wali_syscall_timer_getoverrun (wasm_exec_env_t exec_env); +long wali_syscall_timer_delete (wasm_exec_env_t exec_env); +long wali_syscall_clock_settime (wasm_exec_env_t exec_env); +long wali_syscall_clock_gettime (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_clock_getres (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_clock_nanosleep (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_exit_group (wasm_exec_env_t exec_env, long a1); +long wali_syscall_epoll_wait (wasm_exec_env_t exec_env); +long wali_syscall_epoll_ctl (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_tgkill (wasm_exec_env_t exec_env); +long wali_syscall_utimes (wasm_exec_env_t exec_env); +long wali_syscall_vserver (wasm_exec_env_t exec_env); +long wali_syscall_mbind (wasm_exec_env_t exec_env); +long wali_syscall_set_mempolicy (wasm_exec_env_t exec_env); +long wali_syscall_get_mempolicy (wasm_exec_env_t exec_env); +long wali_syscall_mq_open (wasm_exec_env_t exec_env); +long wali_syscall_mq_unlink (wasm_exec_env_t exec_env); +long wali_syscall_mq_timedsend (wasm_exec_env_t exec_env); +long wali_syscall_mq_timedreceive (wasm_exec_env_t exec_env); +long wali_syscall_mq_notify (wasm_exec_env_t exec_env); +long wali_syscall_mq_getsetattr (wasm_exec_env_t exec_env); +long wali_syscall_kexec_load (wasm_exec_env_t exec_env); +long wali_syscall_waitid (wasm_exec_env_t exec_env); +long wali_syscall_add_key (wasm_exec_env_t exec_env); +long wali_syscall_request_key (wasm_exec_env_t exec_env); +long wali_syscall_keyctl (wasm_exec_env_t exec_env); +long wali_syscall_ioprio_set (wasm_exec_env_t exec_env); +long wali_syscall_ioprio_get (wasm_exec_env_t exec_env); +long wali_syscall_inotify_init (wasm_exec_env_t exec_env); +long wali_syscall_inotify_add_watch (wasm_exec_env_t exec_env); +long wali_syscall_inotify_rm_watch (wasm_exec_env_t exec_env); +long wali_syscall_migrate_pages (wasm_exec_env_t exec_env); +long wali_syscall_openat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_mkdirat (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_mknodat (wasm_exec_env_t exec_env); +long wali_syscall_fchownat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_futimesat (wasm_exec_env_t exec_env); +long wali_syscall_fstatat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_unlinkat (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_renameat (wasm_exec_env_t exec_env); +long wali_syscall_linkat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_symlinkat (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_readlinkat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_fchmodat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_faccessat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_pselect6 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6); +long wali_syscall_ppoll (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_unshare (wasm_exec_env_t exec_env); +long wali_syscall_set_robust_list (wasm_exec_env_t exec_env); +long wali_syscall_get_robust_list (wasm_exec_env_t exec_env); +long wali_syscall_splice (wasm_exec_env_t exec_env); +long wali_syscall_tee (wasm_exec_env_t exec_env); +long wali_syscall_sync_file_range (wasm_exec_env_t exec_env); +long wali_syscall_vmsplice (wasm_exec_env_t exec_env); +long wali_syscall_move_pages (wasm_exec_env_t exec_env); +long wali_syscall_utimensat (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_epoll_pwait (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5, long a6); +long wali_syscall_signalfd (wasm_exec_env_t exec_env); +long wali_syscall_timerfd_create (wasm_exec_env_t exec_env); +long wali_syscall_eventfd (wasm_exec_env_t exec_env, long a1); +long wali_syscall_fallocate (wasm_exec_env_t exec_env); +long wali_syscall_timerfd_settime (wasm_exec_env_t exec_env); +long wali_syscall_timerfd_gettime (wasm_exec_env_t exec_env); +long wali_syscall_accept4 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_signalfd4 (wasm_exec_env_t exec_env); +long wali_syscall_eventfd2 (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_epoll_create1 (wasm_exec_env_t exec_env, long a1); +long wali_syscall_dup3 (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_pipe2 (wasm_exec_env_t exec_env, long a1, long a2); +long wali_syscall_inotify_init1 (wasm_exec_env_t exec_env); +long wali_syscall_preadv (wasm_exec_env_t exec_env); +long wali_syscall_pwritev (wasm_exec_env_t exec_env); +long wali_syscall_rt_tgsigqueueinfo (wasm_exec_env_t exec_env); +long wali_syscall_perf_event_open (wasm_exec_env_t exec_env); +long wali_syscall_recvmmsg (wasm_exec_env_t exec_env); +long wali_syscall_fanotify_init (wasm_exec_env_t exec_env); +long wali_syscall_fanotify_mark (wasm_exec_env_t exec_env); +long wali_syscall_prlimit64 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); +long wali_syscall_name_to_handle_at (wasm_exec_env_t exec_env); +long wali_syscall_open_by_handle_at (wasm_exec_env_t exec_env); +long wali_syscall_clock_adjtime (wasm_exec_env_t exec_env); +long wali_syscall_syncfs (wasm_exec_env_t exec_env); +long wali_syscall_sendmmsg (wasm_exec_env_t exec_env); +long wali_syscall_setns (wasm_exec_env_t exec_env); +long wali_syscall_getcpu (wasm_exec_env_t exec_env); +long wali_syscall_process_vm_readv (wasm_exec_env_t exec_env); +long wali_syscall_process_vm_writev (wasm_exec_env_t exec_env); +long wali_syscall_kcmp (wasm_exec_env_t exec_env); +long wali_syscall_finit_module (wasm_exec_env_t exec_env); +long wali_syscall_sched_setattr (wasm_exec_env_t exec_env); +long wali_syscall_sched_getattr (wasm_exec_env_t exec_env); +long wali_syscall_renameat2 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_seccomp (wasm_exec_env_t exec_env); +long wali_syscall_getrandom (wasm_exec_env_t exec_env, long a1, long a2, long a3); +long wali_syscall_memfd_create (wasm_exec_env_t exec_env); +long wali_syscall_kexec_file_load (wasm_exec_env_t exec_env); +long wali_syscall_bpf (wasm_exec_env_t exec_env); +long wali_syscall_execveat (wasm_exec_env_t exec_env); +long wali_syscall_userfaultfd (wasm_exec_env_t exec_env); +long wali_syscall_membarrier (wasm_exec_env_t exec_env); +long wali_syscall_mlock2 (wasm_exec_env_t exec_env); +long wali_syscall_copy_file_range (wasm_exec_env_t exec_env); +long wali_syscall_preadv2 (wasm_exec_env_t exec_env); +long wali_syscall_pwritev2 (wasm_exec_env_t exec_env); +long wali_syscall_pkey_mprotect (wasm_exec_env_t exec_env); +long wali_syscall_pkey_alloc (wasm_exec_env_t exec_env); +long wali_syscall_pkey_free (wasm_exec_env_t exec_env); +long wali_syscall_statx (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); +long wali_syscall_io_pgetevents (wasm_exec_env_t exec_env); +long wali_syscall_rseq (wasm_exec_env_t exec_env); +long wali_syscall_faccessat2 (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4); + +/** Alias calls **/ +long wali_syscall_ppoll_aliased (wasm_exec_env_t exec_env, long a1, long a2, long a3, long a4, long a5); + +/** Auxillary **/ +int wali_sigsetjmp (wasm_exec_env_t exec_env, int sigjmp_buf_addr, int savesigs); +void wali_siglongjmp (wasm_exec_env_t exec_env, int sigjmp_buf_addr, int val); + +/** Startup/Environment **/ +void wali_call_ctors (wasm_exec_env_t exec_env); +void wali_call_dtors (wasm_exec_env_t exec_env); +void wali_proc_exit (wasm_exec_env_t exec_env, long v); +int wali_cl_get_argc (wasm_exec_env_t exec_env); +int wali_cl_get_argv_len (wasm_exec_env_t exec_env, int arg_idx); +int wali_cl_copy_argv (wasm_exec_env_t exec_env, int argv_addr, int arg_idx); +int wali_get_init_envfile (wasm_exec_env_t exec_env, int faddr, int fsize); + +/** Threads **/ +int wali_wasm_thread_spawn (wasm_exec_env_t exec_env, int setup_fnptr, int arg_wasm); + +#endif diff --git a/core/iwasm/libraries/libc-wali/wali_arch/__sigsetjmp_tail.c b/core/iwasm/libraries/libc-wali/wali_arch/__sigsetjmp_tail.c new file mode 100644 index 0000000000..f95cdfd53c --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/__sigsetjmp_tail.c @@ -0,0 +1,9 @@ +#include "../wali.h" +#include + +__attribute__ ((visibility("hidden"))) +int __libc_sigsetjmp_tail(__libc_sigjmp_buf jb, int ret) { + void *p = jb->__ss; + syscall(SYS_rt_sigprocmask, SIG_SETMASK, ret?p:0, ret?0:p, _NSIG/8); + return ret; +} diff --git a/core/iwasm/libraries/libc-wali/wali_arch/aarch64/copy_arch.h b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/copy_arch.h new file mode 100644 index 0000000000..732a4d4352 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/copy_arch.h @@ -0,0 +1,74 @@ +/* + MIT License + + Copyright (c) [2023] [Arjun Ramesh] + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef WALI_COPY_ARCH_H +#define WALI_COPY_ARCH_H + +/* Copy for differing `struct stat` */ +extern inline void copy2wasm_stat_struct (wasm_exec_env_t exec_env, Addr wasm_stat, struct stat *n_stat) { + if (n_stat == NULL) { return; } + WR_FIELD(wasm_stat, n_stat->st_dev, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_ino, uint64_t); + + long nlink = n_stat->st_nlink; + WR_FIELD(wasm_stat, nlink, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_mode, uint32_t); + + WR_FIELD(wasm_stat, n_stat->st_uid, uint32_t); + WR_FIELD(wasm_stat, n_stat->st_gid, uint32_t); + int pad = 0; + WR_FIELD(wasm_stat, pad, uint32_t); // Pad + WR_FIELD(wasm_stat, n_stat->st_rdev, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_size, uint64_t); + + long blksize = n_stat->st_blksize; + WR_FIELD(wasm_stat, blksize, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_blocks, uint64_t); + + WR_FIELD(wasm_stat, n_stat->st_atim, struct timespec); + WR_FIELD(wasm_stat, n_stat->st_mtim, struct timespec); + WR_FIELD(wasm_stat, n_stat->st_ctim, struct timespec); +} + + +extern inline int swap_bits (int val, int b1pos, int b2pos) { + int b1 = (val >> b1pos) & 1; + int b2 = (val >> b2pos) & 1; + int x = b1 ^ b2; + x = ((x << b1pos) | (x << b2pos)); + return val ^ x; +} +/* aarch64 swaps O_DIRECTORY <-> O_DIRECT + * and O_NOFOLLOW <-> O_LARGEFILE */ +extern inline int swap_open_flags (int open_flags) { + int odirectory_shf = __builtin_ctz(O_DIRECTORY); + int odirect_shf = __builtin_ctz(O_DIRECT); + int olargefile_shf = __builtin_ctz(O_LARGEFILE); + int onofollow_shf = __builtin_ctz(O_NOFOLLOW); + int one_swap = swap_bits(open_flags, odirectory_shf, odirect_shf); + int result = swap_bits(one_swap, olargefile_shf, onofollow_shf); + return result; +} + +#endif diff --git a/core/iwasm/libraries/libc-wali/wali_arch/aarch64/setjmp/longjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/setjmp/longjmp.s new file mode 100644 index 0000000000..92037732fe --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/setjmp/longjmp.s @@ -0,0 +1,20 @@ +.global __libc_longjmp_asm +.type __libc_longjmp_asm,%function +__libc_longjmp_asm: + // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#104] + mov sp, x2 + ldp d8 , d9, [x0,#112] + ldp d10, d11, [x0,#128] + ldp d12, d13, [x0,#144] + ldp d14, d15, [x0,#160] + + cmp w1, 0 + csinc w0, w1, wzr, ne + br x30 diff --git a/core/iwasm/libraries/libc-wali/wali_arch/aarch64/setjmp/setjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/setjmp/setjmp.s new file mode 100644 index 0000000000..940c393c04 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/setjmp/setjmp.s @@ -0,0 +1,18 @@ +.global __libc_setjmp_asm +.type __libc_setjmp_asm,@function +__libc_setjmp_asm: + // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0,#104] + stp d8, d9, [x0,#112] + stp d10, d11, [x0,#128] + stp d12, d13, [x0,#144] + stp d14, d15, [x0,#160] + mov x0, #0 + ret diff --git a/core/iwasm/libraries/libc-wali/wali_arch/aarch64/signal/restore.s b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/signal/restore.s new file mode 100644 index 0000000000..75d9dc2514 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/signal/restore.s @@ -0,0 +1,8 @@ +.global __libc_restore_rt +.global __libc_restore +.type __libc_restore_rt,@function +.type __libc_restore,@function +__libc_restore_rt: +__libc_restore: + mov x8,#139 // SYS_rt_sigreturn + svc 0 diff --git a/core/iwasm/libraries/libc-wali/wali_arch/aarch64/signal/sigsetjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/signal/sigsetjmp.s new file mode 100644 index 0000000000..a12cf72913 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/signal/sigsetjmp.s @@ -0,0 +1,18 @@ +.global __libc_sigsetjmp_asm +.type __libc_sigsetjmp_asm,@function +__libc_sigsetjmp_asm: + cbz x1,__libc_setjmp_asm + + str x30,[x0,#176] + str x19,[x0,#176+8+8] + mov x19,x0 + + bl __libc_setjmp_asm + + mov w1,w0 + mov x0,x19 + ldr x30,[x0,#176] + ldr x19,[x0,#176+8+8] + +.hidden __libc_sigsetjmp_tail + b __libc_sigsetjmp_tail diff --git a/core/iwasm/libraries/libc-wali/wali_arch/aarch64/syscall.h b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/syscall.h new file mode 100644 index 0000000000..44314001d9 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/aarch64/syscall.h @@ -0,0 +1,73 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(x0) : __VA_ARGS__ : "memory", "cc"); \ + return x0; \ + } while (0) + +static inline long __syscall0(long n) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0"); + __asm_syscall("r"(x8)); +} + +static inline long __syscall1(long n, long a) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + __asm_syscall("r"(x8), "0"(x0)); +} + +static inline long __syscall2(long n, long a, long b) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + __asm_syscall("r"(x8), "0"(x0), "r"(x1)); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2)); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + register long x5 __asm__("x5") = f; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)); +} + diff --git a/core/iwasm/libraries/libc-wali/wali_arch/riscv64/copy_arch.h b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/copy_arch.h new file mode 100644 index 0000000000..4086701ffe --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/copy_arch.h @@ -0,0 +1,54 @@ +/* + MIT License + + Copyright (c) [2023] [Arjun Ramesh] + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef WALI_COPY_ARCH_H +#define WALI_COPY_ARCH_H + +/* Copy for differing `struct stat` */ +extern inline void copy2wasm_stat_struct (wasm_exec_env_t exec_env, Addr wasm_stat, struct stat *n_stat) { + if (n_stat == NULL) { return; } + WR_FIELD(wasm_stat, n_stat->st_dev, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_ino, uint64_t); + + long nlink = n_stat->st_nlink; + WR_FIELD(wasm_stat, nlink, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_mode, uint32_t); + + WR_FIELD(wasm_stat, n_stat->st_uid, uint32_t); + WR_FIELD(wasm_stat, n_stat->st_gid, uint32_t); + int pad = 0; + WR_FIELD(wasm_stat, pad, uint32_t); // Pad + WR_FIELD(wasm_stat, n_stat->st_rdev, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_size, uint64_t); + + long blksize = n_stat->st_blksize; + WR_FIELD(wasm_stat, blksize, uint64_t); + WR_FIELD(wasm_stat, n_stat->st_blocks, uint64_t); + + WR_FIELD(wasm_stat, n_stat->st_atim, struct timespec); + WR_FIELD(wasm_stat, n_stat->st_mtim, struct timespec); + WR_FIELD(wasm_stat, n_stat->st_ctim, struct timespec); +} + +#endif diff --git a/core/iwasm/libraries/libc-wali/wali_arch/riscv64/setjmp/longjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/setjmp/longjmp.s new file mode 100644 index 0000000000..5b0f0aed86 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/setjmp/longjmp.s @@ -0,0 +1,38 @@ +/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ +.global __libc_longjmp_asm +.type __libc_longjmp_asm,@function +__libc_longjmp_asm: + ld s0, 0(a0) + ld s1, 8(a0) + ld s2, 16(a0) + ld s3, 24(a0) + ld s4, 32(a0) + ld s5, 40(a0) + ld s6, 48(a0) + ld s7, 56(a0) + ld s8, 64(a0) + ld s9, 72(a0) + ld s10, 80(a0) + ld s11, 88(a0) + ld sp, 96(a0) + ld ra, 104(a0) + +#ifndef __riscv_float_abi_soft + fld fs0, 112(a0) + fld fs1, 120(a0) + fld fs2, 128(a0) + fld fs3, 136(a0) + fld fs4, 144(a0) + fld fs5, 152(a0) + fld fs6, 160(a0) + fld fs7, 168(a0) + fld fs8, 176(a0) + fld fs9, 184(a0) + fld fs10, 192(a0) + fld fs11, 200(a0) +#endif + + seqz a0, a1 + add a0, a0, a1 + ret + diff --git a/core/iwasm/libraries/libc-wali/wali_arch/riscv64/setjmp/setjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/setjmp/setjmp.s new file mode 100644 index 0000000000..26ccf54f95 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/setjmp/setjmp.s @@ -0,0 +1,35 @@ +.global __libc_setjmp_asm +.type __libc_setjmp_asm,@function +__libc_setjmp_asm: + sd s0, 0(a0) + sd s1, 8(a0) + sd s2, 16(a0) + sd s3, 24(a0) + sd s4, 32(a0) + sd s5, 40(a0) + sd s6, 48(a0) + sd s7, 56(a0) + sd s8, 64(a0) + sd s9, 72(a0) + sd s10, 80(a0) + sd s11, 88(a0) + sd sp, 96(a0) + sd ra, 104(a0) + +#ifndef __riscv_float_abi_soft + fsd fs0, 112(a0) + fsd fs1, 120(a0) + fsd fs2, 128(a0) + fsd fs3, 136(a0) + fsd fs4, 144(a0) + fsd fs5, 152(a0) + fsd fs6, 160(a0) + fsd fs7, 168(a0) + fsd fs8, 176(a0) + fsd fs9, 184(a0) + fsd fs10, 192(a0) + fsd fs11, 200(a0) +#endif + + li a0, 0 + ret diff --git a/core/iwasm/libraries/libc-wali/wali_arch/riscv64/signal/restore.s b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/signal/restore.s new file mode 100644 index 0000000000..fceacae011 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/signal/restore.s @@ -0,0 +1,9 @@ +.global __libc_restore_rt +.global __libc_restore +.type __libc_restore_rt,@function +.type __libc_restore,@function +__libc_restore_rt: +__libc_restore: + li a7, 139 # SYS_rt_sigreturn + ecall + diff --git a/core/iwasm/libraries/libc-wali/wali_arch/riscv64/signal/sigsetjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/signal/sigsetjmp.s new file mode 100644 index 0000000000..a70cba9bad --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/signal/sigsetjmp.s @@ -0,0 +1,21 @@ +.global __libc_sigsetjmp_asm +.type __libc_sigsetjmp_asm,@function +__libc_sigsetjmp_asm: + bnez a1, 1f + tail __libc_setjmp_asm +1: + + sd ra, 208(a0) + sd s0, 224(a0) + mv s0, a0 + + call __libc_setjmp_asm + + mv a1, a0 + mv a0, s0 + ld s0, 224(a0) + ld ra, 208(a0) + +.hidden __libc_sigsetjmp_tail + tail __libc_sigsetjmp_tail + diff --git a/core/iwasm/libraries/libc-wali/wali_arch/riscv64/syscall.h b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/syscall.h new file mode 100644 index 0000000000..31435f3ae1 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/riscv64/syscall.h @@ -0,0 +1,72 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(...) \ + __asm__ __volatile__ ("ecall\n\t" \ + : "=r"(a0) : __VA_ARGS__ : "memory"); \ + return a0; \ + +static inline long __syscall0(long n) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0"); + __asm_syscall("r"(a7)) +} + +static inline long __syscall1(long n, long a) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + __asm_syscall("r"(a7), "0"(a0)) +} + +static inline long __syscall2(long n, long a, long b) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + __asm_syscall("r"(a7), "0"(a0), "r"(a1)) +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2)) +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3)) +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + register long a4 __asm__("a4") = e; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)) +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + register long a4 __asm__("a4") = e; + register long a5 __asm__("a5") = f; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)) +} + diff --git a/core/iwasm/libraries/libc-wali/wali_arch/x86_64/atomics.h b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/atomics.h new file mode 100644 index 0000000000..c941f9ee44 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/atomics.h @@ -0,0 +1,115 @@ + +/***** Atomics *****/ +int wali_a_cas (wasm_exec_env_t exec_env, long p, int t, int s) { + ATOM(a_cas); + __asm__ __volatile__ ( + "lock ; cmpxchg %3, %1" + : "=a"(t), "=m"(*MADDR(p)) : "a"(t), "r"(s) : "memory" ); + return t; + +} + +int wali_a_cas_p (wasm_exec_env_t exec_env, long p, long t, long s) { + ATOM(a_cas_p); + Addr tm = MADDR(t); + __asm__( "lock ; cmpxchg %3, %1" + : "=a"(tm), "=m"(*(void *volatile *)MADDR(p)) + : "a"(tm), "r"(MADDR(s)) : "memory" ); + return WADDR(tm); +} + +int wali_a_swap (wasm_exec_env_t exec_env, long p, int v) { + ATOM(a_swap); + __asm__ __volatile__( + "xchg %0, %1" + : "=r"(v), "=m"(*MADDR(p)) : "0"(v) : "memory" ); + return v; +} + +int wali_a_fetch_add (wasm_exec_env_t exec_env, long p, int v) { + ATOM(a_fetch_add); + __asm__ __volatile__( + "lock ; xadd %0, %1" + : "=r"(v), "=m"(*MADDR(p)) : "0"(v) : "memory" ); + return v; +} + +void wali_a_and (wasm_exec_env_t exec_env, long p, int v) { + ATOM(a_and); + __asm__ __volatile__( + "lock ; and %1, %0" + : "=m"(*MADDR(p)) : "r"(v) : "memory" ); +} + +void wali_a_or (wasm_exec_env_t exec_env, long p, int v) { + ATOM(a_or); + __asm__ __volatile__( + "lock ; or %1, %0" + : "=m"(*MADDR(p)) : "r"(v) : "memory" ); +} + +void wali_a_and_64 (wasm_exec_env_t exec_env, long p, long v) { + ATOM(a_and_64); + __asm__ __volatile( + "lock ; and %1, %0" + : "=m"(*MADDR(p)) : "r"(v) : "memory" ); +} + +void wali_a_or_64 (wasm_exec_env_t exec_env, long p, long v) { + ATOM(a_or_64); + __asm__ __volatile__( + "lock ; or %1, %0" + : "=m"(*MADDR(p)) : "r"(v) : "memory" ); +} + +void wali_a_inc (wasm_exec_env_t exec_env, long p) { + ATOM(a_inc); + Addr pm = MADDR(p); + __asm__ __volatile__( + "lock ; incl %0" + : "=m"(*pm) : "m"(*pm) : "memory" ); +} + +void wali_a_dec (wasm_exec_env_t exec_env, long p) { + ATOM(a_dec); + Addr pm = MADDR(p); + __asm__ __volatile__( + "lock ; decl %0" + : "=m"(*pm) : "m"(*pm) : "memory" ); +} + +void wali_a_store (wasm_exec_env_t exec_env, long p, int x) { + ATOM(a_store); + __asm__ __volatile__( + "mov %1, %0 ; lock ; orl $0,(%%rsp)" + : "=m"(*MADDR(p)) : "r"(x) : "memory" ); +} + +void wali_a_barrier (wasm_exec_env_t exec_env) { + ATOM(a_barrier); + __asm__ __volatile__( "" : : : "memory" ); +} + +void wali_a_spin (wasm_exec_env_t exec_env) { + ATOM(a_spin); + __asm__ __volatile__( "pause" : : : "memory" ); +} + +void wali_a_crash (wasm_exec_env_t exec_env) { + ATOM(a_crash); + __asm__ __volatile__( "hlt" : : : "memory" ); +} + +int wali_a_ctz_64 (wasm_exec_env_t exec_env, long x) { + ATOM(a_ctz_64); + __asm__( "bsf %1,%0" : "=r"(x) : "r"(x) ); + return x; +} + +int wali_a_clz_64 (wasm_exec_env_t exec_env, long x) { + ATOM(a_clz_64); + __asm__( "bsr %1,%0 ; xor $63,%0" : "=r"(x) : "r"(x) ); + return x; +} + +/*************************/ diff --git a/core/iwasm/libraries/libc-wali/wali_arch/x86_64/setjmp/longjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/setjmp/longjmp.s new file mode 100644 index 0000000000..d114578d82 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/setjmp/longjmp.s @@ -0,0 +1,15 @@ +/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ +.global __libc_longjmp_asm +.type __libc_longjmp_asm,@function +__libc_longjmp_asm: + xor %eax,%eax + cmp $1,%esi /* CF = val ? 0 : 1 */ + adc %esi,%eax /* eax = val + !val */ + mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */ + mov 8(%rdi),%rbp + mov 16(%rdi),%r12 + mov 24(%rdi),%r13 + mov 32(%rdi),%r14 + mov 40(%rdi),%r15 + mov 48(%rdi),%rsp + jmp *56(%rdi) /* goto saved address without altering rsp */ diff --git a/core/iwasm/libraries/libc-wali/wali_arch/x86_64/setjmp/setjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/setjmp/setjmp.s new file mode 100644 index 0000000000..ea66febee0 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/setjmp/setjmp.s @@ -0,0 +1,16 @@ +/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ +.global __libc_setjmp_asm +.type __libc_setjmp_asm,@function +__libc_setjmp_asm: + mov %rbx,(%rdi) /* rdi is jmp_buf, move registers onto it */ + mov %rbp,8(%rdi) + mov %r12,16(%rdi) + mov %r13,24(%rdi) + mov %r14,32(%rdi) + mov %r15,40(%rdi) + lea 8(%rsp),%rdx /* this is our rsp WITHOUT current ret addr */ + mov %rdx,48(%rdi) + mov (%rsp),%rdx /* save return addr ptr for new rip */ + mov %rdx,56(%rdi) + xor %eax,%eax /* always return 0 */ + ret diff --git a/core/iwasm/libraries/libc-wali/wali_arch/x86_64/signal/restore.s b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/signal/restore.s new file mode 100644 index 0000000000..b44c99eff8 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/signal/restore.s @@ -0,0 +1,8 @@ +.global __libc_restore_rt +.global __libc_restore +.type __libc_restore_rt,@function +.type __libc_restore,@function +__libc_restore_rt: +__libc_restore: + movl $15, %eax + syscall diff --git a/core/iwasm/libraries/libc-wali/wali_arch/x86_64/signal/sigsetjmp.s b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/signal/sigsetjmp.s new file mode 100644 index 0000000000..56e6e44052 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/signal/sigsetjmp.s @@ -0,0 +1,21 @@ +.global __libc_sigsetjmp_asm +.type __libc_sigsetjmp_asm,@function +__libc_sigsetjmp_asm: + test %esi,%esi + jz 1f + + popq 64(%rdi) + mov %rbx,72+8(%rdi) + mov %rdi,%rbx + + call __libc_setjmp_asm@PLT + + pushq 64(%rbx) + mov %rbx,%rdi + mov %eax,%esi + mov 72+8(%rbx),%rbx + +.hidden __libc_sigsetjmp_tail + jmp __libc_sigsetjmp_tail + +1: jmp __libc_setjmp_asm@PLT diff --git a/core/iwasm/libraries/libc-wali/wali_arch/x86_64/syscall.h b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/syscall.h new file mode 100644 index 0000000000..a85c440c27 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_arch/x86_64/syscall.h @@ -0,0 +1,62 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +static __inline long __syscall0(long n) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall1(long n, long a1) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall2(long n, long a1, long a2) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) + : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall3(long n, long a1, long a2, long a3) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10): "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + register long r9 __asm__("r9") = a6; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); + return ret; +} diff --git a/core/iwasm/libraries/libc-wali/wali_defs.h b/core/iwasm/libraries/libc-wali/wali_defs.h new file mode 100644 index 0000000000..e01acc6595 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_defs.h @@ -0,0 +1,35 @@ +#ifndef _WALI_DEFS_H_ +#define _WALI_DEFS_H_ + +/** Architecture **/ +#ifndef __riscv64__ +#if __riscv + #if __riscv_xlen == 64 + #define __riscv64__ 1 + #endif +#endif +#endif + +#if !__x86_64__ && !__aarch64__ && !__riscv64__ +#error "Unsupported architecture for WALI -- Only supports [x86_64, aarch64, riscv64]" +#endif + + +/** Memory defines **/ +#define WASM_PAGESIZE 65536 + +/** Signal defines **/ +#define WASM_SIG_DFL (0) +#define WASM_SIG_ERR (-1) +#define WASM_SIG_IGN (-2) + +#define SIG_MEM_PROF 37 +#define SIG_SYSCALL_PROF 38 +#define SIG_WASM_THREAD_TERM 39 + +extern bool invoked_wali; +extern int wali_app_argc; +extern char **wali_app_argv; +extern char *wali_app_env_file; + +#endif diff --git a/core/iwasm/libraries/libc-wali/wali_init.h b/core/iwasm/libraries/libc-wali/wali_init.h new file mode 100644 index 0000000000..0c42e69e24 --- /dev/null +++ b/core/iwasm/libraries/libc-wali/wali_init.h @@ -0,0 +1,8 @@ +#ifndef _WALI_INIT_H +#define _WALI_INIT_H + +#include "wasm_export.h" + +void wali_init_native (wasm_module_inst_t module_inst); + +#endif diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 49545de727..9ce23bf584 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -16,6 +16,10 @@ #include "debug_engine.h" #endif +#if WASM_ENABLE_LIBC_WALI != 0 +#include "../../../libc-wali/wali_defs.h" +#endif + typedef struct { bh_list_link l; void (*destroy_cb)(WASMCluster *); @@ -1278,6 +1282,10 @@ set_exception_visitor(void *node, void *user_data) /* Terminate the thread so it can exit from dead loops */ if (data->exception != NULL) { set_thread_cancel_flags(exec_env); +#if WASM_ENABLE_LIBC_WALI != 0 + /* Force suspended threads to wake */ + pthread_kill(exec_env->handle, SIG_WASM_THREAD_TERM); +#endif } else { clear_thread_cancel_flags(exec_env); diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index ecd08655c3..d706c8e50e 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required (VERSION 3.14) include(CheckPIESupported) -project (iwasm) +project (iwasm LANGUAGES C ASM) set (CMAKE_VERBOSE_MAKEFILE OFF) diff --git a/product-mini/platforms/linux/main.c b/product-mini/platforms/linux/main.c index 8f0e84a97f..a1defb2ab5 100644 --- a/product-mini/platforms/linux/main.c +++ b/product-mini/platforms/linux/main.c @@ -2,5 +2,4 @@ * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ - #include "../posix/main.c" diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index b27bd8c2e5..4ca1fe4134 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -18,8 +18,13 @@ #include #endif +#if WASM_ENABLE_LIBC_WALI != 0 +#include "../libraries/libc-wali/wali_defs.h" +#endif + static int app_argc; static char **app_argv; +static char *app_env_file; /* clang-format off */ static int @@ -109,6 +114,7 @@ print_help() #if WASM_ENABLE_STATIC_PGO != 0 printf(" --gen-prof-file= Generate LLVM PGO (Profile-Guided Optimization) profile file\n"); #endif + printf(" --env-file= WALI environment variables initialization file\n"); printf(" --version Show version information\n"); return 1; } @@ -818,6 +824,14 @@ main(int argc, char *argv[]) return print_help(); gen_prof_file = argv[0] + 16; } +#endif +#if WASM_ENABLE_LIBC_WALI != 0 + else if (!strncmp(argv[0], "--env-file=", 11)) { + if (argv[0][11] == '\0') + return print_help(); + app_env_file = argv[0] + 11; + wali_app_env_file = app_env_file; + } #endif else if (!strncmp(argv[0], "--version", 9)) { uint32 major, minor, patch; @@ -837,9 +851,11 @@ main(int argc, char *argv[]) app_argc = argc; app_argv = argv; + /* Set init args */ memset(&init_args, 0, sizeof(RuntimeInitArgs)); init_args.running_mode = running_mode; + #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 init_args.mem_alloc_type = Alloc_With_Pool; init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; @@ -995,10 +1011,17 @@ main(int argc, char *argv[]) } } -#if WASM_ENABLE_LIBC_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_LIBC_WALI != 0 if (ret == 0) { - /* propagate wasi exit code. */ - ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); + /* wait for threads to finish and propagate exit code. */ + if (invoked_wali) { + ret = wasm_runtime_get_wali_exit_code(wasm_module_inst); + if (ret) { + printf("Exit code Fail: %d\n", ret); + } + } + else + ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); } #endif diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index ba0902cdf2..2a736ee861 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -34,7 +34,8 @@ set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") add_definitions(-DWASM_ENABLE_INTERP=1) add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1) add_definitions(-DWASM_ENABLE_BULK_MEMORY=1) -add_definitions(-DWASM_DISABLE_HW_BOUND_CHECK=1) +add_definitions(-DWASM_DISABLE_HW_BOUND_CHECK=0) +add_definitions(-DWASM_ENABLE_MULTI_MODULE=1) add_definitions(-DWASM_ENABLE_SHARED_MEMORY=1) add_definitions(-DWASM_ENABLE_THREAD_MGR=1) add_definitions(-DWASM_ENABLE_TAIL_CALL=1) @@ -47,6 +48,10 @@ add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1) add_definitions(-DWASM_ENABLE_LIB_WASI_THREADS=1) add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1) +add_compile_definitions(WALI_ENABLE_SIGNAL_HANDLING=1) +add_compile_definitions(WALI_ENABLE_LOOP_SIGPOLL=1) + + if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1) add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1) endif() diff --git a/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h b/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h index 802e9ac5bf..1cb4f2f5a9 100644 --- a/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h @@ -29,6 +29,44 @@ typedef unsigned short int uint16_t; typedef unsigned int uint32_t; typedef unsigned long long int uint64_t; +/* For atomics */ +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; + +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN + +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX + +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + + + typedef __INTPTR_TYPE__ intptr_t; typedef __UINTPTR_TYPE__ uintptr_t; @@ -82,10 +120,35 @@ typedef __UINTPTR_TYPE__ uintptr_t; #define SIZE_MAX UINT32_MAX #endif +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + + /* clang-format on */ #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif