mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 06:55:07 +00:00
Merge branch main into dev/shared_heap
This commit is contained in:
commit
1fd422ae6e
|
@ -124,7 +124,8 @@ include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
|||
if (NOT WIN32)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security \
|
||||
-ffunction-sections -fdata-sections \
|
||||
-Wno-unused-parameter -Wno-pedantic")
|
||||
-Wno-unused-parameter -Wno-pedantic \
|
||||
-fvisibility=hidden")
|
||||
# Remove the extra spaces for better make log
|
||||
string (REGEX REPLACE " *" " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wno-unused")
|
||||
|
@ -168,7 +169,7 @@ if (WAMR_BUILD_STATIC)
|
|||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(iwasm_static PRIVATE ntdll)
|
||||
target_link_libraries(iwasm_static PRIVATE ntdll)
|
||||
endif()
|
||||
|
||||
install (TARGETS iwasm_static ARCHIVE DESTINATION lib)
|
||||
|
@ -190,7 +191,7 @@ if (WAMR_BUILD_SHARED)
|
|||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(iwasm_shared PRIVATE ntdll)
|
||||
target_link_libraries(iwasm_shared PRIVATE ntdll)
|
||||
endif()
|
||||
|
||||
install (TARGETS iwasm_shared LIBRARY DESTINATION lib)
|
||||
|
|
|
@ -409,6 +409,10 @@ endif ()
|
|||
if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
|
||||
message (" Debug AOT enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_DYNAMIC_AOT_DEBUG EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_DYNAMIC_AOT_DEBUG=1)
|
||||
message (" Dynamic AOT debug enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_LOAD_CUSTOM_SECTION EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
|
||||
message (" Load custom section enabled")
|
||||
|
|
|
@ -75,6 +75,10 @@
|
|||
#define WASM_ENABLE_AOT 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_DYNAMIC_AOT_DEBUG
|
||||
#define WASM_ENABLE_DYNAMIC_AOT_DEBUG 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_WORD_ALIGN_READ
|
||||
#define WASM_ENABLE_WORD_ALIGN_READ 0
|
||||
#endif
|
||||
|
|
|
@ -634,73 +634,6 @@ str2uint32(const char *buf, uint32 *p_res);
|
|||
static bool
|
||||
str2uint64(const char *buf, uint64 *p_res);
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static void *
|
||||
aot_loader_resolve_function(const AOTModule *module, const char *function_name,
|
||||
const AOTFuncType *expected_function_type,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
static void *
|
||||
aot_loader_resolve_function_ex(const char *module_name,
|
||||
const char *function_name,
|
||||
const AOTFuncType *expected_function_type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMModuleCommon *module_reg;
|
||||
|
||||
module_reg = wasm_runtime_find_module_registered(module_name);
|
||||
if (!module_reg || module_reg->module_type != Wasm_Module_AoT) {
|
||||
LOG_DEBUG("can not find a module named %s for function %s", module_name,
|
||||
function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "unknown import");
|
||||
return NULL;
|
||||
}
|
||||
return aot_loader_resolve_function((AOTModule *)module_reg, function_name,
|
||||
expected_function_type, error_buf,
|
||||
error_buf_size);
|
||||
}
|
||||
|
||||
static void *
|
||||
aot_loader_resolve_function(const AOTModule *module, const char *function_name,
|
||||
const AOTFuncType *expected_function_type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
void *function = NULL;
|
||||
AOTExport *export = NULL;
|
||||
AOTFuncType *target_function_type = NULL;
|
||||
|
||||
export = loader_find_export((WASMModuleCommon *)module, module->name,
|
||||
function_name, EXPORT_KIND_FUNC, error_buf,
|
||||
error_buf_size);
|
||||
if (!export) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* resolve function type and function */
|
||||
if (export->index < module->import_func_count) {
|
||||
target_function_type = module->import_funcs[export->index].func_type;
|
||||
function = module->import_funcs[export->index].func_ptr_linked;
|
||||
}
|
||||
else {
|
||||
target_function_type =
|
||||
(AOTFuncType *)module
|
||||
->types[module->func_type_indexes[export->index
|
||||
- module->import_func_count]];
|
||||
function =
|
||||
(module->func_ptrs[export->index - module->import_func_count]);
|
||||
}
|
||||
/* check function type */
|
||||
if (!wasm_type_equal((WASMType *)expected_function_type,
|
||||
(WASMType *)target_function_type, module->types,
|
||||
module->type_count)) {
|
||||
LOG_DEBUG("%s.%s failed the type check", module->name, function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "incompatible import type");
|
||||
return NULL;
|
||||
}
|
||||
return function;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_MULTI_MODULE */
|
||||
|
||||
static bool
|
||||
load_native_symbol_section(const uint8 *buf, const uint8 *buf_end,
|
||||
AOTModule *module, bool is_load_from_file_buf,
|
||||
|
@ -2285,19 +2218,13 @@ destroy_import_funcs(AOTImportFunc *import_funcs)
|
|||
|
||||
static bool
|
||||
load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||
bool is_load_from_file_buf, char *error_buf,
|
||||
bool is_load_from_file_buf, bool no_resolve, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
char *module_name, *field_name;
|
||||
const uint8 *buf = *p_buf;
|
||||
AOTImportFunc *import_funcs;
|
||||
uint64 size;
|
||||
uint32 i;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
AOTModule *sub_module = NULL;
|
||||
AOTFunc *linked_func = NULL;
|
||||
AOTFuncType *declare_func_type = NULL;
|
||||
#endif
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTImportFunc) * (uint64)module->import_func_count;
|
||||
|
@ -2314,53 +2241,17 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
declare_func_type =
|
||||
(AOTFuncType *)module->types[import_funcs[i].func_type_index];
|
||||
read_string(buf, buf_end, module_name);
|
||||
read_string(buf, buf_end, field_name);
|
||||
|
||||
import_funcs[i].module_name = module_name;
|
||||
import_funcs[i].func_name = field_name;
|
||||
linked_func = wasm_native_resolve_symbol(
|
||||
module_name, field_name, declare_func_type,
|
||||
&import_funcs[i].signature, &import_funcs[i].attachment,
|
||||
&import_funcs[i].call_conv_raw);
|
||||
if (!linked_func) {
|
||||
sub_module = NULL;
|
||||
if (!wasm_runtime_is_built_in_module(module_name)) {
|
||||
sub_module = (AOTModule *)wasm_runtime_load_depended_module(
|
||||
(WASMModuleCommon *)module, module_name, error_buf,
|
||||
error_buf_size);
|
||||
if (!sub_module) {
|
||||
LOG_ERROR("failed to load sub module: %s", error_buf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!sub_module)
|
||||
linked_func = aot_loader_resolve_function_ex(
|
||||
module_name, field_name, declare_func_type, error_buf,
|
||||
error_buf_size);
|
||||
else
|
||||
linked_func = aot_loader_resolve_function(
|
||||
sub_module, field_name, declare_func_type, error_buf,
|
||||
error_buf_size);
|
||||
}
|
||||
import_funcs[i].func_ptr_linked = linked_func;
|
||||
import_funcs[i].func_type = declare_func_type;
|
||||
|
||||
#else
|
||||
import_funcs[i].func_type =
|
||||
(AOTFuncType *)module->types[import_funcs[i].func_type_index];
|
||||
read_string(buf, buf_end, import_funcs[i].module_name);
|
||||
read_string(buf, buf_end, import_funcs[i].func_name);
|
||||
module_name = import_funcs[i].module_name;
|
||||
field_name = import_funcs[i].func_name;
|
||||
import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol(
|
||||
module_name, field_name, import_funcs[i].func_type,
|
||||
&import_funcs[i].signature, &import_funcs[i].attachment,
|
||||
&import_funcs[i].call_conv_raw);
|
||||
#endif
|
||||
import_funcs[i].attachment = NULL;
|
||||
import_funcs[i].signature = NULL;
|
||||
import_funcs[i].call_conv_raw = false;
|
||||
|
||||
if (!no_resolve) {
|
||||
aot_resolve_import_func(module, &import_funcs[i]);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
|
||||
|
@ -2378,7 +2269,7 @@ fail:
|
|||
static bool
|
||||
load_import_func_info(const uint8 **p_buf, const uint8 *buf_end,
|
||||
AOTModule *module, bool is_load_from_file_buf,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
bool no_resolve, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *buf = *p_buf;
|
||||
|
||||
|
@ -2387,7 +2278,7 @@ load_import_func_info(const uint8 **p_buf, const uint8 *buf_end,
|
|||
/* load import funcs */
|
||||
if (module->import_func_count > 0
|
||||
&& !load_import_funcs(&buf, buf_end, module, is_load_from_file_buf,
|
||||
error_buf, error_buf_size))
|
||||
no_resolve, error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
*p_buf = buf;
|
||||
|
@ -2514,7 +2405,7 @@ fail:
|
|||
static bool
|
||||
load_init_data_section(const uint8 *buf, const uint8 *buf_end,
|
||||
AOTModule *module, bool is_load_from_file_buf,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
bool no_resolve, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
|
||||
|
@ -2525,7 +2416,7 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end,
|
|||
error_buf, error_buf_size)
|
||||
|| !load_global_info(&p, p_end, module, error_buf, error_buf_size)
|
||||
|| !load_import_func_info(&p, p_end, module, is_load_from_file_buf,
|
||||
error_buf, error_buf_size))
|
||||
no_resolve, error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
/* load function count and start function index */
|
||||
|
@ -3819,7 +3710,7 @@ has_module_memory64(AOTModule *module)
|
|||
|
||||
static bool
|
||||
load_from_sections(AOTModule *module, AOTSection *sections,
|
||||
bool is_load_from_file_buf, char *error_buf,
|
||||
bool is_load_from_file_buf, bool no_resolve, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
AOTSection *section = sections;
|
||||
|
@ -3852,8 +3743,8 @@ load_from_sections(AOTModule *module, AOTSection *sections,
|
|||
break;
|
||||
case AOT_SECTION_TYPE_INIT_DATA:
|
||||
if (!load_init_data_section(buf, buf_end, module,
|
||||
is_load_from_file_buf, error_buf,
|
||||
error_buf_size))
|
||||
is_load_from_file_buf, no_resolve,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
break;
|
||||
case AOT_SECTION_TYPE_TEXT:
|
||||
|
@ -4076,7 +3967,7 @@ aot_load_from_sections(AOTSection *section_list, char *error_buf,
|
|||
if (!module)
|
||||
return NULL;
|
||||
|
||||
if (!load_from_sections(module, section_list, false, error_buf,
|
||||
if (!load_from_sections(module, section_list, false, false, error_buf,
|
||||
error_buf_size)) {
|
||||
aot_unload(module);
|
||||
return NULL;
|
||||
|
@ -4246,7 +4137,8 @@ fail:
|
|||
|
||||
static bool
|
||||
load(const uint8 *buf, uint32 size, AOTModule *module,
|
||||
bool wasm_binary_freeable, char *error_buf, uint32 error_buf_size)
|
||||
bool wasm_binary_freeable, bool no_resolve, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *buf_end = buf + size;
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
|
@ -4273,7 +4165,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module,
|
|||
return false;
|
||||
|
||||
ret = load_from_sections(module, section_list, !wasm_binary_freeable,
|
||||
error_buf, error_buf_size);
|
||||
no_resolve, error_buf, error_buf_size);
|
||||
if (!ret) {
|
||||
/* If load_from_sections() fails, then aot text is destroyed
|
||||
in destroy_sections() */
|
||||
|
@ -4321,8 +4213,8 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
|
|||
return NULL;
|
||||
|
||||
os_thread_jit_write_protect_np(false); /* Make memory writable */
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
||||
error_buf_size)) {
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, args->no_resolve,
|
||||
error_buf, error_buf_size)) {
|
||||
aot_unload(module);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1058,7 +1058,24 @@ fail1:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static AOTMemoryInstance *
|
||||
AOTMemoryInstance *
|
||||
aot_lookup_memory(AOTModuleInstance *module_inst, char const *name)
|
||||
{
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
uint32 i;
|
||||
for (i = 0; i < module_inst->export_memory_count; i++)
|
||||
if (!strcmp(module_inst->export_memories[i].name, name))
|
||||
return module_inst->export_memories[i].memory;
|
||||
return NULL;
|
||||
#else
|
||||
(void)module_inst->export_memories;
|
||||
if (!module_inst->memories)
|
||||
return NULL;
|
||||
return module_inst->memories[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
AOTMemoryInstance *
|
||||
aot_get_default_memory(AOTModuleInstance *module_inst)
|
||||
{
|
||||
if (module_inst->memories)
|
||||
|
@ -1067,6 +1084,14 @@ aot_get_default_memory(AOTModuleInstance *module_inst)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
AOTMemoryInstance *
|
||||
aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index)
|
||||
{
|
||||
if ((index >= module_inst->memory_count) || !module_inst->memories)
|
||||
return NULL;
|
||||
return module_inst->memories[index];
|
||||
}
|
||||
|
||||
static bool
|
||||
memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
|
||||
AOTModule *module, uint32 heap_size,
|
||||
|
@ -1388,6 +1413,36 @@ create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
static WASMExportMemInstance *
|
||||
export_memories_instantiate(const AOTModule *module,
|
||||
AOTModuleInstance *module_inst,
|
||||
uint32 export_mem_count, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
WASMExportMemInstance *export_memories, *export_memory;
|
||||
AOTExport *export = module->exports;
|
||||
uint32 i;
|
||||
uint64 total_size =
|
||||
sizeof(WASMExportMemInstance) * (uint64)export_mem_count;
|
||||
|
||||
if (!(export_memory = export_memories =
|
||||
runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < module->export_count; i++, export ++)
|
||||
if (export->kind == EXPORT_KIND_MEMORY) {
|
||||
export_memory->name = export->name;
|
||||
export_memory->memory = module_inst->memories[export->index];
|
||||
export_memory++;
|
||||
}
|
||||
|
||||
bh_assert((uint32)(export_memory - export_memories) == export_mem_count);
|
||||
return export_memories;
|
||||
}
|
||||
#endif /* end of if WASM_ENABLE_MULTI_MEMORY != 0 */
|
||||
|
||||
static bool
|
||||
create_exports(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
|
@ -1414,6 +1469,19 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY == 0
|
||||
bh_assert(module_inst->export_memory_count <= 1);
|
||||
#else
|
||||
if (module_inst->export_memory_count) {
|
||||
module_inst->export_memories = export_memories_instantiate(
|
||||
module, module_inst, module_inst->export_memory_count, error_buf,
|
||||
error_buf_size);
|
||||
if (!module_inst->export_memories) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return create_export_funcs(module_inst, module, error_buf, error_buf_size);
|
||||
}
|
||||
|
||||
|
@ -2057,6 +2125,11 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
|||
if (module_inst->export_functions)
|
||||
wasm_runtime_free(module_inst->export_functions);
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
if (module_inst->export_memories)
|
||||
wasm_runtime_free(module_inst->export_memories);
|
||||
#endif
|
||||
|
||||
if (extra->functions) {
|
||||
uint32 func_idx;
|
||||
for (func_idx = 0; func_idx < extra->function_count; ++func_idx) {
|
||||
|
@ -4999,6 +5072,18 @@ aot_const_str_set_insert(const uint8 *str, int32 len, AOTModule *module,
|
|||
return c_str;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_DYNAMIC_AOT_DEBUG != 0
|
||||
AOTModule *g_dynamic_aot_module = NULL;
|
||||
|
||||
void __attribute__((noinline)) __enable_dynamic_aot_debug(void)
|
||||
{
|
||||
/* empty implementation. */
|
||||
}
|
||||
|
||||
void (*__enable_dynamic_aot_debug_ptr)(void)
|
||||
__attribute__((visibility("default"))) = __enable_dynamic_aot_debug;
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_set_module_name(AOTModule *module, const char *name, char *error_buf,
|
||||
uint32_t error_buf_size)
|
||||
|
@ -5012,6 +5097,12 @@ aot_set_module_name(AOTModule *module, const char *name, char *error_buf,
|
|||
false,
|
||||
#endif
|
||||
error_buf, error_buf_size);
|
||||
#if WASM_ENABLE_DYNAMIC_AOT_DEBUG != 0
|
||||
/* export g_dynamic_aot_module for dynamic aot debug */
|
||||
g_dynamic_aot_module = module;
|
||||
/* trigger breakpoint __enable_dynamic_aot_debug */
|
||||
(*__enable_dynamic_aot_debug_ptr)();
|
||||
#endif
|
||||
return module->name != NULL;
|
||||
}
|
||||
|
||||
|
@ -5020,3 +5111,125 @@ aot_get_module_name(AOTModule *module)
|
|||
{
|
||||
return module->name;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_resolve_symbols(AOTModule *module)
|
||||
{
|
||||
bool ret = true;
|
||||
uint32 idx;
|
||||
for (idx = 0; idx < module->import_func_count; ++idx) {
|
||||
AOTImportFunc *aot_import_func = &module->import_funcs[idx];
|
||||
if (!aot_import_func->func_ptr_linked) {
|
||||
if (!aot_resolve_import_func(module, aot_import_func)) {
|
||||
LOG_WARNING("Failed to link function (%s, %s)",
|
||||
aot_import_func->module_name,
|
||||
aot_import_func->func_name);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static void *
|
||||
aot_resolve_function(const AOTModule *module, const char *function_name,
|
||||
const AOTFuncType *expected_function_type, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
|
||||
static void *
|
||||
aot_resolve_function_ex(const char *module_name, const char *function_name,
|
||||
const AOTFuncType *expected_function_type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMModuleCommon *module_reg;
|
||||
|
||||
module_reg = wasm_runtime_find_module_registered(module_name);
|
||||
if (!module_reg || module_reg->module_type != Wasm_Module_AoT) {
|
||||
LOG_DEBUG("can not find a module named %s for function %s", module_name,
|
||||
function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "unknown import");
|
||||
return NULL;
|
||||
}
|
||||
return aot_resolve_function((AOTModule *)module_reg, function_name,
|
||||
expected_function_type, error_buf,
|
||||
error_buf_size);
|
||||
}
|
||||
|
||||
static void *
|
||||
aot_resolve_function(const AOTModule *module, const char *function_name,
|
||||
const AOTFuncType *expected_function_type, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
void *function = NULL;
|
||||
AOTExport *export = NULL;
|
||||
AOTFuncType *target_function_type = NULL;
|
||||
|
||||
export = loader_find_export((WASMModuleCommon *)module, module->name,
|
||||
function_name, EXPORT_KIND_FUNC, error_buf,
|
||||
error_buf_size);
|
||||
if (!export) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* resolve function type and function */
|
||||
if (export->index < module->import_func_count) {
|
||||
target_function_type = module->import_funcs[export->index].func_type;
|
||||
function = module->import_funcs[export->index].func_ptr_linked;
|
||||
}
|
||||
else {
|
||||
target_function_type =
|
||||
(AOTFuncType *)module
|
||||
->types[module->func_type_indexes[export->index
|
||||
- module->import_func_count]];
|
||||
function =
|
||||
(module->func_ptrs[export->index - module->import_func_count]);
|
||||
}
|
||||
/* check function type */
|
||||
if (!wasm_type_equal((WASMType *)expected_function_type,
|
||||
(WASMType *)target_function_type, module->types,
|
||||
module->type_count)) {
|
||||
LOG_DEBUG("%s.%s failed the type check", module->name, function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "incompatible import type");
|
||||
return NULL;
|
||||
}
|
||||
return function;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_MULTI_MODULE */
|
||||
|
||||
bool
|
||||
aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func)
|
||||
{
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
char error_buf[128];
|
||||
AOTModule *sub_module = NULL;
|
||||
#endif
|
||||
import_func->func_ptr_linked = wasm_native_resolve_symbol(
|
||||
import_func->module_name, import_func->func_name,
|
||||
import_func->func_type, &import_func->signature,
|
||||
&import_func->attachment, &import_func->call_conv_raw);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (!import_func->func_ptr_linked) {
|
||||
if (!wasm_runtime_is_built_in_module(import_func->module_name)) {
|
||||
sub_module = (AOTModule *)wasm_runtime_load_depended_module(
|
||||
(WASMModuleCommon *)module, import_func->module_name, error_buf,
|
||||
sizeof(error_buf));
|
||||
if (!sub_module) {
|
||||
LOG_WARNING("Failed to load sub module: %s", error_buf);
|
||||
}
|
||||
if (!sub_module)
|
||||
import_func->func_ptr_linked = aot_resolve_function_ex(
|
||||
import_func->module_name, import_func->func_name,
|
||||
import_func->func_type, error_buf, sizeof(error_buf));
|
||||
else
|
||||
import_func->func_ptr_linked = aot_resolve_function(
|
||||
sub_module, import_func->func_name, import_func->func_type,
|
||||
error_buf, sizeof(error_buf));
|
||||
if (!import_func->func_ptr_linked) {
|
||||
LOG_WARNING("Failed to link function: %s", error_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return import_func->func_ptr_linked != NULL;
|
||||
}
|
||||
|
|
|
@ -496,6 +496,18 @@ aot_load_from_sections(AOTSection *section_list, char *error_buf,
|
|||
void
|
||||
aot_unload(AOTModule *module);
|
||||
|
||||
/**
|
||||
* Resolve symbols for an AOT module
|
||||
*/
|
||||
bool
|
||||
aot_resolve_symbols(AOTModule *module);
|
||||
|
||||
/**
|
||||
* Helper function to resolve a single function
|
||||
*/
|
||||
bool
|
||||
aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func);
|
||||
|
||||
/**
|
||||
* Instantiate a AOT module.
|
||||
*
|
||||
|
@ -536,6 +548,15 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst);
|
|||
AOTFunctionInstance *
|
||||
aot_lookup_function(const AOTModuleInstance *module_inst, const char *name);
|
||||
|
||||
AOTMemoryInstance *
|
||||
aot_lookup_memory(AOTModuleInstance *module_inst, char const *name);
|
||||
|
||||
AOTMemoryInstance *
|
||||
aot_get_default_memory(AOTModuleInstance *module_inst);
|
||||
|
||||
AOTMemoryInstance *
|
||||
aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index);
|
||||
|
||||
/**
|
||||
* Get a function in the AOT module instance.
|
||||
*
|
||||
|
|
|
@ -1102,11 +1102,9 @@ wasm_get_default_memory(WASMModuleInstance *module_inst)
|
|||
WASMMemoryInstance *
|
||||
wasm_get_memory_with_idx(WASMModuleInstance *module_inst, uint32 index)
|
||||
{
|
||||
bh_assert(index < module_inst->memory_count);
|
||||
if (module_inst->memories)
|
||||
return module_inst->memories[index];
|
||||
else
|
||||
if ((index >= module_inst->memory_count) || !module_inst->memories)
|
||||
return NULL;
|
||||
return module_inst->memories[index];
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1185,20 +1183,13 @@ wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size)
|
|||
return wasm_mremap_linear_memory(NULL, 0, map_size, commit_size);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count,
|
||||
uint32 memidx)
|
||||
static bool
|
||||
wasm_enlarge_memory_internal(WASMModuleInstanceCommon *module,
|
||||
WASMMemoryInstance *memory, uint32 inc_page_count)
|
||||
{
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
WASMMemoryInstance *memory = wasm_get_memory_with_idx(module, memidx);
|
||||
#else
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
WASMSharedHeap *shared_heap;
|
||||
#endif
|
||||
|
||||
uint8 *memory_data_old, *memory_data_new, *heap_data_old;
|
||||
uint32 num_bytes_per_page, heap_size;
|
||||
uint32 cur_page_count, max_page_count, total_page_count;
|
||||
|
@ -1231,8 +1222,23 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count,
|
|||
total_page_count = inc_page_count + cur_page_count;
|
||||
total_size_new = num_bytes_per_page * (uint64)total_page_count;
|
||||
|
||||
if (inc_page_count <= 0)
|
||||
/* No need to enlarge memory */
|
||||
return true;
|
||||
|
||||
if (total_page_count < cur_page_count) { /* integer overflow */
|
||||
ret = false;
|
||||
goto return_func;
|
||||
}
|
||||
|
||||
if (total_page_count > max_page_count) {
|
||||
failure_reason = MAX_SIZE_REACHED;
|
||||
ret = false;
|
||||
goto return_func;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
shared_heap = get_shared_heap((WASMModuleInstanceCommon *)module);
|
||||
shared_heap = get_shared_heap(module);
|
||||
if (shared_heap) {
|
||||
if (memory->is_memory64
|
||||
&& total_size_new > shared_heap->start_off_mem64) {
|
||||
|
@ -1248,20 +1254,6 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count,
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (inc_page_count <= 0)
|
||||
/* No need to enlarge memory */
|
||||
return true;
|
||||
|
||||
if (total_page_count < cur_page_count) { /* integer overflow */
|
||||
ret = false;
|
||||
goto return_func;
|
||||
}
|
||||
|
||||
if (total_page_count > max_page_count) {
|
||||
failure_reason = MAX_SIZE_REACHED;
|
||||
ret = false;
|
||||
goto return_func;
|
||||
}
|
||||
|
||||
bh_assert(total_size_new
|
||||
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
|
||||
|
@ -1364,7 +1356,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count,
|
|||
wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
|
||||
|
||||
return_func:
|
||||
if (!ret && enlarge_memory_error_cb) {
|
||||
if (!ret && module && enlarge_memory_error_cb) {
|
||||
WASMExecEnv *exec_env = NULL;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
|
@ -1377,8 +1369,7 @@ return_func:
|
|||
#endif
|
||||
|
||||
enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
|
||||
failure_reason,
|
||||
(WASMModuleInstanceCommon *)module, exec_env,
|
||||
failure_reason, module, exec_env,
|
||||
enlarge_memory_error_user_data);
|
||||
}
|
||||
|
||||
|
@ -1422,15 +1413,16 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
|
|||
{
|
||||
bool ret = false;
|
||||
|
||||
if (module->memory_count > 0) {
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (module->memory_count > 0)
|
||||
shared_memory_lock(module->memories[0]);
|
||||
#endif
|
||||
ret = wasm_enlarge_memory_internal(module, inc_page_count, 0);
|
||||
ret = wasm_enlarge_memory_internal((WASMModuleInstanceCommon *)module,
|
||||
module->memories[0], inc_page_count);
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (module->memory_count > 0)
|
||||
shared_memory_unlock(module->memories[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1441,15 +1433,117 @@ wasm_enlarge_memory_with_idx(WASMModuleInstance *module, uint32 inc_page_count,
|
|||
{
|
||||
bool ret = false;
|
||||
|
||||
if (memidx < module->memory_count) {
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (memidx < module->memory_count)
|
||||
shared_memory_lock(module->memories[memidx]);
|
||||
#endif
|
||||
ret = wasm_enlarge_memory_internal(module, inc_page_count, memidx);
|
||||
ret = wasm_enlarge_memory_internal((WASMModuleInstanceCommon *)module,
|
||||
module->memories[memidx],
|
||||
inc_page_count);
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (memidx < module->memory_count)
|
||||
shared_memory_unlock(module->memories[memidx]);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_runtime_lookup_memory(WASMModuleInstanceCommon *module_inst,
|
||||
const char *name)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_lookup_memory((WASMModuleInstance *)module_inst, name);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_lookup_memory((WASMModuleInstance *)module_inst, name);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_runtime_get_default_memory(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_get_default_memory((WASMModuleInstance *)module_inst);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_get_default_memory((AOTModuleInstance *)module_inst);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_runtime_get_memory(WASMModuleInstanceCommon *module_inst, uint32 index)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_get_memory_with_idx((WASMModuleInstance *)module_inst,
|
||||
index);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_get_memory_with_index((AOTModuleInstance *)module_inst,
|
||||
index);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64
|
||||
wasm_memory_get_cur_page_count(WASMMemoryInstance *memory)
|
||||
{
|
||||
return memory->cur_page_count;
|
||||
}
|
||||
|
||||
uint64
|
||||
wasm_memory_get_max_page_count(WASMMemoryInstance *memory)
|
||||
{
|
||||
return memory->max_page_count;
|
||||
}
|
||||
|
||||
uint64
|
||||
wasm_memory_get_bytes_per_page(WASMMemoryInstance *memory)
|
||||
{
|
||||
return memory->num_bytes_per_page;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_memory_get_shared(WASMMemoryInstance *memory)
|
||||
{
|
||||
return memory->is_shared_memory;
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_memory_get_base_address(WASMMemoryInstance *memory)
|
||||
{
|
||||
return memory->memory_data;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_memory_enlarge(WASMMemoryInstance *memory, uint64 inc_page_count)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (memory) {
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
shared_memory_lock(memory);
|
||||
#endif
|
||||
ret =
|
||||
wasm_enlarge_memory_internal(NULL, memory, (uint32)inc_page_count);
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
shared_memory_unlock(memory);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1484,6 +1484,22 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args,
|
|||
error_buf_size);
|
||||
}
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_resolve_symbols(WASMModuleCommon *module)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module->module_type == Wasm_Module_Bytecode) {
|
||||
return wasm_resolve_symbols((WASMModule *)module);
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module->module_type == Wasm_Module_AoT) {
|
||||
return aot_resolve_symbols((AOTModule *)module);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
WASMModuleCommon *
|
||||
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
|
@ -4505,7 +4521,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
|||
#endif
|
||||
typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *);
|
||||
NativeRawFuncPtr invoke_native_raw = (NativeRawFuncPtr)func_ptr;
|
||||
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size, arg_i64;
|
||||
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size;
|
||||
uint32 *argv_src = argv, i, argc1, ptr_len;
|
||||
uint32 arg_i32;
|
||||
bool ret = false;
|
||||
|
@ -4568,6 +4584,8 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
|||
case VALUE_TYPE_I64:
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
{
|
||||
uint64 arg_i64;
|
||||
|
||||
PUT_I64_TO_ADDR((uint32 *)argv_dst,
|
||||
GET_I64_FROM_ADDR(argv_src));
|
||||
argv_src += 2;
|
||||
|
|
|
@ -1407,7 +1407,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
LLVMValueRef *param_values = NULL, value_ret = NULL, func;
|
||||
LLVMValueRef import_func_idx, res;
|
||||
LLVMValueRef ext_ret, ext_ret_ptr, ext_ret_idx;
|
||||
#if WASM_ENABLE_AOT_STACK_FRAME != 0
|
||||
LLVMValueRef func_idx_ref;
|
||||
#endif
|
||||
int32 i, j = 0, param_count, result_count, ext_ret_count;
|
||||
uint64 total_size;
|
||||
uint8 wasm_ret_type;
|
||||
|
|
|
@ -534,6 +534,10 @@ typedef struct LoadArgs {
|
|||
bool clone_wasm_binary;
|
||||
/* This option is only used by the AOT/wasm loader (see wasm_export.h) */
|
||||
bool wasm_binary_freeable;
|
||||
/* false by default, if true, don't resolve the symbols yet. The
|
||||
wasm_runtime_load_ex has to be followed by a wasm_runtime_resolve_symbols
|
||||
call */
|
||||
bool no_resolve;
|
||||
/* TODO: more fields? */
|
||||
} LoadArgs;
|
||||
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
||||
|
|
|
@ -120,6 +120,10 @@ typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
|
|||
typedef void WASMFunctionInstanceCommon;
|
||||
typedef WASMFunctionInstanceCommon *wasm_function_inst_t;
|
||||
|
||||
/* Memory instance */
|
||||
struct WASMMemoryInstance;
|
||||
typedef struct WASMMemoryInstance *wasm_memory_inst_t;
|
||||
|
||||
/* WASM section */
|
||||
typedef struct wasm_section_t {
|
||||
struct wasm_section_t *next;
|
||||
|
@ -251,6 +255,11 @@ typedef struct LoadArgs {
|
|||
const strings), making it possible to free the wasm binary buffer after
|
||||
loading. */
|
||||
bool wasm_binary_freeable;
|
||||
|
||||
/* false by default, if true, don't resolve the symbols yet. The
|
||||
wasm_runtime_load_ex has to be followed by a wasm_runtime_resolve_symbols
|
||||
call */
|
||||
bool no_resolve;
|
||||
/* TODO: more fields? */
|
||||
} LoadArgs;
|
||||
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
||||
|
@ -572,6 +581,12 @@ WASM_RUNTIME_API_EXTERN wasm_module_t
|
|||
wasm_runtime_load_ex(uint8_t *buf, uint32_t size, const LoadArgs *args,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
|
||||
/**
|
||||
* Resolve symbols for a previously loaded WASM module. Only useful when the
|
||||
* module was loaded with LoadArgs::no_resolve set to true
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_resolve_symbols(wasm_module_t module);
|
||||
/**
|
||||
* Load a WASM module from a specified WASM or AOT section list.
|
||||
*
|
||||
|
@ -946,6 +961,100 @@ WASM_RUNTIME_API_EXTERN void
|
|||
wasm_runtime_set_module_inst(wasm_exec_env_t exec_env,
|
||||
const wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
* @brief Lookup a memory instance by name
|
||||
*
|
||||
* @param module_inst The module instance
|
||||
* @param name The name of the memory instance
|
||||
*
|
||||
* @return The memory instance if found, NULL otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN wasm_memory_inst_t
|
||||
wasm_runtime_lookup_memory(const wasm_module_inst_t module_inst,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* @brief Get the default memory instance
|
||||
*
|
||||
* @param module_inst The module instance
|
||||
*
|
||||
* @return The memory instance if found, NULL otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN wasm_memory_inst_t
|
||||
wasm_runtime_get_default_memory(const wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
* @brief Get a memory instance by index
|
||||
*
|
||||
* @param module_inst The module instance
|
||||
* @param index The index of the memory instance
|
||||
*
|
||||
* @return The memory instance if found, NULL otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN wasm_memory_inst_t
|
||||
wasm_runtime_get_memory(const wasm_module_inst_t module_inst, uint32_t index);
|
||||
|
||||
/**
|
||||
* @brief Get the current number of pages for a memory instance
|
||||
*
|
||||
* @param memory_inst The memory instance
|
||||
*
|
||||
* @return The current number of pages
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN uint64_t
|
||||
wasm_memory_get_cur_page_count(const wasm_memory_inst_t memory_inst);
|
||||
|
||||
/**
|
||||
* @brief Get the maximum number of pages for a memory instance
|
||||
*
|
||||
* @param memory_inst The memory instance
|
||||
*
|
||||
* @return The maximum number of pages
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN uint64_t
|
||||
wasm_memory_get_max_page_count(const wasm_memory_inst_t memory_inst);
|
||||
|
||||
/**
|
||||
* @brief Get the number of bytes per page for a memory instance
|
||||
*
|
||||
* @param memory_inst The memory instance
|
||||
*
|
||||
* @return The number of bytes per page
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN uint64_t
|
||||
wasm_memory_get_bytes_per_page(const wasm_memory_inst_t memory_inst);
|
||||
|
||||
/**
|
||||
* @brief Get the shared status for a memory instance
|
||||
*
|
||||
* @param memory_inst The memory instance
|
||||
*
|
||||
* @return True if shared, false otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_memory_get_shared(const wasm_memory_inst_t memory_inst);
|
||||
|
||||
/**
|
||||
* @brief Get the base address for a memory instance
|
||||
*
|
||||
* @param memory_inst The memory instance
|
||||
*
|
||||
* @return The base address on success, false otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_memory_get_base_address(const wasm_memory_inst_t memory_inst);
|
||||
|
||||
/**
|
||||
* @brief Enlarge a memory instance by a number of pages
|
||||
*
|
||||
* @param memory_inst The memory instance
|
||||
* @param inc_page_count The number of pages to add
|
||||
*
|
||||
* @return True if successful, false otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_memory_enlarge(wasm_memory_inst_t memory_inst, uint64_t inc_page_count);
|
||||
|
||||
/**
|
||||
* Call the given WASM function of a WASM module instance with
|
||||
* arguments (bytecode and AoT).
|
||||
|
|
|
@ -2246,60 +2246,6 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name,
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static WASMFunction *
|
||||
wasm_loader_resolve_function(const char *module_name, const char *function_name,
|
||||
const WASMFuncType *expected_function_type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMModuleCommon *module_reg;
|
||||
WASMFunction *function = NULL;
|
||||
WASMExport *export = NULL;
|
||||
WASMModule *module = NULL;
|
||||
WASMFuncType *target_function_type = NULL;
|
||||
|
||||
module_reg = wasm_runtime_find_module_registered(module_name);
|
||||
if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
|
||||
LOG_DEBUG("can not find a module named %s for function %s", module_name,
|
||||
function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "unknown import");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module = (WASMModule *)module_reg;
|
||||
export =
|
||||
wasm_loader_find_export(module, module_name, function_name,
|
||||
EXPORT_KIND_FUNC, error_buf, error_buf_size);
|
||||
if (!export) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* resolve function type and function */
|
||||
if (export->index < module->import_function_count) {
|
||||
target_function_type =
|
||||
module->import_functions[export->index].u.function.func_type;
|
||||
function = module->import_functions[export->index]
|
||||
.u.function.import_func_linked;
|
||||
}
|
||||
else {
|
||||
target_function_type =
|
||||
module->functions[export->index - module->import_function_count]
|
||||
->func_type;
|
||||
function =
|
||||
module->functions[export->index - module->import_function_count];
|
||||
}
|
||||
|
||||
/* check function type */
|
||||
if (!wasm_type_equal((WASMType *)expected_function_type,
|
||||
(WASMType *)target_function_type, module->types,
|
||||
module->type_count)) {
|
||||
LOG_DEBUG("%s.%s failed the type check", module_name, function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "incompatible import type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
static WASMTable *
|
||||
wasm_loader_resolve_table(const char *module_name, const char *table_name,
|
||||
uint32 init_size, uint32 max_size, char *error_buf,
|
||||
|
@ -2494,21 +2440,11 @@ static bool
|
|||
load_function_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||
const WASMModule *parent_module,
|
||||
const char *sub_module_name, const char *function_name,
|
||||
WASMFunctionImport *function, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
WASMFunctionImport *function, bool no_resolve,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||
uint32 declare_type_index = 0;
|
||||
WASMFuncType *declare_func_type = NULL;
|
||||
WASMFunction *linked_func = NULL;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *sub_module = NULL;
|
||||
bool is_built_in_module = false;
|
||||
#endif
|
||||
const char *linked_signature = NULL;
|
||||
void *linked_attachment = NULL;
|
||||
bool linked_call_conv_raw = false;
|
||||
bool is_native_symbol = false;
|
||||
|
||||
read_leb_uint32(p, p_end, declare_type_index);
|
||||
*p_buf = p;
|
||||
|
@ -2527,43 +2463,19 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end,
|
|||
parent_module->types, parent_module->type_count, declare_type_index);
|
||||
#endif
|
||||
|
||||
declare_func_type =
|
||||
function->func_type =
|
||||
(WASMFuncType *)parent_module->types[declare_type_index];
|
||||
|
||||
/* lookup registered native symbols first */
|
||||
linked_func = wasm_native_resolve_symbol(
|
||||
sub_module_name, function_name, declare_func_type, &linked_signature,
|
||||
&linked_attachment, &linked_call_conv_raw);
|
||||
if (linked_func) {
|
||||
is_native_symbol = true;
|
||||
}
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
else {
|
||||
if (!(is_built_in_module =
|
||||
wasm_runtime_is_built_in_module(sub_module_name))) {
|
||||
sub_module = (WASMModule *)wasm_runtime_load_depended_module(
|
||||
(WASMModuleCommon *)parent_module, sub_module_name, error_buf,
|
||||
error_buf_size);
|
||||
}
|
||||
if (is_built_in_module || sub_module)
|
||||
linked_func = wasm_loader_resolve_function(
|
||||
sub_module_name, function_name, declare_func_type, error_buf,
|
||||
error_buf_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
function->module_name = (char *)sub_module_name;
|
||||
function->field_name = (char *)function_name;
|
||||
function->func_type = declare_func_type;
|
||||
/* func_ptr_linked is for native registered symbol */
|
||||
function->func_ptr_linked = is_native_symbol ? linked_func : NULL;
|
||||
function->signature = linked_signature;
|
||||
function->attachment = linked_attachment;
|
||||
function->call_conv_raw = linked_call_conv_raw;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
function->import_module = is_native_symbol ? NULL : sub_module;
|
||||
function->import_func_linked = is_native_symbol ? NULL : linked_func;
|
||||
#endif
|
||||
function->attachment = NULL;
|
||||
function->signature = NULL;
|
||||
function->call_conv_raw = false;
|
||||
|
||||
/* lookup registered native symbols first */
|
||||
if (!no_resolve) {
|
||||
wasm_resolve_import_func(parent_module, function);
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
|
@ -3258,8 +3170,8 @@ fail:
|
|||
|
||||
static bool
|
||||
load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
bool is_load_from_file_buf, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
bool is_load_from_file_buf, bool no_resolve,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = buf, *p_end = buf_end, *p_old;
|
||||
uint32 import_count, name_len, type_index, i, u32, flags;
|
||||
|
@ -3442,9 +3354,10 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
case IMPORT_KIND_FUNC: /* import function */
|
||||
bh_assert(import_functions);
|
||||
import = import_functions++;
|
||||
if (!load_function_import(
|
||||
&p, p_end, module, sub_module_name, field_name,
|
||||
&import->u.function, error_buf, error_buf_size)) {
|
||||
if (!load_function_import(&p, p_end, module,
|
||||
sub_module_name, field_name,
|
||||
&import->u.function, no_resolve,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -5760,7 +5673,7 @@ static void **handle_table;
|
|||
static bool
|
||||
load_from_sections(WASMModule *module, WASMSection *sections,
|
||||
bool is_load_from_file_buf, bool wasm_binary_freeable,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
bool no_resolve, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMExport *export;
|
||||
WASMSection *section = sections;
|
||||
|
@ -5817,8 +5730,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
break;
|
||||
case SECTION_TYPE_IMPORT:
|
||||
if (!load_import_section(buf, buf_end, module,
|
||||
reuse_const_strings, error_buf,
|
||||
error_buf_size))
|
||||
reuse_const_strings, no_resolve,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
break;
|
||||
case SECTION_TYPE_FUNC:
|
||||
|
@ -6343,7 +6256,7 @@ wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
|
|||
if (!module)
|
||||
return NULL;
|
||||
|
||||
if (!load_from_sections(module, section_list, false, true, error_buf,
|
||||
if (!load_from_sections(module, section_list, false, true, false, error_buf,
|
||||
error_buf_size)) {
|
||||
wasm_loader_unload(module);
|
||||
return NULL;
|
||||
|
@ -6488,7 +6401,8 @@ static union {
|
|||
|
||||
static bool
|
||||
load(const uint8 *buf, uint32 size, WASMModule *module,
|
||||
bool wasm_binary_freeable, char *error_buf, uint32 error_buf_size)
|
||||
bool wasm_binary_freeable, bool no_resolve, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *buf_end = buf + size;
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
|
@ -6519,7 +6433,7 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
|
|||
|
||||
if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size)
|
||||
|| !load_from_sections(module, section_list, true, wasm_binary_freeable,
|
||||
error_buf, error_buf_size)) {
|
||||
no_resolve, error_buf, error_buf_size)) {
|
||||
destroy_sections(section_list);
|
||||
return false;
|
||||
}
|
||||
|
@ -6695,8 +6609,8 @@ wasm_loader_load(uint8 *buf, uint32 size,
|
|||
module->load_size = size;
|
||||
#endif
|
||||
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
||||
error_buf_size)) {
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, args->no_resolve,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,124 @@ wasm_unload(WASMModule *module)
|
|||
wasm_loader_unload(module);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_resolve_symbols(WASMModule *module)
|
||||
{
|
||||
bool ret = true;
|
||||
uint32 idx;
|
||||
for (idx = 0; idx < module->import_function_count; ++idx) {
|
||||
WASMFunctionImport *import = &module->import_functions[idx].u.function;
|
||||
bool linked = import->func_ptr_linked;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (import->import_func_linked) {
|
||||
linked = true;
|
||||
}
|
||||
#endif
|
||||
if (!linked && !wasm_resolve_import_func(module, import)) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static WASMFunction *
|
||||
wasm_resolve_function(const char *module_name, const char *function_name,
|
||||
const WASMFuncType *expected_function_type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMModuleCommon *module_reg;
|
||||
WASMFunction *function = NULL;
|
||||
WASMExport *export = NULL;
|
||||
WASMModule *module = NULL;
|
||||
WASMFuncType *target_function_type = NULL;
|
||||
|
||||
module_reg = wasm_runtime_find_module_registered(module_name);
|
||||
if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
|
||||
LOG_DEBUG("can not find a module named %s for function %s", module_name,
|
||||
function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "unknown import");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module = (WASMModule *)module_reg;
|
||||
export = loader_find_export((WASMModuleCommon *)module, module_name,
|
||||
function_name, EXPORT_KIND_FUNC, error_buf,
|
||||
error_buf_size);
|
||||
if (!export) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* resolve function type and function */
|
||||
if (export->index < module->import_function_count) {
|
||||
target_function_type =
|
||||
module->import_functions[export->index].u.function.func_type;
|
||||
function = module->import_functions[export->index]
|
||||
.u.function.import_func_linked;
|
||||
}
|
||||
else {
|
||||
target_function_type =
|
||||
module->functions[export->index - module->import_function_count]
|
||||
->func_type;
|
||||
function =
|
||||
module->functions[export->index - module->import_function_count];
|
||||
}
|
||||
|
||||
/* check function type */
|
||||
if (!wasm_type_equal((WASMType *)expected_function_type,
|
||||
(WASMType *)target_function_type, module->types,
|
||||
module->type_count)) {
|
||||
LOG_DEBUG("%s.%s failed the type check", module_name, function_name);
|
||||
set_error_buf(error_buf, error_buf_size, "incompatible import type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return function;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
wasm_resolve_import_func(const WASMModule *module, WASMFunctionImport *function)
|
||||
{
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
char error_buf[128];
|
||||
WASMModule *sub_module = NULL;
|
||||
#endif
|
||||
function->func_ptr_linked = wasm_native_resolve_symbol(
|
||||
function->module_name, function->field_name, function->func_type,
|
||||
&function->signature, &function->attachment, &function->call_conv_raw);
|
||||
|
||||
if (function->func_ptr_linked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (!wasm_runtime_is_built_in_module(function->module_name)) {
|
||||
sub_module = (WASMModule *)wasm_runtime_load_depended_module(
|
||||
(WASMModuleCommon *)module, function->module_name, error_buf,
|
||||
sizeof(error_buf));
|
||||
if (!sub_module) {
|
||||
LOG_WARNING("failed to load sub module: %s", error_buf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function->import_func_linked = wasm_resolve_function(
|
||||
function->module_name, function->field_name, function->func_type,
|
||||
error_buf, sizeof(error_buf));
|
||||
|
||||
if (function->import_func_linked) {
|
||||
function->import_module = sub_module;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LOG_WARNING("failed to link function (%s, %s): %s",
|
||||
function->module_name, function->field_name, error_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void *
|
||||
runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
|
@ -1323,42 +1441,6 @@ export_tags_instantiate(const WASMModule *module,
|
|||
}
|
||||
#endif /* end of WASM_ENABLE_TAGS != 0 */
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static void
|
||||
export_globals_deinstantiate(WASMExportGlobInstance *globals)
|
||||
{
|
||||
if (globals)
|
||||
wasm_runtime_free(globals);
|
||||
}
|
||||
|
||||
static WASMExportGlobInstance *
|
||||
export_globals_instantiate(const WASMModule *module,
|
||||
WASMModuleInstance *module_inst,
|
||||
uint32 export_glob_count, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
WASMExportGlobInstance *export_globals, *export_global;
|
||||
WASMExport *export = module->exports;
|
||||
uint32 i;
|
||||
uint64 total_size =
|
||||
sizeof(WASMExportGlobInstance) * (uint64)export_glob_count;
|
||||
|
||||
if (!(export_global = export_globals =
|
||||
runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < module->export_count; i++, export ++)
|
||||
if (export->kind == EXPORT_KIND_GLOBAL) {
|
||||
export_global->name = export->name;
|
||||
export_global->global = &module_inst->e->globals[export->index];
|
||||
export_global++;
|
||||
}
|
||||
|
||||
bh_assert((uint32)(export_global - export_globals) == export_glob_count);
|
||||
return export_globals;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
static void
|
||||
export_memories_deinstantiate(WASMExportMemInstance *memories)
|
||||
|
@ -1396,6 +1478,42 @@ export_memories_instantiate(const WASMModule *module,
|
|||
}
|
||||
#endif /* end of if WASM_ENABLE_MULTI_MEMORY != 0 */
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static void
|
||||
export_globals_deinstantiate(WASMExportGlobInstance *globals)
|
||||
{
|
||||
if (globals)
|
||||
wasm_runtime_free(globals);
|
||||
}
|
||||
|
||||
static WASMExportGlobInstance *
|
||||
export_globals_instantiate(const WASMModule *module,
|
||||
WASMModuleInstance *module_inst,
|
||||
uint32 export_glob_count, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
WASMExportGlobInstance *export_globals, *export_global;
|
||||
WASMExport *export = module->exports;
|
||||
uint32 i;
|
||||
uint64 total_size =
|
||||
sizeof(WASMExportGlobInstance) * (uint64)export_glob_count;
|
||||
|
||||
if (!(export_global = export_globals =
|
||||
runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < module->export_count; i++, export ++)
|
||||
if (export->kind == EXPORT_KIND_GLOBAL) {
|
||||
export_global->name = export->name;
|
||||
export_global->global = &module_inst->e->globals[export->index];
|
||||
export_global++;
|
||||
}
|
||||
|
||||
bh_assert((uint32)(export_global - export_globals) == export_glob_count);
|
||||
return export_globals;
|
||||
}
|
||||
|
||||
#endif /* end of if WASM_ENABLE_MULTI_MODULE != 0 */
|
||||
|
||||
static WASMFunctionInstance *
|
||||
|
@ -2388,11 +2506,13 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
|
||||
/* export */
|
||||
module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC);
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
module_inst->export_memory_count =
|
||||
get_export_count(module, EXPORT_KIND_MEMORY);
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
module_inst->export_table_count =
|
||||
get_export_count(module, EXPORT_KIND_TABLE);
|
||||
module_inst->export_memory_count =
|
||||
get_export_count(module, EXPORT_KIND_MEMORY);
|
||||
#if WASM_ENABLE_TAGS != 0
|
||||
module_inst->e->export_tag_count =
|
||||
get_export_count(module, EXPORT_KIND_TAG);
|
||||
|
@ -2432,7 +2552,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
module, module_inst, module_inst->export_global_count,
|
||||
error_buf, error_buf_size)))
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
|| (module_inst->export_memory_count > 0
|
||||
&& !(module_inst->export_memories = export_memories_instantiate(
|
||||
module, module_inst, module_inst->export_memory_count,
|
||||
|
@ -3240,7 +3360,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
|||
export_globals_deinstantiate(module_inst->export_globals);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
export_memories_deinstantiate(module_inst->export_memories);
|
||||
#endif
|
||||
|
||||
|
@ -3292,17 +3412,6 @@ wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMGlobalInstance *
|
||||
wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name)
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < module_inst->export_global_count; i++)
|
||||
if (!strcmp(module_inst->export_globals[i].name, name))
|
||||
return module_inst->export_globals[i].global;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name)
|
||||
{
|
||||
|
@ -3314,10 +3423,23 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name)
|
|||
return NULL;
|
||||
#else
|
||||
(void)module_inst->export_memories;
|
||||
if (!module_inst->memories)
|
||||
return NULL;
|
||||
return module_inst->memories[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMGlobalInstance *
|
||||
wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name)
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < module_inst->export_global_count; i++)
|
||||
if (!strcmp(module_inst->export_globals[i].name, name))
|
||||
return module_inst->export_globals[i].global;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WASMTableInstance *
|
||||
wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
|
||||
{
|
||||
|
|
|
@ -528,6 +528,13 @@ wasm_load_from_sections(WASMSection *section_list, char *error_buf,
|
|||
void
|
||||
wasm_unload(WASMModule *module);
|
||||
|
||||
bool
|
||||
wasm_resolve_symbols(WASMModule *module);
|
||||
|
||||
bool
|
||||
wasm_resolve_import_func(const WASMModule *module,
|
||||
WASMFunctionImport *function);
|
||||
|
||||
WASMModuleInstance *
|
||||
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size,
|
||||
|
@ -554,13 +561,13 @@ wasm_set_running_mode(WASMModuleInstance *module_inst,
|
|||
WASMFunctionInstance *
|
||||
wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMGlobalInstance *
|
||||
wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
WASMTableInstance *
|
||||
wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
|
|
|
@ -49,6 +49,12 @@ else()
|
|||
add_definitions(-DWASM_ENABLE_WORD_ALIGN_READ=0)
|
||||
endif()
|
||||
|
||||
if(CONFIG_INTERPRETERS_WAMR_DYNAMIC_AOT_DEBUG)
|
||||
add_definitions(-DWASM_ENABLE_DYNAMIC_AOT_DEBUG=1)
|
||||
else()
|
||||
add_definitions(-DWASM_ENABLE_DYNAMIC_AOT_DEBUG=0)
|
||||
endif()
|
||||
|
||||
if(CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE)
|
||||
add_definitions(-DWASM_STACK_GUARD_SIZE=0)
|
||||
else()
|
||||
|
|
|
@ -148,6 +148,12 @@ else
|
|||
CFLAGS += -DWASM_ENABLE_WORD_ALIGN_READ=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_DYNAMIC_AOT_DEBUG),y)
|
||||
CFLAGS += -DWASM_ENABLE_DYNAMIC_AOT_DEBUG=1
|
||||
else
|
||||
CFLAGS += -DWASM_ENABLE_DYNAMIC_AOT_DEBUG=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_MEM_DUAL_BUS_MIRROR),y)
|
||||
CFLAGS += -DWASM_MEM_DUAL_BUS_MIRROR=1
|
||||
else
|
||||
|
|
|
@ -928,6 +928,15 @@ main(int argc, char *argv[])
|
|||
goto fail2;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_DYNAMIC_AOT_DEBUG != 0
|
||||
if (!wasm_runtime_set_module_name(wasm_module, wasm_file, error_buf,
|
||||
sizeof(error_buf))) {
|
||||
printf("set aot module name failed in dynamic aot debug mode, %s\n",
|
||||
error_buf);
|
||||
goto fail3;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx);
|
||||
#endif
|
||||
|
|
139
test-tools/dynamic-aot-debug/README.md
Normal file
139
test-tools/dynamic-aot-debug/README.md
Normal file
|
@ -0,0 +1,139 @@
|
|||
# Dynamic AOT Module Debugging
|
||||
|
||||
> Note: Dynamic AOT debugging is experimental and only a few debugging capabilities are supported.
|
||||
|
||||
This guide explains how to debug WAMR AOT modules with dynamic AOT features. Follow these steps to set up and run your debugging environment.
|
||||
|
||||
## 1. Test source code
|
||||
|
||||
The following c program file is used as a debugging test file.
|
||||
|
||||
```bash
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("hello, world!\n");
|
||||
int a = 1024;
|
||||
printf("a is %d\n",a);
|
||||
int b = 42;
|
||||
printf("b is %d\n",b);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Build iwasm with dynamic aot debugging feature
|
||||
|
||||
To enable dynamic AOT debugging, ensure the following
|
||||
compile options are enabled when you [build iwasm](../../product-mini/README.md):
|
||||
|
||||
```bash
|
||||
cmake -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_DYNAMIC_AOT_DEBUG=1 -DCMAKE_BUILD_TYPE=Debug
|
||||
```
|
||||
|
||||
## 3. Build wamrc
|
||||
|
||||
Developer may need to build out two versions of wamrc, one is to compile the wasm binary into the AOT file, the other is to compile the wasm binary into an object file. To build out the former, just build wamrc as normal, see [wamrc-compiler/README.md](../../wamr-compiler/README.md). To build out the latter, the `WAMR_BUILD_DEBUG_AOT` flag must be added to cmake, please refer to the first two steps in [doc/source_debugging_aot.md](../../doc/source_debugging_aot.md), and if you encounter the error “‘eLanguageTypeC17’ not declared in this scope”, you can bypass it by commenting out the case judgments. This will not affect the debugging results.
|
||||
|
||||
## 4. Dynamic aot debugging and verification across various platforms
|
||||
|
||||
You can adjust the compiler options for different architectures and instruction sets.
|
||||
|
||||
### 4.1 Linux
|
||||
|
||||
#### Compile test.c to test.wasm
|
||||
|
||||
```bash
|
||||
/opt/wasi-sdk/bin/clang -O0 -g -gdwarf-2 -o test.wasm test.c
|
||||
```
|
||||
|
||||
#### Compile test.wasm to test.aot
|
||||
|
||||
```bash
|
||||
./wamrc --opt-level=0 -o test.aot test.wasm
|
||||
```
|
||||
|
||||
#### Compile test.wasm to test object file
|
||||
|
||||
> Note: please use the version wamrc which was built with `cmake -DWAMR_BUILD_DEBUG_AOT` flag.
|
||||
|
||||
```bash
|
||||
./wamrc --opt-level=0 --format=object -o test.obj test.wasm
|
||||
```
|
||||
|
||||
#### Launch the program using gdbserver on the remote linux host
|
||||
|
||||
```bash
|
||||
cd ~/aot_debug # This directory contains iwasm and test.aot
|
||||
gdbserver hostip:port ./iwasm test.aot
|
||||
```
|
||||
|
||||
#### Local remote debugging
|
||||
|
||||
```bash
|
||||
expport OBJ_PATH=~/aot_debug
|
||||
cd ~/aot_debug # This directory contains iwasm, test.c, test obj file and dynamic_aot_debug.py
|
||||
gdb ./iwasm
|
||||
(gdb) target remote hostip:port
|
||||
(gdb) source dynamic_aot_debug.py
|
||||
(gdb) c
|
||||
(gdb) b test.c:main
|
||||
(gdb) n
|
||||
```
|
||||
|
||||
### 4.2 ARMv7
|
||||
|
||||
#### Compile test.c to test.wasm
|
||||
|
||||
```bash
|
||||
/opt/wasi-sdk/bin/clang -O0 -nostdlib -z stack-size=8192 -Wl,--initial-memory=65536
|
||||
-g -gdwarf-2 -o test.wasm test.c -Wl,--export=main -Wl,--export=__main_argc_argv
|
||||
-Wl,--export=__heap_base -Wl,--export=__data_end -Wl,--no-entry -Wl,--allow-undefined
|
||||
```
|
||||
|
||||
#### Compile test.wasm to test.aot
|
||||
|
||||
```bash
|
||||
./wamrc --opt-level=0 --target=thumbv7 --target-abi=gnueabihf --cpu=cortex-a7
|
||||
--cpu-features=-neon -o test.aot test.wasm
|
||||
```
|
||||
|
||||
#### Compile test.wasm to test object file
|
||||
|
||||
> Note: please use the version wamrc which was built with `cmake -DWAMR_BUILD_DEBUG_AOT` flag.
|
||||
|
||||
```bash
|
||||
./wamrc --opt-level=0 --format=object --target=thumbv7 --target-abi=gnueabihf
|
||||
--cpu=cortex-a7 --cpu-features=-neon -o test.obj test.wasm
|
||||
```
|
||||
|
||||
#### Start Emulator
|
||||
|
||||
In Terminal 1, start the emulator in debug mode and launch the GDB server:
|
||||
|
||||
```bash
|
||||
# start emulator on debug mode, and will start gdb server, set port as 1234
|
||||
./emulator.sh vela -qemu -S -s
|
||||
ap> iwasm test.aot
|
||||
```
|
||||
|
||||
#### Start NuttX Using GDB
|
||||
|
||||
In Terminal 2, set the path to your object file and start NuttX with GDB:
|
||||
|
||||
```bash
|
||||
# You can save test.obj file in this path
|
||||
export OBJ_PATH=~/work/data/aot_debug
|
||||
gdb-multiarch nuttx -ex "tar remote:1234" -ex "source dynamic_aot_debug.py"
|
||||
```
|
||||
|
||||
In the GDB prompt:
|
||||
|
||||
```bash
|
||||
(gdb) c
|
||||
(gdb) b test.c:main
|
||||
(gdb) n
|
||||
```
|
||||
|
||||
## 5. Workflow
|
||||
|
||||
Refer to the workflow diagram (wasm-micro-runtime/test-tools/dynamic-aot-debug) for an overview of the debugging process. In addition, the implementation of this dynamic aot debugging solution is not complete yet. It only supports breakpoints and single-step execution, and it is not yet known to view detailed information such as variables.
|
104
test-tools/dynamic-aot-debug/dynamic_aot_debug.py
Normal file
104
test-tools/dynamic-aot-debug/dynamic_aot_debug.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
import os
|
||||
import gdb
|
||||
|
||||
# Get object file path from environment variable or use default value
|
||||
path_objs = os.getenv("OBJ_PATH", "~/objects/")
|
||||
|
||||
# Expand user directory symbol (~)
|
||||
path_objs = os.path.expanduser(path_objs)
|
||||
print(f"Object files will be loaded from: {path_objs} on localhost")
|
||||
|
||||
|
||||
def add_symbol_with_aot_info(aot_module_info):
|
||||
"""Add symbol file with AOT information to GDB and list current breakpoints."""
|
||||
try:
|
||||
text_addr = aot_module_info.get("code")
|
||||
file_name = aot_module_info.get("name")
|
||||
|
||||
if not text_addr or not file_name:
|
||||
print("Error: 'code' or 'name' missing in AOT module info.")
|
||||
return
|
||||
|
||||
# Extract base file name without extension
|
||||
file_name_without_extension, _ = os.path.splitext(file_name)
|
||||
|
||||
# Remove directory part if present
|
||||
file_name = os.path.basename(file_name_without_extension)
|
||||
|
||||
# Add .obj extension to the file name
|
||||
file_name = file_name + ".obj"
|
||||
|
||||
# Construct the path for the symbol file
|
||||
path_symfile = os.path.join(path_objs, file_name)
|
||||
|
||||
# Construct the command to add the symbol file
|
||||
cmd = f"add-symbol-file {path_symfile} {text_addr}"
|
||||
gdb.execute(cmd)
|
||||
|
||||
# Print current breakpoints
|
||||
breakpoints = gdb.execute("info breakpoints", to_string=True)
|
||||
print("Current breakpoints:", breakpoints)
|
||||
|
||||
except gdb.error as e:
|
||||
print(f"GDB error: {e}")
|
||||
except Exception as e:
|
||||
print(f"Unexpected error: {e}")
|
||||
|
||||
|
||||
class ReadGDynamicAotModule(gdb.Command):
|
||||
"""Command to read the g_dynamic_aot_module structure and extract information."""
|
||||
|
||||
def __init__(self):
|
||||
super(self.__class__, self).__init__("read_gda", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
"""Retrieve and process the g_dynamic_aot_module structure."""
|
||||
try:
|
||||
aot_module = gdb.parse_and_eval("g_dynamic_aot_module")
|
||||
aot_module_info = {}
|
||||
|
||||
# Ensure aot_module is a pointer and dereference it
|
||||
if aot_module.type.code == gdb.TYPE_CODE_PTR:
|
||||
aot_module = aot_module.dereference()
|
||||
|
||||
# Check if it's a structure type
|
||||
if aot_module.type.strip_typedefs().code == gdb.TYPE_CODE_STRUCT:
|
||||
for field in aot_module.type.fields():
|
||||
field_name = field.name
|
||||
var = aot_module[field_name]
|
||||
|
||||
if field_name == "name":
|
||||
aot_module_info["name"] = var.string()
|
||||
elif field_name == "code":
|
||||
aot_module_info["code"] = str(var)
|
||||
|
||||
if "name" in aot_module_info and "code" in aot_module_info:
|
||||
add_symbol_with_aot_info(aot_module_info)
|
||||
else:
|
||||
print("Could not find 'name' or 'code' in Aot_module.")
|
||||
else:
|
||||
print("Aot_module is not of struct type.")
|
||||
else:
|
||||
print("Aot_module is not a pointer type.")
|
||||
except gdb.error as e:
|
||||
print(f"An error occurred: {e}")
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize environment and set up debugger."""
|
||||
# Register the command to gdb
|
||||
ReadGDynamicAotModule()
|
||||
|
||||
# Set a breakpoint at function __enable_dynamic_aot_debug
|
||||
breakpoint = gdb.Breakpoint("__enable_dynamic_aot_debug")
|
||||
# Attach the self-defined command to the created breakpoint, read_gda means read global dynamic aot info.
|
||||
breakpoint.commands = "read_gda"
|
||||
|
||||
|
||||
init()
|
17
test-tools/dynamic-aot-debug/dynamic_aot_debug_workflow.svg
Normal file
17
test-tools/dynamic-aot-debug/dynamic_aot_debug_workflow.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 94 KiB |
Loading…
Reference in New Issue
Block a user