Merge main into dev/fast_jit

This commit is contained in:
Wenyong Huang 2022-03-25 04:17:04 +08:00
commit dc0e28b790
58 changed files with 2730 additions and 481 deletions

View File

@ -11,6 +11,8 @@ WAMR project reused some components from other open source project:
- **wasmtime**: for the wasi libc implementation
- **zephyr**: for several platform specific examples
- **WebAssembly debugging patch for LLDB**: for extending the ability of LLDB to support wasm debugging
- **libuv**: for the WASI Libc with uvwasi implementation
- **uvwasi**: for the WASI Libc with uvwasi implementation
The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated oprand stack location.
@ -25,6 +27,8 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
| wasmtime | unspecified | v0.26.0 | https://github.com/bytecodealliance/wasmtime | |
| zephyr | unspecified | v2.5.0 | https://www.zephyrproject.org/ | https://www.cvedetails.com/vendor/19255/Zephyrproject.html |
| WebAssembly debugging patch for LLDB | unspecified | unspecified | https://reviews.llvm.org/D78801 | |
| libuv | v1.42.0 | v1.44.1 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html |
| uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | |
## Licenses
@ -69,3 +73,9 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
### wac
[LICENSE](./tests/wamr-test-suites/spec-test-script/LICENSE)
### libuv
[LICENSE](./core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV)
### uvwasi
[LICENSE](./core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI)

View File

@ -42,6 +42,7 @@ iwasm VM core
- [Source debugging support](./doc/source_debugging.md), ref to [document](./doc/source_debugging.md)
- [WAMR-IDE (Experimental)](./test-tools/wamr-ide) to develop WebAssembly applications with build, run and debug support, ref to [document](./test-tools/wamr-ide)
- [XIP (Execution In Place) support](./doc/xip.md), ref to [document](./doc/xip.md)
- [Berkeley/Posix Socket support](./doc/socket_api.md), ref to [document](./doc/socket_api.md) and [sample](./samples/socket-api)
### WASM post-MVP features
- [wasm-c-api](https://github.com/WebAssembly/wasm-c-api), ref to [document](doc/wasm_c_api.md) and [sample](samples/wasm-c-api)
@ -153,6 +154,7 @@ The WAMR [samples](./samples) integrate the iwasm VM core, application manager a
- **[multi-module](./samples/multi-module)**: Demonstrating the [multiple modules as dependencies](./doc/multi_module.md) feature which implements the [load-time dynamic linking](https://webassembly.org/docs/dynamic-linking/).
- **[ref-types](./samples/ref-types)**: Demonstrating how to call wasm functions with argument of externref type introduced by [reference types proposal](https://github.com/WebAssembly/reference-types).
- **[wasm-c-api](./samples/wasm-c-api/README.md)**: Demonstrating how to run some samples from [wasm-c-api proposal](https://github.com/WebAssembly/wasm-c-api) and showing the supported API's.
- **[socket-api](./samples/socket-api/README.md)**: Demonstrating how to run wasm tcp server and tcp client applications, and how they communicate with each other.
- **[workload](./samples/workload/README.md)**: Demonstrating how to build and run some complex workloads, e.g. tensorflow-lite, XNNPACK, wasm-av1, meshoptimizer and bwa.

View File

@ -96,10 +96,17 @@ def run_clang_format(file_path: pathlib, root: pathlib) -> bool:
def run_clang_format_diff(root: pathlib, commits: str) -> bool:
"""
Use `clang-format-12` and `git-clang-format-12` to check code
format of the PR, which specificed a commit range. It is required to
format code before `git commit` or when failed the PR check:
Use `clang-format-12` or `git-clang-format-12` to check code format of
the PR, with a commit range specified. It is required to format the
code before committing the PR, or it might fail to pass the CI check:
1. Install clang-format-12.0.0
Normally we can install it by `sudo apt-get install clang-format-12`,
or download the `clang+llvm-12.0.0-xxx-tar.xz` package from
https://github.com/llvm/llvm-project/releases/tag/llvmorg-12.0.0
and install it
2. Format the C/C++ source file
``` shell
cd path/to/wamr/root
clang-format-12 --style file -i path/to/file

View File

@ -19,6 +19,7 @@
#include "debug/jit_debug.h"
#endif
#define YMM_PLT_PREFIX "__ymm@"
#define XMM_PLT_PREFIX "__xmm@"
#define REAL_PLT_PREFIX "__real@"
@ -1805,7 +1806,8 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
is_literal ? module->literal_size : module->code_size;
uint32 i, func_index, symbol_len;
#if defined(BH_PLATFORM_WINDOWS)
uint32 xmm_plt_index = 0, real_plt_index = 0, float_plt_index = 0;
uint32 ymm_plt_index = 0, xmm_plt_index = 0;
uint32 real_plt_index = 0, float_plt_index = 0, j;
#endif
char symbol_buf[128] = { 0 }, *symbol, *p;
void *symbol_addr;
@ -1860,31 +1862,45 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
symbol_addr = module->literal;
}
#if defined(BH_PLATFORM_WINDOWS)
/* Relocation for symbols which start with "__xmm@" or "__real@" and
end with the xmm value or real value. In Windows PE file, the data
is stored in some individual ".rdata" sections. We simply create
extra plt data, parse the values from the symbols and stored them
into the extra plt data. */
/* Relocation for symbols which start with "__ymm@", "__xmm@" or
"__real@" and end with the ymm value, xmm value or real value.
In Windows PE file, the data is stored in some individual ".rdata"
sections. We simply create extra plt data, parse the values from
the symbols and stored them into the extra plt data. */
else if (!strcmp(group->section_name, ".text")
&& !strncmp(symbol, YMM_PLT_PREFIX, strlen(YMM_PLT_PREFIX))
&& strlen(symbol) == strlen(YMM_PLT_PREFIX) + 64) {
char ymm_buf[17] = { 0 };
symbol_addr = module->extra_plt_data + ymm_plt_index * 32;
for (j = 0; j < 4; j++) {
bh_memcpy_s(ymm_buf, sizeof(ymm_buf),
symbol + strlen(YMM_PLT_PREFIX) + 48 - 16 * j, 16);
if (!str2uint64(ymm_buf,
(uint64 *)((uint8 *)symbol_addr + 8 * j))) {
set_error_buf_v(error_buf, error_buf_size,
"resolve symbol %s failed", symbol);
goto check_symbol_fail;
}
}
ymm_plt_index++;
}
else if (!strcmp(group->section_name, ".text")
&& !strncmp(symbol, XMM_PLT_PREFIX, strlen(XMM_PLT_PREFIX))
&& strlen(symbol) == strlen(XMM_PLT_PREFIX) + 32) {
char xmm_buf[17] = { 0 };
symbol_addr = module->extra_plt_data + xmm_plt_index * 16;
bh_memcpy_s(xmm_buf, sizeof(xmm_buf),
symbol + strlen(XMM_PLT_PREFIX) + 16, 16);
if (!str2uint64(xmm_buf, (uint64 *)symbol_addr)) {
set_error_buf_v(error_buf, error_buf_size,
"resolve symbol %s failed", symbol);
goto check_symbol_fail;
}
bh_memcpy_s(xmm_buf, sizeof(xmm_buf),
symbol + strlen(XMM_PLT_PREFIX), 16);
if (!str2uint64(xmm_buf, (uint64 *)((uint8 *)symbol_addr + 8))) {
set_error_buf_v(error_buf, error_buf_size,
"resolve symbol %s failed", symbol);
goto check_symbol_fail;
symbol_addr = module->extra_plt_data + module->ymm_plt_count * 32
+ xmm_plt_index * 16;
for (j = 0; j < 2; j++) {
bh_memcpy_s(xmm_buf, sizeof(xmm_buf),
symbol + strlen(XMM_PLT_PREFIX) + 16 - 16 * j, 16);
if (!str2uint64(xmm_buf,
(uint64 *)((uint8 *)symbol_addr + 8 * j))) {
set_error_buf_v(error_buf, error_buf_size,
"resolve symbol %s failed", symbol);
goto check_symbol_fail;
}
}
xmm_plt_index++;
}
@ -1893,8 +1909,8 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
&& strlen(symbol) == strlen(REAL_PLT_PREFIX) + 16) {
char real_buf[17] = { 0 };
symbol_addr = module->extra_plt_data + module->xmm_plt_count * 16
+ real_plt_index * 8;
symbol_addr = module->extra_plt_data + module->ymm_plt_count * 32
+ module->xmm_plt_count * 16 + real_plt_index * 8;
bh_memcpy_s(real_buf, sizeof(real_buf),
symbol + strlen(REAL_PLT_PREFIX), 16);
if (!str2uint64(real_buf, (uint64 *)symbol_addr)) {
@ -1909,7 +1925,8 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
&& strlen(symbol) == strlen(REAL_PLT_PREFIX) + 8) {
char float_buf[9] = { 0 };
symbol_addr = module->extra_plt_data + module->xmm_plt_count * 16
symbol_addr = module->extra_plt_data + module->ymm_plt_count * 32
+ module->xmm_plt_count * 16
+ module->real_plt_count * 8 + float_plt_index * 4;
bh_memcpy_s(float_buf, sizeof(float_buf),
symbol + strlen(REAL_PLT_PREFIX), 8);
@ -2121,11 +2138,19 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
|| (module->is_indirect_mode
&& group_name_len == strlen(".text") + 1))
&& !strncmp(group_name, ".text", strlen(".text"))) {
if ((symbol_name_len == strlen(XMM_PLT_PREFIX) + 32
if ((symbol_name_len == strlen(YMM_PLT_PREFIX) + 64
|| (module->is_indirect_mode
&& symbol_name_len == strlen(XMM_PLT_PREFIX) + 32 + 1))
&& !strncmp(symbol_name, XMM_PLT_PREFIX,
strlen(XMM_PLT_PREFIX))) {
&& symbol_name_len == strlen(YMM_PLT_PREFIX) + 64 + 1))
&& !strncmp(symbol_name, YMM_PLT_PREFIX,
strlen(YMM_PLT_PREFIX))) {
module->ymm_plt_count++;
}
else if ((symbol_name_len == strlen(XMM_PLT_PREFIX) + 32
|| (module->is_indirect_mode
&& symbol_name_len
== strlen(XMM_PLT_PREFIX) + 32 + 1))
&& !strncmp(symbol_name, XMM_PLT_PREFIX,
strlen(XMM_PLT_PREFIX))) {
module->xmm_plt_count++;
}
else if ((symbol_name_len == strlen(REAL_PLT_PREFIX) + 16
@ -2149,7 +2174,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
}
/* Allocate memory for extra plt data */
size = sizeof(uint64) * 2 * module->xmm_plt_count
size = sizeof(uint64) * 4 * module->ymm_plt_count
+ sizeof(uint64) * 2 * module->xmm_plt_count
+ sizeof(uint64) * module->real_plt_count
+ sizeof(uint32) * module->float_plt_count;
if (size > 0) {

View File

@ -1020,6 +1020,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
module->wasi_args.dir_list, module->wasi_args.dir_count,
module->wasi_args.map_dir_list, module->wasi_args.map_dir_count,
module->wasi_args.env, module->wasi_args.env_count,
module->wasi_args.addr_pool, module->wasi_args.addr_count,
module->wasi_args.argv, module->wasi_args.argc,
module->wasi_args.stdio[0], module->wasi_args.stdio[1],
module->wasi_args.stdio[2], error_buf, error_buf_size))
@ -2818,8 +2819,8 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx,
dst_tbl_inst = aot_get_table_inst(module_inst, dst_tbl_idx);
bh_assert(dst_tbl_inst);
if ((uint64)src_offset + length > dst_tbl_inst->cur_size
|| (uint64)dst_offset + length > src_tbl_inst->cur_size) {
if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
|| (uint64)src_offset + length > src_tbl_inst->cur_size) {
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
@ -3024,7 +3025,8 @@ aot_dump_call_stack(WASMExecEnv *exec_env)
/* release previous stack frames and create new ones */
if (!bh_vector_destroy(module_inst->frames.ptr)
|| !bh_vector_init(module_inst->frames.ptr, n, sizeof(WASMCApiFrame))) {
|| !bh_vector_init(module_inst->frames.ptr, n, sizeof(WASMCApiFrame),
false)) {
return;
}

View File

@ -197,10 +197,11 @@ typedef struct AOTModule {
uint32 literal_size;
#if defined(BH_PLATFORM_WINDOWS)
/* extra plt data area for __xmm and __real constants
/* extra plt data area for __ymm, __xmm and __real constants
in Windows platform, NULL for JIT mode */
uint8 *extra_plt_data;
uint32 extra_plt_data_size;
uint32 ymm_plt_count;
uint32 xmm_plt_count;
uint32 real_plt_count;
uint32 float_plt_count;

View File

@ -109,113 +109,115 @@ failed: \
}
/* vectors with no ownership management of elements */
#define WASM_DEFINE_VEC_PLAIN(name) \
WASM_DEFINE_VEC(name) \
void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \
own wasm_##name##_t const data[]) \
{ \
if (!out) { \
return; \
} \
\
memset(out, 0, sizeof(wasm_##name##_vec_t)); \
\
if (!size) { \
return; \
} \
\
if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t))) { \
LOG_DEBUG("bh_vector_init failed"); \
goto failed; \
} \
\
if (data) { \
uint32 size_in_bytes = 0; \
size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t)); \
bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \
out->num_elems = size; \
} \
\
RETURN_VOID(out, wasm_##name##_vec_delete) \
} \
void wasm_##name##_vec_copy(wasm_##name##_vec_t *out, \
const wasm_##name##_vec_t *src) \
{ \
wasm_##name##_vec_new(out, src->size, src->data); \
} \
void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \
{ \
if (v) { \
bh_vector_destroy((Vector *)v); \
} \
#define WASM_DEFINE_VEC_PLAIN(name) \
WASM_DEFINE_VEC(name) \
void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \
own wasm_##name##_t const data[]) \
{ \
if (!out) { \
return; \
} \
\
memset(out, 0, sizeof(wasm_##name##_vec_t)); \
\
if (!size) { \
return; \
} \
\
if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t), \
true)) { \
LOG_DEBUG("bh_vector_init failed"); \
goto failed; \
} \
\
if (data) { \
uint32 size_in_bytes = 0; \
size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t)); \
bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \
out->num_elems = size; \
} \
\
RETURN_VOID(out, wasm_##name##_vec_delete) \
} \
void wasm_##name##_vec_copy(wasm_##name##_vec_t *out, \
const wasm_##name##_vec_t *src) \
{ \
wasm_##name##_vec_new(out, src->size, src->data); \
} \
void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \
{ \
if (v) { \
bh_vector_destroy((Vector *)v); \
} \
}
/* vectors that own their elements */
#define WASM_DEFINE_VEC_OWN(name, elem_destroy_func) \
WASM_DEFINE_VEC(name) \
void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \
own wasm_##name##_t *const data[]) \
{ \
if (!out) { \
return; \
} \
\
memset(out, 0, sizeof(wasm_##name##_vec_t)); \
\
if (!size) { \
return; \
} \
\
if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t *))) { \
LOG_DEBUG("bh_vector_init failed"); \
goto failed; \
} \
\
if (data) { \
uint32 size_in_bytes = 0; \
size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t *)); \
bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \
out->num_elems = size; \
} \
\
RETURN_VOID(out, wasm_##name##_vec_delete) \
} \
void wasm_##name##_vec_copy(own wasm_##name##_vec_t *out, \
const wasm_##name##_vec_t *src) \
{ \
size_t i = 0; \
memset(out, 0, sizeof(Vector)); \
\
if (!src || !src->size) { \
return; \
} \
\
if (!bh_vector_init((Vector *)out, src->size, \
sizeof(wasm_##name##_t *))) { \
LOG_DEBUG("bh_vector_init failed"); \
goto failed; \
} \
\
for (i = 0; i != src->num_elems; ++i) { \
if (!(out->data[i] = wasm_##name##_copy(src->data[i]))) { \
LOG_DEBUG("wasm_%s_copy failed", #name); \
goto failed; \
} \
} \
out->num_elems = src->num_elems; \
\
RETURN_VOID(out, wasm_##name##_vec_delete) \
} \
void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \
{ \
size_t i = 0; \
if (!v) { \
return; \
} \
for (i = 0; i != v->num_elems; ++i) { \
elem_destroy_func(*(v->data + i)); \
} \
bh_vector_destroy((Vector *)v); \
#define WASM_DEFINE_VEC_OWN(name, elem_destroy_func) \
WASM_DEFINE_VEC(name) \
void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \
own wasm_##name##_t *const data[]) \
{ \
if (!out) { \
return; \
} \
\
memset(out, 0, sizeof(wasm_##name##_vec_t)); \
\
if (!size) { \
return; \
} \
\
if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t *), \
true)) { \
LOG_DEBUG("bh_vector_init failed"); \
goto failed; \
} \
\
if (data) { \
uint32 size_in_bytes = 0; \
size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t *)); \
bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \
out->num_elems = size; \
} \
\
RETURN_VOID(out, wasm_##name##_vec_delete) \
} \
void wasm_##name##_vec_copy(own wasm_##name##_vec_t *out, \
const wasm_##name##_vec_t *src) \
{ \
size_t i = 0; \
memset(out, 0, sizeof(Vector)); \
\
if (!src || !src->size) { \
return; \
} \
\
if (!bh_vector_init((Vector *)out, src->size, \
sizeof(wasm_##name##_t *), true)) { \
LOG_DEBUG("bh_vector_init failed"); \
goto failed; \
} \
\
for (i = 0; i != src->num_elems; ++i) { \
if (!(out->data[i] = wasm_##name##_copy(src->data[i]))) { \
LOG_DEBUG("wasm_%s_copy failed", #name); \
goto failed; \
} \
} \
out->num_elems = src->num_elems; \
\
RETURN_VOID(out, wasm_##name##_vec_delete) \
} \
void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \
{ \
size_t i = 0; \
if (!v) { \
return; \
} \
for (i = 0; i != v->num_elems; ++i) { \
elem_destroy_func(*(v->data + i)); \
} \
bh_vector_destroy((Vector *)v); \
}
WASM_DEFINE_VEC_PLAIN(byte)
@ -320,6 +322,8 @@ wasm_engine_new()
singleton_engine =
wasm_engine_new_internal(Alloc_With_System_Allocator, NULL);
}
if (singleton_engine)
singleton_engine->ref_count++;
return singleton_engine;
}
@ -336,6 +340,8 @@ wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts)
if (!singleton_engine) {
singleton_engine = wasm_engine_new_internal(type, opts);
}
if (singleton_engine)
singleton_engine->ref_count++;
return singleton_engine;
}
@ -343,7 +349,7 @@ wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts)
void
wasm_engine_delete(wasm_engine_t *engine)
{
if (engine) {
if (engine && (--engine->ref_count == 0)) {
wasm_engine_delete_internal(engine);
singleton_engine = NULL;
}
@ -375,7 +381,7 @@ wasm_store_new(wasm_engine_t *engine)
DEFAULT_VECTOR_INIT_LENGTH);
if (!(store->foreigns = malloc_internal(sizeof(Vector)))
|| !(bh_vector_init(store->foreigns, 24, sizeof(Vector *)))) {
|| !(bh_vector_init(store->foreigns, 24, sizeof(Vector *), true))) {
goto failed;
}

View File

@ -27,6 +27,7 @@ WASM_DECLARE_VEC(store, *)
struct wasm_engine_t {
/* support one store for now */
wasm_store_vec_t *stores;
uint32_t ref_count;
};
struct wasm_store_t {

View File

@ -772,7 +772,7 @@ register_module_with_null_name(WASMModuleCommon *module_common, char *error_buf,
}
WASMModuleCommon *
wasm_runtime_load(const uint8 *buf, uint32 size, char *error_buf,
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size)
{
WASMModuleCommon *module_common = NULL;
@ -1328,7 +1328,8 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
bh_assert((argv && ret_argv) || (argc == 0));
if (argv == ret_argv) {
if (argv == ret_argv || argc == 0) {
/* no need to transfrom externref results */
return true;
}
@ -2210,14 +2211,36 @@ wasm_runtime_set_wasi_args(WASMModuleCommon *module, const char *dir_list[],
argc, -1, -1, -1);
}
void
wasm_runtime_set_wasi_addr_pool(wasm_module_t module, const char *addr_pool[],
uint32 addr_pool_size)
{
WASIArguments *wasi_args = NULL;
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
if (module->module_type == Wasm_Module_Bytecode)
wasi_args = &((WASMModule *)module)->wasi_args;
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
wasi_args = &((AOTModule *)module)->wasi_args;
#endif
if (wasi_args) {
wasi_args->addr_pool = addr_pool;
wasi_args->addr_count = addr_pool_size;
}
}
#if WASM_ENABLE_UVWASI == 0
bool
wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
const char *dir_list[], uint32 dir_count,
const char *map_dir_list[], uint32 map_dir_count,
const char *env[], uint32 env_count, char *argv[],
uint32 argc, int stdinfd, int stdoutfd, int stderrfd,
char *error_buf, uint32 error_buf_size)
const char *env[], uint32 env_count,
const char *addr_pool[], uint32 addr_pool_size,
char *argv[], uint32 argc, int stdinfd, int stdoutfd,
int stderrfd, char *error_buf, uint32 error_buf_size)
{
WASIContext *wasi_ctx;
char *argv_buf = NULL;
@ -2229,8 +2252,10 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
struct fd_table *curfds = NULL;
struct fd_prestats *prestats = NULL;
struct argv_environ_values *argv_environ = NULL;
struct addr_pool *apool = NULL;
bool fd_table_inited = false, fd_prestats_inited = false;
bool argv_environ_inited = false;
bool addr_pool_inited = false;
__wasi_fd_t wasm_fd = 3;
int32 raw_fd;
char *path, resolved_path[PATH_MAX];
@ -2304,7 +2329,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
if (!(curfds = wasm_runtime_malloc(sizeof(struct fd_table)))
|| !(prestats = wasm_runtime_malloc(sizeof(struct fd_prestats)))
|| !(argv_environ =
wasm_runtime_malloc(sizeof(struct argv_environ_values)))) {
wasm_runtime_malloc(sizeof(struct argv_environ_values)))
|| !(apool = wasm_runtime_malloc(sizeof(struct addr_pool)))) {
set_error_buf(error_buf, error_buf_size,
"Init wasi environment failed: allocate memory failed");
goto fail;
@ -2335,6 +2361,14 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
}
argv_environ_inited = true;
if (!addr_pool_init(apool)) {
set_error_buf(error_buf, error_buf_size,
"Init wasi environment failed: "
"init the address pool failed");
goto fail;
}
addr_pool_inited = true;
/* Prepopulate curfds with stdin, stdout, and stderr file descriptors. */
if (!fd_table_insert_existing(curfds, 0, (stdinfd != -1) ? stdinfd : 0)
|| !fd_table_insert_existing(curfds, 1, (stdoutfd != -1) ? stdoutfd : 1)
@ -2369,9 +2403,34 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
fd_prestats_insert(prestats, dir_list[i], wasm_fd);
}
/* addr_pool(textual) -> apool */
for (i = 0; i < addr_pool_size; i++) {
char *cp, *address, *mask;
bool ret = false;
cp = bh_strdup(addr_pool[i]);
if (!cp) {
set_error_buf(error_buf, error_buf_size,
"Init wasi environment failed: copy address failed");
goto fail;
}
address = strtok(cp, "/");
mask = strtok(NULL, "/");
ret = addr_pool_insert(apool, address, (uint8)(mask ? atoi(mask) : 0));
wasm_runtime_free(cp);
if (!ret) {
set_error_buf(error_buf, error_buf_size,
"Init wasi environment failed: store address failed");
goto fail;
}
}
wasi_ctx->curfds = curfds;
wasi_ctx->prestats = prestats;
wasi_ctx->argv_environ = argv_environ;
wasi_ctx->addr_pool = apool;
wasi_ctx->argv_buf = argv_buf;
wasi_ctx->argv_list = argv_list;
wasi_ctx->env_buf = env_buf;
@ -2386,12 +2445,16 @@ fail:
fd_prestats_destroy(prestats);
if (fd_table_inited)
fd_table_destroy(curfds);
if (addr_pool_inited)
addr_pool_destroy(apool);
if (curfds)
wasm_runtime_free(curfds);
if (prestats)
wasm_runtime_free(prestats);
if (argv_environ)
wasm_runtime_free(argv_environ);
if (apool)
wasm_runtime_free(apool);
if (argv_buf)
wasm_runtime_free(argv_buf);
if (argv_list)
@ -2449,9 +2512,10 @@ bool
wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
const char *dir_list[], uint32 dir_count,
const char *map_dir_list[], uint32 map_dir_count,
const char *env[], uint32 env_count, char *argv[],
uint32 argc, int stdinfd, int stdoutfd, int stderrfd,
char *error_buf, uint32 error_buf_size)
const char *env[], uint32 env_count,
const char *addr_pool[], uint32 addr_pool_size,
char *argv[], uint32 argc, int stdinfd, int stdoutfd,
int stderrfd, char *error_buf, uint32 error_buf_size)
{
uvwasi_t *uvwasi = NULL;
uvwasi_options_t init_options;
@ -2614,6 +2678,10 @@ wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst)
fd_prestats_destroy(wasi_ctx->prestats);
wasm_runtime_free(wasi_ctx->prestats);
}
if (wasi_ctx->addr_pool) {
addr_pool_destroy(wasi_ctx->addr_pool);
wasm_runtime_free(wasi_ctx->addr_pool);
}
if (wasi_ctx->argv_buf)
wasm_runtime_free(wasi_ctx->argv_buf);
if (wasi_ctx->argv_list)

View File

@ -352,6 +352,7 @@ typedef struct WASIContext {
struct fd_table *curfds;
struct fd_prestats *prestats;
struct argv_environ_values *argv_environ;
struct addr_pool *addr_pool;
char *argv_buf;
char **argv_list;
char *env_buf;
@ -412,7 +413,7 @@ wasm_runtime_is_xip_file(const uint8 *buf, uint32 size);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN WASMModuleCommon *
wasm_runtime_load(const uint8 *buf, uint32 size, char *error_buf,
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size);
/* See wasm_export.h for description */
@ -712,9 +713,10 @@ bool
wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
const char *dir_list[], uint32 dir_count,
const char *map_dir_list[], uint32 map_dir_count,
const char *env[], uint32 env_count, char *argv[],
uint32 argc, int stdinfd, int stdoutfd, int stderrfd,
char *error_buf, uint32 error_buf_size);
const char *env[], uint32 env_count,
const char *addr_pool[], uint32 addr_pool_size,
char *argv[], uint32 argc, int stdinfd, int stdoutfd,
int stderrfd, char *error_buf, uint32 error_buf_size);
void
wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst);
@ -726,6 +728,9 @@ wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst,
WASIContext *
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_wasi_addr_pool(wasm_module_t module, const char *addr_pool[],
uint32 addr_pool_size);
#endif /* end of WASM_ENABLE_LIBC_WASI */
#if WASM_ENABLE_REF_TYPES != 0

View File

@ -374,7 +374,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
if (timeout < 0)
timeout = BHT_WAIT_FOREVER;
os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock, timeout);
os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock,
timeout / 1000);
os_mutex_unlock(&wait_node->wait_lock);

View File

@ -88,6 +88,7 @@ typedef double float64_t;
wasm_##name##_t ptr_or_none* data; \
size_t num_elems; \
size_t size_of_elem; \
void *lock; \
} wasm_##name##_vec_t; \
\
WASM_API_EXTERN void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t* out); \
@ -589,8 +590,8 @@ WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_exte
// Vectors
#define WASM_EMPTY_VEC {0, NULL, 0, 0}
#define WASM_ARRAY_VEC(array) {sizeof(array)/sizeof(*(array)), array, sizeof(array)/sizeof(*(array)), sizeof(*(array))}
#define WASM_EMPTY_VEC {0, NULL, 0, 0, NULL}
#define WASM_ARRAY_VEC(array) {sizeof(array)/sizeof(*(array)), array, sizeof(array)/sizeof(*(array)), sizeof(*(array)), NULL}
// Value Type construction short-hands

View File

@ -300,7 +300,10 @@ wasm_runtime_find_module_registered(const char *module_name);
* WASM binary data when interpreter or JIT is enabled, or AOT binary data
* when AOT is enabled. If it is AOT binary data, it must be 4-byte aligned.
*
* @param buf the byte buffer which contains the WASM binary data
* @param buf the byte buffer which contains the WASM/AOT binary data,
* note that the byte buffer must be writable since runtime may
* change its content for footprint and performance purpose, and
* it must be referencable until wasm_runtime_unload is called
* @param size the size of the buffer
* @param error_buf output of the exception info
* @param error_buf_size the size of the exception string
@ -308,7 +311,7 @@ wasm_runtime_find_module_registered(const char *module_name);
* @return return WASM module loaded, NULL if failed
*/
WASM_RUNTIME_API_EXTERN wasm_module_t
wasm_runtime_load(const uint8_t *buf, uint32_t size,
wasm_runtime_load(uint8_t *buf, uint32_t size,
char *error_buf, uint32_t error_buf_size);
/**
@ -348,6 +351,10 @@ wasm_runtime_set_wasi_args(wasm_module_t module,
const char *env[], uint32_t env_count,
char *argv[], int argc);
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_wasi_addr_pool(wasm_module_t module, const char *addr_pool[],
uint32_t addr_pool_size);
/**
* Instantiate a WASM module.
*

View File

@ -308,6 +308,9 @@ typedef struct WASIArguments {
uint32 map_dir_count;
const char **env;
uint32 env_count;
/* in CIDR noation */
const char **addr_pool;
uint32 addr_count;
char **argv;
uint32 argc;
int stdio[3];

View File

@ -73,8 +73,14 @@ typedef struct WASMInterpFrame {
static inline unsigned
wasm_interp_interp_frame_size(unsigned all_cell_num)
{
return align_uint((uint32)offsetof(WASMInterpFrame, lp) + all_cell_num * 5,
4);
unsigned frame_size;
#if WASM_ENABLE_FAST_INTERP == 0
frame_size = (uint32)offsetof(WASMInterpFrame, lp) + all_cell_num * 4;
#else
frame_size = (uint32)offsetof(WASMInterpFrame, operand) + all_cell_num * 4;
#endif
return align_uint(frame_size, 4);
}
void

View File

@ -229,15 +229,15 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
frame_sp += 2; \
} while (0)
#define PUSH_CSP(_label_type, cell_num, _target_addr) \
do { \
bh_assert(frame_csp < frame->csp_boundary); \
/* frame_csp->label_type = _label_type; */ \
frame_csp->cell_num = cell_num; \
frame_csp->begin_addr = frame_ip; \
frame_csp->target_addr = _target_addr; \
frame_csp->frame_sp = frame_sp; \
frame_csp++; \
#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
do { \
bh_assert(frame_csp < frame->csp_boundary); \
/* frame_csp->label_type = _label_type; */ \
frame_csp->cell_num = cell_num; \
frame_csp->begin_addr = frame_ip; \
frame_csp->target_addr = _target_addr; \
frame_csp->frame_sp = frame_sp - param_cell_num; \
frame_csp++; \
} while (0)
#define POP_I32() (--frame_sp, *(int32 *)frame_sp)
@ -994,7 +994,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint8 *else_addr, *end_addr, *maddr = NULL;
uint32 local_idx, local_offset, global_idx;
uint8 local_type, *global_addr;
uint32 cache_index, type_index, cell_num;
uint32 cache_index, type_index, param_cell_num, cell_num;
uint8 value_type;
#if WASM_ENABLE_LABELS_AS_VALUES != 0
@ -1022,6 +1022,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(EXT_OP_BLOCK)
{
read_leb_uint32(frame_ip, frame_ip_end, type_index);
param_cell_num = wasm_types[type_index]->param_cell_num;
cell_num = wasm_types[type_index]->ret_cell_num;
goto handle_op_block;
}
@ -1029,6 +1030,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_BLOCK)
{
value_type = *frame_ip++;
param_cell_num = 0;
cell_num = wasm_value_type_cell_num(value_type);
handle_op_block:
cache_index = ((uintptr_t)frame_ip)
@ -1052,13 +1054,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
else {
end_addr = NULL;
}
PUSH_CSP(LABEL_TYPE_BLOCK, cell_num, end_addr);
PUSH_CSP(LABEL_TYPE_BLOCK, param_cell_num, cell_num, end_addr);
HANDLE_OP_END();
}
HANDLE_OP(EXT_OP_LOOP)
{
read_leb_uint32(frame_ip, frame_ip_end, type_index);
param_cell_num = wasm_types[type_index]->param_cell_num;
cell_num = wasm_types[type_index]->param_cell_num;
goto handle_op_loop;
}
@ -1066,15 +1069,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_LOOP)
{
value_type = *frame_ip++;
param_cell_num = 0;
cell_num = wasm_value_type_cell_num(value_type);
handle_op_loop:
PUSH_CSP(LABEL_TYPE_LOOP, cell_num, frame_ip);
PUSH_CSP(LABEL_TYPE_LOOP, param_cell_num, cell_num, frame_ip);
HANDLE_OP_END();
}
HANDLE_OP(EXT_OP_IF)
{
read_leb_uint32(frame_ip, frame_ip_end, type_index);
param_cell_num = wasm_types[type_index]->param_cell_num;
cell_num = wasm_types[type_index]->ret_cell_num;
goto handle_op_if;
}
@ -1082,6 +1087,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_IF)
{
value_type = *frame_ip++;
param_cell_num = 0;
cell_num = wasm_value_type_cell_num(value_type);
handle_op_if:
cache_index = ((uintptr_t)frame_ip)
@ -1106,7 +1112,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
cond = (uint32)POP_I32();
if (cond) { /* if branch is met */
PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr);
PUSH_CSP(LABEL_TYPE_IF, param_cell_num, cell_num, end_addr);
}
else { /* if branch is not met */
/* if there is no else branch, go to the end addr */
@ -1115,7 +1121,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
}
/* if there is an else branch, go to the else addr */
else {
PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr);
PUSH_CSP(LABEL_TYPE_IF, param_cell_num, cell_num,
end_addr);
frame_ip = else_addr + 1;
}
}
@ -3063,8 +3070,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
s = (uint32)POP_I32();
d = (uint32)POP_I32();
if (s + n > dst_tbl_inst->cur_size
|| d + n > src_tbl_inst->cur_size) {
if (d + n > dst_tbl_inst->cur_size
|| s + n > src_tbl_inst->cur_size) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
@ -3659,7 +3666,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* Push function block as first block */
cell_num = func_type->ret_cell_num;
PUSH_CSP(LABEL_TYPE_FUNCTION, cell_num, frame_ip_end - 1);
PUSH_CSP(LABEL_TYPE_FUNCTION, 0, cell_num, frame_ip_end - 1);
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame);
#if WASM_ENABLE_THREAD_MGR != 0

View File

@ -2984,8 +2984,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
s = (uint32)POP_I32();
d = (uint32)POP_I32();
if (s + n > dst_tbl_inst->cur_size
|| d + n > src_tbl_inst->cur_size) {
if (d + n > dst_tbl_inst->cur_size
|| s + n > src_tbl_inst->cur_size) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;

View File

@ -3593,7 +3593,7 @@ check_wasi_abi_compatibility(const WASMModule *module, bool main_module,
#endif
WASMModule *
wasm_loader_load(const uint8 *buf, uint32 size,
wasm_loader_load(uint8 *buf, uint32 size,
#if WASM_ENABLE_MULTI_MODULE != 0
bool main_module,
#endif
@ -6436,6 +6436,7 @@ re_scan:
uint8 value_type;
BlockType block_type;
p_org = p - 1;
value_type = read_uint8(p);
if (is_byte_a_type(value_type)) {
/* If the first byte is one of these special values:
@ -6463,9 +6464,9 @@ re_scan:
* the block quickly.
*/
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p - 2, *(p - 2));
record_fast_op(module, p_org, *p_org);
#endif
*(p - 2) = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
*p_org = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
#endif
}
@ -7332,33 +7333,21 @@ re_scan:
PUSH_OFFSET_TYPE(local_type);
#else
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
&& (WASM_ENABLE_FAST_JIT == 0)
&& (WASM_ENABLE_FAST_JIT == 0) && (WASM_ENABLE_DEBUG_INTERP == 0)
if (local_offset < 0x80) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = EXT_OP_GET_LOCAL_FAST;
if (is_32bit_type(local_type)) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)local_offset;
}
else {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)(local_offset | 0x80);
}
while (p_org < p) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = WASM_OP_NOP;
}
}
#endif
#endif
#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
break;
}
@ -7408,33 +7397,21 @@ re_scan:
}
#else
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
&& (WASM_ENABLE_FAST_JIT == 0)
&& (WASM_ENABLE_FAST_JIT == 0) && (WASM_ENABLE_DEBUG_INTERP == 0)
if (local_offset < 0x80) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = EXT_OP_SET_LOCAL_FAST;
if (is_32bit_type(local_type)) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)local_offset;
}
else {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)(local_offset | 0x80);
}
while (p_org < p) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = WASM_OP_NOP;
}
}
#endif
#endif
#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
break;
}
@ -7480,33 +7457,21 @@ re_scan:
- wasm_value_type_cell_num(local_type)));
#else
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
&& (WASM_ENABLE_FAST_JIT == 0)
&& (WASM_ENABLE_FAST_JIT == 0) && (WASM_ENABLE_DEBUG_INTERP == 0)
if (local_offset < 0x80) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = EXT_OP_TEE_LOCAL_FAST;
if (is_32bit_type(local_type)) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)local_offset;
}
else {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)(local_offset | 0x80);
}
while (p_org < p) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = WASM_OP_NOP;
}
}
#endif
#endif
#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
break;
}

View File

@ -24,7 +24,7 @@ extern "C" {
* @return return module loaded, NULL if failed
*/
WASMModule *
wasm_loader_load(const uint8 *buf, uint32 size,
wasm_loader_load(uint8 *buf, uint32 size,
#if WASM_ENABLE_MULTI_MODULE != 0
bool main_module,
#endif

View File

@ -2346,7 +2346,7 @@ load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
}
WASMModule *
wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf,
wasm_loader_load(uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size)
{
WASMModule *module = create_module(error_buf, error_buf_size);
@ -4823,6 +4823,7 @@ re_scan:
uint8 value_type;
BlockType block_type;
p_org = p - 1;
value_type = read_uint8(p);
if (is_byte_a_type(value_type)) {
/* If the first byte is one of these special values:
@ -4845,7 +4846,7 @@ re_scan:
* to new extended opcode so that interpreter can resolve
* the block quickly.
*/
*(p - 2) = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
*p_org = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
#endif
}
@ -5754,12 +5755,10 @@ re_scan:
PUSH_TYPE(global_type);
#if WASM_ENABLE_FAST_INTERP == 0
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
if (global_type == VALUE_TYPE_I64
|| global_type == VALUE_TYPE_F64) {
*p_org = WASM_OP_GET_GLOBAL_64;
}
#endif
#else /* else of WASM_ENABLE_FAST_INTERP */
if (is_64bit_type(global_type)) {
skip_label();
@ -5799,7 +5798,6 @@ re_scan:
POP_TYPE(global_type);
#if WASM_ENABLE_FAST_INTERP == 0
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
if (is_64bit_type(global_type)) {
*p_org = WASM_OP_SET_GLOBAL_64;
}
@ -5807,7 +5805,6 @@ re_scan:
&& global_idx == module->aux_stack_top_global_index) {
*p_org = WASM_OP_SET_GLOBAL_AUX_STACK;
}
#endif
#else /* else of WASM_ENABLE_FAST_INTERP */
if (is_64bit_type(global_type)) {
skip_label();

View File

@ -45,7 +45,7 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
}
WASMModule *
wasm_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size)
wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size)
{
return wasm_loader_load(buf, size,
#if WASM_ENABLE_MULTI_MODULE != 0
@ -1522,6 +1522,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
module->wasi_args.dir_list, module->wasi_args.dir_count,
module->wasi_args.map_dir_list, module->wasi_args.map_dir_count,
module->wasi_args.env, module->wasi_args.env_count,
module->wasi_args.addr_pool, module->wasi_args.addr_count,
module->wasi_args.argv, module->wasi_args.argc,
module->wasi_args.stdio[0], module->wasi_args.stdio[1],
module->wasi_args.stdio[2], error_buf, error_buf_size)) {
@ -2503,7 +2504,8 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
/* release previous stack frames and create new ones */
if (!bh_vector_destroy(module_inst->frames)
|| !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame))) {
|| !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame),
false)) {
return;
}

View File

@ -273,8 +273,7 @@ wasm_get_func_code_end(WASMFunctionInstance *func)
}
WASMModule *
wasm_load(const uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size);
wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size);
WASMModule *
wasm_load_from_sections(WASMSection *section_list, char *error_buf,

View File

@ -224,6 +224,8 @@ on_rsp_byte_arrive(unsigned char ch, rsp_recv_context_t *ctx)
if (ctx->size_in_phase == 2) {
ctx->size_in_phase = 0;
bh_assert(ctx->receive_index >= 3);
if ((hex(ctx->receive_buffer[ctx->receive_index - 2]) << 4
| hex(ctx->receive_buffer[ctx->receive_index - 1]))
!= ctx->check_sum) {

View File

@ -0,0 +1,410 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _WASI_SOCKET_EXT_H_
#define _WASI_SOCKET_EXT_H_
#include <stddef.h>
#include <stdint.h>
/*Be a part of <wasi/api.h>*/
typedef enum {
SOCKET_DGRAM = 0,
SOCKET_STREAM,
} __wasi_sock_type_t;
typedef uint16_t __wasi_ip_port_t;
typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
/* n0.n1.n2.n3 */
typedef struct __wasi_addr_ip4_t {
uint8_t n0;
uint8_t n1;
uint8_t n2;
uint8_t n3;
} __wasi_addr_ip4_t;
typedef struct __wasi_addr_ip4_port_t {
__wasi_addr_ip4_t addr;
__wasi_ip_port_t port;
} __wasi_addr_ip4_port_t;
typedef struct __wasi_addr_ip6_t {
uint16_t n0;
uint16_t n1;
uint16_t n2;
uint16_t n3;
uint16_t h0;
uint16_t h1;
uint16_t h2;
uint16_t h3;
} __wasi_addr_ip6_t;
typedef struct __wasi_addr_ip6_port_t {
__wasi_addr_ip6_t addr;
__wasi_ip_port_t port;
} __wasi_addr_ip6_port_t;
typedef struct __wasi_addr_t {
__wasi_addr_type_t kind;
union {
__wasi_addr_ip4_port_t ip4;
__wasi_addr_ip6_port_t ip6;
} addr;
} __wasi_addr_t;
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
#ifdef __wasi__
/**
* Reimplement below POSIX APIs with __wasi_sock_XXX functions.
*
* Keep sync with
* <sys/socket.h>
* <sys/types.h>
*/
int
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int
bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int
listen(int sockfd, int backlog);
int
socket(int domain, int type, int protocol);
#endif
/**
* Accept a connection on a socket
* Note: This is similar to `accept`
*/
int32_t
__imported_wasi_snapshot_preview1_sock_accept(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_accept")));
static inline __wasi_errno_t
__wasi_sock_accept(__wasi_fd_t fd, __wasi_fd_t *fd_new)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_accept(
(int32_t)fd, (int32_t)fd_new);
}
/**
* Returns the local address to which the socket is bound.
*
* Note: This is similar to `getsockname` in POSIX
*
* When successful, the contents of the output buffer consist of an IP address,
* either IP4 or IP6.
*/
int32_t
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_addr_local")));
static inline __wasi_errno_t
__wasi_sock_addr_local(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
}
/**
* Returns the remote address to which the socket is connected to.
*
* Note: This is similar to `getpeername` in POSIX
*
* When successful, the contents of the output buffer consist of an IP address,
* either IP4 or IP6.
*/
int32_t
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_addr_remote")));
static inline __wasi_errno_t
__wasi_sock_addr_remote(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
}
/**
* Resolves a hostname and a port to one or more IP addresses. Port is optional
* and you can pass 0 (zero) in most cases, it is used a hint for protocol.
*
* Note: This is similar to `getaddrinfo` in POSIX
*
* When successful, the contents of the output buffer consist of a sequence of
* IPv4 and/or IPv6 addresses. Each address entry consists of a addr_t object.
*
* This function fills the output buffer as much as possible, potentially
* truncating the last address entry. It is advisable that the buffer is
*/
int32_t
__imported_wasi_snapshot_preview1_addr_resolve(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("addr_resolve")));
static inline __wasi_errno_t
__wasi_addr_resolve(__wasi_fd_t fd, const char *host, __wasi_ip_port_t port,
uint8_t *buf, __wasi_size_t size)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_addr_resolve(
(int32_t)fd, (int32_t)host, (int32_t)port, (int32_t)buf, (int32_t)size);
}
/**
* Bind a socket
* Note: This is similar to `bind` in POSIX using PF_INET
*/
int32_t
__imported_wasi_snapshot_preview1_sock_bind(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_bind")));
static inline __wasi_errno_t
__wasi_sock_bind(__wasi_fd_t fd, __wasi_addr_t *addr)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_bind(
(int32_t)fd, (int32_t)addr);
}
/**
* Close a socket (this is an alias for `fd_close`)
* Note: This is similar to `close` in POSIX.
*/
int32_t
__imported_wasi_snapshot_preview1_sock_close(int32_t arg0)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_close")));
static inline __wasi_errno_t
__wasi_sock_close(__wasi_fd_t fd)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_close(
(int32_t)fd);
}
/**
* Initiate a connection on a socket to the specified address
* Note: This is similar to `connect` in POSIX
*/
int32_t
__imported_wasi_snapshot_preview1_sock_connect(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_connect")));
static inline __wasi_errno_t
__wasi_sock_connect(__wasi_fd_t fd, __wasi_addr_t *addr)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_connect(
(int32_t)fd, (int32_t)addr);
}
/**
* Retrieve the size of the receive buffer
* Note: This is similar to `getsockopt` in POSIX for SO_RCVBUF
*/
int32_t
__imported_wasi_snapshot_preview1_sock_get_recv_buf_size(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_recv_buf_size")));
static inline __wasi_errno_t
__wasi_sock_get_recv_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_recv_buf_size((int32_t)fd,
(int32_t)size);
}
/**
* Retrieve status of address reuse on a socket
* Note: This is similar to `getsockopt` in POSIX for SO_REUSEADDR
*/
int32_t
__imported_wasi_snapshot_preview1_sock_get_reuse_addr(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_reuse_addr")));
static inline __wasi_errno_t
__wasi_sock_get_reuse_addr(__wasi_fd_t fd, uint8_t *reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_reuse_addr((int32_t)fd,
(int32_t)reuse);
}
/**
* Retrieve status of port reuse on a socket
* Note: This is similar to `getsockopt` in POSIX for SO_REUSEPORT
*/
int32_t
__imported_wasi_snapshot_preview1_sock_get_reuse_port(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_reuse_port")));
static inline __wasi_errno_t
__wasi_sock_get_reuse_port(__wasi_fd_t fd, int8_t *reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_reuse_port((int32_t)fd,
(int32_t)reuse);
}
/**
* Retrieve the size of the send buffer
* Note: This is similar to `getsockopt` in POSIX for SO_SNDBUF
*/
int32_t
__imported_wasi_snapshot_preview1_sock_get_send_buf_size(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_send_buf_size")));
static inline __wasi_errno_t
__wasi_sock_get_send_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_send_buf_size((int32_t)fd,
(int32_t)size);
}
/**
* Listen for connections on a socket
* Note: This is similar to `listen`
*/
int32_t
__imported_wasi_snapshot_preview1_sock_listen(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_listen")));
static inline __wasi_errno_t
__wasi_sock_listen(__wasi_fd_t fd, __wasi_size_t backlog)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_listen(
(int32_t)fd, (int32_t)backlog);
}
/**
* Open a socket
* The first argument to this function is a handle to an
* address pool. The address pool determines what actions can
* be performed and at which addresses they can be performed to.
* The address pool cannot be re-assigned. You will need to close
* the socket and open a new one to use a different address pool.
* Note: This is similar to `socket` in POSIX using PF_INET
*/
int32_t
__imported_wasi_snapshot_preview1_sock_open(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_open")));
static inline __wasi_errno_t
__wasi_sock_open(__wasi_fd_t fd, __wasi_address_family_t af,
__wasi_sock_type_t socktype, __wasi_fd_t *sockfd)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_open(
(int32_t)fd, (int32_t)af, (int32_t)socktype, (int32_t)sockfd);
}
/**
* Set size of receive buffer
* Note: This is similar to `setsockopt` in POSIX for SO_RCVBUF
*/
int32_t
__imported_wasi_snapshot_preview1_sock_set_recv_buf_size(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_recv_buf_size")));
static inline __wasi_errno_t
__wasi_sock_set_recv_buf_size(__wasi_fd_t fd, __wasi_size_t size)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_recv_buf_size((int32_t)fd,
(int32_t)size);
}
/**
* Enable/disable address reuse on a socket
* Note: This is similar to `setsockopt` in POSIX for SO_REUSEADDR
*/
int32_t
__imported_wasi_snapshot_preview1_sock_set_reuse_addr(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_reuse_addr")));
static inline __wasi_errno_t
__wasi_sock_set_reuse_addr(__wasi_fd_t fd, uint8_t reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_reuse_addr((int32_t)fd,
(int32_t)reuse);
}
/**
* Enable port reuse on a socket
* Note: This is similar to `setsockopt` in POSIX for SO_REUSEPORT
*/
int32_t
__imported_wasi_snapshot_preview1_sock_set_reuse_port(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_reuse_port")));
static inline __wasi_errno_t
__wasi_sock_set_reuse_port(__wasi_fd_t fd, uint8_t reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_reuse_port((int32_t)fd,
(int32_t)reuse);
}
/**
* Set size of send buffer
* Note: This is similar to `setsockopt` in POSIX for SO_SNDBUF
*/
int32_t
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_send_buf_size")));
static inline __wasi_errno_t
__wasi_sock_set_send_buf_size(__wasi_fd_t fd)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_send_buf_size((int32_t)fd);
}
/**
* TODO: modify recv() and send()
* since don't want to re-compile the wasi-libc,
* we tend to keep original implentations of recv() and send().
*/
#endif

View File

@ -0,0 +1,9 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required (VERSION 2.8...3.16)
project(socket_wasi_ext)
add_library(${PROJECT_NAME} STATIC ${CMAKE_CURRENT_LIST_DIR}/src/wasi/wasi_socket_ext.c)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc/)

View File

@ -0,0 +1,180 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <wasi/api.h>
#include <wasi_socket_ext.h>
#define HANDLE_ERROR(error) \
if (error != __WASI_ERRNO_SUCCESS) { \
errno = error; \
return -1; \
}
/* addr_num and port are in network order */
static void
ipv4_addr_to_wasi_addr(uint32_t addr_num, uint16_t port, __wasi_addr_t *out)
{
out->kind = IPv4;
out->addr.ip4.port = ntohs(port);
out->addr.ip4.addr.n3 = (addr_num & 0xFF000000) >> 24;
out->addr.ip4.addr.n2 = (addr_num & 0x00FF0000) >> 16;
out->addr.ip4.addr.n1 = (addr_num & 0x0000FF00) >> 8;
out->addr.ip4.addr.n0 = (addr_num & 0x000000FF);
}
static __wasi_errno_t
sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
__wasi_addr_t *wasi_addr)
{
__wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
if (AF_INET == sock_addr->sa_family) {
assert(sizeof(struct sockaddr_in) == addrlen);
ipv4_addr_to_wasi_addr(
((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
}
else if (AF_INET6 == sock_addr->sa_family) {
// TODO: IPV6
ret = __WASI_ERRNO_AFNOSUPPORT;
}
else {
ret = __WASI_ERRNO_AFNOSUPPORT;
}
return ret;
}
static __wasi_errno_t
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_errno_t error;
error =
__wasi_sock_addr_remote(fd, (uint8_t *)&wasi_addr, sizeof(wasi_addr));
if (__WASI_ERRNO_SUCCESS != error) {
return error;
}
if (IPv4 == wasi_addr.kind) {
struct sockaddr_in sock_addr_in = { 0 };
sock_addr_in.sin_family = AF_INET;
sock_addr_in.sin_addr.s_addr = (wasi_addr.addr.ip4.addr.n3 << 24)
| (wasi_addr.addr.ip4.addr.n2 << 16)
| (wasi_addr.addr.ip4.addr.n1 << 8)
| wasi_addr.addr.ip4.addr.n0;
sock_addr_in.sin_port = htons(wasi_addr.addr.ip4.port);
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
*addrlen = sizeof(sock_addr_in);
}
else if (IPv6 == wasi_addr.kind) {
// TODO: IPV6
return __WASI_ERRNO_AFNOSUPPORT;
}
else {
return __WASI_ERRNO_AFNOSUPPORT;
}
return __WASI_ERRNO_SUCCESS;
}
int
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_fd_t new_sockfd;
__wasi_errno_t error;
error = __wasi_sock_accept(sockfd, &new_sockfd);
HANDLE_ERROR(error)
// error = sock_addr_remote(new_sockfd, addr, addrlen);
// HANDLE_ERROR(error)
*addrlen = 0;
return new_sockfd;
}
int
bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_errno_t error;
error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
HANDLE_ERROR(error)
error = __wasi_sock_bind(sockfd, &wasi_addr);
HANDLE_ERROR(error)
return __WASI_ERRNO_SUCCESS;
}
int
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_errno_t error;
error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
HANDLE_ERROR(error)
error = __wasi_sock_connect(sockfd, &wasi_addr);
HANDLE_ERROR(error)
return __WASI_ERRNO_SUCCESS;
}
int
listen(int sockfd, int backlog)
{
__wasi_errno_t error = __wasi_sock_listen(sockfd, backlog);
HANDLE_ERROR(error)
return __WASI_ERRNO_SUCCESS;
}
int
socket(int domain, int type, int protocol)
{
// the stub of address pool fd
__wasi_fd_t poolfd = -1;
__wasi_fd_t sockfd;
__wasi_errno_t error;
__wasi_address_family_t af;
__wasi_sock_type_t socktype;
if (AF_INET == domain) {
af = INET4;
}
else if (AF_INET6 == domain) {
af = INET6;
}
else {
return __WASI_ERRNO_NOPROTOOPT;
}
if (SOCK_DGRAM == type) {
socktype = SOCKET_DGRAM;
}
else if (SOCK_STREAM == type) {
socktype = SOCKET_STREAM;
}
else {
return __WASI_ERRNO_NOPROTOOPT;
}
error = __wasi_sock_open(poolfd, af, socktype, &sockfd);
HANDLE_ERROR(error)
return sockfd;
}

View File

@ -0,0 +1,66 @@
libuv is licensed for use as follows:
====
Copyright (c) 2015-present libuv project contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
====
This license applies to parts of libuv originating from the
https://github.com/joyent/libuv repository:
====
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
====
This license applies to all parts of libuv that are not externally
maintained libraries.
The externally maintained libraries used by libuv are:
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
license.
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
clause BSD license.
- pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
Three clause BSD license.

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Colin Ihrig and Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -2,21 +2,22 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR})
set (UVWASI_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../deps/uvwasi)
set (LIBUV_VERSION v1.42.0)
add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1)
include(FetchContent)
## https://libuv.org
## libuv
FetchContent_Declare(
libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG ${LIBUV_VERSION})
GIT_TAG ${LIBUV_VERSION}
)
FetchContent_GetProperties(libuv)
if(NOT libuv_POPULATED)
message ("-- Fetching libuv ..")
if (NOT libuv_POPULATED)
message("-- Fetching libuv ..")
FetchContent_Populate(libuv)
include_directories("${libuv_SOURCE_DIR}/include")
add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL)
@ -24,8 +25,20 @@ if(NOT libuv_POPULATED)
set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1)
endif()
include_directories(${UVWASI_DIR}/include)
## uvwasi
FetchContent_Declare(
uvwasi
GIT_REPOSITORY https://github.com/nodejs/uvwasi.git
GIT_TAG main
)
FetchContent_GetProperties(uvwasi)
if (NOT uvwasi_POPULATED)
message("-- Fetching uvwasi ..")
FetchContent_Populate(uvwasi)
include_directories("${uvwasi_SOURCE_DIR}/include")
add_subdirectory(${uvwasi_SOURCE_DIR} ${uvwasi_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c ${UVWASI_DIR}/src/*.c)
file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c ${uvwasi_SOURCE_DIR}/src/*.c)
set (LIBC_WASI_SOURCE ${source_all})

View File

@ -50,6 +50,7 @@ typedef struct WASIContext {
struct fd_table *curfds;
struct fd_prestats *prestats;
struct argv_environ_values *argv_environ;
struct addr_pool *addr_pool;
char *argv_buf;
char **argv_list;
char *env_buf;
@ -83,6 +84,14 @@ wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
return wasi_ctx->prestats;
}
static inline struct addr_pool *
wasi_ctx_get_addr_pool(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
{
if (!wasi_ctx)
return NULL;
return wasi_ctx->addr_pool;
}
static wasi_errno_t
wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
{
@ -987,112 +996,277 @@ wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
}
static wasi_errno_t
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
uint32 ri_data_len, wasi_riflags_t ri_flags,
uint32 *ro_datalen_app, wasi_roflags_t *ro_flags)
wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fd_t *fd_new)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
return wasi_ssp_sock_accept(curfds, fd, fd_new);
}
static wasi_errno_t
wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
wasi_size_t buf_len)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
return wasi_ssp_sock_addr_local(curfds, fd, buf, buf_len);
}
static wasi_errno_t
wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
wasi_size_t buf_len)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
return wasi_ssp_sock_addr_remote(curfds, fd, buf, buf_len);
}
static wasi_errno_t
wasi_sock_addr_resolve(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *host,
wasi_ip_port_t port, uint8 *buf, wasi_size_t size)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
struct addr_pool *addr_pool = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr);
}
static wasi_errno_t
wasi_sock_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
struct addr_pool *addr_pool = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr);
}
static wasi_errno_t
wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
wasi_size_t *size)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
wasi_size_t *size)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
return wasi_ssp_sock_listen(curfds, fd, backlog);
}
static wasi_errno_t
wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd,
wasi_address_family_t af, wasi_sock_type_t socktype,
wasi_fd_t *sockfd)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = NULL;
if (!wasi_ctx)
return __WASI_EACCES;
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd);
}
static wasi_errno_t
wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
wasi_size_t size)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
wasi_size_t size)
{
return __WASI_ENOSYS;
}
static wasi_errno_t
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len,
wasi_roflags_t *ro_flags)
{
/**
* ri_data_len is the length of a list of iovec_app_t, which head is
* ri_data. ro_data_len is the number of bytes received
**/
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
wasi_iovec_t *iovec, *iovec_begin;
uint64 total_size;
size_t ro_datalen;
uint32 i;
wasi_errno_t err;
if (!wasi_ctx)
return (wasi_errno_t)-1;
return __WASI_EINVAL;
total_size = sizeof(iovec_app_t) * (uint64)ri_data_len;
if (!validate_native_addr(ro_datalen_app, (uint32)sizeof(uint32))
if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32))
|| !validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))
|| total_size >= UINT32_MAX
|| !validate_native_addr(ri_data, (uint32)total_size))
return (wasi_errno_t)-1;
return __WASI_EINVAL;
total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len;
if (total_size >= UINT32_MAX
|| !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
return (wasi_errno_t)-1;
/* recv ri_data one by one */
*ro_data_len = 0;
for (i = 0; i < ri_data_len; ri_data++, i++) {
void *buf;
size_t bytes_recv;
iovec = iovec_begin;
for (i = 0; i < ri_data_len; i++, ri_data++, iovec++) {
if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) {
err = (wasi_errno_t)-1;
goto fail;
return __WASI_EINVAL;
}
iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset);
iovec->buf_len = ri_data->buf_len;
buf = (void *)addr_app_to_native(ri_data->buf_offset);
err = wasmtime_ssp_sock_recv(curfds, sock, buf, ri_data->buf_len,
&bytes_recv);
if (err != __WASI_ESUCCESS) {
return err;
}
*ro_data_len += bytes_recv;
}
err = wasmtime_ssp_sock_recv(curfds, sock, iovec_begin, ri_data_len,
ri_flags, &ro_datalen, ro_flags);
if (err)
goto fail;
*(uint32 *)ro_datalen_app = (uint32)ro_datalen;
/* success */
err = 0;
fail:
wasm_runtime_free(iovec_begin);
return err;
*ro_flags = ri_flags;
return __WASI_ESUCCESS;
}
static wasi_errno_t
wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
const iovec_app_t *si_data, uint32 si_data_len,
wasi_siflags_t si_flags, uint32 *so_datalen_app)
wasi_siflags_t si_flags, uint32 *so_data_len)
{
/**
* si_data_len is the length of a list of iovec_app_t, which head is
* si_data. so_data_len is the number of bytes sent
**/
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
wasi_ciovec_t *ciovec, *ciovec_begin;
uint64 total_size;
size_t so_datalen;
uint32 i;
wasi_errno_t err;
if (!wasi_ctx)
return (wasi_errno_t)-1;
return __WASI_EINVAL;
total_size = sizeof(iovec_app_t) * (uint64)si_data_len;
if (!validate_native_addr(so_datalen_app, sizeof(uint32))
if (!validate_native_addr(so_data_len, sizeof(uint32))
|| total_size >= UINT32_MAX
|| !validate_native_addr((void *)si_data, (uint32)total_size))
return (wasi_errno_t)-1;
return __WASI_EINVAL;
total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len;
if (total_size >= UINT32_MAX
|| !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
return (wasi_errno_t)-1;
/* send si_data one by one */
*so_data_len = 0;
for (i = 0; i < si_data_len; i++, si_data++) {
void *buf;
size_t bytes_sent;
ciovec = ciovec_begin;
for (i = 0; i < si_data_len; i++, si_data++, ciovec++) {
if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
err = (wasi_errno_t)-1;
goto fail;
return __WASI_EINVAL;
}
ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset);
ciovec->buf_len = si_data->buf_len;
buf = (void *)addr_app_to_native(si_data->buf_offset);
err = wasmtime_ssp_sock_send(curfds, sock, buf, si_data->buf_len,
&bytes_sent);
if (err != __WASI_ESUCCESS) {
return err;
}
*so_data_len += bytes_sent;
}
err = wasmtime_ssp_sock_send(curfds, sock, ciovec_begin, si_data_len,
si_flags, &so_datalen);
if (err)
goto fail;
*so_datalen_app = (uint32)so_datalen;
/* success */
err = 0;
fail:
wasm_runtime_free(ciovec_begin);
return err;
return __WASI_ESUCCESS;
}
static wasi_errno_t
@ -1103,9 +1277,9 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
if (!wasi_ctx)
return (wasi_errno_t)-1;
return __WASI_EINVAL;
return wasmtime_ssp_sock_shutdown(curfds, sock, how);
return wasmtime_ssp_sock_shutdown(curfds, sock);
}
static wasi_errno_t
@ -1161,8 +1335,25 @@ static NativeSymbol native_symbols_libc_wasi[] = {
REG_NATIVE_FUNC(proc_exit, "(i)"),
REG_NATIVE_FUNC(proc_raise, "(i)i"),
REG_NATIVE_FUNC(random_get, "(*~)i"),
REG_NATIVE_FUNC(sock_accept, "(i*)i"),
REG_NATIVE_FUNC(sock_addr_local, "(i*i)i"),
REG_NATIVE_FUNC(sock_addr_remote, "(i*i)i"),
REG_NATIVE_FUNC(sock_addr_resolve, "(i*i*i)i"),
REG_NATIVE_FUNC(sock_bind, "(i*)i"),
REG_NATIVE_FUNC(sock_close, "(i)i"),
REG_NATIVE_FUNC(sock_connect, "(i*)i"),
REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"),
REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"),
REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"),
REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"),
REG_NATIVE_FUNC(sock_listen, "(ii)i"),
REG_NATIVE_FUNC(sock_open, "(iii*)i"),
REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"),
REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"),
REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"),
REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"),
REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
REG_NATIVE_FUNC(sched_yield, "()i"),
};

View File

@ -13,38 +13,43 @@
extern "C" {
#endif
typedef __wasi_errno_t wasi_errno_t;
typedef __wasi_fd_t wasi_fd_t;
typedef __wasi_clockid_t wasi_clockid_t;
typedef __wasi_timestamp_t wasi_timestamp_t;
typedef __wasi_prestat_t wasi_prestat_t;
typedef __wasi_iovec_t wasi_iovec_t;
typedef __wasi_ciovec_t wasi_ciovec_t;
typedef __wasi_filetype_t wasi_filetype_t;
typedef __wasi_filesize_t wasi_filesize_t;
typedef __wasi_filedelta_t wasi_filedelta_t;
typedef __wasi_whence_t wasi_whence_t;
typedef __wasi_fdstat_t wasi_fdstat_t;
typedef __wasi_fdflags_t wasi_fdflags_t;
typedef __wasi_rights_t wasi_rights_t;
typedef __wasi_address_family_t wasi_address_family_t;
typedef __wasi_addr_t wasi_addr_t;
typedef __wasi_advice_t wasi_advice_t;
typedef __wasi_lookupflags_t wasi_lookupflags_t;
typedef __wasi_oflags_t wasi_oflags_t;
typedef __wasi_ciovec_t wasi_ciovec_t;
typedef __wasi_clockid_t wasi_clockid_t;
typedef __wasi_dircookie_t wasi_dircookie_t;
typedef __wasi_filestat_t wasi_filestat_t;
typedef __wasi_fstflags_t wasi_fstflags_t;
typedef __wasi_subscription_t wasi_subscription_t;
typedef __wasi_errno_t wasi_errno_t;
typedef __wasi_event_t wasi_event_t;
typedef __wasi_exitcode_t wasi_exitcode_t;
typedef __wasi_signal_t wasi_signal_t;
typedef __wasi_riflags_t wasi_riflags_t;
typedef __wasi_roflags_t wasi_roflags_t;
typedef __wasi_siflags_t wasi_siflags_t;
typedef __wasi_sdflags_t wasi_sdflags_t;
typedef __wasi_fdflags_t wasi_fdflags_t;
typedef __wasi_fdstat_t wasi_fdstat_t;
typedef __wasi_fd_t wasi_fd_t;
typedef __wasi_filedelta_t wasi_filedelta_t;
typedef __wasi_filesize_t wasi_filesize_t;
typedef __wasi_filestat_t wasi_filestat_t;
typedef __wasi_filetype_t wasi_filetype_t;
typedef __wasi_fstflags_t wasi_fstflags_t;
typedef __wasi_iovec_t wasi_iovec_t;
typedef __wasi_ip_port_t wasi_ip_port_t;
typedef __wasi_lookupflags_t wasi_lookupflags_t;
typedef __wasi_oflags_t wasi_oflags_t;
typedef __wasi_preopentype_t wasi_preopentype_t;
typedef __wasi_prestat_t wasi_prestat_t;
typedef __wasi_riflags_t wasi_riflags_t;
typedef __wasi_rights_t wasi_rights_t;
typedef __wasi_roflags_t wasi_roflags_t;
typedef __wasi_sdflags_t wasi_sdflags_t;
typedef __wasi_siflags_t wasi_siflags_t;
typedef __wasi_signal_t wasi_signal_t;
typedef __wasi_size_t wasi_size_t;
typedef __wasi_sock_type_t wasi_sock_type_t;
typedef __wasi_subscription_t wasi_subscription_t;
typedef __wasi_timestamp_t wasi_timestamp_t;
typedef __wasi_whence_t wasi_whence_t;
#ifdef __cplusplus
}
#endif
#endif /* end of _LIBC_WASI_WRAPPER_H */
#endif /* end of _LIBC_WASI_WRAPPER_H */

View File

@ -49,6 +49,9 @@ _Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout");
_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout");
#endif
typedef uint32_t __wasi_size_t;
_Static_assert(_Alignof(__wasi_size_t) == 4, "non-wasi data layout");
typedef uint8_t __wasi_advice_t;
#define __WASI_ADVICE_NORMAL (0)
#define __WASI_ADVICE_SEQUENTIAL (1)
@ -211,35 +214,44 @@ typedef uint64_t __wasi_rights_t;
* Observe that WASI defines rights in the plural form
* TODO: refactor to use RIGHTS instead of RIGHT
*/
#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(1 << 0))
#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(1 << 1))
#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(1 << 2))
#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(1 << 3))
#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(1 << 4))
#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(1 << 5))
#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(1 << 6))
#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(1 << 7))
#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(1 << 8))
#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(1 << 9))
#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(1 << 10))
#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(1 << 11))
#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(1 << 12))
#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(1 << 13))
#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(1 << 14))
#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(1 << 15))
#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(1 << 16))
#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(1 << 17))
#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(1 << 18))
#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 19))
#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 20))
#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(1 << 21))
#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 22))
#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 23))
#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(1 << 24))
#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(1 << 25))
#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(1 << 26))
#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(1 << 27))
#define __WASI_RIGHT_SOCK_SHUTDOWN ((__wasi_rights_t)(1 << 28))
#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(UINT64_C(1) << 0))
#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(UINT64_C(1) << 1))
#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(UINT64_C(1) << 2))
#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(UINT64_C(1) << 3))
#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(UINT64_C(1) << 4))
#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(UINT64_C(1) << 5))
#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(UINT64_C(1) << 6))
#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(UINT64_C(1) << 7))
#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(UINT64_C(1) << 8))
#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 9))
#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(UINT64_C(1) << 10))
#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 11))
#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(UINT64_C(1) << 12))
#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(UINT64_C(1) << 13))
#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(UINT64_C(1) << 14))
#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(UINT64_C(1) << 15))
#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 16))
#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(UINT64_C(1) << 17))
#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 18))
#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 19))
#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 20))
#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 21))
#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 22))
#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 23))
#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(UINT64_C(1) << 24))
#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 25))
#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(UINT64_C(1) << 26))
#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(UINT64_C(1) << 27))
#define __WASI_RIGHT_SOCK_CONNECT ((__wasi_rights_t)(UINT64_C(1) << 28))
#define __WASI_RIGHT_SOCK_LISTEN ((__wasi_rights_t)(UINT64_C(1) << 29))
#define __WASI_RIGHT_SOCK_BIND ((__wasi_rights_t)(UINT64_C(1) << 30))
#define __WASI_RIGHT_SOCK_ACCEPT ((__wasi_rights_t)(UINT64_C(1) << 31))
#define __WASI_RIGHT_SOCK_RECV ((__wasi_rights_t)(UINT64_C(1) << 32))
#define __WASI_RIGHT_SOCK_SEND ((__wasi_rights_t)(UINT64_C(1) << 33))
#define __WASI_RIGHT_SOCK_ADDR_LOCAL ((__wasi_rights_t)(UINT64_C(1) << 34))
#define __WASI_RIGHT_SOCK_ADDR_REMOTE ((__wasi_rights_t)(UINT64_C(1) << 35))
#define __WASI_RIGHT_SOCK_RECV_FROM ((__wasi_rights_t)(UINT64_C(1) << 36))
#define __WASI_RIGHT_SOCK_SEND_TO ((__wasi_rights_t)(UINT64_C(1) << 37))
typedef uint16_t __wasi_roflags_t;
#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001)
@ -301,6 +313,7 @@ typedef uint8_t __wasi_preopentype_t;
struct fd_table;
struct fd_prestats;
struct argv_environ_values;
struct addr_pool;
typedef struct __wasi_dirent_t {
__wasi_dircookie_t d_next;
@ -536,6 +549,55 @@ _Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align");
_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset");
_Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset");
/* keep syncing with wasi_socket_ext.h */
typedef enum {
SOCKET_DGRAM = 0,
SOCKET_STREAM,
} __wasi_sock_type_t;
typedef uint16_t __wasi_ip_port_t;
typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
/* n0.n1.n2.n3 */
typedef struct __wasi_addr_ip4_t {
uint8_t n0;
uint8_t n1;
uint8_t n2;
uint8_t n3;
} __wasi_addr_ip4_t;
typedef struct __wasi_addr_ip4_port_t {
__wasi_addr_ip4_t addr;
__wasi_ip_port_t port;
} __wasi_addr_ip4_port_t;
typedef struct __wasi_addr_ip6_t {
uint16_t n0;
uint16_t n1;
uint16_t n2;
uint16_t n3;
uint16_t h0;
uint16_t h1;
uint16_t h2;
uint16_t h3;
} __wasi_addr_ip6_t;
typedef struct __wasi_addr_ip6_port_t {
__wasi_addr_ip6_t addr;
__wasi_ip_port_t port;
} __wasi_addr_ip6_port_t;
typedef struct __wasi_addr_t {
__wasi_addr_type_t kind;
union {
__wasi_addr_ip4_port_t ip4;
__wasi_addr_ip6_port_t ip6;
} addr;
} __wasi_addr_t;
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
#if defined(WASMTIME_SSP_WASI_API)
#define WASMTIME_SSP_SYSCALL_NAME(name) \
asm("__wasi_" #name)
@ -920,16 +982,71 @@ __wasi_errno_t wasmtime_ssp_random_get(
size_t buf_len
) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_accept(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_fd_t *fd_new
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_addr_local(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_addr_remote(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_open(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
__wasi_fd_t *sockfd
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_bind(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_listen(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t backlog
) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_recv(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
const __wasi_iovec_t *ri_data,
size_t ri_data_len,
__wasi_riflags_t ri_flags,
size_t *ro_datalen,
__wasi_roflags_t *ro_flags
void *buf,
size_t buf_len,
size_t *recv_len
) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send(
@ -937,18 +1054,16 @@ __wasi_errno_t wasmtime_ssp_sock_send(
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
const __wasi_ciovec_t *si_data,
size_t si_data_len,
__wasi_siflags_t si_flags,
size_t *so_datalen
const void *buf,
size_t buf_len,
size_t *sent_len
) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
__wasi_sdflags_t how
__wasi_fd_t sock
) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sched_yield(void)

View File

@ -60,6 +60,7 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t),
static __thread struct fd_table *curfds;
static __thread struct fd_prestats *prestats;
static __thread struct argv_environ_values *argv_environ;
static __thread struct addr_pool *addr_pool;
#endif
// Converts a POSIX error code to a CloudABI error code.
@ -2715,44 +2716,246 @@ wasmtime_ssp_random_get(void *buf, size_t nbyte)
return 0;
}
__wasi_errno_t
wasi_ssp_sock_accept(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_fd_t *fd_new)
{
__wasi_filetype_t wasi_type;
__wasi_rights_t max_base, max_inheriting;
struct fd_object *fo;
bh_socket_t new_sock;
int ret;
__wasi_errno_t error =
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ACCEPT, 0);
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL);
fd_object_release(fo);
if (ret == BHT_ERROR)
return convert_errno(errno);
error = fd_determine_type_rights(new_sock, &wasi_type, &max_base,
&max_inheriting);
if (error != __WASI_ESUCCESS) {
os_socket_close(ret);
return error;
}
error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base,
max_inheriting, fd_new);
if (error != __WASI_ESUCCESS) {
os_socket_close(ret);
return error;
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasi_ssp_sock_addr_local(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
{
struct fd_object *fo;
__wasi_errno_t error =
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
if (error != __WASI_ESUCCESS)
return error;
fd_object_release(fo);
return __WASI_ENOSYS;
}
__wasi_errno_t
wasi_ssp_sock_addr_remote(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
{
struct fd_object *fo;
__wasi_errno_t error =
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_REMOTE, 0);
if (error != __WASI_ESUCCESS)
return error;
fd_object_release(fo);
return __WASI_ENOSYS;
}
__wasi_errno_t
wasi_ssp_sock_bind(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr)
{
char buf[24] = { 0 };
const char *format = "%u.%u.%u.%u";
struct fd_object *fo;
__wasi_errno_t error;
int port = addr->addr.ip4.port;
int ret;
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
if (!addr_pool_search(addr_pool, buf)) {
return __WASI_EACCES;
}
error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_bind(fd_number(fo), buf, &port);
fd_object_release(fo);
if (ret == BHT_ERROR) {
return convert_errno(errno);
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasi_ssp_sock_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr)
{
char buf[24] = { 0 };
const char *format = "%u.%u.%u.%u";
struct fd_object *fo;
__wasi_errno_t error;
int ret;
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
if (!addr_pool_search(addr_pool, buf)) {
return __WASI_EACCES;
}
error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_connect(fd_number(fo), buf, addr->addr.ip4.port);
fd_object_release(fo);
if (ret == BHT_ERROR) {
return convert_errno(errno);
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasi_ssp_sock_listen(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t backlog)
{
struct fd_object *fo;
int ret;
__wasi_errno_t error =
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_LISTEN, 0);
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_listen(fd_number(fo), backlog);
fd_object_release(fo);
if (ret == BHT_ERROR) {
return convert_errno(errno);
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasi_ssp_sock_open(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
__wasi_fd_t *sockfd)
{
bh_socket_t sock;
int tcp_or_udp = 0;
int ret;
__wasi_filetype_t wasi_type;
__wasi_rights_t max_base, max_inheriting;
__wasi_errno_t error;
(void)poolfd;
if (INET4 != af) {
return __WASI_EAFNOSUPPORT;
}
tcp_or_udp = SOCKET_DGRAM == socktype ? 0 : 1;
ret = os_socket_create(&sock, tcp_or_udp);
if (ret == BHT_ERROR) {
return convert_errno(errno);
}
error =
fd_determine_type_rights(sock, &wasi_type, &max_base, &max_inheriting);
if (error != __WASI_ESUCCESS) {
os_socket_close(sock);
return error;
}
if (SOCKET_DGRAM == socktype) {
assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM);
}
else {
assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM);
}
// TODO: base rights and inheriting rights ?
error = fd_table_insert_fd(curfds, sock, wasi_type, max_base,
max_inheriting, sockfd);
if (error != __WASI_ESUCCESS) {
os_socket_close(sock);
return error;
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_recv(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, const __wasi_iovec_t *ri_data, size_t ri_data_len,
__wasi_riflags_t ri_flags, size_t *ro_datalen, __wasi_roflags_t *ro_flags)
__wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len)
{
// Convert input to msghdr.
struct msghdr hdr = {
.msg_iov = (struct iovec *)ri_data,
.msg_iovlen = ri_data_len,
};
int nflags = 0;
if ((ri_flags & __WASI_SOCK_RECV_PEEK) != 0)
nflags |= MSG_PEEK;
if ((ri_flags & __WASI_SOCK_RECV_WAITALL) != 0)
nflags |= MSG_WAITALL;
struct fd_object *fo;
__wasi_errno_t error =
fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
if (error != 0) {
return error;
}
ssize_t datalen = recvmsg(fd_number(fo), &hdr, nflags);
ret = os_socket_recv(fd_number(fo), buf, buf_len);
fd_object_release(fo);
if (datalen < 0) {
if (ret == BHT_ERROR) {
return convert_errno(errno);
}
// Convert msghdr to output.
*ro_datalen = (size_t)datalen;
*ro_flags = 0;
if ((hdr.msg_flags & MSG_TRUNC) != 0)
*ro_flags |= __WASI_SOCK_RECV_DATA_TRUNCATED;
return 0;
*recv_len = (size_t)ret;
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -2760,34 +2963,25 @@ wasmtime_ssp_sock_send(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, const __wasi_ciovec_t *si_data, size_t si_data_len,
__wasi_siflags_t si_flags, size_t *so_datalen) NO_LOCK_ANALYSIS
__wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len)
{
// Convert input to msghdr.
struct msghdr hdr = {
.msg_iov = (struct iovec *)si_data,
.msg_iovlen = si_data_len,
};
// Attach file descriptors if present.
__wasi_errno_t error;
// Send message.
struct fd_object *fo;
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
if (error != 0)
goto out;
ssize_t len = sendmsg(fd_number(fo), &hdr, 0);
fd_object_release(fo);
if (len < 0) {
error = convert_errno(errno);
}
else {
*so_datalen = (size_t)len;
if (error != 0) {
return error;
}
out:
return error;
ret = os_socket_send(fd_number(fo), buf, buf_len);
fd_object_release(fo);
if (ret == BHT_ERROR) {
return convert_errno(errno);
}
*sent_len = (size_t)ret;
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -2795,34 +2989,22 @@ wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, __wasi_sdflags_t how)
__wasi_fd_t sock)
{
int nhow;
switch (how) {
case __WASI_SHUT_RD:
nhow = SHUT_RD;
break;
case __WASI_SHUT_WR:
nhow = SHUT_WR;
break;
case __WASI_SHUT_RD | __WASI_SHUT_WR:
nhow = SHUT_RDWR;
break;
default:
return __WASI_EINVAL;
}
struct fd_object *fo;
__wasi_errno_t error =
fd_object_get(curfds, &fo, sock, __WASI_RIGHT_SOCK_SHUTDOWN, 0);
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
int ret = shutdown(fd_number(fo), nhow);
ret = os_socket_shutdown(fd_number(fo));
fd_object_release(fo);
if (ret < 0)
if (ret == BHT_ERROR)
return convert_errno(errno);
return 0;
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -2943,3 +3125,88 @@ fd_prestats_destroy(struct fd_prestats *pt)
wasm_runtime_free(pt->prestats);
}
}
bool
addr_pool_init(struct addr_pool *addr_pool)
{
addr_pool->next = NULL;
addr_pool->addr = 0;
addr_pool->mask = 0;
return true;
}
bool
addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
{
struct addr_pool *cur = addr_pool;
struct addr_pool *next;
if (!addr_pool) {
return false;
}
if (!(next = wasm_runtime_malloc(sizeof(struct addr_pool)))) {
return false;
}
next->next = NULL;
next->mask = mask;
if (os_socket_inet_network(addr, &next->addr) != BHT_OK) {
wasm_runtime_free(next);
return false;
}
/* attach with */
while (cur->next) {
cur = cur->next;
}
cur->next = next;
return true;
}
static bool
compare_address(const struct addr_pool *addr_pool_entry, const char *addr)
{
/* host order */
uint32 target;
uint32 address = addr_pool_entry->addr;
/* 0.0.0.0 means any address */
if (0 == address) {
return true;
}
if (os_socket_inet_network(addr, &target) != BHT_OK) {
return false;
}
uint32 mask = addr_pool_entry->mask;
uint32 first_address = address & mask;
uint32 last_address = address | (~mask);
return first_address <= target && target <= last_address;
}
bool
addr_pool_search(struct addr_pool *addr_pool, const char *addr)
{
struct addr_pool *cur = addr_pool->next;
while (cur) {
if (compare_address(cur, addr))
return true;
cur = cur->next;
}
return false;
}
void
addr_pool_destroy(struct addr_pool *addr_pool)
{
struct addr_pool *cur = addr_pool->next;
while (cur) {
struct addr_pool *next = cur->next;
wasm_runtime_free(cur);
cur = next;
}
}

View File

@ -46,6 +46,13 @@ struct argv_environ_values {
size_t environ_count;
};
struct addr_pool {
struct addr_pool *next;
/* addr and mask in host order */
uint32 addr;
uint8 mask;
};
bool
fd_table_init(struct fd_table *);
bool
@ -66,4 +73,13 @@ fd_table_destroy(struct fd_table *ft);
void
fd_prestats_destroy(struct fd_prestats *pt);
bool
addr_pool_init(struct addr_pool *);
bool
addr_pool_insert(struct addr_pool *, const char *, uint8 mask);
bool
addr_pool_search(struct addr_pool *, const char *);
void
addr_pool_destroy(struct addr_pool *);
#endif

View File

@ -32,7 +32,13 @@
__WASI_RIGHT_FD_FILESTAT_SET_SIZE | \
__WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \
__WASI_RIGHT_PATH_REMOVE_DIRECTORY | \
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_SHUTDOWN)
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
__WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
__WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
__WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
__WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
__WASI_RIGHT_SOCK_SEND_TO)
// Block and character device interaction is outside the scope of
// CloudABI. Simply allow everything.
@ -71,10 +77,15 @@
#define RIGHTS_REGULAR_FILE_INHERITING 0
// Operations that apply to sockets and socket pairs.
#define RIGHTS_SOCKET_BASE \
(__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
__WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_SHUTDOWN)
#define RIGHTS_SOCKET_BASE \
(__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
__WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
__WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
__WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
__WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
__WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
__WASI_RIGHT_SOCK_SEND_TO)
#define RIGHTS_SOCKET_INHERITING RIGHTS_ALL
// Operations that apply to TTYs.

View File

@ -362,6 +362,9 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasm_module_t module;
wasm_module_inst_t new_module_inst;
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx;
#endif
WASMExecEnv *new_exec_env;
uint32 aux_stack_start, aux_stack_size;
uint32 stack_size = 8192;
@ -393,6 +396,11 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
wasm_runtime_set_custom_data_internal(
new_module_inst, wasm_runtime_get_custom_data(module_inst));
#if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif
new_exec_env = wasm_exec_env_create_internal(new_module_inst,
exec_env->wasm_stack_size);
if (!new_exec_env)

View File

@ -8,6 +8,16 @@
#include <arpa/inet.h>
static void
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr_in *out)
{
assert(textual);
out->sin_family = AF_INET;
out->sin_port = htons(port);
out->sin_addr.s_addr = inet_addr(textual);
}
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
{
@ -113,6 +123,23 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
return BHT_OK;
}
int
os_socket_connect(bh_socket_t socket, const char *addr, int port)
{
struct sockaddr_in addr_in = { 0 };
socklen_t addr_len = sizeof(struct sockaddr_in);
int ret = 0;
textual_addr_to_sockaddr(addr, port, &addr_in);
ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
if (ret == -1) {
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
{
@ -138,3 +165,13 @@ os_socket_shutdown(bh_socket_t socket)
shutdown(socket, O_RDWR);
return BHT_OK;
}
int
os_socket_inet_network(const char *cp, uint32 *out)
{
if (!cp)
return BHT_ERROR;
*out = inet_network(cp);
return BHT_OK;
}

View File

@ -265,6 +265,17 @@ int
os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
unsigned int *addrlen);
/**
* initiate a connection on a socket
*
* @param socket the socket to connect with
* @param addr the ip address, only IPv4 supported currently
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_connect(bh_socket_t socket, const char *addr, int port);
/**
* Blocking receive message from a socket.
*
@ -310,6 +321,18 @@ os_socket_close(bh_socket_t socket);
int
os_socket_shutdown(bh_socket_t socket);
/**
* converts cp into a number in host byte order suitable for use as
* an Internet network address
*
* @param cp a string in IPv4 numbers-and-dots notation
*
* @return On success, the converted address is returned.
* If the input is invalid, -1 is returned
*/
int
os_socket_inet_network(const char *cp, uint32 *out);
#ifdef __cplusplus
}
#endif

View File

@ -227,4 +227,72 @@ shutdown(int sockfd, int how)
return ret;
}
int
os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
unsigned int *addrlen)
{
errno = ENOSYS;
return -1;
}
int
os_socket_bind(bh_socket_t socket, const char *host, int *port)
{
errno = ENOSYS;
return -1;
}
int
os_socket_close(bh_socket_t socket)
{
errno = ENOSYS;
return -1;
}
int
os_socket_connect(bh_socket_t socket, const char *addr, int port)
{}
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
{
errno = ENOSYS;
return -1;
}
int
os_socket_inet_network(const char *cp, uint32 *out)
{
errno = ENOSYS;
return -1;
}
int
os_socket_listen(bh_socket_t socket, int max_client)
{
errno = ENOSYS;
return -1;
}
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
{
errno = ENOSYS;
return -1;
}
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{
errno = ENOSYS;
return -1;
}
int
os_socket_shutdown(bh_socket_t socket)
{
errno = ENOSYS;
return -1;
}
#endif

View File

@ -152,3 +152,13 @@ os_socket_shutdown(bh_socket_t socket)
shutdown(socket, SD_BOTH);
return BHT_OK;
}
int
os_socket_inet_network(const char *cp, uint32 *out)
{
if (!cp)
return BHT_ERROR;
*out = inet_addr(cp);
return BHT_OK;
}

View File

@ -38,15 +38,21 @@ extend_vector(Vector *vector, size_t length)
return false;
}
if (vector->lock)
os_mutex_lock(vector->lock);
memcpy(data, vector->data, vector->size_elem * vector->max_elems);
BH_FREE(vector->data);
vector->data = data;
vector->max_elems = length;
if (vector->lock)
os_mutex_unlock(vector->lock);
return true;
}
bool
bh_vector_init(Vector *vector, size_t init_length, size_t size_elem)
bh_vector_init(Vector *vector, size_t init_length, size_t size_elem,
bool use_lock)
{
if (!vector) {
LOG_ERROR("Init vector failed: vector is NULL.\n");
@ -65,6 +71,26 @@ bh_vector_init(Vector *vector, size_t init_length, size_t size_elem)
vector->size_elem = size_elem;
vector->max_elems = init_length;
vector->num_elems = 0;
vector->lock = NULL;
if (use_lock) {
if (!(vector->lock = BH_MALLOC(sizeof(korp_mutex)))) {
LOG_ERROR("Init vector failed: alloc locker failed.\n");
bh_vector_destroy(vector);
return false;
}
if (BHT_OK != os_mutex_init(vector->lock)) {
LOG_ERROR("Init vector failed: init locker failed.\n");
BH_FREE(vector->lock);
vector->lock = NULL;
bh_vector_destroy(vector);
return false;
}
}
return true;
}
@ -81,13 +107,17 @@ bh_vector_set(Vector *vector, uint32 index, const void *elem_buf)
return false;
}
if (vector->lock)
os_mutex_lock(vector->lock);
memcpy(vector->data + vector->size_elem * index, elem_buf,
vector->size_elem);
if (vector->lock)
os_mutex_unlock(vector->lock);
return true;
}
bool
bh_vector_get(const Vector *vector, uint32 index, void *elem_buf)
bh_vector_get(Vector *vector, uint32 index, void *elem_buf)
{
if (!vector || !elem_buf) {
LOG_ERROR("Get vector elem failed: vector or elem buf is NULL.\n");
@ -99,8 +129,12 @@ bh_vector_get(const Vector *vector, uint32 index, void *elem_buf)
return false;
}
if (vector->lock)
os_mutex_lock(vector->lock);
memcpy(elem_buf, vector->data + vector->size_elem * index,
vector->size_elem);
if (vector->lock)
os_mutex_unlock(vector->lock);
return true;
}
@ -125,6 +159,8 @@ bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf)
return false;
}
if (vector->lock)
os_mutex_lock(vector->lock);
p = vector->data + vector->size_elem * vector->num_elems;
for (i = vector->num_elems - 1; i > index; i--) {
memcpy(p, p - vector->size_elem, vector->size_elem);
@ -133,6 +169,8 @@ bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf)
memcpy(p, elem_buf, vector->size_elem);
vector->num_elems++;
if (vector->lock)
os_mutex_unlock(vector->lock);
return true;
}
@ -149,9 +187,13 @@ bh_vector_append(Vector *vector, const void *elem_buf)
return false;
}
if (vector->lock)
os_mutex_lock(vector->lock);
memcpy(vector->data + vector->size_elem * vector->num_elems, elem_buf,
vector->size_elem);
vector->num_elems++;
if (vector->lock)
os_mutex_unlock(vector->lock);
return true;
}
@ -171,6 +213,8 @@ bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
return false;
}
if (vector->lock)
os_mutex_lock(vector->lock);
p = vector->data + vector->size_elem * index;
if (old_elem_buf) {
@ -183,6 +227,8 @@ bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
}
vector->num_elems--;
if (vector->lock)
os_mutex_unlock(vector->lock);
return true;
}
@ -202,6 +248,12 @@ bh_vector_destroy(Vector *vector)
if (vector->data)
BH_FREE(vector->data);
if (vector->lock) {
os_mutex_destroy(vector->lock);
BH_FREE(vector->lock);
}
memset(vector, 0, sizeof(Vector));
return true;
}

View File

@ -23,6 +23,7 @@ typedef struct Vector {
size_t num_elems;
/* size of each element */
size_t size_elem;
void *lock;
} Vector;
/**
@ -35,7 +36,8 @@ typedef struct Vector {
* @return true if success, false otherwise
*/
bool
bh_vector_init(Vector *vector, size_t init_length, size_t size_elem);
bh_vector_init(Vector *vector, size_t init_length, size_t size_elem,
bool use_lock);
/**
* Set element of vector
@ -60,7 +62,7 @@ bh_vector_set(Vector *vector, uint32 index, const void *elem_buf);
* @return true if success, false otherwise
*/
bool
bh_vector_get(const Vector *vector, uint32 index, void *elem_buf);
bh_vector_get(Vector *vector, uint32 index, void *elem_buf);
/**
* Insert element of vector

View File

@ -51,12 +51,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
- **WAMR_BUILD_LIBC_UVWASI**=1/0 (Experiment), build the [WASI](https://github.com/WebAssembly/WASI) libc subset for WASM app based on [uvwasi](https://github.com/nodejs/uvwasi) implementation, default to disable if not set
> Note: for platform which doesn't support **WAMR_BUILD_LIBC_WASI**, e.g. Windows, developer can try using **WAMR_BUILD_LIBC_UVWASI**. And the uvwasi source code must be cloned under core/deps:
>
> ```bash
> cd <WAMR-ROOT>/core/deps
> git clone https://github.com/nodejs/uvwasi.git
> ```
> Note: for platform which doesn't support **WAMR_BUILD_LIBC_WASI**, e.g. Windows, developer can try using **WAMR_BUILD_LIBC_UVWASI**.
#### **Enable Multi-Module feature**
@ -297,9 +292,6 @@ Make sure `MSVC` and `cmake` are installed and available in the command line env
Then build the source codes:
``` Bash
cd core/deps/
git clone https://github.com/nodejs/uvwasi.git
cd product-mini/platforms/windows/
mkdir build
cd build
@ -335,8 +327,8 @@ pacman -R cmake
pacman -S mingw-w64-x86_64-cmake
```
Then follow the build instructions for Windows above, minus cloning uvwasi and
adding the following arguments for cmake:
Then follow the build instructions for Windows above, and add the following
arguments for cmake:
```Bash
cmake .. -G"Unix Makefiles" \

View File

@ -1,9 +1,31 @@
Embedding WAMR guideline
=====================================
**Note**: All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files.
## Embed WAMR into developer's project
WAMR is designed to be easy embeddable in any project, a typical way of building WAMR is to use cmake, developer can configure features by setting cmake variables and then include the script `runtime_lib.cmake` under folder [build-scripts](../build-scripts) in his CMakeList.txt, for example:
``` cmake
set (WAMR_BUILD_PLATFORM "linux")
set (WAMR_BUILD_TARGET "X86_64")
set (WAMR_BUILD_INTERP 1)
set (WAMR_BUILD_FAST_INTERP 1)
set (WAMR_BUILD_AOT 1)
set (WAMR_BUILD_LIBC_BUILTIN 1)
set (WAMR_BUILD_LIBC_WASI 1)
set (WAMR_BUILD_SIMD 1)
set (WAMR_ROOT_DIR path/to/wamr/root)
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
target_link_libraries (your_project vmlib)
```
Examples can be found in [CMakeLists.txt of linux platform](../product-mini/platforms/linux/CMakeLists.txt) and [other platforms](../product-mini/platforms). The available features to configure can be found in [Build WAMR vmcore](./build_wamr.md#wamr-vmcore-cmake-building-configurations).
Developer can also use Makefile to embed WAMR, by defining macros and including directories, and adding the source files, examples can be found in [makefile of alios-things platform](../product-mini/platforms/alios-things/aos.mk) and [makefile of nuttx platform](../product-mini/platforms/nuttx/wamr.mk).
## The runtime initialization
``` C

66
doc/socket_api.md Normal file
View File

@ -0,0 +1,66 @@
# How to use Berkeley/Posix Socket APIs in WebAssembly
**_Berkeley sockets_** usually means an API for Internet sockets and Unix domain
sockets. A socket is an abstract representation of the local endpoint of a
network communication path.
Currently, WAMR supports a limit set of all well-known functions:
`accept()`, `bind()`, `connect()`, `listen()`, `recv()`, `send()`, `shutdown()`
and `socket()`. Users can call those functions in WebAssembly code directly.
Those WebAssembly socket calls will be dispatched to the imported
functions and eventually will be implemented by host socket APIs.
This document introduces a way to support _Berkeley/Posix Socket APIs_ in
WebAssembly code.
## Patch the native code
The first step is to include a header file of the WAMR socket extension in the
native source code.
```c
#ifdef __wasi__
#include <wasi_socket_ext.h>
#endif
```
`__wasi__` is a Marco defined by WASI. The host compiler will not enable it.
## CMake files
It is recommended that the project should use CMake as its build system. Use
[_wasi-sdk_](https://github.com/WebAssembly/wasi-sdk)
as a toolchain to compile C/C++ to WebAssembly
```bash
$ cmake -DWASI_SDK_PREFIX=${WASI_SDK_DIR}
-DCMAKE_TOOLCHAIN_FILE=${WASI_TOOLCHAIN_FILE}
-DCMAKE_SYSROOT=${WASI_SYS_ROOT}
..
```
In the *CMakeLists.txt*, include an extension of socket support and link with it.
```cmake
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake)
add_executable(socket_example tcp_server.c)
target_link_libraries(socket_example socket_wasi_ext)
```
Now, the native code with socket APIs is ready for compilation.
## Run with iwasm
If having the _.wasm_, the last step is to run it with _iwasm_.
The _iwasm_ should be compiled with `WAMR_BUILD_LIBC_WASI=1`. By default, it is
enabled.
_iwasm_ accepts address ranges via an option, `--addr-pool`, to implement
the capability control. All IP address the WebAssebmly application may need to `bind()` or `connect()` should be announced first. Every IP address should be in CIRD notation.
```bash
$ iwasm --addr-pool=1.2.3.4/15,2.3.4.6/16 socket_example.wasm
```
Refer to [socket api sample](../samples/socket-api) for more details.

View File

@ -3,24 +3,42 @@
All samples come from the commit 340fd9528cc3b26d22fe30ee1628c8c3f2b8c53b
of [wasm-c-api](https://github.com/WebAssembly/wasm-c-api).
Developer can learn these *APIs* from
Developer can learn these _APIs_ from
[wasm.h](https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h).
And here are [examples](https://github.com/WebAssembly/wasm-c-api/tree/master/example) which
are helpful.
## FYI
- The thread model of _wasm_c_api_ is
- An `wasm_engine_t` instance may only be created once per process
- Every `wasm_store_t` and its objects may only be accessed in a single thread
- `wasm_engine_new`, `wasm_engine_new_with_config`, `wasm_engine_new_with_args`,
`wasm_engine_delete`should be called in a thread-safe environment. Such
behaviors are not recommended, and please make sure an appropriate calling
sequence if it has to be.
- call `wasm_engine_new` and `wasm_engine_delete` in different threads
- call `wasm_engine_new` or `wasm_engine_delete` multiple times in
different threads
## unspported list
Currently WAMR supports most of the APIs, the unsupported APIs are listed as below:
- References
``` c
```c
WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*);
WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*);
```
- Several Module APIs
``` c
```c
WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
```
@ -30,12 +48,12 @@ by host-side function callings.
- Table Grow APIs
``` c
```c
WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init);
```
- Memory Grow APIs
``` c
```c
WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
```

View File

@ -16,8 +16,6 @@
static int app_argc;
static char **app_argv;
#define MODULE_PATH ("--module-path=")
/* clang-format off */
static int
print_help()
@ -41,6 +39,10 @@ print_help()
printf(" --dir=<dir> Grant wasi access to the given host directories\n");
printf(" to the program, for example:\n");
printf(" --dir=<dir1> --dir=<dir2>\n");
printf(" --addr-pool= Grant wasi access to the given network addresses in\n");
printf(" CIRD notation to the program, seperated with ',',\n");
printf(" for example:\n");
printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n");
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
printf(" --module-path= Indicate a module search path. default is current\n"
@ -244,6 +246,8 @@ main(int argc, char *argv[])
uint32 dir_list_size = 0;
const char *env_list[8] = { NULL };
uint32 env_list_size = 0;
const char *addr_pool[8] = { NULL };
uint32 addr_pool_size = 0;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
char *ip_addr = NULL;
@ -312,9 +316,30 @@ main(int argc, char *argv[])
return print_help();
}
}
/* TODO: parse the configuration file via --addr-pool-file */
else if (!strncmp(argv[0], "--addr-pool=", strlen("--addr-pool="))) {
/* like: --addr-pool=100.200.244.255/30 */
char *token = NULL;
if ('\0' == argv[0][12])
return print_help();
token = strtok(argv[0] + strlen("--addr-pool="), ",");
while (token) {
if (addr_pool_size >= sizeof(addr_pool) / sizeof(char *)) {
printf("Only allow max address number %d\n",
(int)(sizeof(addr_pool) / sizeof(char *)));
return -1;
}
addr_pool[addr_pool_size++] = token;
token = strtok(NULL, ";");
}
}
#endif /* WASM_ENABLE_LIBC_WASI */
#if WASM_ENABLE_MULTI_MODULE != 0
else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) {
else if (!strncmp(argv[0],
"--module-path=", strlen("--module-path="))) {
module_search_path = handle_module_path(argv[0]);
if (!strlen(module_search_path)) {
return print_help();
@ -422,6 +447,8 @@ main(int argc, char *argv[])
#if WASM_ENABLE_LIBC_WASI != 0
wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0,
env_list, env_list_size, argv, argc);
wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size);
#endif
/* instantiate the module */

View File

@ -103,7 +103,8 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN -D_WINSOCK_DEPRECATED_NO_WARNINGS")
#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS")
if (NOT MINGW)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")

View File

@ -0,0 +1,162 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required(VERSION 2.8...3.18)
project(socket_api_sample)
#######################################
## Detect toolchain
#######################################
message(CHECK_START "Detecting WASI-SDK at /opt/wasi-sdk")
if(NOT (DEFINED WASI_SDK_DIR OR DEFINED CACHE{WASI_SDK_DIR}))
find_path(WASI_SDK_PARENT
wasi-sdk
PATHS /opt
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(WASI_SDK_PARENT)
set(WASI_SDK_DIR ${WASI_SDK_PARENT}/wasi-sdk)
endif()
endif()
if(WASI_SDK_DIR)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
if(NOT EXISTS ${WASI_SDK_DIR})
message(FATAL_ERROR "Please install WASI-SDK under /opt/wasi-sdk")
endif()
message(CHECK_START "Detecting WASI_TOOLCHAIN_FILE at ${WASI_SDK_DIR}")
find_file(WASI_TOOLCHAIN_FILE
wasi-sdk.cmake
PATHS "${WASI_SDK_DIR}/share/cmake"
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(WASI_TOOLCHAIN_FILE)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
if(WASI_TOOLCHAIN_FILE-NOTFOUND)
message(FATAL_ERROR "Can not find wasi-sdk.cmake under ${WASI_SDK_DIR}")
endif()
message(CHECK_START "Detecting WASI_SYS_ROOT at ${WASI_SDK_DIR}")
find_path(WASI_SYS_ROOT
wasi-sysroot
PATHS "${WASI_SDK_DIR}/share"
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(WASI_SYS_ROOT)
message(CHECK_PASS "found")
set(WASI_SYS_ROOT ${WASI_SYS_ROOT}/wasi-sysroot)
else()
message(CHECK_FAIL "not found")
endif()
if(WASI_SYS_ROOT-NOTFOUND)
message(FATAL_ERROR "Can not find wasi-sysroot/ under ${WASI_SDK_DIR}")
endif()
message(STATUS "WASI_SDK_DIR is ${WASI_SDK_DIR}")
message(STATUS "WASI_TOOLCHAIN_FILE is ${WASI_TOOLCHAIN_FILE}")
message(STATUS "WASI_SYS_ROOT is ${WASI_SYS_ROOT}")
###############################################################
## Build socket applications of wasm version and native version
###############################################################
include(ExternalProject)
ExternalProject_Add(wasm-app
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/../../wamr-sdk/app/libc-builtin-sysroot/include/pthread.h
${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/inc
&& ${CMAKE_COMMAND}
-DWASI_SDK_PREFIX=${WASI_SDK_DIR}
-DCMAKE_TOOLCHAIN_FILE=${WASI_TOOLCHAIN_FILE}
-DCMAKE_SYSROOT=${WASI_SYS_ROOT}
${CMAKE_CURRENT_SOURCE_DIR}/wasm-src
BUILD_COMMAND ${CMAKE_COMMAND} --build .
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy
tcp_client.wasm ${CMAKE_CURRENT_SOURCE_DIR}/build
tcp_server.wasm ${CMAKE_CURRENT_SOURCE_DIR}/build
tcp_client.wasm.dump ${CMAKE_CURRENT_SOURCE_DIR}/build
tcp_server.wasm.dump ${CMAKE_CURRENT_SOURCE_DIR}/build
)
add_executable(tcp_server ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/tcp_server.c)
target_link_libraries(tcp_server pthread)
add_executable(tcp_client ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/tcp_client.c)
############################################
## Build iwasm with wasi and pthread support
############################################
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
if (APPLE)
add_definitions(-DBH_PLATFORM_DARWIN)
endif ()
# Reset linker flags
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
# Set WAMR features
# 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")
else ()
# Build as X86_32 by default in 32-bit platform
set (WAMR_BUILD_TARGET "X86_32")
endif ()
endif ()
if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE Release)
endif ()
set(WAMR_BUILD_INTERP 1)
set(WAMR_BUILD_FAST_INTERP 1)
set(WAMR_BUILD_AOT 1)
set(WAMR_BUILD_JIT 0)
set(WAMR_BUILD_LIBC_BUILTIN 1)
set(WAMR_BUILD_LIBC_WASI 1)
set(WAMR_BUILD_LIB_PTHREAD 1)
# compiling and linking flags
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -fPIE")
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")
# build vmlib static lib
set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
# build iwasm
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
set (RUNTIME_SOURCE_ALL
${CMAKE_CURRENT_LIST_DIR}/../../product-mini/platforms/linux/main.c
${UNCOMMON_SHARED_SOURCE}
)
add_executable (iwasm ${RUNTIME_SOURCE_ALL})
target_link_libraries(iwasm vmlib -lpthread -lm)

View File

@ -0,0 +1,57 @@
"socket-api" sample introduction
================================
This sample demonstrates how to use WAMR socket-api to develop wasm network applications.
Two wasm applications are provided: tcp-server and tcp-client, and this sample demonstrates
how they communicate with each other.
## Preparation
Please install WASI SDK, download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`.
And install wabt, download the [wabt release](https://github.com/WebAssembly/wabt/releases) and extract the archive to default path `/opt/wabt`
## Build the sample
```bash
mkdir build
cd build
cmake ..
make
```
The file `tcp_server.wasm`, `tcp_client.wasm` and `iwasm` will be created.
And also file `tcp_server` and `tcp_client` of native version are created.
Note that iwasm is built with libc-wasi and lib-pthread enabled.
## Run workload
Start the tcp server, which opens port 1234 and waits for clients to connect.
```bash
cd build
./iwasm --addr-pool=0.0.0.0/15 tcp_server.wasm
```
Start the tcp client, which connects the server and receives message.
```bash
cd build
./iwasm --addr-pool=127.0.0.1/15 tcp_client.wasm
```
The output of client is like:
```bash
[Client] Create socket
[Client] Connect socket
[Client] Client receive
[Client] 115 bytes received:
Buffer recieved:
Say Hi from the Server
Say Hi from the Server
Say Hi from the Server
Say Hi from the Server
Say Hi from the Server
[Client] BYE
```
Refer to [socket api document](../../doc/socket_api.md) for more details.

View File

@ -0,0 +1,80 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required(VERSION 2.8...3.18)
project(socket_api_sample_wasm_app)
message(CHECK_START "Detecting WABT")
if(NOT (DEFINED WABT_DIR OR DEFINED CACHE{WABT_DIR}))
find_path(WABT_DIR
wabt
PATHS /opt
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(DEFINED WABT_DIR)
set(WABT_DIR ${WABT_DIR}/wabt)
endif()
endif()
if(WABT_DIR)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
message(CHECK_START "Detecting WASM_OBJDUMP at ${WABT_DIR}")
find_program(WASM_OBJDUMP
wasm-objdump
PATHS "${WABT_DIR}/bin"
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(WASM_OBJDUMP)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
set(SRC ${CMAKE_CURRENT_SOURCE_DIR})
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake)
function(COMPILE_WITH_CLANG SOURCE_FILE)
get_filename_component(FILE_NAME ${SOURCE_FILE} NAME_WLE)
set(WASM_MODULE ${FILE_NAME}.wasm)
set(MAIN_TARGET_NAME MODULE_${FILE_NAME})
add_executable(${MAIN_TARGET_NAME} ${SOURCE_FILE})
set_target_properties(${MAIN_TARGET_NAME} PROPERTIES OUTPUT_NAME ${WASM_MODULE})
target_include_directories(${MAIN_TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/inc)
target_compile_options(${MAIN_TARGET_NAME} INTERFACE -pthread)
target_link_libraries(${MAIN_TARGET_NAME} socket_wasi_ext)
target_link_options(${MAIN_TARGET_NAME} PRIVATE
LINKER:--export=__heap_base
LINKER:--export=__data_end
LINKER:--shared-memory,--max-memory=196608
LINKER:--no-check-features
LINKER:--allow-undefined
)
if(EXISTS ${WASM_OBJDUMP})
message(STATUS "Dumping ${WASM_MODULE}...")
set(WASM_DUMP ${WASM_MODULE}.dump)
set(DUMP_TARGET_NAME DUMP_${FILE_NAME})
add_custom_command(OUTPUT ${WASM_DUMP}
COMMAND ${WASM_OBJDUMP} -dx ${WASM_MODULE} > ${WASM_DUMP}
COMMENT "Dumping ${WASM_MODULE}..."
DEPENDS ${MAIN_TARGET_NAME}
)
add_custom_target(${DUMP_TARGET_NAME} ALL
DEPENDS ${WASM_DUMP}
)
endif()
endfunction()
compile_with_clang(tcp_server.c)
compile_with_clang(tcp_client.c)

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifdef __wasi__
#include <wasi_socket_ext.h>
#endif
int
main(int argc, char *argv[])
{
int socket_fd, ret, total_size = 0;
char buffer[1024] = { 0 };
struct sockaddr_in server_address = { 0 };
printf("[Client] Create socket\n");
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1) {
perror("Create socket failed");
return EXIT_FAILURE;
}
/* 127.0.0.1:1234 */
server_address.sin_family = AF_INET;
server_address.sin_port = htons(1234);
server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
printf("[Client] Connect socket\n");
if (connect(socket_fd, (struct sockaddr *)&server_address,
sizeof(server_address))
== -1) {
perror("Connect failed");
close(socket_fd);
return EXIT_FAILURE;
}
printf("[Client] Client receive\n");
while (1) {
ret = recv(socket_fd, buffer + total_size, sizeof(buffer) - total_size,
0);
if (ret <= 0)
break;
total_size += ret;
}
printf("[Client] %d bytes received:\n", total_size);
if (total_size > 0) {
printf("Buffer recieved:\n%s\n", buffer);
}
close(socket_fd);
printf("[Client] BYE \n");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifdef __wasi__
#include <wasi_socket_ext.h>
#endif
#define WORKER_NUM 5
void *
run(void *arg)
{
const char *message = "Say Hi from the Server\n";
int new_socket = *(int *)arg;
int i;
printf("[Server] Communicate with the new connection #%u @ %p ..\n",
new_socket, (void *)(uintptr_t)pthread_self());
for (i = 0; i < 5; i++) {
if (send(new_socket, message, strlen(message), 0) < 0) {
perror("Send failed");
break;
}
}
printf("[Server] Shuting down the new connection #%u ..\n", new_socket);
shutdown(new_socket, SHUT_RDWR);
return NULL;
}
int
main(int argc, char *argv[])
{
int socket_fd = -1, addrlen = 0;
struct sockaddr_in addr = { 0 };
unsigned connections = 0;
pthread_t workers[WORKER_NUM] = { 0 };
int client_sock_fds[WORKER_NUM] = { 0 };
printf("[Server] Create socket\n");
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0) {
perror("Create socket failed");
goto fail;
}
/* 0.0.0.0:1234 */
addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("[Server] Bind socket\n");
addrlen = sizeof(addr);
if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) {
perror("Bind failed");
goto fail;
}
printf("[Server] Listening on socket\n");
if (listen(socket_fd, 3) < 0) {
perror("Listen failed");
goto fail;
}
printf("[Server] Wait for clients to connect ..\n");
while (connections < WORKER_NUM) {
client_sock_fds[connections] =
accept(socket_fd, (struct sockaddr *)&addr, (socklen_t *)&addrlen);
if (client_sock_fds[connections] < 0) {
perror("Accept failed");
break;
}
printf("[Server] Client connected\n");
if (pthread_create(&workers[connections], NULL, run,
&client_sock_fds[connections])) {
perror("Create a worker thread failed");
shutdown(client_sock_fds[connections], SHUT_RDWR);
break;
}
connections++;
}
if (connections == WORKER_NUM) {
printf("[Server] Achieve maximum amount of connections\n");
}
for (int i = 0; i < WORKER_NUM; i++) {
pthread_join(workers[i], NULL);
}
printf("[Server] Shuting down ..\n");
shutdown(socket_fd, SHUT_RDWR);
sleep(3);
printf("[Server] BYE \n");
return EXIT_SUCCESS;
fail:
printf("[Server] Shuting down ..\n");
if (socket_fd >= 0)
close(socket_fd);
sleep(3);
return EXIT_FAILURE;
}

View File

@ -34,7 +34,7 @@ void check(bool success) {
void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) {
wasm_val_t r[] = {WASM_INIT_VAL};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t), NULL};
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
if (wasm_func_call(func, &args_, &results) || r[0].of.i32 != expected) {
printf("> Error on result\n");
@ -57,7 +57,7 @@ void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected
}
void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) {
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t), NULL};
wasm_val_vec_t results = WASM_EMPTY_VEC;
if (wasm_func_call(func, &args_, &results)) {
printf("> Error on result, expected empty\n");
@ -72,7 +72,7 @@ void check_ok2(wasm_func_t* func, int32_t arg1, int32_t arg2) {
void check_trap(wasm_func_t* func, int i, wasm_val_t args[]) {
wasm_val_t r[] = {WASM_INIT_VAL};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t), NULL};
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
own wasm_trap_t* trap = wasm_func_call(func, &args_, &results);
if (! trap) {

View File

@ -15,6 +15,10 @@ void print_mutability(wasm_mutability_t mut) {
}
void print_limits(const wasm_limits_t* limits) {
if (!limits) {
printf("unknown limits");
return;
}
printf("%ud", limits->min);
if (limits->max < wasm_limits_max_default) printf(" %ud", limits->max);
}
@ -43,6 +47,10 @@ void print_valtypes(const wasm_valtype_vec_t* types) {
}
void print_externtype(const wasm_externtype_t* type) {
if (!type) {
printf("unknown extern type");
return;
}
switch (wasm_externtype_kind(type)) {
case WASM_EXTERN_FUNC: {
const wasm_functype_t* functype =
@ -78,6 +86,10 @@ void print_externtype(const wasm_externtype_t* type) {
}
void print_name(const wasm_name_t* name) {
if (!name) {
printf("unknown name");
return;
}
printf("\"%.*s\"", (int)name->size, name->data);
}

View File

@ -25,8 +25,9 @@ g++ -O3 -msse2 -msse3 -msse4 -o ${OUT_DIR}/gcc-loops_native gcc-loops.cpp
echo "Build gcc-loops with em++ .."
em++ -O3 -s STANDALONE_WASM=1 -msimd128 \
-s INITIAL_MEMORY=1048576 \
-s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=32768 \
-s TOTAL_STACK=32768 \
-s "EXPORTED_FUNCTIONS=['_main']" \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
-o ${OUT_DIR}/gcc-loops.wasm gcc-loops.cpp
echo "Compile gcc-loops.wasm to gcc-loops.aot"
@ -38,7 +39,7 @@ gcc -O3 -msse2 -msse3 -msse4 -o ${OUT_DIR}/quicksort_native quicksort.c
echo "Build quicksort with emcc .."
emcc -O3 -s STANDALONE_WASM=1 -msimd128 \
-s INITIAL_MEMORY=1048576 \
-s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=32768 \
-s TOTAL_STACK=32768 \
-s "EXPORTED_FUNCTIONS=['_main']" \
-o ${OUT_DIR}/quicksort.wasm quicksort.c
@ -52,7 +53,7 @@ g++ -O3 -msse2 -msse3 -msse4 -o ${OUT_DIR}/HashSet_native HashSet.cpp \
echo "Build HashSet with em++ .."
em++ -O3 -s STANDALONE_WASM=1 -msimd128 \
-s INITIAL_MEMORY=1048576 \
-s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=32768 \
-s TOTAL_STACK=32768 \
-s "EXPORTED_FUNCTIONS=['_main']" \
-o ${OUT_DIR}/HashSet.wasm HashSet.cpp
@ -65,7 +66,7 @@ gcc -O3 -msse2 -msse3 -msse4 -o ${OUT_DIR}/float-mm_native float-mm.c
echo "Build float-mm with emcc .."
emcc -O3 -s STANDALONE_WASM=1 -msimd128 \
-s INITIAL_MEMORY=1048576 \
-s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=32768 \
-s TOTAL_STACK=32768 \
-s "EXPORTED_FUNCTIONS=['_main']" \
-o ${OUT_DIR}/float-mm.wasm float-mm.c

View File

@ -181,7 +181,13 @@ include (${SHARED_DIR}/utils/shared_utils.cmake)
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
if (NOT MINGW)
if (NOT MSVC)
include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
else()
include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
endif()
endif()
include (${IWASM_DIR}/libraries/lib-pthread/lib_pthread.cmake)
include (${IWASM_DIR}/common/iwasm_common.cmake)
include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
@ -253,10 +259,13 @@ add_executable (wamrc main.c)
if (NOT MSVC)
target_link_libraries (wamrc aotclib vmlib LLVMDemangle ${LLVM_AVAILABLE_LIBS} ${lib_ubsan}
-lm -ldl -lpthread ${lib_lldb})
-lm -lpthread ${lib_lldb} ${UV_A_LIBS})
if (MINGW)
target_link_libraries (wamrc -lssp -lWs2_32)
else()
target_link_libraries (wamrc -ldl)
endif()
else()
target_link_libraries (wamrc aotclib vmlib ${lib_lldb} ${LLVM_AVAILABLE_LIBS} ${lib_ubsan})
target_link_libraries (wamrc aotclib vmlib ${lib_lldb} ${LLVM_AVAILABLE_LIBS} ${lib_ubsan}
${UV_A_LIBS})
endif()