Add no_resolve to LoadArgs and wasm_runtime_resolve_symbols (#3790)
Add no_resolve to LoadArgs and wasm_runtime_resolve_symbols so one can delay resolving of symbols. This is useful for inspecting the module between loading and instantiating.
This commit is contained in:
@ -634,73 +634,6 @@ str2uint32(const char *buf, uint32 *p_res);
|
|||||||
static bool
|
static bool
|
||||||
str2uint64(const char *buf, uint64 *p_res);
|
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
|
static bool
|
||||||
load_native_symbol_section(const uint8 *buf, const uint8 *buf_end,
|
load_native_symbol_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
AOTModule *module, bool is_load_from_file_buf,
|
AOTModule *module, bool is_load_from_file_buf,
|
||||||
@ -2285,19 +2218,13 @@ destroy_import_funcs(AOTImportFunc *import_funcs)
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
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)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
char *module_name, *field_name;
|
|
||||||
const uint8 *buf = *p_buf;
|
const uint8 *buf = *p_buf;
|
||||||
AOTImportFunc *import_funcs;
|
AOTImportFunc *import_funcs;
|
||||||
uint64 size;
|
uint64 size;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
|
||||||
AOTModule *sub_module = NULL;
|
|
||||||
AOTFunc *linked_func = NULL;
|
|
||||||
AOTFuncType *declare_func_type = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
size = sizeof(AOTImportFunc) * (uint64)module->import_func_count;
|
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;
|
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 =
|
import_funcs[i].func_type =
|
||||||
(AOTFuncType *)module->types[import_funcs[i].func_type_index];
|
(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].module_name);
|
||||||
read_string(buf, buf_end, import_funcs[i].func_name);
|
read_string(buf, buf_end, import_funcs[i].func_name);
|
||||||
module_name = import_funcs[i].module_name;
|
import_funcs[i].attachment = NULL;
|
||||||
field_name = import_funcs[i].func_name;
|
import_funcs[i].signature = NULL;
|
||||||
import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol(
|
import_funcs[i].call_conv_raw = false;
|
||||||
module_name, field_name, import_funcs[i].func_type,
|
|
||||||
&import_funcs[i].signature, &import_funcs[i].attachment,
|
if (!no_resolve) {
|
||||||
&import_funcs[i].call_conv_raw);
|
aot_resolve_import_func(module, &import_funcs[i]);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_LIBC_WASI != 0
|
#if WASM_ENABLE_LIBC_WASI != 0
|
||||||
if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
|
if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
|
||||||
@ -2378,7 +2269,7 @@ fail:
|
|||||||
static bool
|
static bool
|
||||||
load_import_func_info(const uint8 **p_buf, const uint8 *buf_end,
|
load_import_func_info(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
AOTModule *module, bool is_load_from_file_buf,
|
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;
|
const uint8 *buf = *p_buf;
|
||||||
|
|
||||||
@ -2387,7 +2278,7 @@ load_import_func_info(const uint8 **p_buf, const uint8 *buf_end,
|
|||||||
/* load import funcs */
|
/* load import funcs */
|
||||||
if (module->import_func_count > 0
|
if (module->import_func_count > 0
|
||||||
&& !load_import_funcs(&buf, buf_end, module, is_load_from_file_buf,
|
&& !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;
|
return false;
|
||||||
|
|
||||||
*p_buf = buf;
|
*p_buf = buf;
|
||||||
@ -2514,7 +2405,7 @@ fail:
|
|||||||
static bool
|
static bool
|
||||||
load_init_data_section(const uint8 *buf, const uint8 *buf_end,
|
load_init_data_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
AOTModule *module, bool is_load_from_file_buf,
|
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;
|
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)
|
error_buf, error_buf_size)
|
||||||
|| !load_global_info(&p, p_end, module, 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,
|
|| !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;
|
return false;
|
||||||
|
|
||||||
/* load function count and start function index */
|
/* load function count and start function index */
|
||||||
@ -3819,7 +3710,7 @@ has_module_memory64(AOTModule *module)
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
load_from_sections(AOTModule *module, AOTSection *sections,
|
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)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
AOTSection *section = sections;
|
AOTSection *section = sections;
|
||||||
@ -3852,8 +3743,8 @@ load_from_sections(AOTModule *module, AOTSection *sections,
|
|||||||
break;
|
break;
|
||||||
case AOT_SECTION_TYPE_INIT_DATA:
|
case AOT_SECTION_TYPE_INIT_DATA:
|
||||||
if (!load_init_data_section(buf, buf_end, module,
|
if (!load_init_data_section(buf, buf_end, module,
|
||||||
is_load_from_file_buf, error_buf,
|
is_load_from_file_buf, no_resolve,
|
||||||
error_buf_size))
|
error_buf, error_buf_size))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case AOT_SECTION_TYPE_TEXT:
|
case AOT_SECTION_TYPE_TEXT:
|
||||||
@ -4076,7 +3967,7 @@ aot_load_from_sections(AOTSection *section_list, char *error_buf,
|
|||||||
if (!module)
|
if (!module)
|
||||||
return NULL;
|
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)) {
|
error_buf_size)) {
|
||||||
aot_unload(module);
|
aot_unload(module);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -4246,7 +4137,8 @@ fail:
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
load(const uint8 *buf, uint32 size, AOTModule *module,
|
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 *buf_end = buf + size;
|
||||||
const uint8 *p = buf, *p_end = buf_end;
|
const uint8 *p = buf, *p_end = buf_end;
|
||||||
@ -4273,7 +4165,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ret = load_from_sections(module, section_list, !wasm_binary_freeable,
|
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 (!ret) {
|
||||||
/* If load_from_sections() fails, then aot text is destroyed
|
/* If load_from_sections() fails, then aot text is destroyed
|
||||||
in destroy_sections() */
|
in destroy_sections() */
|
||||||
@ -4321,8 +4213,8 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
os_thread_jit_write_protect_np(false); /* Make memory writable */
|
os_thread_jit_write_protect_np(false); /* Make memory writable */
|
||||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
if (!load(buf, size, module, args->wasm_binary_freeable, args->no_resolve,
|
||||||
error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
aot_unload(module);
|
aot_unload(module);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5111,3 +5111,125 @@ aot_get_module_name(AOTModule *module)
|
|||||||
{
|
{
|
||||||
return module->name;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -492,6 +492,18 @@ aot_load_from_sections(AOTSection *section_list, char *error_buf,
|
|||||||
void
|
void
|
||||||
aot_unload(AOTModule *module);
|
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.
|
* Instantiate a AOT module.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1484,6 +1484,22 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args,
|
|||||||
error_buf_size);
|
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 *
|
WASMModuleCommon *
|
||||||
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
|
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
|
||||||
uint32 error_buf_size)
|
uint32 error_buf_size)
|
||||||
|
|||||||
@ -534,6 +534,10 @@ typedef struct LoadArgs {
|
|||||||
bool clone_wasm_binary;
|
bool clone_wasm_binary;
|
||||||
/* This option is only used by the AOT/wasm loader (see wasm_export.h) */
|
/* This option is only used by the AOT/wasm loader (see wasm_export.h) */
|
||||||
bool wasm_binary_freeable;
|
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? */
|
/* TODO: more fields? */
|
||||||
} LoadArgs;
|
} LoadArgs;
|
||||||
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
||||||
|
|||||||
@ -252,6 +252,11 @@ typedef struct LoadArgs {
|
|||||||
const strings), making it possible to free the wasm binary buffer after
|
const strings), making it possible to free the wasm binary buffer after
|
||||||
loading. */
|
loading. */
|
||||||
bool wasm_binary_freeable;
|
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? */
|
/* TODO: more fields? */
|
||||||
} LoadArgs;
|
} LoadArgs;
|
||||||
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
||||||
@ -569,6 +574,12 @@ WASM_RUNTIME_API_EXTERN wasm_module_t
|
|||||||
wasm_runtime_load_ex(uint8_t *buf, uint32_t size, const LoadArgs *args,
|
wasm_runtime_load_ex(uint8_t *buf, uint32_t size, const LoadArgs *args,
|
||||||
char *error_buf, uint32_t error_buf_size);
|
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.
|
* Load a WASM module from a specified WASM or AOT section list.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -2246,60 +2246,6 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
#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 *
|
static WASMTable *
|
||||||
wasm_loader_resolve_table(const char *module_name, const char *table_name,
|
wasm_loader_resolve_table(const char *module_name, const char *table_name,
|
||||||
uint32 init_size, uint32 max_size, char *error_buf,
|
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,
|
load_function_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
const WASMModule *parent_module,
|
const WASMModule *parent_module,
|
||||||
const char *sub_module_name, const char *function_name,
|
const char *sub_module_name, const char *function_name,
|
||||||
WASMFunctionImport *function, char *error_buf,
|
WASMFunctionImport *function, bool no_resolve,
|
||||||
uint32 error_buf_size)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||||
uint32 declare_type_index = 0;
|
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);
|
read_leb_uint32(p, p_end, declare_type_index);
|
||||||
*p_buf = p;
|
*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);
|
parent_module->types, parent_module->type_count, declare_type_index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
declare_func_type =
|
function->func_type =
|
||||||
(WASMFuncType *)parent_module->types[declare_type_index];
|
(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->module_name = (char *)sub_module_name;
|
||||||
function->field_name = (char *)function_name;
|
function->field_name = (char *)function_name;
|
||||||
function->func_type = declare_func_type;
|
function->attachment = NULL;
|
||||||
/* func_ptr_linked is for native registered symbol */
|
function->signature = NULL;
|
||||||
function->func_ptr_linked = is_native_symbol ? linked_func : NULL;
|
function->call_conv_raw = false;
|
||||||
function->signature = linked_signature;
|
|
||||||
function->attachment = linked_attachment;
|
/* lookup registered native symbols first */
|
||||||
function->call_conv_raw = linked_call_conv_raw;
|
if (!no_resolve) {
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
wasm_resolve_import_func(parent_module, function);
|
||||||
function->import_module = is_native_symbol ? NULL : sub_module;
|
}
|
||||||
function->import_func_linked = is_native_symbol ? NULL : linked_func;
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
@ -3258,8 +3170,8 @@ fail:
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
bool is_load_from_file_buf, char *error_buf,
|
bool is_load_from_file_buf, bool no_resolve,
|
||||||
uint32 error_buf_size)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = buf, *p_end = buf_end, *p_old;
|
const uint8 *p = buf, *p_end = buf_end, *p_old;
|
||||||
uint32 import_count, name_len, type_index, i, u32, flags;
|
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 */
|
case IMPORT_KIND_FUNC: /* import function */
|
||||||
bh_assert(import_functions);
|
bh_assert(import_functions);
|
||||||
import = import_functions++;
|
import = import_functions++;
|
||||||
if (!load_function_import(
|
if (!load_function_import(&p, p_end, module,
|
||||||
&p, p_end, module, sub_module_name, field_name,
|
sub_module_name, field_name,
|
||||||
&import->u.function, error_buf, error_buf_size)) {
|
&import->u.function, no_resolve,
|
||||||
|
error_buf, error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -5760,7 +5673,7 @@ static void **handle_table;
|
|||||||
static bool
|
static bool
|
||||||
load_from_sections(WASMModule *module, WASMSection *sections,
|
load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
bool is_load_from_file_buf, bool wasm_binary_freeable,
|
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;
|
WASMExport *export;
|
||||||
WASMSection *section = sections;
|
WASMSection *section = sections;
|
||||||
@ -5817,8 +5730,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||||||
break;
|
break;
|
||||||
case SECTION_TYPE_IMPORT:
|
case SECTION_TYPE_IMPORT:
|
||||||
if (!load_import_section(buf, buf_end, module,
|
if (!load_import_section(buf, buf_end, module,
|
||||||
reuse_const_strings, error_buf,
|
reuse_const_strings, no_resolve,
|
||||||
error_buf_size))
|
error_buf, error_buf_size))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case SECTION_TYPE_FUNC:
|
case SECTION_TYPE_FUNC:
|
||||||
@ -6343,7 +6256,7 @@ wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
|
|||||||
if (!module)
|
if (!module)
|
||||||
return NULL;
|
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)) {
|
error_buf_size)) {
|
||||||
wasm_loader_unload(module);
|
wasm_loader_unload(module);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -6488,7 +6401,8 @@ static union {
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
load(const uint8 *buf, uint32 size, WASMModule *module,
|
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 *buf_end = buf + size;
|
||||||
const uint8 *p = buf, *p_end = buf_end;
|
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)
|
if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size)
|
||||||
|| !load_from_sections(module, section_list, true, wasm_binary_freeable,
|
|| !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);
|
destroy_sections(section_list);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -6695,8 +6609,8 @@ wasm_loader_load(uint8 *buf, uint32 size,
|
|||||||
module->load_size = size;
|
module->load_size = size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
if (!load(buf, size, module, args->wasm_binary_freeable, args->no_resolve,
|
||||||
error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -83,6 +83,124 @@ wasm_unload(WASMModule *module)
|
|||||||
wasm_loader_unload(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 *
|
static void *
|
||||||
runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
|
runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -513,6 +513,13 @@ wasm_load_from_sections(WASMSection *section_list, char *error_buf,
|
|||||||
void
|
void
|
||||||
wasm_unload(WASMModule *module);
|
wasm_unload(WASMModule *module);
|
||||||
|
|
||||||
|
bool
|
||||||
|
wasm_resolve_symbols(WASMModule *module);
|
||||||
|
|
||||||
|
bool
|
||||||
|
wasm_resolve_import_func(const WASMModule *module,
|
||||||
|
WASMFunctionImport *function);
|
||||||
|
|
||||||
WASMModuleInstance *
|
WASMModuleInstance *
|
||||||
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
WASMExecEnv *exec_env_main, uint32 stack_size,
|
WASMExecEnv *exec_env_main, uint32 stack_size,
|
||||||
|
|||||||
Reference in New Issue
Block a user