mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 15:05:19 +00:00
Fix data/elem drop (#2747)
Currently, `data.drop` instruction is implemented by directly modifying the underlying module. It breaks use cases where you have multiple instances sharing a single loaded module. `elem.drop` has the same problem too. This PR fixes the issue by keeping track of which data/elem segments have been dropped by using bitmaps for each module instances separately, and add a sample to demonstrate the issue and make the CI run it. Also add a missing check of dropped elements to the fast-jit `table.init`. Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2735 Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2772
This commit is contained in:
parent
08c0ec74c4
commit
562a5dd1b6
|
@ -444,6 +444,12 @@ jobs:
|
||||||
cmake --build . --config Release --parallel 4
|
cmake --build . --config Release --parallel 4
|
||||||
./iwasm wasm-apps/no_pthread.wasm
|
./iwasm wasm-apps/no_pthread.wasm
|
||||||
|
|
||||||
|
- name: Build Sample [shared-module]
|
||||||
|
run: |
|
||||||
|
cd samples/shared-module
|
||||||
|
./build.sh
|
||||||
|
./run.sh
|
||||||
|
|
||||||
test:
|
test:
|
||||||
needs:
|
needs:
|
||||||
[
|
[
|
||||||
|
|
6
.github/workflows/compilation_on_macos.yml
vendored
6
.github/workflows/compilation_on_macos.yml
vendored
|
@ -327,3 +327,9 @@ jobs:
|
||||||
cmake ..
|
cmake ..
|
||||||
cmake --build . --config Release --parallel 4
|
cmake --build . --config Release --parallel 4
|
||||||
./iwasm wasm-apps/no_pthread.wasm
|
./iwasm wasm-apps/no_pthread.wasm
|
||||||
|
|
||||||
|
- name: Build Sample [shared-module]
|
||||||
|
run: |
|
||||||
|
cd samples/shared-module
|
||||||
|
./build.sh
|
||||||
|
./run.sh
|
||||||
|
|
6
.github/workflows/nightly_run.yml
vendored
6
.github/workflows/nightly_run.yml
vendored
|
@ -501,6 +501,12 @@ jobs:
|
||||||
cmake ..
|
cmake ..
|
||||||
cmake --build . --config Release --parallel 4
|
cmake --build . --config Release --parallel 4
|
||||||
./iwasm wasm-apps/no_pthread.wasm
|
./iwasm wasm-apps/no_pthread.wasm
|
||||||
|
|
||||||
|
- name: Build Sample [shared-module]
|
||||||
|
run: |
|
||||||
|
cd samples/shared-module
|
||||||
|
./build.sh
|
||||||
|
./run.sh
|
||||||
test:
|
test:
|
||||||
needs:
|
needs:
|
||||||
[
|
[
|
||||||
|
|
|
@ -1095,7 +1095,6 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
|
|
||||||
data_list[i]->mode = mode;
|
data_list[i]->mode = mode;
|
||||||
data_list[i]->elem_type = elem_type;
|
data_list[i]->elem_type = elem_type;
|
||||||
data_list[i]->is_dropped = false;
|
|
||||||
data_list[i]->table_index = table_index;
|
data_list[i]->table_index = table_index;
|
||||||
data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
|
data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
|
||||||
data_list[i]->offset.u.i64 = (int64)init_expr_value;
|
data_list[i]->offset.u.i64 = (int64)init_expr_value;
|
||||||
|
|
|
@ -1098,6 +1098,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||||
char *error_buf, uint32 error_buf_size)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
AOTModuleInstance *module_inst;
|
AOTModuleInstance *module_inst;
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
|
||||||
|
WASMModuleInstanceExtraCommon *common;
|
||||||
|
#endif
|
||||||
const uint32 module_inst_struct_size =
|
const uint32 module_inst_struct_size =
|
||||||
offsetof(AOTModuleInstance, global_table_data.bytes);
|
offsetof(AOTModuleInstance, global_table_data.bytes);
|
||||||
const uint64 module_inst_mem_inst_size =
|
const uint64 module_inst_mem_inst_size =
|
||||||
|
@ -1164,6 +1167,32 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
|
||||||
|
common = &((AOTModuleInstanceExtra *)module_inst->e)->common;
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
if (module->mem_init_data_count > 0) {
|
||||||
|
common->data_dropped = bh_bitmap_new(0, module->mem_init_data_count);
|
||||||
|
if (common->data_dropped == NULL) {
|
||||||
|
LOG_DEBUG("failed to allocate bitmaps");
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"failed to allocate bitmaps");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
if (module->table_init_data_count > 0) {
|
||||||
|
common->elem_dropped = bh_bitmap_new(0, module->table_init_data_count);
|
||||||
|
if (common->elem_dropped == NULL) {
|
||||||
|
LOG_DEBUG("failed to allocate bitmaps");
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"failed to allocate bitmaps");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialize global info */
|
/* Initialize global info */
|
||||||
p = (uint8 *)module_inst + module_inst_struct_size
|
p = (uint8 *)module_inst + module_inst_struct_size
|
||||||
+ module_inst_mem_inst_size;
|
+ module_inst_mem_inst_size;
|
||||||
|
@ -1264,6 +1293,8 @@ fail:
|
||||||
void
|
void
|
||||||
aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
||||||
{
|
{
|
||||||
|
WASMModuleInstanceExtraCommon *common =
|
||||||
|
&((AOTModuleInstanceExtra *)module_inst->e)->common;
|
||||||
if (module_inst->exec_env_singleton) {
|
if (module_inst->exec_env_singleton) {
|
||||||
/* wasm_exec_env_destroy will call
|
/* wasm_exec_env_destroy will call
|
||||||
wasm_cluster_wait_for_all_except_self to wait for other
|
wasm_cluster_wait_for_all_except_self to wait for other
|
||||||
|
@ -1306,7 +1337,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
||||||
if (module_inst->func_type_indexes)
|
if (module_inst->func_type_indexes)
|
||||||
wasm_runtime_free(module_inst->func_type_indexes);
|
wasm_runtime_free(module_inst->func_type_indexes);
|
||||||
|
|
||||||
if (((AOTModuleInstanceExtra *)module_inst->e)->common.c_api_func_imports)
|
if (common->c_api_func_imports)
|
||||||
wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e)
|
wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e)
|
||||||
->common.c_api_func_imports);
|
->common.c_api_func_imports);
|
||||||
|
|
||||||
|
@ -1317,6 +1348,13 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
||||||
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
|
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
bh_bitmap_delete(common->data_dropped);
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
bh_bitmap_delete(common->elem_dropped);
|
||||||
|
#endif
|
||||||
|
|
||||||
wasm_runtime_free(module_inst);
|
wasm_runtime_free(module_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2302,13 +2340,21 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset,
|
||||||
{
|
{
|
||||||
AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
|
AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
|
||||||
AOTModule *aot_module;
|
AOTModule *aot_module;
|
||||||
uint8 *data = NULL;
|
uint8 *data;
|
||||||
uint8 *maddr;
|
uint8 *maddr;
|
||||||
uint64 seg_len = 0;
|
uint64 seg_len;
|
||||||
|
|
||||||
|
if (bh_bitmap_get_bit(
|
||||||
|
((AOTModuleInstanceExtra *)module_inst->e)->common.data_dropped,
|
||||||
|
seg_index)) {
|
||||||
|
seg_len = 0;
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
aot_module = (AOTModule *)module_inst->module;
|
aot_module = (AOTModule *)module_inst->module;
|
||||||
seg_len = aot_module->mem_init_data_list[seg_index]->byte_count;
|
seg_len = aot_module->mem_init_data_list[seg_index]->byte_count;
|
||||||
data = aot_module->mem_init_data_list[seg_index]->bytes;
|
data = aot_module->mem_init_data_list[seg_index]->bytes;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
|
if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
|
||||||
dst, len))
|
dst, len))
|
||||||
|
@ -2331,9 +2377,9 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset,
|
||||||
bool
|
bool
|
||||||
aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index)
|
aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index)
|
||||||
{
|
{
|
||||||
AOTModule *aot_module = (AOTModule *)module_inst->module;
|
bh_bitmap_set_bit(
|
||||||
|
((AOTModuleInstanceExtra *)module_inst->e)->common.data_dropped,
|
||||||
aot_module->mem_init_data_list[seg_index]->byte_count = 0;
|
seg_index);
|
||||||
/* Currently we can't free the dropped data segment
|
/* Currently we can't free the dropped data segment
|
||||||
as the mem_init_data_count is a continuous array */
|
as the mem_init_data_count is a continuous array */
|
||||||
return true;
|
return true;
|
||||||
|
@ -2546,9 +2592,9 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
|
||||||
void
|
void
|
||||||
aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx)
|
aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx)
|
||||||
{
|
{
|
||||||
AOTModule *module = (AOTModule *)module_inst->module;
|
bh_bitmap_set_bit(
|
||||||
AOTTableInitData *tbl_seg = module->table_init_data_list[tbl_seg_idx];
|
((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped,
|
||||||
tbl_seg->is_dropped = true;
|
tbl_seg_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2576,7 +2622,9 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tbl_seg->is_dropped) {
|
if (bh_bitmap_get_bit(
|
||||||
|
((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped,
|
||||||
|
tbl_seg_idx)) {
|
||||||
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,6 @@ aot_create_table_init_data_list(const WASMModule *module)
|
||||||
data_list[i]->mode = module->table_segments[i].mode;
|
data_list[i]->mode = module->table_segments[i].mode;
|
||||||
data_list[i]->elem_type = module->table_segments[i].elem_type;
|
data_list[i]->elem_type = module->table_segments[i].elem_type;
|
||||||
/* runtime control it */
|
/* runtime control it */
|
||||||
data_list[i]->is_dropped = false;
|
|
||||||
data_list[i]->table_index = module->table_segments[i].table_index;
|
data_list[i]->table_index = module->table_segments[i].table_index;
|
||||||
bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
|
bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
|
||||||
&module->table_segments[i].base_offset,
|
&module->table_segments[i].base_offset,
|
||||||
|
|
|
@ -143,7 +143,6 @@ typedef struct AOTTableInitData {
|
||||||
uint32 mode;
|
uint32 mode;
|
||||||
/* funcref or externref, elemkind will be considered as funcref */
|
/* funcref or externref, elemkind will be considered as funcref */
|
||||||
uint32 elem_type;
|
uint32 elem_type;
|
||||||
bool is_dropped;
|
|
||||||
/* optional, only for active */
|
/* optional, only for active */
|
||||||
uint32 table_index;
|
uint32 table_index;
|
||||||
/* Start address of init data */
|
/* Start address of init data */
|
||||||
|
|
|
@ -269,7 +269,7 @@ static uint32
|
||||||
get_table_init_data_size(AOTTableInitData *table_init_data)
|
get_table_init_data_size(AOTTableInitData *table_init_data)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* mode (4 bytes), elem_type (4 bytes), do not need is_dropped field
|
* mode (4 bytes), elem_type (4 bytes)
|
||||||
*
|
*
|
||||||
* table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
|
* table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
|
||||||
* bytes)
|
* bytes)
|
||||||
|
|
|
@ -650,6 +650,7 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
|
||||||
WASMDataSeg *data_segment;
|
WASMDataSeg *data_segment;
|
||||||
uint32 mem_size;
|
uint32 mem_size;
|
||||||
uint8 *mem_addr, *data_addr;
|
uint8 *mem_addr, *data_addr;
|
||||||
|
uint32 seg_len;
|
||||||
|
|
||||||
/* if d + n > the length of mem.data */
|
/* if d + n > the length of mem.data */
|
||||||
mem_inst = inst->memories[mem_idx];
|
mem_inst = inst->memories[mem_idx];
|
||||||
|
@ -659,13 +660,19 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
|
||||||
|
|
||||||
/* if s + n > the length of data.data */
|
/* if s + n > the length of data.data */
|
||||||
bh_assert(seg_idx < inst->module->data_seg_count);
|
bh_assert(seg_idx < inst->module->data_seg_count);
|
||||||
|
if (bh_bitmap_get_bit(inst->e->common.data_dropped, seg_idx)) {
|
||||||
|
seg_len = 0;
|
||||||
|
data_addr = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
data_segment = inst->module->data_segments[seg_idx];
|
data_segment = inst->module->data_segments[seg_idx];
|
||||||
if (data_segment->data_length < data_offset
|
seg_len = data_segment->data_length;
|
||||||
|| data_segment->data_length - data_offset < len)
|
data_addr = data_segment->data + data_offset;
|
||||||
|
}
|
||||||
|
if (seg_len < data_offset || seg_len - data_offset < len)
|
||||||
goto out_of_bounds;
|
goto out_of_bounds;
|
||||||
|
|
||||||
mem_addr = mem_inst->memory_data + mem_offset;
|
mem_addr = mem_inst->memory_data + mem_offset;
|
||||||
data_addr = data_segment->data + data_offset;
|
|
||||||
bh_memcpy_s(mem_addr, mem_size - mem_offset, data_addr, len);
|
bh_memcpy_s(mem_addr, mem_size - mem_offset, data_addr, len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -706,21 +713,22 @@ fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wasm_data_drop(WASMModuleInstance *inst, uint32 seg_idx)
|
||||||
|
{
|
||||||
|
bh_bitmap_set_bit(inst->e->common.data_dropped, seg_idx);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx)
|
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx)
|
||||||
{
|
{
|
||||||
JitReg module = get_module_reg(cc->jit_frame);
|
JitReg args[2] = { 0 };
|
||||||
JitReg data_segments = jit_cc_new_reg_ptr(cc);
|
|
||||||
JitReg data_segment = jit_cc_new_reg_ptr(cc);
|
|
||||||
|
|
||||||
GEN_INSN(LDPTR, data_segments, module,
|
args[0] = get_module_inst_reg(cc->jit_frame);
|
||||||
NEW_CONST(I32, offsetof(WASMModule, data_segments)));
|
args[1] = NEW_CONST(I32, seg_idx);
|
||||||
GEN_INSN(LDPTR, data_segment, data_segments,
|
|
||||||
NEW_CONST(I32, seg_idx * sizeof(WASMDataSeg *)));
|
|
||||||
GEN_INSN(STI32, NEW_CONST(I32, 0), data_segment,
|
|
||||||
NEW_CONST(I32, offsetof(WASMDataSeg, data_length)));
|
|
||||||
|
|
||||||
return true;
|
return jit_emit_callnative(cc, wasm_data_drop, 0, args,
|
||||||
|
sizeof(args) / sizeof(args[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -10,21 +10,22 @@
|
||||||
#include "../jit_frontend.h"
|
#include "../jit_frontend.h"
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
static void
|
||||||
|
wasm_elem_drop(WASMModuleInstance *inst, uint32 tbl_seg_idx)
|
||||||
|
{
|
||||||
|
bh_bitmap_set_bit(inst->e->common.elem_dropped, tbl_seg_idx);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
|
jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
|
||||||
{
|
{
|
||||||
JitReg module, tbl_segs;
|
JitReg args[2] = { 0 };
|
||||||
|
|
||||||
module = get_module_reg(cc->jit_frame);
|
args[0] = get_module_inst_reg(cc->jit_frame);
|
||||||
|
args[1] = NEW_CONST(I32, tbl_seg_idx);
|
||||||
|
|
||||||
tbl_segs = jit_cc_new_reg_ptr(cc);
|
return jit_emit_callnative(cc, wasm_elem_drop, 0, args,
|
||||||
GEN_INSN(LDPTR, tbl_segs, module,
|
sizeof(args) / sizeof(args[0]));
|
||||||
NEW_CONST(I32, offsetof(WASMModule, table_segments)));
|
|
||||||
|
|
||||||
GEN_INSN(STI32, NEW_CONST(I32, true), tbl_segs,
|
|
||||||
NEW_CONST(I32, tbl_seg_idx * sizeof(WASMTableSeg)
|
|
||||||
+ offsetof(WASMTableSeg, is_dropped)));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -105,6 +106,12 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
|
||||||
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
|
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
|
||||||
goto out_of_bounds;
|
goto out_of_bounds;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bh_bitmap_get_bit(inst->e->common.elem_dropped, elem_idx))
|
||||||
|
goto out_of_bounds;
|
||||||
|
|
||||||
bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
|
bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
|
||||||
+ dst_offset * sizeof(uint32),
|
+ dst_offset * sizeof(uint32),
|
||||||
(uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
|
(uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
|
||||||
|
|
|
@ -311,7 +311,6 @@ typedef struct WASMTableSeg {
|
||||||
uint32 mode;
|
uint32 mode;
|
||||||
/* funcref or externref, elemkind will be considered as funcref */
|
/* funcref or externref, elemkind will be considered as funcref */
|
||||||
uint32 elem_type;
|
uint32 elem_type;
|
||||||
bool is_dropped;
|
|
||||||
/* optional, only for active */
|
/* optional, only for active */
|
||||||
uint32 table_index;
|
uint32 table_index;
|
||||||
InitializerExpression base_offset;
|
InitializerExpression base_offset;
|
||||||
|
|
|
@ -3160,9 +3160,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
maddr = memory->memory_data + (uint32)addr;
|
maddr = memory->memory_data + (uint32)addr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
seg_len = (uint64)module->module->data_segments[segment]
|
if (bh_bitmap_get_bit(module->e->common.data_dropped,
|
||||||
|
segment)) {
|
||||||
|
seg_len = 0;
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seg_len =
|
||||||
|
(uint64)module->module->data_segments[segment]
|
||||||
->data_length;
|
->data_length;
|
||||||
data = module->module->data_segments[segment]->data;
|
data = module->module->data_segments[segment]->data;
|
||||||
|
}
|
||||||
if (offset + bytes > seg_len)
|
if (offset + bytes > seg_len)
|
||||||
goto out_of_bounds;
|
goto out_of_bounds;
|
||||||
|
|
||||||
|
@ -3175,7 +3183,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
uint32 segment;
|
uint32 segment;
|
||||||
|
|
||||||
read_leb_uint32(frame_ip, frame_ip_end, segment);
|
read_leb_uint32(frame_ip, frame_ip_end, segment);
|
||||||
module->module->data_segments[segment]->data_length = 0;
|
bh_bitmap_set_bit(module->e->common.data_dropped,
|
||||||
|
segment);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_OP_MEMORY_COPY:
|
case WASM_OP_MEMORY_COPY:
|
||||||
|
@ -3270,8 +3279,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (module->module->table_segments[elem_idx]
|
if (bh_bitmap_get_bit(module->e->common.elem_dropped,
|
||||||
.is_dropped) {
|
elem_idx)) {
|
||||||
wasm_set_exception(module,
|
wasm_set_exception(module,
|
||||||
"out of bounds table access");
|
"out of bounds table access");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
|
@ -3303,8 +3312,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
|
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
|
||||||
bh_assert(elem_idx < module->module->table_seg_count);
|
bh_assert(elem_idx < module->module->table_seg_count);
|
||||||
|
|
||||||
module->module->table_segments[elem_idx].is_dropped =
|
bh_bitmap_set_bit(module->e->common.elem_dropped,
|
||||||
true;
|
elem_idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_OP_TABLE_COPY:
|
case WASM_OP_TABLE_COPY:
|
||||||
|
|
|
@ -3005,10 +3005,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
goto out_of_bounds;
|
goto out_of_bounds;
|
||||||
maddr = memory->memory_data + (uint32)addr;
|
maddr = memory->memory_data + (uint32)addr;
|
||||||
#endif
|
#endif
|
||||||
|
if (bh_bitmap_get_bit(module->e->common.data_dropped,
|
||||||
|
segment)) {
|
||||||
|
seg_len = 0;
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
seg_len = (uint64)module->module->data_segments[segment]
|
seg_len =
|
||||||
|
(uint64)module->module->data_segments[segment]
|
||||||
->data_length;
|
->data_length;
|
||||||
data = module->module->data_segments[segment]->data;
|
data = module->module->data_segments[segment]->data;
|
||||||
|
}
|
||||||
if (offset + bytes > seg_len)
|
if (offset + bytes > seg_len)
|
||||||
goto out_of_bounds;
|
goto out_of_bounds;
|
||||||
|
|
||||||
|
@ -3021,8 +3029,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
uint32 segment;
|
uint32 segment;
|
||||||
|
|
||||||
segment = read_uint32(frame_ip);
|
segment = read_uint32(frame_ip);
|
||||||
|
bh_bitmap_set_bit(module->e->common.data_dropped,
|
||||||
module->module->data_segments[segment]->data_length = 0;
|
segment);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_OP_MEMORY_COPY:
|
case WASM_OP_MEMORY_COPY:
|
||||||
|
@ -3114,8 +3122,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (module->module->table_segments[elem_idx]
|
if (bh_bitmap_get_bit(module->e->common.elem_dropped,
|
||||||
.is_dropped) {
|
elem_idx)) {
|
||||||
wasm_set_exception(module,
|
wasm_set_exception(module,
|
||||||
"out of bounds table access");
|
"out of bounds table access");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
|
@ -3144,9 +3152,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
{
|
{
|
||||||
uint32 elem_idx = read_uint32(frame_ip);
|
uint32 elem_idx = read_uint32(frame_ip);
|
||||||
bh_assert(elem_idx < module->module->table_seg_count);
|
bh_assert(elem_idx < module->module->table_seg_count);
|
||||||
|
bh_bitmap_set_bit(module->e->common.elem_dropped,
|
||||||
module->module->table_segments[elem_idx].is_dropped =
|
elem_idx);
|
||||||
true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_OP_TABLE_COPY:
|
case WASM_OP_TABLE_COPY:
|
||||||
|
|
|
@ -1666,6 +1666,31 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
if (module->data_seg_count > 0) {
|
||||||
|
module_inst->e->common.data_dropped =
|
||||||
|
bh_bitmap_new(0, module->data_seg_count);
|
||||||
|
if (module_inst->e->common.data_dropped == NULL) {
|
||||||
|
LOG_DEBUG("failed to allocate bitmaps");
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"failed to allocate bitmaps");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
if (module->table_seg_count > 0) {
|
||||||
|
module_inst->e->common.elem_dropped =
|
||||||
|
bh_bitmap_new(0, module->table_seg_count);
|
||||||
|
if (module_inst->e->common.elem_dropped == NULL) {
|
||||||
|
LOG_DEBUG("failed to allocate bitmaps");
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"failed to allocate bitmaps");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
if (!(module_inst->frames = runtime_malloc((uint64)sizeof(Vector),
|
if (!(module_inst->frames = runtime_malloc((uint64)sizeof(Vector),
|
||||||
error_buf, error_buf_size))) {
|
error_buf, error_buf_size))) {
|
||||||
|
@ -2189,6 +2214,13 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||||
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
|
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
bh_bitmap_delete(module_inst->e->common.data_dropped);
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
bh_bitmap_delete(module_inst->e->common.elem_dropped);
|
||||||
|
#endif
|
||||||
|
|
||||||
wasm_runtime_free(module_inst);
|
wasm_runtime_free(module_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3148,16 +3180,23 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index,
|
||||||
{
|
{
|
||||||
WASMMemoryInstance *memory_inst;
|
WASMMemoryInstance *memory_inst;
|
||||||
WASMModule *module;
|
WASMModule *module;
|
||||||
uint8 *data = NULL;
|
uint8 *data;
|
||||||
uint8 *maddr;
|
uint8 *maddr;
|
||||||
uint64 seg_len = 0;
|
uint64 seg_len;
|
||||||
|
|
||||||
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
|
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
|
||||||
|
|
||||||
memory_inst = wasm_get_default_memory(module_inst);
|
memory_inst = wasm_get_default_memory(module_inst);
|
||||||
|
|
||||||
|
if (bh_bitmap_get_bit(module_inst->e->common.data_dropped, seg_index)) {
|
||||||
|
seg_len = 0;
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
module = module_inst->module;
|
module = module_inst->module;
|
||||||
seg_len = module->data_segments[seg_index]->data_length;
|
seg_len = module->data_segments[seg_index]->data_length;
|
||||||
data = module->data_segments[seg_index]->data;
|
data = module->data_segments[seg_index]->data;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
|
if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
|
||||||
dst, len))
|
dst, len))
|
||||||
|
@ -3182,7 +3221,7 @@ llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index)
|
||||||
{
|
{
|
||||||
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
|
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
|
||||||
|
|
||||||
module_inst->module->data_segments[seg_index]->data_length = 0;
|
bh_bitmap_set_bit(module_inst->e->common.data_dropped, seg_index);
|
||||||
/* Currently we can't free the dropped data segment
|
/* Currently we can't free the dropped data segment
|
||||||
as they are stored in wasm bytecode */
|
as they are stored in wasm bytecode */
|
||||||
return true;
|
return true;
|
||||||
|
@ -3193,12 +3232,8 @@ llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index)
|
||||||
void
|
void
|
||||||
llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx)
|
llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx)
|
||||||
{
|
{
|
||||||
WASMTableSeg *tbl_segs;
|
|
||||||
|
|
||||||
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
|
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
|
||||||
|
bh_bitmap_set_bit(module_inst->e->common.elem_dropped, tbl_seg_idx);
|
||||||
tbl_segs = module_inst->module->table_segments;
|
|
||||||
tbl_segs[tbl_seg_idx].is_dropped = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3227,7 +3262,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tbl_seg->is_dropped) {
|
if (bh_bitmap_get_bit(module_inst->e->common.elem_dropped, tbl_seg_idx)) {
|
||||||
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "wasm.h"
|
#include "wasm.h"
|
||||||
#include "bh_atomic.h"
|
#include "bh_atomic.h"
|
||||||
|
#include "bh_bitmap.h"
|
||||||
#include "bh_hashmap.h"
|
#include "bh_hashmap.h"
|
||||||
#include "../common/wasm_runtime_common.h"
|
#include "../common/wasm_runtime_common.h"
|
||||||
#include "../common/wasm_exec_env.h"
|
#include "../common/wasm_exec_env.h"
|
||||||
|
@ -223,6 +224,12 @@ typedef struct WASMModuleInstanceExtraCommon {
|
||||||
/* Disable bounds checks or not */
|
/* Disable bounds checks or not */
|
||||||
bool disable_bounds_checks;
|
bool disable_bounds_checks;
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
bh_bitmap *data_dropped;
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
bh_bitmap *elem_dropped;
|
||||||
|
#endif
|
||||||
} WASMModuleInstanceExtraCommon;
|
} WASMModuleInstanceExtraCommon;
|
||||||
|
|
||||||
/* Extra info of WASM module instance for interpreter/jit mode */
|
/* Extra info of WASM module instance for interpreter/jit mode */
|
||||||
|
|
27
core/shared/utils/bh_bitmap.c
Normal file
27
core/shared/utils/bh_bitmap.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bh_bitmap.h"
|
||||||
|
|
||||||
|
bh_bitmap *
|
||||||
|
bh_bitmap_new(uintptr_t begin_index, unsigned bitnum)
|
||||||
|
{
|
||||||
|
bh_bitmap *bitmap;
|
||||||
|
uint32 bitmap_size = (bitnum + 7) / 8;
|
||||||
|
uint32 total_size = offsetof(bh_bitmap, map) + bitmap_size;
|
||||||
|
|
||||||
|
if (bitnum > UINT32_MAX - 7 || total_size < offsetof(bh_bitmap, map)
|
||||||
|
|| (total_size - offsetof(bh_bitmap, map)) != bitmap_size) {
|
||||||
|
return NULL; /* integer overflow */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((bitmap = BH_MALLOC(total_size)) != NULL) {
|
||||||
|
memset(bitmap, 0, total_size);
|
||||||
|
bitmap->begin_index = begin_index;
|
||||||
|
bitmap->end_index = begin_index + bitnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
114
core/shared/utils/bh_bitmap.h
Normal file
114
core/shared/utils/bh_bitmap.h
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BH_BITMAP_H
|
||||||
|
#define _BH_BITMAP_H
|
||||||
|
|
||||||
|
#include "bh_platform.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple fixed size bitmap.
|
||||||
|
*/
|
||||||
|
typedef struct bh_bitmap {
|
||||||
|
/* The first valid bit index. */
|
||||||
|
uintptr_t begin_index;
|
||||||
|
|
||||||
|
/* The last valid bit index plus one. */
|
||||||
|
uintptr_t end_index;
|
||||||
|
|
||||||
|
/* The bitmap. */
|
||||||
|
uint8 map[1];
|
||||||
|
} bh_bitmap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new bitmap.
|
||||||
|
*
|
||||||
|
* @param begin_index the first valid bit index
|
||||||
|
* @param bitnum maximal bit number of the bitmap.
|
||||||
|
*
|
||||||
|
* @return the new bitmap if succeeds, NULL otherwise.
|
||||||
|
*/
|
||||||
|
bh_bitmap *
|
||||||
|
bh_bitmap_new(uintptr_t begin_index, unsigned bitnum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a bitmap.
|
||||||
|
*
|
||||||
|
* @param bitmap the bitmap to be deleted
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
bh_bitmap_delete(bh_bitmap *bitmap)
|
||||||
|
{
|
||||||
|
if (bitmap != NULL)
|
||||||
|
BH_FREE(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the given index is in the range of the bitmap.
|
||||||
|
*
|
||||||
|
* @param bitmap the bitmap
|
||||||
|
* @param n the bit index
|
||||||
|
*
|
||||||
|
* @return true if the index is in range, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
bh_bitmap_is_in_range(bh_bitmap *bitmap, unsigned n)
|
||||||
|
{
|
||||||
|
return n >= bitmap->begin_index && n < bitmap->end_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a bit in the bitmap
|
||||||
|
*
|
||||||
|
* @param bitmap the bitmap
|
||||||
|
* @param n the n-th bit to be get
|
||||||
|
*
|
||||||
|
* @return value of the bit
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
bh_bitmap_get_bit(bh_bitmap *bitmap, unsigned n)
|
||||||
|
{
|
||||||
|
unsigned idx = n - bitmap->begin_index;
|
||||||
|
bh_assert(n >= bitmap->begin_index && n < bitmap->end_index);
|
||||||
|
return (bitmap->map[idx / 8] >> (idx % 8)) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a bit in the bitmap.
|
||||||
|
*
|
||||||
|
* @param bitmap the bitmap
|
||||||
|
* @param n the n-th bit to be set
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
bh_bitmap_set_bit(bh_bitmap *bitmap, unsigned n)
|
||||||
|
{
|
||||||
|
unsigned idx = n - bitmap->begin_index;
|
||||||
|
bh_assert(n >= bitmap->begin_index && n < bitmap->end_index);
|
||||||
|
bitmap->map[idx / 8] |= 1 << (idx % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a bit in the bitmap.
|
||||||
|
*
|
||||||
|
* @param bitmap the bitmap
|
||||||
|
* @param n the n-th bit to be cleared
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
bh_bitmap_clear_bit(bh_bitmap *bitmap, unsigned n)
|
||||||
|
{
|
||||||
|
unsigned idx = n - bitmap->begin_index;
|
||||||
|
bh_assert(n >= bitmap->begin_index && n < bitmap->end_index);
|
||||||
|
bitmap->map[idx / 8] &= ~(1 << (idx % 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -98,6 +98,7 @@ $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/alios_platform.c \
|
||||||
${SHARED_ROOT}/mem-alloc/ems/ems_alloc.c \
|
${SHARED_ROOT}/mem-alloc/ems/ems_alloc.c \
|
||||||
${SHARED_ROOT}/mem-alloc/ems/ems_hmu.c \
|
${SHARED_ROOT}/mem-alloc/ems/ems_hmu.c \
|
||||||
${SHARED_ROOT}/utils/bh_assert.c \
|
${SHARED_ROOT}/utils/bh_assert.c \
|
||||||
|
${SHARED_ROOT}/utils/bh_bitmap.c \
|
||||||
${SHARED_ROOT}/utils/bh_common.c \
|
${SHARED_ROOT}/utils/bh_common.c \
|
||||||
${SHARED_ROOT}/utils/bh_hashmap.c \
|
${SHARED_ROOT}/utils/bh_hashmap.c \
|
||||||
${SHARED_ROOT}/utils/bh_list.c \
|
${SHARED_ROOT}/utils/bh_list.c \
|
||||||
|
|
|
@ -371,6 +371,7 @@ CSRCS += nuttx_platform.c \
|
||||||
ems_alloc.c \
|
ems_alloc.c \
|
||||||
ems_hmu.c \
|
ems_hmu.c \
|
||||||
bh_assert.c \
|
bh_assert.c \
|
||||||
|
bh_bitmap.c \
|
||||||
bh_common.c \
|
bh_common.c \
|
||||||
bh_hashmap.c \
|
bh_hashmap.c \
|
||||||
bh_list.c \
|
bh_list.c \
|
||||||
|
|
1
samples/shared-module/.gitignore
vendored
Normal file
1
samples/shared-module/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/out/
|
95
samples/shared-module/CMakeLists.txt
Normal file
95
samples/shared-module/CMakeLists.txt
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 3.14)
|
||||||
|
|
||||||
|
include(CheckPIESupported)
|
||||||
|
|
||||||
|
project (shared-module)
|
||||||
|
|
||||||
|
set (CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
################ runtime settings ################
|
||||||
|
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||||
|
if (APPLE)
|
||||||
|
add_definitions(-DBH_PLATFORM_DARWIN)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Reset default linker flags
|
||||||
|
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||||
|
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||||
|
|
||||||
|
# WAMR features switch
|
||||||
|
|
||||||
|
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||||
|
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||||
|
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||||
|
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||||
|
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
|
||||||
|
set (WAMR_BUILD_TARGET "AARCH64")
|
||||||
|
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||||
|
set (WAMR_BUILD_TARGET "RISCV64")
|
||||||
|
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
# Build as X86_64 by default in 64-bit platform
|
||||||
|
set (WAMR_BUILD_TARGET "X86_64")
|
||||||
|
elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
|
# Build as X86_32 by default in 32-bit platform
|
||||||
|
set (WAMR_BUILD_TARGET "X86_32")
|
||||||
|
else ()
|
||||||
|
message(SEND_ERROR "Unsupported build target platform!")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
|
set (CMAKE_BUILD_TYPE Debug)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set (WAMR_BUILD_INTERP 1)
|
||||||
|
set (WAMR_BUILD_AOT 1)
|
||||||
|
set (WAMR_BUILD_JIT 0)
|
||||||
|
|
||||||
|
# fast interpreter
|
||||||
|
# set (WAMR_BUILD_FAST_INTERP 1)
|
||||||
|
|
||||||
|
# fast-jit
|
||||||
|
# set (WAMR_BUILD_FAST_JIT 1)
|
||||||
|
|
||||||
|
# llvm jit
|
||||||
|
# set (WAMR_BUILD_JIT 1)
|
||||||
|
# set (LLVM_DIR /usr/local/opt/llvm@14/lib/cmake/llvm)
|
||||||
|
|
||||||
|
set (WAMR_BUILD_REF_TYPES 1)
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
# linker flags
|
||||||
|
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||||
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||||
|
endif ()
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
|
||||||
|
if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||||
|
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# build out vmlib
|
||||||
|
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||||
|
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||||
|
|
||||||
|
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||||
|
|
||||||
|
################ application related ################
|
||||||
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||||
|
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||||
|
|
||||||
|
add_executable (shared-module src/main.c ${UNCOMMON_SHARED_SOURCE})
|
||||||
|
|
||||||
|
check_pie_supported()
|
||||||
|
set_target_properties (shared-module PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
target_link_libraries (shared-module vmlib -lm -ldl -lpthread ${LLVM_AVAILABLE_LIBS})
|
||||||
|
else ()
|
||||||
|
target_link_libraries (shared-module vmlib -lm -ldl -lpthread -lrt ${LLVM_AVAILABLE_LIBS})
|
||||||
|
endif ()
|
5
samples/shared-module/README.md
Normal file
5
samples/shared-module/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
The "shared-module" sample project
|
||||||
|
==================================
|
||||||
|
|
||||||
|
This sample demonstrates a bug described in:
|
||||||
|
https://github.com/bytecodealliance/wasm-micro-runtime/issues/2735.
|
63
samples/shared-module/build.sh
Executable file
63
samples/shared-module/build.sh
Executable file
|
@ -0,0 +1,63 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
#
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURR_DIR=$PWD
|
||||||
|
WAMR_DIR=${PWD}/../..
|
||||||
|
OUT_DIR=${PWD}/out
|
||||||
|
|
||||||
|
WASM_APPS=${PWD}/wasm-apps
|
||||||
|
|
||||||
|
|
||||||
|
rm -rf ${OUT_DIR}
|
||||||
|
mkdir ${OUT_DIR}
|
||||||
|
mkdir ${OUT_DIR}/wasm-apps
|
||||||
|
|
||||||
|
|
||||||
|
echo "##################### build shared-module project"
|
||||||
|
cd ${CURR_DIR}
|
||||||
|
mkdir -p cmake_build
|
||||||
|
cd cmake_build
|
||||||
|
cmake ..
|
||||||
|
make -j ${nproc}
|
||||||
|
if [ $? != 0 ];then
|
||||||
|
echo "BUILD_FAIL shared-module exit as $?\n"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp -a shared-module ${OUT_DIR}
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
|
echo "##################### build wasm apps"
|
||||||
|
|
||||||
|
cd ${WASM_APPS}
|
||||||
|
|
||||||
|
for i in `ls *.wat`
|
||||||
|
do
|
||||||
|
APP_SRC="$i"
|
||||||
|
OUT_FILE=${i%.*}.wasm
|
||||||
|
|
||||||
|
# Note: the CI installs wabt in /opt/wabt
|
||||||
|
if type wat2wasm; then
|
||||||
|
WAT2WASM=${WAT2WASM:-wat2wasm}
|
||||||
|
elif [ -x /opt/wabt/bin/wat2wasm ]; then
|
||||||
|
WAT2WASM=${WAT2WASM:-/opt/wabt/bin/wat2wasm}
|
||||||
|
fi
|
||||||
|
|
||||||
|
${WAT2WASM} -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC}
|
||||||
|
|
||||||
|
# aot
|
||||||
|
# wamrc -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot ${OUT_DIR}/wasm-apps/${OUT_FILE}
|
||||||
|
# mv ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot ${OUT_DIR}/wasm-apps/${OUT_FILE}
|
||||||
|
|
||||||
|
if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then
|
||||||
|
echo "build ${OUT_FILE} success"
|
||||||
|
else
|
||||||
|
echo "build ${OUT_FILE} fail"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "##################### build wasm apps done"
|
3
samples/shared-module/run.sh
Executable file
3
samples/shared-module/run.sh
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
out/shared-module -f out/wasm-apps/testapp.wasm
|
206
samples/shared-module/src/main.c
Normal file
206
samples/shared-module/src/main.c
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wasm_export.h"
|
||||||
|
#include "bh_read_file.h"
|
||||||
|
#include "bh_getopt.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
print_usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Options:\r\n");
|
||||||
|
fprintf(stdout, " -f [path of wasm file] \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv_main[])
|
||||||
|
{
|
||||||
|
int exit_code = 1;
|
||||||
|
static char global_heap_buf[512 * 1024];
|
||||||
|
char *buffer;
|
||||||
|
char error_buf[128];
|
||||||
|
int opt;
|
||||||
|
char *wasm_path = NULL;
|
||||||
|
|
||||||
|
const unsigned int N = 4;
|
||||||
|
wasm_module_t module = NULL;
|
||||||
|
wasm_module_inst_t module_inst[N];
|
||||||
|
wasm_exec_env_t exec_env[N];
|
||||||
|
const char *name_test_data_drop = "test_data_drop";
|
||||||
|
const char *name_test_elem_drop = "test_elem_drop";
|
||||||
|
wasm_function_inst_t func_test_data_drop[N];
|
||||||
|
wasm_function_inst_t func_test_elem_drop[N];
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int iter;
|
||||||
|
uint32 buf_size, stack_size = 8092, heap_size = 8092;
|
||||||
|
|
||||||
|
for (i = 0; i < N; i++) {
|
||||||
|
module_inst[i] = NULL;
|
||||||
|
exec_env[i] = NULL;
|
||||||
|
func_test_data_drop[i] = NULL;
|
||||||
|
func_test_elem_drop[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeInitArgs init_args;
|
||||||
|
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv_main, "hf:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
wasm_path = optarg;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
print_usage();
|
||||||
|
return 0;
|
||||||
|
case '?':
|
||||||
|
print_usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optind == 1) {
|
||||||
|
print_usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&init_args, 0, sizeof(init_args));
|
||||||
|
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||||
|
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
|
||||||
|
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
|
||||||
|
|
||||||
|
if (!wasm_runtime_full_init(&init_args)) {
|
||||||
|
printf("Init runtime environment failed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = bh_read_file_to_buffer(wasm_path, &buf_size);
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
printf("Open wasm app file [%s] failed.\n", wasm_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf,
|
||||||
|
sizeof(error_buf));
|
||||||
|
if (!module) {
|
||||||
|
printf("Load wasm module failed. error: %s\n", error_buf);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < N; i++) {
|
||||||
|
module_inst[i] = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||||
|
error_buf, sizeof(error_buf));
|
||||||
|
|
||||||
|
if (!module_inst[i]) {
|
||||||
|
printf("Instantiate wasm module failed. error: %s\n", error_buf);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_env[i] = wasm_runtime_create_exec_env(module_inst[i], stack_size);
|
||||||
|
if (!exec_env[i]) {
|
||||||
|
printf("Create wasm execution environment failed.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_test_data_drop[i] = wasm_runtime_lookup_function(
|
||||||
|
module_inst[i], name_test_data_drop, NULL);
|
||||||
|
if (!func_test_data_drop[i]) {
|
||||||
|
printf("The wasm function %s is not found.\n", name_test_data_drop);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_test_elem_drop[i] = wasm_runtime_lookup_function(
|
||||||
|
module_inst[i], name_test_elem_drop, NULL);
|
||||||
|
if (!func_test_elem_drop[i]) {
|
||||||
|
printf("The wasm function %s is not found.\n", name_test_elem_drop);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (iter = 0; iter < 2; iter++) {
|
||||||
|
/*
|
||||||
|
* as we drop data/table in the first iteration,
|
||||||
|
* the later iterations should trap.
|
||||||
|
*/
|
||||||
|
const bool should_trap = iter > 0;
|
||||||
|
|
||||||
|
for (i = 0; i < N; i++) {
|
||||||
|
uint32_t argv[1] = {};
|
||||||
|
if (wasm_runtime_call_wasm(exec_env[i], func_test_data_drop[i], 0,
|
||||||
|
argv)) {
|
||||||
|
uint32_t result = argv[0];
|
||||||
|
printf(
|
||||||
|
"Native finished calling wasm function: %s, return: %x\n",
|
||||||
|
name_test_data_drop, result);
|
||||||
|
if (result != 0x64636261) { /* "abcd" */
|
||||||
|
printf("unexpected return value\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (should_trap) {
|
||||||
|
printf("a trap is expected\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (should_trap) {
|
||||||
|
printf("call wasm function %s failed as expected. error: %s\n",
|
||||||
|
name_test_data_drop,
|
||||||
|
wasm_runtime_get_exception(module_inst[i]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("call wasm function %s failed. error: %s\n",
|
||||||
|
name_test_data_drop,
|
||||||
|
wasm_runtime_get_exception(module_inst[i]));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < N; i++) {
|
||||||
|
wasm_runtime_clear_exception(module_inst[i]);
|
||||||
|
|
||||||
|
uint32_t argv[1] = {};
|
||||||
|
if (wasm_runtime_call_wasm(exec_env[i], func_test_elem_drop[i], 0,
|
||||||
|
argv)) {
|
||||||
|
uint32_t result = argv[0];
|
||||||
|
printf(
|
||||||
|
"Native finished calling wasm function: %s, return: %x\n",
|
||||||
|
name_test_elem_drop, result);
|
||||||
|
if (result != 0) {
|
||||||
|
printf("unexpected return value\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (should_trap) {
|
||||||
|
printf("a trap is expected\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (should_trap) {
|
||||||
|
printf("call wasm function %s failed as expected. error: %s\n",
|
||||||
|
name_test_elem_drop,
|
||||||
|
wasm_runtime_get_exception(module_inst[i]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("call wasm function %s failed. error: %s\n",
|
||||||
|
name_test_elem_drop,
|
||||||
|
wasm_runtime_get_exception(module_inst[i]));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_code = 0;
|
||||||
|
fail:
|
||||||
|
for (i = 0; i < N; i++) {
|
||||||
|
if (exec_env[i])
|
||||||
|
wasm_runtime_destroy_exec_env(exec_env[i]);
|
||||||
|
if (module_inst[i])
|
||||||
|
wasm_runtime_deinstantiate(module_inst[i]);
|
||||||
|
}
|
||||||
|
if (module)
|
||||||
|
wasm_runtime_unload(module);
|
||||||
|
if (buffer)
|
||||||
|
BH_FREE(buffer);
|
||||||
|
wasm_runtime_destroy();
|
||||||
|
return exit_code;
|
||||||
|
}
|
22
samples/shared-module/wasm-apps/testapp.wat
Normal file
22
samples/shared-module/wasm-apps/testapp.wat
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
;; Copyright (C) 2023 Midokura Japan KK. All rights reserved.
|
||||||
|
;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
|
||||||
|
(module
|
||||||
|
(func (export "test_data_drop") (result i32)
|
||||||
|
(memory.init 0 (i32.const 0) (i32.const 0) (i32.const 4))
|
||||||
|
data.drop 0
|
||||||
|
(i32.load (i32.const 0))
|
||||||
|
)
|
||||||
|
(func (export "test_elem_drop") (result i32)
|
||||||
|
(table.init 0 (i32.const 0) (i32.const 0) (i32.const 4))
|
||||||
|
elem.drop 0
|
||||||
|
i32.const 3
|
||||||
|
table.get 0
|
||||||
|
ref.is_null
|
||||||
|
)
|
||||||
|
(func $f)
|
||||||
|
(memory 1 1)
|
||||||
|
(table 4 4 funcref)
|
||||||
|
(data "abcd")
|
||||||
|
(elem func $f $f $f $f)
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user