From 2aaa42569eec9e255774643041135a2b593b533f Mon Sep 17 00:00:00 2001 From: wenyongh Date: Mon, 25 Nov 2019 22:26:51 +0800 Subject: [PATCH] Sync up with internal/feature --- README.md | 113 +- .../lib/native/libc/libc_builtin_wrapper.c | 1333 +++++++++++++++++ core/iwasm/lib/native/libc/wasm_libc.cmake | 2 +- .../native/libc}/wasmtime-wasi-c/LICENSE | 0 .../sandboxed-system-primitives/LICENSE | 0 .../include/LICENSE | 0 .../include/wasmtime_ssp.h | 0 .../sandboxed-system-primitives/src/LICENSE | 0 .../sandboxed-system-primitives/src/README.md | 0 .../sandboxed-system-primitives/src/config.h | 0 .../sandboxed-system-primitives/src/locking.h | 0 .../src/numeric_limits.h | 0 .../sandboxed-system-primitives/src/posix.c | 0 .../sandboxed-system-primitives/src/posix.h | 0 .../sandboxed-system-primitives/src/queue.h | 0 .../sandboxed-system-primitives/src/random.c | 0 .../sandboxed-system-primitives/src/random.h | 0 .../src/refcount.h | 0 .../sandboxed-system-primitives/src/rights.h | 0 .../sandboxed-system-primitives/src/signals.h | 0 .../sandboxed-system-primitives/src/str.c | 0 .../sandboxed-system-primitives/src/str.h | 0 .../native/libc}/wasmtime-wasi-c/wasi.cmake | 0 core/iwasm/products/darwin/CMakeLists.txt | 6 +- core/iwasm/products/darwin/main.c | 2 + core/iwasm/products/linux-sgx/CMakeLists.txt | 2 +- core/iwasm/products/linux/CMakeLists.txt | 2 +- core/iwasm/products/linux/main.c | 2 + core/iwasm/products/vxworks/CMakeLists.txt | 6 +- core/iwasm/products/vxworks/main.c | 2 + .../runtime/vmcore-wasm/wasm_application.c | 35 +- doc/build_wamr.md | 198 +++ doc/build_wamr_app.md | 182 +++ doc/export_native_api.md | 116 ++ doc/wamr_api.md | 118 +- test-tools/toolchain/sysroot/include/stdlib.h | 2 +- 36 files changed, 1947 insertions(+), 174 deletions(-) create mode 100644 core/iwasm/lib/native/libc/libc_builtin_wrapper.c rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/LICENSE (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h (100%) rename core/iwasm/{runtime => lib/native/libc}/wasmtime-wasi-c/wasi.cmake (100%) create mode 100644 doc/build_wamr.md create mode 100644 doc/build_wamr_app.md create mode 100644 doc/export_native_api.md diff --git a/README.md b/README.md index f52d4c2c8..f221c95e0 100644 --- a/README.md +++ b/README.md @@ -14,79 +14,114 @@ WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with Current Features of WAMR ========================= - WASM interpreter (AOT is planned) -- Supports for a subset of Libc API. -- Supports for [WASI API](https://github.com/WebAssembly/WASI) - Provides embedding C API - Provides a mechanism for exporting native API's to WASM applications -- Supports the programming of firmware apps in a large range of languages (C/C++/Java/Rust/Go/TypeScript etc.) -- App sandbox execution environment on embedded OS -- The purely asynchronized programming model -- Menu configuration for easy platform integration -- Supports micro-service and pub-sub event inter-app communication models -- Easy to extend to support remote FW application management from host or cloud +- Supports libc for WASM applications in two modes: the built-in libc subset for embedded environment and [WASI](https://github.com/WebAssembly/WASI) for standard libc +- The WASM application framework and asynchronized app programming model +- Supports for micro-service and pub-sub event inter-app communication models +- Supports remote WASM application management from either host or cloud +- Menu configuration for easy integration of application libraries Application framework architecture =================================== -By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains. +By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains. The WAMR has offered a comprehensive application framework for device and IoT usages. The framework solves many common requirements for building a real project: - Modular design for more language runtimes support - Inter application communication - Remote application management -- WASM APP programming model and API extension mechanism +- WASM APP programming model and API extension mechanism -Build WAMR Core and run WASM applications -================================================ +Build WAMR +========== -WAMR VM core (iwasm) can support building on different platforms: +## Build WAMR VM core + + +WAMR VM core (iwasm) can support building for different target platforms: - Linux - Zephyr - Mac - VxWorks - AliOS-Things -- Docker - Intel Software Guard Extention (SGX) -After building the iwasm, we can compile some basic WASM applications and run it from the WAMR core. As the WAMR core doesn't include the extended application library, your WASM applications can only use the [WAMR built-in APIs](./doc/wamr_api.md). +See [Build WAMR VM core](./doc/build_wamr.md) for the detailed instructions. -See the [doc/building.md](./doc/building.md) for the detailed instructions. +## Libc building options + +WAMR supports WASI for standard libc library as well as a [built-in libc subset](./doc/wamr_api.md) for tiny footprint. + +WASI is supported for following platforms and enabled by default building: +- Linux -Embed WAMR -=========== -WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product. +## Embed WAMR VM core -WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. +WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product. -See the [doc/embed_wamr.md](./doc/embed_wamr.md) for the details. +WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. See [Embed WAMR VM core](./doc/embed_wamr.md) for the details. -WAMR application programming library -=================================== +The WAMR application framework supports dynamically installing WASM application remotely by embedding the WAMR VM core. It can be used as reference for how to use the embedding APIs. + + +## Integrate WAMR application library + +The WAMR provides an application framework which supports event driven programming model as below: -WAMR defined event driven programming model: - Single thread per WASM app instance - App must implement system callbacks: on_init, on_destroy +Application programming API sets are available as below: -In general there are a few API classes for the WASM application programming: -- WAMR Built-in API: WAMR core provides a minimal libc API set for WASM APP -- WAMR application libraries: - - Timer - - Micro service (Request/Response) - - Pub/Sub - - Sensor - - Connection and data transmission - - 2D graphic UI (based on littlevgl) -- User extended native API: extend the native API to the WASM applications -- 3rd party libraries: Programmers can download any 3rd party C/C++ source code and build it together with the WASM APP code +- Timer +- Micro service (Request/Response) and Pub/Sub inter-app communication +- Sensor +- Connectivity and data transmission +- 2D graphic UI (based on littlevgl) -See the [doc/wamr_api.md](./doc/wamr_api.md) for the details. +See [WAMR application library](./doc/wamr_api.md) for the details. + +One WAMR runtime version can also select a subsets from the WAMR application library. Refer to the sample "simple" for how to integrate API sets into WAMR building. + + + +## Build WAMR with customized application library + +In general when you build a WAMR version for a specific project, you probably will create additional APIs for the applications. The APIs can be expansion or modification to the standard WAMR application library. + +The extended application library should be created in the folder {repo-root}/core/iwasm/lib/app-lib. See the [doc/export_native_api.md](./doc/export_native_api.md) for the details. + + + +# Create WASM application SDK + +When you ship your WAMR runtime with the products, you will need to distribute the associated WASM application SDK for the application developers to develop WASM applications for your products. At the most time, the WASM application SDK should have a version match with the runtime distribution. + + + +Typically there are a few components in a WASM APP SDK package: + +* **WASI-SDK**: only needed when WASI is enabled in the runtime. It can be a link to the WASI-SDK GitHub or the full offline copy. +* **sysroot** folder: only needed when WASI is not enabled in the runtime. copied from `{repo-root}/test-tools/toolchain/sysroot` +* **app-lib** folder: copied from `{repo-root}/core/iwasm/lib/app-lib` +* **cmake toolchain** file: copied from `{repo-root}/test-tools/toolchain/wamr_toolchain.cmake` +* optionally with some guide documents and samples + + + +Build WASM applications +=================================== + +WebAssembly as a new binary instruction can be viewed as a virtual architecture. If the WASM application is developed in C/C++ language, developers can use conventional cross-compilation procedure to build the WASM application. cmake is the recommended building tool and Clang is the preferred compiler. While emcc may still work but it is not guaranteed. + +Refer to [Build WASM applications](doc/build_wasm_app.md) for details. Samples and demos @@ -94,7 +129,7 @@ Samples and demos The WAMR samples are located in folder [./samples](./samples). A sample usually contains the WAMR runtime build, WASM applications and test tools. The WARM provides following samples: - [Simple](./samples/simple/README.md): The runtime is integrated with most of the WAMR APP libaries and multiple WASM applications are provided for using different WASM API set. -- [littlevgl](./samples/littlevgl/README.md): Demostrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. +- [littlevgl](./samples/littlevgl/README.md): Demostrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. - [gui](./samples/gui/README.md): Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. - [IoT-APP-Store-Demo](./test-tools/IoT-APP-Store-Demo/README.md): A web site for demostrating a WASM APP store usage where we can remotely install and uninstall WASM application on remote devices. @@ -109,9 +144,9 @@ The graphic user interface demo photo: Releases and acknowledgments ============================ -WAMR is a community efforts. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community. +WAMR is a community efforts. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community. -See the [major features releasing history and contributor names](./doc/release_ack.md) +See the [major features releasing history and contributor names](./doc/release_ack.md) Roadmap diff --git a/core/iwasm/lib/native/libc/libc_builtin_wrapper.c b/core/iwasm/lib/native/libc/libc_builtin_wrapper.c new file mode 100644 index 000000000..671716651 --- /dev/null +++ b/core/iwasm/lib/native/libc/libc_builtin_wrapper.c @@ -0,0 +1,1333 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_native.h" +#include "wasm_export.h" +#include "wasm_log.h" +#include "wasm_platform_log.h" +#include "bh_common.h" +#if WASM_ENABLE_WASI != 0 +#include "wasi_wrapper.h" +#endif + +void +wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); + +uint32 +wasm_runtime_get_temp_ret(wasm_module_inst_t module); + +void +wasm_runtime_set_temp_ret(wasm_module_inst_t module, uint32 temp_ret); + +uint32 +wasm_runtime_get_llvm_stack(wasm_module_inst_t module); + +void +wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack); + +#define validate_app_addr(offset, size) \ + wasm_runtime_validate_app_addr(module_inst, offset, size) + +#define validate_app_str_addr(offset) \ + wasm_runtime_validate_app_str_addr(module_inst, offset) + +#define addr_app_to_native(offset) \ + wasm_runtime_addr_app_to_native(module_inst, offset) + +#define addr_native_to_app(ptr) \ + wasm_runtime_addr_native_to_app(module_inst, ptr) + +#define module_malloc(size) \ + wasm_runtime_module_malloc(module_inst, size) + +#define module_free(offset) \ + wasm_runtime_module_free(module_inst, offset) + +typedef int (*out_func_t)(int c, void *ctx); + +enum pad_type { + PAD_NONE, + PAD_ZERO_BEFORE, + PAD_SPACE_BEFORE, + PAD_SPACE_AFTER, +}; + +typedef char *_va_list; +#define _INTSIZEOF(n) \ + (((uint32)sizeof(n) + 3) & (uint32)~3) +#define _va_arg(ap, t) \ + (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) + +#define CHECK_VA_ARG(ap, t) do { \ + if ((uint8*)ap + _INTSIZEOF(t) > native_end_addr) \ + goto fail; \ +} while (0) + +/** + * @brief Output an unsigned int in hex format + * + * Output an unsigned int on output installed by platform at init time. Should + * be able to handle an unsigned int of any size, 32 or 64 bit. + * @param num Number to output + * + * @return N/A + */ +static void +_printf_hex_uint(out_func_t out, void *ctx, + const uint64 num, bool is_u64, + enum pad_type padding, + int min_width) +{ + int size = sizeof(num) * (is_u64 ? 2 : 1); + int found_largest_digit = 0; + int remaining = 8; /* 8 digits max */ + int digits = 0; + + for (; size; size--) { + char nibble = (num >> ((size - 1) << 2) & 0xf); + + if (nibble || found_largest_digit || size == 1) { + found_largest_digit = 1; + nibble = (char)(nibble + (nibble > 9 ? 87 : 48)); + out((int) nibble, ctx); + digits++; + continue; + } + + if (remaining-- <= min_width) { + if (padding == PAD_ZERO_BEFORE) { + out('0', ctx); + } else if (padding == PAD_SPACE_BEFORE) { + out(' ', ctx); + } + } + } + + if (padding == PAD_SPACE_AFTER) { + remaining = min_width * 2 - digits; + while (remaining-- > 0) { + out(' ', ctx); + } + } +} + +/** + * @brief Output an unsigned int in decimal format + * + * Output an unsigned int on output installed by platform at init time. Only + * works with 32-bit values. + * @param num Number to output + * + * @return N/A + */ +static void +_printf_dec_uint(out_func_t out, void *ctx, + const uint32 num, + enum pad_type padding, + int min_width) +{ + uint32 pos = 999999999; + uint32 remainder = num; + int found_largest_digit = 0; + int remaining = 10; /* 10 digits max */ + int digits = 1; + + /* make sure we don't skip if value is zero */ + if (min_width <= 0) { + min_width = 1; + } + + while (pos >= 9) { + if (found_largest_digit || remainder > pos) { + found_largest_digit = 1; + out((int) ((remainder / (pos + 1)) + 48), ctx); + digits++; + } else if (remaining <= min_width && padding < PAD_SPACE_AFTER) { + out((int) (padding == PAD_ZERO_BEFORE ? '0' : ' '), ctx); + digits++; + } + remaining--; + remainder %= (pos + 1); + pos /= 10; + } + out((int) (remainder + 48), ctx); + + if (padding == PAD_SPACE_AFTER) { + remaining = min_width - digits; + while (remaining-- > 0) { + out(' ', ctx); + } + } +} + +static void +print_err(out_func_t out, void *ctx) +{ + out('E', ctx); + out('R', ctx); + out('R', ctx); +} + +static bool +_vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, + wasm_module_inst_t module_inst) +{ + int might_format = 0; /* 1 if encountered a '%' */ + enum pad_type padding = PAD_NONE; + int min_width = -1; + int long_ctr = 0; + uint8 *native_end_addr; + + if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)ap, + NULL, &native_end_addr)) + goto fail; + + /* fmt has already been adjusted if needed */ + + while (*fmt) { + if (!might_format) { + if (*fmt != '%') { + out((int) *fmt, ctx); + } + else { + might_format = 1; + min_width = -1; + padding = PAD_NONE; + long_ctr = 0; + } + } + else { + switch (*fmt) { + case '-': + padding = PAD_SPACE_AFTER; + goto still_might_format; + + case '0': + if (min_width < 0 && padding == PAD_NONE) { + padding = PAD_ZERO_BEFORE; + goto still_might_format; + } + /* Fall through */ + case '1' ... '9': + if (min_width < 0) { + min_width = *fmt - '0'; + } else { + min_width = 10 * min_width + *fmt - '0'; + } + + if (padding == PAD_NONE) { + padding = PAD_SPACE_BEFORE; + } + goto still_might_format; + + case 'l': + long_ctr++; + /* Fall through */ + case 'z': + case 'h': + /* FIXME: do nothing for these modifiers */ + goto still_might_format; + + case 'd': + case 'i': { + int32 d; + + if (long_ctr < 2) { + CHECK_VA_ARG(ap, int32); + d = _va_arg(ap, int32); + } + else { + int64 lld; + CHECK_VA_ARG(ap, int64); + lld = _va_arg(ap, int64); + if (lld > INT32_MAX || lld < INT32_MIN) { + print_err(out, ctx); + break; + } + d = (int32)lld; + } + + if (d < 0) { + out((int)'-', ctx); + d = -d; + min_width--; + } + _printf_dec_uint(out, ctx, (uint32)d, padding, min_width); + break; + } + case 'u': { + uint32 u; + + if (long_ctr < 2) { + CHECK_VA_ARG(ap, uint32); + u = _va_arg(ap, uint32); + } + else { + uint64 llu; + CHECK_VA_ARG(ap, uint64); + llu = _va_arg(ap, uint64); + if (llu > INT32_MAX) { + print_err(out, ctx); + break; + } + u = (uint32)llu; + } + _printf_dec_uint(out, ctx, u, padding, min_width); + break; + } + case 'p': + out('0', ctx); + out('x', ctx); + /* left-pad pointers with zeros */ + padding = PAD_ZERO_BEFORE; + min_width = 8; + /* Fall through */ + case 'x': + case 'X': { + uint64 x; + bool is_ptr = (*fmt == 'p') ? true : false; + + if (long_ctr < 2) { + CHECK_VA_ARG(ap, uint32); + x = _va_arg(ap, uint32); + } else { + CHECK_VA_ARG(ap, uint64); + x = _va_arg(ap, uint64); + } + _printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width); + break; + } + + case 's': { + char *s; + char *start; + int32 s_offset; + + CHECK_VA_ARG(ap, int32); + s_offset = _va_arg(ap, int32); + + if (!validate_app_str_addr(s_offset)) { + return false; + } + + s = start = addr_app_to_native(s_offset); + + while (*s) + out((int) (*s++), ctx); + + if (padding == PAD_SPACE_AFTER) { + int remaining = min_width - (int32)(s - start); + while (remaining-- > 0) { + out(' ', ctx); + } + } + break; + } + + case 'c': { + int c; + CHECK_VA_ARG(ap, int); + c = _va_arg(ap, int); + out(c, ctx); + break; + } + + case '%': { + out((int) '%', ctx); + break; + } + + default: + out((int) '%', ctx); + out((int) *fmt, ctx); + break; + } + + might_format = 0; + } + +still_might_format: + ++fmt; + } + return true; + +fail: + wasm_runtime_set_exception(module_inst, "out of bounds memory access"); + return false; +} + +struct str_context { + char *str; + uint32 max; + uint32 count; +}; + +static int +sprintf_out(int c, struct str_context *ctx) +{ + if (!ctx->str || ctx->count >= ctx->max) { + ctx->count++; + return c; + } + + if (ctx->count == ctx->max - 1) { + ctx->str[ctx->count++] = '\0'; + } else { + ctx->str[ctx->count++] = (char)c; + } + + return c; +} + +static int +printf_out(int c, struct str_context *ctx) +{ + bh_printf("%c", c); + ctx->count++; + return c; +} + +static inline _va_list +get_va_list(uint32 *args) +{ + union { + uint32 u; + _va_list v; + } u; + u.u = args[0]; + return u.v; +} + +static bool +parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset, + int32 va_list_offset, const char **p_fmt, + _va_list *p_va_args) +{ + const char *fmt; + union { + uintptr_t u; + _va_list v; + } u; + + if (!validate_app_str_addr(fmt_offset) + || !validate_app_addr(va_list_offset, sizeof(int32))) + return false; + + fmt = (const char*) addr_app_to_native(fmt_offset); + u.u = (uintptr_t) addr_app_to_native(va_list_offset); + + *p_fmt = fmt; + *p_va_args = u.v; + return true; +} + +static int +_printf_wrapper(wasm_module_inst_t module_inst, + int32 fmt_offset, int32 va_list_offset) +{ + struct str_context ctx = { NULL, 0, 0 }; + const char *fmt; + _va_list va_args; + + if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args)) + return 0; + + if (!_vprintf_wa((out_func_t)printf_out, &ctx, fmt, va_args, module_inst)) + return 0; + return (int)ctx.count; +} + +static int +_sprintf_wrapper(wasm_module_inst_t module_inst, + int32 str_offset, int32 fmt_offset, int32 va_list_offset) +{ + int32 app_end_offset; + struct str_context ctx; + char *str; + const char *fmt; + _va_list va_args; + + if (!wasm_runtime_get_app_addr_range(module_inst, str_offset, + NULL, &app_end_offset)) { + wasm_runtime_set_exception(module_inst, "out of bounds memory access"); + return false; + } + + str = addr_app_to_native(str_offset); + + if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args)) + return 0; + + ctx.str = str; + ctx.max = (uint32)(app_end_offset - str_offset); + ctx.count = 0; + + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst)) + return 0; + + if (ctx.count < ctx.max) { + str[ctx.count] = '\0'; + } + + return (int)ctx.count; +} + +static int +_snprintf_wrapper(wasm_module_inst_t module_inst, + int32 str_offset, uint32 size, int32 fmt_offset, + int32 va_list_offset) +{ + struct str_context ctx; + char *str; + const char *fmt; + _va_list va_args; + + if (!validate_app_addr(str_offset, size)) + return 0; + + str = addr_app_to_native(str_offset); + + if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args)) + return 0; + + ctx.str = str; + ctx.max = size; + ctx.count = 0; + + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst)) + return 0; + + if (ctx.count < ctx.max) { + str[ctx.count] = '\0'; + } + + return (int)ctx.count; +} + +static int +_puts_wrapper(wasm_module_inst_t module_inst, + int32 str_offset) +{ + const char *str; + + if (!validate_app_str_addr(str_offset)) + return 0; + + str = addr_app_to_native(str_offset); + return bh_printf("%s\n", str); +} + +static int +_putchar_wrapper(wasm_module_inst_t module_inst, int c) +{ + bh_printf("%c", c); + return 1; +} + +static int32 +_strdup_wrapper(wasm_module_inst_t module_inst, + int32 str_offset) +{ + char *str, *str_ret; + uint32 len; + int32 str_ret_offset = 0; + + if (!validate_app_str_addr(str_offset)) + return 0; + + str = addr_app_to_native(str_offset); + + if (str) { + len = (uint32)strlen(str) + 1; + + str_ret_offset = module_malloc(len); + if (str_ret_offset) { + str_ret = addr_app_to_native(str_ret_offset); + bh_memcpy_s(str_ret, len, str, len); + } + } + + return str_ret_offset; +} + +static int32 +__strdup_wrapper(wasm_module_inst_t module_inst, + int32 str_offset) +{ + return _strdup_wrapper(module_inst, str_offset); +} + +static int32 +_memcmp_wrapper(wasm_module_inst_t module_inst, + int32 s1_offset, int32 s2_offset, uint32 size) +{ + void *s1, *s2; + + if (!validate_app_addr(s1_offset, size) + || !validate_app_addr(s2_offset, size)) + return 0; + + s1 = addr_app_to_native(s1_offset); + s2 = addr_app_to_native(s2_offset); + return memcmp(s1, s2, size); +} + +static int32 +_memcpy_wrapper(wasm_module_inst_t module_inst, + int32 dst_offset, int32 src_offset, uint32 size) +{ + void *dst, *src; + + if (size == 0) + return dst_offset; + + if (!validate_app_addr(dst_offset, size) + || !validate_app_addr(src_offset, size)) + return dst_offset; + + dst = addr_app_to_native(dst_offset); + src = addr_app_to_native(src_offset); + bh_memcpy_s(dst, size, src, size); + return dst_offset; +} + +static int32 +_memmove_wrapper(wasm_module_inst_t module_inst, + int32 dst_offset, int32 src_offset, uint32 size) +{ + void *dst, *src; + + if (!validate_app_addr(dst_offset, size) + || !validate_app_addr(src_offset, size)) + return dst_offset; + + dst = addr_app_to_native(dst_offset); + src = addr_app_to_native(src_offset); + memmove(dst, src, size); + return dst_offset; +} + +static int32 +_memset_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, int32 c, uint32 size) +{ + void *s; + + if (!validate_app_addr(s_offset, size)) + return s_offset; + + s = addr_app_to_native(s_offset); + memset(s, c, size); + return s_offset; +} + +static int32 +_strchr_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, int32 c) +{ + const char *s; + char *ret; + + if (!validate_app_str_addr(s_offset)) + return s_offset; + + s = addr_app_to_native(s_offset); + ret = strchr(s, c); + return ret ? addr_native_to_app(ret) : 0; +} + +static int32 +_strcmp_wrapper(wasm_module_inst_t module_inst, + int32 s1_offset, int32 s2_offset) +{ + void *s1, *s2; + + if (!validate_app_str_addr(s1_offset) + || !validate_app_str_addr(s2_offset)) + return 0; + + s1 = addr_app_to_native(s1_offset); + s2 = addr_app_to_native(s2_offset); + return strcmp(s1, s2); +} + +static int32 +_strncmp_wrapper(wasm_module_inst_t module_inst, + int32 s1_offset, int32 s2_offset, uint32 size) +{ + void *s1, *s2; + + if (!validate_app_addr(s1_offset, size) + || !validate_app_addr(s2_offset, size)) + return 0; + + s1 = addr_app_to_native(s1_offset); + s2 = addr_app_to_native(s2_offset); + return strncmp(s1, s2, size); +} + +static int32 +_strcpy_wrapper(wasm_module_inst_t module_inst, + int32 dst_offset, int32 src_offset) +{ + char *dst, *src; + uint32 len; + + if (!validate_app_str_addr(src_offset)) + return 0; + + src = addr_app_to_native(src_offset); + len = (uint32)strlen(src); + + if (!validate_app_addr(dst_offset, len + 1)) + return 0; + + dst = addr_app_to_native(dst_offset); + strncpy(dst, src, len + 1); + return dst_offset; +} + +static int32 +_strncpy_wrapper(wasm_module_inst_t module_inst, + int32 dst_offset, int32 src_offset, uint32 size) +{ + char *dst, *src; + + if (!validate_app_addr(dst_offset, size) + || !validate_app_addr(src_offset, size)) + return 0; + + dst = addr_app_to_native(dst_offset); + src = addr_app_to_native(src_offset); + strncpy(dst, src, size); + return dst_offset; +} + +static uint32 +_strlen_wrapper(wasm_module_inst_t module_inst, + int32 s_offset) +{ + char *s; + + if (!validate_app_str_addr(s_offset)) + return 0; + + s = addr_app_to_native(s_offset); + return (uint32)strlen(s); +} + +static int32 +_malloc_wrapper(wasm_module_inst_t module_inst, + uint32 size) +{ + return module_malloc(size); +} + +static int32 +_calloc_wrapper(wasm_module_inst_t module_inst, + uint32 nmemb, uint32 size) +{ + uint64 total_size = (uint64) nmemb * (uint64) size; + int32 ret_offset = 0; + uint8 *ret_ptr; + + if (total_size >= UINT32_MAX) + return 0; + + ret_offset = module_malloc((uint32)total_size); + if (ret_offset) { + ret_ptr = addr_app_to_native(ret_offset); + memset(ret_ptr, 0, (uint32) total_size); + } + + return ret_offset; +} + +static void +_free_wrapper(wasm_module_inst_t module_inst, + int32 ptr_offset) +{ + if (!validate_app_addr(ptr_offset, 4)) + return; + return module_free(ptr_offset); +} + +static int32 +_atoi_wrapper(wasm_module_inst_t module_inst, + int32 s_offset) +{ + char *str; + + if (!validate_app_str_addr(s_offset)) + return 0; + + str = addr_app_to_native(s_offset); + + return atoi(str); +} + +static int32 +_bsearch_wrapper(wasm_module_inst_t module_inst, + int32 key_offset, /* const void * */ + int32 array_offset, /* const void * */ + uint32 count, + uint32 size, + int32 cmp_index) +{ + wasm_runtime_set_exception(module_inst, "bsearch not implemented."); + + return 0; +} + +static void +_exit_wrapper(wasm_module_inst_t module_inst, + int32 status) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "env.exit(%i)", status); + wasm_runtime_set_exception(module_inst, buf); +} + +static int32 +_strtol_wrapper(wasm_module_inst_t module_inst, + int32 nptr_offset, /* const char * */ + int32 endptr_offset, /* char ** */ + int32 base) +{ + char *nptr, **endptr; + int32 num = 0; + + if (!validate_app_str_addr(nptr_offset) + || !validate_app_addr(endptr_offset, sizeof(int32))) + return 0; + + nptr = addr_app_to_native(nptr_offset); + endptr = addr_app_to_native(endptr_offset); + + num = (int32)strtol(nptr, endptr, base); + *(int32 *)endptr = addr_native_to_app(*endptr); + + return num; +} + +static uint32 +_strtoul_wrapper(wasm_module_inst_t module_inst, + int32 nptr_offset, /* const char * */ + int32 endptr_offset, /* char ** */ + int32 base) +{ + char *nptr, **endptr; + uint32 num = 0; + + if (!validate_app_str_addr(nptr_offset) + || !validate_app_addr(endptr_offset, sizeof(int32))) + return 0; + + nptr = addr_app_to_native(nptr_offset); + endptr = addr_app_to_native(endptr_offset); + + num = (uint32)strtoul(nptr, endptr, base); + *(int32 *)endptr = addr_native_to_app(*endptr); + + return num; +} + +static int32 +_memchr_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const void * */ + int32 c, + uint32 n) +{ + void *s, *res; + + if (!validate_app_addr(s_offset, n)) + return 0; + + s = (void*)addr_app_to_native(s_offset); + + res = memchr(s, c, n); + + return addr_native_to_app(res); +} + +static int32 +_strncasecmp_wrapper(wasm_module_inst_t module_inst, + int32 s1_offset, /* const char * */ + int32 s2_offset, /* const char * */ + uint32 n) +{ + char *s1, *s2; + + if (!validate_app_str_addr(s1_offset) + || !validate_app_str_addr(s2_offset)) + return 0; + + s1 = addr_app_to_native(s1_offset); + s2 = addr_app_to_native(s2_offset); + + return strncasecmp(s1, s2, n); +} + +static uint32 +_strspn_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const char * */ + int32 accept_offset) /* const char * */ +{ + char *s, *accept; + + if (!validate_app_str_addr(s_offset) + || !validate_app_str_addr(accept_offset)) + return 0; + + s = addr_app_to_native(s_offset); + accept = addr_app_to_native(accept_offset); + + return (uint32)strspn(s, accept); +} + +static uint32 +_strcspn_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const char * */ + int32 reject_offset) /* const char * */ +{ + char *s, *reject; + + if (!validate_app_str_addr(s_offset) + || !validate_app_str_addr(reject_offset)) + return 0; + + s = addr_app_to_native(s_offset); + reject = addr_app_to_native(reject_offset); + + return (uint32)strcspn(s, reject); +} + +static int32 +_strstr_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const char * */ + int32 find_offset) /* const char * */ +{ + char *s, *find, *res; + + if (!validate_app_str_addr(s_offset) + || !validate_app_str_addr(find_offset)) + return 0; + + s = addr_app_to_native(s_offset); + find = addr_app_to_native(find_offset); + + res = strstr(s, find); + + return addr_native_to_app(res); +} + +static int32 +_isupper_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isupper(c); +} + +static int32 +_isalpha_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isalpha(c); +} + +static int32 +_isspace_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isspace(c); +} + +static int32 +_isgraph_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isgraph(c); +} + +static int32 +_isprint_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isprint(c); +} + +static int32 +_isdigit_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isdigit(c); +} + +static int32 +_isxdigit_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isxdigit(c); +} + +static int32 +_tolower_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return tolower(c); +} + +static int32 +_toupper_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return toupper(c); +} + +static int32 +_isalnum_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isalnum(c); +} + +static void +setTempRet0_wrapper(wasm_module_inst_t module_inst, + uint32 temp_ret) +{ + wasm_runtime_set_temp_ret(module_inst, temp_ret); +} + +static uint32 +getTempRet0_wrapper(wasm_module_inst_t module_inst) +{ + return wasm_runtime_get_temp_ret(module_inst); +} + +static uint32 +_llvm_bswap_i16_wrapper(wasm_module_inst_t module_inst, + uint32 data) +{ + return (data & 0xFFFF0000) + | ((data & 0xFF) << 8) + | ((data & 0xFF00) >> 8); +} + +static uint32 +_llvm_bswap_i32_wrapper(wasm_module_inst_t module_inst, + uint32 data) +{ + return ((data & 0xFF) << 24) + | ((data & 0xFF00) << 8) + | ((data & 0xFF0000) >> 8) + | ((data & 0xFF000000) >> 24); +} + +static uint32 +_bitshift64Lshr_wrapper(wasm_module_inst_t module_inst, + uint32 uint64_part0, uint32 uint64_part1, + uint32 bits) +{ + union { + uint64 value; + uint32 parts[2]; + } u; + + u.parts[0] = uint64_part0; + u.parts[1] = uint64_part1; + + u.value >>= bits; + /* return low 32bit and save high 32bit to temp ret */ + wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32)); + return (uint32) u.value; +} + +static uint32 +_bitshift64Shl_wrapper(wasm_module_inst_t module_inst, + uint32 int64_part0, uint32 int64_part1, + uint32 bits) +{ + union { + int64 value; + uint32 parts[2]; + } u; + + u.parts[0] = int64_part0; + u.parts[1] = int64_part1; + + u.value <<= bits; + /* return low 32bit and save high 32bit to temp ret */ + wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32)); + return (uint32) u.value; +} + +static void +_llvm_stackrestore_wrapper(wasm_module_inst_t module_inst, + uint32 llvm_stack) +{ + bh_printf("_llvm_stackrestore called!\n"); + wasm_runtime_set_llvm_stack(module_inst, llvm_stack); +} + +static uint32 +_llvm_stacksave_wrapper(wasm_module_inst_t module_inst) +{ + bh_printf("_llvm_stacksave called!\n"); + return wasm_runtime_get_llvm_stack(module_inst); +} + +static int32 +_emscripten_memcpy_big_wrapper(wasm_module_inst_t module_inst, + int32 dst_offset, int32 src_offset, + uint32 size) +{ + void *dst, *src; + + if (!validate_app_addr(dst_offset, size) + || !validate_app_addr(src_offset, size)) + return dst_offset; + + dst = addr_app_to_native(dst_offset); + src = addr_app_to_native(src_offset); + + bh_memcpy_s(dst, size, src, size); + return dst_offset; +} + +static void +abort_wrapper(wasm_module_inst_t module_inst, + int32 code) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "env.abort(%i)", code); + wasm_runtime_set_exception(module_inst, buf); +} + +static void +abortStackOverflow_wrapper(wasm_module_inst_t module_inst, + int32 code) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "env.abortStackOverflow(%i)", code); + wasm_runtime_set_exception(module_inst, buf); +} + +static void +nullFunc_X_wrapper(wasm_module_inst_t module_inst, + int32 code) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "env.nullFunc_X(%i)", code); + wasm_runtime_set_exception(module_inst, buf); +} + +static int32 +__cxa_allocate_exception_wrapper(wasm_module_inst_t module_inst, + uint32 thrown_size) +{ + int32 exception = module_malloc(thrown_size); + if (!exception) + return 0; + + return exception; +} + +static void +__cxa_begin_catch_wrapper(wasm_module_inst_t module_inst, + int32 exception_object_offset) +{ + +} + +static void +__cxa_throw_wrapper(wasm_module_inst_t module_inst, + int32 thrown_exception_offset, + int32 tinfo_offset, + uint32 table_elem_idx) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++"); + wasm_runtime_set_exception(module_inst, buf); +} + +/*#define ENABLE_SPEC_TEST 1*/ + +#ifdef ENABLE_SPEC_TEST +static void +print_i32_wrapper(wasm_module_inst_t module_inst, int i32) +{ + bh_printf("%d\n", i32); +} + +static void +print_wrapper(wasm_module_inst_t module_inst, int i32) +{ + bh_printf("%d\n", i32); +} +#endif + +/* TODO: add function parameter/result types check */ +#define REG_NATIVE_FUNC(module_name, func_name) \ + { #module_name, #func_name, func_name##_wrapper } + +typedef struct WASMNativeFuncDef { + const char *module_name; + const char *func_name; + void *func_ptr; +} WASMNativeFuncDef; + +static WASMNativeFuncDef native_func_defs[] = { +#ifdef ENABLE_SPEC_TEST + REG_NATIVE_FUNC(spectest, print_i32), + REG_NATIVE_FUNC(spectest, print), +#endif + REG_NATIVE_FUNC(env, _printf), + REG_NATIVE_FUNC(env, _sprintf), + REG_NATIVE_FUNC(env, _snprintf), + REG_NATIVE_FUNC(env, _puts), + REG_NATIVE_FUNC(env, _putchar), + REG_NATIVE_FUNC(env, _memcmp), + REG_NATIVE_FUNC(env, _memcpy), + REG_NATIVE_FUNC(env, _memmove), + REG_NATIVE_FUNC(env, _memset), + REG_NATIVE_FUNC(env, _strchr), + REG_NATIVE_FUNC(env, _strcmp), + REG_NATIVE_FUNC(env, _strcpy), + REG_NATIVE_FUNC(env, _strlen), + REG_NATIVE_FUNC(env, _strncmp), + REG_NATIVE_FUNC(env, _strncpy), + REG_NATIVE_FUNC(env, _malloc), + REG_NATIVE_FUNC(env, _calloc), + REG_NATIVE_FUNC(env, _strdup), + /* clang may introduce __strdup */ + REG_NATIVE_FUNC(env, __strdup), + REG_NATIVE_FUNC(env, _free), + REG_NATIVE_FUNC(env, _atoi), + REG_NATIVE_FUNC(env, _bsearch), + REG_NATIVE_FUNC(env, _exit), + REG_NATIVE_FUNC(env, _strtol), + REG_NATIVE_FUNC(env, _strtoul), + REG_NATIVE_FUNC(env, _memchr), + REG_NATIVE_FUNC(env, _strncasecmp), + REG_NATIVE_FUNC(env, _strspn), + REG_NATIVE_FUNC(env, _strcspn), + REG_NATIVE_FUNC(env, _strstr), + REG_NATIVE_FUNC(env, _isupper), + REG_NATIVE_FUNC(env, _isalpha), + REG_NATIVE_FUNC(env, _isspace), + REG_NATIVE_FUNC(env, _isgraph), + REG_NATIVE_FUNC(env, _isprint), + REG_NATIVE_FUNC(env, _isdigit), + REG_NATIVE_FUNC(env, _isxdigit), + REG_NATIVE_FUNC(env, _tolower), + REG_NATIVE_FUNC(env, _toupper), + REG_NATIVE_FUNC(env, _isalnum), + REG_NATIVE_FUNC(env, setTempRet0), + REG_NATIVE_FUNC(env, getTempRet0), + REG_NATIVE_FUNC(env, _llvm_bswap_i16), + REG_NATIVE_FUNC(env, _llvm_bswap_i32), + REG_NATIVE_FUNC(env, _bitshift64Lshr), + REG_NATIVE_FUNC(env, _bitshift64Shl), + REG_NATIVE_FUNC(env, _llvm_stackrestore), + REG_NATIVE_FUNC(env, _llvm_stacksave), + REG_NATIVE_FUNC(env, _emscripten_memcpy_big), + REG_NATIVE_FUNC(env, abort), + REG_NATIVE_FUNC(env, abortStackOverflow), + REG_NATIVE_FUNC(env, nullFunc_X), + REG_NATIVE_FUNC(env, __cxa_allocate_exception), + REG_NATIVE_FUNC(env, __cxa_begin_catch), + REG_NATIVE_FUNC(env, __cxa_throw) +}; + +void* +wasm_native_func_lookup(const char *module_name, const char *func_name) +{ + uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef); + WASMNativeFuncDef *func_def = native_func_defs; + WASMNativeFuncDef *func_def_end = func_def + size; + void *ret; + + if (!module_name || !func_name) + return NULL; + + while (func_def < func_def_end) { + if (!strcmp(func_def->module_name, module_name) + && (!strcmp(func_def->func_name, func_name) + || (func_def->func_name[0] == '_' + && !strcmp(func_def->func_name + 1, func_name)))) + return (void*) (uintptr_t) func_def->func_ptr; + func_def++; + } + + if ((ret = wasm_platform_native_func_lookup(module_name, func_name))) + return ret; + +#if WASM_ENABLE_WASI != 0 + if ((ret = wasi_native_func_lookup(module_name, func_name))) + return ret; +#endif + + return NULL; +} + +/************************************* + * Global Variables * + *************************************/ + +typedef struct WASMNativeGlobalDef { + const char *module_name; + const char *global_name; + WASMValue global_data; +} WASMNativeGlobalDef; + +static WASMNativeGlobalDef native_global_defs[] = { +#ifdef ENABLE_SPEC_TEST + { "spectest", "global_i32", .global_data.u32 = 0 }, +#endif + { "env", "STACKTOP", .global_data.u32 = 0 }, + { "env", "STACK_MAX", .global_data.u32 = 0 }, + { "env", "ABORT", .global_data.u32 = 0 }, + { "env", "memoryBase", .global_data.u32 = 0 }, + { "env", "__memory_base", .global_data.u32 = 0 }, + { "env", "tableBase", .global_data.u32 = 0 }, + { "env", "__table_base", .global_data.u32 = 0 }, + { "env", "DYNAMICTOP_PTR", .global_data.addr = 0 }, + { "env", "tempDoublePtr", .global_data.addr = 0 }, + { "global", "NaN", .global_data.u64 = 0x7FF8000000000000LL }, + { "global", "Infinity", .global_data.u64 = 0x7FF0000000000000LL } +}; + +bool +wasm_native_global_lookup(const char *module_name, const char *global_name, + WASMGlobalImport *global) +{ + uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef); + WASMNativeGlobalDef *global_def = native_global_defs; + WASMNativeGlobalDef *global_def_end = global_def + size; + + if (!module_name || !global_name || !global) + return false; + + /* Lookup constant globals which can be defined by table */ + while (global_def < global_def_end) { + if (!strcmp(global_def->module_name, module_name) + && !strcmp(global_def->global_name, global_name)) { + global->global_data_linked = global_def->global_data; + return true; + } + global_def++; + } + + return false; +} + +bool +wasm_native_init() +{ + /* TODO: qsort the function defs and global defs. */ + return true; +} + diff --git a/core/iwasm/lib/native/libc/wasm_libc.cmake b/core/iwasm/lib/native/libc/wasm_libc.cmake index f84c3ac63..df5be0c09 100644 --- a/core/iwasm/lib/native/libc/wasm_libc.cmake +++ b/core/iwasm/lib/native/libc/wasm_libc.cmake @@ -6,7 +6,7 @@ set (WASM_LIBC_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${WASM_LIBC_DIR}) -file (GLOB_RECURSE source_all ${WASM_LIBC_DIR}/*.c) +file (GLOB source_all ${WASM_LIBC_DIR}/*.c) set (WASM_LIBC_SOURCE ${source_all}) diff --git a/core/iwasm/runtime/wasmtime-wasi-c/LICENSE b/core/iwasm/lib/native/libc/wasmtime-wasi-c/LICENSE similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/LICENSE rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/LICENSE diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h diff --git a/core/iwasm/runtime/wasmtime-wasi-c/wasi.cmake b/core/iwasm/lib/native/libc/wasmtime-wasi-c/wasi.cmake similarity index 100% rename from core/iwasm/runtime/wasmtime-wasi-c/wasi.cmake rename to core/iwasm/lib/native/libc/wasmtime-wasi-c/wasi.cmake diff --git a/core/iwasm/products/darwin/CMakeLists.txt b/core/iwasm/products/darwin/CMakeLists.txt index deeae5671..9d5f5f58e 100644 --- a/core/iwasm/products/darwin/CMakeLists.txt +++ b/core/iwasm/products/darwin/CMakeLists.txt @@ -61,8 +61,8 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () if (NOT DEFINED WASM_ENABLE_WASI) - # Enable wasi support by default - set (WASM_ENABLE_WASI 1) + # Disable wasi support by default + set (WASM_ENABLE_WASI 0) endif () if (WASM_ENABLE_WASI EQUAL 1) @@ -95,7 +95,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../runtime/wasmtime-wasi-c/wasi.cmake) +include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) diff --git a/core/iwasm/products/darwin/main.c b/core/iwasm/products/darwin/main.c index b92a439da..ffda65c94 100644 --- a/core/iwasm/products/darwin/main.c +++ b/core/iwasm/products/darwin/main.c @@ -129,6 +129,7 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } +#if WASM_ENABLE_WASI != 0 static bool validate_env_str(char *env) { @@ -145,6 +146,7 @@ validate_env_str(char *env) return true; } +#endif #define USE_GLOBAL_HEAP_BUF 0 diff --git a/core/iwasm/products/linux-sgx/CMakeLists.txt b/core/iwasm/products/linux-sgx/CMakeLists.txt index 9edf99e67..de91f1e62 100644 --- a/core/iwasm/products/linux-sgx/CMakeLists.txt +++ b/core/iwasm/products/linux-sgx/CMakeLists.txt @@ -96,7 +96,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../runtime/wasmtime-wasi-c/wasi.cmake) +include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) diff --git a/core/iwasm/products/linux/CMakeLists.txt b/core/iwasm/products/linux/CMakeLists.txt index 8d1b64279..1e9dab882 100644 --- a/core/iwasm/products/linux/CMakeLists.txt +++ b/core/iwasm/products/linux/CMakeLists.txt @@ -92,7 +92,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../runtime/wasmtime-wasi-c/wasi.cmake) +include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) diff --git a/core/iwasm/products/linux/main.c b/core/iwasm/products/linux/main.c index 44a3cc713..0ea3b9fd8 100644 --- a/core/iwasm/products/linux/main.c +++ b/core/iwasm/products/linux/main.c @@ -156,6 +156,7 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } +#if WASM_ENABLE_WASI != 0 static bool validate_env_str(char *env) { @@ -172,6 +173,7 @@ validate_env_str(char *env) return true; } +#endif #define USE_GLOBAL_HEAP_BUF 0 diff --git a/core/iwasm/products/vxworks/CMakeLists.txt b/core/iwasm/products/vxworks/CMakeLists.txt index bd42cb155..64045a3dc 100644 --- a/core/iwasm/products/vxworks/CMakeLists.txt +++ b/core/iwasm/products/vxworks/CMakeLists.txt @@ -78,8 +78,8 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () if (NOT DEFINED WASM_ENABLE_WASI) - # Enable wasi support by default - set (WASM_ENABLE_WASI 1) + # Disable wasi support by default + set (WASM_ENABLE_WASI 0) endif () if (WASM_ENABLE_WASI EQUAL 1) @@ -110,7 +110,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../runtime/wasmtime-wasi-c/wasi.cmake) +include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) diff --git a/core/iwasm/products/vxworks/main.c b/core/iwasm/products/vxworks/main.c index 6d35e1f96..6cbe2438e 100644 --- a/core/iwasm/products/vxworks/main.c +++ b/core/iwasm/products/vxworks/main.c @@ -156,6 +156,7 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } +#if WASM_ENABLE_WASI != 0 static bool validate_env_str(char *env) { @@ -172,6 +173,7 @@ validate_env_str(char *env) return true; } +#endif static char global_heap_buf[512 * 1024] = { 0 }; diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_application.c b/core/iwasm/runtime/vmcore-wasm/wasm_application.c index 20ed543ea..ce9f37a85 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_application.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_application.c @@ -105,11 +105,17 @@ wasm_application_execute_main(WASMModuleInstance *module_inst, #endif func = resolve_main_function(module_inst); - if (!func || func->is_import_func) + if (!func || func->is_import_func) { + wasm_runtime_set_exception(module_inst, + "lookup main function failed."); return false; + } - if (!check_main_func_type(func->u.func->func_type)) + if (!check_main_func_type(func->u.func->func_type)) { + wasm_runtime_set_exception(module_inst, + "invalid function type of main function."); return false; + } if (func->u.func->func_type->param_count) { for (i = 0; i < argc; i++) @@ -120,8 +126,11 @@ wasm_application_execute_main(WASMModuleInstance *module_inst, if (total_size >= UINT32_MAX || !(argv_buf_offset = - wasm_runtime_module_malloc(module_inst, (uint32)total_size))) + wasm_runtime_module_malloc(module_inst, (uint32)total_size))) { + wasm_runtime_set_exception(module_inst, + "allocate memory failed."); return false; + } argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset); argv_offsets = (int32*)(p + total_argv_size); @@ -209,17 +218,20 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, int32 i, p; uint64 total_size; const char *exception; + char buf[128]; wasm_assert(argc >= 0); func = resolve_function(module_inst, name); if (!func || func->is_import_func) { - LOG_ERROR("Wasm lookup function %s failed.\n", name); + snprintf(buf, sizeof(buf), "lookup function %s failed.", name); + wasm_runtime_set_exception(module_inst, buf); return false; } type = func->u.func->func_type; if (type->param_count != (uint32)argc) { - LOG_ERROR("Wasm prepare param failed: invalid param count.\n"); + wasm_runtime_set_exception(module_inst, + "invalid input argument count."); return false; } @@ -227,7 +239,7 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, total_size = sizeof(uint32) * (uint64)(argc1 > 2 ? argc1 : 2); if (total_size >= UINT32_MAX || (!(argv1 = wasm_malloc((uint32)total_size)))) { - LOG_ERROR("Wasm prepare param failed: malloc failed.\n"); + wasm_runtime_set_exception(module_inst, "allocate memory failed."); return false; } @@ -236,7 +248,8 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, char *endptr = NULL; wasm_assert(argv[i] != NULL); if (argv[i][0] == '\0') { - LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]); + snprintf(buf, sizeof(buf), "invalid input argument %d.", i); + wasm_runtime_set_exception(module_inst, buf); goto fail; } switch (type->types[i]) { @@ -303,11 +316,15 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, } } if (endptr && *endptr != '\0' && *endptr != '_') { - LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]); + snprintf(buf, sizeof(buf), "invalid input argument %d: %s.", + i, argv[i]); + wasm_runtime_set_exception(module_inst, buf); goto fail; } if (errno != 0) { - LOG_ERROR("Wasm prepare param failed: errno %d.\n", errno); + snprintf(buf, sizeof(buf), + "prepare function argument error, errno: %d.", errno); + wasm_runtime_set_exception(module_inst, buf); goto fail; } } diff --git a/doc/build_wamr.md b/doc/build_wamr.md new file mode 100644 index 000000000..477429d9e --- /dev/null +++ b/doc/build_wamr.md @@ -0,0 +1,198 @@ + +Build WAMR Core +========================= +Please follow the instructions below to build the WAMR core on different platforms. + +Linux +------------------------- +First of all please install library dependencies of lib gcc. +Use installation commands below for Ubuntu Linux: +``` Bash +sudo apt install lib32gcc-5-dev g++-multilib +``` +Or in Fedora: +``` Bash +sudo dnf install glibc-devel.i686 +``` + +After installing dependencies, build the source code: +``` Bash +cd core/iwasm/products/linux/ +mkdir build +cd build +cmake .. +make +``` +Note: +The WASI feature is enabled by default, if we want to disable it, please run: +``` Bash +cmake .. -DWASM_ENALBE_WASI=0 +``` + +Linux SGX (Intel Software Guard Extention) +------------------------- +First of all please install library dependencies of lib gcc. +Use installation commands below for Ubuntu Linux: +``` Bash +sudo apt install lib32gcc-5-dev g++-multilib +``` +Or in Fedora: +``` Bash +sudo dnf install glibc-devel.i686 +``` + +And then install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk). + +After installing dependencies, build the source code: +``` Bash +source /environment +cd core/iwasm/products/linux-sgx/ +mkdir build +cd build +cmake .. +make +``` +This builds the libraries used by SGX enclave sample, the generated file libvmlib.a and libextlib.a will be copied to enclave-sample folder. + +Then build the enclave sample: +``` Bash +source /environment +cd enclave-sample +make +``` +The binary file app will be generated. + +To run the sample: +``` Bash +source /environment +./app +``` + +Mac +------------------------- +Make sure to install Xcode from App Store firstly, and install cmake. + +If you use Homebrew, install cmake from the command line: +``` Bash +brew install cmake +``` + +Then build the source codes: +``` +cd core/iwasm/products/darwin/ +mkdir build +cd build +cmake .. +make +``` + +VxWorks +------------------------- +VxWorks 7 SR0620 release is validated. + +First you need to build a VSB. Make sure *UTILS_UNIX* layer is added in the VSB. +After the VSB is built, export the VxWorks toolchain path by: +``` +export /host/vx-compiler/bin:$PATH +``` +Now switch to iwasm source tree to build the source code: +``` +cd core/iwasm/products/vxworks/ +mkdir build +cd build +cmake .. +make +``` +Create a VIP based on the VSB. Make sure the following components are added: +* INCLUDE_POSIX_PTHREADS +* INCLUDE_POSIX_PTHREAD_SCHEDULER +* INCLUDE_SHARED_DATA +* INCLUDE_SHL + +Copy the generated iwasm executable, the test WASM binary as well as the needed +shared libraries (libc.so.1, libllvm.so.1 or libgnu.so.1 depending on the VSB, +libunix.so.1) to a supported file system (eg: romfs). + +WASI +------------------------- +On Linux, WASI is enabled by default. To build iwasm without wasi support, pass an option when you run cmake: +``` +cmake .. -DWASM_ENABLE_WASI=0 +make +``` + +Zephyr +------------------------- +You need to download the Zephyr source code first and embed WAMR into it. +``` Bash +git clone https://github.com/zephyrproject-rtos/zephyr.git +cd zephyr/samples/ +cp -a /products/zephyr/simple . +cd simple +ln -s iwasm +ln -s shared-lib +mkdir build && cd build +source ../../../zephyr-env.sh +cmake -GNinja -DBOARD=qemu_x86 .. +ninja +``` + +AliOS-Things +------------------------- +1. a developerkit board id needed for testing +2. download the AliOS-Things code + ``` Bash + git clone https://github.com/alibaba/AliOS-Things.git + ``` +3. copy /products/alios-things directory to AliOS-Things/middleware, and rename it as iwasm + ``` Bash + cp -a /products/alios-things middleware/iwasm + ``` +4. create a link to in middleware/iwasm/ and rename it to iwasm + ``` Bash + ln -s middleware/iwasm/iwasm + ``` +5. create a link to in middleware/iwasm/ and rename it to shared-lib + ``` Bash + ln -s middle/iwasm/shared-lib + ``` +6. modify file app/example/helloworld/helloworld.c, patch as: + ``` C + #include + #include + extern bool iwasm_init(); + int application_start(int argc, char *argv[]) + { + int count = 0; + iwasm_init(); + ... + } + ``` +7. modify file app/example/helloworld/aos.mk + ``` C + $(NAME)_COMPONENTS := osal_aos iwasm + ``` +8. build source code + ``` Bash + aos make helloworld@developerkit -c config + aos make + ``` +9. download the binary to developerkit board, check the output from serial port + +Docker +------------------------- +[Docker](https://www.docker.com/) will download all the dependencies and build WAMR Core on your behalf. + +Make sure you have Docker installed on your machine: [macOS](https://docs.docker.com/docker-for-mac/install/), [Windows](https://docs.docker.com/docker-for-windows/install/) or [Linux](https://docs.docker.com/install/linux/docker-ce/ubuntu/). + +Build the Docker image: + +``` Bash +docker build --rm -f "Dockerfile" -t wamr:latest . +``` +Run the image in interactive mode: +``` Bash +docker run --rm -it wamr:latest +``` +You'll now enter the container at `/root`. + diff --git a/doc/build_wamr_app.md b/doc/build_wamr_app.md new file mode 100644 index 000000000..c7bc9b95c --- /dev/null +++ b/doc/build_wamr_app.md @@ -0,0 +1,182 @@ + + +Build WASM app +========================= +You can write a simple ```test.c``` as the first sample. + +```C +#include +#include + +int main(int argc, char **argv) +{ + char *buf; + + printf("Hello world!\n"); + + buf = malloc(1024); + if (!buf) { + printf("malloc buf failed\n"); + return -1; + } + + printf("buf ptr: %p\n", buf); + + sprintf(buf, "%s", "1234\n"); + printf("buf: %s", buf); + + free(buf); + return 0; +} +``` + +There are several methods to build a WASM binary. They are the clang compiler, Docker, Emscripten and so on. + +## Use clang compiler + +The recommended method to build a WASM binary is to use clang compiler ```clang-8```. You can refer to [apt.llvm.org](https://apt.llvm.org) for the detailed instructions. Here are referenced steps to install clang-8 in Ubuntu 16.04 and Ubuntu 18.04. + +(1) Add source to your system source list from llvm website + +For Ubuntu 16.04, add the following lines to /etc/apt/sources.list: + +```Bash +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main +# 8 +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main +# 9 +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main +``` + +For Ubuntu 18.04, add the following lines to /etc/apt/sources.list: + +```Bash +# i386 not available +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +# 8 +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +# 9 +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main + +(2) Download and install clang-8 tool-chain using following commands: + +```Bash +sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - +# Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 +sudo apt-get update +sudo apt-get install llvm-8 lld-8 clang-8 +``` + +(3) Create a soft link under /usr/bin: + +```Bash +cd /usr/bin +sudo ln -s wasm-ld-8 wasm-ld +``` + +(4) Use the clang-8 command below to build the WASM C source code into the WASM binary. + +```Bash +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined,--export=main \ + -Wl,--strip-all,--no-entry -nostdlib \ + -o test.wasm test.c +``` + +You will get ```test.wasm``` which is the WASM app binary. + +## Use cmake + +If you have a cmake project, you can cross compile your project by using the toolchain provided by WAMR, the compiler used by WAMR toolchain is `clang-8`. + +We can generate a `CMakeLists.txt` file for `test.c`: +```cmake +cmake_minimum_required (VERSION 3.5) +project(hello_world) +add_executable(hello_world test.c) +``` +It is quite simple to build this project by cmake: +```Bash +mkdir build && cd build +cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/test-tools/toolchain/wamr_toolchain.cmake +make +``` +You will get ```hello_world``` which is the WASM app binary. + +For more details about wamr toolchain, please refer to [test-tools/toolchain](../test-tools/toolchain/README.md). + +## Use wasi-sdk + +To build a wasm application with wasi support, wasi-sdk is required. Download the [wasi-sdk](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive, then you can use it to build your application: +```Bash +/path/to/wasi-sdk/bin/clang test.c -o test.wasm +``` + +You will get ```test.wasm``` which is the WASM app binary. + +## Using Docker + +Another method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future. + +Use the clang-8 command below to build the WASM C source code into the WASM binary. + +```Bash +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined,--export=main \ + -Wl,--strip-all,--no-entry -nostdlib \ + -o test.wasm test.c +``` + +You will get ```test.wasm``` which is the WASM app binary. + +## Use Emscripten tool + +The last method to build a WASM binary is to use Emscripten tool ```emcc```. +Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below: + +``` +git clone https://github.com/emscripten-core/emsdk.git +cd emsdk +./emsdk install latest-fastcomp +./emsdk activate latest-fastcomp +``` +The Emscripten website provides other installation methods beyond Linux. + +Use the emcc command below to build the WASM C source code into the WASM binary. +``` Bash +cd emsdk +source emsdk_env.sh (or add it to ~/.bashrc if you don't want to run it each time) +cd +EMCC_ONLY_FORCED_STDLIBS=1 emcc -g -O3 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \ + -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ + -s "EXPORTED_FUNCTIONS=['_main']" -o test.wasm test.c +``` +You will get ```test.wasm``` which is the WASM app binary. + +Run WASM app +======================== + +Assume you are using Linux, the command to run the test.wasm is: +``` Bash +cd iwasm/products/linux/build +./iwasm test.wasm +``` +You will get the following output: +``` +Hello world! +buf ptr: 0x400002b0 +buf: 1234 +``` +If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute: +``` +ninja run +``` diff --git a/doc/export_native_api.md b/doc/export_native_api.md new file mode 100644 index 000000000..55137018c --- /dev/null +++ b/doc/export_native_api.md @@ -0,0 +1,116 @@ + +The mechanism of exporting native API to WASM application +======================================================= + +The basic working flow for WASM application calling into the native API is shown in the following diagram: + +![WAMR WASM API ext diagram](./pics/extend_library.PNG "WAMR WASM API ext architecture diagram") + + +WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library. +``` C +static NativeSymbol extended_native_symbol_defs[] = { + EXPORT_WASM_API(wasm_register_resource), + EXPORT_WASM_API(wasm_response_send), + EXPORT_WASM_API(wasm_post_request), + EXPORT_WASM_API(wasm_sub_event), + EXPORT_WASM_API(wasm_create_timer), + EXPORT_WASM_API(wasm_timer_set_interval), + EXPORT_WASM_API(wasm_timer_cancel), + EXPORT_WASM_API(wasm_timer_restart) +}; +``` + +![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must: +- Only use 32 bits number for parameters +- Should not pass data to the structure pointer (do data serialization instead) +- Should do the pointer address conversion in the native API +- Should not pass function pointer as callback + +Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world. + + + + + +Steps for exporting native API +========================== + +WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps: + +**Step 1. Create a header file**
+Declare the API's for your WASM application source project to include. + +**Step 2. Create a source file**
+Export the platform API's, for example in ``` products/linux/ext_lib_export.c ``` +``` C +#include "lib_export.h" + +static NativeSymbol extended_native_symbol_defs[] = +{ +}; + +#include "ext_lib_export.h" +``` + +**Step 3. Register new API's**
+Use the macro `EXPORT_WASM_API` and `EXPORT_WASM_API2` to add exported API's into the array of ```extended_native_symbol_defs```. +The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function export: +``` c +#define EXPORT_WASM_API(symbol) {#symbol, symbol} +``` + +Below code example shows how to extend the library to support `customized()`: + +``` +//lib_export_impl.c +void customized() +{ + // your code +} + + +// lib_export_dec.h +#ifndef _LIB_EXPORT_DEC_H_ +#define _LIB_EXPORT_DEC_H_ +#ifdef __cplusplus +extern "C" { +#endif + +void customized(); + +#ifdef __cplusplus +} +#endif +#endif + + +// ext_lib_export.c +#include "lib_export.h" +#include "lib_export_dec.h" + +static NativeSymbol extended_native_symbol_defs[] = +{ + EXPORT_WASM_API(customized) +}; + +#include "ext_lib_export.h" +``` + +Use extended library +------------------------ +In the application source project, it will include the WAMR built-in API's header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this: +``` C +#include +#include "lib_export_dec.h" // provided by the platform vendor + +int main(int argc, char **argv) +{ + int I; + char *buf = “abcd”; + customized(); // customized API provided by the platform vendor + return i; +} +``` + + diff --git a/doc/wamr_api.md b/doc/wamr_api.md index 7b46e2220..7001af087 100644 --- a/doc/wamr_api.md +++ b/doc/wamr_api.md @@ -1,5 +1,5 @@ -WASM application library +WAMR application library ======================== WAMR APP API includes built-in Libc API's, Base library and Extension library reference. @@ -89,120 +89,6 @@ bool api_config_connection(connection_t *conn, attr_container_t *cfg); ``` GUI API: The API's is list in header file ```lib/app-libs/extension/gui/wgl.h``` which is implemented based open soure 2D graphic library [LittlevGL](https://docs.littlevgl.com/en/html/index.html). Currently supported widgets include button, label, list and check box and more wigdet would be provided in future. -The mechanism of exporting native API to WASM application -======================================================= - -The basic working flow for WASM application calling into the native API is shown in the following diagram: - -![WAMR WASM API ext diagram](./pics/extend_library.PNG "WAMR WASM API ext architecture diagram") - - -WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library. -``` C -static NativeSymbol extended_native_symbol_defs[] = { - EXPORT_WASM_API(wasm_register_resource), - EXPORT_WASM_API(wasm_response_send), - EXPORT_WASM_API(wasm_post_request), - EXPORT_WASM_API(wasm_sub_event), - EXPORT_WASM_API(wasm_create_timer), - EXPORT_WASM_API(wasm_timer_set_interval), - EXPORT_WASM_API(wasm_timer_cancel), - EXPORT_WASM_API(wasm_timer_restart) -}; -``` - -![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must: -- Only use 32 bits number for parameters -- Should not pass data to the structure pointer (do data serialization instead) -- Should do the pointer address conversion in the native API -- Should not pass function pointer as callback - -Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world. - - - - - -Steps for exporting native API -========================== - -WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps: - -**Step 1. Create a header file**
-Declare the API's for your WASM application source project to include. - -**Step 2. Create a source file**
-Export the platform API's, for example in ``` products/linux/ext_lib_export.c ``` -``` C -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = -{ -}; - -#include "ext_lib_export.h" -``` - -**Step 3. Register new API's**
-Use the macro `EXPORT_WASM_API` and `EXPORT_WASM_API2` to add exported API's into the array of ```extended_native_symbol_defs```. -The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function export: -``` c -#define EXPORT_WASM_API(symbol) {#symbol, symbol} -``` - -Below code example shows how to extend the library to support `customized()`: - -``` -//lib_export_impl.c -void customized() -{ - // your code -} - - -// lib_export_dec.h -#ifndef _LIB_EXPORT_DEC_H_ -#define _LIB_EXPORT_DEC_H_ -#ifdef __cplusplus -extern "C" { -#endif - -void customized(); - -#ifdef __cplusplus -} -#endif -#endif - - -// ext_lib_export.c -#include "lib_export.h" -#include "lib_export_dec.h" - -static NativeSymbol extended_native_symbol_defs[] = -{ - EXPORT_WASM_API(customized) -}; - -#include "ext_lib_export.h" -``` - -Use extended library ------------------------- -In the application source project, it will include the WAMR built-in API's header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this: -``` C -#include -#include "lib_export_dec.h" // provided by the platform vendor - -int main(int argc, char **argv) -{ - int I; - char *buf = “abcd”; - customized(); // customized API provided by the platform vendor - return i; -} -``` - Communication programming models ========================= @@ -307,4 +193,4 @@ void on_destroy() { } ``` -**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for deail usage. \ No newline at end of file +**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for deail usage. diff --git a/test-tools/toolchain/sysroot/include/stdlib.h b/test-tools/toolchain/sysroot/include/stdlib.h index 14ab7c1f7..60e3bea8f 100644 --- a/test-tools/toolchain/sysroot/include/stdlib.h +++ b/test-tools/toolchain/sysroot/include/stdlib.h @@ -15,7 +15,7 @@ typedef unsigned int size_t; int atoi(const char *s); void exit(int status); long strtol(const char *nptr, char **endptr, register int base); -unsigned long strtoul(const char *nptr, char **endptr, register int base) +unsigned long strtoul(const char *nptr, char **endptr, register int base); void *malloc(size_t size); void *calloc(size_t n, size_t size); void free(void *ptr);