diff --git a/Dockerfile b/Dockerfile index 565b740e6..993f11a28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,8 @@ WORKDIR /root RUN git clone https://github.com/intel/wasm-micro-runtime -RUN cd wasm-micro-runtime/core/iwasm/products/linux/ && mkdir build && \ +RUN cd wasm-micro-runtime/product-mini/platforms/linux/ && mkdir build && \ cd build && cmake .. && make RUN cd /usr/bin && ln -s wasm-ld-8 wasm-ld -RUN cd /usr/bin && ln -s ~/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm iwasm +RUN cd /usr/bin && ln -s ~/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm iwasm diff --git a/README.md b/README.md index 3bf0b7b0f..d16353ea8 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ WebAssembly Micro Runtime ========================= -[Building WAMR VM core](./doc/build_wamr.md) | [Embedding WAMR VM core](./doc/embed_wamr.md) | [Building WASM applications](./doc/build_wasm_app.md) | [Samples and demos](https://github.com/bytecodealliance/wasm-micro-runtime#samples-and-demos) +[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples-and-demos) **A [Bytecode Alliance][BA] project** [BA]: https://bytecodealliance.org/ -WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with small footprint. It includes a few parts as below: -- The "iwasm" VM core, supporting WebAssembly interpreter, ahead of time compilation (AoT) and Just-in-Time compilation (JIT) +WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with a small footprint. It includes a few parts as below: +- The **"iwasm" VM core**, supporting WebAssembly interpreter, ahead of time compilation (AoT) and Just-in-Time compilation (JIT) -- The application framework and the supporting API's for the WASM applications +- The **application framework** and the supporting API's for the WASM applications -- The dynamic management of the WASM applications +- The **dynamic management** of the WASM applications @@ -20,16 +20,16 @@ iwasm VM core ### key features -- Embeddable with the supporting C API's +- [Embeddable with the supporting C API's](./doc/embed_wamr.md) - Small runtime binary size (85K for interpreter and 50K for AoT) and low memory usage - Near to native speed by AoT -- AoT module loader works for both embedded OS and Linux system -- Choices of WASM application libc support: the built-in libc subset for embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc -- The mechanism for exporting native API's to WASM applications +- Unique AoT support for embedded systems which have no system loaders +- Choices of WASM application libc support: the built-in libc subset for the embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc +- [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md) ### Supported architectures and platforms -The iwasm supports following architectures: +The iwasm supports the following architectures: - X86-64, X86-32 - ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested) @@ -38,13 +38,7 @@ The iwasm supports following architectures: Following platforms are supported: -- [Linux](./doc/build_wamr.md#linux) -- [Zephyr](./doc/build_wamr.md#zephyr) -- [MacOS](./doc/build_wamr.md#macos) -- [VxWorks](./doc/build_wamr.md#vxworks) -- [AliOS-Things](./doc/build_wamr.md#alios-things) -- [Intel Software Guard Extention (Linux)](./doc/build_wamr.md#linux-sgx-intel-software-guard-extention) -- [Android](./doc/build_wamr.md#android) +- [Linux](./doc/build_wamr.md#linux), [Zephyr](./doc/build_wamr.md#zephyr), [MacOS](./doc/build_wamr.md#macos), [VxWorks](./doc/build_wamr.md#vxworks), [AliOS-Things](./doc/build_wamr.md#alios-things), [Intel Software Guard Extention (Linux)](./doc/build_wamr.md#linux-sgx-intel-software-guard-extention), [Android](./doc/build_wamr.md#android) Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. @@ -55,107 +49,51 @@ Execute following commands to build **wamrc** compiler: ```shell cd wamr-compiler ./build_llvm.sh -mkdir build -cd build +mkdir build && cd build cmake .. make +ln -s ./wamrc /usr/bin/wamrc ``` -After build is completed, create a symbolic link **/usr/bin/wamrc** to the generated wamrc. - ### Build the mini product -WAMR supports building the iwasm VM core only (no app framework) to the mini product. The WAMR mini product takes the WASM application file name as input, and then executes it. For the detailed procedure, see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**. - -### 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. For the details, see [embed WAMR VM core](./doc/embed_wamr.md). +WAMR supports building the iwasm VM core only (no app framework) to the mini product. The WAMR mini product takes the WASM application file name as input and then executes it. For the detailed procedure, see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**. Application framework =================================== -By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some efforts. +By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some effort. -The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, which are based on the event driven programming model. Here are the supporting API sets by the [WAMR application library](./doc/wamr_api.md) : +The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, that are based on the event driven programming model. Here are the supporting API sets by the [WAMR application framework library](./doc/wamr_api.md) : -- Timer -- Micro service (Request/Response) and Pub/Sub inter-app communication -- Sensor -- Connectivity and data transmission -- 2D graphic UI (based on littlevgl) +- Timer, Inter-app communication (request/response and pub/sub), Sensor, Connectivity and data transmission, 2D graphic UI -Every subfolder under [WAMR application framework](./core/app-framework) folder is a compilation configurable component. The developers can copy the template folder to create new components to the application framework. If a component needs to export native functions to the WASM application, refer to the [export_native_api.md](./doc/export_native_api.md) . +Browse the folder [core/app-framework](./core/app-framework) for how to extend the application framework. # Remote application management -The WAMR application manager supports remote application management from host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes. - - - - - -The tool [host_tool](./test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from host system. And the [IoT App Store Demo](./test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from cloud. +The WAMR application manager supports remote application management from the host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes. +The tool [host_tool](./test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from the host system. And the [IoT App Store Demo](./test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from the cloud. +Browse the folder [core/app-mgr](./core/app-mgr) for the details. WAMR SDK ========== -The **wamr-sdk** tools build the WAMR to both **runtime SDK** for embedding by your native codes and **APP SDK** for developing the WASM applications. A SDK profile presents a configuration of build parameters for the selection of CPU arch, software platforms, execution mode, libc and application framework components. +Usually there are two tasks for integrating the WAMR into a particular project: -**Note**: [WASI-SDK](https://github.com/CraneStation/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK. +- Select what WAMR components (vmcore, libc, app-mgr, app-framework components) to be integrated, and get the associated source files added into the project building configuration +- Generate the APP SDK for developing the WASM apps on the selected libc and framework components -### Menu configuration for building SDK - -Menu configuration is supported for easy integration of runtime components and application libraries for the target architecture and platform. - -``` -cd wamr-sdk -./build_sdk.sh -i -n [profile name] -``` - -wamr build menu configuration - -After the menu configuration is finished, the building process is automatically started. When the building gets successful, the SDK package is generated under folder $wamr-sdk/out/{profile}, and the header files of configured components were copied into the SDK package. - -The directory structure of a SDK package with profile name "simple": - -``` -simple/ -├── app-sdk -│   ├── libc-builtin-sysroot -│   │   ├── include -│   │   └── share -│   └── wamr-app-framework -│   ├── include -│   │   ├── bi-inc -│   │   └── wa-inc -│   ├── lib -│   └── share -└── runtime-sdk - ├── include - │   └── bi-inc - └── lib -``` +The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly. It supports menu configuration for selecting WAMR components and builds the WAMR to a SDK package that includes **runtime SDK** and **APP SDK**. The runtime SDK is used for building the native application and the APP SDK should be shipped to WASM application developers. - -### Use Runtime SDK - -The folder "**runtime-sdk**" contains all the header files and library files for integration with project native code. - -### Build WASM applications with APP-SDK - -The folder “**app-sdk**” contains all the header files and WASM library for developing the WASM application. For C/C++ based WASM applications, the developers can use conventional cross-compilation procedure to build the WASM application. Refer to [build WASM applications](./doc/build_wasm_app.md) for the details. - - - - -Samples and demos +Samples ================= The WAMR samples integrate the iwasm VM core, application manager and selected application framework components. The samples are located in folder [samples](./samples): @@ -164,9 +102,6 @@ The WAMR samples integrate the iwasm VM core, application manager and selected a - **[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. It uses **WASI libc** and executes apps in **interpreter** mode by default. -The graphic user interface demo photo: - -![WAMR samples diagram](./doc/pics/vgl_demo.png "WAMR samples diagram") Releases and acknowledgments @@ -182,7 +117,7 @@ Roadmap See the [roadmap](./doc/roadmap.md) to understand what major features are planned or under development. -Please submit issues for any new feature request, or your plan for contributing new features. +Please submit issues for any new feature request or your plan for contributing new features. License diff --git a/core/app-framework/README.md b/core/app-framework/README.md new file mode 100644 index 000000000..0deb4af86 --- /dev/null +++ b/core/app-framework/README.md @@ -0,0 +1,125 @@ +Application framework +======= + +## Directory structure + + + +This folder "app-native-shared" is for the source files shared by both WASM APP and native runtime + +- The c files in this directory are compiled into both the WASM APP and runtime. +- The header files for distributing to SDK are placed in the "bi-inc" folder. + + + +This folder "template" contains a pre-defined directory structure for a framework component. The developers can copy the template folder to create new components to the application framework. + + + +Every other subfolder is framework component. Each component contains two library parts: **app and native**. + +- The "base" component provide timer API and inter-app communication support. It must be enabled if other components are selected. +- Under the "app" folder of a component, the subfolder "wa_inc" holds all header files that should be included by the WASM applications + + + +## Application framework basic model + +The app framework is built on top of two fundamental operations: + +- [Native calls into WASM function](../../doc/embed_wamr.md) + +- [WASM app calls into native API](../../doc/export_native_api.md) + +Asynchronized programming model is supported for WASM applications + +- Every WASM app has its own sandbox and thread + +- Queue and messaging + + + + + +## Customized building of app framework + +A component can be compilation configurable to the runtime. The wamr SDK tool "build_sdk.sh" supports menu config to select app components for building a customized runtime. + +A number of CMAKE variables are defined to control build of framework and components. You can create a cmake file for defining these variables and include it in the CMakeList.txt for your software, or pass it in "-x" argument when run the [build_sdk.sh](../../wamr-sdk/build_sdk.sh) for building the runtime SDK. + +```cmake +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE) +``` + +Variables: + +- **WAMR_BUILD_APP_FRAMEWORK**: enable the application framework +- **WAMR_BUILD_APP_LIST**: the selected components to be built into the final runtime + + + +The configuration file can be generated through the wamr-sdk menu config: + +```bash +cd wamr-sdk +./build_sdk -n [profile] -i +``` + + + +## Create new components + +Generally you should follow following steps to create a new component: + +- Copy the “template” for creating a new folder + +- Implement the app part + + - If your component exports native function to WASM, ensure your created a header file under app for declaring the function prototype. + - If you component provides header files for the WASM applications to include, ensure it is placed under subfolder "wa_inc". + +- Implement the native part + + - If your native function is exported to WASM, you need to create an inl file for the registration. It can be any file name, assuming the file name is "my_component.inl" here: + + ```c + //use right signature for your functions + EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_1, "(i*~)i"), + EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_2, "(i)i"), + ``` + + - Ensure "wasm_lib.cmake" is provided as it will be included by the WAMR SDK building script + + - Add a definition in "wasm_lib.cmake" for your component, e.g. + + ```cmake + add_definitions (-DAPP_FRAMEWORK_MY_COMPONENT) + ``` + +- Modify the file [app_ext_lib_export.c](./app_ext_lib_export.c) to register native APIs exported for the new introduced component. Skip it if not exporting native functions. + + ``` + #include "lib_export.h" + + ... + #ifdef APP_FRAMEWORK_MY_COMPONENT // this definition is created in wasm_lib.cmake + #include "my_component_native_api.h" + #endif + + static NativeSymbol extended_native_symbol_defs[] = { + ... + #ifdef APP_FRAMEWORK_MY_COMPONENT + #include "my_component.inl" + #endif + }; + ``` + + + +## Sensor component working flow + + + +![](../../doc/pics/sensor_callflow.PNG) + diff --git a/core/app-framework/app-native-shared/native_interface.h b/core/app-framework/app-native-shared/native_interface.h index 0c094267a..0e0d063b1 100644 --- a/core/app-framework/app-native-shared/native_interface.h +++ b/core/app-framework/app-native-shared/native_interface.h @@ -26,8 +26,8 @@ #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_malloc(size, p_native_addr) \ + wasm_runtime_module_malloc(module_inst, size, p_native_addr) #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) diff --git a/core/app-framework/app_ext_lib_export.c b/core/app-framework/app_ext_lib_export.c new file mode 100644 index 000000000..6e66fdfb6 --- /dev/null +++ b/core/app-framework/app_ext_lib_export.c @@ -0,0 +1,39 @@ +#include "lib_export.h" + +#ifdef APP_FRAMEWORK_SENSOR + #include "sensor_native_api.h" +#endif + +#ifdef APP_FRAMEWORK_CONNECTION + #include "connection_native_api.h" +#endif + +#ifdef APP_FRAMEWORK_WGL + #include "gui_native_api.h" +#endif + +/* More header file here */ + +static NativeSymbol extended_native_symbol_defs[] = { +#ifdef APP_FRAMEWORK_SENSOR + #include "runtime_sensor.inl" +#endif + +#ifdef APP_FRAMEWORK_CONNECTION + #include "connection.inl" +#endif + +#ifdef APP_FRAMEWORK_WGL + #include "wamr_gui.inl" +#endif + +/* More inl file here */ +}; + +int +get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis) +{ + *p_ext_lib_apis = extended_native_symbol_defs; + return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol); +} + diff --git a/core/app-framework/app_framework.cmake b/core/app-framework/app_framework.cmake index 68439d874..8ad43dec1 100644 --- a/core/app-framework/app_framework.cmake +++ b/core/app-framework/app_framework.cmake @@ -1,8 +1,15 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +add_definitions (-DWASM_ENABLE_APP_FRAMEWORK=1) + set (APP_FRAMEWORK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) +if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE ) + LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${CMAKE_CURRENT_LIST_DIR}/app_ext_lib_export.c) +endif() + # app-native-shared and base are required include (${APP_FRAMEWORK_ROOT_DIR}/app-native-shared/native_interface.cmake) LIST (APPEND WASM_APP_SOURCE_ALL ${NATIVE_INTERFACE_SOURCE}) @@ -31,10 +38,6 @@ function (add_module_native arg) LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_CURRENT_SOURCE}) set (WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_SOURCE_ALL} PARENT_SCOPE) - - # VARIABLES in function are only used in this scope, - # set PARENT_SCOPE to pass to top CMakeLists - set (WASM_LIB_BASE_SOURCE ${WASM_LIB_BASE_SOURCE} PARENT_SCOPE) endfunction () function (add_module_app arg) @@ -83,4 +86,4 @@ else () endif () ENDFOREACH (dir) -endif() \ No newline at end of file +endif() diff --git a/core/app-framework/base/native/base_lib.inl b/core/app-framework/base/native/base_lib.inl index 84df855f8..3c228cc93 100644 --- a/core/app-framework/base/native/base_lib.inl +++ b/core/app-framework/base/native/base_lib.inl @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ - 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_destroy), - EXPORT_WASM_API(wasm_timer_cancel), - EXPORT_WASM_API(wasm_timer_restart), - EXPORT_WASM_API(wasm_get_sys_tick_ms), + EXPORT_WASM_API_WITH_SIG(wasm_register_resource, "($)"), + EXPORT_WASM_API_WITH_SIG(wasm_response_send, "(*~)i"), + EXPORT_WASM_API_WITH_SIG(wasm_post_request, "(*~)"), + EXPORT_WASM_API_WITH_SIG(wasm_sub_event, "($)"), + EXPORT_WASM_API_WITH_SIG(wasm_create_timer, "(iii)i"), + EXPORT_WASM_API_WITH_SIG(wasm_timer_destroy, "(i)"), + EXPORT_WASM_API_WITH_SIG(wasm_timer_cancel, "(i)"), + EXPORT_WASM_API_WITH_SIG(wasm_timer_restart, "(ii)"), + EXPORT_WASM_API_WITH_SIG(wasm_get_sys_tick_ms, "()i"), diff --git a/core/app-framework/base/native/req_resp_native_api.h b/core/app-framework/base/native/req_resp_native_api.h index 7e8592b89..6fe0581b6 100644 --- a/core/app-framework/base/native/req_resp_native_api.h +++ b/core/app-framework/base/native/req_resp_native_api.h @@ -14,19 +14,13 @@ extern "C" { #endif bool -wasm_response_send(wasm_exec_env_t exec_env, - int32 buffer_offset, int size); +wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size); void -wasm_register_resource(wasm_exec_env_t exec_env, - int32 url_offset); +wasm_register_resource(wasm_exec_env_t exec_env, char *url); void -wasm_post_request(wasm_exec_env_t exec_env, - int32 buffer_offset, int size); +wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size); void -wasm_sub_event(wasm_exec_env_t exec_env, - int32 url_offset); - - +wasm_sub_event(wasm_exec_env_t exec_env, char *url); #ifdef __cplusplus } diff --git a/core/app-framework/base/native/request_response.c b/core/app-framework/base/native/request_response.c index 2d725d35d..4088c3885 100644 --- a/core/app-framework/base/native/request_response.c +++ b/core/app-framework/base/native/request_response.c @@ -11,17 +11,8 @@ extern void module_request_handler(request_t *request, void *user_data); bool -wasm_response_send(wasm_exec_env_t exec_env, - int32 buffer_offset, int size) +wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *buffer = NULL; - - if (!validate_app_addr(buffer_offset, size)) - return false; - - buffer = addr_app_to_native(buffer_offset); - if (buffer != NULL) { response_t response[1]; @@ -37,15 +28,9 @@ wasm_response_send(wasm_exec_env_t exec_env, } void -wasm_register_resource(wasm_exec_env_t exec_env, int32 url_offset) +wasm_register_resource(wasm_exec_env_t exec_env, char *url) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *url = NULL; - - if (!validate_app_str_addr(url_offset)) - return; - - url = addr_app_to_native(url_offset); if (url != NULL) { unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, @@ -56,16 +41,9 @@ wasm_register_resource(wasm_exec_env_t exec_env, int32 url_offset) } void -wasm_post_request(wasm_exec_env_t exec_env, - int32 buffer_offset, int size) +wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *buffer = NULL; - - if (!validate_app_addr(buffer_offset, size)) - return; - - buffer = addr_app_to_native(buffer_offset); if (buffer != NULL) { request_t req[1]; @@ -91,15 +69,9 @@ wasm_post_request(wasm_exec_env_t exec_env, } void -wasm_sub_event(wasm_exec_env_t exec_env, int32 url_offset) +wasm_sub_event(wasm_exec_env_t exec_env, char *url) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *url = NULL; - - if (!validate_app_str_addr(url_offset)) - return; - - url = addr_app_to_native(url_offset); if (url != NULL) { unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, diff --git a/core/app-framework/connection/native/connection.inl b/core/app-framework/connection/native/connection.inl index 2956e2696..b2d01aa9f 100644 --- a/core/app-framework/connection/native/connection.inl +++ b/core/app-framework/connection/native/connection.inl @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -EXPORT_WASM_API(wasm_open_connection), -EXPORT_WASM_API(wasm_close_connection), -EXPORT_WASM_API(wasm_send_on_connection), -EXPORT_WASM_API(wasm_config_connection), +EXPORT_WASM_API_WITH_SIG(wasm_open_connection, "($*~)i"), +EXPORT_WASM_API_WITH_SIG(wasm_close_connection, "(i)"), +EXPORT_WASM_API_WITH_SIG(wasm_send_on_connection, "(i*~)i"), +EXPORT_WASM_API_WITH_SIG(wasm_config_connection, "(i*~)i"), diff --git a/core/app-framework/connection/native/connection_native_api.h b/core/app-framework/connection/native/connection_native_api.h index 3b4fcaa54..79e911d19 100644 --- a/core/app-framework/connection/native/connection_native_api.h +++ b/core/app-framework/connection/native/connection_native_api.h @@ -20,16 +20,16 @@ extern "C" { uint32 wasm_open_connection(wasm_exec_env_t exec_env, - int32 name_offset, int32 args_offset, uint32 len); + char *name, char *args_buf, uint32 len); void wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle); int wasm_send_on_connection(wasm_exec_env_t exec_env, - uint32 handle, int32 data_offset, uint32 len); + uint32 handle, char *data, uint32 len); bool wasm_config_connection(wasm_exec_env_t exec_env, - uint32 handle, int32 cfg_offset, uint32 len); + uint32 handle, char *cfg_buf, uint32 len); diff --git a/core/app-framework/connection/native/connection_wrapper.c b/core/app-framework/connection/native/connection_wrapper.c index b60a24988..742a45b28 100644 --- a/core/app-framework/connection/native/connection_wrapper.c +++ b/core/app-framework/connection/native/connection_wrapper.c @@ -16,17 +16,10 @@ uint32 wasm_open_connection(wasm_exec_env_t exec_env, - int32 name_offset, int32 args_offset, uint32 len) + char *name, char *args_buf, uint32 len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); attr_container_t *args; - char *name, *args_buf; - - if (!validate_app_str_addr(name_offset) || - !validate_app_addr(args_offset, len) || - !(name = addr_app_to_native(name_offset)) || - !(args_buf = addr_app_to_native(args_offset))) - return -1; args = (attr_container_t *)args_buf; @@ -45,15 +38,8 @@ wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle) int wasm_send_on_connection(wasm_exec_env_t exec_env, - uint32 handle, int32 data_offset, uint32 len) + uint32 handle, char *data, uint32 len) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *data; - - if (!validate_app_addr(data_offset, len) || - !(data = addr_app_to_native(data_offset))) - return -1; - if (connection_impl._send != NULL) return connection_impl._send(handle, data, len); @@ -62,16 +48,10 @@ wasm_send_on_connection(wasm_exec_env_t exec_env, bool wasm_config_connection(wasm_exec_env_t exec_env, - uint32 handle, int32 cfg_offset, uint32 len) + uint32 handle, char *cfg_buf, uint32 len) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *cfg_buf; attr_container_t *cfg; - if (!validate_app_addr(cfg_offset, len) || - !(cfg_buf = addr_app_to_native(cfg_offset))) - return false; - cfg = (attr_container_t *)cfg_buf; if (connection_impl._config != NULL) diff --git a/core/app-framework/connection/native/wasm_lib.cmake b/core/app-framework/connection/native/wasm_lib.cmake index d78763f74..58db0c1d8 100644 --- a/core/app-framework/connection/native/wasm_lib.cmake +++ b/core/app-framework/connection/native/wasm_lib.cmake @@ -5,6 +5,9 @@ set (WASM_LIB_CONN_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${WASM_LIB_CONN_DIR}) +add_definitions (-DAPP_FRAMEWORK_CONNECTION) + + include (${CMAKE_CURRENT_LIST_DIR}/${WAMR_BUILD_PLATFORM}/connection_mgr.cmake) file (GLOB source_all diff --git a/core/app-framework/sensor/native/runtime_sensor.c b/core/app-framework/sensor/native/runtime_sensor.c index 5a10434cb..63a03983d 100644 --- a/core/app-framework/sensor/native/runtime_sensor.c +++ b/core/app-framework/sensor/native/runtime_sensor.c @@ -135,15 +135,9 @@ wasm_sensor_config(wasm_exec_env_t exec_env, uint32 wasm_sensor_open(wasm_exec_env_t exec_env, - int32 name_offset, int instance) + char *name, int instance) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *name = NULL; - - if (!validate_app_str_addr(name_offset)) - return -1; - - name = addr_app_to_native(name_offset); if (name != NULL) { sensor_client_t *c; @@ -192,17 +186,8 @@ wasm_sensor_open(wasm_exec_env_t exec_env, bool wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, - uint32 sensor, int32 buffer_offset, - int len) + uint32 sensor, char *buffer, int len) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *buffer = NULL; - - if (!validate_app_addr(buffer_offset, len)) - return false; - - buffer = addr_app_to_native(buffer_offset); - if (buffer != NULL) { attr_container_t *cfg = (attr_container_t *)buffer; sensor_obj_t s = find_sys_sensor_id(sensor); diff --git a/core/app-framework/sensor/native/runtime_sensor.inl b/core/app-framework/sensor/native/runtime_sensor.inl index 1b7af765b..a7b9f4778 100644 --- a/core/app-framework/sensor/native/runtime_sensor.inl +++ b/core/app-framework/sensor/native/runtime_sensor.inl @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -EXPORT_WASM_API(wasm_sensor_open), -EXPORT_WASM_API(wasm_sensor_config), -EXPORT_WASM_API(wasm_sensor_config_with_attr_container), -EXPORT_WASM_API(wasm_sensor_close), +EXPORT_WASM_API_WITH_SIG(wasm_sensor_open, "($i)i"), +EXPORT_WASM_API_WITH_SIG(wasm_sensor_config, "(iiii)i"), +EXPORT_WASM_API_WITH_SIG(wasm_sensor_config_with_attr_container, "(i*~)i"), +EXPORT_WASM_API_WITH_SIG(wasm_sensor_close, "(i)i"), diff --git a/core/app-framework/sensor/native/sensor_native_api.h b/core/app-framework/sensor/native/sensor_native_api.h index 5cc8ad836..ed323174e 100644 --- a/core/app-framework/sensor/native/sensor_native_api.h +++ b/core/app-framework/sensor/native/sensor_native_api.h @@ -19,12 +19,11 @@ wasm_sensor_config(wasm_exec_env_t exec_env, int bit_cfg, int delay); uint32 wasm_sensor_open(wasm_exec_env_t exec_env, - int32 name_offset, int instance); + char *name, int instance); bool wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, - uint32 sensor, int32 buffer_offset, - int len); + uint32 sensor, char *buffer, int len); bool wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor); diff --git a/core/app-framework/sensor/native/wasm_lib.cmake b/core/app-framework/sensor/native/wasm_lib.cmake index e233334c1..65a83ba59 100644 --- a/core/app-framework/sensor/native/wasm_lib.cmake +++ b/core/app-framework/sensor/native/wasm_lib.cmake @@ -3,6 +3,8 @@ set (WASM_LIB_SENSOR_DIR ${CMAKE_CURRENT_LIST_DIR}) +add_definitions (-DAPP_FRAMEWORK_SENSOR) + include_directories(${WASM_LIB_SENSOR_DIR}) diff --git a/core/app-framework/wgl/native/gui_native_api.h b/core/app-framework/wgl/native/gui_native_api.h index 57d987104..f61d9b51a 100644 --- a/core/app-framework/wgl/native/gui_native_api.h +++ b/core/app-framework/wgl/native/gui_native_api.h @@ -20,23 +20,23 @@ extern "C" { void wasm_obj_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc); + int32 func_id, uint32 *argv, uint32 argc); void wasm_btn_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc); + int32 func_id, uint32 *argv, uint32 argc); void wasm_label_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc); + int32 func_id, uint32 *argv, uint32 argc); void wasm_cb_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc); + int32 func_id, uint32 *argv, uint32 argc); void wasm_list_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc); + int32 func_id, uint32 *argv, uint32 argc); #ifdef __cplusplus } diff --git a/core/app-framework/wgl/native/wamr_gui.inl b/core/app-framework/wgl/native/wamr_gui.inl index 908a19155..c7855b17b 100644 --- a/core/app-framework/wgl/native/wamr_gui.inl +++ b/core/app-framework/wgl/native/wamr_gui.inl @@ -4,25 +4,25 @@ */ /* button */ -EXPORT_WASM_API(wasm_btn_native_call), +EXPORT_WASM_API_WITH_SIG(wasm_btn_native_call, "(i*i)"), /* obj */ -EXPORT_WASM_API(wasm_obj_native_call), +EXPORT_WASM_API_WITH_SIG(wasm_obj_native_call, "(i*i)"), /* label */ -EXPORT_WASM_API(wasm_label_native_call), +EXPORT_WASM_API_WITH_SIG(wasm_label_native_call, "(i*i)"), /* cont */ -//EXPORT_WASM_API(wasm_cont_native_call), +//EXPORT_WASM_API_WITH_SIG(wasm_cont_native_call, "(i*i)"), /* page */ -//EXPORT_WASM_API(wasm_page_native_call), +//EXPORT_WASM_API_WITH_SIG(wasm_page_native_call, "(i*i)"), /* list */ -EXPORT_WASM_API(wasm_list_native_call), +EXPORT_WASM_API_WITH_SIG(wasm_list_native_call, "(i*i)"), /* drop down list */ -//EXPORT_WASM_API(wasm_ddlist_native_call), +//EXPORT_WASM_API_WITH_SIG(wasm_ddlist_native_call, "(i*i)"), /* check box */ -EXPORT_WASM_API(wasm_cb_native_call), +EXPORT_WASM_API_WITH_SIG(wasm_cb_native_call, "(i*i)"), diff --git a/core/app-framework/wgl/native/wasm_lib.cmake b/core/app-framework/wgl/native/wasm_lib.cmake index d2ccf3c25..b452fb114 100644 --- a/core/app-framework/wgl/native/wasm_lib.cmake +++ b/core/app-framework/wgl/native/wasm_lib.cmake @@ -6,6 +6,7 @@ set (WASM_LIB_GUI_DIR ${CMAKE_CURRENT_LIST_DIR}) set (DEPS_DIR ${WASM_LIB_GUI_DIR}/../../../deps) add_definitions(-DLV_CONF_INCLUDE_SIMPLE) +add_definitions (-DAPP_FRAMEWORK_WGL) include_directories(${WASM_LIB_GUI_DIR} ${DEPS_DIR} diff --git a/core/app-framework/wgl/native/wgl_btn_wrapper.c b/core/app-framework/wgl/native/wgl_btn_wrapper.c index 7a08062e9..4fd35e39f 100644 --- a/core/app-framework/wgl/native/wgl_btn_wrapper.c +++ b/core/app-framework/wgl/native/wgl_btn_wrapper.c @@ -126,7 +126,7 @@ static WGLNativeFuncDef btn_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void wasm_btn_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc) + int32 func_id, uint32 *argv, uint32 argc) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef); @@ -135,6 +135,6 @@ wasm_btn_native_call(wasm_exec_env_t exec_env, btn_native_func_defs, size, func_id, - argv_offset, + argv, argc); } diff --git a/core/app-framework/wgl/native/wgl_cb_wrapper.c b/core/app-framework/wgl/native/wgl_cb_wrapper.c index d0609b402..77ea8e9ee 100644 --- a/core/app-framework/wgl/native/wgl_cb_wrapper.c +++ b/core/app-framework/wgl/native/wgl_cb_wrapper.c @@ -73,7 +73,7 @@ static WGLNativeFuncDef cb_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void wasm_cb_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc) + int32 func_id, uint32 *argv, uint32 argc) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef); @@ -82,6 +82,6 @@ wasm_cb_native_call(wasm_exec_env_t exec_env, cb_native_func_defs, size, func_id, - argv_offset, + argv, argc); } diff --git a/core/app-framework/wgl/native/wgl_label_wrapper.c b/core/app-framework/wgl/native/wgl_label_wrapper.c index 2aaa38594..8106c73d4 100644 --- a/core/app-framework/wgl/native/wgl_label_wrapper.c +++ b/core/app-framework/wgl/native/wgl_label_wrapper.c @@ -64,7 +64,7 @@ static WGLNativeFuncDef label_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void wasm_label_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc) + int32 func_id, uint32 *argv, uint32 argc) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef); @@ -73,6 +73,6 @@ wasm_label_native_call(wasm_exec_env_t exec_env, label_native_func_defs, size, func_id, - argv_offset, + argv, argc); } diff --git a/core/app-framework/wgl/native/wgl_list_wrapper.c b/core/app-framework/wgl/native/wgl_list_wrapper.c index 2db29481b..98430b750 100644 --- a/core/app-framework/wgl/native/wgl_list_wrapper.c +++ b/core/app-framework/wgl/native/wgl_list_wrapper.c @@ -49,7 +49,7 @@ static WGLNativeFuncDef list_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void wasm_list_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc) + int32 func_id, uint32 *argv, uint32 argc) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef); @@ -58,6 +58,6 @@ wasm_list_native_call(wasm_exec_env_t exec_env, list_native_func_defs, size, func_id, - argv_offset, + argv, argc); } diff --git a/core/app-framework/wgl/native/wgl_native_utils.c b/core/app-framework/wgl/native/wgl_native_utils.c index 5fdaffdd7..353329802 100644 --- a/core/app-framework/wgl/native/wgl_native_utils.c +++ b/core/app-framework/wgl/native/wgl_native_utils.c @@ -109,17 +109,11 @@ void wgl_native_func_call(wasm_module_inst_t module_inst, WGLNativeFuncDef *funcs, uint32 size, int32 func_id, - uint32 argv_offset, + uint32 *argv, uint32 argc) { WGLNativeFuncDef *func_def = funcs; WGLNativeFuncDef *func_def_end = func_def + size; - uint32 *argv; - - if (!validate_app_addr(argv_offset, argc * sizeof(uint32))) - return; - - argv = addr_app_to_native(argv_offset); while (func_def < func_def_end) { if (func_def->func_id == func_id) { diff --git a/core/app-framework/wgl/native/wgl_native_utils.h b/core/app-framework/wgl/native/wgl_native_utils.h index cc8b2d215..fdb5e505a 100644 --- a/core/app-framework/wgl/native/wgl_native_utils.h +++ b/core/app-framework/wgl/native/wgl_native_utils.h @@ -74,7 +74,7 @@ void wgl_native_func_call(wasm_module_inst_t module_inst, WGLNativeFuncDef *funcs, uint32 size, int32 func_id, - uint32 argv_offset, + uint32 *argv, uint32 argc); #ifdef __cplusplus diff --git a/core/app-framework/wgl/native/wgl_obj_wrapper.c b/core/app-framework/wgl/native/wgl_obj_wrapper.c index d8116571f..9f2940ff9 100644 --- a/core/app-framework/wgl/native/wgl_obj_wrapper.c +++ b/core/app-framework/wgl/native/wgl_obj_wrapper.c @@ -378,7 +378,7 @@ static WGLNativeFuncDef obj_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void wasm_obj_native_call(wasm_exec_env_t exec_env, - int32 func_id, uint32 argv_offset, uint32 argc) + int32 func_id, uint32 *argv, uint32 argc) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef); @@ -387,6 +387,6 @@ wasm_obj_native_call(wasm_exec_env_t exec_env, obj_native_func_defs, size, func_id, - argv_offset, + argv, argc); } diff --git a/core/app-mgr/README.md b/core/app-mgr/README.md new file mode 100644 index 000000000..d5e058815 --- /dev/null +++ b/core/app-mgr/README.md @@ -0,0 +1,10 @@ +WASM application management +======= + +## structure + + + + + + diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 8915103ab..211ba61f9 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -735,42 +735,13 @@ fail: } static void -destroy_import_funcs(AOTImportFunc *import_funcs, bool is_jit_mode) +destroy_import_funcs(AOTImportFunc *import_funcs, + bool is_jit_mode) { if (!is_jit_mode) wasm_free(import_funcs); } -static void* -resolve_sym(const char *module_name, const char *field_name) -{ - void *sym; - -#if WASM_ENABLE_LIBC_BUILTIN != 0 - if ((sym = wasm_native_lookup_libc_builtin_func(module_name, - field_name))) - return sym; -#endif - -#if WASM_ENABLE_LIBC_WASI != 0 - if ((sym = wasm_native_lookup_libc_wasi_func(module_name, - field_name))) - return sym; -#endif - -#if WASM_ENABLE_BASE_LIB != 0 - if ((sym = wasm_native_lookup_base_lib_func(module_name, - field_name))) - return sym; -#endif - - if ((sym = wasm_native_lookup_extension_lib_func(module_name, - field_name))) - return sym; - - return NULL; -} - static bool load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, @@ -804,13 +775,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, "invalid function type index."); return false; } + import_funcs[i].func_type = module->func_types[import_funcs[i].func_type_index]; read_string(buf, buf_end, import_funcs[i].module_name); read_string(buf, buf_end, import_funcs[i].func_name); module_name = import_funcs[i].module_name; field_name = import_funcs[i].func_name; if (!(import_funcs[i].func_ptr_linked = - resolve_sym(module_name, field_name))) { + wasm_native_resolve_symbol(module_name, field_name, + import_funcs[i].func_type, + &import_funcs[i].signature))) { LOG_WARNING("warning: fail to link import function (%s, %s)\n", module_name, field_name); } @@ -2053,46 +2027,61 @@ aot_unload(AOTModule *module) #if WASM_ENABLE_JIT != 0 if (module->comp_data) aot_destroy_comp_data(module->comp_data); + if (module->comp_ctx) aot_destroy_comp_context(module->comp_ctx); + if (module->wasm_module) wasm_loader_unload(module->wasm_module); #endif + if (module->mem_init_data_list) destroy_mem_init_data_list(module->mem_init_data_list, module->mem_init_data_count, module->is_jit_mode); + if (module->table_init_data_list) destroy_table_init_data_list(module->table_init_data_list, module->table_init_data_count, module->is_jit_mode); + if (module->func_types) destroy_func_types(module->func_types, module->func_type_count, module->is_jit_mode); + if (module->import_globals) destroy_import_globals(module->import_globals, module->is_jit_mode); + if (module->globals) destroy_globals(module->globals, module->is_jit_mode); + if (module->import_funcs) destroy_import_funcs(module->import_funcs, module->is_jit_mode); + if (module->export_funcs) destroy_export_funcs(module->export_funcs, module->is_jit_mode); + if (module->func_type_indexes) wasm_free(module->func_type_indexes); + if (module->func_ptrs) wasm_free(module->func_ptrs); + if (module->const_str_set) bh_hash_map_destroy(module->const_str_set); + if (module->code) bh_munmap(module->code, module->code_size); + if (module->data_sections) destroy_object_data_sections(module->data_sections, module->data_section_count); + wasm_free(module); } diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 9102b89ec..02931dd29 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -16,6 +16,7 @@ typedef struct { REG_SYM(aot_set_exception_with_id), \ REG_SYM(aot_get_exception), \ REG_SYM(aot_is_wasm_type_equal), \ + REG_SYM(aot_invoke_native), \ REG_SYM(wasm_runtime_enlarge_memory), \ REG_SYM(wasm_runtime_set_exception), \ REG_SYM(fmin), \ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 9deacf0c9..44c7d48fd 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -28,7 +28,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Initialize import global data */ for (i = 0; i < module->import_global_count; i++, import_global++) { bh_assert(import_global->data_offset == - p - (uint8*)module_inst->global_data.ptr); + (uint32)(p - (uint8*)module_inst->global_data.ptr)); memcpy(p, &import_global->global_data_linked, import_global->size); p += import_global->size; } @@ -36,7 +36,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Initialize defined global data */ for (i = 0; i < module->global_count; i++, global++) { bh_assert(global->data_offset == - p - (uint8*)module_inst->global_data.ptr); + (uint32)(p - (uint8*)module_inst->global_data.ptr)); init_expr = &global->init_expr; switch (init_expr->init_expr_type) { case INIT_EXPR_TYPE_GET_GLOBAL: @@ -53,7 +53,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, p += global->size; } - bh_assert(module_inst->global_data_size == p - (uint8*)module_inst->global_data.ptr); + bh_assert(module_inst->global_data_size == + (uint32)(p - (uint8*)module_inst->global_data.ptr)); return true; } @@ -420,65 +421,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst) wasm_free(module_inst); } -static bool -check_type(uint8 type, const char *p) -{ - const char *str = "i32"; - - if (strlen(p) < 3) - return false; - - switch (type) { - case VALUE_TYPE_I32: - str = "i32"; - break; - case VALUE_TYPE_I64: - str = "i64"; - break; - case VALUE_TYPE_F32: - str = "f32"; - break; - case VALUE_TYPE_F64: - str = "f64"; - break; - } - if (strncmp(p, str, 3)) - return false; - - return true; -} - -static bool -check_function_type(const WASMType *type, - const char *signature) -{ - uint32 i; - const char *p = signature; - - if (!p || *p++ != '(') - return false; - - for (i = 0; i < type->param_count; i++) { - if (!check_type(type->types[i], p)) - return false; - p += 3; - } - - if (*p++ != ')') - return false; - - if (type->result_count) { - if (!check_type(type->types[type->param_count], p)) - return false; - p += 3; - } - - if (*p != '\0') - return false; - - return true; -} - AOTFunctionInstance* aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, const char *signature) @@ -486,13 +428,10 @@ aot_lookup_function(const AOTModuleInstance *module_inst, uint32 i; AOTModule *module = (AOTModule*)module_inst->aot_module.ptr; - for (i = 0; i < module->export_func_count; i++) { - if (!strcmp(module->export_funcs[i].func_name, name) - && check_function_type(module->export_funcs[i].func_type, - signature)) + for (i = 0; i < module->export_func_count; i++) + if (!strcmp(module->export_funcs[i].func_name, name)) return &module->export_funcs[i]; - } - + (void)signature; return NULL; } @@ -517,8 +456,8 @@ aot_call_function(WASMExecEnv *exec_env, { AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst; AOTFuncType *func_type = function->func_type; - bool ret = wasm_runtime_invoke_native(function->func_ptr, func_type, - exec_env, argv, argc, argv); + bool ret = wasm_runtime_invoke_native(exec_env, function->func_ptr, + func_type, NULL, argv, argc, argv); return ret && !aot_get_exception(module_inst) ? true : false; } @@ -612,11 +551,14 @@ aot_clear_exception(AOTModuleInstance *module_inst) } int32 -aot_module_malloc(AOTModuleInstance *module_inst, uint32 size) +aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, + void **p_native_addr) { uint8 *addr = mem_allocator_malloc(module_inst->heap_handle.ptr, size); + if (p_native_addr) + *p_native_addr = addr; if (!addr) { aot_set_exception(module_inst, "out of memory"); return 0; @@ -641,10 +583,11 @@ int32 aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, uint32 size) { - int32 buffer_offset = aot_module_malloc(module_inst, size); + char *buffer; + int32 buffer_offset = aot_module_malloc(module_inst, size, + (void**)&buffer); if (buffer_offset != 0) { - char *buffer; buffer = aot_addr_app_to_native(module_inst, buffer_offset); memcpy(buffer, src, size); } @@ -858,3 +801,35 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst, return wasm_type_equal(type1, type2); } + +void +aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, + uint32 *frame_lp, uint32 argc, uint32 *argv_ret) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance*) + wasm_runtime_get_module_inst(exec_env); + AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr; + uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr; + uint32 func_type_idx = func_type_indexes[func_idx]; + AOTFuncType *func_type = aot_module->func_types[func_type_idx]; + void **func_ptrs = (void**)module_inst->func_ptrs.ptr; + void *func_ptr = func_ptrs[func_idx]; + AOTImportFunc *import_func; + const char *signature = NULL; + char buf[128]; + + if (func_idx < aot_module->import_func_count) { + import_func = aot_module->import_funcs + func_idx; + if (!func_ptr) { + snprintf(buf, sizeof(buf), + "fail to call unlinked import function (%s, %s)", + import_func->module_name, import_func->func_name); + aot_set_exception(module_inst, buf); + return; + } + signature = import_func->signature; + } + wasm_runtime_invoke_native(exec_env, func_ptr, + func_type, signature, frame_lp, argc, argv_ret); +} + diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 5a941321a..977d3ec96 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -141,7 +141,7 @@ typedef struct AOTModule { /* is jit mode or not */ bool is_jit_mode; -#if WASM_ENABLE_JIT +#if WASM_ENABLE_JIT != 0 WASMModule *wasm_module; AOTCompContext *comp_ctx; AOTCompData *comp_data; @@ -379,7 +379,8 @@ void aot_clear_exception(AOTModuleInstance *module_inst); int32 -aot_module_malloc(AOTModuleInstance *module_inst, uint32 size); +aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, + void **p_native_addr); void aot_module_free(AOTModuleInstance *module_inst, int32 ptr); @@ -431,6 +432,13 @@ bool aot_is_wasm_type_equal(AOTModuleInstance *module_inst, uint32 type1_idx, uint32 type2_idx); +/** + * Invoke native function from aot code + */ +void +aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, + uint32 *frame_lp, uint32 argc, uint32 *argv_ret); + uint32 aot_get_plt_table_size(); diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 6e7054e26..92ec42c96 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -20,6 +20,14 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, return NULL; memset(exec_env, 0, (uint32)total_size); + +#if WASM_ENABLE_AOT != 0 + if (!(exec_env->argv_buf = wasm_malloc(sizeof(uint32) * 64))) { + wasm_free(exec_env); + return NULL; + } +#endif + exec_env->module_inst = module_inst; exec_env->wasm_stack_size = stack_size; exec_env->wasm_stack.s.top_boundary = @@ -31,6 +39,9 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, void wasm_exec_env_destroy(WASMExecEnv *exec_env) { +#if WASM_ENABLE_AOT != 0 + wasm_free(exec_env->argv_buf); +#endif wasm_free(exec_env); } diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index d2d49b869..d25469669 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -30,6 +30,10 @@ typedef struct WASMExecEnv { /* The WASM module instance of current thread */ struct WASMModuleInstanceCommon *module_inst; +#if WASM_ENABLE_AOT != 0 + uint32 *argv_buf; +#endif + /* Current interpreter frame of current thread */ struct WASMInterpFrame *cur_frame; diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index d7244391c..29b762da8 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -4,44 +4,124 @@ */ #include "wasm_native.h" +#include "wasm_runtime_common.h" +#include "bh_log.h" -typedef struct NativeSymbol { - const char *symbol; - void *func_ptr; -} NativeSymbol; +static NativeSymbolsList g_native_symbols_list = NULL; +static NativeSymbolsList g_native_symbols_list_end = NULL; + +uint32 +get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis); + +uint32 +get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis); + +uint32 +get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis); + +uint32 +get_base_lib_export_apis(NativeSymbol **p_base_lib_apis); + +uint32 +get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis); static bool -sort_symbol_ptr(NativeSymbol *ptr, int len) +check_symbol_signature(const WASMType *type, const char *signature) { - int i, j; - NativeSymbol temp; + const char *p = signature, *p_end; + char sig_map[] = { 'F', 'f', 'I', 'i' }, sig; + uint32 i = 0; - for (i = 0; i < len - 1; ++i) { - for (j = i + 1; j < len; ++j) { - if (strcmp((ptr+i)->symbol, (ptr+j)->symbol) > 0) { - temp = ptr[i]; - ptr[i] = ptr[j]; - ptr[j] = temp; + if (!p || strlen(p) < 2) + return false; + + p_end = p + strlen(signature); + + if (*p++ != '(') + return false; + + if ((uint32)(p_end - p) < type->param_count + 1) + /* signatures of parameters, and ')' */ + return false; + + for (i = 0; i < type->param_count; i++) { + sig = *p++; + if (sig == sig_map[type->types[i] - VALUE_TYPE_F64]) + /* normal parameter */ + continue; + + if (type->types[i] != VALUE_TYPE_I32) + /* pointer and string must be i32 type */ + return false; + + if (sig == '*') { + /* it is a pointer */ + if (i + 1 < type->param_count + && type->types[i + 1] == VALUE_TYPE_I32 + && *p == '~') { + /* pointer length followed */ + i++; + p++; } } + else if (sig == '$') { + /* it is a string */ + } + else { + /* invalid signature */ + return false; + } } + if (*p++ != ')') + return false; + + if (type->result_count) { + if (p >= p_end) + return false; + if (*p++ != sig_map[type->types[i] - VALUE_TYPE_F64]) + return false; + } + + if (*p != '\0') + return false; + return true; } +static void +sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols) +{ + uint32 i, j; + NativeSymbol temp; + + for (i = 0; i < n_native_symbols - 1; i++) { + for (j = i + 1; j < n_native_symbols; j++) { + if (strcmp(native_symbols[i].symbol, + native_symbols[j].symbol) > 0) { + temp = native_symbols[i]; + native_symbols[i] = native_symbols[j]; + native_symbols[j] = temp; + } + } + } +} + static void * -lookup_symbol(NativeSymbol *ptr, int len, const char *symbol) +lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols, + const char *symbol, const char **p_signature) { int low = 0, mid, ret; - int high = len - 1; + int high = n_native_symbols - 1; while (low <= high) { mid = (low + high) / 2; - ret = strcmp(symbol, ptr[mid].symbol); - - if (ret == 0) - return ptr[mid].func_ptr; + ret = strcmp(symbol, native_symbols[mid].symbol); + if (ret == 0) { + *p_signature = native_symbols[mid].signature; + return native_symbols[mid].func_ptr; + } else if (ret < 0) high = mid - 1; else @@ -51,75 +131,135 @@ lookup_symbol(NativeSymbol *ptr, int len, const char *symbol) return NULL; } +void* +wasm_native_resolve_symbol(const char *module_name, const char *field_name, + const WASMType *func_type, const char **p_signature) +{ + NativeSymbolsNode *node, *node_next; + const char *signature = NULL; + void *func_ptr = NULL; + + node = g_native_symbols_list; + while (node) { + node_next = node->next; + if (!strcmp(node->module_name, module_name)) { + if ((func_ptr = lookup_symbol(node->native_symbols, + node->n_native_symbols, + field_name, &signature)) + || (field_name[0] == '_' + && (func_ptr = lookup_symbol(node->native_symbols, + node->n_native_symbols, + field_name + 1, &signature)))) + break; + } + node = node_next; + } + + if (func_ptr) { + if (signature && signature[0] != '\0') { + /* signature is not empty, check its format */ + if (!check_symbol_signature(func_type, signature)) { + LOG_WARNING("failed to check signature '%s' and resolve " + "pointer params for import function (%s %s)\n", + signature, module_name, field_name); + return NULL; + } + else + /* Save signature for runtime to do pointer check and + address conversion */ + *p_signature = signature; + } + else + /* signature is empty */ + *p_signature = NULL; + } + + return func_ptr; +} + +bool +wasm_native_register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols) +{ + NativeSymbolsNode *node; + + if (!(node = bh_malloc(sizeof(NativeSymbolsNode)))) + return false; + + node->module_name = module_name; + node->native_symbols = native_symbols; + node->n_native_symbols = n_native_symbols; + node->next = NULL; + + if (g_native_symbols_list_end) { + g_native_symbols_list_end->next = node; + g_native_symbols_list_end = node; + } + else { + g_native_symbols_list = g_native_symbols_list_end = node; + } + + sort_symbol_ptr(native_symbols, n_native_symbols); + return true; +} + +bool +wasm_native_init() +{ + NativeSymbol *native_symbols; + uint32 n_native_symbols; + +#if WASM_ENABLE_LIBC_BUILTIN != 0 + n_native_symbols = get_libc_builtin_export_apis(&native_symbols); + if (!wasm_native_register_natives("env", + native_symbols, n_native_symbols)) + return false; + + n_native_symbols = get_spectest_export_apis(&native_symbols); + if (!wasm_native_register_natives("spectest", + native_symbols, n_native_symbols)) + return false; +#endif + +#if WASM_ENABLE_LIBC_WASI != 0 + n_native_symbols = get_libc_wasi_export_apis(&native_symbols); + if (!wasm_native_register_natives("wasi_unstable", + native_symbols, n_native_symbols)) + return false; +#endif + #if WASM_ENABLE_BASE_LIB != 0 -static bool is_base_lib_sorted = false; -static NativeSymbol *base_native_symbol_defs; -static int base_native_symbol_len; + n_native_symbols = get_base_lib_export_apis(&native_symbols); + if (n_native_symbols > 0 + && !wasm_native_register_natives("env", + native_symbols, n_native_symbols)) + return false; +#endif -int -get_base_lib_export_apis(NativeSymbol **p_base_lib_apis); +#if WASM_ENABLE_APP_FRAMEWORK != 0 + n_native_symbols = get_ext_lib_export_apis(&native_symbols); + if (n_native_symbols > 0 + && !wasm_native_register_natives("env", + native_symbols, n_native_symbols)) + return false; +#endif -void * -wasm_native_lookup_base_lib_func(const char *module_name, - const char *func_name) -{ - void *ret; - - if (strcmp(module_name, "env")) - return NULL; - - if (!is_base_lib_sorted) { - base_native_symbol_len = get_base_lib_export_apis(&base_native_symbol_defs); - - if (base_native_symbol_len > 0) - sort_symbol_ptr(base_native_symbol_defs, base_native_symbol_len); - - is_base_lib_sorted = true; - } - - if ((ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len, - func_name)) - || (func_name[0] == '_' - && (ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len, - func_name + 1)))) - return ret; - - return NULL; -} -#endif /* end of WASM_ENABLE_BASE_LIB */ - -static bool is_ext_lib_sorted = false; -static NativeSymbol *ext_native_symbol_defs; -static int ext_native_symbol_len; - -int -get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis); - -void * -wasm_native_lookup_extension_lib_func(const char *module_name, - const char *func_name) -{ - void *ret; - - if (strcmp(module_name, "env")) - return NULL; - - if (!is_ext_lib_sorted) { - ext_native_symbol_len = get_ext_lib_export_apis(&ext_native_symbol_defs); - - if (ext_native_symbol_len > 0) - sort_symbol_ptr(ext_native_symbol_defs, ext_native_symbol_len); - - is_ext_lib_sorted = true; - } - - if ((ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len, - func_name)) - || (func_name[0] == '_' - && (ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len, - func_name + 1)))) - return ret; - - return NULL; + return true; +} + +void +wasm_native_destroy() +{ + NativeSymbolsNode *node, *node_next; + + node = g_native_symbols_list; + while (node) { + node_next = node->next; + bh_free(node); + node = node_next; + } + + g_native_symbols_list = g_native_symbols_list_end = NULL; } diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index a8fdc3f7a..dcacd5826 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -7,82 +7,66 @@ #define _WASM_NATIVE_H #include "bh_common.h" -#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 #include "../interpreter/wasm.h" -#endif #ifdef __cplusplus extern "C" { #endif -/** - * Lookup native function implementation of a given import function - * in libc builtin API's - * - * @param module_name the module name of the import function - * @param func_name the function name of the import function - * - * @return return the native function pointer if success, NULL otherwise - */ -void * -wasm_native_lookup_libc_builtin_func(const char *module_name, - const char *func_name); +typedef struct NativeSymbol { + const char *symbol; + void *func_ptr; + const char *signature; +} NativeSymbol; + +typedef struct NativeSymbolsNode { + struct NativeSymbolsNode *next; + const char *module_name; + NativeSymbol *native_symbols; + uint32 n_native_symbols; +} NativeSymbolsNode, *NativeSymbolsList; -#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 /** * Lookup global variable of a given import global - * in libc builtin globals + * from libc builtin globals * * @param module_name the module name of the import global * @param global_name the global name of the import global * @param global return the global data * - * @param return true if success, false otherwise + * @param true if success, false otherwise */ bool wasm_native_lookup_libc_builtin_global(const char *module_name, const char *global_name, WASMGlobalImport *global); -#endif /** - * Lookup native function implementation of a given import function - * in libc wasi API's + * Resolve native symbol in all libraries, including libc-builtin, libc-wasi, + * base lib and extension lib, and user registered natives + * function, which can be auto checked by vm before calling native function * * @param module_name the module name of the import function * @param func_name the function name of the import function + * @param func_type the function prototype of the import function + * @param p_signature output the signature if resolve success * - * @return return the native function pointer if success, NULL otherwise + * @return the native function pointer if success, NULL otherwise */ -void * -wasm_native_lookup_libc_wasi_func(const char *module_name, - const char *func_name); +void* +wasm_native_resolve_symbol(const char *module_name, const char *field_name, + const WASMType *func_type, const char **p_signature); -/** - * Lookup native function implementation of a given import function - * in base lib API's - * - * @param module_name the module name of the import function - * @param func_name the function name of the import function - * - * @return return the native function pointer if success, NULL otherwise - */ -void * -wasm_native_lookup_base_lib_func(const char *module_name, - const char *func_name); +bool +wasm_native_register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols); -/** - * Lookup native function implementation of a given import function - * in extension lib API's - * - * @param module_name the module name of the import function - * @param func_name the function name of the import function - * - * @return return the native function pointer if success, NULL otherwise - */ -void * -wasm_native_lookup_extension_lib_func(const char *module_name, - const char *func_name); +bool +wasm_native_init(); + +void +wasm_native_destroy(); #ifdef __cplusplus } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 4727fd511..8aaa97674 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -35,12 +35,18 @@ wasm_runtime_init() if (vm_thread_sys_init() != 0) return false; + if (wasm_native_init() == false) { + wasm_runtime_destroy(); + return false; + } + return true; } void wasm_runtime_destroy() { + wasm_native_destroy(); vm_thread_sys_destroy(); } @@ -342,15 +348,18 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst) } int32 -wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size) +wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size, + void **p_native_addr) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_module_malloc((WASMModuleInstance*)module_inst, size); + return wasm_module_malloc((WASMModuleInstance*)module_inst, size, + p_native_addr); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_module_malloc((AOTModuleInstance*)module_inst, size); + return aot_module_malloc((AOTModuleInstance*)module_inst, size, + p_native_addr); #endif return 0; } @@ -691,20 +700,17 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, total_size = sizeof(size_t) * (uint64)argc; if (total_size >= UINT32_MAX || !(offset_argv_offsets = wasm_runtime_module_malloc - (module_inst, (uint32)total_size)) + (module_inst, (uint32)total_size, + (void**)&argv_offsets)) || argv_buf_len >= UINT32_MAX || !(offset_argv_buf = wasm_runtime_module_malloc - (module_inst, (uint32)argv_buf_len))) { + (module_inst, (uint32)argv_buf_len, + (void**)&argv_buf))) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: allocate memory failed."); goto fail; } - argv_offsets = (size_t*) - wasm_runtime_addr_app_to_native(module_inst, offset_argv_offsets); - argv_buf = (char*) - wasm_runtime_addr_app_to_native(module_inst, offset_argv_buf); - for (i = 0; i < argc; i++) { argv_offsets[i] = argv_buf_offset; bh_strcpy_s(argv_buf + argv_buf_offset, @@ -718,20 +724,17 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, total_size = sizeof(size_t) * (uint64)argc; if (total_size >= UINT32_MAX || !(offset_env_offsets = wasm_runtime_module_malloc - (module_inst, (uint32)total_size)) + (module_inst, (uint32)total_size, + (void**)&env_offsets)) || env_buf_len >= UINT32_MAX || !(offset_env_buf = wasm_runtime_module_malloc - (module_inst, (uint32)env_buf_len))) { + (module_inst, (uint32)env_buf_len, + (void**)&env_buf))) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: allocate memory failed."); goto fail; } - env_offsets = (size_t*) - wasm_runtime_addr_app_to_native(module_inst, offset_env_offsets); - env_buf = (char*) - wasm_runtime_addr_app_to_native(module_inst, offset_env_buf); - for (i = 0; i < env_count; i++) { env_offsets[i] = env_buf_offset; bh_strcpy_s(env_buf + env_buf_offset, @@ -740,23 +743,20 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, } if (!(offset_curfds = wasm_runtime_module_malloc - (module_inst, sizeof(struct fd_table))) + (module_inst, sizeof(struct fd_table), (void**)&curfds)) || !(offset_prestats = wasm_runtime_module_malloc - (module_inst, sizeof(struct fd_prestats))) + (module_inst, sizeof(struct fd_prestats), (void**)&prestats)) || !(offset_argv_environ = wasm_runtime_module_malloc - (module_inst, sizeof(struct argv_environ_values)))) { + (module_inst, sizeof(struct argv_environ_values), + (void**)&argv_environ))) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: allocate memory failed."); goto fail; } - curfds = wasi_ctx->curfds = (struct fd_table*) - wasm_runtime_addr_app_to_native(module_inst, offset_curfds); - prestats = wasi_ctx->prestats = (struct fd_prestats*) - wasm_runtime_addr_app_to_native(module_inst, offset_prestats); - argv_environ = wasi_ctx->argv_environ = - (struct argv_environ_values*)wasm_runtime_addr_app_to_native - (module_inst, offset_argv_environ); + wasi_ctx->curfds = curfds; + wasi_ctx->prestats = prestats; + wasi_ctx->argv_environ = argv_environ; fd_table_init(curfds); fd_prestats_init(prestats); @@ -1064,13 +1064,14 @@ wasm_application_execute_main(WASMModuleInstanceCommon *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, + (void**)&argv_buf))) { 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); + p = argv_buf; argv_offsets = (int32*)(p + total_argv_size); p_end = p + total_size; @@ -1379,6 +1380,15 @@ fail: return false; } +bool +wasm_runtime_register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols) +{ + return wasm_native_register_natives(module_name, + native_symbols, n_native_symbols); +} + /** * Implementation of wasm_runtime_invoke_native() */ @@ -1425,13 +1435,16 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; #define MAX_REG_FLOATS 16 bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMExecEnv *exec_env, - uint32 *argv, uint32 argc, uint32 *ret) +wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + uint32 *argv, uint32 argc, uint32 *argv_ret) { + WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); /* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args */ uint32 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size; uint32 *argv_src = argv, i, argc1, n_ints = 0, n_fps = 0, n_stacks = 0; + uint32 arg_i32, ptr_len; + bool ret = false; n_ints++; /* exec env */ @@ -1508,11 +1521,41 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, for (i = 0; i < func_type->param_count; i++) { switch (func_type->types[i]) { case VALUE_TYPE_I32: + { + arg_i32 = *argv_src++; + + if (signature) { + if (signature[i + 1] == '*') { + /* param is a pointer */ + if (signature[i + 2] == '~') + /* pointer with length followed */ + ptr_len = *argv_src; + else + /* pointer without length followed */ + ptr_len = 1; + + if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + goto fail; + + arg_i32 = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + else if (signature[i + 1] == '$') { + /* param is a string */ + if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + goto fail; + + arg_i32 = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + } + if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *argv_src++; + ints[n_ints++] = arg_i32; else - stacks[n_stacks++] = *argv_src++; + stacks[n_stacks++] = arg_i32; break; + } case VALUE_TYPE_I64: if (n_ints < MAX_REG_INTS - 1) { /* 64-bit data must be 8 bytes aligned in arm */ @@ -1565,26 +1608,29 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, else { switch (func_type->types[func_type->param_count]) { case VALUE_TYPE_I32: - ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); + argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); + PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); break; case VALUE_TYPE_F32: - *(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks); + *(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); + PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); break; default: bh_assert(0); break; } } + + ret = true; + +fail: if (argv1 != argv_buf) wasm_free(argv1); - - return true; + return ret; } #endif /* end of defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) */ @@ -1609,12 +1655,15 @@ static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMExecEnv *exec_env, - uint32 *argv, uint32 argc, uint32 *ret) +wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + uint32 *argv, uint32 argc, uint32 *argv_ret) { + WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0; + uint32 arg_i32, ptr_len; uint64 size; + bool ret = false; #if defined(BUILD_TARGET_X86_32) argc1 = argc + 2; @@ -1637,20 +1686,49 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, for (i = 0; i < sizeof(WASMExecEnv*) / sizeof(uint32); i++) argv1[j++] = ((uint32*)&exec_env)[i]; -#if defined(BUILD_TARGET_X86_32) - word_copy(argv1 + j, argv, argc); - j += argc; -#else for (i = 0; i < func_type->param_count; i++) { switch (func_type->types[i]) { case VALUE_TYPE_I32: - argv1[j++] = *argv++; + { + arg_i32 = *argv++; + + if (signature) { + if (signature[i + 1] == '*') { + /* param is a pointer */ + if (signature[i + 2] == '~') + /* pointer with length followed */ + ptr_len = *argv; + else + /* pointer without length followed */ + ptr_len = 1; + + if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + goto fail; + + arg_i32 = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + else if (signature[i + 1] == '$') { + /* param is a string */ + if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + goto fail; + + arg_i32 = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + } + + argv1[j++] = arg_i32; break; + } case VALUE_TYPE_I64: case VALUE_TYPE_F64: - /* 64-bit data must be 8 bytes aligned in arm and mips */ +#if !defined(BUILD_TARGET_X86_32) + /* 64-bit data must be 8 bytes aligned in arm, thumb, mips + and xtensa */ if (j & 1) j++; +#endif argv1[j++] = *argv++; argv1[j++] = *argv++; break; @@ -1662,7 +1740,6 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, break; } } -#endif /* end of defined(BUILD_TARGET_X86_32) */ argc1 = j; if (func_type->result_count == 0) { @@ -1671,16 +1748,16 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, else { switch (func_type->types[func_type->param_count]) { case VALUE_TYPE_I32: - ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1); + argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1); break; case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, argc1)); + PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, argc1)); break; case VALUE_TYPE_F32: - *(float32*)ret = invokeNative_Float32(func_ptr, argv1, argc1); + *(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, argc1); break; case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, argc1)); + PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, argc1)); break; default: bh_assert(0); @@ -1688,9 +1765,12 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, } } + ret = true; + +fail: if (argv1 != argv_buf) wasm_free(argv1); - return true; + return ret; } #endif /* end of defined(BUILD_TARGET_X86_32) \ @@ -1724,12 +1804,15 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; #endif bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMExecEnv *exec_env, - uint32 *argv, uint32 argc, uint32 *ret) +wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + uint32 *argv, uint32 argc, uint32 *argv_ret) { - uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size; + WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); + uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size, arg_i64; uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0; + uint32 arg_i32, ptr_len; + bool ret = false; #if defined(_WIN32) || defined(_WIN32_) /* important difference in calling conventions */ #define n_fps n_ints @@ -1757,11 +1840,40 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, for (i = 0; i < func_type->param_count; i++) { switch (func_type->types[i]) { case VALUE_TYPE_I32: + { + arg_i32 = *argv_src++; + arg_i64 = arg_i32; + if (signature) { + if (signature[i + 1] == '*') { + /* param is a pointer */ + if (signature[i + 2] == '~') + /* pointer with length followed */ + ptr_len = *argv_src; + else + /* pointer without length followed */ + ptr_len = 1; + + if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + goto fail; + + arg_i64 = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + else if (signature[i + 1] == '$') { + /* param is a string */ + if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + goto fail; + + arg_i64 = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + } if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *argv_src++; + ints[n_ints++] = arg_i64; else - stacks[n_stacks++] = *argv_src++; + stacks[n_stacks++] = arg_i64; break; + } case VALUE_TYPE_I64: if (n_ints < MAX_REG_INTS) ints[n_ints++] = *(uint64*)argv_src; @@ -1794,16 +1906,16 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, else { switch (func_type->types[func_type->param_count]) { case VALUE_TYPE_I32: - ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); + argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); + PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); break; case VALUE_TYPE_F32: - *(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks); + *(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); + PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); break; default: bh_assert(0); @@ -1811,10 +1923,12 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, } } + ret = true; +fail: if (argv1 != argv_buf) wasm_free(argv1); - return true; + return ret; } #endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */ diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 5e3fc2501..11fc5c797 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -10,6 +10,7 @@ #include "bh_common.h" #include "bh_thread.h" #include "wasm_exec_env.h" +#include "wasm_native.h" #include "../interpreter/wasm.h" #if WASM_ENABLE_LIBC_WASI != 0 #include "wasmtime_ssp.h" @@ -172,7 +173,8 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst); /* See wasm_export.h for description */ int32 -wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size); +wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size, + void **p_native_addr); /* See wasm_export.h for description */ void @@ -282,9 +284,15 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst); bool wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count); +/* See wasm_export.h for description */ bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMExecEnv *exec_env, +wasm_runtime_register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols); + +bool +wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, uint32 *argv, uint32 argc, uint32 *ret); diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 5c2f9eb97..83b6bb981 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -265,6 +265,7 @@ aot_create_import_funcs(const WASMModule *module) import_funcs[i].func_name = import_func->field_name; import_funcs[i].func_ptr_linked = import_func->func_ptr_linked; import_funcs[i].func_type = import_func->func_type; + import_funcs[i].signature = import_func->signature; /* Resolve function type index */ for (j = 0; j < module->type_count; j++) if (import_func->func_type == module->types[j]) { diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index be33867de..afc099eb7 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -83,6 +83,8 @@ typedef struct AOTImportFunc { uint32 func_type_index; /* function pointer after linked */ void *func_ptr_linked; + /* signature from registered native symbols */ + const char *signature; } AOTImportFunc; /** diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index fc447090c..c9959e0ad 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -208,6 +208,7 @@ typedef enum FloatArithmetic { #define F64_ZERO (comp_ctx->llvm_consts.f64_zero) #define I32_ONE (comp_ctx->llvm_consts.i32_one) #define I32_TWO (comp_ctx->llvm_consts.i32_two) +#define I32_THREE (comp_ctx->llvm_consts.i32_three) #define I32_FOUR (comp_ctx->llvm_consts.i32_four) #define I32_EIGHT (comp_ctx->llvm_consts.i32_eight) #define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one) diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index 3311806b7..21c7324e0 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -82,21 +82,149 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return true; } +static bool +call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef func_idx, AOTFuncType *aot_func_type, + LLVMTypeRef *param_types, LLVMValueRef *param_values, + uint32 param_count, uint32 param_cell_num, + LLVMTypeRef ret_type, uint8 wasm_ret_type, + LLVMValueRef *p_value_ret) +{ + LLVMTypeRef func_type, func_ptr_type, func_param_types[5]; + LLVMTypeRef ret_ptr_type, elem_ptr_type; + LLVMValueRef func, elem_idx, elem_ptr; + LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res; + char buf[32], *func_name = "aot_invoke_native"; + uint32 i, cell_num = 0; + + /* prepare function type of aot_invoke_native */ + func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ + func_param_types[1] = I32_TYPE; /* func_idx */ + func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */ + func_param_types[3] = I32_TYPE; /* argc */ + func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */ + if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) { + aot_set_last_error("llvm add function type failed."); + return false; + } + + /* prepare function pointer */ + if (comp_ctx->is_jit_mode) { + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + + /* JIT mode, call the function directly */ + if (!(func = I64_CONST((uint64)(uintptr_t)aot_invoke_native)) + || !(func = LLVMConstIntToPtr(func, func_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + return false; + } + } + else { + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) + && !(func = LLVMAddFunction(comp_ctx->module, + func_name, func_type))) { + aot_set_last_error("add LLVM function failed."); + return false; + } + } + + if (param_count > 64) { + aot_set_last_error("prepare native arguments failed: " + "maximum 64 parameter cell number supported."); + return false; + } + + /* prepare frame_lp */ + for (i = 0; i < param_count; i++) { + if (!(elem_idx = I32_CONST(cell_num)) + || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) { + aot_set_last_error("llvm add const or pointer type failed."); + return false; + } + + snprintf(buf, sizeof(buf), "%s%d", "elem", i); + if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->argv_buf, &elem_idx, 1, buf)) + || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr, + elem_ptr_type, buf))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) { + aot_set_last_error("llvm build store failed."); + return false; + } + LLVMSetAlignment(res, 1); + + cell_num += wasm_value_type_cell_num(aot_func_type->types[i]); + } + + if (wasm_ret_type != VALUE_TYPE_VOID) { + if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) { + aot_set_last_error("llvm add pointer type failed."); + return false; + } + + if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf, + ret_ptr_type, "argv_ret"))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + /* convert to int32 pointer */ + if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret, + INT32_PTR_TYPE, "argv_ret_ptr"))) { + aot_set_last_error("llvm build store failed."); + return false; + } + } + else { + value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE); + } + + func_param_values[0] = func_ctx->exec_env; + func_param_values[1] = func_idx; + func_param_values[2] = func_ctx->argv_buf; + func_param_values[3] = I32_CONST(param_cell_num); + func_param_values[4] = value_ret_ptr; + + if (!func_param_values[3]) { + aot_set_last_error("llvm create const failed."); + return false; + } + + /* call aot_invoke_native() function */ + if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) { + aot_set_last_error("llvm build call failed."); + return false; + } + + if (wasm_ret_type != VALUE_TYPE_VOID) + /* get function return value */ + *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret"); + + return true; +} + bool aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 func_idx, uint8 **p_frame_ip) { uint32 import_func_count = comp_ctx->comp_data->import_func_count; AOTImportFunc *import_funcs = comp_ctx->comp_data->import_funcs; - uint32 func_count = comp_ctx->func_ctx_count; + uint32 func_count = comp_ctx->func_ctx_count, param_cell_num = 0; AOTFuncContext **func_ctxes = comp_ctx->func_ctxes; AOTFuncType *func_type; - LLVMTypeRef *param_types = NULL, ret_type, f_type, f_ptr_type; - LLVMValueRef *param_values = NULL, value_ret, func, value, cmp; - LLVMBasicBlockRef check_func_ptr_succ; + LLVMTypeRef *param_types = NULL, ret_type; + LLVMValueRef *param_values = NULL, value_ret = NULL, func; + LLVMValueRef import_func_idx; int32 i, j = 0, param_count; - void *func_ptr; uint64 total_size; + uint8 wasm_ret_type; bool ret = false; /* Check function index */ @@ -112,6 +240,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, func_type = func_ctxes[func_idx - import_func_count]-> aot_func->func_type; + /* Get param cell number */ + param_cell_num = wasm_type_param_cell_num(func_type); + /* Allocate memory for parameters */ param_count = (int32)func_type->param_count; total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); @@ -129,8 +260,10 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP(param_values[i + j], func_type->types[i]); if (func_idx < import_func_count) { - /* Get function pointer linked */ - func_ptr = import_funcs[func_idx].func_ptr_linked; + if (!(import_func_idx = I32_CONST(func_idx))) { + aot_set_last_error("llvm build inbounds gep failed."); + goto fail; + } /* Initialize parameter types of the LLVM function */ total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); @@ -146,99 +279,37 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, for (i = 0; i < param_count; i++) param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); - /* Resolve return type of the LLVM function */ - if (func_type->result_count) - ret_type = TO_LLVM_TYPE(func_type->types[func_type->param_count]); - else - ret_type = VOID_TYPE; - - /* Resolve function prototype */ - if (!(f_type = LLVMFunctionType(ret_type, param_types, - (uint32)param_count + 1, false)) - || !(f_ptr_type = LLVMPointerType(f_type, 0))) { - aot_set_last_error("create LLVM function type failed."); - goto fail; - } - - if (comp_ctx->is_jit_mode) { - if (!func_ptr) { - /* The import function isn't linked, throw exception - when calling it. */ - if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_CALL_UNLINKED_IMPORT_FUNC, - false, NULL, NULL)) - goto fail; - ret = aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); - goto fail; - } - - /* JIT mode, call the linked function directly */ - if (!(value = I64_CONST((uint64)(uintptr_t)func_ptr)) - || !(func = LLVMConstIntToPtr(value, f_ptr_type))) { - aot_set_last_error("create LLVM value failed."); - goto fail; - } + if (func_type->result_count) { + wasm_ret_type = func_type->types[func_type->param_count]; + ret_type = TO_LLVM_TYPE(wasm_ret_type); } else { - /* Load function pointer */ - if (!(value = I32_CONST(func_idx)) - || !(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->func_ptrs, - &value, 1, "func_ptr"))) { - aot_set_last_error("llvm build inbounds gep failed."); - goto fail; - } - - if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Check whether import function is NULL */ - if (!(cmp = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - /* Throw exception if import function is NULL */ - if (!(check_func_ptr_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_func_ptr_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_func_ptr_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_CALL_UNLINKED_IMPORT_FUNC, - true, cmp, check_func_ptr_succ))) - goto fail; - - if (!(func = LLVMBuildBitCast(comp_ctx->builder, func, - f_ptr_type, "func"))) { - aot_set_last_error("create LLVM value failed."); - goto fail; - } + wasm_ret_type = VALUE_TYPE_VOID; + ret_type = VOID_TYPE; } + + /* call aot_invoke_native() */ + if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type, + param_types + 1, param_values + 1, + param_count, param_cell_num, + ret_type, wasm_ret_type, &value_ret)) + goto fail; } else { func = func_ctxes[func_idx - import_func_count]->func; - } - /* Call the function */ - if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, - param_values, (uint32)param_count + 1, - (func_type->result_count > 0 - ? "call" : "")))) { - aot_set_last_error("LLVM build call failed."); - goto fail; - } + /* Call the function */ + if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, + param_values, (uint32)param_count + 1, + (func_type->result_count > 0 + ? "call" : "")))) { + aot_set_last_error("LLVM build call failed."); + goto fail; + } - /* Set calling convention for the call with the func's calling convention */ - LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func)); + /* Set calling convention for the call with the func's calling convention */ + LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func)); + } if (func_type->result_count > 0) PUSH(value_ret, func_type->types[func_type->param_count]); @@ -269,10 +340,12 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, f_type, f_ptr_type; LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ; LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ; - int32 i, j = 0, param_count; - uint64 total_size; - bool ret; char *func_name = "aot_is_wasm_type_equal"; + int32 i, j = 0, param_count; + uint32 param_cell_num; + uint64 total_size; + uint8 wasm_ret_type; + bool ret; /* Check function type index */ if (type_idx >= comp_ctx->comp_data->func_type_count) { @@ -282,6 +355,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, func_type = comp_ctx->comp_data->func_types[type_idx]; + param_cell_num = wasm_type_param_cell_num(func_type); + POP_I32(elem_idx); table_size_const = I32_CONST(comp_ctx->comp_data->table_size); @@ -383,9 +458,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } /* Create LLVM function with const function pointer */ - if (!(func_const = - I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal)) - || !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) { + if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal)) + || !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) { aot_set_last_error("create LLVM value failed."); goto fail; } @@ -485,23 +559,13 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); /* Resolve return type of the LLVM function */ - if (func_type->result_count) - ret_type = TO_LLVM_TYPE(func_type->types[func_type->param_count]); - else - ret_type = VOID_TYPE; - - /* Resolve function prototype */ - if (!(f_type = LLVMFunctionType(ret_type, param_types, - (uint32)param_count + 1, false)) - || !(f_ptr_type = LLVMPointerType(f_type, 0))) { - aot_set_last_error("create LLVM function type failed."); - goto fail; + if (func_type->result_count) { + wasm_ret_type = func_type->types[func_type->param_count]; + ret_type = TO_LLVM_TYPE(wasm_ret_type); } - - if (!(func = LLVMBuildBitCast(comp_ctx->builder, func, - f_ptr_type, "func"))) { - aot_set_last_error("create LLVM value failed."); - goto fail; + else { + wasm_ret_type = VALUE_TYPE_VOID; + ret_type = VOID_TYPE; } /* Allocate memory for parameters */ @@ -520,14 +584,11 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, for (i = param_count - 1; i >= 0; i--) POP(param_values[i + j], func_type->types[i]); - /* Call the function */ - if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, - param_values, (uint32)param_count + 1, - (func_type->result_count > 0 - ? "call_indirect" : "")))) { - aot_set_last_error("LLVM build call failed."); + if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type, + param_types + 1, param_values + 1, + param_count, param_cell_num, + ret_type, wasm_ret_type, &value_ret)) goto fail; - } if (func_type->result_count > 0) PUSH(value_ret, func_type->types[func_type->param_count]); diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index e07aea1e6..f12ff7c28 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -440,8 +440,9 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, AOTFuncContext *func_ctx; AOTFuncType *aot_func_type = comp_data->func_types[func->func_type_index]; AOTBlock *aot_block; - LLVMTypeRef int8_ptr_type; + LLVMTypeRef int8_ptr_type, int32_ptr_type; LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr; + LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr; char local_name[32]; uint64 size; uint32 i, j = 0; @@ -476,7 +477,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, func_ctx->exec_env = LLVMGetParam(func_ctx->func, j++); /* Get aot inst address, the layout of exec_env is: - exec_env->next, exec_env->prev, and exec_env->module_inst */ + exec_env->next, exec_env->prev, exec_env->module_inst, and argv_buf */ if (!(aot_inst_addr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, &aot_inst_offset, 1, "aot_inst_addr"))) { @@ -491,6 +492,32 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, goto fail; } + /* Get argv buffer address */ + if (!(argv_buf_addr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, + &argv_buf_offset, 1, "argv_buf_addr"))) { + aot_set_last_error("llvm build in bounds gep failed"); + goto fail; + } + + if (!(int32_ptr_type = LLVMPointerType(INT32_PTR_TYPE, 0))) { + aot_set_last_error("llvm add pointer type failed"); + goto fail; + } + + /* Convert to int32 pointer type */ + if (!(argv_buf_addr = LLVMBuildBitCast(comp_ctx->builder, argv_buf_addr, + int32_ptr_type, "argv_buf_ptr"))) { + aot_set_last_error("llvm build load failed"); + goto fail; + } + + if (!(func_ctx->argv_buf = LLVMBuildLoad(comp_ctx->builder, + argv_buf_addr, "argv_buf"))) { + aot_set_last_error("llvm build load failed"); + goto fail; + } + for (i = 0; i < aot_func_type->param_count; i++, j++) { snprintf(local_name, sizeof(local_name), "l%d", i); func_ctx->locals[i] = @@ -674,6 +701,7 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx) consts->f64_zero = F64_CONST(0); consts->i32_one = I32_CONST(1); consts->i32_two = I32_CONST(2); + consts->i32_three = I32_CONST(3); consts->i32_four = I32_CONST(4); consts->i32_eight = I32_CONST(8); consts->i32_neg_one = I32_CONST((uint32)-1); @@ -692,6 +720,7 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx) && consts->f64_zero && consts->i32_one && consts->i32_two + && consts->i32_three && consts->i32_four && consts->i32_eight && consts->i32_neg_one diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index c654eae7a..80113b73e 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -92,6 +92,7 @@ typedef struct AOTFuncContext { LLVMValueRef exec_env; LLVMValueRef aot_inst; LLVMValueRef table_base; + LLVMValueRef argv_buf; LLVMValueRef mem_data_size; LLVMValueRef mem_base_addr; @@ -150,6 +151,7 @@ typedef struct AOTLLVMConsts { LLVMValueRef f64_zero; LLVMValueRef i32_one; LLVMValueRef i32_two; + LLVMValueRef i32_three; LLVMValueRef i32_four; LLVMValueRef i32_eight; LLVMValueRef i32_neg_one; diff --git a/core/iwasm/include/ext_lib_export.h b/core/iwasm/include/ext_lib_export.h deleted file mode 100644 index fbf8d17d4..000000000 --- a/core/iwasm/include/ext_lib_export.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _EXT_LIB_EXPORT_H_ -#define _EXT_LIB_EXPORT_H_ - -#include "lib_export.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int -get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis) -{ - *p_ext_lib_apis = extended_native_symbol_defs; - return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol); -} - -#ifdef __cplusplus -} -#endif - -#endif /* end of _EXT_LIB_EXPORT_H_ */ - diff --git a/core/iwasm/include/lib_export.h b/core/iwasm/include/lib_export.h index c7f0dbc63..97e043e11 100644 --- a/core/iwasm/include/lib_export.h +++ b/core/iwasm/include/lib_export.h @@ -13,10 +13,16 @@ extern "C" { typedef struct NativeSymbol { const char *symbol; void *func_ptr; + const char *signature; } NativeSymbol; -#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol} -#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper} +#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL} +#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL} + +#define EXPORT_WASM_API_WITH_SIG(symbol, signature) \ + {#symbol, (void*)symbol, signature} +#define EXPORT_WASM_API_WITH_SIG2(symbol, signature) \ + {#symbol, (void*)symbol##_wrapper, signature} /** * Get the exported APIs of base lib diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 92bdece48..a0654c496 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -8,6 +8,7 @@ #include #include +#include "lib_export.h" #ifdef __cplusplus @@ -161,8 +162,7 @@ wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst); * * @param module_inst the module instance * @param name the name of the function - * @param signature the signature of the function, use "i32"/"i64"/"f32"/"f64" - * to represent the type of i32/i64/f32/f64, e.g. "(i32i64)" "(i32)f32" + * @param signature the signature of the function, ignored currently * * @return the function instance found */ @@ -293,6 +293,8 @@ wasm_runtime_get_custom_data(wasm_module_inst_t module_inst); * * @param module_inst the WASM module instance which contains heap * @param size the size bytes to allocate + * @param p_native_addr return native address of the allocated memory + * if it is not NULL, and return NULL if memory malloc failed * * @return the allocated memory address, which is a relative offset to the * base address of the module instance's memory space, the value range @@ -300,7 +302,8 @@ wasm_runtime_get_custom_data(wasm_module_inst_t module_inst); * Return non-zero if success, zero if failed. */ int32_t -wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size); +wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size, + void **p_native_addr); /** * Free memory to the heap of WASM module instance @@ -432,6 +435,36 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst, uint8_t **p_native_start_addr, uint8_t **p_native_end_addr); +/** + * Register native functions with same module name + * + * @param module_name the module name of the native functions + * @param native_symbols specifies an array of NativeSymbol structures which + * contain the names, function pointers and signatures + * Note: WASM runtime will not allocate memory to clone the data, so + * user must ensure the array can be used forever + * Meanings of letters in function signature: + * 'i': the parameter is i32 type + * 'I': the parameter is i64 type + * 'f': the parameter is f32 type + * 'F': the parameter is f64 type + * '*': the parameter is a pointer (i32 in WASM), and runtime will + * auto check its boundary before calling the native function. + * If it is followed by '~', the checked length of the pointer + * is gotten from the following parameter, if not, the checked + * length of the pointer is 1. + * '~': the parameter is the pointer's length with i32 type, and must + * follow after '*' + * '$': the parameter is a string (i32 in WASM), and runtime will + * auto check its boundary before calling the native function + * @param n_native_symbols specifies the number of native symbols in the array + * + * @return true if success, false otherwise + */ +bool wasm_runtime_register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32_t n_native_symbols); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 2ecc973a1..f730d7a11 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -137,6 +137,8 @@ typedef struct WASMFunctionImport { WASMType *func_type; /* function pointer after linked */ void *func_ptr_linked; + /* signature from registered native symbols */ + const char *signature; } WASMFunctionImport; typedef struct WASMGlobalImport { @@ -288,8 +290,7 @@ typedef struct WASMModule { auxiliary stack top pointer */ uint32 llvm_aux_stack_global_index; - /* Whether there is possible memory grow, e.g. - memory.grow opcode or call enlargeMemory */ + /* Whether there is possible memory grow, e.g. memory.grow opcode */ bool possible_memory_grow; StringList const_str_list; diff --git a/core/iwasm/interpreter/wasm_interp.c b/core/iwasm/interpreter/wasm_interp.c index e46fd9b5e..bcba0d516 100644 --- a/core/iwasm/interpreter/wasm_interp.c +++ b/core/iwasm/interpreter/wasm_interp.c @@ -726,9 +726,11 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { + WASMFunctionImport *func_import = cur_func->u.func_import; unsigned local_cell_num = 2; WASMInterpFrame *frame; uint32 argv_ret[2]; + char buf[128]; bool ret; if (!(frame = ALLOC_FRAME(exec_env, @@ -742,19 +744,16 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, wasm_exec_env_set_cur_frame(exec_env, frame); - if (!cur_func->u.func_import->func_ptr_linked) { - char buf[128]; - snprintf(buf, - sizeof(buf), "fail to call unlinked import function (%s, %s)", - cur_func->u.func_import->module_name, - cur_func->u.func_import->field_name); - wasm_set_exception((WASMModuleInstance*)module_inst, buf); + if (!func_import->func_ptr_linked) { + snprintf(buf, sizeof(buf), + "fail to call unlinked import function (%s, %s)", + func_import->module_name, func_import->field_name); + wasm_set_exception(module_inst, buf); return; } - ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked, - cur_func->u.func_import->func_type, - exec_env, + ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked, + func_import->func_type, func_import->signature, frame->lp, cur_func->param_cell_num, argv_ret); if (!ret) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 26f5e0b18..f9968c92d 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -556,36 +556,6 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, return true; } -static void* -resolve_sym(const char *module_name, const char *field_name) -{ - void *sym; - -#if WASM_ENABLE_LIBC_BUILTIN != 0 - if ((sym = wasm_native_lookup_libc_builtin_func(module_name, - field_name))) - return sym; -#endif - -#if WASM_ENABLE_LIBC_WASI != 0 - if ((sym = wasm_native_lookup_libc_wasi_func(module_name, - field_name))) - return sym; -#endif - -#if WASM_ENABLE_BASE_LIB != 0 - if ((sym = wasm_native_lookup_base_lib_func(module_name, - field_name))) - return sym; -#endif - - if ((sym = wasm_native_lookup_extension_lib_func(module_name, - field_name))) - return sym; - - return NULL; -} - static bool load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, char *error_buf, uint32 error_buf_size) @@ -737,13 +707,10 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } import->u.function.func_type = module->types[type_index]; - if (!module->possible_memory_grow - && !strcmp(module_name, "env") - && !(strcmp(field_name, "enlargeMemory"))) - module->possible_memory_grow = true; - if (!(import->u.function.func_ptr_linked = - resolve_sym(module_name, field_name))) { + wasm_native_resolve_symbol(module_name, field_name, + import->u.function.func_type, + &import->u.function.signature))) { #if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */ LOG_WARNING("warning: fail to link import function (%s, %s)\n", module_name, field_name); @@ -3016,7 +2983,8 @@ handle_next_reachable_block: POP_TYPE(func_type->types[idx]); } - PUSH_TYPE(func_type->types[func_type->param_count]); + if (func_type->result_count > 0) + PUSH_TYPE(func_type->types[func_type->param_count]); func->has_op_func_call = true; break; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 5f78bfa62..6f56cce69 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -849,75 +849,15 @@ wasm_deinstantiate(WASMModuleInstance *module_inst) wasm_free(module_inst); } -static bool -check_type(uint8 type, const char *p) -{ - const char *str = "i32"; - - if (strlen(p) < 3) - return false; - - switch (type) { - case VALUE_TYPE_I32: - str = "i32"; - break; - case VALUE_TYPE_I64: - str = "i64"; - break; - case VALUE_TYPE_F32: - str = "f32"; - break; - case VALUE_TYPE_F64: - str = "f64"; - break; - } - if (strncmp(p, str, 3)) - return false; - - return true; -} - -static bool -check_function_type(const WASMType *type, const char *signature) -{ - uint32 i; - const char *p = signature; - - if (!p || *p++ != '(') - return false; - - for (i = 0; i < type->param_count; i++) { - if (!check_type(type->types[i], p)) - return false; - p += 3; - } - - if (*p++ != ')') - return false; - - if (type->result_count) { - if (!check_type(type->types[type->param_count], p)) - return false; - p += 3; - } - - if (*p != '\0') - return false; - - return true; -} - WASMFunctionInstance* wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, const char *signature) { uint32 i; for (i = 0; i < module_inst->export_func_count; i++) - if (!strcmp(module_inst->export_functions[i].name, name) - && check_function_type( - module_inst->export_functions[i].function->u.func->func_type, - signature)) + if (!strcmp(module_inst->export_functions[i].name, name)) return module_inst->export_functions[i].function; + (void)signature; return NULL; } @@ -972,10 +912,13 @@ wasm_get_exception(WASMModuleInstance *module_inst) } int32 -wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size) +wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, + void **p_native_addr) { WASMMemoryInstance *memory = module_inst->default_memory; uint8 *addr = mem_allocator_malloc(memory->heap_handle, size); + if (p_native_addr) + *p_native_addr = addr; if (!addr) { wasm_set_exception(module_inst, "out of memory"); return 0; @@ -998,9 +941,10 @@ int32 wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src, uint32 size) { - int32 buffer_offset = wasm_module_malloc(module_inst, size); + char *buffer; + int32 buffer_offset = wasm_module_malloc(module_inst, size, + (void**)&buffer); if (buffer_offset != 0) { - char *buffer; buffer = wasm_addr_app_to_native(module_inst, buffer_offset); bh_memcpy_s(buffer, size, src, size); } diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 85f5d7242..aa025fcc6 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -222,7 +222,8 @@ const char* wasm_get_exception(WASMModuleInstance *module); int32 -wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size); +wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, + void **p_native_addr); void wasm_module_free(WASMModuleInstance *module_inst, int32 ptr); diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index 28aba59db..66f1badf8 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -6,9 +6,7 @@ #include "bh_common.h" #include "bh_log.h" #include "wasm_export.h" -#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 #include "../interpreter/wasm.h" -#endif void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); @@ -34,14 +32,17 @@ wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack); #define validate_app_str_addr(offset) \ wasm_runtime_validate_app_str_addr(module_inst, offset) +#define validate_native_addr(addr, size) \ + wasm_runtime_validate_native_addr(module_inst, addr, size) + #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_malloc(size, p_native_addr) \ + wasm_runtime_module_malloc(module_inst, size, p_native_addr) #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) @@ -392,73 +393,46 @@ printf_out(int c, struct str_context *ctx) return c; } -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_exec_env_t exec_env, - int32 fmt_offset, int32 va_list_offset) +printf_wrapper(wasm_exec_env_t exec_env, + const char * format, _va_list va_args) { wasm_module_inst_t module_inst = get_module_inst(exec_env); 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)) + /* format has been checked by runtime */ + if (!validate_native_addr(va_args, sizeof(int32))) return 0; - if (!_vprintf_wa((out_func_t)printf_out, &ctx, fmt, va_args, module_inst)) + if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args, module_inst)) return 0; + return (int)ctx.count; } static int -_sprintf_wrapper(wasm_exec_env_t exec_env, - int32 str_offset, int32 fmt_offset, int32 va_list_offset) +sprintf_wrapper(wasm_exec_env_t exec_env, + char *str, const char *format, _va_list va_args) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - int32 app_end_offset; + uint8 *native_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)) { + /* str and format have been checked by runtime */ + if (!validate_native_addr(va_args, sizeof(uint32))) + return 0; + + if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)str, + NULL, &native_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.max = (uint32)(native_end_offset - (uint8*)str); ctx.count = 0; - if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst)) + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, module_inst)) return 0; if (ctx.count < ctx.max) { @@ -469,29 +443,21 @@ _sprintf_wrapper(wasm_exec_env_t exec_env, } static int -_snprintf_wrapper(wasm_exec_env_t exec_env, - int32 str_offset, uint32 size, int32 fmt_offset, - int32 va_list_offset) +snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size, + const char *format, _va_list va_args) { wasm_module_inst_t module_inst = get_module_inst(exec_env); 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)) + /* str and format have been checked by runtime */ + if (!validate_native_addr(va_args, sizeof(uint32))) 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)) + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, module_inst)) return 0; if (ctx.count < ctx.max) { @@ -502,46 +468,32 @@ _snprintf_wrapper(wasm_exec_env_t exec_env, } static int -_puts_wrapper(wasm_exec_env_t exec_env, - int32 str_offset) +puts_wrapper(wasm_exec_env_t exec_env, const char *str) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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_exec_env_t exec_env, int c) +putchar_wrapper(wasm_exec_env_t exec_env, int c) { bh_printf("%c", c); return 1; } static int32 -_strdup_wrapper(wasm_exec_env_t exec_env, - int32 str_offset) +strdup_wrapper(wasm_exec_env_t exec_env, const char *str) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *str, *str_ret; + char *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); - + /* str has been checked by runtime */ if (str) { len = (uint32)strlen(str) + 1; - str_ret_offset = module_malloc(len); + str_ret_offset = module_malloc(len, (void**)&str_ret); if (str_ret_offset) { - str_ret = addr_app_to_native(str_ret_offset); bh_memcpy_s(str_ret, len, str, len); } } @@ -550,192 +502,151 @@ _strdup_wrapper(wasm_exec_env_t exec_env, } static int32 -__strdup_wrapper(wasm_exec_env_t exec_env, - int32 str_offset) +_strdup_wrapper(wasm_exec_env_t exec_env, const char *str) { - return _strdup_wrapper(exec_env, str_offset); + return strdup_wrapper(exec_env, str); } static int32 -_memcmp_wrapper(wasm_exec_env_t exec_env, - int32 s1_offset, int32 s2_offset, uint32 size) +memcmp_wrapper(wasm_exec_env_t exec_env, + const void *s1, const void *s2, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *s1, *s2; - if (!validate_app_addr(s1_offset, size) - || !validate_app_addr(s2_offset, size)) + /* s2 has been checked by runtime */ + if (!validate_native_addr((void*)s1, 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_exec_env_t exec_env, - int32 dst_offset, int32 src_offset, uint32 size) +memcpy_wrapper(wasm_exec_env_t exec_env, + void *dst, const void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *dst, *src; + int32 dst_offset = addr_native_to_app(dst); if (size == 0) return dst_offset; - if (!validate_app_addr(dst_offset, size) - || !validate_app_addr(src_offset, size)) + /* src has been checked by runtime */ + if (!validate_native_addr(dst, 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_exec_env_t exec_env, - int32 dst_offset, int32 src_offset, uint32 size) +memmove_wrapper(wasm_exec_env_t exec_env, + void *dst, void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *dst, *src; + int32 dst_offset = addr_native_to_app(dst); - if (!validate_app_addr(dst_offset, size) - || !validate_app_addr(src_offset, size)) + if (size == 0) + return dst_offset; + + /* src has been checked by runtime */ + if (!validate_native_addr(dst, 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_exec_env_t exec_env, - int32 s_offset, int32 c, uint32 size) +memset_wrapper(wasm_exec_env_t exec_env, + void *s, int32 c, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *s; + int32 s_offset = addr_native_to_app(s); - if (!validate_app_addr(s_offset, size)) + if (!validate_native_addr(s, size)) return s_offset; - s = addr_app_to_native(s_offset); memset(s, c, size); return s_offset; } static int32 -_strchr_wrapper(wasm_exec_env_t exec_env, - int32 s_offset, int32 c) +strchr_wrapper(wasm_exec_env_t exec_env, + const char *s, int32 c) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - const char *s; char *ret; - if (!validate_app_str_addr(s_offset)) - return s_offset; - - s = addr_app_to_native(s_offset); + /* s has been checked by runtime */ ret = strchr(s, c); return ret ? addr_native_to_app(ret) : 0; } static int32 -_strcmp_wrapper(wasm_exec_env_t exec_env, - int32 s1_offset, int32 s2_offset) +strcmp_wrapper(wasm_exec_env_t exec_env, + const char *s1, const char *s2) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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); + /* s1 and s2 have been checked by runtime */ return strcmp(s1, s2); } static int32 -_strncmp_wrapper(wasm_exec_env_t exec_env, - int32 s1_offset, int32 s2_offset, uint32 size) +strncmp_wrapper(wasm_exec_env_t exec_env, + const char *s1, const char *s2, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *s1, *s2; - if (!validate_app_addr(s1_offset, size) - || !validate_app_addr(s2_offset, size)) + /* s2 has been checked by runtime */ + if (!validate_native_addr((void*)s1, 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_exec_env_t exec_env, - int32 dst_offset, int32 src_offset) +strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *dst, *src; - uint32 len; + uint32 len = strlen(src) + 1; - if (!validate_app_str_addr(src_offset)) + /* src has been checked by runtime */ + if (!validate_native_addr(dst, len)) 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; + strncpy(dst, src, len); + return addr_native_to_app(dst); } static int32 -_strncpy_wrapper(wasm_exec_env_t exec_env, - int32 dst_offset, int32 src_offset, uint32 size) +strncpy_wrapper(wasm_exec_env_t exec_env, + char *dst, const char *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *dst, *src; - if (!validate_app_addr(dst_offset, size) - || !validate_app_addr(src_offset, size)) + /* src has been checked by runtime */ + if (!validate_native_addr(dst, size)) return 0; - dst = addr_app_to_native(dst_offset); - src = addr_app_to_native(src_offset); strncpy(dst, src, size); - return dst_offset; + return addr_native_to_app(dst); } static uint32 -_strlen_wrapper(wasm_exec_env_t exec_env, - int32 s_offset) +strlen_wrapper(wasm_exec_env_t exec_env, const char *s) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *s; - - if (!validate_app_str_addr(s_offset)) - return 0; - - s = addr_app_to_native(s_offset); + /* s has been checked by runtime */ return (uint32)strlen(s); } static int32 -_malloc_wrapper(wasm_exec_env_t exec_env, - uint32 size) +malloc_wrapper(wasm_exec_env_t exec_env, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - return module_malloc(size); + return module_malloc(size, NULL); } static int32 -_calloc_wrapper(wasm_exec_env_t exec_env, - uint32 nmemb, uint32 size) +calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint64 total_size = (uint64) nmemb * (uint64) size; @@ -745,9 +656,8 @@ _calloc_wrapper(wasm_exec_env_t exec_env, if (total_size >= UINT32_MAX) return 0; - ret_offset = module_malloc((uint32)total_size); + ret_offset = module_malloc((uint32)total_size, (void**)&ret_ptr); if (ret_offset) { - ret_ptr = addr_app_to_native(ret_offset); memset(ret_ptr, 0, (uint32) total_size); } @@ -755,47 +665,25 @@ _calloc_wrapper(wasm_exec_env_t exec_env, } static void -_free_wrapper(wasm_exec_env_t exec_env, - int32 ptr_offset) +free_wrapper(wasm_exec_env_t exec_env, void *ptr) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!validate_app_addr(ptr_offset, 4)) + + if (!validate_native_addr(ptr, sizeof(uint32))) return; - return module_free(ptr_offset); + + return module_free(addr_native_to_app(ptr)); } static int32 -_atoi_wrapper(wasm_exec_env_t exec_env, - int32 s_offset) +atoi_wrapper(wasm_exec_env_t exec_env, const char *s) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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_exec_env_t exec_env, - int32 key_offset, /* const void * */ - int32 array_offset, /* const void * */ - uint32 count, - uint32 size, - int32 cmp_index) -{ - wasm_module_inst_t module_inst = get_module_inst(exec_env); - wasm_runtime_set_exception(module_inst, "bsearch not implemented."); - - return 0; + /* s has been checked by runtime */ + return atoi(s); } static void -_exit_wrapper(wasm_exec_env_t exec_env, - int32 status) +exit_wrapper(wasm_exec_env_t exec_env, int32 status) { wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; @@ -804,45 +692,33 @@ _exit_wrapper(wasm_exec_env_t exec_env, } static int32 -_strtol_wrapper(wasm_exec_env_t exec_env, - int32 nptr_offset, /* const char * */ - int32 endptr_offset, /* char ** */ - int32 base) +strtol_wrapper(wasm_exec_env_t exec_env, + const char *nptr, char **endptr, int32 base) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *nptr, **endptr; int32 num = 0; - if (!validate_app_str_addr(nptr_offset) - || !validate_app_addr(endptr_offset, sizeof(int32))) + /* nptr has been checked by runtime */ + if (!validate_native_addr(endptr, sizeof(uint32))) 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); + *(int32*)endptr = addr_native_to_app(*endptr); return num; } static uint32 -_strtoul_wrapper(wasm_exec_env_t exec_env, - int32 nptr_offset, /* const char * */ - int32 endptr_offset, /* char ** */ - int32 base) +strtoul_wrapper(wasm_exec_env_t exec_env, + const char *nptr, char **endptr, int32 base) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *nptr, **endptr; uint32 num = 0; - if (!validate_app_str_addr(nptr_offset) - || !validate_app_addr(endptr_offset, sizeof(int32))) + /* nptr has been checked by runtime */ + if (!validate_native_addr(endptr, sizeof(uint32))) 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); @@ -850,162 +726,115 @@ _strtoul_wrapper(wasm_exec_env_t exec_env, } static int32 -_memchr_wrapper(wasm_exec_env_t exec_env, - int32 s_offset, /* const void * */ - int32 c, - uint32 n) +memchr_wrapper(wasm_exec_env_t exec_env, + const void *s, int32 c, uint32 n) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *s, *res; + void *res; - if (!validate_app_addr(s_offset, n)) + if (!validate_native_addr((void*)s, 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_exec_env_t exec_env, - int32 s1_offset, /* const char * */ - int32 s2_offset, /* const char * */ - uint32 n) +strncasecmp_wrapper(wasm_exec_env_t exec_env, + const char *s1, const char *s2, int32 n) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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); - + /* s1 and s2 have been checked by runtime */ return strncasecmp(s1, s2, n); } static uint32 -_strspn_wrapper(wasm_exec_env_t exec_env, - int32 s_offset, /* const char * */ - int32 accept_offset) /* const char * */ +strspn_wrapper(wasm_exec_env_t exec_env, + const char *s, const char *accept) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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); - + /* s and accept have been checked by runtime */ return (uint32)strspn(s, accept); } static uint32 -_strcspn_wrapper(wasm_exec_env_t exec_env, - int32 s_offset, /* const char * */ - int32 reject_offset) /* const char * */ +strcspn_wrapper(wasm_exec_env_t exec_env, + const char *s, const char *reject) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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); - + /* s and reject have been checked by runtime */ return (uint32)strcspn(s, reject); } static int32 -_strstr_wrapper(wasm_exec_env_t exec_env, - int32 s_offset, /* const char * */ - int32 find_offset) /* const char * */ +strstr_wrapper(wasm_exec_env_t exec_env, + const char *s, const char *find) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - 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); - + /* s and find have been checked by runtime */ + char *res = strstr(s, find); return addr_native_to_app(res); } static int32 -_isupper_wrapper(wasm_exec_env_t exec_env, int32 c) +isupper_wrapper(wasm_exec_env_t exec_env, int32 c) { return isupper(c); } static int32 -_isalpha_wrapper(wasm_exec_env_t exec_env, int32 c) +isalpha_wrapper(wasm_exec_env_t exec_env, int32 c) { return isalpha(c); } static int32 -_isspace_wrapper(wasm_exec_env_t exec_env, int32 c) +isspace_wrapper(wasm_exec_env_t exec_env, int32 c) { return isspace(c); } static int32 -_isgraph_wrapper(wasm_exec_env_t exec_env, int32 c) +isgraph_wrapper(wasm_exec_env_t exec_env, int32 c) { return isgraph(c); } static int32 -_isprint_wrapper(wasm_exec_env_t exec_env, int32 c) +isprint_wrapper(wasm_exec_env_t exec_env, int32 c) { return isprint(c); } static int32 -_isdigit_wrapper(wasm_exec_env_t exec_env, int32 c) +isdigit_wrapper(wasm_exec_env_t exec_env, int32 c) { return isdigit(c); } static int32 -_isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c) +isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c) { return isxdigit(c); } static int32 -_tolower_wrapper(wasm_exec_env_t exec_env, int32 c) +tolower_wrapper(wasm_exec_env_t exec_env, int32 c) { return tolower(c); } static int32 -_toupper_wrapper(wasm_exec_env_t exec_env, int32 c) +toupper_wrapper(wasm_exec_env_t exec_env, int32 c) { return toupper(c); } static int32 -_isalnum_wrapper(wasm_exec_env_t exec_env, int32 c) +isalnum_wrapper(wasm_exec_env_t exec_env, int32 c) { return isalnum(c); } static void -setTempRet0_wrapper(wasm_exec_env_t exec_env, - uint32 temp_ret) +setTempRet0_wrapper(wasm_exec_env_t exec_env, uint32 temp_ret) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasm_runtime_set_temp_ret(module_inst, temp_ret); @@ -1019,8 +848,7 @@ getTempRet0_wrapper(wasm_exec_env_t exec_env) } static uint32 -_llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, - uint32 data) +llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, uint32 data) { return (data & 0xFFFF0000) | ((data & 0xFF) << 8) @@ -1028,8 +856,7 @@ _llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, } static uint32 -_llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, - uint32 data) +llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, uint32 data) { return ((data & 0xFF) << 24) | ((data & 0xFF00) << 8) @@ -1038,9 +865,9 @@ _llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, } static uint32 -_bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, - uint32 uint64_part0, uint32 uint64_part1, - uint32 bits) +bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, + uint32 uint64_part0, uint32 uint64_part1, + uint32 bits) { wasm_module_inst_t module_inst = get_module_inst(exec_env); union { @@ -1058,9 +885,9 @@ _bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, } static uint32 -_bitshift64Shl_wrapper(wasm_exec_env_t exec_env, - uint32 int64_part0, uint32 int64_part1, - uint32 bits) +bitshift64Shl_wrapper(wasm_exec_env_t exec_env, + uint32 int64_part0, uint32 int64_part1, + uint32 bits) { wasm_module_inst_t module_inst = get_module_inst(exec_env); union { @@ -1078,8 +905,7 @@ _bitshift64Shl_wrapper(wasm_exec_env_t exec_env, } static void -_llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, - uint32 llvm_stack) +llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack) { wasm_module_inst_t module_inst = get_module_inst(exec_env); bh_printf("_llvm_stackrestore called!\n"); @@ -1087,7 +913,7 @@ _llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, } static uint32 -_llvm_stacksave_wrapper(wasm_exec_env_t exec_env) +llvm_stacksave_wrapper(wasm_exec_env_t exec_env) { wasm_module_inst_t module_inst = get_module_inst(exec_env); bh_printf("_llvm_stacksave called!\n"); @@ -1095,27 +921,22 @@ _llvm_stacksave_wrapper(wasm_exec_env_t exec_env) } static int32 -_emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, - int32 dst_offset, int32 src_offset, - uint32 size) +emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, + void *dst, const void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *dst, *src; + int32 dst_offset = addr_native_to_app(dst); - if (!validate_app_addr(dst_offset, size) - || !validate_app_addr(src_offset, size)) + /* src has been checked by runtime */ + if (!validate_native_addr(dst, 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_exec_env_t exec_env, - int32 code) +abort_wrapper(wasm_exec_env_t exec_env, int32 code) { wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; @@ -1124,8 +945,7 @@ abort_wrapper(wasm_exec_env_t exec_env, } static void -abortStackOverflow_wrapper(wasm_exec_env_t exec_env, - int32 code) +abortStackOverflow_wrapper(wasm_exec_env_t exec_env, int32 code) { wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; @@ -1134,8 +954,7 @@ abortStackOverflow_wrapper(wasm_exec_env_t exec_env, } static void -nullFunc_X_wrapper(wasm_exec_env_t exec_env, - int32 code) +nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code) { wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; @@ -1148,7 +967,7 @@ __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - int32 exception = module_malloc(thrown_size); + int32 exception = module_malloc(thrown_size, NULL); if (!exception) return 0; @@ -1157,15 +976,14 @@ __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, static void __cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, - int32 exception_object_offset) + void *exception_object) { - } static void __cxa_throw_wrapper(wasm_exec_env_t exec_env, - int32 thrown_exception_offset, - int32 tinfo_offset, + void *thrown_exception, + void *tinfo, uint32 table_elem_idx) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -1175,114 +993,90 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env, wasm_runtime_set_exception(module_inst, buf); } -#ifndef ENABLE_SPEC_TEST -#define ENABLE_SPEC_TEST 0 -#endif - -#if ENABLE_SPEC_TEST != 0 static void print_i32_wrapper(wasm_exec_env_t exec_env, int32 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 } +#define REG_NATIVE_FUNC(func_name, signature) \ + { #func_name, func_name##_wrapper, signature } -typedef struct WASMNativeFuncDef { - const char *module_name; - const char *func_name; - void *func_ptr; -} WASMNativeFuncDef; - -static WASMNativeFuncDef native_func_defs[] = { -#if ENABLE_SPEC_TEST != 0 - REG_NATIVE_FUNC(spectest, print_i32), -#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), +static NativeSymbol native_symbols_libc_builtin[] = { + REG_NATIVE_FUNC(printf, "($*)i"), + REG_NATIVE_FUNC(sprintf, "($$*)i"), + REG_NATIVE_FUNC(snprintf, "(*~$*)i"), + REG_NATIVE_FUNC(puts, "($)i"), + REG_NATIVE_FUNC(putchar, "(i)i"), + REG_NATIVE_FUNC(memcmp, "(**~)i"), + REG_NATIVE_FUNC(memcpy, "(**~)i"), + REG_NATIVE_FUNC(memmove, "(**~)i"), + REG_NATIVE_FUNC(memset, "(*ii)i"), + REG_NATIVE_FUNC(strchr, "($i)i"), + REG_NATIVE_FUNC(strcmp, "($$)i"), + REG_NATIVE_FUNC(strcpy, "(*$)i"), + REG_NATIVE_FUNC(strlen, "($)i"), + REG_NATIVE_FUNC(strncmp, "(**~)i"), + REG_NATIVE_FUNC(strncpy, "(**~)i"), + REG_NATIVE_FUNC(malloc, "(i)i"), + REG_NATIVE_FUNC(calloc, "(ii)i"), + REG_NATIVE_FUNC(strdup, "($)i"), /* 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) + REG_NATIVE_FUNC(_strdup, "($)i"), + REG_NATIVE_FUNC(free, "(*)"), + REG_NATIVE_FUNC(atoi, "($)i"), + REG_NATIVE_FUNC(exit, "(i)"), + REG_NATIVE_FUNC(strtol, "($*i)i"), + REG_NATIVE_FUNC(strtoul, "($*i)i"), + REG_NATIVE_FUNC(memchr, "(*ii)"), + REG_NATIVE_FUNC(strncasecmp, "($$i)"), + REG_NATIVE_FUNC(strspn, "($$)i"), + REG_NATIVE_FUNC(strcspn, "($$)i"), + REG_NATIVE_FUNC(strstr, "($$)i"), + REG_NATIVE_FUNC(isupper, "(i)i"), + REG_NATIVE_FUNC(isalpha, "(i)i"), + REG_NATIVE_FUNC(isspace, "(i)i"), + REG_NATIVE_FUNC(isgraph, "(i)i"), + REG_NATIVE_FUNC(isprint, "(i)i"), + REG_NATIVE_FUNC(isdigit, "(i)i"), + REG_NATIVE_FUNC(isxdigit, "(i)i"), + REG_NATIVE_FUNC(tolower, "(i)i"), + REG_NATIVE_FUNC(toupper, "(i)i"), + REG_NATIVE_FUNC(isalnum, "(i)i"), + REG_NATIVE_FUNC(setTempRet0, "(i)"), + REG_NATIVE_FUNC(getTempRet0, "()i"), + REG_NATIVE_FUNC(llvm_bswap_i16, "(i)i"), + REG_NATIVE_FUNC(llvm_bswap_i32, "(i)i"), + REG_NATIVE_FUNC(bitshift64Lshr, "(iii)i"), + REG_NATIVE_FUNC(bitshift64Shl, "(iii)i"), + REG_NATIVE_FUNC(llvm_stackrestore, "(i)"), + REG_NATIVE_FUNC(llvm_stacksave, "()i"), + REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"), + REG_NATIVE_FUNC(abort, "(i)"), + REG_NATIVE_FUNC(abortStackOverflow, "(i)"), + REG_NATIVE_FUNC(nullFunc_X, "(i)"), + REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"), + REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"), + REG_NATIVE_FUNC(__cxa_throw, "(**i)") }; -void * -wasm_native_lookup_libc_builtin_func(const char *module_name, - const char *func_name) +static NativeSymbol native_symbols_spectest[] = { + REG_NATIVE_FUNC(print_i32, "(i)") +}; + +uint32 +get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis) { - uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef); - WASMNativeFuncDef *func_def = native_func_defs; - WASMNativeFuncDef *func_def_end = func_def + size; - - 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++; - } - - return NULL; + *p_libc_builtin_apis = native_symbols_libc_builtin; + return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol); } -#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +uint32 +get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis) +{ + *p_libc_builtin_apis = native_symbols_spectest; + return sizeof(native_symbols_spectest) / sizeof(NativeSymbol); +} /************************************* * Global Variables * @@ -1295,13 +1089,11 @@ typedef struct WASMNativeGlobalDef { } WASMNativeGlobalDef; static WASMNativeGlobalDef native_global_defs[] = { -#if ENABLE_SPEC_TEST != 0 { "spectest", "global_i32", .global_data.i32 = 666 }, { "spectest", "global_f32", .global_data.f32 = 0 }, { "spectest", "global_f64", .global_data.f64 = 0 }, { "test", "global-i32", .global_data.i32 = 0 }, { "test", "global-f32", .global_data.f32 = 0 }, -#endif { "env", "STACKTOP", .global_data.u32 = 0 }, { "env", "STACK_MAX", .global_data.u32 = 0 }, { "env", "ABORT", .global_data.u32 = 0 }, @@ -1340,5 +1132,3 @@ wasm_native_lookup_libc_builtin_global(const char *module_name, return false; } -#endif /* end of WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 */ - diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 59ee56baf..724fe61c9 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -20,24 +20,21 @@ wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); #define validate_app_addr(offset, size) \ wasm_runtime_validate_app_addr(module_inst, offset, size) +#define validate_native_addr(addr, size) \ + wasm_runtime_validate_native_addr(module_inst, addr, size) + #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_malloc(size, p_native_addr) \ + wasm_runtime_module_malloc(module_inst, size, p_native_addr) #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) -#define WASI_CHECK_ERR() do { \ - if (err) { \ - return err; \ - } \ - } while (0) - typedef struct wasi_prestat_app { wasi_preopentype_t pr_type; uint32 pr_name_len; @@ -58,247 +55,193 @@ wasi_ctx_t wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); static wasi_errno_t -wasi_args_get(wasm_exec_env_t exec_env, - int32 argv_offset /* char ** */, - int32 argv_buf_offset /* char * */) +wasi_args_get(wasm_exec_env_t exec_env, int32 *argv_offsets, char *argv_buf) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t argc, argv_buf_size, i; - uint64 total_size1, total_size2; - int32 *argv_app; - char *argv_buf_app; - wasi_errno_t err; char **argv; + uint64 total_size; + wasi_errno_t err; err = wasmtime_ssp_args_sizes_get(wasi_ctx->argv_environ, &argc, &argv_buf_size); - WASI_CHECK_ERR(); - - total_size1 = sizeof(char *) * ((uint64)argc + 1); - total_size2 = sizeof(char) * (uint64)argv_buf_size; - if (total_size1 >= UINT32_MAX - || !validate_app_addr(argv_offset, (uint32)total_size1) - || total_size2 >= UINT32_MAX - || !validate_app_addr(argv_buf_offset, (uint32)total_size2)) - return (wasi_errno_t)-1; - - argv = bh_malloc((uint32)total_size1); - if (!argv) - return (wasi_errno_t)-1; - - argv_app = (int32*)addr_app_to_native(argv_offset); - argv_buf_app= (char*)addr_app_to_native(argv_buf_offset); - - err = wasmtime_ssp_args_get(wasi_ctx->argv_environ, - argv, argv_buf_app); if (err) - goto fail; + return err; + + total_size = sizeof(int32) * ((uint64)argc + 1); + if (total_size >= UINT32_MAX + || !validate_native_addr(argv_offsets, (uint32)total_size) + || argv_buf_size >= UINT32_MAX + || !validate_native_addr(argv_buf, (uint32)argv_buf_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(char*) * ((uint64)argc + 1); + if (total_size >= UINT32_MAX + || !(argv = bh_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_args_get(wasi_ctx->argv_environ, argv, argv_buf); + if (err) { + bh_free(argv); + return err; + } for (i = 0; i < argc; i++) - argv_app[i] = addr_native_to_app(argv[i]); - argv_app[argc] = 0; + argv_offsets[i] = addr_native_to_app(argv[i]); + argv_offsets[argc] = 0; - /* success */ - err = 0; - -fail: bh_free(argv); - return err; + return 0; } static wasi_errno_t wasi_args_sizes_get(wasm_exec_env_t exec_env, - int32 argc_offset /* size_t * */, - int32 argv_buf_size_offset /* size_t * */) + uint32 *argc_app, uint32 *argv_buf_size_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t argc, argv_buf_size; - uint32 *argc_app, *argv_buf_size_app; wasi_errno_t err; - if (!validate_app_addr(argc_offset, sizeof(uint32)) - || !validate_app_addr(argv_buf_size_offset, sizeof(uint32))) + if (!validate_native_addr(argc_app, sizeof(uint32)) + || !validate_native_addr(argv_buf_size_app, sizeof(uint32))) return (wasi_errno_t)-1; - argc_app = (uint32*)addr_app_to_native(argc_offset); - argv_buf_size_app = (uint32*)addr_app_to_native(argv_buf_size_offset); - err = wasmtime_ssp_args_sizes_get(wasi_ctx->argv_environ, &argc, &argv_buf_size); - WASI_CHECK_ERR(); - - *(uint32*)argc_app = (uint32)argc; - *(uint32*)argv_buf_size_app = (uint32)argv_buf_size; + if (err) + return err; + *argc_app = (uint32)argc; + *argv_buf_size_app = (uint32)argv_buf_size; return 0; } static wasi_errno_t wasi_clock_res_get(wasm_exec_env_t exec_env, - wasi_clockid_t clock_id, - int32 resolution_offset /* wasi_timestamp_t * */) + wasi_clockid_t clock_id, /* uint32 clock_id */ + wasi_timestamp_t *resolution /* uint64 *resolution */) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - wasi_timestamp_t resolution; - uint32 *resolution_app; - wasi_errno_t err; - if (!validate_app_addr(resolution_offset, sizeof(wasi_timestamp_t))) + if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_clock_res_get(clock_id, &resolution); - WASI_CHECK_ERR(); - - resolution_app = addr_app_to_native(resolution_offset); - - memcpy(resolution_app, &resolution, sizeof(wasi_timestamp_t)); - - return 0; + return wasmtime_ssp_clock_res_get(clock_id, resolution); } static wasi_errno_t wasi_clock_time_get(wasm_exec_env_t exec_env, - wasi_clockid_t clock_id, - wasi_timestamp_t precision, - int32 time_offset /*wasi_timestamp_t * */) + wasi_clockid_t clock_id, /* uint32 clock_id */ + wasi_timestamp_t precision, /* uint64 precision */ + wasi_timestamp_t *time /* uint64 *time */) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - wasi_timestamp_t time; - uint32 *time_app; - wasi_errno_t err; - if (!validate_app_addr(time_offset, sizeof(wasi_timestamp_t))) + if (!validate_native_addr(time, sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_clock_time_get(clock_id, precision, &time); - WASI_CHECK_ERR(); - - time_app = addr_app_to_native(time_offset); - - memcpy(time_app, &time, sizeof(wasi_timestamp_t)); - - return 0; + return wasmtime_ssp_clock_time_get(clock_id, precision, time); } static wasi_errno_t wasi_environ_get(wasm_exec_env_t exec_env, - int32 environ_offset /* char ** */, - int32 environ_buf_offset /* char */) + int32 *environ_offsets, char *environ_buf) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t environ_count, environ_buf_size, i; uint64 total_size; - int32 *environ_app; - char *environ_buff_app; - char **environ; + char **environs; wasi_errno_t err; err = wasmtime_ssp_environ_sizes_get(wasi_ctx->argv_environ, &environ_count, &environ_buf_size); - WASI_CHECK_ERR(); - - total_size = sizeof(char*) * ((uint64)environ_count + 1); - if (total_size >= UINT32_MAX - || !validate_app_addr(environ_offset, (uint32)total_size) - || environ_buf_size >= UINT32_MAX - || !validate_app_addr(environ_buf_offset, (uint32)environ_buf_size)) - return (wasi_errno_t)-1; - - environ_app = (int32*)addr_app_to_native(environ_offset); - environ_buff_app = (char*)addr_app_to_native(environ_buf_offset); - - environ = bh_malloc((uint32)total_size); - if (!environ) - return (wasi_errno_t)-1; - - err = wasmtime_ssp_environ_get(wasi_ctx->argv_environ, - environ, environ_buff_app); if (err) - goto fail; + return err; + + total_size = sizeof(int32) * ((uint64)environ_count + 1); + if (total_size >= UINT32_MAX + || !validate_native_addr(environ_offsets, (uint32)total_size) + || environ_buf_size >= UINT32_MAX + || !validate_native_addr(environ_buf, (uint32)environ_buf_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(char*) * (((uint64)environ_count + 1)); + + if (total_size >= UINT32_MAX + || !(environs = bh_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_environ_get(wasi_ctx->argv_environ, environs, environ_buf); + if (err) { + bh_free(environs); + return err; + } for (i = 0; i < environ_count; i++) - environ_app[i] = addr_native_to_app(environ[i]); - environ_app[environ_count] = 0; + environ_offsets[i] = addr_native_to_app(environs[i]); + environ_offsets[environ_count] = 0; - /* success */ - err = 0; - -fail: - bh_free(environ); - return err; + bh_free(environs); + return 0; } static wasi_errno_t wasi_environ_sizes_get(wasm_exec_env_t exec_env, - int32 environ_count_offset /* size_t * */, - int32 environ_buf_size_offset /* size_t * */) + uint32 *environ_count_app, uint32 *environ_buf_size_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t environ_count, environ_buf_size; - uint32 *environ_count_app, *environ_buf_size_app; wasi_errno_t err; - if (!validate_app_addr(environ_count_offset, sizeof(uint32)) - || !validate_app_addr(environ_buf_size_offset, sizeof(uint32))) + if (!validate_native_addr(environ_count_app, sizeof(uint32)) + || !validate_native_addr(environ_buf_size_app, sizeof(uint32))) return (wasi_errno_t)-1; err = wasmtime_ssp_environ_sizes_get(wasi_ctx->argv_environ, &environ_count, &environ_buf_size); - WASI_CHECK_ERR(); + if (err) + return err; - environ_count_app = (uint32*)addr_app_to_native(environ_count_offset); - environ_buf_size_app = (uint32*)addr_app_to_native(environ_buf_size_offset); - - *(uint32*)environ_count_app = (uint32)environ_count; - *(uint32*)environ_buf_size_app = (uint32)environ_buf_size; + *environ_count_app = (uint32)environ_count; + *environ_buf_size_app = (uint32)environ_buf_size; return 0; } static wasi_errno_t wasi_fd_prestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 buf_offset /* wasi_prestat_t * */) + wasi_fd_t fd, wasi_prestat_app_t *prestat_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - wasi_prestat_app_t *prestat_app; wasi_prestat_t prestat; wasi_errno_t err; - if (!validate_app_addr(buf_offset, sizeof(wasi_prestat_app_t))) + if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_prestat_get(wasi_ctx->prestats, fd, &prestat); - WASI_CHECK_ERR(); + if (err) + return err; - prestat_app = (wasi_prestat_app_t*)addr_app_to_native(buf_offset); prestat_app->pr_type = prestat.pr_type; prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len; - return 0; } static wasi_errno_t wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 path_offset /* char * */, - uint32 path_len) + wasi_fd_t fd, char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path_app; - if (!validate_app_addr(path_offset, path_len)) - return (wasi_errno_t)-1; - - path_app = (char*)addr_app_to_native(path_offset); - return wasmtime_ssp_fd_prestat_dir_name(wasi_ctx->prestats, fd, - path_app, path_len); + return wasmtime_ssp_fd_prestat_dir_name(wasi_ctx->prestats, + fd, path, path_len); } static wasi_errno_t @@ -321,39 +264,30 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) static wasi_errno_t wasi_fd_pread(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 iovs_offset /* const wasi_iovec_t * */, - uint32 iovs_len, - wasi_filesize_t offset, - int32 nread_offset /* size_t * */) + wasi_fd_t fd, iovec_app_t *iovec_app, uint32 iovs_len, + wasi_filesize_t offset, uint32 *nread_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - int32 mem; wasi_iovec_t *iovec, *iovec_begin; - iovec_app_t *iovec_app; - uint32 i; - size_t nread; - uint32 *nread_app; uint64 total_size; + size_t nread; + int32 mem; + uint32 i; wasi_errno_t err; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_app_addr(nread_offset, (uint32)sizeof(uint32)) + if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_app_addr(iovs_offset, (uint32)total_size)) - return (wasi_errno_t)-1; - - iovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); - if (!iovec_app) + || !validate_native_addr(iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; if (total_size >= UINT32_MAX - || !(mem = module_malloc((uint32)total_size))) + || !(mem = module_malloc((uint32)total_size, (void**)&iovec_begin))) return (wasi_errno_t)-1; - iovec = iovec_begin = (wasi_iovec_t*)addr_app_to_native(mem); + iovec = iovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { @@ -369,8 +303,7 @@ wasi_fd_pread(wasm_exec_env_t exec_env, if (err) goto fail; - nread_app = (uint32*)addr_app_to_native(nread_offset); - *(uint32*)nread_app = (uint32)nread; + *nread_app = (uint32)nread; /* success */ err = 0; @@ -382,44 +315,38 @@ fail: static wasi_errno_t wasi_fd_pwrite(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 iovs_offset /* const wasi_ciovec_t * */, - uint32 iovs_len, - wasi_filesize_t offset, - int32 nwritten_offset /* size_t * */) + wasi_fd_t fd, const iovec_app_t *iovec_app, uint32 iovs_len, + wasi_filesize_t offset, uint32 *nwritten_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - int32 mem; wasi_ciovec_t *ciovec, *ciovec_begin; - iovec_app_t *ciovec_app; - uint32 i; - size_t nwritten; - uint32 *nwritten_app; uint64 total_size; + size_t nwritten; + int32 mem; + uint32 i; wasi_errno_t err; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_app_addr(nwritten_offset, (uint32)sizeof(uint32)) + if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_app_addr(iovs_offset, (uint32)total_size)) + || !validate_native_addr((void*)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; - ciovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); - total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; if (total_size >= UINT32_MAX - || !(mem = module_malloc((uint32)total_size))) + || !(mem = module_malloc((uint32)total_size, (void**)&ciovec_begin))) return (wasi_errno_t)-1; - ciovec_begin = ciovec = (wasi_ciovec_t*)addr_app_to_native(mem); - for (i = 0; i < iovs_len; i++, ciovec_app++, ciovec++) { - if (!validate_app_addr(ciovec_app->buf_offset, ciovec_app->buf_len)) { + ciovec = ciovec_begin; + + for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(ciovec_app->buf_offset); - ciovec->buf_len = ciovec_app->buf_len; + ciovec->buf = (char*)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf_len = iovec_app->buf_len; } err = wasmtime_ssp_fd_pwrite(wasi_ctx->curfds, fd, ciovec_begin, @@ -427,8 +354,7 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, if (err) goto fail; - nwritten_app = (uint32*)addr_app_to_native(nwritten_offset); - *(uint32*)nwritten_app = (uint32)nwritten; + *nwritten_app = (uint32)nwritten; /* success */ err = 0; @@ -440,36 +366,30 @@ fail: static wasi_errno_t wasi_fd_read(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 iovs_offset /* const wasi_iovec_t * */, - uint32 iovs_len, - int32 nread_offset /* size_t * */) + wasi_fd_t fd, const iovec_app_t *iovec_app, uint32 iovs_len, + uint32 *nread_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - int32 mem; wasi_iovec_t *iovec, *iovec_begin; - iovec_app_t *iovec_app; - uint32 i; - size_t nread; - uint32 *nread_app; uint64 total_size; + size_t nread; + uint32 i; + int32 mem; wasi_errno_t err; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_app_addr(nread_offset, (uint32)sizeof(uint32)) + if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_app_addr(iovs_offset, (uint32)total_size)) + || !validate_native_addr((void*)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; - iovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); - total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; if (total_size >= UINT32_MAX - || !(mem = module_malloc((uint32)total_size))) + || !(mem = module_malloc((uint32)total_size, (void**)&iovec_begin))) return (wasi_errno_t)-1; - iovec = iovec_begin = (wasi_iovec_t*)addr_app_to_native(mem); + iovec = iovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { @@ -485,8 +405,7 @@ wasi_fd_read(wasm_exec_env_t exec_env, if (err) goto fail; - nread_app = (uint32*)addr_app_to_native(nread_offset); - *(uint32*)nread_app = (uint32)nread; + *nread_app = (uint32)nread; /* success */ err = 0; @@ -497,8 +416,7 @@ fail: } static wasi_errno_t -wasi_fd_renumber(wasm_exec_env_t exec_env, - wasi_fd_t from, wasi_fd_t to) +wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -509,83 +427,60 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, static wasi_errno_t wasi_fd_seek(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_filedelta_t offset, - wasi_whence_t whence, - int32 newoffset_offset /* wasi_filesize_t * */) + wasi_fd_t fd, wasi_filedelta_t offset, wasi_whence_t whence, + wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - wasi_filesize_t newoffset, *newoffset_app; - wasi_errno_t err; - if (!validate_app_addr(newoffset_offset, sizeof(wasi_filesize_t))) + if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_seek(wasi_ctx->curfds, fd, - offset, whence, &newoffset); - WASI_CHECK_ERR(); - - newoffset_app = (wasi_filesize_t*)addr_app_to_native(newoffset_offset); - *newoffset_app = newoffset; - - return 0; + return wasmtime_ssp_fd_seek(wasi_ctx->curfds, fd, + offset, whence, newoffset); } static wasi_errno_t wasi_fd_tell(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 newoffset_offset /* wasi_filesize_t * */) + wasi_fd_t fd, wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - wasi_filesize_t newoffset, *newoffset_app; - wasi_errno_t err; - if (!validate_app_addr(newoffset_offset, sizeof(wasi_filesize_t))) + if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_tell(wasi_ctx->curfds, fd, &newoffset); - WASI_CHECK_ERR(); - - newoffset_app = (wasi_filesize_t*)addr_app_to_native(newoffset_offset); - *newoffset_app = newoffset; - - return 0; + return wasmtime_ssp_fd_tell(wasi_ctx->curfds, fd, newoffset); } static wasi_errno_t wasi_fd_fdstat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 buf_offset /* wasi_fdstat_t * */) + wasi_fd_t fd, wasi_fdstat_t *fdstat_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - wasi_fdstat_t fdstat, *fdstat_app; + wasi_fdstat_t fdstat; wasi_errno_t err; - if (!validate_app_addr(buf_offset, sizeof(wasi_fdstat_t))) + if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_fdstat_get(wasi_ctx->curfds, fd, &fdstat); - WASI_CHECK_ERR(); + if (err) + return err; - fdstat_app = (wasi_fdstat_t*)addr_app_to_native(buf_offset); memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t)); - return 0; } static wasi_errno_t wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_fdflags_t flags) + wasi_fd_t fd, wasi_fdflags_t flags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_fdstat_set_flags(wasi_ctx->curfds, fd, flags); - } static wasi_errno_t @@ -611,44 +506,39 @@ wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd) } static wasi_errno_t -wasi_fd_write(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 iovs_offset /* const wasi_ciovec_t * */, - uint32 iovs_len, - int32 nwritten_offset /* size_t * */) +wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, + uint32 *nwritten_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - int32 mem; wasi_ciovec_t *ciovec, *ciovec_begin; - iovec_app_t *ciovec_app; - uint32 i; - size_t nwritten; - uint32 *nwritten_app; uint64 total_size; + size_t nwritten; + int32 mem; + uint32 i; wasi_errno_t err; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_app_addr(nwritten_offset, (uint32)sizeof(uint32)) + if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_app_addr(iovs_offset, (uint32)total_size)) + || !validate_native_addr((void*)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; - ciovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); - total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; if (total_size >= UINT32_MAX - || !(mem = module_malloc((uint32)total_size))) + || !(mem = module_malloc((uint32)total_size, (void**)&ciovec_begin))) return (wasi_errno_t)-1; - ciovec_begin = ciovec = (wasi_ciovec_t*)addr_app_to_native(mem); - for (i = 0; i < iovs_len; i++, ciovec_app++, ciovec++) { - if (!validate_app_addr(ciovec_app->buf_offset, ciovec_app->buf_len)) { + ciovec = ciovec_begin; + + for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(ciovec_app->buf_offset); - ciovec->buf_len = ciovec_app->buf_len; + ciovec->buf = (char*)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf_len = iovec_app->buf_len; } err = wasmtime_ssp_fd_write(wasi_ctx->curfds, fd, @@ -656,8 +546,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, if (err) goto fail; - nwritten_app = (uint32*)addr_app_to_native(nwritten_offset); - *(uint32*)nwritten_app = (uint32)nwritten; + *nwritten_app = (uint32)nwritten; /* success */ err = 0; @@ -694,18 +583,10 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, static wasi_errno_t wasi_path_create_directory(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 path_offset /* const char * */, - uint32 path_len) + wasi_fd_t fd, const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path; - - if (!validate_app_addr(path_offset, path_len)) - return (wasi_errno_t)-1; - - path = (char*)addr_app_to_native(path_offset); return wasmtime_ssp_path_create_directory(wasi_ctx->curfds, fd, path, path_len); @@ -715,22 +596,12 @@ static wasi_errno_t wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, wasi_lookupflags_t old_flags, - int32 old_path_offset /* const char * */, - uint32 old_path_len, + const char *old_path, uint32 old_path_len, wasi_fd_t new_fd, - int32 new_path_offset /* const char * */, - uint32 new_path_len) + const char *new_path, uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *old_path, *new_path; - - if (!validate_app_addr(old_path_offset, old_path_len) - || !validate_app_addr(new_path_offset, new_path_len)) - return (wasi_errno_t)-1; - - old_path = (char*)addr_app_to_native(old_path_offset); - new_path = (char*)addr_app_to_native(new_path_offset); return wasmtime_ssp_path_link(wasi_ctx->curfds, wasi_ctx->prestats, old_fd, old_flags, old_path, old_path_len, @@ -741,156 +612,107 @@ static wasi_errno_t wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, wasi_lookupflags_t dirflags, - int32 path_offset /* const char * */, - uint32 path_len, + const char *path, uint32 path_len, wasi_oflags_t oflags, wasi_rights_t fs_rights_base, wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags, - int32 fd_offset /* wasi_fd_t * */) + wasi_fd_t *fd_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path; - wasi_fd_t fd = (wasi_fd_t)-1; - uint32 *fd_app; + wasi_fd_t fd = -1; /* set fd_app -1 if path open failed */ wasi_errno_t err; - if (!validate_app_addr(path_offset, path_len) - || !validate_app_addr(fd_offset, 1)) + if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) return (wasi_errno_t)-1; - path = (char*)addr_app_to_native(path_offset); - err = wasmtime_ssp_path_open(wasi_ctx->curfds, - dirfd, dirflags, - path, path_len, - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - &fd); + dirfd, dirflags, + path, path_len, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + &fd); - fd_app = (wasi_fd_t*)addr_app_to_native(fd_offset); - *fd_app = (uint32)fd; - - WASI_CHECK_ERR(); - - return 0; + *fd_app = fd; + return err; } static wasi_errno_t wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, - int32 buf_offset /* void *buf */, - uint32 buf_len, + void *buf, uint32 buf_len, wasi_dircookie_t cookie, - int32 bufused_offset /* size_t * */) + uint32 *bufused_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - void *buf; size_t bufused; - uint32 *bufused_app; wasi_errno_t err; - if (!validate_app_addr(buf_offset, buf_len) - || !validate_app_addr(bufused_offset, sizeof(uint32))) + if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - buf = (void*)addr_app_to_native(buf_offset); - err = wasmtime_ssp_fd_readdir(wasi_ctx->curfds, fd, buf, buf_len, cookie, &bufused); - WASI_CHECK_ERR(); - - bufused_app = (uint32*)addr_app_to_native(bufused_offset); - *(uint32*)bufused_app = (uint32)bufused; + if (err) + return err; + *bufused_app = (uint32)bufused; return 0; } static wasi_errno_t wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, - int32 path_offset /* const char * */, - uint32 path_len, - int32 buf_offset /* char * */, - uint32 buf_len, - int32 bufused_offset /* size_t * */) + const char *path, uint32 path_len, + char *buf, uint32 buf_len, + uint32 *bufused_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path, *buf; size_t bufused; - uint32 *bufused_app; wasi_errno_t err; - if (!validate_app_addr(path_offset, path_len) - || !validate_app_addr(buf_offset, buf_len) - || !validate_app_addr(bufused_offset, sizeof(uint32))) + if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - path = (char*)addr_app_to_native(path_offset); - buf = (char*)addr_app_to_native(buf_offset); - err = wasmtime_ssp_path_readlink(wasi_ctx->curfds, fd, - path, path_len, buf, - buf_len, &bufused); - WASI_CHECK_ERR(); - - bufused_app = (uint32*)addr_app_to_native(bufused_offset); - *(uint32*)bufused_app = (uint32)bufused; + path, path_len, + buf, buf_len, &bufused); + if (err) + return err; + *bufused_app = (uint32)bufused; return 0; } static wasi_errno_t wasi_path_rename(wasm_exec_env_t exec_env, - wasi_fd_t old_fd, - int32 old_path_offset /* const char * */, - uint32 old_path_len, - wasi_fd_t new_fd, - int32 new_path_offset /* const char * */, - uint32 new_path_len) + wasi_fd_t old_fd, const char *old_path, uint32 old_path_len, + wasi_fd_t new_fd, const char *new_path, uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *old_path, *new_path; - if (!validate_app_addr(old_path_offset, old_path_len) - || !validate_app_addr(new_path_offset, new_path_len)) - return (wasi_errno_t)-1; - - old_path = (char*)addr_app_to_native(old_path_offset); - new_path = (char*)addr_app_to_native(new_path_offset); - - return wasmtime_ssp_path_rename(wasi_ctx->curfds, old_fd, - old_path, old_path_len, - new_fd, new_path, - new_path_len); + return wasmtime_ssp_path_rename(wasi_ctx->curfds, + old_fd, old_path, old_path_len, + new_fd, new_path, new_path_len); } static wasi_errno_t wasi_fd_filestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 buf_offset /* wasi_filestat_t * */) + wasi_fd_t fd, wasi_filestat_t *filestat) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - wasi_filestat_t filestat, *filestat_app; - wasi_errno_t err; - if (!validate_app_addr(buf_offset, sizeof(wasi_filestat_t))) + if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_filestat_get(wasi_ctx->curfds, fd, &filestat); - WASI_CHECK_ERR(); - - filestat_app = (wasi_filestat_t*)addr_app_to_native(buf_offset); - memcpy(filestat_app, &filestat, sizeof(wasi_filestat_t)); - - return 0; + return wasmtime_ssp_fd_filestat_get(wasi_ctx->curfds, fd, filestat); } static wasi_errno_t @@ -922,50 +744,30 @@ static wasi_errno_t wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_lookupflags_t flags, - int32 path_offset /* const char * */, - uint32 path_len, - int32 buf_offset /* wasi_filestat_t * */) + const char *path, uint32 path_len, + wasi_filestat_t *filestat) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path; - wasi_filestat_t filestat, *filestat_app; - wasi_errno_t err; - if (!validate_app_addr(path_offset, path_len) - || !validate_app_addr(buf_offset, sizeof(wasi_filestat_t))) + if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - path = (char*)addr_app_to_native(path_offset); - - err = wasmtime_ssp_path_filestat_get(wasi_ctx->curfds, fd, - flags, path, path_len, &filestat); - WASI_CHECK_ERR(); - - filestat_app = (wasi_filestat_t*)addr_app_to_native(buf_offset); - memcpy(filestat_app, &filestat, sizeof(wasi_filestat_t)); - - return 0; + return wasmtime_ssp_path_filestat_get(wasi_ctx->curfds, fd, + flags, path, path_len, filestat); } static wasi_errno_t wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_lookupflags_t flags, - int32 path_offset /* const char * */, - uint32 path_len, + const char *path, uint32 path_len, wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path; - - if (!validate_app_addr(path_offset, path_len)) - return (wasi_errno_t)-1; - - path = (char*)addr_app_to_native(path_offset); return wasmtime_ssp_path_filestat_set_times(wasi_ctx->curfds, fd, flags, path, path_len, @@ -974,93 +776,58 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, static wasi_errno_t wasi_path_symlink(wasm_exec_env_t exec_env, - int32 old_path_offset /* const char * */, - uint32 old_path_len, - wasi_fd_t fd, - int32 new_path_offset /* const char * */, - uint32 new_path_len) + const char *old_path, uint32 old_path_len, + wasi_fd_t fd, const char *new_path, uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *old_path, *new_path; - - if (!validate_app_addr(old_path_offset, old_path_len) - || !validate_app_addr(new_path_offset, new_path_len)) - return (wasi_errno_t)-1; - - old_path = (char*)addr_app_to_native(old_path_offset); - new_path = (char*)addr_app_to_native(new_path_offset); return wasmtime_ssp_path_symlink(wasi_ctx->curfds, wasi_ctx->prestats, - old_path, old_path_len, fd, new_path, - new_path_len); + old_path, old_path_len, fd, + new_path, new_path_len); } static wasi_errno_t wasi_path_unlink_file(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 path_offset /* const char * */, - uint32 path_len) + wasi_fd_t fd, const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path; - - if (!validate_app_addr(path_offset, path_len)) - return (wasi_errno_t)-1; - - path = (char*)addr_app_to_native(path_offset); return wasmtime_ssp_path_unlink_file(wasi_ctx->curfds, fd, path, path_len); } static wasi_errno_t wasi_path_remove_directory(wasm_exec_env_t exec_env, - wasi_fd_t fd, - int32 path_offset /* const char * */, - uint32 path_len) + wasi_fd_t fd, const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - char *path; - - if (!validate_app_addr(path_offset, path_len)) - return (wasi_errno_t)-1; - - path = (char*)addr_app_to_native(path_offset); return wasmtime_ssp_path_remove_directory(wasi_ctx->curfds, fd, path, path_len); } static wasi_errno_t wasi_poll_oneoff(wasm_exec_env_t exec_env, - int32 in_offset /* const wasi_subscription_t * */, - int32 out_offset /* wasi_event_t * */, - uint32 nsubscriptions, - int32 nevents_offset /* size_t * */) + const wasi_subscription_t *in, wasi_event_t *out, + uint32 nsubscriptions, uint32 *nevents_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - wasi_subscription_t *in; - wasi_event_t *out; size_t nevents; - uint32 *nevents_app; wasi_errno_t err; - if (!validate_app_addr(in_offset, sizeof(wasi_subscription_t)) - || !validate_app_addr(out_offset, sizeof(wasi_event_t)) - || !validate_app_addr(nevents_offset, sizeof(uint32))) + if (!validate_native_addr((void*)in, sizeof(wasi_subscription_t)) + || !validate_native_addr(out, sizeof(wasi_event_t)) + || !validate_native_addr(nevents_app, sizeof(uint32))) return (wasi_errno_t)-1; - in = (wasi_subscription_t*)addr_app_to_native(in_offset); - out = (wasi_event_t*)addr_app_to_native(out_offset); - - err = wasmtime_ssp_poll_oneoff(wasi_ctx->curfds, in, out, nsubscriptions, &nevents); - WASI_CHECK_ERR(); - - nevents_app = (uint32*)addr_app_to_native(nevents_offset); - *(uint32*)nevents_app = (uint32)nevents; + err = wasmtime_ssp_poll_oneoff(wasi_ctx->curfds, in, out, + nsubscriptions, &nevents); + if (err) + return err; + *nevents_app = (uint32)nevents; return 0; } @@ -1082,79 +849,59 @@ wasi_proc_raise(wasm_exec_env_t exec_env, wasi_signal_t sig) } static wasi_errno_t -wasi_random_get(wasm_exec_env_t exec_env, - int32 buf_offset /* void * */, - uint32 buf_len) +wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); - void *buf; - - if (!validate_app_addr(buf_offset, buf_len)) - return (wasi_errno_t)-1; - - buf = (void*)addr_app_to_native(buf_offset); - return wasmtime_ssp_random_get(buf, buf_len); } static wasi_errno_t wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, - int32 ri_data_offset /* const wasi_iovec_t * */, - uint32 ri_data_len, + iovec_app_t *ri_data, uint32 ri_data_len, wasi_riflags_t ri_flags, - int32 ro_datalen_offset /* size_t * */, - int32 ro_flags_offset /* wasi_roflags_t * */) + uint32 *ro_datalen_app, + wasi_roflags_t *ro_flags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_iovec_t *iovec, *iovec_begin; - int32 mem; - iovec_app_t *ri_data_app; - uint32 i; - size_t ro_datalen; - wasi_roflags_t ro_flags; - uint32 *ro_datalen_app, *ro_flags_app; uint64 total_size; + size_t ro_datalen; + int32 mem; + uint32 i; wasi_errno_t err; total_size = sizeof(iovec_app_t) * (uint64)ri_data_len; - if (!validate_app_addr(ro_datalen_offset, (uint32)sizeof(uint32)) - || !validate_app_addr(ro_flags_offset, (uint32)sizeof(uint32)) + if (!validate_native_addr(ro_datalen_app, (uint32)sizeof(uint32)) + || !validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t)) || total_size >= UINT32_MAX - || !validate_app_addr(ri_data_offset, (uint32)total_size)) + || !validate_native_addr(ri_data, (uint32)total_size)) return (wasi_errno_t)-1; - ri_data_app = (iovec_app_t*)addr_app_to_native(ri_data_offset); - total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len; if (total_size >= UINT32_MAX - || !(mem = module_malloc((uint32)total_size))) + || !(mem = module_malloc((uint32)total_size, (void**)&iovec_begin))) return (wasi_errno_t)-1; - iovec = iovec_begin = (wasi_iovec_t*)addr_app_to_native(mem); + iovec = iovec_begin; - for (i = 0; i < ri_data_len; i++, ri_data_app++, iovec++) { - if (!validate_app_addr(ri_data_app->buf_offset, ri_data_app->buf_len)) { + 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; } - iovec->buf = (void*)addr_app_to_native(ri_data_app->buf_offset); - iovec->buf_len = ri_data_app->buf_len; + iovec->buf = (void*)addr_app_to_native(ri_data->buf_offset); + iovec->buf_len = ri_data->buf_len; } err = wasmtime_ssp_sock_recv(wasi_ctx->curfds, sock, iovec_begin, ri_data_len, ri_flags, &ro_datalen, - &ro_flags); + ro_flags); if (err) goto fail; - ro_datalen_app = (uint32*)addr_app_to_native(ro_datalen_offset); - ro_flags_app = (uint32*)addr_app_to_native(ro_flags_offset); - *(uint32*)ro_datalen_app = (uint32)ro_datalen; - *(uint32*)ro_flags_app = (uint32)ro_flags; /* success */ err = 0; @@ -1167,44 +914,39 @@ fail: static wasi_errno_t wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, - int32 si_data_offset /* const wasi_ciovec_t * */, - uint32 si_data_len, + const iovec_app_t *si_data, uint32 si_data_len, wasi_siflags_t si_flags, - int32 so_datalen_offset /* size_t * */) + uint32 *so_datalen_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - int32 mem; wasi_ciovec_t *ciovec, *ciovec_begin; - iovec_app_t *si_data_app; - uint32 i; - size_t so_datalen; - uint32 *so_datalen_app; uint64 total_size; + size_t so_datalen; + int32 mem; + uint32 i; wasi_errno_t err; total_size = sizeof(iovec_app_t) * (uint64)si_data_len; - if (!validate_app_addr(so_datalen_offset, sizeof(uint32)) + if (!validate_native_addr(so_datalen_app, sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_app_addr(si_data_offset, (uint32)total_size)) + || !validate_native_addr((void*)si_data, (uint32)total_size)) return (wasi_errno_t)-1; - si_data_app = (iovec_app_t*)addr_app_to_native(si_data_offset); - total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len; if (total_size >= UINT32_MAX - || !(mem = module_malloc((uint32)total_size))) + || !(mem = module_malloc((uint32)total_size, (void**)&ciovec_begin))) return (wasi_errno_t)-1; - ciovec_begin = ciovec = (wasi_ciovec_t*)addr_app_to_native(mem); + ciovec = ciovec_begin; - for (i = 0; i < si_data_len; i++, si_data_app++, ciovec++) { - if (!validate_app_addr(si_data_app->buf_offset, si_data_app->buf_len)) { + 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; } - ciovec->buf = (char*)addr_app_to_native(si_data_app->buf_offset); - ciovec->buf_len = si_data_app->buf_len; + ciovec->buf = (char*)addr_app_to_native(si_data->buf_offset); + ciovec->buf_len = si_data->buf_len; } err = wasmtime_ssp_sock_send(wasi_ctx->curfds, sock, @@ -1213,8 +955,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, if (err) goto fail; - so_datalen_app = (uint32*)addr_app_to_native(so_datalen_offset); - *(uint32*)so_datalen_app = (uint32)so_datalen; + *so_datalen_app = (uint32)so_datalen; /* success */ err = 0; @@ -1240,81 +981,61 @@ wasi_sched_yield(wasm_exec_env_t exec_env) return wasmtime_ssp_sched_yield(); } -#define REG_NATIVE_FUNC(func_name) \ - { "wasi_unstable", #func_name, wasi_##func_name } +#define REG_NATIVE_FUNC(func_name, signature) \ + { #func_name, wasi_##func_name, signature } -typedef struct WASMNativeFuncDef { - const char *module_name; - const char *func_name; - void *func_ptr; -} WASMNativeFuncDef; - -static WASMNativeFuncDef native_func_defs[] = { - REG_NATIVE_FUNC(args_get), - REG_NATIVE_FUNC(args_sizes_get), - REG_NATIVE_FUNC(clock_res_get), - REG_NATIVE_FUNC(clock_time_get), - REG_NATIVE_FUNC(environ_get), - REG_NATIVE_FUNC(environ_sizes_get), - REG_NATIVE_FUNC(fd_prestat_get), - REG_NATIVE_FUNC(fd_prestat_dir_name), - REG_NATIVE_FUNC(fd_close), - REG_NATIVE_FUNC(fd_datasync), - REG_NATIVE_FUNC(fd_pread), - REG_NATIVE_FUNC(fd_pwrite), - REG_NATIVE_FUNC(fd_read), - REG_NATIVE_FUNC(fd_renumber), - REG_NATIVE_FUNC(fd_seek), - REG_NATIVE_FUNC(fd_tell), - REG_NATIVE_FUNC(fd_fdstat_get), - REG_NATIVE_FUNC(fd_fdstat_set_flags), - REG_NATIVE_FUNC(fd_fdstat_set_rights), - REG_NATIVE_FUNC(fd_sync), - REG_NATIVE_FUNC(fd_write), - REG_NATIVE_FUNC(fd_advise), - REG_NATIVE_FUNC(fd_allocate), - REG_NATIVE_FUNC(path_create_directory), - REG_NATIVE_FUNC(path_link), - REG_NATIVE_FUNC(path_open), - REG_NATIVE_FUNC(fd_readdir), - REG_NATIVE_FUNC(path_readlink), - REG_NATIVE_FUNC(path_rename), - REG_NATIVE_FUNC(fd_filestat_get), - REG_NATIVE_FUNC(fd_filestat_set_times), - REG_NATIVE_FUNC(fd_filestat_set_size), - REG_NATIVE_FUNC(path_filestat_get), - REG_NATIVE_FUNC(path_filestat_set_times), - REG_NATIVE_FUNC(path_symlink), - REG_NATIVE_FUNC(path_unlink_file), - REG_NATIVE_FUNC(path_remove_directory), - REG_NATIVE_FUNC(poll_oneoff), - REG_NATIVE_FUNC(proc_exit), - REG_NATIVE_FUNC(proc_raise), - REG_NATIVE_FUNC(random_get), - REG_NATIVE_FUNC(sock_recv), - REG_NATIVE_FUNC(sock_send), - REG_NATIVE_FUNC(sock_shutdown), - REG_NATIVE_FUNC(sched_yield), +static NativeSymbol native_symbols_libc_wasi[] = { + REG_NATIVE_FUNC(args_get, "(**)i"), + REG_NATIVE_FUNC(args_sizes_get, "(**)i"), + REG_NATIVE_FUNC(clock_res_get, "(i*)i"), + REG_NATIVE_FUNC(clock_time_get, "(iI*)i"), + REG_NATIVE_FUNC(environ_get, "(**)i"), + REG_NATIVE_FUNC(environ_sizes_get, "(**)i"), + REG_NATIVE_FUNC(fd_prestat_get, "(i*)i"), + REG_NATIVE_FUNC(fd_prestat_dir_name, "(i*~)i"), + REG_NATIVE_FUNC(fd_close, "(i)i"), + REG_NATIVE_FUNC(fd_datasync, "(i)i"), + REG_NATIVE_FUNC(fd_pread, "(i*iI*)i"), + REG_NATIVE_FUNC(fd_pwrite, "(i*iI*)i"), + REG_NATIVE_FUNC(fd_read, "(i*i*)i"), + REG_NATIVE_FUNC(fd_renumber, "(ii)i"), + REG_NATIVE_FUNC(fd_seek, "(iIi*)i"), + REG_NATIVE_FUNC(fd_tell, "(i*)i"), + REG_NATIVE_FUNC(fd_fdstat_get, "(i*)i"), + REG_NATIVE_FUNC(fd_fdstat_set_flags, "(ii)i"), + REG_NATIVE_FUNC(fd_fdstat_set_rights, "(iII)i"), + REG_NATIVE_FUNC(fd_sync, "(i)i"), + REG_NATIVE_FUNC(fd_write, "(i*i*)i"), + REG_NATIVE_FUNC(fd_advise, "(iIIi)i"), + REG_NATIVE_FUNC(fd_allocate, "(iII)i"), + REG_NATIVE_FUNC(path_create_directory, "(i*~)i"), + REG_NATIVE_FUNC(path_link, "(ii*~i*~)i"), + REG_NATIVE_FUNC(path_open, "(ii*~iIIi*)i"), + REG_NATIVE_FUNC(fd_readdir, "(i*~I*)i"), + REG_NATIVE_FUNC(path_readlink, "(i*~*~*)i"), + REG_NATIVE_FUNC(path_rename, "(i*~i*~)i"), + REG_NATIVE_FUNC(fd_filestat_get, "(i*)i"), + REG_NATIVE_FUNC(fd_filestat_set_times, "(iIIi)i"), + REG_NATIVE_FUNC(fd_filestat_set_size, "(iI)i"), + REG_NATIVE_FUNC(path_filestat_get, "(ii*~*)i"), + REG_NATIVE_FUNC(path_filestat_set_times, "(ii*~IIi)i"), + REG_NATIVE_FUNC(path_symlink, "(*~i*~)i"), + REG_NATIVE_FUNC(path_unlink_file, "(i*~)i"), + REG_NATIVE_FUNC(path_remove_directory, "(i*~)i"), + REG_NATIVE_FUNC(poll_oneoff, "(**i*)i"), + REG_NATIVE_FUNC(proc_exit, "(i)"), + REG_NATIVE_FUNC(proc_raise, "(i)i"), + REG_NATIVE_FUNC(random_get, "(*~)i"), + REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"), + REG_NATIVE_FUNC(sock_send, "(i*ii*)i"), + REG_NATIVE_FUNC(sock_shutdown, "(ii)i"), + REG_NATIVE_FUNC(sched_yield, "()i"), }; -void * -wasm_native_lookup_libc_wasi_func(const char *module_name, - const char *func_name) +uint32 +get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis) { - uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef); - WASMNativeFuncDef *func_def = native_func_defs; - WASMNativeFuncDef *func_def_end = func_def + size; - - 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)) - return (void*) (uintptr_t) func_def->func_ptr; - func_def++; - } - - return NULL; + *p_libc_wasi_apis = native_symbols_libc_wasi; + return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol); } diff --git a/core/shared/include/config.h b/core/shared/include/config.h index ed00e2f89..bb98980ee 100644 --- a/core/shared/include/config.h +++ b/core/shared/include/config.h @@ -80,6 +80,10 @@ enum { #define WASM_ENABLE_BASE_LIB 0 #endif +#ifndef WASM_ENABLE_APP_FRAMEWORK +#define WASM_ENABLE_APP_FRAMEWORK 0 +#endif + /* WASM log system */ #ifndef WASM_ENABLE_LOG #define WASM_ENABLE_LOG 1 @@ -148,8 +152,8 @@ enum { #define APP_THREAD_STACK_SIZE_MIN (16 * 1024) #define APP_THREAD_STACK_SIZE_MAX (256 * 1024) #else -#define APP_THREAD_STACK_SIZE_DEFAULT (4 * 1024) -#define APP_THREAD_STACK_SIZE_MIN (2 * 1024) +#define APP_THREAD_STACK_SIZE_DEFAULT (6 * 1024) +#define APP_THREAD_STACK_SIZE_MIN (4 * 1024) #define APP_THREAD_STACK_SIZE_MAX (256 * 1024) #endif diff --git a/core/shared/platform/zephyr/bh_platform.c b/core/shared/platform/zephyr/bh_platform.c index 27c35ff34..f2bc2e380 100755 --- a/core/shared/platform/zephyr/bh_platform.c +++ b/core/shared/platform/zephyr/bh_platform.c @@ -91,7 +91,7 @@ bh_mprotect(void *addr, uint32 size, int prot) void bh_dcache_flush() { -#if defined(CONFIG_CPU_CORTEX_M7) +#if defined(CONFIG_CPU_CORTEX_M7) && defined(CONFIG_ARM_MPU) uint32 key; key = irq_lock(); SCB_CleanDCache(); diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index 351dd351c..3a2c530aa 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -1,10 +1,13 @@ -Embed WAMR into software production +Embedding WAMR guideline ===================================== -![WAMR embed diagram](./pics/embed.PNG "WAMR embed architecture diagram") + +**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. + +## The initialization procedure + -A typical WAMR API usage is shown below (some return value checks are ignored): ``` C static char global_heap_buf[512 * 1024]; @@ -13,27 +16,162 @@ A typical WAMR API usage is shown below (some return value checks are ignored): wasm_module_inst_t module_inst; wasm_function_inst_t func; wasm_exec_env_t exec_env; - uint32 argv[2], size, stack_size = 8092, heap_size = 8092; + uint32 size, stack_size = 8092, heap_size = 8092; + // all the WAMR heap and WASM applications are limited in this buffer bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)); + wasm_runtime_init(); + // read WASM file into a memory buffer buffer = read_wasm_binary_to_buffer(…, &size); + + // parse the WASM file from buffer and create a WASM module module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); - module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, - error_buf, sizeof(error_buf)); - func = wasm_runtime_lookup_function(module_inst, "fib", "(i32)i32"); + + // create an instance of the WASM module (WASM linear memory is ready) + module_inst = wasm_runtime_instantiate(module, + stack_size, + heap_size, + error_buf, + sizeof(error_buf)); +``` + + + + + +## Native calls WASM functions and passes parameters + +After a module is instantiated, the runtime native can lookup WASM functions by the names and call them. + +```c + unit32 argv[2]; + + // lookup a WASM function by its name + func = wasm_runtime_lookup_function(module_inst, "fib", NULL); + + // creat a excution environment which can be used by executing WASM functions exec_env = wasm_runtime_create_exec_env(module_inst, stack_size); + // arguments are always transferred in 32 bits element argv[0] = 8; - if (wasm_runtime_call_wasm(exec_env, func, 1, argv_buf) ) { + + // call the WASM function + if (wasm_runtime_call_wasm(exec_env, func, 1, argv) ) { + /* the return value is stored in argv[0] */ printf("fib function return: %d\n", argv[0]); } else { printf("%s\n", wasm_runtime_get_exception(module_inst)); } +``` + + +The parameters are transferred in an array of 32 bits elements. For parameters that occupy 4 or fewer bytes, each parameter can be a single array element. For parameters in types like double or int64, each parameter will take two array elements. The function return value will be sent back in the first one or two elements of the array according to the value type. See the sample code below: + +```c + unit32 argv[6]; + char arg1 = 'a'; + int arg2 = 10; + double arg3 = 1.0; + int 64 arg4 = 100; + double ret; + + argv[0] = arg1; + argv[1] = arg2; + + // use memory copy for 8 bytes parameters rather than + // *(double*)(&argv[2]) = arg3 here because some archs + // like ARM, MIPS requires address is 8 aligned. + // Or use the aligned malloc or compiler align attribute + // to ensure the array address is 8 bytes aligned + memcpy(&argv[2], &arg3, sizeof(arg3)); + memcpy(&argv[4], &arg4, sizeof(arg4)); + + // + // attention: the arg number is 6 here since both + // arg3 and arg4 each takes 2 elements + // + wasm_runtime_call_wasm(exec_env, func, 6, argv); + + // if the return value is type of 8 bytes, it takes + // the first two array elements + memcpy(&ret, &argv[0], sizeof(ret)); + +``` + + + +## Pass buffer to WASM function + + + +If we need to transfer a buffer to WASM function, we can pass the buffer address through a parameter. **Attention**: The sandbox will forbid the WASM code to access outside memory, we must **allocate the buffer from WASM instance's own memory space and pass the buffer address in instance's space (not the runtime native address)**. + + + +There are two runtime APIs available for this purpose. + +```c +/* +* description: malloc a buffer from instance's private memory space. +* +* return: the buffer address in instance's memory space (pass to the WASM funciton) +* p_native_addr: return the native address of allocated memory +* size: the buffer size to allocate +*/ +int32_t +wasm_runtime_module_malloc(wasm_module_inst_t module_inst, + uint32_t size, + void **p_native_addr); + +/* +* description: malloc a buffer from instance's private memory space, +* and copy the data from another native buffer to it. +* return: the buffer address in instance's memory space (pass to the WASM funciton) +* src: the native buffer address +* size: the size of buffer to be allocated and copy data +*/ +int32 +wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, + const char *src, + uint32 size); +``` + + + +Usage sample: + +```c +char * buffer = NULL; +int32_t buffer_for_wasm; + +buffer_for_wasm = wasm_runtime_module_malloc(module_inst, 100, &buffer); +if(buffer_for_wasm != 0) +{ + unit32 argv[2]; + strncpy(buffer, "hello", 100); // use native address for accessing in runtime + argv[0] = buffer_for_wasm; // pass the buffer address for WASM space. + argv[1] = 100; // the size of buffer + wasm_runtime_call_wasm(exec_env, func, 2, argv); +} + +``` + + + +## Pass structured data to WASM function + +We can't pass structure data or class objects through the pointer since the memory layout can different in two worlds. The way to do it is serialization. Refer to [export_native_api.md](./export_native_api.md) for the details. + + + +## The deinitialization procedure + +``` wasm_runtime_destroy_exec_env(exec_env); wasm_runtime_deinstantiate(module_inst); wasm_runtime_unload(module); @@ -41,3 +179,8 @@ A typical WAMR API usage is shown below (some return value checks are ignored): bh_memory_destroy(); ``` + + +## Native calling WASM function working flow + +![WAMR embed diagram](./pics/embed.PNG "WAMR embed architecture diagram") diff --git a/doc/export_native_api.md b/doc/export_native_api.md index f1bfbabcf..04c914e2d 100644 --- a/doc/export_native_api.md +++ b/doc/export_native_api.md @@ -2,202 +2,239 @@ Export 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. +Exporting native API steps +-------------------------- + +#### Step 1: Declare the function interface in WASM app + +Create a header file in a WASM app and declare the functions that are exported from native. In this example, we declare foo and foo2 as below in the header file "example.h" + +```c +/*** file name: example.h ***/ + +int foo(int a, int b); +void foo2(char * msg, char * buffer, int buf_len); +``` + + + +#### Step 2: Define the native API + +Define the native functions which are executed from the WASM app in the runtime source file. The native function can be any name, for example **foo_native** and **foo2** here: + ``` 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) +int foo_native(wasm_exec_env_t exec_env , int a, int b) +{ + return a+b; +} + +void foo2(wasm_exec_env_t exec_env, char * msg, uint8 * buffer, int buf_len) +{ + strncpy(buffer, msg, buf_len); +} +``` + +The first parameter exec_env must be defined using type **wasm_exec_env_t** which is the calling convention for exporting native API by WAMR. + +The rest parameters should be in the same types as the parameters of WASM function foo(), but there are a few special cases that are explained in section "Buffer address conversion and boundary check". Regarding the parameter names, they don't have to be the same, but we would suggest using the same names for easy maintenance. + + + +#### Step 3: Register the native APIs + +Register the native APIs in the runtime, then everything is fine. It is ready to build the runtime software. + +``` C +// Define an array of NativeSymbol for the APIs to be exported. +// Note: the array must be static defined since runtime +// will keep it after registration +static NativeSymbol native_symbols[] = +{ + { + "foo", // the name of WASM function name + foo_native, // the native function pointer + "(ii)i" // the function prototype signature + }, + { + "foo2", // the name of WASM function name + foo2, // the native function pointer + "($*~)" // the function prototype signature + } +}; + +// ensure the memory and runtime initialization is finsihed +// before registering the native functions +bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)); +wasm_runtime_init(); + +int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); +if (!wasm_runtime_register_natives("env", + native_symbols, + n_native_symbols)) { + goto fail1; +} + +// natives registeration must be done before loading WASM modules +module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); + +``` + +**Function signature**: + +The function signature field in **NativeSymbol** structure is a string for describing the function prototype. It is critical to ensure the function signature is correctly mapping the native function interface. + +Each letter in the "()" represents a parameter type, and the one following after ")" represents the return value type. The meaning of each letter: + +- 'i': i32 +- 'I': i64 +- 'f': f32 +- 'F': f64 +- '*': the parameter is a buffer address in WASM application +- '~': the parameter is the byte length of WASM buffer as referred by preceding argument "\*". It must follow after '*', otherwise, registration will fail +- '$': the parameter is a string in WASM application + +**Use EXPORT_WASM_API_WITH_SIG** + +The above foo2 NativeSymbol element can be also defined with macro EXPORT_WASM_API_WITH_SIG. This macro can be used when the native function name is the same as the WASM symbol name. + +```c +static NativeSymbol native_symbols[] = +{ + EXPORT_WASM_API_WITH_SIG(foo2, "($*~)") }; ``` -**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 +## Call exported API in wasm application - - -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. - -In wasm world: -``` C -void api_send_request(request_t * request, response_handler_f response_handler, - void * user_data) -{ - int size; - char *buffer; - transaction_t *trans; - - if ((trans = (transaction_t *) malloc(sizeof(transaction_t))) == NULL) { - printf( - "send request: allocate memory for request transaction failed!\n"); - return; - } - - memset(trans, 0, sizeof(transaction_t)); - trans->handler = response_handler; - trans->mid = request->mid; - trans->time = wasm_get_sys_tick_ms(); - trans->user_data = user_data; - - // pack request - if ((buffer = pack_request(request, &size)) == NULL) { - printf("send request: pack request failed!\n"); - free(trans); - return; - } - - transaction_add(trans); - - /* if the trans is the 1st one, start the timer */ - if (trans == g_transactions) { - /* assert(g_trans_timer == NULL); */ - if (g_trans_timer == NULL) { - g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS, - false, - true, transaction_timeout_handler); - } - } - - // call native API - wasm_post_request(buffer, size); - - free_req_resp_packet(buffer); -} -``` - -In native world: -``` C -void -wasm_post_request(wasm_exec_env_t exec_env, - int32 buffer_offset, int size) -{ - wasm_module_inst_t module_inst = get_module_inst(exec_env); - char *buffer = NULL; - - // do boundary check - if (!validate_app_addr(buffer_offset, size)) - return; - - // do address conversion - buffer = addr_app_to_native(buffer_offset); - - if (buffer != NULL) { - request_t req[1]; - - // De-serialize data - if (!unpack_request(buffer, size, req)) - return; - - // set sender to help dispatch the response to the sender app later - unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, - module_inst); - bh_assert(mod_id != ID_NONE); - req->sender = mod_id; - - if (req->action == COAP_EVENT) { - am_publish_event(req); - return; - } - - am_dispatch_request(req); - } -} -``` - - - - - -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: Define the native API for exporting - -Define the function **example_native_func** in your source file, namely `example.c` here: -``` C -int example_native_func(wasm_exec_env_t exec_env, - int arg1, int arg2) -{ - // Your implementation here -} -``` -The first function argument must be defined using type **wasm_exec_env_t** which is the WAMR calling convention for native API exporting. - -The function prototype should also be declared in a header file so the wasm application can include it. -``` C -#ifndef _EXAMPLE_H_ -#define _EXAMPLE_H_ -#ifdef __cplusplus -extern "C" { -#endif - -void example_native_func(int arg1, int arg2); - -#ifdef __cplusplus -} -#endif -#endif -``` - -## Step 2: Declare the native API exporting - -Declare the function **example_native_func** with macro **EXPORT_WASM_API** in your **.inl** file, namely `example.inl` in this sample. -``` C -EXPORT_WASM_API(example_native_func), -``` - -Then include the file **example.inl** in definition of array **extended_native_symbol_defs** in the `ext_lib_export.c`. -``` C -static NativeSymbol extended_native_symbol_defs[] = { - #include "example.inl" -}; - -#include "ext_lib_export.h" -``` - - -## Step 3: Compile the runtime product -Add the source file **example.c** and **ext_lib_export.c** into the CMakeList.txt for building runtime with the exported API's: -``` cmake -set (EXT_API_SOURCE example.c) - -add_executable (sample - # other source files - # ...... - ${EXT_API_SOURCE} - ext_lib_export.c -) -``` - -# Use exported API in wasm application - -We can call the exported native API **example_native_func** in wasm application like this: +Now we can call the exported native API in wasm application like this: ``` C #include -#include "example.h" +#include "example.h" // where the APIs are declared int main(int argc, char **argv) { int a = 0, b = 1; + char * msg = "hello"; + char buffer[100]; - example_native_func(a, b); + int c = foo(a, b); // call into native foo_native() + foo2(msg, buffer, sizeof(buffer)); // call into native foo2() + return 0; } -``` \ No newline at end of file +``` + + + +## Buffer address conversion and boundary check + + A WebAssembly sandbox ensures applications only access to its own memory with a private address space. When passing a pointer address from WASM to native, the address value must be converted to native address before the native function can access it. It is also the native world's responsibility to check the buffer length is not over its sandbox boundary. + + + +The signature letter '$', '\*' and '\~' help the runtime do automatic address conversion and buffer boundary check, so the native function directly uses the string and buffer address. **Notes**: if '\*' is not followed by '\~', the native function should not assume the length of the buffer is more than 1 byte. + + + +As function parameters are always passed in 32 bits numbers, you can also use 'i' for the pointer type argument, then you must do all the address conversion and boundary checking in your native function. For example, if you change the foo2 signature to "(iii)", then you will implement the native part as the following sample: + +```c +void foo2(wasm_exec_env_t exec_env, + uint32 msg_offset, + uint32 buffer_offset, + int32 buf_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + char *buffer; + char * msg ; + + // do boundary check + if (!wasm_runtime_validate_app_str_add(msg_offset)) + return 0; + + if (!wasm_runtime_validate_app_addr(buffer_offset, buf_len)) + return; + + // do address conversion + buffer = wasm_runtime_addr_app_to_native(buffer_offset); + msg = wasm_runtime_addr_app_to_native(msg_offset); + + strncpy(buffer, msg, buf_len); +} +``` + + + + + +## Sandbox security attention + +The runtime builder should ensure not broking the memory sandbox when exporting the native function to WASM. + +A few key ground rules: + +- Never pass any structure/class object pointer to native (do data serialization instead) +- Do the pointer address conversion in the native API if "$\*" is not used for the pointer in the function signature +- Never pass a function pointer to the native + + + +## Pass structured data or class object + +We must do data serialization for passing structured data or class objects between the two worlds of WASM and native. There are two serialization methods available in WASM as below, and yet you can introduce more like json, cbor etc. + +- [attributes container](../core/app-framework/app-native-shared/attr_container.c) +- [restful request/response](../core/app-framework/app-native-shared/restful_utils.c) + +Note the serialization library is separately compiled into WASM and runtime. And the source files are located in the folder "[core/app-framework/app-native-shared](../core/app-framework/app-native-shared)“ where all source files will be compiled into both worlds. + + + +The following sample code demonstrates WASM app packs a response structure to buffer, then pass the buffer pointer to the native: + +```c +/*** file name: core/app-framework/base/app/request.c ***/ + +void api_response_send(response_t *response) +{ + int size; + char * buffer = pack_response(response, &size); + if (buffer == NULL) + return; + + wasm_response_send(buffer, size); // calling exported native API + free_req_resp_packet(buffer); +} +``` + + + +The following code demonstrates the native API unpack the WASM buffer to local native data structure: + +```c +/*** file name: core/app-framework/base/native/request_response.c ***/ + +bool +wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size) +{ + if (buffer != NULL) { + response_t response[1]; + + if (NULL == unpack_response(buffer, size, response)) + return false; + + am_send_response(response); + + return true; + } + + return false; +} +``` + + + diff --git a/doc/pics/app_framework.PNG b/doc/pics/app_framework.PNG new file mode 100644 index 000000000..802c45ba2 Binary files /dev/null and b/doc/pics/app_framework.PNG differ diff --git a/doc/pics/sensor_callflow.PNG b/doc/pics/sensor_callflow.PNG index ff471da0b..12839aa5a 100644 Binary files a/doc/pics/sensor_callflow.PNG and b/doc/pics/sensor_callflow.PNG differ diff --git a/doc/pics/workflow.PNG b/doc/pics/workflow.PNG deleted file mode 100644 index 2bba240ff..000000000 Binary files a/doc/pics/workflow.PNG and /dev/null differ diff --git a/product-mini/platforms/alios-things/aos.mk b/product-mini/platforms/alios-things/aos.mk index ea92eda76..461cb5102 100644 --- a/product-mini/platforms/alios-things/aos.mk +++ b/product-mini/platforms/alios-things/aos.mk @@ -92,7 +92,7 @@ $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/bh_assert.c \ ${IWASM_ROOT}/common/wasm_native.c \ ${IWASM_ROOT}/common/wasm_exec_env.c \ ${IWASM_ROOT}/common/arch/${INVOKE_NATIVE} \ - src/main.c src/ext_lib_export.c + src/main.c ifeq (${WAMR_BUILD_INTERP}, 1) $(NAME)_SOURCES += ${IWASM_ROOT}/interpreter/wasm_interp.c \ diff --git a/product-mini/platforms/alios-things/src/ext_lib_export.c b/product-mini/platforms/alios-things/src/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/alios-things/src/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index 1d20819c8..bdfd10e19 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -4,22 +4,23 @@ cmake_minimum_required (VERSION 3.4.1) set (CMAKE_VERBOSE_MAKEFILE on) +set (CMAKE_BUILD_TYPE Release) set (CMAKE_TOOLCHAIN_FILE "$ENV{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake") set (ANDROID_NDK $ENV{ANDROID_NDK_HOME}) set (ANDROID_SDK $ENV{ANDROID_SDK_HOME}) -set (ANDROID_ABI "armeabi-v7a") +set (ANDROID_ABI "x86") +set (ANDROID_LD lld) project (iwasm) set (WAMR_BUILD_PLATFORM "android") -set (WAMR_BUILD_TARGET "ARMv7") -set (WAMR_BUILD_TYPE Debug) +set (WAMR_BUILD_TARGET "X86_32") +set (WAMR_BUILD_TYPE Release) set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_AOT 0) set (WAMR_BUILD_LIBC_BUILTIN 1) set (WAMR_BUILD_LIBC_WASI 0) -set (CMAKE_BUILD_TYPE Debug) # Reset default linker flags set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") @@ -89,8 +90,12 @@ endif () #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") -add_library (iwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE} ext_lib_export.c) +add_library (iwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +if (CMAKE_BUILD_TYPE STREQUAL Release) +target_link_libraries (iwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -landroid -llog -s) +else() target_link_libraries (iwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -landroid -llog) +endif() set (distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build/distribution) set_target_properties (iwasm PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${distribution_DIR}/wasm/lib") diff --git a/product-mini/platforms/android/ext_lib_export.c b/product-mini/platforms/android/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/android/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/product-mini/platforms/darwin/CMakeLists.txt b/product-mini/platforms/darwin/CMakeLists.txt index 5a44af8c8..2eb5d8d82 100644 --- a/product-mini/platforms/darwin/CMakeLists.txt +++ b/product-mini/platforms/darwin/CMakeLists.txt @@ -62,7 +62,7 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -add_executable (iwasm main.c ext_lib_export.c) +add_executable (iwasm main.c) install (TARGETS iwasm DESTINATION bin) diff --git a/product-mini/platforms/darwin/ext_lib_export.c b/product-mini/platforms/darwin/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/darwin/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/product-mini/platforms/linux-sgx/CMakeLists.txt b/product-mini/platforms/linux-sgx/CMakeLists.txt index 9e92dff4e..d30636866 100644 --- a/product-mini/platforms/linux-sgx/CMakeLists.txt +++ b/product-mini/platforms/linux-sgx/CMakeLists.txt @@ -113,4 +113,3 @@ add_library (vmlib ${IWASM_AOT_SOURCE} ${IWASM_COMPL_SOURCE}) -add_library (extlib ext_lib_export.c) diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Makefile b/product-mini/platforms/linux-sgx/enclave-sample/Makefile index dac4f78da..56016bd98 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Makefile +++ b/product-mini/platforms/linux-sgx/enclave-sample/Makefile @@ -96,7 +96,7 @@ Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fst Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++03 -nostdinc++ Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ - libvmlib.a libextlib.a \ + libvmlib.a \ -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ @@ -174,11 +174,7 @@ libvmlib.a: ../build/libvmlib.a @cp $< $@ @echo "CP $@ <= $<" -libextlib.a: ../build/libextlib.a - @cp $< $@ - @echo "CP $@ <= $<" - -$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) libvmlib.a libextlib.a +$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) libvmlib.a @$(CXX) $^ -o $@ $(Enclave_Link_Flags) @echo "LINK => $@" diff --git a/product-mini/platforms/linux-sgx/ext_lib_export.c b/product-mini/platforms/linux-sgx/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/linux-sgx/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 320534b55..193d9ec0e 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -76,7 +76,7 @@ endif () #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") -add_executable (iwasm main.c ext_lib_export.c) +add_executable (iwasm main.c) install (TARGETS iwasm DESTINATION bin) diff --git a/product-mini/platforms/linux/ext_lib_export.c b/product-mini/platforms/linux/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/linux/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/product-mini/platforms/vxworks/CMakeLists.txt b/product-mini/platforms/vxworks/CMakeLists.txt index 88ba8328c..dc92494eb 100644 --- a/product-mini/platforms/vxworks/CMakeLists.txt +++ b/product-mini/platforms/vxworks/CMakeLists.txt @@ -66,7 +66,7 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -add_executable (iwasm main.c ext_lib_export.c) +add_executable (iwasm main.c) install (TARGETS iwasm DESTINATION bin) diff --git a/product-mini/platforms/vxworks/ext_lib_export.c b/product-mini/platforms/vxworks/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/vxworks/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/product-mini/platforms/zephyr/simple/CMakeLists.txt b/product-mini/platforms/zephyr/simple/CMakeLists.txt index cafc7002f..c55de4a76 100644 --- a/product-mini/platforms/zephyr/simple/CMakeLists.txt +++ b/product-mini/platforms/zephyr/simple/CMakeLists.txt @@ -80,6 +80,5 @@ set (VM_LIB_SRCS target_sources(app PRIVATE ${VM_LIB_SRCS} - src/main.c - src/ext_lib_export.c) + src/main.c) diff --git a/product-mini/platforms/zephyr/simple/src/ext_lib_export.c b/product-mini/platforms/zephyr/simple/src/ext_lib_export.c deleted file mode 100644 index 8813f0dbf..000000000 --- a/product-mini/platforms/zephyr/simple/src/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/samples/gui/README.md b/samples/gui/README.md index 364dab8c0..09cdc18fb 100644 --- a/samples/gui/README.md +++ b/samples/gui/README.md @@ -112,3 +112,9 @@ First, connect PC and STM32 with UART. Then install to use host_tool.
- Install AOT version WASM application `wamrc --target=thumbv7 --target-abi=eabi --cpu=cortex-m7 -o ui_app.aot ui_app.wasm` `./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app.aot` + + + +The graphic user interface demo photo: + +![WAMR samples diagram](../../doc/pics/vgl_demo.png "WAMR samples diagram") \ No newline at end of file diff --git a/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt index c1aa7b3c7..c4ec6637b 100644 --- a/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt @@ -42,7 +42,6 @@ include_directories( set (SOURCES ${PROJECT_SRC_DIR}/main.c ${PROJECT_SRC_DIR}/iwasm_main.c - ${PROJECT_SRC_DIR}/../../ext_lib_export.c ${LV_DRIVERS_SOURCES} ) diff --git a/samples/gui/wasm-runtime-wgl/src/ext_lib_export.c b/samples/gui/wasm-runtime-wgl/src/ext_lib_export.c deleted file mode 100644 index 0058f9908..000000000 --- a/samples/gui/wasm-runtime-wgl/src/ext_lib_export.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "lib_export.h" -#include "sensor_native_api.h" -#include "connection_native_api.h" -#include "gui_native_api.h" - -static NativeSymbol extended_native_symbol_defs[] = { -#include "runtime_sensor.inl" -#include "connection.inl" -#include "wamr_gui.inl" -}; - -#include "ext_lib_export.h" diff --git a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt index ef9dc919c..2ff88b002 100644 --- a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt @@ -73,5 +73,4 @@ target_sources(app PRIVATE ${LVGL_DRV_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c ) diff --git a/samples/littlevgl/README.md b/samples/littlevgl/README.md index d7d574f55..bb41a27fb 100644 --- a/samples/littlevgl/README.md +++ b/samples/littlevgl/README.md @@ -4,7 +4,6 @@ This sample demonstrates that a graphic user interface application in WebAssembl In this sample, the whole LittlevGL source code is built into the WebAssembly code with the user application. The platform interfaces defined by LittlevGL is implemented in the runtime and exported to the application through the declarations from source "ext_lib_export.c" as below: - EXPORT_WASM_API(display_init), EXPORT_WASM_API(display_input_read), EXPORT_WASM_API(display_flush), EXPORT_WASM_API(display_fill), diff --git a/samples/littlevgl/build.sh b/samples/littlevgl/build.sh index bb9b198dc..dc51bdb3a 100755 --- a/samples/littlevgl/build.sh +++ b/samples/littlevgl/build.sh @@ -38,7 +38,7 @@ fi echo "##################### 0. build wamr-sdk littlevgl start#####################" cd ${WAMR_DIR}/wamr-sdk -./build_sdk.sh -n littlevgl -x ${PROJECT_DIR}/wamr_config_littlevgl.cmake -e ${LV_CFG_PATH} +./build_sdk.sh -n littlevgl -x ${PROJECT_DIR}/wamr_config_littlevgl.cmake -e ${LV_CFG_PATH} -c [ $? -eq 0 ] || exit $? echo "#####################build wamr-sdk littlevgl success" diff --git a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt index aa9193361..d79b1f7ae 100644 --- a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt @@ -27,7 +27,7 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/src) add_executable (vgl_wasm_runtime src/platform/${WAMR_BUILD_PLATFORM}/main.c src/platform/${WAMR_BUILD_PLATFORM}/iwasm_main.c - src/ext_lib_export.c src/platform/${WAMR_BUILD_PLATFORM}/display_indev.c + src/platform/${WAMR_BUILD_PLATFORM}/display_indev.c src/platform/${WAMR_BUILD_PLATFORM}/mouse.c) target_link_libraries (vgl_wasm_runtime vmlib -lm -ldl -lpthread -lSDL2) diff --git a/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h b/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h index 78daefe33..c87c3df44 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h +++ b/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h @@ -58,11 +58,11 @@ enum { extern void xpt2046_init(void); -extern bool touchscreen_read(lv_indev_data_t * data); +extern bool touchscreen_read(lv_indev_data_t *data); -extern bool mouse_read(lv_indev_data_t * data); +extern bool mouse_read(lv_indev_data_t *data); -extern void display_init(wasm_exec_env_t exec_env); +extern void display_init(void); extern void display_deinit(wasm_exec_env_t exec_env); @@ -70,22 +70,21 @@ extern int time_get_ms(wasm_exec_env_t exec_env); extern void display_flush(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - int32 color_p_offset); + lv_color_t *color); extern void display_fill(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - lv_color_t color_p); + lv_color_t *color); extern void display_map(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p); + const lv_color_t *color); -extern bool display_input_read(wasm_exec_env_t exec_env, - int32 data_offset); +extern bool display_input_read(wasm_exec_env_t exec_env, void *data); void display_vdb_write(wasm_exec_env_t exec_env, - int32 buf_offset, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, int32 color_p_offset, lv_opa_t opa); + void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t *color, lv_opa_t opa); #endif diff --git a/samples/littlevgl/vgl-wasm-runtime/src/ext_lib_export.c b/samples/littlevgl/vgl-wasm-runtime/src/ext_lib_export.c deleted file mode 100644 index 8262770b4..000000000 --- a/samples/littlevgl/vgl-wasm-runtime/src/ext_lib_export.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "lib_export.h" -#include "sensor_native_api.h" -#include "connection_native_api.h" -#include "display_indev.h" - -static NativeSymbol extended_native_symbol_defs[] = { -#include "runtime_sensor.inl" -#include "connection.inl" - EXPORT_WASM_API(display_init), - EXPORT_WASM_API(display_input_read), - EXPORT_WASM_API(display_flush), - EXPORT_WASM_API(display_fill), - EXPORT_WASM_API(display_vdb_write), - EXPORT_WASM_API(display_map), - EXPORT_WASM_API(time_get_ms) -}; - -#include "ext_lib_export.h" diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c index 52d57d506..956d55d0c 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c @@ -41,7 +41,7 @@ static volatile bool sdl_refr_qry = false; static volatile bool sdl_quit_qry = false; void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t * color) { /*Return if the area is out the screen*/ if (x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1 @@ -53,10 +53,10 @@ void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t w = x2 - x1 + 1; for (y = y1; y <= y2; y++) { - memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p, + memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color, w * sizeof(lv_color_t)); - color_p += w; + color += w; } sdl_refr_qry = true; @@ -72,7 +72,7 @@ void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, * @param color fill color */ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - lv_color_t color) + lv_color_t *color) { /*Return if the area is out the screen*/ if (x2 < 0) @@ -92,7 +92,7 @@ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x; int32_t y; - uint32_t color32 = color.full; //lv_color_to32(color); + uint32_t color32 = color->full; //lv_color_to32(color); for (x = act_x1; x <= act_x2; x++) { for (y = act_y1; y <= act_y2; y++) { @@ -109,10 +109,10 @@ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, * @param y1 top coordinate * @param x2 right coordinate * @param y2 bottom coordinate - * @param color_p an array of colors + * @param color an array of colors */ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t *color) { /*Return if the area is out the screen*/ if (x2 < 0) @@ -135,11 +135,11 @@ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, for (y = act_y1; y <= act_y2; y++) { for (x = act_x1; x <= act_x2; x++) { - tft_fb[y * MONITOR_HOR_RES + x] = color_p->full; //lv_color_to32(*color_p); - color_p++; + tft_fb[y * MONITOR_HOR_RES + x] = color->full; //lv_color_to32(*color); + color++; } - color_p += x2 - act_x2; + color += x2 - act_x2; } sdl_refr_qry = true; @@ -147,62 +147,64 @@ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, void -display_init(wasm_exec_env_t exec_env) +display_init(void) { } void display_flush(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - int32 color_p_offset) + lv_color_t *color) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) - return; - lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst, - color_p_offset); - monitor_flush(x1, y1, x2, y2, color_p); + if (!wasm_runtime_validate_native_addr(module_inst, + color, sizeof(lv_color_t))) + return; + + monitor_flush(x1, y1, x2, y2, color); } void display_fill(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - lv_color_t color_p) + lv_color_t *color) { - monitor_fill(x1, y1, x2, y2, color_p); + monitor_fill(x1, y1, x2, y2, color); } void display_map(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t *color) { - monitor_map(x1, y1, x2, y2, color_p); + monitor_map(x1, y1, x2, y2, color); } +typedef struct display_input_data { + lv_point_t point; + int32 user_data_offset; + uint8 state; +} display_input_data; + bool display_input_read(wasm_exec_env_t exec_env, - int32 data_p_offset) + void *input_data_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); + display_input_data *data_app = (display_input_data*)input_data_app; bool ret; - if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1)) + + if (!wasm_runtime_validate_native_addr(module_inst, + data_app, + sizeof(display_input_data))) return false; - struct { - lv_point_t point; - int32 user_data_offset; - uint8 state; - } *data_app; lv_indev_data_t data = {0}; ret = mouse_read(&data); - data_app = wasm_runtime_addr_app_to_native(module_inst, - data_p_offset); - data_app->point = data.point; data_app->user_data_offset = wasm_runtime_addr_native_to_app(module_inst, data.user_data); @@ -218,35 +220,17 @@ display_deinit(wasm_exec_env_t exec_env) void display_vdb_write(wasm_exec_env_t exec_env, - int32 buf_offset, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, int32 color_p_offset, lv_opa_t opa) + void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t *color, lv_opa_t opa) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) + unsigned char *buf_xy = (unsigned char*)buf + 4 * x + 4 * y * buf_w; + + if (!wasm_runtime_validate_native_addr(module_inst, + color, sizeof(lv_color_t))) return; - lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst, - color_p_offset); - void *buf = wasm_runtime_addr_app_to_native(module_inst, buf_offset); - - unsigned char *buf_xy = buf + 4 * x + 4 * y * buf_w; - lv_color_t * temp = (lv_color_t *) buf_xy; - *temp = *color; - /* - if (opa != LV_OPA_COVER) { - lv_color_t mix_color; - - mix_color.red = *buf_xy; - mix_color.green = *(buf_xy+1); - mix_color.blue = *(buf_xy+2); - color = lv_color_mix(color, mix_color, opa); - } - */ - /* - *buf_xy = color->red; - *(buf_xy + 1) = color->green; - *(buf_xy + 2) = color->blue; - */ + *(lv_color_t *)buf_xy = *color; } int monitor_sdl_refr_thread(void * param) diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c index 1081cd727..18ad0331a 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c @@ -32,6 +32,10 @@ #include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" +#include "sensor_native_api.h" +#include "connection_native_api.h" +#include "display_indev.h" + #define MAX 2048 #ifndef CONNECTION_UART @@ -389,7 +393,9 @@ static bool parse_args(int argc, char *argv[]) { "uart", required_argument, NULL, 'u' }, { "baudrate", required_argument, NULL, 'b' }, #endif +#if WASM_ENABLE_LIBC_WASI != 0 { "wasi_root", required_argument, NULL, 'w' }, +#endif { "help", required_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; @@ -421,12 +427,14 @@ static bool parse_args(int argc, char *argv[]) printf("uart baudrate: %s\n", optarg); break; #endif +#if WASM_ENABLE_LIBC_WASI != 0 case 'w': if (!wasm_set_wasi_root_dir(optarg)) { printf("Fail to set wasi root dir: %s\n", optarg); return false; } break; +#endif case 'h': showUsage(); return false; @@ -439,10 +447,22 @@ static bool parse_args(int argc, char *argv[]) return true; } +static NativeSymbol native_symbols[] = { + #include "runtime_sensor.inl" + #include "connection.inl" + EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), + EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)"), + EXPORT_WASM_API_WITH_SIG(display_fill, "(iiii*)"), + EXPORT_WASM_API_WITH_SIG(display_vdb_write, "(*iii*i)"), + EXPORT_WASM_API_WITH_SIG(display_map, "(iiii*)"), + EXPORT_WASM_API_WITH_SIG(time_get_ms, "()i") +}; + // Driver function int iwasm_main(int argc, char *argv[]) { korp_thread tid; + uint32 n_native_symbols; if (!parse_args(argc, argv)) return -1; @@ -457,6 +477,13 @@ int iwasm_main(int argc, char *argv[]) goto fail1; } + /* Register native functions */ + n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + if (!wasm_runtime_register_natives("env", + native_symbols, n_native_symbols)) { + goto fail1; + } + if (!init_connection_framework()) { vm_thread_sys_destroy(); goto fail1; diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c index d537db6d3..6701ceebb 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c @@ -15,10 +15,12 @@ #define MONITOR_ZOOM 1 #endif +extern int ili9340_init(); + static int lcd_initialized = 0; void -display_init(wasm_exec_env_t exec_env) +display_init(void) { if (lcd_initialized != 0) { return; @@ -32,23 +34,23 @@ display_init(wasm_exec_env_t exec_env) void display_flush(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - int32 color_p_offset) + lv_color_t *color) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) + struct display_buffer_descriptor desc; + + if (!wasm_runtime_validate_native_addr(module_inst, + color, sizeof(lv_color_t))) return; - lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst, - color_p_offset); u16_t w = x2 - x1 + 1; u16_t h = y2 - y1 + 1; - struct display_buffer_descriptor desc; desc.buf_size = 3 * w * h; desc.width = w; desc.pitch = w; desc.height = h; - display_write(NULL, x1, y1, &desc, (void *) color_p); + display_write(NULL, x1, y1, &desc, (void *)color); /*lv_flush_ready();*/ } @@ -56,27 +58,28 @@ display_flush(wasm_exec_env_t exec_env, void display_fill(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - lv_color_t color_p) + lv_color_t *color) { } void display_map(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t *color) { } bool -display_input_read(wasm_exec_env_t exec_env, int32 data_p_offset) +display_input_read(wasm_exec_env_t exec_env, void *data) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1)) - return false; - lv_indev_data_t * data = wasm_runtime_addr_app_to_native(module_inst, - data_p_offset); + lv_indev_data_t *lv_data = (lv_indev_data_t*)data; - return touchscreen_read(data); + if (!wasm_runtime_validate_native_addr(module_inst, + lv_data, sizeof(lv_indev_data_t))) + return false; + + return touchscreen_read(lv_data); } void @@ -86,28 +89,16 @@ display_deinit(wasm_exec_env_t exec_env) void display_vdb_write(wasm_exec_env_t exec_env, - int32 buf_offset, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, int32 color_p_offset, lv_opa_t opa) + void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t *color, lv_opa_t opa) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) + u8_t *buf_xy = (u8_t*)buf + 3 * x + 3 * y * buf_w; + + if (!wasm_runtime_validate_native_addr(module_inst, + color, sizeof(lv_color_t))) return; - lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst, - color_p_offset); - void *buf = wasm_runtime_addr_app_to_native(module_inst, buf_offset); - - u8_t *buf_xy = buf + 3 * x + 3 * y * buf_w; - /* - if (opa != LV_OPA_COVER) { - lv_color_t mix_color; - - mix_color.red = *buf_xy; - mix_color.green = *(buf_xy+1); - mix_color.blue = *(buf_xy+2); - color = lv_color_mix(color, mix_color, opa); - } - */ *buf_xy = color->red; *(buf_xy + 1) = color->green; *(buf_xy + 2) = color->blue; diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c index 6d4b00575..a9639dc20 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c @@ -15,6 +15,9 @@ #include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" +#include "sensor_native_api.h" +#include "connection_native_api.h" +#include "display_indev.h" #include #include @@ -30,7 +33,6 @@ int uart_char_cnt = 0; static void uart_irq_callback(struct device *dev) { unsigned char ch; - int size = 0; while (uart_poll_in(dev, &ch) == 0) { uart_char_cnt++; @@ -77,11 +79,21 @@ timer_ctx_t timer_ctx; static char global_heap_buf[370 * 1024] = { 0 }; -extern void display_init(void); +static NativeSymbol native_symbols[] = { + #include "runtime_sensor.inl" + #include "connection.inl" + EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), + EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)"), + EXPORT_WASM_API_WITH_SIG(display_fill, "(iiii*)"), + EXPORT_WASM_API_WITH_SIG(display_vdb_write, "(*iii*i)"), + EXPORT_WASM_API_WITH_SIG(display_map, "(iiii*)"), + EXPORT_WASM_API_WITH_SIG(time_get_ms, "()i") +}; int iwasm_main() { korp_thread tid, tm_tid; + uint32 n_native_symbols; host_init(); @@ -95,6 +107,13 @@ int iwasm_main() goto fail1; } + /* Register native functions */ + n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + if (!wasm_runtime_register_natives("env", + native_symbols, n_native_symbols)) { + goto fail1; + } + display_init(); // timer manager diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt index 9da334037..7458080d2 100644 --- a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt @@ -65,5 +65,4 @@ target_sources(app PRIVATE ${LVGL_DRV_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c ) diff --git a/samples/littlevgl/wasm-apps/src/display_indev.h b/samples/littlevgl/wasm-apps/src/display_indev.h index fe07d9ab6..0d55cea2c 100644 --- a/samples/littlevgl/wasm-apps/src/display_indev.h +++ b/samples/littlevgl/wasm-apps/src/display_indev.h @@ -10,13 +10,26 @@ #include "lvgl/lv_misc/lv_color.h" #include "lvgl/lv_hal/lv_hal_indev.h" + extern void display_init(void); -extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p); -extern bool display_input_read(lv_indev_data_t * data); + extern void display_deinit(void); -extern void display_vdb_write(void *buf, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, lv_color_t *color, lv_opa_t opa); + +extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + const lv_color_t * color); + +extern bool display_input_read(lv_indev_data_t *data); + +extern void display_vdb_write(void *buf, + lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t *color, lv_opa_t opa); + +void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + const lv_color_t *color); + +void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + const lv_color_t *color); + extern uint32_t time_get_ms(void); #endif diff --git a/samples/littlevgl/wasm-apps/src/main.c b/samples/littlevgl/wasm-apps/src/main.c index f13e76f8c..04da156da 100644 --- a/samples/littlevgl/wasm-apps/src/main.c +++ b/samples/littlevgl/wasm-apps/src/main.c @@ -119,27 +119,32 @@ void on_init() * Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library */ void display_flush_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t * color_p) { display_flush(x1, y1, x2, y2, color_p); lv_flush_ready(); } -void display_vdb_write_wrapper(uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, lv_color_t color, lv_opa_t opa) + +void display_vdb_write_wrapper(uint8_t *buf, + lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa) { display_vdb_write(buf, buf_w, x, y, &color, opa); } -extern void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - lv_color_t color_p); -extern void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p); + +void display_fill_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + lv_color_t color) +{ + display_fill(x1, y1, x2, y2, &color); +} + static void hal_init(void) { /* Add a display*/ lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); /*Basic initialization*/ disp_drv.disp_flush = display_flush_wrapper; /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/ - disp_drv.disp_fill = display_fill; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/ + disp_drv.disp_fill = display_fill_wrapper; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/ disp_drv.disp_map = display_map; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/ #if LV_VDB_SIZE != 0 disp_drv.vdb_wr = display_vdb_write_wrapper; diff --git a/samples/simple/CMakeLists.txt b/samples/simple/CMakeLists.txt index 3d3e45f84..85f1e00bc 100644 --- a/samples/simple/CMakeLists.txt +++ b/samples/simple/CMakeLists.txt @@ -27,7 +27,7 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/src) #Note: uncomment below line to use UART mode #add_definitions (-DCONNECTION_UART) -add_executable (simple src/main.c src/iwasm_main.c src/ext_lib_export.c) +add_executable (simple src/main.c src/iwasm_main.c) target_link_libraries (simple vmlib -lm -ldl -lpthread -lrt) diff --git a/samples/simple/src/ext_lib_export.c b/samples/simple/src/ext_lib_export.c deleted file mode 100644 index b3868bb7e..000000000 --- a/samples/simple/src/ext_lib_export.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "lib_export.h" -#include "sensor_native_api.h" -#include "timer_native_api.h" -#include "req_resp_native_api.h" -#include "connection_native_api.h" - -static NativeSymbol extended_native_symbol_defs[] = { -#include "runtime_sensor.inl" -#include "connection.inl" -}; - -#include "ext_lib_export.h" diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 78794b6b9..b3e0d80c6 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -121,7 +121,7 @@ add_library (vmlib add_library (aotclib ${IWASM_COMPL_SOURCE}) -add_executable (wamrc main.c ext_lib_export.c) +add_executable (wamrc main.c) target_link_libraries (wamrc aotclib vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) diff --git a/wamr-compiler/ext_lib_export.c b/wamr-compiler/ext_lib_export.c deleted file mode 100644 index 42bc64375..000000000 --- a/wamr-compiler/ext_lib_export.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = { }; - -#include "ext_lib_export.h" diff --git a/wamr-sdk/README.md b/wamr-sdk/README.md index a84be84f7..f9d143c7e 100644 --- a/wamr-sdk/README.md +++ b/wamr-sdk/README.md @@ -1,52 +1,126 @@ -# SDK for Wasm Micro Runtime -This folder contains some tools to generate sdk for wamr runtime and wasm applications, the script and cmake files here are called by `make`, don't use them manually. +# WebAssembly Micro Runtime SDK + + +**Note**: [WASI-SDK](https://github.com/CraneStation/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK. + + + +### SDK profile and configuration file + +A SDK profile presents a configuration of build parameters for the selection of CPU architecture, software platforms, execution mode, libc and application framework components. The profile configurations are saved in a cmake file that will be included by the WAMR SDK building tool `build_sdk.sh`. + +Here is the default configuration file [wamr-sdk/wamr_config_default.cmake](./wamr_config_default.cmake): -## Build the SDK -``` Bash -cd ${WAMR_ROOT}/wamr-sdk -make config ``` -Following the prompt to finish the settings for your customized runtime and app sdk, then you will get `out` folder under `${WAMR_ROOT}` - -The structure of the output folder is like bellow: +set (WAMR_BUILD_PLATFORM "linux") +set (WAMR_BUILD_TARGET X86_64) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE) ``` -out -|--app-sdk/ -| |--sysroot/ -| |--wamr_toolchain.cmake -| -|--runtime-sdk/ - |--include - |--lib - |--wamr_config.cmake + + + +Execute following command to build the WAMR SDK for a configuration profile: + +``` +cd wamr-sdk +./build_sdk.sh -n [profile name] -x [config file path] ``` -### app-sdk usage -The `app-sdk` is used to develop wasm applications, if your project are built with cmake, then the `wamr_toolchain.cmake` file is what you need to compile your project into wasm bytecode. -### runtime-sdk usage -The `runtime-sdk` is used to help you embed WAMR runtime into your product easier. There are two method you can use the SDK: +The output directory structure of a SDK package with profile name "simple": -1. Use the provided `runtime_lib.cmake` file: +``` +simple/ +├── app-sdk +│   ├── libc-builtin-sysroot +│   │   ├── include +│   │   └── share +│   └── wamr-app-framework +│   ├── include +│   │   ├── bi-inc +│   │   └── wa-inc +│   ├── lib +│   └── share +└── runtime-sdk + ├── include + │   └── bi-inc + └── lib +``` - You can include `${WAMR_ROOT}/cmake/runtime_lib.cmake` in your project's `CMakeLists.txt` file: - ``` cmake - include (${WAMR_ROOT}/cmake/runtime_lib.cmake) - add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) - # ...... - target_link_libraries (your_target vmlib -lm -ldl -lpthread) - ``` -2. Use the pre-built static library: - You can link the pre-built library: - ``` cmake - link_directories(${SDK_DIR}/runtime-sdk/lib) - include_directories(${SDK_DIR}/runtime-sdk/include) - # ...... - target_link_libraries (your_target vmlib -lm -ldl -lpthread) - ``` - This method can also be used when you don't use cmake +Like the WAMR samples, a project probably has its own pre-defined SDK configuration file. The project building script can call the `build_sdk.sh` by passing the configuration file name to the build_sdk.sh to generate its own WAMR SDK package. + + + +### Menu configuration for building SDK + +Menu configuration is supported for easy integration of runtime components and application libraries for the target architecture and platform. Run following command to start the menu config. + +``` +cd wamr-sdk +./build_sdk.sh -i -n [profile name] +``` + + The argument "-i" will make the command enter menu config mode as depicted below. + +wamr build menu configuration + +After the menu configuration is finished, the profile config file is saved and the building process is automatically started. When the building gets successful, the SDK package is generated under folder $wamr-sdk/out/{profile}, and the header files of configured components were copied into the SDK package. + + + +### Build WASM applications with APP-SDK + +The folder “**app-sdk**” under the profile output directory contains all the header files and WASM library for developing the WASM application. For C/C++ based WASM applications, the developers can use conventional cross-compilation procedure to build the WASM application. According to the profile selection of libc, following cmake toolchain files under folder [wamr-sdk/app](./app) are available for cross compiling WASM application: + +- ` wamr_toolchain.cmake` +- `wasi_toolchain.cmake` + + + +Refer to [build WASM applications](./doc/build_wasm_app.md) for the details. + + + +### Use Runtime SDK to build native application + +The output folder "**runtime-sdk**" contains all the header files and library files for integration with project native code. + +You can link the pre-built library: +``` cmake +link_directories(${SDK_DIR}/runtime-sdk/lib) +include_directories(${SDK_DIR}/runtime-sdk/include) +# ...... +target_link_libraries (your_target vmlib -lm -ldl -lpthread) +``` + +This method can also be used when you don't use cmake You can refer to this sample: [CMakeLists.txt](../samples/simple/CMakeLists.txt). -> NOTE: If you are familiar with how to configure WAMR by cmake and don't want to build the SDK, you can set the related settings on the top of your `CMakeLists.txt`, then the `runtime_lib.cmake` will not load settings from the SDK. \ No newline at end of file +> NOTE: If you are familiar with how to configure WAMR by cmake and don't want to build the SDK, you can set the related settings on the top of your `CMakeLists.txt`, then the `runtime_lib.cmake` will not load settings from the SDK. + + + +### Integrate WAMR without pre-built WAMR library + +Use the provided `runtime_lib.cmake` file: + +You can include `${WAMR_ROOT}/cmake/runtime_lib.cmake` in your project's `CMakeLists.txt` file: + +``` cmake +include (${WAMR_ROOT}/cmake/runtime_lib.cmake) +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +# ...... +target_link_libraries (your_target vmlib -lm -ldl -lpthread) +``` + +You can refer to to product-mini building for Linux: [`product-mini/platforms/linux/CMakeLists.txt`](../product-mini/platforms/linux/CMakeLists.txt). + +>