Add WASI ABI compatibility check for multi-module (#913)
Refer to https://github.com/WebAssembly/WASI/blob/main/design/application-abi.md to check the WASI ABI compatibility: - Command (main module) may export _start function with signature "()" - Reactor (sub module) may export _initialize function with signature "()" - _start and _initialize can not be exported at the same time - Reactor cannot export _start function - Command and Reactor must export memory And - Rename module->is_wasi_module to module->import_wasi_api - Refactor wasm_loader_find_export() - Remove MULTI_MODULE related codes from mini_loader - Update multi-module samples - Fix a "use-after-free" issue. Since we reuse the memory instance of sub module, just to protect it from freeing an imported memory instance
This commit is contained in:
@ -48,10 +48,6 @@ static union {
|
||||
/**
|
||||
* Implementation of wasm_application_execute_main()
|
||||
*/
|
||||
|
||||
static WASMFunctionInstanceCommon *
|
||||
resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name);
|
||||
|
||||
static bool
|
||||
check_main_func_type(const WASMType *type)
|
||||
{
|
||||
@ -96,23 +92,29 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
|
||||
bool ret, is_import_func = true;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if (wasm_runtime_is_wasi_mode(module_inst)) {
|
||||
/* In wasi mode, we should call function named "_start"
|
||||
which initializes the wasi envrionment and then calls
|
||||
the actual main function. Directly call main function
|
||||
may cause exception thrown. */
|
||||
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst)))
|
||||
return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func,
|
||||
0, NULL);
|
||||
/* If no start function was found, we execute
|
||||
the main function as normal */
|
||||
/* In wasi mode, we should call function named "_start"
|
||||
which initializes the wasi envrionment and then calls
|
||||
the actual main function. Directly call main function
|
||||
may cause exception thrown. */
|
||||
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
|
||||
return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, 0,
|
||||
NULL);
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
if (!(func = resolve_function(module_inst, "main"))
|
||||
&& !(func = resolve_function(module_inst, "__main_argc_argv"))
|
||||
&& !(func = resolve_function(module_inst, "_main"))) {
|
||||
wasm_runtime_set_exception(module_inst, "lookup main function failed");
|
||||
if (!(func = wasm_runtime_lookup_function(module_inst, "main", NULL))
|
||||
&& !(func = wasm_runtime_lookup_function(module_inst,
|
||||
"__main_argc_argv", NULL))
|
||||
&& !(func = wasm_runtime_lookup_function(module_inst, "_main", NULL))) {
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasm_runtime_set_exception(
|
||||
module_inst, "lookup the entry point symbol (like _start, main, "
|
||||
"_main, __main_argc_argv) failed");
|
||||
#else
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"lookup the entry point symbol (like main, "
|
||||
"_main, __main_argc_argv) failed");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -238,21 +240,23 @@ parse_function_name(char *orig_function_name, char **p_module_name,
|
||||
* Implementation of wasm_application_execute_func()
|
||||
*/
|
||||
|
||||
static WASMFunctionInstanceCommon *
|
||||
resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name)
|
||||
static bool
|
||||
resolve_function(WASMModuleInstanceCommon *module_inst, const char *name,
|
||||
WASMFunctionInstanceCommon **out_func,
|
||||
WASMModuleInstanceCommon **out_module_inst)
|
||||
{
|
||||
uint32 i = 0;
|
||||
WASMFunctionInstanceCommon *ret = NULL;
|
||||
WASMFunctionInstanceCommon *target_func = NULL;
|
||||
WASMModuleInstanceCommon *target_inst = NULL;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModuleInstance *sub_module_inst = NULL;
|
||||
char *function_name = NULL;
|
||||
char *orig_name = NULL;
|
||||
char *sub_module_name = NULL;
|
||||
char *function_name = NULL;
|
||||
uint32 length = (uint32)(strlen(name) + 1);
|
||||
|
||||
orig_name = runtime_malloc(sizeof(char) * length, NULL, NULL, 0);
|
||||
if (!orig_name) {
|
||||
return NULL;
|
||||
goto LEAVE;
|
||||
}
|
||||
|
||||
strncpy(orig_name, name, length);
|
||||
@ -264,53 +268,33 @@ resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name)
|
||||
LOG_DEBUG("%s -> %s and %s", name, sub_module_name, function_name);
|
||||
|
||||
if (sub_module_name) {
|
||||
sub_module_inst = get_sub_module_inst((WASMModuleInstance *)module_inst,
|
||||
sub_module_name);
|
||||
if (!sub_module_inst) {
|
||||
target_inst = (WASMModuleInstanceCommon *)get_sub_module_inst(
|
||||
(WASMModuleInstance *)module_inst, sub_module_name);
|
||||
if (!target_inst) {
|
||||
LOG_DEBUG("can not find a sub module named %s", sub_module_name);
|
||||
goto LEAVE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
target_inst = module_inst;
|
||||
}
|
||||
#else
|
||||
const char *function_name = name;
|
||||
target_inst = module_inst;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
wasm_inst = sub_module_inst ? sub_module_inst : wasm_inst;
|
||||
#endif /* WASM_ENABLE_MULTI_MODULE */
|
||||
|
||||
for (i = 0; i < wasm_inst->export_func_count; i++) {
|
||||
if (!strcmp(wasm_inst->export_functions[i].name, function_name)) {
|
||||
ret = wasm_inst->export_functions[i].function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WASM_ENABLE_INTERP */
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst;
|
||||
AOTFunctionInstance *export_funcs =
|
||||
(AOTFunctionInstance *)aot_inst->export_funcs.ptr;
|
||||
for (i = 0; i < aot_inst->export_func_count; i++) {
|
||||
if (!strcmp(export_funcs[i].func_name, function_name)) {
|
||||
ret = &export_funcs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
target_func =
|
||||
wasm_runtime_lookup_function(target_inst, function_name, NULL);
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
LEAVE:
|
||||
wasm_runtime_free(orig_name);
|
||||
if (orig_name)
|
||||
wasm_runtime_free(orig_name);
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
*out_func = target_func;
|
||||
*out_module_inst = target_inst;
|
||||
return target_func;
|
||||
}
|
||||
|
||||
union ieee754_float {
|
||||
@ -358,7 +342,8 @@ bool
|
||||
wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
const char *name, int32 argc, char *argv[])
|
||||
{
|
||||
WASMFunctionInstanceCommon *func;
|
||||
WASMFunctionInstanceCommon *target_func;
|
||||
WASMModuleInstanceCommon *target_inst;
|
||||
WASMType *type = NULL;
|
||||
uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
|
||||
int32 i, p, module_type;
|
||||
@ -368,31 +353,15 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
|
||||
bh_assert(argc >= 0);
|
||||
LOG_DEBUG("call a function \"%s\" with %d arguments", name, argc);
|
||||
func = resolve_function(module_inst, name);
|
||||
|
||||
if (!func) {
|
||||
if (!resolve_function(module_inst, name, &target_func, &target_inst)) {
|
||||
snprintf(buf, sizeof(buf), "lookup function %s failed", name);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMFunctionInstance *wasm_func = (WASMFunctionInstance *)func;
|
||||
if (wasm_func->is_import_func
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
&& !wasm_func->import_func_inst
|
||||
#endif
|
||||
) {
|
||||
snprintf(buf, sizeof(buf), "lookup function %s failed", name);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
module_type = module_inst->module_type;
|
||||
type = wasm_runtime_get_function_type(func, module_type);
|
||||
module_type = target_inst->module_type;
|
||||
type = wasm_runtime_get_function_type(target_func, module_type);
|
||||
|
||||
if (!type) {
|
||||
LOG_ERROR("invalid module instance type");
|
||||
@ -408,7 +377,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
|
||||
|
||||
total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
|
||||
if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst, NULL, 0)))) {
|
||||
if ((!(argv1 = runtime_malloc((uint32)total_size, target_inst, NULL, 0)))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -538,7 +507,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
void *extern_obj = (void *)(uintptr_t)val;
|
||||
uint32 externref_idx;
|
||||
|
||||
if (!wasm_externref_obj2ref(module_inst, extern_obj,
|
||||
if (!wasm_externref_obj2ref(target_inst, extern_obj,
|
||||
&externref_idx)) {
|
||||
wasm_runtime_set_exception(
|
||||
module_inst, "map extern object to ref failed");
|
||||
@ -563,8 +532,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
bh_assert(p == (int32)argc1);
|
||||
|
||||
wasm_runtime_set_exception(module_inst, NULL);
|
||||
if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1,
|
||||
argv1)) {
|
||||
if (!wasm_runtime_create_exec_env_and_call_wasm(target_inst, target_func,
|
||||
argc1, argv1)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user