mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 06:55:07 +00:00
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:
parent
d91047cc37
commit
b554a9d05d
|
@ -132,7 +132,7 @@ The WAMR [samples](./samples) integrate the iwasm VM core, application manager a
|
|||
|
||||
Project Technical Steering Committee
|
||||
====================================
|
||||
The [WAMR PTSC Charter](./TSC_Charter.md) governs the operations of the project TSC.
|
||||
The [WAMR PTSC Charter](./TSC_Charter.md) governs the operations of the project TSC.
|
||||
The current TSC members:
|
||||
- [lum1n0us](https://github.com/lum1n0us) - **Liang He**, <liang.he@intel.com>
|
||||
- [qinxk-inter](https://github.com/qinxk-inter) - **Xiaokang Qin**, <xiaokang.qxk@antgroup.com>
|
||||
|
|
|
@ -2,23 +2,23 @@
|
|||
|
||||
## Section 1. Guiding Principle
|
||||
|
||||
The WebAssembly Micro Runtime (WAMR) project is part of the
|
||||
Bytecode Alliance (BA) which operates transparently, openly,
|
||||
collaboratively, and ethically. Project proposals, timelines, and status
|
||||
The WebAssembly Micro Runtime (WAMR) project is part of the
|
||||
Bytecode Alliance (BA) which operates transparently, openly,
|
||||
collaboratively, and ethically. Project proposals, timelines, and status
|
||||
must not merely be open, but also easily visible to outsiders.
|
||||
|
||||
## Section 2. Project Governance under Bytecode Alliance
|
||||
|
||||
Technical leadership for the WAMR projects within the Bytecode Alliance
|
||||
is delegated to the projects through the project charter. Though the BA TSC
|
||||
Technical leadership for the WAMR projects within the Bytecode Alliance
|
||||
is delegated to the projects through the project charter. Though the BA TSC
|
||||
will not interfere with day-to-day discussions, votes or meetings of the PTSC,
|
||||
the BA TSC may request additional amendments to the PTSC charter when
|
||||
the BA TSC may request additional amendments to the PTSC charter when
|
||||
there is misalignment between the project charter and the BA mission and values.
|
||||
|
||||
|
||||
|
||||
The PTSC structure described in this document may be overhauled as part of
|
||||
establishing a BA TSC in order to adhere to constraints or requirements that
|
||||
The PTSC structure described in this document may be overhauled as part of
|
||||
establishing a BA TSC in order to adhere to constraints or requirements that
|
||||
TSC will impose on project-level governance.
|
||||
|
||||
## Section 3. Establishment of the PTSC
|
||||
|
@ -26,7 +26,7 @@ TSC will impose on project-level governance.
|
|||
PTSC memberships are not time-limited. There is no maximum size of the PTSC.
|
||||
The size is expected to vary in order to ensure adequate coverage of important
|
||||
areas of expertise, balanced with the ability to make decisions efficiently.
|
||||
The PTSC must have at least four members.
|
||||
The PTSC must have at least four members.
|
||||
|
||||
There is no specific set of requirements or qualifications for PTSC
|
||||
membership beyond these rules. The PTSC may add additional members to the
|
||||
|
@ -77,11 +77,11 @@ The PTSC will define WAMR project’s release vehicles.
|
|||
|
||||
## Section 5. WAMR Project Operations
|
||||
|
||||
The PTSC will establish and maintain a development process for the WAMR
|
||||
The PTSC will establish and maintain a development process for the WAMR
|
||||
project. The development process will establish guidelines
|
||||
for how the developers and community will operate. It will, for example,
|
||||
establish appropriate timelines for PTSC review (e.g. agenda items must be
|
||||
published at least a certain number of hours in advance of a PTSC
|
||||
published at least a certain number of hours in advance of a PTSC
|
||||
meeting).
|
||||
|
||||
The PTSC and entire technical community will follow any processes as may
|
||||
|
@ -106,7 +106,7 @@ the candidate's election. Elections shall be done within the projects by
|
|||
the Collaborators active in the project.
|
||||
|
||||
The PTSC will elect from amongst voting PTSC members a PTSC Chairperson to
|
||||
work on building an agenda for PTSC meetings. The PTSC shall hold annual
|
||||
work on building an agenda for PTSC meetings. The PTSC shall hold annual
|
||||
|
||||
elections to select a PTSC Chairperson; there are no limits on the number
|
||||
of terms a PTSC Chairperson may serve.
|
||||
|
|
|
@ -1896,7 +1896,7 @@ aot_validate_app_addr(AOTModuleInstance *module_inst,
|
|||
}
|
||||
|
||||
/* integer overflow check */
|
||||
if(app_offset + size < app_offset) {
|
||||
if(app_offset > UINT32_MAX - size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1920,7 +1920,7 @@ aot_validate_native_addr(AOTModuleInstance *module_inst,
|
|||
}
|
||||
|
||||
/* integer overflow check */
|
||||
if (addr + size < addr) {
|
||||
if ((uintptr_t)addr > UINTPTR_MAX - size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ failed: \
|
|||
size_t i = 0; \
|
||||
memset(out, 0, sizeof(Vector)); \
|
||||
\
|
||||
if (!src->size) { \
|
||||
if (!src || !src->size) { \
|
||||
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(instance, wasm_instance_delete_internal)
|
||||
WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete)
|
||||
WASM_DEFINE_VEC_OWN(frame, wasm_frame_delete)
|
||||
|
||||
static inline bool
|
||||
valid_module_type(uint32 module_type)
|
||||
|
@ -255,6 +256,21 @@ valid_module_type(uint32 module_type)
|
|||
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 */
|
||||
static void
|
||||
wasm_engine_delete_internal(wasm_engine_t *engine)
|
||||
|
@ -264,6 +280,10 @@ wasm_engine_delete_internal(wasm_engine_t *engine)
|
|||
wasm_runtime_free(engine);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
aot_compile_wasm_file_destroy();
|
||||
#endif
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
if (!aot_compile_wasm_file_init()) {
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create wasm_engine_t */
|
||||
if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
|
||||
goto failed;
|
||||
|
@ -1289,10 +1315,106 @@ wasm_val_same(const wasm_val_t *v1, const wasm_val_t *v2)
|
|||
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 *
|
||||
wasm_trap_new_internal(const char *string)
|
||||
wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
|
||||
const char *default_error_info)
|
||||
{
|
||||
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)))) {
|
||||
return NULL;
|
||||
|
@ -1302,11 +1424,39 @@ wasm_trap_new_internal(const char *string)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
wasm_name_new_from_string(trap->message, string);
|
||||
if (strlen(string) && !trap->message->data) {
|
||||
wasm_name_new_from_string_nt(trap->message, error_info);
|
||||
if (strlen(error_info) && !trap->message->data) {
|
||||
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;
|
||||
failed:
|
||||
wasm_trap_delete(trap);
|
||||
|
@ -1342,6 +1492,7 @@ wasm_trap_delete(wasm_trap_t *trap)
|
|||
}
|
||||
|
||||
DEINIT_VEC(trap->message, wasm_byte_vec_delete);
|
||||
/* reuse frames of WASMModuleInstance, do not free it here */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 WASMModuleCommon *module_comm_rt;
|
||||
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 };
|
||||
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);
|
||||
|
||||
|
@ -1401,12 +1615,35 @@ 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);
|
||||
|
||||
module_ex->module_comm_rt = wasm_runtime_load(
|
||||
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
|
||||
error_buf, (uint32)sizeof(error_buf));
|
||||
if (!(module_ex->module_comm_rt)) {
|
||||
LOG_ERROR(error_buf);
|
||||
goto failed;
|
||||
#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(
|
||||
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
|
||||
error_buf, (uint32)sizeof(error_buf));
|
||||
if (!(module_ex->module_comm_rt)) {
|
||||
LOG_ERROR(error_buf);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* add it to a watching list in store */
|
||||
|
@ -2255,12 +2492,13 @@ failed:
|
|||
if (argv != argv_buf)
|
||||
wasm_runtime_free(argv);
|
||||
|
||||
/* trap -> exception -> trap */
|
||||
if (wasm_runtime_get_exception(func->inst_comm_rt)) {
|
||||
return wasm_trap_new_internal(
|
||||
wasm_runtime_get_exception(func->inst_comm_rt));
|
||||
return wasm_trap_new_internal(func->inst_comm_rt, NULL);
|
||||
}
|
||||
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)
|
||||
{
|
||||
char error_buf[128] = { 0 };
|
||||
const uint32 stack_size = 16 * 1024;
|
||||
const uint32 heap_size = 16 * 1024;
|
||||
const uint32 stack_size = 32 * 1024;
|
||||
const uint32 heap_size = 32 * 1024;
|
||||
uint32 import_count = 0;
|
||||
wasm_instance_t *instance = NULL;
|
||||
uint32 i = 0;
|
||||
|
|
|
@ -86,8 +86,16 @@ struct wasm_ref_t {
|
|||
uint32 obj;
|
||||
};
|
||||
|
||||
struct wasm_frame_t {
|
||||
wasm_instance_t *instance;
|
||||
uint32 module_offset;
|
||||
uint32 func_index;
|
||||
uint32 func_offset;
|
||||
};
|
||||
|
||||
struct wasm_trap_t {
|
||||
wasm_byte_vec_t *message;
|
||||
Vector *frames;
|
||||
};
|
||||
|
||||
struct wasm_func_t {
|
||||
|
|
|
@ -2135,19 +2135,82 @@ extern void
|
|||
wasm_set_ref_types_flag(bool enable);
|
||||
#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*
|
||||
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)
|
||||
{
|
||||
WASMModuleCommon *wasm_module = NULL;
|
||||
WASMModule *wasm_module = NULL;
|
||||
AOTCompData *comp_data = NULL;
|
||||
AOTCompContext *comp_ctx = NULL;
|
||||
RuntimeInitArgs init_args;
|
||||
AOTCompOption option = { 0 };
|
||||
AOTFileMap *file_map = NULL, *file_map_next;
|
||||
uint8 *wasm_file_buf_cloned = NULL;
|
||||
uint8 *aot_file_buf = NULL;
|
||||
uint32 aot_file_size;
|
||||
char error_buf[128];
|
||||
|
||||
option.is_jit_mode = false;
|
||||
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;
|
||||
/* default value, enable or disable depends on the platform */
|
||||
option.bounds_checks = 2;
|
||||
option.enable_simd = true;
|
||||
option.enable_aux_stack_check = true;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
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.free_func = free;
|
||||
|
||||
/* load WASM module */
|
||||
if (!(wasm_module = (WASMModuleCommon*)
|
||||
wasm_load(wasm_file_buf, wasm_file_size,
|
||||
error_buf, sizeof(error_buf)))) {
|
||||
os_printf("%s\n", error_buf);
|
||||
aot_set_last_error(error_buf);
|
||||
return NULL;
|
||||
os_mutex_lock(&aot_file_map_lock);
|
||||
|
||||
/* lookup the file maps */
|
||||
file_map = aot_file_maps;
|
||||
while (file_map) {
|
||||
file_map_next = file_map->next;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
file_map = file_map_next;
|
||||
}
|
||||
|
||||
if (!(comp_data = aot_create_comp_data((WASMModule*)wasm_module))) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) {
|
||||
os_printf("%s\n", aot_get_last_error());
|
||||
bh_memcpy_s(wasm_file_buf_cloned, wasm_file_size,
|
||||
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;
|
||||
}
|
||||
|
||||
if (!aot_compile_wasm(comp_ctx)) {
|
||||
os_printf("%s\n", aot_get_last_error());
|
||||
if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) {
|
||||
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
|
||||
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,
|
||||
&aot_file_size))) {
|
||||
os_printf("%s\n", aot_get_last_error());
|
||||
goto fail3;
|
||||
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
|
||||
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;
|
||||
|
||||
fail3:
|
||||
fail4:
|
||||
/* Destroy compiler context */
|
||||
aot_destroy_comp_context(comp_ctx);
|
||||
fail2:
|
||||
fail3:
|
||||
/* Destroy compile data */
|
||||
aot_destroy_comp_data(comp_data);
|
||||
fail2:
|
||||
wasm_unload(wasm_module);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -368,18 +368,19 @@ aot_emit_aot_file(AOTCompContext *comp_ctx,
|
|||
AOTCompData *comp_data,
|
||||
const char *file_name);
|
||||
|
||||
uint8_t*
|
||||
uint8*
|
||||
aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
|
||||
AOTCompData *comp_data,
|
||||
uint32_t *p_aot_file_size);
|
||||
uint32 *p_aot_file_size);
|
||||
|
||||
bool
|
||||
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
|
||||
|
||||
uint8_t*
|
||||
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 *p_aot_file_size);
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
|
|
|
@ -77,11 +77,18 @@ aot_emit_aot_file(aot_comp_context_t comp_ctx,
|
|||
void
|
||||
aot_destroy_aot_file(uint8_t *aot_file);
|
||||
|
||||
bool
|
||||
aot_compile_wasm_file_init();
|
||||
|
||||
uint8_t*
|
||||
aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
|
||||
uint32_t opt_level, uint32_t size_level,
|
||||
char *error_buf, uint32_t error_buf_size,
|
||||
uint32_t *p_aot_file_size);
|
||||
|
||||
void
|
||||
aot_compile_wasm_file_destroy();
|
||||
|
||||
char*
|
||||
aot_get_last_error();
|
||||
|
||||
|
|
|
@ -1950,7 +1950,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
local_type_index = 0;
|
||||
for (j = 0; j < local_set_count; j++) {
|
||||
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) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid local count");
|
||||
|
|
|
@ -981,8 +981,10 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
local_type_index = 0;
|
||||
for (j = 0; j < local_set_count; j++) {
|
||||
read_leb_uint32(p_code, buf_code_end, sub_local_count);
|
||||
bh_assert(!(local_type_index + sub_local_count <= local_type_index
|
||||
|| local_type_index + sub_local_count > local_count));
|
||||
bh_assert(sub_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);
|
||||
/* 0x7F/0x7E/0x7D/0x7C */
|
||||
|
|
|
@ -1580,6 +1580,14 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
|||
if (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);
|
||||
}
|
||||
|
||||
|
@ -1925,7 +1933,7 @@ wasm_validate_app_addr(WASMModuleInstance *module_inst,
|
|||
memory_data_size = memory->num_bytes_per_page * memory->cur_page_count;
|
||||
|
||||
/* integer overflow check */
|
||||
if (app_offset + size < app_offset) {
|
||||
if (app_offset > UINT32_MAX - size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1949,7 +1957,7 @@ wasm_validate_native_addr(WASMModuleInstance *module_inst,
|
|||
}
|
||||
|
||||
/* integer overflow check */
|
||||
if (addr + size < addr) {
|
||||
if ((uintptr_t)addr > UINTPTR_MAX - size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -2421,19 +2429,59 @@ void
|
|||
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
|
||||
{
|
||||
WASMModuleInstance *module_inst =
|
||||
(WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
|
||||
WASMInterpFrame *cur_frame =
|
||||
wasm_exec_env_get_cur_frame(exec_env);
|
||||
WASMFunctionInstance *func_inst;
|
||||
WASMExportFuncInstance *export_func;
|
||||
const char *func_name = NULL;
|
||||
uint32 n, i;
|
||||
(WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
|
||||
WASMInterpFrame *first_frame,
|
||||
*cur_frame = wasm_exec_env_get_cur_frame(exec_env);
|
||||
uint32 n = 0;
|
||||
|
||||
/* 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");
|
||||
for (n = 0; cur_frame && cur_frame->function; n++) {
|
||||
func_name = NULL;
|
||||
func_inst = cur_frame->function;
|
||||
while (cur_frame) {
|
||||
struct WASMFrame frame = { 0 };
|
||||
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) {
|
||||
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,
|
||||
search symbols from export table */
|
||||
if (!func_name) {
|
||||
uint32 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) {
|
||||
func_name = export_func->name;
|
||||
break;
|
||||
|
@ -2462,7 +2512,11 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
|
|||
os_printf("#%02d %s \n", n, func_name);
|
||||
}
|
||||
|
||||
/* keep print */
|
||||
bh_vector_append(module_inst->frames, &frame);
|
||||
|
||||
cur_frame = cur_frame->prev_frame;
|
||||
n++;
|
||||
}
|
||||
os_printf("\n");
|
||||
}
|
||||
|
|
|
@ -150,6 +150,15 @@ typedef struct WASMExportMemInstance {
|
|||
} WASMExportMemInstance;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
struct WASMFrame {
|
||||
void *instance;
|
||||
uint32 module_offset;
|
||||
uint32 func_index;
|
||||
uint32 func_offset;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct WASMModuleInstance {
|
||||
/* Module instance type, for module instance loaded from
|
||||
WASM bytecode binary, this field is Wasm_Module_Bytecode;
|
||||
|
@ -209,6 +218,10 @@ struct WASMModuleInstance {
|
|||
/* The exception buffer of wasm interpreter for current thread. */
|
||||
char cur_exception[128];
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
Vector *frames;
|
||||
#endif
|
||||
|
||||
/* The custom data that can be set/get by
|
||||
* wasm_set_custom_data/wasm_get_custom_data */
|
||||
void *custom_data;
|
||||
|
|
|
@ -94,6 +94,12 @@ if (COLLECT_CODE_COVERAGE EQUAL 1)
|
|||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
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}/../../..)
|
||||
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
|
|
@ -41,6 +41,7 @@ endif()
|
|||
set(WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
set(WAMR_BUILD_LIBC_WASI 0)
|
||||
set(WAMR_BUILD_MULTI_MODULE 1)
|
||||
set(WAMR_BUILD_DUMP_CALL_STACK 1)
|
||||
|
||||
if(NOT DEFINED WAMR_BUILD_FAST_INTERP)
|
||||
set(WAMR_BUILD_FAST_INTERP 1)
|
||||
|
|
|
@ -92,32 +92,6 @@ DEFINE_FUNCTION(log)
|
|||
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"
|
||||
// -1: memory
|
||||
|
@ -221,11 +195,33 @@ main(int argc, const char *argv[])
|
|||
|
||||
// Instantiate.
|
||||
printf("Instantiating module...\n");
|
||||
const wasm_extern_t *imports[10] = { 0 };
|
||||
|
||||
// Create external functions.
|
||||
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 =
|
||||
wasm_instance_new(store, module, imports, NULL);
|
||||
|
@ -234,6 +230,11 @@ main(int argc, const char *argv[])
|
|||
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.
|
||||
printf("Extracting export...\n");
|
||||
wasm_instance_exports(instance, &exports);
|
||||
|
|
|
@ -19,6 +19,17 @@ own wasm_trap_t* fail_callback(
|
|||
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[]) {
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
|
@ -93,7 +104,6 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
// Call.
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
char buf[32];
|
||||
const wasm_func_t* func = wasm_extern_as_func(exports.data[i]);
|
||||
if (func == NULL) {
|
||||
printf("> Error accessing export!\n");
|
||||
|
@ -111,9 +121,29 @@ int main(int argc, const char* argv[]) {
|
|||
printf("Printing message...\n");
|
||||
own wasm_name_t message;
|
||||
wasm_trap_message(trap, &message);
|
||||
snprintf(buf, sizeof(buf), "> %%.%us\n", (unsigned)message.size);
|
||||
printf(buf, message.data);
|
||||
printf("> %s\n", 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_name_delete(&message);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user