Merge branch main into dev/shared_heap

This commit is contained in:
Wenyong Huang 2024-09-20 14:34:00 +08:00
commit 1fd422ae6e
20 changed files with 1024 additions and 338 deletions

View File

@ -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")

View File

@ -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")

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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).

View File

@ -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, &section_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;
}

View File

@ -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)
{

View File

@ -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);

View File

@ -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()

View File

@ -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

View File

@ -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

View 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.

View 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()

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 94 KiB