Implement wasm-c-api frame/trap APIs for interpreter mode (#660)

And enable to cache compiled AOT file buffer for wasm-c-api JIT mode
Avoid checks that rely on undefined C behavior
Fix issues of wasm-c-api sample trap and callback_chain

Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
Wenyong Huang 2021-07-06 17:05:59 +08:00 committed by GitHub
parent d91047cc37
commit b554a9d05d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 576 additions and 104 deletions

View File

@ -1896,7 +1896,7 @@ aot_validate_app_addr(AOTModuleInstance *module_inst,
} }
/* integer overflow check */ /* integer overflow check */
if(app_offset + size < app_offset) { if(app_offset > UINT32_MAX - size) {
goto fail; goto fail;
} }
@ -1920,7 +1920,7 @@ aot_validate_native_addr(AOTModuleInstance *module_inst,
} }
/* integer overflow check */ /* integer overflow check */
if (addr + size < addr) { if ((uintptr_t)addr > UINTPTR_MAX - size) {
goto fail; goto fail;
} }

View File

@ -189,7 +189,7 @@ failed: \
size_t i = 0; \ size_t i = 0; \
memset(out, 0, sizeof(Vector)); \ memset(out, 0, sizeof(Vector)); \
\ \
if (!src->size) { \ if (!src || !src->size) { \
return; \ return; \
} \ } \
\ \
@ -232,6 +232,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal) WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal)
WASM_DEFINE_VEC_OWN(instance, wasm_instance_delete_internal) WASM_DEFINE_VEC_OWN(instance, wasm_instance_delete_internal)
WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete) WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete)
WASM_DEFINE_VEC_OWN(frame, wasm_frame_delete)
static inline bool static inline bool
valid_module_type(uint32 module_type) valid_module_type(uint32 module_type)
@ -255,6 +256,21 @@ valid_module_type(uint32 module_type)
return result; return result;
} }
/* conflicting declaration between aot_export.h and aot.h */
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
bool
aot_compile_wasm_file_init();
void
aot_compile_wasm_file_destroy();
uint8*
aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
uint32 opt_level, uint32 size_level,
char *error_buf, uint32 error_buf_size,
uint32 *p_aot_file_size);
#endif
/* Runtime Environment */ /* Runtime Environment */
static void static void
wasm_engine_delete_internal(wasm_engine_t *engine) wasm_engine_delete_internal(wasm_engine_t *engine)
@ -264,6 +280,10 @@ wasm_engine_delete_internal(wasm_engine_t *engine)
wasm_runtime_free(engine); wasm_runtime_free(engine);
} }
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
aot_compile_wasm_file_destroy();
#endif
wasm_runtime_destroy(); wasm_runtime_destroy();
} }
@ -311,6 +331,12 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
bh_log_set_verbose_level(3); bh_log_set_verbose_level(3);
#endif #endif
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
if (!aot_compile_wasm_file_init()) {
goto failed;
}
#endif
/* create wasm_engine_t */ /* create wasm_engine_t */
if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) { if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
goto failed; goto failed;
@ -1289,10 +1315,106 @@ wasm_val_same(const wasm_val_t *v1, const wasm_val_t *v2)
return false; return false;
} }
static wasm_frame_t *
wasm_frame_new(wasm_instance_t *instance,
size_t module_offset,
uint32 func_index,
size_t func_offset)
{
wasm_frame_t *frame;
if (!(frame = malloc_internal(sizeof(wasm_frame_t)))) {
return NULL;
}
frame->instance = instance;
frame->module_offset = module_offset;
frame->func_index = func_index;
frame->func_offset = func_offset;
return frame;
}
own wasm_frame_t *
wasm_frame_copy(const wasm_frame_t *src)
{
if (!src) {
return NULL;
}
return wasm_frame_new(src->instance, src->module_offset, src->func_index,
src->func_offset);
}
void
wasm_frame_delete(own wasm_frame_t *frame)
{
if (!frame) {
return;
}
wasm_runtime_free(frame);
}
struct wasm_instance_t *
wasm_frame_instance(const wasm_frame_t *frame)
{
return frame ? frame->instance : NULL;
}
size_t
wasm_frame_module_offset(const wasm_frame_t *frame)
{
return frame ? frame->module_offset : 0;
}
uint32_t
wasm_frame_func_index(const wasm_frame_t *frame)
{
return frame ? frame->func_index : 0;
}
size_t
wasm_frame_func_offset(const wasm_frame_t *frame)
{
return frame ? frame->func_offset : 0;
}
static wasm_trap_t * static wasm_trap_t *
wasm_trap_new_internal(const char *string) wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
const char *default_error_info)
{ {
wasm_trap_t *trap; wasm_trap_t *trap;
const char *error_info = NULL;
wasm_instance_vec_t *instances;
wasm_instance_t *frame_instance = NULL;
uint32 i;
if (!singleton_engine || !singleton_engine->stores
|| !singleton_engine->stores->num_elems) {
return NULL;
}
#if WASM_ENABLE_INTERP != 0
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
if (!(error_info =
wasm_get_exception((WASMModuleInstance *)inst_comm_rt))) {
return NULL;
}
}
#endif
#if WASM_ENABLE_AOT != 0
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
if (!(error_info =
aot_get_exception((AOTModuleInstance *)inst_comm_rt))) {
return NULL;
}
}
#endif
if (!error_info && !(error_info = default_error_info)) {
return NULL;
}
if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) { if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
return NULL; return NULL;
@ -1302,11 +1424,39 @@ wasm_trap_new_internal(const char *string)
goto failed; goto failed;
} }
wasm_name_new_from_string(trap->message, string); wasm_name_new_from_string_nt(trap->message, error_info);
if (strlen(string) && !trap->message->data) { if (strlen(error_info) && !trap->message->data) {
goto failed; goto failed;
} }
#if WASM_ENABLE_DUMP_CALL_STACK != 0
#if WASM_ENABLE_INTERP != 0
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
trap->frames = ((WASMModuleInstance *)inst_comm_rt)->frames;
}
#endif
#endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */
/* allow a NULL frames list */
if (!trap->frames) {
return trap;
}
if (!(instances = singleton_engine->stores->data[0]->instances)) {
goto failed;
}
for (i = 0; i < instances->num_elems; i++) {
if (instances->data[i]->inst_comm_rt == inst_comm_rt) {
frame_instance = instances->data[i];
break;
}
}
for (i = 0; i < trap->frames->num_elems; i++) {
(((wasm_frame_t *)trap->frames->data) + i)->instance = frame_instance;
}
return trap; return trap;
failed: failed:
wasm_trap_delete(trap); wasm_trap_delete(trap);
@ -1342,6 +1492,7 @@ wasm_trap_delete(wasm_trap_t *trap)
} }
DEINIT_VEC(trap->message, wasm_byte_vec_delete); DEINIT_VEC(trap->message, wasm_byte_vec_delete);
/* reuse frames of WASMModuleInstance, do not free it here */
wasm_runtime_free(trap); wasm_runtime_free(trap);
} }
@ -1356,6 +1507,65 @@ wasm_trap_message(const wasm_trap_t *trap, own wasm_message_t *out)
wasm_byte_vec_copy(out, trap->message); wasm_byte_vec_copy(out, trap->message);
} }
own wasm_frame_t *
wasm_trap_origin(const wasm_trap_t *trap)
{
wasm_frame_t *latest_frame;
if (!trap || !trap->frames || !trap->frames->num_elems) {
return NULL;
}
/* first frame is the latest frame */
latest_frame = (wasm_frame_t *)trap->frames->data;
return wasm_frame_copy(latest_frame);
}
void
wasm_trap_trace(const wasm_trap_t *trap, own wasm_frame_vec_t *out)
{
uint32 i;
if (!trap || !out) {
return;
}
if (!trap->frames || !trap->frames->num_elems) {
wasm_frame_vec_new_empty(out);
return;
}
wasm_frame_vec_new_uninitialized(out, trap->frames->num_elems);
if (out->size && !out->data) {
return;
}
for (i = 0; i < trap->frames->num_elems; i++) {
wasm_frame_t *frame;
frame = ((wasm_frame_t *)trap->frames->data) + i;
if (!(out->data[i] =
wasm_frame_new(frame->instance, frame->module_offset,
frame->func_index, frame->func_offset))) {
goto failed;
}
out->num_elems++;
}
return;
failed:
for (i = 0; i < out->num_elems; i++) {
if (out->data[i]) {
wasm_runtime_free(out->data[i]);
}
}
if (out->data) {
wasm_runtime_free(out->data);
}
}
struct wasm_module_ex_t { struct wasm_module_ex_t {
struct WASMModuleCommon *module_comm_rt; struct WASMModuleCommon *module_comm_rt;
wasm_byte_vec_t *binary; wasm_byte_vec_t *binary;
@ -1386,6 +1596,10 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
{ {
char error_buf[128] = { 0 }; char error_buf[128] = { 0 };
wasm_module_ex_t *module_ex = NULL; wasm_module_ex_t *module_ex = NULL;
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
uint8 *aot_file_buf = NULL;
uint32 aot_file_size;
#endif
bh_assert(singleton_engine); bh_assert(singleton_engine);
@ -1401,6 +1615,28 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data); INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
if (get_package_type((uint8 *)module_ex->binary->data,
(uint32)module_ex->binary->size)
== Wasm_Module_Bytecode) {
if (!(aot_file_buf = aot_compile_wasm_file(
(uint8 *)module_ex->binary->data,
(uint32)module_ex->binary->size, 3, 3, error_buf,
(uint32)sizeof(error_buf), &aot_file_size))) {
LOG_ERROR(error_buf);
goto failed;
}
if (!(module_ex->module_comm_rt =
wasm_runtime_load(aot_file_buf, aot_file_size, error_buf,
(uint32)sizeof(error_buf)))) {
LOG_ERROR(error_buf);
goto failed;
}
}
else
#endif
{
module_ex->module_comm_rt = wasm_runtime_load( module_ex->module_comm_rt = wasm_runtime_load(
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
error_buf, (uint32)sizeof(error_buf)); error_buf, (uint32)sizeof(error_buf));
@ -1408,6 +1644,7 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
LOG_ERROR(error_buf); LOG_ERROR(error_buf);
goto failed; goto failed;
} }
}
/* add it to a watching list in store */ /* add it to a watching list in store */
if (!bh_vector_append((Vector *)store->modules, &module_ex)) { if (!bh_vector_append((Vector *)store->modules, &module_ex)) {
@ -2255,12 +2492,13 @@ failed:
if (argv != argv_buf) if (argv != argv_buf)
wasm_runtime_free(argv); wasm_runtime_free(argv);
/* trap -> exception -> trap */
if (wasm_runtime_get_exception(func->inst_comm_rt)) { if (wasm_runtime_get_exception(func->inst_comm_rt)) {
return wasm_trap_new_internal( return wasm_trap_new_internal(func->inst_comm_rt, NULL);
wasm_runtime_get_exception(func->inst_comm_rt));
} }
else { else {
return wasm_trap_new_internal("wasm_func_call failed"); return wasm_trap_new_internal(func->inst_comm_rt,
"wasm_func_call failed");
} }
} }
@ -3446,8 +3684,8 @@ wasm_instance_new(wasm_store_t *store,
own wasm_trap_t **traps) own wasm_trap_t **traps)
{ {
char error_buf[128] = { 0 }; char error_buf[128] = { 0 };
const uint32 stack_size = 16 * 1024; const uint32 stack_size = 32 * 1024;
const uint32 heap_size = 16 * 1024; const uint32 heap_size = 32 * 1024;
uint32 import_count = 0; uint32 import_count = 0;
wasm_instance_t *instance = NULL; wasm_instance_t *instance = NULL;
uint32 i = 0; uint32 i = 0;

View File

@ -86,8 +86,16 @@ struct wasm_ref_t {
uint32 obj; uint32 obj;
}; };
struct wasm_frame_t {
wasm_instance_t *instance;
uint32 module_offset;
uint32 func_index;
uint32 func_offset;
};
struct wasm_trap_t { struct wasm_trap_t {
wasm_byte_vec_t *message; wasm_byte_vec_t *message;
Vector *frames;
}; };
struct wasm_func_t { struct wasm_func_t {

View File

@ -2135,19 +2135,82 @@ extern void
wasm_set_ref_types_flag(bool enable); wasm_set_ref_types_flag(bool enable);
#endif #endif
typedef struct AOTFileMap {
uint8 *wasm_file_buf;
uint32 wasm_file_size;
uint8 *aot_file_buf;
uint32 aot_file_size;
struct AOTFileMap *next;
} AOTFileMap;
static bool aot_compile_wasm_file_inited = false;
static AOTFileMap *aot_file_maps = NULL;
static korp_mutex aot_file_map_lock;
bool
aot_compile_wasm_file_init()
{
if (aot_compile_wasm_file_inited) {
return true;
}
if (BHT_OK != os_mutex_init(&aot_file_map_lock)) {
return false;
}
aot_file_maps = NULL;
aot_compile_wasm_file_inited = true;
return true;
}
void
aot_compile_wasm_file_destroy()
{
AOTFileMap *file_map = aot_file_maps, *file_map_next;
if (!aot_compile_wasm_file_inited) {
return;
}
while (file_map) {
file_map_next = file_map->next;
wasm_runtime_free(file_map->wasm_file_buf);
wasm_runtime_free(file_map->aot_file_buf);
wasm_runtime_free(file_map);
file_map = file_map_next;
}
aot_file_maps = NULL;
os_mutex_destroy(&aot_file_map_lock);
aot_compile_wasm_file_inited = false;
}
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
{
if (error_buf != NULL) {
snprintf(error_buf, error_buf_size,
"WASM module load failed: %s", string);
}
}
uint8* uint8*
aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
uint32 opt_level, uint32 size_level, uint32 opt_level, uint32 size_level,
char *error_buf, uint32 error_buf_size,
uint32 *p_aot_file_size) uint32 *p_aot_file_size)
{ {
WASMModuleCommon *wasm_module = NULL; WASMModule *wasm_module = NULL;
AOTCompData *comp_data = NULL; AOTCompData *comp_data = NULL;
AOTCompContext *comp_ctx = NULL; AOTCompContext *comp_ctx = NULL;
RuntimeInitArgs init_args; RuntimeInitArgs init_args;
AOTCompOption option = { 0 }; AOTCompOption option = { 0 };
AOTFileMap *file_map = NULL, *file_map_next;
uint8 *wasm_file_buf_cloned = NULL;
uint8 *aot_file_buf = NULL; uint8 *aot_file_buf = NULL;
uint32 aot_file_size; uint32 aot_file_size;
char error_buf[128];
option.is_jit_mode = false; option.is_jit_mode = false;
option.opt_level = opt_level; option.opt_level = opt_level;
@ -2155,7 +2218,6 @@ aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
option.output_format = AOT_FORMAT_FILE; option.output_format = AOT_FORMAT_FILE;
/* default value, enable or disable depends on the platform */ /* default value, enable or disable depends on the platform */
option.bounds_checks = 2; option.bounds_checks = 2;
option.enable_simd = true;
option.enable_aux_stack_check = true; option.enable_aux_stack_check = true;
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
option.enable_bulk_memory = true; option.enable_bulk_memory = true;
@ -2187,46 +2249,94 @@ aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
init_args.mem_alloc_option.allocator.realloc_func = realloc; init_args.mem_alloc_option.allocator.realloc_func = realloc;
init_args.mem_alloc_option.allocator.free_func = free; init_args.mem_alloc_option.allocator.free_func = free;
/* load WASM module */ os_mutex_lock(&aot_file_map_lock);
if (!(wasm_module = (WASMModuleCommon*)
wasm_load(wasm_file_buf, wasm_file_size, /* lookup the file maps */
error_buf, sizeof(error_buf)))) { file_map = aot_file_maps;
os_printf("%s\n", error_buf); while (file_map) {
aot_set_last_error(error_buf); file_map_next = file_map->next;
return NULL;
if (wasm_file_size == file_map->wasm_file_size
&& memcmp(wasm_file_buf, file_map->wasm_file_buf,
wasm_file_size) == 0) {
os_mutex_unlock(&aot_file_map_lock);
/* found */
*p_aot_file_size = file_map->aot_file_size;
return file_map->aot_file_buf;
} }
if (!(comp_data = aot_create_comp_data((WASMModule*)wasm_module))) { file_map = file_map_next;
os_printf("%s\n", aot_get_last_error()); }
/* not found, initialize file map and clone wasm file */
if (!(file_map = wasm_runtime_malloc(sizeof(AOTFileMap)))
|| !(wasm_file_buf_cloned = wasm_runtime_malloc(wasm_file_size))) {
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
goto fail1; goto fail1;
} }
if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) { bh_memcpy_s(wasm_file_buf_cloned, wasm_file_size,
os_printf("%s\n", aot_get_last_error()); wasm_file_buf, wasm_file_size);
memset(file_map, 0, sizeof(AOTFileMap));
file_map->wasm_file_buf = wasm_file_buf_cloned;
file_map->wasm_file_size = wasm_file_size;
/* load WASM module */
if (!(wasm_module = wasm_load(wasm_file_buf, wasm_file_size,
error_buf, sizeof(error_buf)))) {
goto fail1;
}
if (!(comp_data = aot_create_comp_data(wasm_module))) {
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
goto fail2; goto fail2;
} }
if (!aot_compile_wasm(comp_ctx)) { if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) {
os_printf("%s\n", aot_get_last_error()); set_error_buf(error_buf, error_buf_size, aot_get_last_error());
goto fail3; goto fail3;
} }
if (!aot_compile_wasm(comp_ctx)) {
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
goto fail4;
}
if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data,
&aot_file_size))) { &aot_file_size))) {
os_printf("%s\n", aot_get_last_error()); set_error_buf(error_buf, error_buf_size, aot_get_last_error());
goto fail3; goto fail4;
}
file_map->aot_file_buf = aot_file_buf;
file_map->aot_file_size = aot_file_size;
if (!aot_file_maps)
aot_file_maps = file_map;
else {
file_map->next = aot_file_maps;
aot_file_maps = file_map;
} }
*p_aot_file_size = aot_file_size; *p_aot_file_size = aot_file_size;
fail3: fail4:
/* Destroy compiler context */ /* Destroy compiler context */
aot_destroy_comp_context(comp_ctx); aot_destroy_comp_context(comp_ctx);
fail2: fail3:
/* Destroy compile data */ /* Destroy compile data */
aot_destroy_comp_data(comp_data); aot_destroy_comp_data(comp_data);
fail2:
wasm_unload(wasm_module);
fail1: fail1:
wasm_runtime_unload(wasm_module); if (!aot_file_buf) {
if (wasm_file_buf_cloned)
wasm_runtime_free(wasm_file_buf_cloned);
if (file_map)
wasm_runtime_free(file_map);
}
os_mutex_unlock(&aot_file_map_lock);
return aot_file_buf; return aot_file_buf;
} }

View File

@ -368,18 +368,19 @@ aot_emit_aot_file(AOTCompContext *comp_ctx,
AOTCompData *comp_data, AOTCompData *comp_data,
const char *file_name); const char *file_name);
uint8_t* uint8*
aot_emit_aot_file_buf(AOTCompContext *comp_ctx, aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
AOTCompData *comp_data, AOTCompData *comp_data,
uint32_t *p_aot_file_size); uint32 *p_aot_file_size);
bool bool
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name); aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
uint8_t* uint8*
aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size, aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
uint32_t opt_level, uint32_t size_level, uint32 opt_level, uint32 size_level,
uint32_t *p_aot_file_size); char *error_buf, uint32 error_buf_size,
uint32 *p_aot_file_size);
#ifdef __cplusplus #ifdef __cplusplus
} /* end of extern "C" */ } /* end of extern "C" */

View File

@ -77,11 +77,18 @@ aot_emit_aot_file(aot_comp_context_t comp_ctx,
void void
aot_destroy_aot_file(uint8_t *aot_file); aot_destroy_aot_file(uint8_t *aot_file);
bool
aot_compile_wasm_file_init();
uint8_t* uint8_t*
aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size, aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
uint32_t opt_level, uint32_t size_level, uint32_t opt_level, uint32_t size_level,
char *error_buf, uint32_t error_buf_size,
uint32_t *p_aot_file_size); uint32_t *p_aot_file_size);
void
aot_compile_wasm_file_destroy();
char* char*
aot_get_last_error(); aot_get_last_error();

View File

@ -1950,7 +1950,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
local_type_index = 0; local_type_index = 0;
for (j = 0; j < local_set_count; j++) { for (j = 0; j < local_set_count; j++) {
read_leb_uint32(p_code, buf_code_end, sub_local_count); read_leb_uint32(p_code, buf_code_end, sub_local_count);
if (local_type_index + sub_local_count <= local_type_index if (!sub_local_count
|| local_type_index > UINT32_MAX - sub_local_count
|| local_type_index + sub_local_count > local_count) { || local_type_index + sub_local_count > local_count) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"invalid local count"); "invalid local count");

View File

@ -981,8 +981,10 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
local_type_index = 0; local_type_index = 0;
for (j = 0; j < local_set_count; j++) { for (j = 0; j < local_set_count; j++) {
read_leb_uint32(p_code, buf_code_end, sub_local_count); read_leb_uint32(p_code, buf_code_end, sub_local_count);
bh_assert(!(local_type_index + sub_local_count <= local_type_index bh_assert(sub_local_count
|| local_type_index + sub_local_count > local_count)); && local_type_index <= UINT32_MAX - sub_local_count
&& local_type_index + sub_local_count
<= local_count);
CHECK_BUF(p_code, buf_code_end, 1); CHECK_BUF(p_code, buf_code_end, 1);
/* 0x7F/0x7E/0x7D/0x7C */ /* 0x7F/0x7E/0x7D/0x7C */

View File

@ -1580,6 +1580,14 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
if (module_inst->exec_env_singleton) if (module_inst->exec_env_singleton)
wasm_exec_env_destroy(module_inst->exec_env_singleton); wasm_exec_env_destroy(module_inst->exec_env_singleton);
#if WASM_ENABLE_DUMP_CALL_STACK != 0
if (module_inst->frames) {
bh_vector_destroy(module_inst->frames);
wasm_runtime_free(module_inst->frames);
module_inst->frames = NULL;
}
#endif
wasm_runtime_free(module_inst); wasm_runtime_free(module_inst);
} }
@ -1925,7 +1933,7 @@ wasm_validate_app_addr(WASMModuleInstance *module_inst,
memory_data_size = memory->num_bytes_per_page * memory->cur_page_count; memory_data_size = memory->num_bytes_per_page * memory->cur_page_count;
/* integer overflow check */ /* integer overflow check */
if (app_offset + size < app_offset) { if (app_offset > UINT32_MAX - size) {
goto fail; goto fail;
} }
@ -1949,7 +1957,7 @@ wasm_validate_native_addr(WASMModuleInstance *module_inst,
} }
/* integer overflow check */ /* integer overflow check */
if (addr + size < addr) { if ((uintptr_t)addr > UINTPTR_MAX - size) {
goto fail; goto fail;
} }
@ -2422,18 +2430,58 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
{ {
WASMModuleInstance *module_inst = WASMModuleInstance *module_inst =
(WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env); (WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
WASMInterpFrame *cur_frame = WASMInterpFrame *first_frame,
wasm_exec_env_get_cur_frame(exec_env); *cur_frame = wasm_exec_env_get_cur_frame(exec_env);
WASMFunctionInstance *func_inst; uint32 n = 0;
WASMExportFuncInstance *export_func;
const char *func_name = NULL;
uint32 n, i;
/* release previous stack frame */
if (module_inst->frames) {
bh_vector_destroy(module_inst->frames);
wasm_runtime_free(module_inst->frames);
module_inst->frames = NULL;
}
/* count frames includes a function */
first_frame = cur_frame;
while (cur_frame) {
if (cur_frame->function) {
n++;
}
cur_frame = cur_frame->prev_frame;
}
if (!(module_inst->frames = runtime_malloc(
(uint64)sizeof(Vector), module_inst->cur_exception, 128))) {
return;
}
if (!bh_vector_init(module_inst->frames, n, sizeof(struct WASMFrame))) {
wasm_runtime_free(module_inst->frames);
module_inst->frames = NULL;
return;
}
cur_frame = first_frame;
n = 0;
os_printf("\n"); os_printf("\n");
for (n = 0; cur_frame && cur_frame->function; n++) { while (cur_frame) {
func_name = NULL; struct WASMFrame frame = { 0 };
func_inst = cur_frame->function; WASMFunctionInstance *func_inst = cur_frame->function;
const char *func_name = NULL;
if (!func_inst) {
cur_frame = cur_frame->prev_frame;
continue;
}
/* place holder, will overwrite it in wasm_c_api */
frame.instance = module_inst;
frame.module_offset = 0;
frame.func_index = func_inst - module_inst->functions;
frame.func_offset =
cur_frame->ip ? cur_frame->ip - func_inst->u.func->code : 0;
/* look for the function name */
if (func_inst->is_import_func) { if (func_inst->is_import_func) {
func_name = func_inst->u.func_import->field_name; func_name = func_inst->u.func_import->field_name;
} }
@ -2444,8 +2492,10 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
/* if custom name section is not generated, /* if custom name section is not generated,
search symbols from export table */ search symbols from export table */
if (!func_name) { if (!func_name) {
uint32 i;
for (i = 0; i < module_inst->export_func_count; i++) { for (i = 0; i < module_inst->export_func_count; i++) {
export_func = module_inst->export_functions + i; WASMExportFuncInstance *export_func =
module_inst->export_functions + i;
if (export_func->function == func_inst) { if (export_func->function == func_inst) {
func_name = export_func->name; func_name = export_func->name;
break; break;
@ -2462,7 +2512,11 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
os_printf("#%02d %s \n", n, func_name); os_printf("#%02d %s \n", n, func_name);
} }
/* keep print */
bh_vector_append(module_inst->frames, &frame);
cur_frame = cur_frame->prev_frame; cur_frame = cur_frame->prev_frame;
n++;
} }
os_printf("\n"); os_printf("\n");
} }

View File

@ -150,6 +150,15 @@ typedef struct WASMExportMemInstance {
} WASMExportMemInstance; } WASMExportMemInstance;
#endif #endif
#if WASM_ENABLE_DUMP_CALL_STACK != 0
struct WASMFrame {
void *instance;
uint32 module_offset;
uint32 func_index;
uint32 func_offset;
};
#endif
struct WASMModuleInstance { struct WASMModuleInstance {
/* Module instance type, for module instance loaded from /* Module instance type, for module instance loaded from
WASM bytecode binary, this field is Wasm_Module_Bytecode; WASM bytecode binary, this field is Wasm_Module_Bytecode;
@ -209,6 +218,10 @@ struct WASMModuleInstance {
/* The exception buffer of wasm interpreter for current thread. */ /* The exception buffer of wasm interpreter for current thread. */
char cur_exception[128]; char cur_exception[128];
#if WASM_ENABLE_DUMP_CALL_STACK != 0
Vector *frames;
#endif
/* The custom data that can be set/get by /* The custom data that can be set/get by
* wasm_set_custom_data/wasm_get_custom_data */ * wasm_set_custom_data/wasm_get_custom_data */
void *custom_data; void *custom_data;

View File

@ -94,6 +94,12 @@ if (COLLECT_CODE_COVERAGE EQUAL 1)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
endif () endif ()
# UNDEFINED BEHAVIOR
# refer to https://en.cppreference.com/w/cpp/language/ub
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=bounds-strict,undefined -fno-sanitize-recover")
endif()
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)

View File

@ -41,6 +41,7 @@ endif()
set(WAMR_BUILD_LIBC_BUILTIN 1) set(WAMR_BUILD_LIBC_BUILTIN 1)
set(WAMR_BUILD_LIBC_WASI 0) set(WAMR_BUILD_LIBC_WASI 0)
set(WAMR_BUILD_MULTI_MODULE 1) set(WAMR_BUILD_MULTI_MODULE 1)
set(WAMR_BUILD_DUMP_CALL_STACK 1)
if(NOT DEFINED WAMR_BUILD_FAST_INTERP) if(NOT DEFINED WAMR_BUILD_FAST_INTERP)
set(WAMR_BUILD_FAST_INTERP 1) set(WAMR_BUILD_FAST_INTERP 1)

View File

@ -92,32 +92,6 @@ DEFINE_FUNCTION(log)
return NULL; return NULL;
} }
static inline void
create_import_function_list(wasm_store_t *store,
const wasm_extern_t *import_function_list[])
{
#define IMPORT_FUNCTION_VARIABLE_NAME(name, ...) \
own wasm_func_t *function_##name = NULL;
IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME)
#undef IMPORT_FUNCTION_VARIABLE_NAME
#define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \
{ \
own wasm_functype_t *type = CREATE_FUNC_TYPE; \
if (!(function_##name = wasm_func_new(store, type, STUB_##name))) { \
printf("> Error creating new function\n"); \
} \
wasm_functype_delete(type); \
}
IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
#undef CREATE_WASM_FUNCTION
#define ADD_TO_FUNCTION_LIST(name, index, ...) \
import_function_list[index] = wasm_func_as_extern(function_##name);
IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)
#undef CREATE_IMPORT_FUNCTION
}
/**********************************************************************/ /**********************************************************************/
// all exportted wasm functions. check with "/opt/wabt/bin/wasm-objdump -x -j Export X.wasm" // all exportted wasm functions. check with "/opt/wabt/bin/wasm-objdump -x -j Export X.wasm"
// -1: memory // -1: memory
@ -221,11 +195,33 @@ main(int argc, const char *argv[])
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t *imports[10] = { 0 };
// Create external functions. // Create external functions.
printf("Creating callback...\n"); printf("Creating callback...\n");
create_import_function_list(store, imports); #define IMPORT_FUNCTION_VARIABLE_NAME(name, ...) \
own wasm_func_t *function_##name = NULL;
IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME)
#undef IMPORT_FUNCTION_VARIABLE_NAME
const wasm_extern_t *imports[10] = { 0 };
#define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \
{ \
own wasm_functype_t *type = CREATE_FUNC_TYPE; \
if (!(function_##name = wasm_func_new(store, type, STUB_##name))) { \
printf("> Error creating new function\n"); \
return 1; \
} \
wasm_functype_delete(type); \
}
IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
#undef CREATE_WASM_FUNCTION
#define ADD_TO_FUNCTION_LIST(name, index, ...) \
imports[index] = wasm_func_as_extern(function_##name);
IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)
#undef CREATE_IMPORT_FUNCTION
own wasm_instance_t *instance = own wasm_instance_t *instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, imports, NULL);
@ -234,6 +230,11 @@ main(int argc, const char *argv[])
return 1; return 1;
} }
#define DESTROY_WASM_FUNCITON(name, index, ...) \
wasm_func_delete(function_##name);
IMPORT_FUNCTION_LIST(DESTROY_WASM_FUNCITON)
#undef DESTROY_WASM_FUNCITON
// Extract export. // Extract export.
printf("Extracting export...\n"); printf("Extracting export...\n");
wasm_instance_exports(instance, &exports); wasm_instance_exports(instance, &exports);

View File

@ -19,6 +19,17 @@ own wasm_trap_t* fail_callback(
return trap; return trap;
} }
void print_frame(wasm_frame_t* frame) {
printf("> %p @ 0x%zx = %"PRIu32".0x%zx\n",
wasm_frame_instance(frame),
wasm_frame_module_offset(frame),
wasm_frame_func_index(frame),
wasm_frame_func_offset(frame)
);
}
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
// Initialize. // Initialize.
printf("Initializing...\n"); printf("Initializing...\n");
@ -93,7 +104,6 @@ int main(int argc, const char* argv[]) {
// Call. // Call.
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
char buf[32];
const wasm_func_t* func = wasm_extern_as_func(exports.data[i]); const wasm_func_t* func = wasm_extern_as_func(exports.data[i]);
if (func == NULL) { if (func == NULL) {
printf("> Error accessing export!\n"); printf("> Error accessing export!\n");
@ -111,9 +121,29 @@ int main(int argc, const char* argv[]) {
printf("Printing message...\n"); printf("Printing message...\n");
own wasm_name_t message; own wasm_name_t message;
wasm_trap_message(trap, &message); wasm_trap_message(trap, &message);
snprintf(buf, sizeof(buf), "> %%.%us\n", (unsigned)message.size); printf("> %s\n", message.data);
printf(buf, message.data);
printf("Printing origin...\n");
own wasm_frame_t* frame = wasm_trap_origin(trap);
if (frame) {
print_frame(frame);
wasm_frame_delete(frame);
} else {
printf("> Empty origin.\n");
}
printf("Printing trace...\n");
own wasm_frame_vec_t trace;
wasm_trap_trace(trap, &trace);
if (trace.size > 0) {
for (size_t i = 0; i < trace.size; ++i) {
print_frame(trace.data[i]);
}
} else {
printf("> Empty trace.\n");
}
wasm_frame_vec_delete(&trace);
wasm_trap_delete(trap); wasm_trap_delete(trap);
wasm_name_delete(&message); wasm_name_delete(&message);
} }