Merge pull request #2 from intel/master

Sync with remote
This commit is contained in:
Weining 2019-09-10 15:06:07 +08:00 committed by GitHub
commit f610353b78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
170 changed files with 8711 additions and 1302 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.vscode
**/*build/

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
# Currently supports clang-8 compiler
# Using the "test.c" app from the README.md:
# clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main,--no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c
# Pay attention to spacing above! ^
# iwasm test.wasm
FROM ubuntu:latest
RUN apt-get update && \
apt-get -y upgrade && \
apt-get install -y build-essential clang-8 cmake g++-multilib git lib32gcc-5-dev llvm-8 lld-8 nano
WORKDIR /root
RUN git clone https://github.com/intel/wasm-micro-runtime
RUN cd wasm-micro-runtime/core/iwasm/products/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

682
README.md
View File

@ -1,26 +1,17 @@
WebAssembly Micro Runtime
=========================
WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime designed for a small footprint. It includes:
- A WebAssembly (WASM) VM core
WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with small footprint. It includes a few parts as below:
- A WebAssembly VM core (namely iwasm)
- The supporting API's for the WASM applications
- A mechanism for dynamic management of the WASM application
Why should you use a WASM runtime out of your browser? There are a few points where this might be meaningful:
1. WASM is already an LLVM official backend target. That means WASM can run any programming languages which can be compiled to LLVM IR. It is a huge advantage compared to language bound runtimes like JS or Lua.
2. WASM is an open standard and it is fast becoming supported by the whole web ecosystem.
3. WASM is designed to be very friendly for compiling to native binaries and gaining the native speed.
4. It can potentially change the development practices. Imagine we can do both the WASM application development and validation in a browser, then just download the WASM binary code onto the target device.
5. WASM can work without garbage collection. It is designed to support execution determinics for the time sensitive requirement.
6. Maintain the safety goals WASM has of providing a sandboxed execution environment for untrusted code. In addition, because WASM is a compilation target, this implies the benefit of being able to target both an execution and security profile that is consistent across popular high-level programming languages.
Current Features of WAMR
=========================
- WASM interpreter (AOT is planned)
- Provides support for a subset of Libc.
- Supports for a subset of Libc.
- Supports "SIDE_MODULE=1" EMCC compilation option
- Provides API's for embedding runtime into production software
- Provides embedding C API
- Provides a mechanism for exporting native API's to WASM applications
- Supports the programming of firmware apps in a large range of languages (C/C++/Java/Rust/Go/TypeScript etc.)
- App sandbox execution environment on embedded OS
@ -29,631 +20,104 @@ Current Features of WAMR
- Supports micro-service and pub-sub event inter-app communication models
- Easy to extend to support remote FW application management from host or cloud
Architecture
=========================
The application manager component handles the packets that the platform receives from external sources through any communication buses such as a socket, serial port or SPI. A packet type can be either a request, a response or an event. The application manager will serve the requests with URI "/applet" and call the runtime glue layer interfaces for installing/uninstalling the application. For other URI's, it will filter the resource registration table and route the request to the internal queue of the responsible application.
Application framework architecture
===================================
- The WebAssembly runtime provides the execution environment for WASM applications.
By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains.
- The messaging layer can support the API for WASM applications to communicate with each other and also the host environment.
The WAMR has offered a comprehensive application framework for device and IoT usages. The framework solves many common requirements for building a real project:
- Modular design for more language runtimes support
- Inter application communication
- Remote application management
- WASM APP programming model and API extension mechanism
- When ahead of time (AOT) compilation is enabled (TODO), the WASM application could be either WASM or a compiled native binary.
<img src="./doc/pics/wamr-arch.JPG" width="80%">
<img src="./doc/pics/architecture.PNG" width="80%" height="80%">
Build WAMR Core and run WASM applications
================================================
Build WAMR Core
=========================
Please follow the instructions below to build the WAMR core on different platforms.
WAMR VM core (iwasm) can support building on different platforms:
- Linux
- Zephyr
- Mac
- VxWorks
- AliOS-Things
- Docker
- Intel Software Guard Extention (SGX)
Linux
-------------------------
First of all please install library dependencies of lib gcc.
Use installation commands below for Ubuntu Linux:
``` Bash
sudo apt install lib32gcc-5-dev g++-multilib
```
Or in Fedora:
``` Bash
sudo dnf install glibc-devel.i686
```
After building the iwasm, we can compile some basic WASM applications and run it from the WAMR core. As the WAMR core doesn't include the extended application library, your WASM applications can only use the [WAMR built-in APIs](./doc/wamr_api.md).
After installing dependencies, build the source code:
``` Bash
cd core/iwasm/products/linux/
mkdir build
cd build
cmake ..
make
```
VxWorks
-------------------------
VxWorks 7 SR0620 release is validated.
See the [doc/building.md](./doc/building.md) for the detailed instructions.
First you need to build a VSB. Make sure *UTILS_UNIX* layer is added in the VSB.
After the VSB is built, export the VxWorks toolchain path by:
```
export <vsb_dir_path>/host/vx-compiler/bin:$PATH
```
Now switch to iwasm source tree to build the source code:
```
cd core/iwasm/products/vxworks/
mkdir build
cd build
cmake ..
make
```
Create a VIP based on the VSB. Make sure the following components are added:
* INCLUDE_POSIX_PTHREADS
* INCLUDE_POSIX_PTHREAD_SCHEDULER
* INCLUDE_SHARED_DATA
* INCLUDE_SHL
Copy the generated iwasm executable, the test WASM binary as well as the needed
shared libraries (libc.so.1, libllvm.so.1 or libgnu.so.1 depending on the VSB,
libunix.so.1) to a supported file system (eg: romfs).
Embed WAMR
===========
Zephyr
-------------------------
You need to download the Zephyr source code first and embed WAMR into it.
``` Bash
git clone https://github.com/zephyrproject-rtos/zephyr.git
cd zephyr/samples/
cp -a <iwasm_dir>/products/zephyr/simple .
cd simple
ln -s <iwam_dir> iwasm
ln -s <shared_lib_dir> shared-lib
mkdir build && cd build
source ../../../zephyr-env.sh
cmake -GNinja -DBOARD=qemu_x86 ..
ninja
```
AliOS-Things
-------------------------
1. a developerkit board id needed for testing
2. download the AliOS-Things code
``` Bash
git clone https://github.com/alibaba/AliOS-Things.git
```
3. copy <iwasm_root_dir>/products/alios-things directory to AliOS-Things/middleware, and rename it as iwasm
``` Bash
cp -a <iwasm_root_dir>/products/alios-things middleware/iwasm
```
4. create a link to <iwasm_root_dir> in middleware/iwasm/ and rename it to iwasm
``` Bash
ln -s <iwasm_root_dir> middleware/iwasm/iwasm
```
5. create a link to <shared-lib_root_dir> in middleware/iwasm/ and rename it to shared-lib
``` Bash
ln -s <shared-lib_root_dir> middle/iwasm/shared-lib
```
6. modify file app/example/helloworld/helloworld.c, patch as:
``` C
#include <stdbool.h>
#include <aos/kernel.h>
extern bool iwasm_init();
int application_start(int argc, char *argv[])
{
int count = 0;
iwasm_init();
...
}
```
7. modify file app/example/helloworld/aos.mk
``` C
$(NAME)_COMPONENTS := osal_aos iwasm
```
8. build source code
``` Bash
aos make helloworld@developerkit -c config
aos make
```
9. download the binary to developerkit board, check the output from serial port
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product.
Build WASM app
=========================
You can write a simple ```test.c``` as the first sample.
WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call.
```C
#include <stdio.h>
#include <stdlib.h>
See the [doc/embed_wamr.md](./doc/embed_wamr.md) for the details.
int main(int argc, char **argv)
{
char *buf;
WAMR application programming library
===================================
printf("Hello world!\n");
WAMR defined event driven programming model:
- Single thread per WASM app instance
- App must implement system callbacks: on_init, on_destrory
buf = malloc(1024);
if (!buf) {
printf("malloc buf failed\n");
return -1;
}
printf("buf ptr: %p\n", buf);
In general there are a few API classes for the WASM application programming:
- WAMR Built-in API: WAMR core provides a minimal libc API set for WASM APP
- WAMR application libraries:
- Timer
- Micro service (Request/Response)
- Pub/Sub
- Sensor
- Connection and data transmission
- 2D graphic UI (based on littlevgl)
- User extended native API: extend the native API to the WASM applications
- 3rd party libraries: Programmers can download any 3rd party C/C++ source code and build it together with the WASM APP code
sprintf(buf, "%s", "1234\n");
printf("buf: %s", buf);
See the [doc/wamr_api.md](./doc/wamr_api.md) for the details.
free(buf);
return 0;
}
```
There are two methods to build a WASM binary. One is using Emscripten tool, another is using clang compiler.
## Use Emscripten tool
A method to build a WASM binary is to use Emscripten tool ```emcc```.
Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below:
```
git clone https://github.com/emscripten-core/emsdk.git
emsdk install latest
emsdk activate latest
```
source ```./emsdk_env.sh```.
The Emscripten website provides other installation methods beyond Linux.
Use the emcc command below to build the WASM C source code into the WASM binary.
``` Bash
emcc -g -O3 *.c -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
-s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 -o test.wasm
```
You will get ```test.wasm``` which is the WASM app binary.
## Use clang compiler
Another method to build a WASM binary is to use clang compiler```clang-8```.
Add source to your system source list from llvm website, for ubuntu16.04, add following lines to /etc/apt/sources.list:
```Bash
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main # 7
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main # 8
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
```
Download and install clang-8 tool-chain using following commands:
```Bash
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install llvm-8 lld-8 clang-8
```
Create a soft link under /usr/bin:
```Bash
cd /usr/bin
sudo ln -s wasm-ld-8 wasm-ld
```
Use the clang-8 command below to build the WASM C source code into the WASM binary.
```Bash
clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main,
--no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c
```
You will get ```test.wasm``` which is the WASM app binary.
Run WASM app
========================
Assume you are using Linux, the command to run the test.wasm is:
``` Bash
cd iwasm/products/linux/build
./iwasm test.wasm
```
You will get the following output:
```
Hello world!
buf ptr: 0x400002b0
buf: 1234
```
If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute:
```
ninja run
```
Embed WAMR into software production
=====================================
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. To use it in the embedded environment you should embed WAMR into your own software product. WASM provides a set of API's for embedded code to load the WASM module, instantiate the module and invoke a WASM function from a native call.
<img src="./doc/pics/embed.PNG" width="60%" height="60%">
A typical WAMR API usage is shown below (some return value checks are ignored):
``` C
static char global_heap_buf[512 * 1024];
char *buffer;
wasm_module_t module;
wasm_module_inst_t inst;
wasm_function_inst_t func;
wasm_exec_env_t env;
uint32 argv[2];
bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf));
wasm_runtime_init();
buffer = read_wasm_binary_to_buffer(…);
module = wasm_runtime_load(buffer, size, err, err_size);
inst = wasm_runtime_instantiate(module, 0, 0, err, err_size);
func = wasm_runtime_lookup_function(inst, "fib", "(i32)i32");
env = wasm_runtime_create_exec_env(stack_size);
argv[0] = 8;
if (!wasm_runtime_call_wasm(inst, env, func, 1, argv_buf) ) {
wasm_runtime_clear_exception(inst);
}
/* the return value is stored in argv[0] */
printf("fib function return: %d\n", argv[0]);
wasm_runtime_destory_exec_env(env);
wasm_runtime_deinstantiate(inst);
wasm_runtime_unload(module);
wasm_runtime_destroy();
bh_memory_destroy();
```
WASM application library
========================
In general, there are 3 classes of API's important for the WASM application:
- Built-in API's: WAMR provides a minimal API set for developers.
- 3rd party API's: Programmer can download and include any 3rd party C source code and add it into their own WASM app source tree.
- Platform native API's: WAMR provides a mechanism to export a native API to the WASM application.
Built-in application library
---------------
Built-in API's include Libc API's, Base library and Extension library reference.
**Libc API's**<br/>
This is a minimal set of Libc API's for memory allocation, string manipulation and printing. The header file is located at ```lib/app-libs/libc/lib_base.h```. The current supported API set is listed here:
``` C
void *malloc(size_t size);
void *calloc(size_t n, size_t size);
void free(void *ptr);
int memcmp(const void *s1, const void *s2, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
int putchar(int c);
int snprintf(char *str, size_t size, const char *format, ...);
int sprintf(char *str, const char *format, ...);
char *strchr(const char *s, int c);
int strcmp(const char *s1, const char *s2);
char *strcpy(char *dest, const char *src);
size_t strlen(const char *s);
int strncmp(const char * str1, const char * str2, size_t n);
char *strncpy(char *dest, const char *src, unsigned long n);
```
**Base library**<br/>
Basic support for communication, timers, etc is available. You can refer to the header file ```lib/app-libs/base/wasm_app.h``` which contains the definitions for request and response API's, event pub/sub API's and timer API's. Please note that these API's require the native implementations.
The API set is listed below:
``` C
typedef void(*request_handler_f)(request_t *) ;
typedef void(*response_handler_f)(response_t *, void *) ;
// Request API's
bool api_register_resource_handler(const char *url, request_handler_f);
void api_send_request(request_t * request, response_handler_f response_handler, void * user_data);
void api_response_send(response_t *response);
// Event API's
bool api_publish_event(const char *url, int fmt, void *payload, int payload_len);
bool api_subscribe_event(const char * url, request_handler_f handler);
struct user_timer;
typedef struct user_timer * user_timer_t;
// Timer API's
user_timer_t api_timer_create(int interval, bool is_period, bool auto_start, void(*on_user_timer_update)(user_timer_t
));
void api_timer_cancel(user_timer_t timer);
void api_timer_restart(user_timer_t timer, int interval);
```
**Library extension reference**<br/>
Currently we provide several kinds of extension library for reference including sensor, connection and GUI.
Sensor API: In the header file ```lib/app-libs/extension/sensor/sensor.h```, the API set is defined as below:
``` C
sensor_t sensor_open(const char* name, int index,
void(*on_sensor_event)(sensor_t, attr_container_t *, void *),
void *user_data);
bool sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay);
bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg);
bool sensor_close(sensor_t sensor);
```
Connection API: In the header file `lib/app-libs/extension/connection/connection.h.`, the API set is defined as below:
``` C
/* Connection event type */
typedef enum {
/* Data is received */
CONN_EVENT_TYPE_DATA = 1,
/* Connection is disconnected */
CONN_EVENT_TYPE_DISCONNECT
} conn_event_type_t;
typedef void (*on_connection_event_f)(connection_t *conn,
conn_event_type_t type,
const char *data,
uint32 len,
void *user_data);
connection_t *api_open_connection(const char *name,
attr_container_t *args,
on_connection_event_f on_event,
void *user_data);
void api_close_connection(connection_t *conn);
int api_send_on_connection(connection_t *conn, const char *data, uint32 len);
bool api_config_connection(connection_t *conn, attr_container_t *cfg);
```
GUI API: The API's is list in header file ```lib/app-libs/extension/gui/wgl.h``` which is implemented based open soure 2D graphic library [LittlevGL](https://docs.littlevgl.com/en/html/index.html). Currently supported widgets include button, label, list and check box and more wigdet would be provided in future.
The mechanism of exporting native API to WASM application
=======================================================
The basic working flow for WASM application calling into the native API is shown in the following diagram:
<img src="./doc/pics/extend_library.PNG" width="60%" height="60%">
WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library.
``` C
static NativeSymbol extended_native_symbol_defs[] = {
EXPORT_WASM_API(wasm_register_resource),
EXPORT_WASM_API(wasm_response_send),
EXPORT_WASM_API(wasm_post_request),
EXPORT_WASM_API(wasm_sub_event),
EXPORT_WASM_API(wasm_create_timer),
EXPORT_WASM_API(wasm_timer_set_interval),
EXPORT_WASM_API(wasm_timer_cancel),
EXPORT_WASM_API(wasm_timer_restart)
};
```
![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must:
- Only use 32 bits number for parameters
- Should not pass data to the structure pointer (do data serialization instead)
- Should do the pointer address conversion in the native API
- Should not pass function pointer as callback
Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world.
<img src="./doc/pics/safe.PNG" width="100%" height="100%">
Steps for exporting native API
==========================
WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps:
**Step 1. Create a header file**<br/>
Declare the API's for your WASM application source project to include.
**Step 2. Create a source file**<br/>
Export the platform API's, for example in ``` products/linux/ext_lib_export.c ```
``` C
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] =
{
};
#include "ext_lib_export.h"
```
**Step 3. Register new API's**<br/>
Use the macro `EXPORT_WASM_API` and `EXPORT_WASM_API2` to add exported API's into the array of ```extended_native_symbol_defs```.
The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function export:
``` c
#define EXPORT_WASM_API(symbol) {#symbol, symbol}
```
Below code example shows how to extend the library to support `customized()`:
```
//lib_export_impl.c
void customized()
{
// your code
}
// lib_export_dec.h
#ifndef _LIB_EXPORT_DEC_H_
#define _LIB_EXPORT_DEC_H_
#ifdef __cplusplus
extern "C" {
#endif
void customized();
#ifdef __cplusplus
}
#endif
#endif
// ext_lib_export.c
#include "lib_export.h"
#include "lib_export_dec.h"
static NativeSymbol extended_native_symbol_defs[] =
{
EXPORT_WASM_API(customized)
};
#include "ext_lib_export.h"
```
Use extended library
------------------------
In the application source project, it will include the WAMR built-in API's header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this:
``` C
#include <stdio.h>
#include "lib_export_dec.h" // provided by the platform vendor
int main(int argc, char **argv)
{
int I;
char *buf = “abcd”;
customized(); // customized API provided by the platform vendor
return i;
}
```
Communication programming models
=========================
WAMR supports two typical communication programming models, the microservice model and the pub/sub model.
Microservice model
-------------------------
The microservice model is also known as request and response model. One WASM application acts as the server which provides a specific service. Other WASM applications or host/cloud applications request that service and get the response.
<img src="./doc/pics/request.PNG" width="60%" height="60%">
Below is the reference implementation of the server application. It provides room temperature measurement service.
``` C
void on_init()
{
api_register_resource_handler("/room_temp", room_temp_handler);
}
void on_destroy()
{
}
void room_temp_handler(request_t *request)
{
response_t response[1];
attr_container_t *payload;
payload = attr_container_create("room_temp payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "temp unit", "centigrade");
attr_container_set_int(&payload, "value", 26);
make_response_for_request(request, response);
set_response(response,
CONTENT_2_05,
FMT_ATTR_CONTAINER,
payload,
attr_container_get_serialize_length(payload));
api_response_send(response);
attr_container_destroy(payload);
}
```
Pub/sub model
-------------------------
One WASM application acts as the event publisher. It publishes events to notify WASM applications or host/cloud applications which subscribe to the events.
<img src="./doc/pics/sub.PNG" width="60%" height="60%">
Below is the reference implementation of the pub application. It utilizes a timer to repeatedly publish an overheat alert event to the subscriber applications. Then the subscriber applications receive the events immediately.
``` C
/* Timer callback */
void timer_update(user_timer_t timer
{
attr_container_t *event;
event = attr_container_create("event");
attr_container_set_string(&event,
"warning",
"temperature is over high");
api_publish_event("alert/overheat",
FMT_ATTR_CONTAINER,
event,
attr_container_get_serialize_length(event));
attr_container_destroy(event);
}
void on_init()
{
user_timer_t timer;
timer = api_timer_create(1000, true, true, timer_update);
}
void on_destroy()
{
}
```
Below is the reference implementation of the sub application.
``` C
void overheat_handler(request_t *event)
{
printf("Event: %s\n", event->url);
if (event->payload != NULL && event->fmt == FMT_ATTR_CONTAINER)
attr_container_dump((attr_container_t *) event->payload);
}
void on_init(
{
api_subscribe_event ("alert/overheat", overheat_handler);
}
void on_destroy()
{
}
```
**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for deail usage.
Samples and demos
=========================
The simple sample
--------
Please refer to the ```samples/simple``` folder for samples of WASM application life cyle management and programming models.
=================
2D graphic user interface with LittlevGL
------------------------------------------------
We have 2 samples for 2D graphic user interface.
One of them demonstrates that a graphic user interface application in WebAssembly integrates the LittlevGL, an open-source embedded 2d graphic library. The sample source code is under ```samples/littlevgl```
In this sample, the LittlevGL source code is built into the WebAssembly code with the user application source files. 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),
EXPORT_WASM_API(display_vdb_write),
EXPORT_WASM_API(display_map),
EXPORT_WASM_API(time_get_ms), };
The runtime component supports building target for Linux and AliOS-Things, Zephyr/STM Nucleo board respectively. The beauty of this sample is the WebAssembly application can have identical display and behavior when running from both runtime environments. That implies we can do the majority of application validation from the desktop environment then load it to the target device as long as two runtime distributions support the same set of the application interface.
The WAMR samples are located in folder [./samples](./samples). A sample usually contains the WAMR runtime build, WASM applications and test tools. The WARM provides following samples:
- [Simple](./samples/simple/README.md): The runtime is integrated with most of the WAMR APP libaries and multiple WASM applications are provided for using different WASM API set.
- [littlevgl](./samples/littlevgl/README.md): Demostrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application.
- [gui](./samples/gui/README.md): Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API.
- [IoT-APP-Store-Demo](./test-tools/IoT-APP-Store-Demo/README.md): A web site for demostrating a WASM APP store usage where we can remotely install and uninstall WASM application on remote devices.
Below pictures show the WASM application is running on an STM board with an LCD touch panel. When users click the blue button, the WASM application increases the counter, and the latest counter value is displayed on the top banner of the touch panel.
The graphic user interface demo photo:
<img src="./doc/pics/vgl.PNG" width="60%" height="60%">
<img src="./doc/pics/vgl2.PNG" width="60%" height="60%">
![WAMR samples diagram](./doc/pics/vgl_demo.png "WAMR samples diagram")
Releases and acknowledgments
============================
WAMR is a community efforts. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community.
See the [major features releasing history and contributor names](./doc/release_ack.md)
Roadmap
=======
See the [roadmap](./doc/roadmap.md) to understand what major features are planed or under development.
Please submit issues for any new feature request, or your plan for contributing new features.
The sample also provides the native Linux version of application without the runtime under folder "vgl-native-ui-app". It can help to check differences between the implementations in native and WebAssembly.
<img src="./doc/pics/vgl_linux.PNG">
The other sample demonstrates that a graphic user interface application in WebAssembly programming with WAMR graphic library(WGL), which is implemented based on LittlevGL, an open-source embedded 2d graphic library. The sample source code is under ```samples/gui```
Unlike `sample/littlevgl/val-wasm-runtime`, in this sample, the LittlevGL source code is built into the WAMR runtime and exported to Webassembly applicaton but not directly built into Webassembly application. And WGL provides a group of WebAssembly wrapper API's for user to write graphic application. These API's are listed in: `<wamr_root>/core/iwasm/lib/app-libs/extension/gui/wgl.h`. Currently only a few API's are provided and there will be more.
Submit issues and contact the maintainers

View File

@ -176,7 +176,8 @@ void am_publish_event(request_t * event)
if (c->subscriber_id == ID_HOST) {
send_request_to_host(event);
} else {
module_request_handler(event, (void *)c->subscriber_id);
module_request_handler
(event, (void *)(uintptr_t)c->subscriber_id);
}
c = c->next;
}

View File

@ -224,8 +224,8 @@ static void app_instance_queue_callback(void *queue_msg)
app_manager_printf("Cannot find function _on_timer_callback\n");
break;
}
unsigned int timer_id = (unsigned int) bh_message_payload(
queue_msg);
unsigned int timer_id = (unsigned int)(uintptr_t)
bh_message_payload(queue_msg);
argv[0] = timer_id;
if (!wasm_runtime_call_wasm(inst, NULL, func_onTimer, 1, argv)) {
app_manager_printf("Got exception running wasm code: %s\n",
@ -642,7 +642,8 @@ static bool wasm_app_module_uninstall(request_t *msg)
static bool wasm_app_module_handle_host_url(void *queue_msg)
{
//todo: implement in future
app_manager_printf("App handles host url address %d\n", (int) queue_msg);
app_manager_printf("App handles host url address %d\n",
(int)(uintptr_t)queue_msg);
return false;
}

View File

@ -33,7 +33,7 @@ static app_res_register_t * g_resources = NULL;
void module_request_handler(request_t *request, void *user_data)
{
unsigned int mod_id = (unsigned int) user_data;
unsigned int mod_id = (unsigned int)(uintptr_t)user_data;
bh_message_t msg;
module_data *m_data;
request_t *req;
@ -99,7 +99,7 @@ void targeted_app_request_handler(request_t *request, void *unused)
goto end;
}
module_request_handler(request, (void *)m_data->id);
module_request_handler(request, (void *)(uintptr_t)m_data->id);
end: request->url = url;
}
@ -138,7 +138,7 @@ void * am_dispatch_request(request_t *request)
while (r) {
if (check_url_start(request->url, strlen(request->url), r->url) > 0) {
r->request_handler(request, (void *)r->register_id);
r->request_handler(request, (void *)(uintptr_t)r->register_id);
return r;
}
r = r->next;

View File

@ -18,6 +18,8 @@
#include "request.h"
#include "shared_utils.h"
#include "wasm_app.h"
#include "req_resp_api.h"
#include "timer_api.h"
#define TRANSACTION_TIMEOUT_MS 5000
@ -138,15 +140,15 @@ static bool register_url_handler(const char *url,
// tell app mgr to route this url to me
if (reg_type == Reg_Request)
wasm_register_resource((int32)url);
wasm_register_resource(url);
else
wasm_sub_event((int32)url);
wasm_sub_event(url);
return true;
}
bool api_register_resource_handler(const char *url,
request_handler_f request_handler)
request_handler_f request_handler)
{
return register_url_handler(url, request_handler, Reg_Request);
}
@ -242,7 +244,7 @@ void api_send_request(request_t * request, response_handler_f response_handler,
}
}
wasm_post_request((int32)buffer, size);
wasm_post_request(buffer, size);
free_req_resp_packet(buffer);
}
@ -329,7 +331,7 @@ void api_response_send(response_t *response)
if (buffer == NULL)
return;
wasm_response_send((int32)buffer, size);
wasm_response_send(buffer, size);
free_req_resp_packet(buffer);
}
@ -343,7 +345,7 @@ bool api_publish_event(const char *url, int fmt, void *payload, int payload_len)
char * buffer = pack_request(request, &size);
if (buffer == NULL)
return false;
wasm_post_request((int32)buffer, size);
wasm_post_request(buffer, size);
free_req_resp_packet(buffer);

View File

@ -17,7 +17,6 @@
#ifndef _AEE_REQUEST_H_
#define _AEE_REQUEST_H_
#include "native_interface.h"
#include "shared_utils.h"
#ifdef __cplusplus

View File

@ -14,12 +14,12 @@
* limitations under the License.
*/
#include "timer_wasm_app.h"
#include "native_interface.h"
#include <stdlib.h>
#include <string.h>
#include "timer_wasm_app.h"
#include "timer_api.h"
#if 1
#include <stdio.h>
#else

View File

@ -32,7 +32,6 @@
#ifndef _LIB_AEE_H_
#define _LIB_AEE_H_
#include "native_interface.h"
#include "shared_utils.h"
#include "attr_container.h"
#include "request.h"

View File

@ -15,7 +15,7 @@
*/
#include "connection.h"
#include "native_interface.h"
#include "connection_api.h"
/* Raw connection structure */
typedef struct _connection {
@ -44,7 +44,7 @@ connection_t *api_open_connection(const char *name,
char *args_buffer = (char *)args;
uint32 handle, args_len = attr_container_get_serialize_length(args);
handle = wasm_open_connection((int32)name, (int32)args_buffer, args_len);
handle = wasm_open_connection(name, args_buffer, args_len);
if (handle == -1)
return NULL;
@ -91,7 +91,7 @@ void api_close_connection(connection_t *c)
int api_send_on_connection(connection_t *conn, const char *data, uint32 len)
{
return wasm_send_on_connection(conn->handle, (int32)data, len);
return wasm_send_on_connection(conn->handle, data, len);
}
bool api_config_connection(connection_t *conn, attr_container_t *cfg)
@ -99,7 +99,7 @@ bool api_config_connection(connection_t *conn, attr_container_t *cfg)
char *cfg_buffer = (char *)cfg;
uint32 cfg_len = attr_container_get_serialize_length(cfg);
return wasm_config_connection(conn->handle, (int32)cfg_buffer, cfg_len);
return wasm_config_connection(conn->handle, cfg_buffer, cfg_len);
}
void on_connection_data(uint32 handle, char *buffer, uint32 len)

View File

@ -15,11 +15,11 @@
*/
#include "wgl.h"
#include "native_interface.h"
#include "bh_platform.h"
#include "gui_api.h"
#define ARGC sizeof(argv)/sizeof(uint32)
#define CALL_BTN_NATIVE_FUNC(id) wasm_btn_native_call(id, (int32)argv, ARGC)
#define CALL_BTN_NATIVE_FUNC(id) wasm_btn_native_call(id, argv, ARGC)
wgl_obj_t wgl_btn_create(wgl_obj_t par, wgl_obj_t copy)
{

View File

@ -15,12 +15,12 @@
*/
#include "wgl.h"
#include "native_interface.h"
#include "gui_api.h"
#include <string.h>
#define ARGC sizeof(argv)/sizeof(uint32)
#define CALL_CB_NATIVE_FUNC(id) wasm_cb_native_call(id, (uint32)argv, ARGC)
#define CALL_CB_NATIVE_FUNC(id) wasm_cb_native_call(id, argv, ARGC)
wgl_obj_t wgl_cb_create(wgl_obj_t par, const wgl_obj_t copy)
{

View File

@ -16,12 +16,12 @@
#include "wgl.h"
#include "native_interface.h"
#include "gui_api.h"
#include <string.h>
#define ARGC sizeof(argv)/sizeof(uint32)
#define CALL_LABEL_NATIVE_FUNC(id) wasm_label_native_call(id, (uint32)argv, ARGC)
#define CALL_LABEL_NATIVE_FUNC(id) wasm_label_native_call(id, argv, ARGC)
wgl_obj_t wgl_label_create(wgl_obj_t par, wgl_obj_t copy)
{

View File

@ -15,12 +15,12 @@
*/
#include "wgl.h"
#include "native_interface.h"
#include "gui_api.h"
#include <string.h>
#define ARGC sizeof(argv)/sizeof(uint32)
#define CALL_LIST_NATIVE_FUNC(id) wasm_list_native_call(id, (int32)argv, ARGC)
#define CALL_LIST_NATIVE_FUNC(id) wasm_list_native_call(id, argv, ARGC)
wgl_obj_t wgl_list_create(wgl_obj_t par, const wgl_obj_t copy)

View File

@ -15,12 +15,12 @@
*/
#include "wgl.h"
#include "native_interface.h"
#include "gui_api.h"
#include <stdlib.h>
#include <string.h>
#define ARGC sizeof(argv)/sizeof(uint32)
#define CALL_OBJ_NATIVE_FUNC(id) wasm_obj_native_call(id, (int32)argv, ARGC)
#define CALL_OBJ_NATIVE_FUNC(id) wasm_obj_native_call(id, argv, ARGC)
typedef struct _obj_evt_cb {
struct _obj_evt_cb *next;

View File

@ -15,7 +15,7 @@
*/
#include "sensor.h"
#include "native_interface.h"
#include "sensor_api.h"
typedef struct _sensor {
struct _sensor * next;
@ -31,7 +31,7 @@ sensor_t sensor_open(const char* name, int index,
sensor_event_handler_f sensor_event_handler,
void *user_data)
{
uint32 id = wasm_sensor_open((int32)name, index);
uint32 id = wasm_sensor_open(name, index);
if (id == -1)
return NULL;
@ -66,7 +66,7 @@ bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg)
char *buffer = (char *)cfg;
int len = attr_container_get_serialize_length(cfg);
return wasm_sensor_config_with_attr_container(sensor->handle, (int32)buffer, len);
return wasm_sensor_config_with_attr_container(sensor->handle, buffer, len);
}
bool sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay)

View File

@ -16,23 +16,28 @@
#ifndef CONNECTION_API_H_
#define CONNECTION_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
uint32 wasm_open_connection(int32 name_offset, int32 args_offset, uint32 len);
uint32
wasm_open_connection(const char *name, char *args_buf, uint32 args_buf_len);
void wasm_close_connection(uint32 handle);
void
wasm_close_connection(uint32 handle);
int wasm_send_on_connection(uint32 handle, int32 data_offset, uint32 len);
int
wasm_send_on_connection(uint32 handle, const char *data, uint32 data_len);
bool wasm_config_connection(uint32 handle, int32 cfg_offset, uint32 len);
bool
wasm_config_connection(uint32 handle, const char *cfg_buf, uint32 cfg_buf_len);
#ifdef __cplusplus
}
#endif
#endif /* CONNECTION_API_H_ */
#endif /* end of CONNECTION_API_H_ */

View File

@ -14,19 +14,29 @@
* limitations under the License.
*/
#ifndef GUI_API_H_
#define GUI_API_H_
#ifndef _GUI_API_H_
#define _GUI_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
void wasm_obj_native_call(int32 func_id, uint32 argv_offset, uint32 argc);
void wasm_btn_native_call(int32 func_id, uint32 argv_offset, uint32 argc);
void wasm_label_native_call(int32 func_id, uint32 argv_offset, uint32 argc);
void wasm_cb_native_call(int32 func_id, uint32 argv_offset, uint32 argc);
void wasm_list_native_call(int32 func_id, uint32 argv_offset, uint32 argc);
void
wasm_obj_native_call(int32 func_id, uint32 *argv, uint32 argc);
void
wasm_btn_native_call(int32 func_id, uint32 *argv, uint32 argc);
void
wasm_label_native_call(int32 func_id, uint32 *argv, uint32 argc);
void
wasm_cb_native_call(int32 func_id, uint32 *argv, uint32 argc);
void
wasm_list_native_call(int32 func_id, uint32 *argv, uint32 argc);
#ifdef __cplusplus
@ -34,4 +44,4 @@ void wasm_list_native_call(int32 func_id, uint32 argv_offset, uint32 argc);
#endif
#endif /* GUI_API_H_ */
#endif /* end of _GUI_API_H_ */

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
#ifndef DEPS_SSG_MICRO_RUNTIME_WASM_POC_APP_LIBS_NATIVE_INTERFACE_NATIVE_INTERFACE_H_
#define DEPS_SSG_MICRO_RUNTIME_WASM_POC_APP_LIBS_NATIVE_INTERFACE_NATIVE_INTERFACE_H_
#ifndef _NATIVE_INTERFACE_H_
#define _NATIVE_INTERFACE_H_
// note: the bh_plaform.h is the only head file separately
// implemented by both [app] and [native] worlds
/* Note: the bh_plaform.h is the only head file separately
implemented by both [app] and [native] worlds */
#include "bh_platform.h"
#include "wasm_export.h"
#define get_module_inst() \
wasm_runtime_get_current_module_inst()
@ -39,52 +40,102 @@
#define module_free(offset) \
wasm_runtime_module_free(module_inst, offset)
char *wa_strdup(const char *);
bool
wasm_response_send(int32 buffer_offset, int size);
void wasm_register_resource(int32 url_offset);
void wasm_post_request(int32 buffer_offset, int size);
void wasm_sub_event(int32 url_offset);
/*char *wa_strdup(const char *);*/
/*
* ************* sensor interfaces *************
* request/response interfaces
*/
bool
wasm_sensor_config(uint32 sensor, int interval, int bit_cfg, int delay);
uint32
wasm_sensor_open(int32 name_offset, int instance);
bool
wasm_sensor_config_with_attr_container(uint32 sensor, int32 buffer_offset,
int len);
bool
wasm_sensor_close(uint32 sensor);
wasm_response_send(wasm_module_inst_t module_inst,
int32 buffer_offset, int size);
void
wasm_register_resource(wasm_module_inst_t module_inst,
int32 url_offset);
void
wasm_post_request(wasm_module_inst_t module_inst,
int32 buffer_offset, int size);
void
wasm_sub_event(wasm_module_inst_t module_inst,
int32 url_offset);
/*
* *** timer interface ***
* sensor interfaces
*/
bool
wasm_sensor_config(wasm_module_inst_t module_inst,
uint32 sensor, int interval, int bit_cfg, int delay);
uint32
wasm_sensor_open(wasm_module_inst_t module_inst,
int32 name_offset, int instance);
bool
wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst,
uint32 sensor,
int32 buffer_offset, int len);
bool
wasm_sensor_close(wasm_module_inst_t module_inst,
uint32 sensor);
/*
* timer interfaces
*/
typedef unsigned int timer_id_t;
timer_id_t wasm_create_timer(int interval, bool is_period, bool auto_start);
void wasm_timer_destory(timer_id_t timer_id);
void wasm_timer_cancel(timer_id_t timer_id);
void wasm_timer_restart(timer_id_t timer_id, int interval);
uint32 wasm_get_sys_tick_ms(void);
timer_id_t
wasm_create_timer(wasm_module_inst_t module_inst,
int interval, bool is_period, bool auto_start);
void
wasm_timer_destory(wasm_module_inst_t module_inst, timer_id_t timer_id);
void
wasm_timer_cancel(wasm_module_inst_t module_inst, timer_id_t timer_id);
void
wasm_timer_restart(wasm_module_inst_t module_inst,
timer_id_t timer_id, int interval);
uint32
wasm_get_sys_tick_ms(wasm_module_inst_t module_inst);
/*
* *** connection interface ***
* connection interfaces
*/
uint32 wasm_open_connection(int32 name_offset, int32 args_offset, uint32 len);
void wasm_close_connection(uint32 handle);
int wasm_send_on_connection(uint32 handle, int32 data_offset, uint32 len);
bool wasm_config_connection(uint32 handle, int32 cfg_offset, uint32 len);
#include "gui_api.h"
uint32
wasm_open_connection(wasm_module_inst_t module_inst,
int32 name_offset, int32 args_offset, uint32 len);
void
wasm_close_connection(wasm_module_inst_t module_inst,
uint32 handle);
int
wasm_send_on_connection(wasm_module_inst_t module_inst,
uint32 handle, int32 data_offset, uint32 len);
bool
wasm_config_connection(wasm_module_inst_t module_inst,
uint32 handle, int32 cfg_offset, uint32 len);
/**
* gui interfaces
*/
void
wasm_obj_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc);
void
wasm_btn_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc);
void
wasm_label_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc);
void
wasm_cb_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc);
void
wasm_list_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc);
#endif /* end of _NATIVE_INTERFACE_H */
#endif /* DEPS_SSG_MICRO_RUNTIME_WASM_PO
C_APP_LIBS_NATIVE_INTERFACE_NATIVE_INTERFACE_H_ */

View File

@ -1,6 +1,6 @@
Attention:
=======
Only add files are shared by both wasm application and native runtime into this directory!
Only add files which are shared by both wasm application and native runtime into this directory!
The c files are both compiled into the the WASM APP and native runtime.

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _REQ_RESP_API_H_
#define _REQ_RESP_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
bool
wasm_response_send(const char *buf, int size);
void
wasm_register_resource(const char *url);
void
wasm_post_request(const char *buf, int size);
void
wasm_sub_event(const char *url);
#ifdef __cplusplus
}
#endif
#endif /* end of _REQ_RESP_API_H_ */

View File

@ -19,7 +19,6 @@
#include <stdbool.h>
#include <stdio.h>
#include "native_interface.h"
#include "shared_utils.h"
/* Serialization of request and response message

View File

@ -14,8 +14,9 @@
* limitations under the License.
*/
#ifndef DEPS_IWASM_APP_LIBS_NATIVE_INTERFACE_SENSOR_API_H_
#define DEPS_IWASM_APP_LIBS_NATIVE_INTERFACE_SENSOR_API_H_
#ifndef _SENSOR_API_H_
#define _SENSOR_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
@ -29,7 +30,7 @@ bool
wasm_sensor_config(uint32 sensor, int interval, int bit_cfg, int delay);
bool
wasm_sensor_config_with_attr_container(uint32 sensor, char * buffer, int len);
wasm_sensor_config_with_attr_container(uint32 sensor, char *buffer, int len);
bool
wasm_sensor_close(uint32 sensor);
@ -38,4 +39,5 @@ wasm_sensor_close(uint32 sensor);
}
#endif
#endif /* DEPS_IWASM_APP_LIBS_NATIVE_INTERFACE_SENSOR_API_H_ */
#endif /* end of _SENSOR_API_H_ */

View File

@ -14,10 +14,10 @@
* limitations under the License.
*/
#ifndef DEPS_SSG_MICRO_RUNTIME_WASM_POC_APP_LIBS_NATIVE_INTERFACE_SHARED_UTILS_H_
#define DEPS_SSG_MICRO_RUNTIME_WASM_POC_APP_LIBS_NATIVE_INTERFACE_SHARED_UTILS_H_
#ifndef _SHARED_UTILS_H_
#define _SHARED_UTILS_H_
#include "native_interface.h"
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
@ -71,16 +71,27 @@ typedef struct response {
unsigned long reciever;
} response_t;
int check_url_start(const char* url, int url_len, const char * leading_str);
bool match_url(char * pattern, char * matched);
char * find_key_value(char * buffer, int buffer_len, char * key, char * value,
int value_len, char delimiter);
int
check_url_start(const char* url, int url_len, const char * leading_str);
request_t *clone_request(request_t *request);
void request_cleaner(request_t *request);
bool
match_url(char * pattern, char * matched);
response_t * clone_response(response_t * response);
void response_cleaner(response_t * response);
char *
find_key_value(char * buffer, int buffer_len, char * key, char * value,
int value_len, char delimiter);
request_t *
clone_request(request_t *request);
void
request_cleaner(request_t *request);
response_t *
clone_response(response_t * response);
void
response_cleaner(response_t * response);
/**
* @brief Set fields of response.
@ -95,8 +106,9 @@ void response_cleaner(response_t * response);
*
* @warning the response pointer MUST NOT be NULL
*/
response_t * set_response(response_t * response, int status, int fmt,
const char *payload, int payload_len);
response_t *
set_response(response_t * response, int status, int fmt,
const char *payload, int payload_len);
/**
* @brief Make a response for a request.
@ -108,8 +120,8 @@ response_t * set_response(response_t * response, int status, int fmt,
*
* @warning the request and response pointers MUST NOT be NULL
*/
response_t * make_response_for_request(request_t * request,
response_t * response);
response_t *
make_response_for_request(request_t * request, response_t * response);
/**
* @brief Initialize a request.
@ -125,14 +137,24 @@ response_t * make_response_for_request(request_t * request,
*
* @warning the request pointer MUST NOT be NULL
*/
request_t * init_request(request_t * request, char *url, int action, int fmt,
void *payload, int payload_len);
request_t *
init_request(request_t * request, char *url, int action, int fmt,
void *payload, int payload_len);
char * pack_request(request_t *request, int * size);
request_t * unpack_request(char * packet, int size, request_t * request);
char * pack_response(response_t *response, int * size);
response_t * unpack_response(char * packet, int size, response_t * response);
void free_req_resp_packet(char * packet);
char *
pack_request(request_t *request, int * size);
request_t *
unpack_request(char * packet, int size, request_t * request);
char *
pack_response(response_t *response, int * size);
response_t *
unpack_response(char * packet, int size, response_t * response);
void
free_req_resp_packet(char * packet);
#include "wgl_shared_utils.h"
@ -140,4 +162,4 @@ void free_req_resp_packet(char * packet);
}
#endif
#endif /* DEPS_SSG_MICRO_RUNTIME_WASM_POC_APP_LIBS_NATIVE_INTERFACE_SHARED_UTILS_H_ */
#endif /* end of _SHARED_UTILS_H_ */

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _TIMER_API_H_
#define _TIMER_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int timer_id_t;
timer_id_t
wasm_create_timer(int interval, bool is_period, bool auto_start);
void
wasm_timer_destory(timer_id_t timer_id);
void
wasm_timer_cancel(timer_id_t timer_id);
void
wasm_timer_restart(timer_id_t timer_id, int interval);
uint32
wasm_get_sys_tick_ms(void);
#ifdef __cplusplus
}
#endif
#endif /* end of _TIMER_API_H_ */

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _WASM_EXPORT_H
#define _WASM_EXPORT_H
#include <inttypes.h>
#include <stdbool.h>
/**
* API exported to WASM application
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Get current WASM module instance of the current native thread
*
* @return current WASM module instance of the current native thread, 0
* if not found
* Note: the return type is uint64_t but not pointer type, because that
* the we only supports WASM-32, in which the pointer type is
* compiled to WASM i32 type, but the pointer type in native can be
* 32-bit and 64-bit. And if the native pointer is 64-bit, data loss
* occurs after converting it to WASM i32 type.
*/
uint64_t
wasm_runtime_get_current_module_inst();
/**
* Validate the app address, check whether it belongs to WASM module
* instance's address space, or in its heap space or memory space.
*
* @param module_inst the WASM module instance
* @param app_offset the app address to validate, which is a relative address
* @param size the size bytes of the app address
*
* @return true if success, false otherwise.
*/
bool
wasm_runtime_validate_app_addr(uint64_t module_inst,
int32_t app_offset, uint32_t size);
/**
* Validate the native address, check whether it belongs to WASM module
* instance's address space, or in its heap space or memory space.
*
* @param module_inst the WASM module instance
* @param native_ptr the native address to validate, which is an absolute
* address
* @param size the size bytes of the app address
*
* @return true if success, false otherwise.
*/
bool
wasm_runtime_validate_native_addr(uint64_t module_inst,
uint64_t native_ptr, uint32_t size);
/**
* Convert app address(relative address) to native address(absolute address)
*
* @param module_inst the WASM module instance
* @param app_offset the app adress
*
* @return the native address converted
*/
uint64_t
wasm_runtime_addr_app_to_native(uint64_t module_inst,
int32_t app_offset);
/**
* Convert native address(absolute address) to app address(relative address)
*
* @param module_inst the WASM module instance
* @param native_ptr the native address
*
* @return the app address converted
*/
int32_t
wasm_runtime_addr_native_to_app(uint64_t module_inst,
uint64_t native_ptr);
#ifdef __cplusplus
}
#endif
#endif /* end of _WASM_EXPORT_H */

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _WASM_EXPORT_H
#define _WASM_EXPORT_H
#include <inttypes.h>
#include <stdbool.h>
/**
* API exported to WASM application
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Get current WASM module instance of the current native thread
*
* @return current WASM module instance of the current native thread, 0
* if not found
* Note: the return type is uint64_t but not pointer type, because that
* the we only supports WASM-32, in which the pointer type is
* compiled to WASM i32 type, but the pointer type in native can be
* 32-bit and 64-bit. And if the native pointer is 64-bit, data loss
* occurs after converting it to WASM i32 type.
*/
uint64_t
wasm_runtime_get_current_module_inst();
/**
* Validate the app address, check whether it belongs to WASM module
* instance's address space, or in its heap space or memory space.
*
* @param module_inst the WASM module instance
* @param app_offset the app address to validate, which is a relative address
* @param size the size bytes of the app address
*
* @return true if success, false otherwise.
*/
bool
wasm_runtime_validate_app_addr(uint64_t module_inst,
int32_t app_offset, uint32_t size);
/**
* Validate the native address, check whether it belongs to WASM module
* instance's address space, or in its heap space or memory space.
*
* @param module_inst the WASM module instance
* @param native_ptr the native address to validate, which is an absolute
* address
* @param size the size bytes of the app address
*
* @return true if success, false otherwise.
*/
bool
wasm_runtime_validate_native_addr(uint64_t module_inst,
uint64_t native_ptr, uint32_t size);
/**
* Convert app address(relative address) to native address(absolute address)
*
* @param module_inst the WASM module instance
* @param app_offset the app adress
*
* @return the native address converted
*/
uint64_t
wasm_runtime_addr_app_to_native(uint64_t module_inst,
int32_t app_offset);
/**
* Convert native address(absolute address) to app address(relative address)
*
* @param module_inst the WASM module instance
* @param native_ptr the native address
*
* @return the app address converted
*/
int32_t
wasm_runtime_addr_native_to_app(uint64_t module_inst,
uint64_t native_ptr);
#ifdef __cplusplus
}
#endif
#endif /* end of _WASM_EXPORT_H */

View File

@ -18,11 +18,111 @@
#include <stdlib.h>
#include <string.h>
#include "lib_export.h"
#include "bh_platform.h"
#include "wasm_export.h"
#ifdef WASM_ENABLE_BASE_LIB
#include "base_lib_export.h"
#endif
static uint64
wasm_runtime_get_current_module_inst_wrapper(wasm_module_inst_t module_inst)
{
return (uint64)(uintptr_t)module_inst;
}
static bool
wasm_runtime_validate_app_addr_wrapper(wasm_module_inst_t module_inst,
uint32 inst_part0, uint32 inst_part1,
int32 app_offset, uint32 size)
{
bool ret;
union { uint64 u64; uint32 parts[2]; } inst;
inst.parts[0] = inst_part0;
inst.parts[1] = inst_part1;
if (inst.u64 != (uint64)(uintptr_t)module_inst) {
printf("Invalid module instance\n");
return false;
}
ret = wasm_runtime_validate_app_addr(module_inst, app_offset, size);
if (!ret)
wasm_runtime_clear_exception(module_inst);
return ret;
}
static bool
wasm_runtime_validate_native_addr_wrapper(wasm_module_inst_t module_inst,
uint32 inst_part0, uint32 inst_part1,
uint32 native_ptr_part0,
uint32 native_ptr_part1,
uint32 size)
{
bool ret;
union { uint64 u64; uint32 parts[2]; } inst;
union { uint64 u64; uint32 parts[2]; } native_ptr;
inst.parts[0] = inst_part0;
inst.parts[1] = inst_part1;
if (inst.u64 != (uint64)(uintptr_t)module_inst) {
printf("Invalid module instance\n");
return false;
}
native_ptr.parts[0] = native_ptr_part0;
native_ptr.parts[1] = native_ptr_part1;
ret = wasm_runtime_validate_native_addr(module_inst,
(void*)(uintptr_t)native_ptr.u64,
size);
if (!ret)
wasm_runtime_clear_exception(module_inst);
return ret;
}
static uint64
wasm_runtime_addr_app_to_native_wrapper(wasm_module_inst_t module_inst,
uint32 inst_part0, uint32 inst_part1,
int32 app_offset)
{
union { uint64 u64; uint32 parts[2]; } inst;
inst.parts[0] = inst_part0;
inst.parts[1] = inst_part1;
if (inst.u64 != (uint64)(uintptr_t)module_inst) {
printf("Invalid module instance\n");
return 0;
}
return (uint64)(uintptr_t)
wasm_runtime_addr_app_to_native(module_inst, app_offset);
}
static int32
wasm_runtime_addr_native_to_app_wrapper(wasm_module_inst_t module_inst,
uint32 inst_part0, uint32 inst_part1,
uint32 native_ptr_part0,
uint32 native_ptr_part1)
{
union { uint64 u64; uint32 parts[2]; } inst;
union { uint64 u64; uint32 parts[2]; } native_ptr;
inst.parts[0] = inst_part0;
inst.parts[1] = inst_part1;
if (inst.u64 != (uint64)(uintptr_t)module_inst) {
printf("Invalid module instance\n");
return 0;
}
native_ptr.parts[0] = native_ptr_part0;
native_ptr.parts[1] = native_ptr_part1;
return wasm_runtime_addr_native_to_app(module_inst,
(void*)(uintptr_t)native_ptr.u64);
}
static NativeSymbol extended_native_symbol_defs[] = {
/* TODO: use macro EXPORT_WASM_API() or EXPORT_WASM_API2() to
add functions to register. */
@ -38,6 +138,11 @@ static NativeSymbol extended_native_symbol_defs[] = {
EXPORT_WASM_API(wasm_timer_restart),
EXPORT_WASM_API(wasm_get_sys_tick_ms),
#endif
EXPORT_WASM_API2(wasm_runtime_get_current_module_inst),
EXPORT_WASM_API2(wasm_runtime_validate_app_addr),
EXPORT_WASM_API2(wasm_runtime_validate_native_addr),
EXPORT_WASM_API2(wasm_runtime_addr_app_to_native),
EXPORT_WASM_API2(wasm_runtime_addr_native_to_app),
};
int get_base_lib_export_apis(NativeSymbol **p_base_lib_apis)

View File

@ -14,16 +14,16 @@
* limitations under the License.
*/
#include "native_interface.h"
#include "app_manager_export.h"
#include "coap_ext.h"
#include "wasm_export.h"
extern void module_request_handler(request_t *request, void *user_data);
bool wasm_response_send(int32 buffer_offset, int size)
bool
wasm_response_send(wasm_module_inst_t module_inst,
int32 buffer_offset, int size)
{
wasm_module_inst_t module_inst = get_module_inst();
char *buffer = NULL;
if (!validate_app_addr(buffer_offset, size))
@ -45,9 +45,9 @@ bool wasm_response_send(int32 buffer_offset, int size)
return false;
}
void wasm_register_resource(int32 url_offset)
void
wasm_register_resource(wasm_module_inst_t module_inst, int32 url_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
char *url = NULL;
if (!validate_app_addr(url_offset, 1))
@ -61,9 +61,10 @@ void wasm_register_resource(int32 url_offset)
}
}
void wasm_post_request(int32 buffer_offset, int size)
void
wasm_post_request(wasm_module_inst_t module_inst,
int32 buffer_offset, int size)
{
wasm_module_inst_t module_inst = get_module_inst();
char *buffer = NULL;
if (!validate_app_addr(buffer_offset, size))
@ -92,9 +93,9 @@ void wasm_post_request(int32 buffer_offset, int size)
}
}
void wasm_sub_event(int32 url_offset)
void
wasm_sub_event(wasm_module_inst_t module_inst, int32 url_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
char *url = NULL;
if (!validate_app_addr(url_offset, 1))

View File

@ -17,7 +17,6 @@
#ifndef LIB_BASE_RUNTIME_LIB_H_
#define LIB_BASE_RUNTIME_LIB_H_
#include "native_interface.h"
#include "runtime_timer.h"

View File

@ -37,7 +37,7 @@ void wasm_timer_callback(timer_id_t id, unsigned int mod_id)
// !!! the length parameter must be 0, so the receiver will
// not free the payload pointer.
bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *) id, 0);
bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *)(uintptr_t)id, 0);
}
///
@ -149,30 +149,37 @@ timer_ctx_t get_wasm_timer_ctx()
return m->timer_ctx;
}
timer_id_t wasm_create_timer(int interval, bool is_period, bool auto_start)
timer_id_t
wasm_create_timer(wasm_module_inst_t module_inst,
int interval, bool is_period, bool auto_start)
{
return sys_create_timer(get_wasm_timer_ctx(), interval, is_period,
auto_start);
}
void wasm_timer_destory(timer_id_t timer_id)
void
wasm_timer_destory(wasm_module_inst_t module_inst, timer_id_t timer_id)
{
sys_timer_destory(get_wasm_timer_ctx(), timer_id);
}
void wasm_timer_cancel(timer_id_t timer_id)
void
wasm_timer_cancel(wasm_module_inst_t module_inst, timer_id_t timer_id)
{
sys_timer_cancel(get_wasm_timer_ctx(), timer_id);
}
void wasm_timer_restart(timer_id_t timer_id, int interval)
void
wasm_timer_restart(wasm_module_inst_t module_inst,
timer_id_t timer_id, int interval)
{
sys_timer_restart(get_wasm_timer_ctx(), timer_id, interval);
}
extern uint32 get_sys_tick_ms();
uint32 wasm_get_sys_tick_ms(void)
uint32
wasm_get_sys_tick_ms(wasm_module_inst_t module_inst)
{
return (uint32) bh_get_tick_ms();
}

View File

@ -23,10 +23,10 @@
* This file is the consumer of connection lib which is implemented by different platforms
*/
uint32 wasm_open_connection(int32 name_offset, int32 args_offset, uint32 len)
uint32
wasm_open_connection(wasm_module_inst_t module_inst,
int32 name_offset, int32 args_offset, uint32 len)
{
wasm_module_inst_t module_inst = get_module_inst();
attr_container_t *args;
char *name, *args_buf;
@ -44,15 +44,17 @@ uint32 wasm_open_connection(int32 name_offset, int32 args_offset, uint32 len)
return -1;
}
void wasm_close_connection(uint32 handle)
void
wasm_close_connection(wasm_module_inst_t module_inst, uint32 handle)
{
if (connection_impl._close != NULL)
connection_impl._close(handle);
}
int wasm_send_on_connection(uint32 handle, int32 data_offset, uint32 len)
int
wasm_send_on_connection(wasm_module_inst_t module_inst,
uint32 handle, int32 data_offset, uint32 len)
{
wasm_module_inst_t module_inst = get_module_inst();
char *data;
if (!validate_app_addr(data_offset, len) ||
@ -65,9 +67,10 @@ int wasm_send_on_connection(uint32 handle, int32 data_offset, uint32 len)
return -1;
}
bool wasm_config_connection(uint32 handle, int32 cfg_offset, uint32 len)
bool
wasm_config_connection(wasm_module_inst_t module_inst,
uint32 handle, int32 cfg_offset, uint32 len)
{
wasm_module_inst_t module_inst = get_module_inst();
char *cfg_buf;
attr_container_t *cfg;

View File

@ -45,7 +45,9 @@ static WGLNativeFuncDef btn_native_func_defs[] = {
};
/*************** Native Interface to Wasm App ***********/
void wasm_btn_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
void
wasm_btn_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc)
{
uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef);

View File

@ -61,7 +61,9 @@ static WGLNativeFuncDef cb_native_func_defs[] = {
};
/*************** Native Interface to Wasm App ***********/
void wasm_cb_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
void
wasm_cb_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc)
{
uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef);

View File

@ -60,7 +60,9 @@ static WGLNativeFuncDef label_native_func_defs[] = {
};
/*************** Native Interface to Wasm App ***********/
void wasm_label_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
void
wasm_label_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc)
{
uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef);

View File

@ -51,7 +51,9 @@ static WGLNativeFuncDef list_native_func_defs[] = {
};
/*************** Native Interface to Wasm App ***********/
void wasm_list_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
void
wasm_list_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc)
{
uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef);

View File

@ -341,7 +341,9 @@ static WGLNativeFuncDef obj_native_func_defs[] = {
};
/*************** Native Interface to Wasm App ***********/
void wasm_obj_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
void
wasm_obj_native_call(wasm_module_inst_t module_inst,
int32 func_id, uint32 argv_offset, uint32 argc)
{
uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef);

View File

@ -22,8 +22,10 @@
static sys_sensor_t * g_sys_sensors = NULL;
static int g_sensor_id_max = 0;
static sensor_client_t *find_sensor_client(sys_sensor_t * sensor,
unsigned int client_id, bool remove_if_found);
static sensor_client_t *
find_sensor_client(sys_sensor_t * sensor,
unsigned int client_id, bool remove_if_found);
void (*rechedule_sensor_callback)() = NULL;
@ -32,7 +34,8 @@ void (*rechedule_sensor_callback)() = NULL;
*
*/
static void sensor_event_cleaner(sensor_event_data_t *sensor_event)
static void
sensor_event_cleaner(sensor_event_data_t *sensor_event)
{
if (sensor_event->data != NULL) {
if (sensor_event->data_fmt == FMT_ATTR_CONTAINER)
@ -44,8 +47,8 @@ static void sensor_event_cleaner(sensor_event_data_t *sensor_event)
bh_free(sensor_event);
}
static void wasm_sensor_callback(void *client, uint32 sensor_id,
void *user_data)
static void
wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data)
{
attr_container_t *sensor_data = (attr_container_t *) user_data;
attr_container_t *sensor_data_clone;
@ -92,7 +95,10 @@ static void wasm_sensor_callback(void *client, uint32 sensor_id,
bh_post_msg2(module->queue, msg);
}
bool wasm_sensor_config(uint32 sensor, int interval, int bit_cfg, int delay)
bool
wasm_sensor_config(wasm_module_inst_t module_inst,
uint32 sensor, int interval,
int bit_cfg, int delay)
{
attr_container_t * attr_cont;
sensor_client_t * c;
@ -132,9 +138,10 @@ bool wasm_sensor_config(uint32 sensor, int interval, int bit_cfg, int delay)
return true;
}
uint32 wasm_sensor_open(int32 name_offset, int instance)
uint32
wasm_sensor_open(wasm_module_inst_t module_inst,
int32 name_offset, int instance)
{
wasm_module_inst_t module_inst = get_module_inst();
char *name = NULL;
if (!validate_app_addr(name_offset, 1))
@ -185,10 +192,11 @@ uint32 wasm_sensor_open(int32 name_offset, int instance)
return -1;
}
bool wasm_sensor_config_with_attr_container(uint32 sensor, int32 buffer_offset,
int len)
bool
wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst,
uint32 sensor, int32 buffer_offset,
int len)
{
wasm_module_inst_t module_inst = get_module_inst();
char *buffer = NULL;
if (!validate_app_addr(buffer_offset, len))
@ -211,7 +219,8 @@ bool wasm_sensor_config_with_attr_container(uint32 sensor, int32 buffer_offset,
return false;
}
bool wasm_sensor_close(uint32 sensor)
bool
wasm_sensor_close(wasm_module_inst_t module_inst, uint32 sensor)
{
unsigned int mod_id = app_manager_get_module_id(Module_WASM_App);
unsigned int client_id = mod_id;
@ -271,8 +280,9 @@ void refresh_read_interval(sensor_obj_t sensor)
sensor->read_interval = interval;
}
sensor_obj_t add_sys_sensor(char * name, char * description, int instance,
uint32 default_interval, void * read_func, void * config_func)
sensor_obj_t
add_sys_sensor(char * name, char * description, int instance,
uint32 default_interval, void * read_func, void * config_func)
{
sys_sensor_t * s = (sys_sensor_t *) bh_malloc(sizeof(sys_sensor_t));
if (s == NULL)

View File

@ -19,6 +19,8 @@
#include "bh_platform.h"
#include "attr_container.h"
#include "wasm_export.h"
struct _sys_sensor;
typedef struct _sys_sensor* sensor_obj_t;
@ -60,16 +62,19 @@ int check_sensor_timers();
void reschedule_sensor_read();
uint32
wasm_sensor_open(int32 name_offset, int instance);
wasm_sensor_open(wasm_module_inst_t module_inst,
int32 name_offset, int instance);
bool
wasm_sensor_config(uint32 sensor, int interval, int bit_cfg, int delay);
wasm_sensor_config(wasm_module_inst_t module_inst,
uint32 sensor, int interval, int bit_cfg, int delay);
bool
wasm_sensor_config_with_attr_container(uint32 sensor, int32 buffer_offset,
int len);
wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst,
uint32 sensor, int32 buffer_offset,
int len);
bool
wasm_sensor_close(uint32 sensor);
wasm_sensor_close(wasm_module_inst_t module_inst, uint32 sensor);
#endif /* LIB_EXTENSION_RUNTIME_SENSOR_H_ */

View File

@ -34,9 +34,6 @@ wasm_runtime_get_llvm_stack(wasm_module_inst_t module);
void
wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack);
#define get_module_inst() \
wasm_runtime_get_current_module_inst()
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, size)
@ -52,6 +49,29 @@ wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack);
#define module_free(offset) \
wasm_runtime_module_free(module_inst, offset)
static bool
validate_str_addr(wasm_module_inst_t module_inst, int32 str_offset)
{
int32 app_end_offset;
char *str, *str_end;
if (!wasm_runtime_get_app_addr_range(module_inst, str_offset,
NULL, &app_end_offset))
goto fail;
str = addr_app_to_native(str_offset);
str_end = str + (app_end_offset - str_offset);
while (str < str_end && *str != '\0')
str++;
if (str == str_end)
goto fail;
return true;
fail:
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
return false;
}
typedef int (*out_func_t)(int c, void *ctx);
enum pad_type {
@ -64,9 +84,14 @@ enum pad_type {
typedef char *_va_list;
#define _INTSIZEOF(n) \
((sizeof(n) + 3) & ~3)
#define _va_arg(ap,t) \
#define _va_arg(ap, t) \
(*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
#define CHECK_VA_ARG(ap, t) do { \
if ((uint8*)ap + _INTSIZEOF(t) > native_end_addr) \
goto fail; \
} while (0)
/**
* @brief Output an unsigned int in hex format
*
@ -172,14 +197,19 @@ print_err(out_func_t out, void *ctx)
out('R', ctx);
}
static void
_vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
wasm_module_inst_t module_inst)
static bool
_vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap,
wasm_module_inst_t module_inst)
{
int might_format = 0; /* 1 if encountered a '%' */
enum pad_type padding = PAD_NONE;
int min_width = -1;
int long_ctr = 0;
uint8 *native_end_addr;
if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)ap,
NULL, &native_end_addr))
goto fail;
/* fmt has already been adjusted if needed */
@ -232,10 +262,13 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
int32 d;
if (long_ctr < 2) {
CHECK_VA_ARG(ap, int32);
d = _va_arg(ap, int32);
}
else {
int64 lld = _va_arg(ap, int64);
int64 lld;
CHECK_VA_ARG(ap, int64);
lld = _va_arg(ap, int64);
if (lld > INT32_MAX || lld < INT32_MIN) {
print_err(out, ctx);
break;
@ -255,10 +288,13 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
uint32 u;
if (long_ctr < 2) {
CHECK_VA_ARG(ap, uint32);
u = _va_arg(ap, uint32);
}
else {
uint64 llu = _va_arg(ap, uint64);
uint64 llu;
CHECK_VA_ARG(ap, uint64);
llu = _va_arg(ap, uint64);
if (llu > INT32_MAX) {
print_err(out, ctx);
break;
@ -281,8 +317,10 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
bool is_ptr = (*fmt == 'p') ? true : false;
if (long_ctr < 2) {
CHECK_VA_ARG(ap, uint32);
x = _va_arg(ap, uint32);
} else {
CHECK_VA_ARG(ap, uint64);
x = _va_arg(ap, uint64);
}
_printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width);
@ -292,11 +330,13 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
case 's': {
char *s;
char *start;
int32 s_offset = _va_arg(ap, uint32);
int32 s_offset;
if (!validate_app_addr(s_offset, 1)) {
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
return;
CHECK_VA_ARG(ap, uint32);
s_offset = _va_arg(ap, uint32);
if (!validate_str_addr(module_inst, s_offset)) {
return false;
}
s = start = addr_app_to_native(s_offset);
@ -314,7 +354,9 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
}
case 'c': {
int c = _va_arg(ap, int);
int c;
CHECK_VA_ARG(ap, int);
c = _va_arg(ap, int);
out(c, ctx);
break;
}
@ -336,6 +378,11 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
still_might_format:
++fmt;
}
return true;
fail:
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
return false;
}
struct str_context {
@ -364,7 +411,7 @@ sprintf_out(int c, struct str_context *ctx)
static int
printf_out(int c, struct str_context *ctx)
{
printf("%c", c);
bh_printf("%c", c);
ctx->count++;
return c;
}
@ -391,7 +438,7 @@ parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset,
_va_list v;
} u;
if (!validate_app_addr(fmt_offset, 1)
if (!validate_str_addr(module_inst, fmt_offset)
|| !validate_app_addr(va_list_offset, sizeof(int32)))
return false;
@ -404,9 +451,9 @@ parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset,
}
static int
_printf_wrapper(int32 fmt_offset, int32 va_list_offset)
_printf_wrapper(wasm_module_inst_t module_inst,
int32 fmt_offset, int32 va_list_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
struct str_context ctx = { NULL, 0, 0 };
const char *fmt;
_va_list va_args;
@ -414,21 +461,26 @@ _printf_wrapper(int32 fmt_offset, int32 va_list_offset)
if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args))
return 0;
_vprintf((out_func_t) printf_out, &ctx, fmt, va_args, module_inst);
if (!_vprintf_wa((out_func_t)printf_out, &ctx, fmt, va_args, module_inst))
return 0;
return ctx.count;
}
static int
_sprintf_wrapper(int32 str_offset, int32 fmt_offset, int32 va_list_offset)
_sprintf_wrapper(wasm_module_inst_t module_inst,
int32 str_offset, int32 fmt_offset, int32 va_list_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
int32 app_end_offset;
struct str_context ctx;
char *str;
const char *fmt;
_va_list va_args;
if (!validate_app_addr(str_offset, 1))
return 0;
if (!wasm_runtime_get_app_addr_range(module_inst, str_offset,
NULL, &app_end_offset)) {
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
return false;
}
str = addr_app_to_native(str_offset);
@ -436,10 +488,11 @@ _sprintf_wrapper(int32 str_offset, int32 fmt_offset, int32 va_list_offset)
return 0;
ctx.str = str;
ctx.max = INT_MAX;
ctx.max = app_end_offset - str_offset;
ctx.count = 0;
_vprintf((out_func_t) sprintf_out, &ctx, fmt, va_args, module_inst);
if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst))
return 0;
if (ctx.count < ctx.max) {
str[ctx.count] = '\0';
@ -449,10 +502,10 @@ _sprintf_wrapper(int32 str_offset, int32 fmt_offset, int32 va_list_offset)
}
static int
_snprintf_wrapper(int32 str_offset, int32 size, int32 fmt_offset,
_snprintf_wrapper(wasm_module_inst_t module_inst,
int32 str_offset, int32 size, int32 fmt_offset,
int32 va_list_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
struct str_context ctx;
char *str;
const char *fmt;
@ -470,7 +523,8 @@ _snprintf_wrapper(int32 str_offset, int32 size, int32 fmt_offset,
ctx.max = size;
ctx.count = 0;
_vprintf((out_func_t) sprintf_out, &ctx, fmt, va_args, module_inst);
if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst))
return 0;
if (ctx.count < ctx.max) {
str[ctx.count] = '\0';
@ -480,34 +534,34 @@ _snprintf_wrapper(int32 str_offset, int32 size, int32 fmt_offset,
}
static int
_puts_wrapper(int32 str_offset)
_puts_wrapper(wasm_module_inst_t module_inst,
int32 str_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
const char *str;
if (!validate_app_addr(str_offset, 1))
if (!validate_str_addr(module_inst, str_offset))
return 0;
str = addr_app_to_native(str_offset);
return printf("%s\n", str);
return bh_printf("%s\n", str);
}
static int
_putchar_wrapper(int c)
_putchar_wrapper(wasm_module_inst_t module_inst, int c)
{
printf("%c", c);
bh_printf("%c", c);
return 1;
}
static int32
_strdup_wrapper(int32 str_offset)
_strdup_wrapper(wasm_module_inst_t module_inst,
int32 str_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
char *str, *str_ret;
uint32 len;
int32 str_ret_offset = 0;
if (!validate_app_addr(str_offset, 1))
if (!validate_str_addr(module_inst, str_offset))
return 0;
str = addr_app_to_native(str_offset);
@ -526,9 +580,9 @@ _strdup_wrapper(int32 str_offset)
}
static int32
_memcmp_wrapper(int32 s1_offset, int32 s2_offset, int32 size)
_memcmp_wrapper(wasm_module_inst_t module_inst,
int32 s1_offset, int32 s2_offset, int32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
void *s1, *s2;
if (!validate_app_addr(s1_offset, size)
@ -541,9 +595,9 @@ _memcmp_wrapper(int32 s1_offset, int32 s2_offset, int32 size)
}
static int32
_memcpy_wrapper(int32 dst_offset, int32 src_offset, int32 size)
_memcpy_wrapper(wasm_module_inst_t module_inst,
int32 dst_offset, int32 src_offset, int32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
void *dst, *src;
if (size == 0)
@ -560,9 +614,9 @@ _memcpy_wrapper(int32 dst_offset, int32 src_offset, int32 size)
}
static int32
_memmove_wrapper(int32 dst_offset, int32 src_offset, int32 size)
_memmove_wrapper(wasm_module_inst_t module_inst,
int32 dst_offset, int32 src_offset, int32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
void *dst, *src;
if (!validate_app_addr(dst_offset, size)
@ -576,9 +630,9 @@ _memmove_wrapper(int32 dst_offset, int32 src_offset, int32 size)
}
static int32
_memset_wrapper(int32 s_offset, int32 c, int32 size)
_memset_wrapper(wasm_module_inst_t module_inst,
int32 s_offset, int32 c, int32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
void *s;
if (!validate_app_addr(s_offset, size))
@ -590,13 +644,13 @@ _memset_wrapper(int32 s_offset, int32 c, int32 size)
}
static int32
_strchr_wrapper(int32 s_offset, int32 c)
_strchr_wrapper(wasm_module_inst_t module_inst,
int32 s_offset, int32 c)
{
wasm_module_inst_t module_inst = get_module_inst();
const char *s;
char *ret;
if (!validate_app_addr(s_offset, 1))
if (!validate_str_addr(module_inst, s_offset))
return s_offset;
s = addr_app_to_native(s_offset);
@ -605,13 +659,13 @@ _strchr_wrapper(int32 s_offset, int32 c)
}
static int32
_strcmp_wrapper(int32 s1_offset, int32 s2_offset)
_strcmp_wrapper(wasm_module_inst_t module_inst,
int32 s1_offset, int32 s2_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
void *s1, *s2;
if (!validate_app_addr(s1_offset, 1)
|| !validate_app_addr(s2_offset, 1))
if (!validate_str_addr(module_inst, s1_offset)
|| !validate_str_addr(module_inst, s2_offset))
return 0;
s1 = addr_app_to_native(s1_offset);
@ -620,9 +674,9 @@ _strcmp_wrapper(int32 s1_offset, int32 s2_offset)
}
static int32
_strncmp_wrapper(int32 s1_offset, int32 s2_offset, uint32 size)
_strncmp_wrapper(wasm_module_inst_t module_inst,
int32 s1_offset, int32 s2_offset, uint32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
void *s1, *s2;
if (!validate_app_addr(s1_offset, size)
@ -635,25 +689,30 @@ _strncmp_wrapper(int32 s1_offset, int32 s2_offset, uint32 size)
}
static int32
_strcpy_wrapper(int32 dst_offset, int32 src_offset)
_strcpy_wrapper(wasm_module_inst_t module_inst,
int32 dst_offset, int32 src_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
char *dst, *src;
uint32 len;
if (!validate_app_addr(dst_offset, 1)
|| !validate_app_addr(src_offset, 1))
if (!validate_str_addr(module_inst, src_offset))
return 0;
src = addr_app_to_native(src_offset);
len = strlen(src);
if (!validate_app_addr(dst_offset, len + 1))
return 0;
dst = addr_app_to_native(dst_offset);
src = addr_app_to_native(src_offset);
strcpy(dst, src);
strncpy(dst, src, len + 1);
return dst_offset;
}
static int32
_strncpy_wrapper(int32 dst_offset, int32 src_offset, uint32 size)
_strncpy_wrapper(wasm_module_inst_t module_inst,
int32 dst_offset, int32 src_offset, uint32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
char *dst, *src;
if (!validate_app_addr(dst_offset, size)
@ -667,12 +726,12 @@ _strncpy_wrapper(int32 dst_offset, int32 src_offset, uint32 size)
}
static uint32
_strlen_wrapper(int32 s_offset)
_strlen_wrapper(wasm_module_inst_t module_inst,
int32 s_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
char *s;
if (!validate_app_addr(s_offset, 1))
if (!validate_str_addr(module_inst, s_offset))
return 0;
s = addr_app_to_native(s_offset);
@ -680,17 +739,17 @@ _strlen_wrapper(int32 s_offset)
}
static int32
_malloc_wrapper(uint32 size)
_malloc_wrapper(wasm_module_inst_t module_inst,
uint32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
return module_malloc(size);
}
static int32
_calloc_wrapper(uint32 nmemb, uint32 size)
_calloc_wrapper(wasm_module_inst_t module_inst,
uint32 nmemb, uint32 size)
{
uint64 total_size = (uint64) nmemb * (uint64) size;
wasm_module_inst_t module_inst = get_module_inst();
uint32 ret_offset = 0;
uint8 *ret_ptr;
@ -707,31 +766,30 @@ _calloc_wrapper(uint32 nmemb, uint32 size)
}
static void
_free_wrapper(int32 ptr_offset)
_free_wrapper(wasm_module_inst_t module_inst,
int32 ptr_offset)
{
wasm_module_inst_t module_inst = get_module_inst();
if (!validate_app_addr(ptr_offset, 4))
return;
return module_free(ptr_offset);
}
static void
setTempRet0_wrapper(uint32 temp_ret)
setTempRet0_wrapper(wasm_module_inst_t module_inst,
uint32 temp_ret)
{
wasm_module_inst_t module_inst = get_module_inst();
wasm_runtime_set_temp_ret(module_inst, temp_ret);
}
static uint32
getTempRet0_wrapper()
getTempRet0_wrapper(wasm_module_inst_t module_inst)
{
wasm_module_inst_t module_inst = get_module_inst();
return wasm_runtime_get_temp_ret(module_inst);
}
static uint32
_llvm_bswap_i16_wrapper(uint32 data)
_llvm_bswap_i16_wrapper(wasm_module_inst_t module_inst,
uint32 data)
{
return (data & 0xFFFF0000)
| ((data & 0xFF) << 8)
@ -739,7 +797,8 @@ _llvm_bswap_i16_wrapper(uint32 data)
}
static uint32
_llvm_bswap_i32_wrapper(uint32 data)
_llvm_bswap_i32_wrapper(wasm_module_inst_t module_inst,
uint32 data)
{
return ((data & 0xFF) << 24)
| ((data & 0xFF00) << 8)
@ -748,10 +807,10 @@ _llvm_bswap_i32_wrapper(uint32 data)
}
static uint32
_bitshift64Lshr_wrapper(uint32 uint64_part0, uint32 uint64_part1,
_bitshift64Lshr_wrapper(wasm_module_inst_t module_inst,
uint32 uint64_part0, uint32 uint64_part1,
uint32 bits)
{
wasm_module_inst_t module_inst = get_module_inst();
union {
uint64 value;
uint32 parts[2];
@ -767,10 +826,10 @@ _bitshift64Lshr_wrapper(uint32 uint64_part0, uint32 uint64_part1,
}
static uint32
_bitshift64Shl_wrapper(uint32 int64_part0, uint32 int64_part1,
_bitshift64Shl_wrapper(wasm_module_inst_t module_inst,
uint32 int64_part0, uint32 int64_part1,
uint32 bits)
{
wasm_module_inst_t module_inst = get_module_inst();
union {
int64 value;
uint32 parts[2];
@ -786,26 +845,25 @@ _bitshift64Shl_wrapper(uint32 int64_part0, uint32 int64_part1,
}
static void
_llvm_stackrestore_wrapper(uint32 llvm_stack)
_llvm_stackrestore_wrapper(wasm_module_inst_t module_inst,
uint32 llvm_stack)
{
wasm_module_inst_t module_inst = get_module_inst();
printf("_llvm_stackrestore called!\n");
bh_printf("_llvm_stackrestore called!\n");
wasm_runtime_set_llvm_stack(module_inst, llvm_stack);
}
static uint32
_llvm_stacksave_wrapper()
_llvm_stacksave_wrapper(wasm_module_inst_t module_inst)
{
wasm_module_inst_t module_inst = get_module_inst();
printf("_llvm_stacksave called!\n");
bh_printf("_llvm_stacksave called!\n");
return wasm_runtime_get_llvm_stack(module_inst);
}
static int32
_emscripten_memcpy_big_wrapper(int32 dst_offset, int32 src_offset,
_emscripten_memcpy_big_wrapper(wasm_module_inst_t module_inst,
int32 dst_offset, int32 src_offset,
uint32 size)
{
wasm_module_inst_t module_inst = get_module_inst();
void *dst, *src;
if (!validate_app_addr(dst_offset, size)
@ -820,32 +878,48 @@ _emscripten_memcpy_big_wrapper(int32 dst_offset, int32 src_offset,
}
static void
abort_wrapper(int32 code)
abort_wrapper(wasm_module_inst_t module_inst,
int32 code)
{
wasm_module_inst_t module_inst = get_module_inst();
char buf[32];
snprintf(buf, sizeof(buf), "env.abort(%i)", code);
wasm_runtime_set_exception(module_inst, buf);
}
static void
abortStackOverflow_wrapper(int32 code)
abortStackOverflow_wrapper(wasm_module_inst_t module_inst,
int32 code)
{
wasm_module_inst_t module_inst = get_module_inst();
char buf[32];
snprintf(buf, sizeof(buf), "env.abortStackOverflow(%i)", code);
wasm_runtime_set_exception(module_inst, buf);
}
static void
nullFunc_X_wrapper(int32 code)
nullFunc_X_wrapper(wasm_module_inst_t module_inst,
int32 code)
{
wasm_module_inst_t module_inst = get_module_inst();
char buf[32];
snprintf(buf, sizeof(buf), "env.nullFunc_X(%i)", code);
wasm_runtime_set_exception(module_inst, buf);
}
/*#define ENABLE_SPEC_TEST 1*/
#ifdef ENABLE_SPEC_TEST
static void
print_i32_wrapper(wasm_module_inst_t module_inst, int i32)
{
bh_printf("%d\n", i32);
}
static void
print_wrapper(wasm_module_inst_t module_inst, int i32)
{
bh_printf("%d\n", i32);
}
#endif
/* TODO: add function parameter/result types check */
#define REG_NATIVE_FUNC(module_name, func_name) \
{ #module_name, #func_name, func_name##_wrapper }
@ -857,6 +931,10 @@ typedef struct WASMNativeFuncDef {
} WASMNativeFuncDef;
static WASMNativeFuncDef native_func_defs[] = {
#ifdef ENABLE_SPEC_TEST
REG_NATIVE_FUNC(spectest, print_i32),
REG_NATIVE_FUNC(spectest, print),
#endif
REG_NATIVE_FUNC(env, _printf),
REG_NATIVE_FUNC(env, _sprintf),
REG_NATIVE_FUNC(env, _snprintf),
@ -927,6 +1005,9 @@ typedef struct WASMNativeGlobalDef {
} WASMNativeGlobalDef;
static WASMNativeGlobalDef native_global_defs[] = {
#ifdef ENABLE_SPEC_TEST
{ "spectest", "global_i32", .global_data.u32 = 0 },
#endif
{ "env", "STACKTOP", .global_data.u32 = 0 },
{ "env", "STACK_MAX", .global_data.u32 = 0 },
{ "env", "ABORT", .global_data.u32 = 0 },
@ -961,23 +1042,6 @@ wasm_native_global_lookup(const char *module_name, const char *global_name,
global_def++;
}
/* Lookup non-constant globals which cannot be defined by table */
if (!strcmp(module_name, "env")) {
if (!strcmp(global_name, "_stdin")) {
global->global_data_linked.addr = (uintptr_t)stdin;
global->is_addr = true;
return true;
} else if (!strcmp(global_name, "_stdout")) {
global->global_data_linked.addr = (uintptr_t)stdout;
global->is_addr = true;
return true;
} else if (!strcmp(global_name, "_stderr")) {
global->global_data_linked.addr = (uintptr_t)stderr;
global->is_addr = true;
return true;
}
}
return false;
}

View File

@ -29,6 +29,20 @@
static int app_argc;
static char **app_argv;
/**
* Find the unique main function from a WASM module instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the main function is called, false otherwise.
*/
bool
wasm_application_execute_main(wasm_module_inst_t module_inst,
int argc, char *argv[]);
static void*
app_instance_main(wasm_module_inst_t module_inst)
{

View File

@ -0,0 +1,107 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required (VERSION 2.8)
project (iwasm)
set (PLATFORM "darwin")
# Reset default linker flags
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
# Enable repl mode if want to test spec cases
# add_definitions(-DWASM_ENABLE_REPL)
if (NOT ("$ENV{VALGRIND}" STREQUAL "YES"))
add_definitions(-DNVALGRIND)
endif ()
# Currently build as 64-bit by default.
set (BUILD_AS_64BIT_SUPPORT "YES")
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES")
# Add -fPIC flag if build as 64-bit
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
else ()
add_definitions (-m32)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
endif ()
endif ()
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif (NOT CMAKE_BUILD_TYPE)
message ("CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE})
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic")
set (CMAKE_MACOSX_RPATH True)
set (SHARED_LIB_DIR ../../../shared-lib)
include_directories (.
../../runtime/include
../../runtime/platform/include
${SHARED_LIB_DIR}/include)
enable_language (ASM)
include (../../runtime/platform/${PLATFORM}/platform.cmake)
include (../../runtime/utils/utils.cmake)
include (../../runtime/vmcore-wasm/vmcore.cmake)
include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)
include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake)
include (${SHARED_LIB_DIR}/utils/shared_utils.cmake)
add_library (vmlib
${WASM_PLATFORM_LIB_SOURCE}
${WASM_UTILS_LIB_SOURCE}
${VMCORE_LIB_SOURCE}
${WASM_LIB_BASE_DIR}/base_lib_export.c
${WASM_LIBC_SOURCE}
${PLATFORM_SHARED_SOURCE}
${MEM_ALLOC_SHARED_SOURCE}
${UTILS_SHARED_SOURCE})
add_executable (iwasm main.c ext_lib_export.c)
install (TARGETS iwasm DESTINATION bin)
target_link_libraries (iwasm vmlib -lm -ldl -lpthread)
add_library (libiwasm SHARED
${WASM_PLATFORM_LIB_SOURCE}
${WASM_UTILS_LIB_SOURCE}
${VMCORE_LIB_SOURCE}
${WASM_LIB_BASE_DIR}/base_lib_export.c
${WASM_LIBC_SOURCE}
${PLATFORM_SHARED_SOURCE}
${MEM_ALLOC_SHARED_SOURCE}
${UTILS_SHARED_SOURCE}
ext_lib_export.c)
install (TARGETS libiwasm DESTINATION lib)
set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm)
target_link_libraries (libiwasm -lm -ldl -lpthread)

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] = { };
#include "ext_lib_export.h"

View File

@ -0,0 +1,251 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "bh_platform.h"
#include "wasm_application.h"
#include "wasm_assert.h"
#include "wasm_log.h"
#include "wasm_platform_log.h"
#include "wasm_thread.h"
#include "wasm_export.h"
#include "wasm_memory.h"
#include "bh_memory.h"
static int app_argc;
static char **app_argv;
static int print_help()
{
wasm_printf("Usage: iwasm [-options] wasm_file [args...]\n");
wasm_printf("options:\n");
wasm_printf(" -f|--function name Specify function name to run in module\n"
" rather than main\n");
#if WASM_ENABLE_LOG != 0
wasm_printf(" -v=X Set log verbose level (0 to 2, default is 1),\n"
" larger level with more log\n");
#endif
wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n"
" that runs commands in the form of `FUNC ARG...`\n");
return 1;
}
static void*
app_instance_main(wasm_module_inst_t module_inst)
{
const char *exception;
wasm_application_execute_main(module_inst, app_argc, app_argv);
if ((exception = wasm_runtime_get_exception(module_inst)))
wasm_printf("%s\n", exception);
return NULL;
}
static void*
app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
{
const char *exception;
wasm_application_execute_func(module_inst, func_name, app_argc - 1,
app_argv + 1);
if ((exception = wasm_runtime_get_exception(module_inst)))
wasm_printf("%s\n", exception);
return NULL;
}
/**
* Split a space separated strings into an array of strings
* Returns NULL on failure
* Memory must be freed by caller
* Based on: http://stackoverflow.com/a/11198630/471795
*/
static char **
split_string(char *str, int *count)
{
char **res = NULL;
char *p;
int idx = 0;
/* split string and append tokens to 'res' */
do {
p = strtok(str, " ");
str = NULL;
res = (char**) realloc(res, sizeof(char*) * (idx + 1));
if (res == NULL) {
return NULL;
}
res[idx++] = p;
} while (p);
if (count) {
*count = idx - 1;
}
return res;
}
static void*
app_instance_repl(wasm_module_inst_t module_inst)
{
char *cmd = NULL;
size_t len = 0;
ssize_t n;
while ((wasm_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) {
wasm_assert(n > 0);
if (cmd[n - 1] == '\n') {
if (n == 1)
continue;
else
cmd[n - 1] = '\0';
}
app_argv = split_string(cmd, &app_argc);
if (app_argv == NULL) {
LOG_ERROR("Wasm prepare param failed: split string failed.\n");
break;
}
if (app_argc != 0) {
wasm_application_execute_func(module_inst, app_argv[0],
app_argc - 1, app_argv + 1);
}
free(app_argv);
}
free(cmd);
return NULL;
}
#define USE_GLOBAL_HEAP_BUF 0
#if USE_GLOBAL_HEAP_BUF != 0
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
#endif
int main(int argc, char *argv[])
{
char *wasm_file = NULL;
const char *func_name = NULL;
uint8 *wasm_file_buf = NULL;
int wasm_file_size;
wasm_module_t wasm_module = NULL;
wasm_module_inst_t wasm_module_inst = NULL;
char error_buf[128];
#if WASM_ENABLE_LOG != 0
int log_verbose_level = 1;
#endif
bool is_repl_mode = false;
/* Process options. */
for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) {
argc--, argv++;
if (argc < 2) {
print_help();
return 0;
}
func_name = argv[0];
}
#if WASM_ENABLE_LOG != 0
else if (!strncmp(argv[0], "-v=", 3)) {
log_verbose_level = atoi(argv[0] + 3);
if (log_verbose_level < 0 || log_verbose_level > 2)
return print_help();
}
#endif
else if (!strcmp(argv[0], "--repl"))
is_repl_mode = true;
else
return print_help();
}
if (argc == 0)
return print_help();
wasm_file = argv[0];
app_argc = argc;
app_argv = argv;
#if USE_GLOBAL_HEAP_BUF != 0
if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf))
!= 0) {
wasm_printf("Init memory with global heap buffer failed.\n");
return -1;
}
#else
if (bh_memory_init_with_allocator(malloc, free)) {
wasm_printf("Init memory with memory allocator failed.\n");
return -1;
}
#endif
/* initialize runtime environment */
if (!wasm_runtime_init())
goto fail1;
wasm_log_set_verbose_level(log_verbose_level);
/* load WASM byte buffer from WASM bin file */
if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file,
&wasm_file_size)))
goto fail2;
/* load WASM module */
if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
error_buf, sizeof(error_buf)))) {
wasm_printf("%s\n", error_buf);
goto fail3;
}
/* instantiate the module */
if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module,
64 * 1024, /* stack size */
64 * 1024, /* heap size */
error_buf,
sizeof(error_buf)))) {
wasm_printf("%s\n", error_buf);
goto fail4;
}
if (is_repl_mode)
app_instance_repl(wasm_module_inst);
else if (func_name)
app_instance_func(wasm_module_inst, func_name);
else
app_instance_main(wasm_module_inst);
/* destroy the module instance */
wasm_runtime_deinstantiate(wasm_module_inst);
fail4:
/* unload the module */
wasm_runtime_unload(wasm_module);
fail3:
/* free the file buffer */
wasm_free(wasm_file_buf);
fail2:
/* destroy runtime environment */
wasm_runtime_destroy();
fail1:
bh_memory_destroy();
return 0;
}

View File

@ -0,0 +1,90 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required (VERSION 2.8)
project (iwasm)
set (PLATFORM "linux-sgx")
# Reset default linker flags
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
add_definitions(-DUSE_SGX=1)
add_definitions(-DOPS_INPUT_OUTPUT=1)
add_definitions(-DOPS_UNSAFE_BUFFERS=0)
add_definitions(-DWASM_ENABLE_LOG=0)
add_definitions(-Dbh_printf=bh_printf_sgx)
# Enable repl mode if want to test spec cases
# add_definitions(-DWASM_ENABLE_REPL)
if (NOT ("$ENV{VALGRIND}" STREQUAL "YES"))
add_definitions(-DNVALGRIND)
endif ()
# Currently build as 64-bit by default.
set (BUILD_AS_64BIT_SUPPORT "YES")
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES")
# Add -fPIC flag if build as 64-bit
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
else ()
add_definitions (-m32)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
endif ()
endif ()
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif (NOT CMAKE_BUILD_TYPE)
message ("CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE})
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic")
set (SHARED_LIB_DIR ../../../shared-lib)
include_directories (.
../../runtime/include
../../runtime/platform/include
${SHARED_LIB_DIR}/include
$ENV{SGX_SDK}/include)
enable_language (ASM)
include (../../runtime/platform/${PLATFORM}/platform.cmake)
include (../../runtime/utils/utils.cmake)
include (../../runtime/vmcore-wasm/vmcore.cmake)
include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)
include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake)
include (${SHARED_LIB_DIR}/utils/shared_utils.cmake)
add_library (vmlib
${WASM_PLATFORM_LIB_SOURCE}
${WASM_UTILS_LIB_SOURCE}
${VMCORE_LIB_SOURCE}
${WASM_LIB_BASE_DIR}/base_lib_export.c
${WASM_LIBC_SOURCE}
${PLATFORM_SHARED_SOURCE}
${MEM_ALLOC_SHARED_SOURCE}
${UTILS_SHARED_SOURCE})
add_library (extlib ext_lib_export.c)

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] = { };
#include "ext_lib_export.h"

View File

@ -68,6 +68,7 @@ include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)
include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake)
include (${SHARED_LIB_DIR}/utils/shared_utils.cmake)
add_library (vmlib
${WASM_PLATFORM_LIB_SOURCE}
@ -76,7 +77,8 @@ add_library (vmlib
${WASM_LIB_BASE_DIR}/base_lib_export.c
${WASM_LIBC_SOURCE}
${PLATFORM_SHARED_SOURCE}
${MEM_ALLOC_SHARED_SOURCE})
${MEM_ALLOC_SHARED_SOURCE}
${UTILS_SHARED_SOURCE})
add_executable (iwasm main.c ext_lib_export.c)
@ -91,7 +93,8 @@ add_library (libiwasm SHARED
${WASM_LIB_BASE_DIR}/base_lib_export.c
${WASM_LIBC_SOURCE}
${PLATFORM_SHARED_SOURCE}
${MEM_ALLOC_SHARED_SOURCE})
${MEM_ALLOC_SHARED_SOURCE}
${UTILS_SHARED_SOURCE})
install (TARGETS libiwasm DESTINATION lib)

View File

@ -46,6 +46,35 @@ static int print_help()
return 1;
}
/**
* Find the unique main function from a WASM module instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the main function is called, false otherwise.
*/
bool
wasm_application_execute_main(wasm_module_inst_t module_inst,
int argc, char *argv[]);
/**
* Find the specified function in argv[0] from WASM module of current instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param name the name of the function to execute
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the specified function is called, false otherwise.
*/
bool
wasm_application_execute_func(wasm_module_inst_t module_inst,
const char *name, int argc, char *argv[]);
static void*
app_instance_main(wasm_module_inst_t module_inst)
{
@ -129,7 +158,11 @@ app_instance_repl(wasm_module_inst_t module_inst)
return NULL;
}
static char global_heap_buf[512 * 1024] = { 0 };
#define USE_GLOBAL_HEAP_BUF 0
#if USE_GLOBAL_HEAP_BUF != 0
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
#endif
int main(int argc, char *argv[])
{
@ -175,11 +208,18 @@ int main(int argc, char *argv[])
app_argc = argc;
app_argv = argv;
#if USE_GLOBAL_HEAP_BUF != 0
if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf))
!= 0) {
wasm_printf("Init global heap failed.\n");
wasm_printf("Init memory with global heap buffer failed.\n");
return -1;
}
#else
if (bh_memory_init_with_allocator(malloc, free)) {
wasm_printf("Init memory with memory allocator failed.\n");
return -1;
}
#endif
/* initialize runtime environment */
if (!wasm_runtime_init())
@ -201,8 +241,8 @@ int main(int argc, char *argv[])
/* instantiate the module */
if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module,
16 * 1024, /* stack size */
8 * 1024, /* heap size */
64 * 1024, /* stack size */
64 * 1024, /* heap size */
error_buf,
sizeof(error_buf)))) {
wasm_printf("%s\n", error_buf);

View File

@ -46,6 +46,35 @@ static int print_help()
return 1;
}
/**
* Find the unique main function from a WASM module instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the main function is called, false otherwise.
*/
bool
wasm_application_execute_main(wasm_module_inst_t module_inst,
int argc, char *argv[]);
/**
* Find the specified function in argv[0] from WASM module of current instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param name the name of the function to execute
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the specified function is called, false otherwise.
*/
bool
wasm_application_execute_func(wasm_module_inst_t module_inst,
const char *name, int argc, char *argv[]);
static void*
app_instance_main(wasm_module_inst_t module_inst)
{

View File

@ -26,9 +26,28 @@
#include "bh_memory.h"
#include "test_wasm.h"
#define CONFIG_GLOBAL_HEAP_BUF_SIZE 131072
#define CONFIG_APP_STACK_SIZE 8192
#define CONFIG_APP_HEAP_SIZE 8192
#define CONFIG_MAIN_THREAD_STACK_SIZE 4096
static int app_argc;
static char **app_argv;
/**
* Find the unique main function from a WASM module instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the main function is called, false otherwise.
*/
bool
wasm_application_execute_main(wasm_module_inst_t module_inst,
int argc, char *argv[]);
static void*
app_instance_main(wasm_module_inst_t module_inst)
{
@ -40,7 +59,7 @@ app_instance_main(wasm_module_inst_t module_inst)
return NULL;
}
static char global_heap_buf[512 * 1024] = { 0 };
static char global_heap_buf[CONFIG_GLOBAL_HEAP_BUF_SIZE] = { 0 };
void iwasm_main(void *arg1, void *arg2, void *arg3)
{
@ -58,7 +77,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3)
(void) arg3;
if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf))
!= 0) {
!= 0) {
wasm_printf("Init global heap failed.\n");
return;
}
@ -77,14 +96,17 @@ void iwasm_main(void *arg1, void *arg2, void *arg3)
/* load WASM module */
if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
error_buf, sizeof(error_buf)))) {
error_buf, sizeof(error_buf)))) {
wasm_printf("%s\n", error_buf);
goto fail2;
}
/* instantiate the module */
if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024,
8 * 1024, error_buf, sizeof(error_buf)))) {
if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module,
CONFIG_APP_STACK_SIZE,
CONFIG_APP_HEAP_SIZE,
error_buf,
sizeof(error_buf)))) {
wasm_printf("%s\n", error_buf);
goto fail3;
}
@ -105,24 +127,23 @@ void iwasm_main(void *arg1, void *arg2, void *arg3)
fail1: bh_memory_destroy();
}
#define DEFAULT_THREAD_STACKSIZE (6 * 1024)
#define DEFAULT_THREAD_PRIORITY 5
#define MAIN_THREAD_STACK_SIZE (CONFIG_MAIN_THREAD_STACK_SIZE)
#define MAIN_THREAD_PRIORITY 5
K_THREAD_STACK_DEFINE(iwasm_main_thread_stack, DEFAULT_THREAD_STACKSIZE);
K_THREAD_STACK_DEFINE(iwasm_main_thread_stack, MAIN_THREAD_STACK_SIZE);
static struct k_thread iwasm_main_thread;
bool iwasm_init(void)
{
k_tid_t tid = k_thread_create(&iwasm_main_thread, iwasm_main_thread_stack,
DEFAULT_THREAD_STACKSIZE, iwasm_main, NULL, NULL, NULL,
DEFAULT_THREAD_PRIORITY, 0, K_NO_WAIT);
MAIN_THREAD_STACK_SIZE,
iwasm_main, NULL, NULL, NULL,
MAIN_THREAD_PRIORITY, 0, K_NO_WAIT);
return tid ? true : false;
}
#ifndef CONFIG_AEE_ENABLE
void main(void)
{
iwasm_init();
}
#endif

View File

@ -0,0 +1,110 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BH_MEMORY_H
#define _BH_MEMORY_H
#ifdef __cplusplus
extern "C" {
#endif
#define BH_KB (1024)
#define BH_MB ((BH_KB)*1024)
#define BH_GB ((BH_MB)*1024)
/**
* Initialize memory allocator with a pool, the bh_malloc/bh_free function
* will malloc/free memory from the pool
*
* @param mem the pool buffer
* @param bytes the size bytes of the buffer
*
* @return 0 if success, -1 otherwise
*/
int bh_memory_init_with_pool(void *mem, unsigned int bytes);
/**
* Initialize memory allocator with memory allocator, the bh_malloc/bh_free
* function will malloc/free memory with the allocator passed
*
* @param malloc_func the malloc function
* @param free_func the free function
*
* @return 0 if success, -1 otherwise
*/
int bh_memory_init_with_allocator(void *malloc_func, void *free_func);
/**
* Destroy memory
*/
void bh_memory_destroy();
/**
* Get the pool size of memory, if memory is initialized with allocator,
* return 1GB by default.
*/
int bh_memory_pool_size();
#if BEIHAI_ENABLE_MEMORY_PROFILING == 0
/**
* This function allocates a memory chunk from system
*
* @param size bytes need allocate
*
* @return the pointer to memory allocated
*/
void* bh_malloc(unsigned int size);
/**
* This function frees memory chunk
*
* @param ptr the pointer to memory need free
*/
void bh_free(void *ptr);
#else
void* bh_malloc_profile(const char *file, int line, const char *func, unsigned int size);
void bh_free_profile(const char *file, int line, const char *func, void *ptr);
#define bh_malloc(size) bh_malloc_profile(__FILE__, __LINE__, __func__, size)
#define bh_free(ptr) bh_free_profile(__FILE__, __LINE__, __func__, ptr)
/**
* Print current memory profiling data
*
* @param file file name of the caller
* @param line line of the file of the caller
* @param func function name of the caller
*/
void memory_profile_print(const char *file, int line, const char *func, int alloc);
/**
* Summarize memory usage and print it out
* Can use awk to analyze the output like below:
* awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1
*/
void memory_usage_summarize();
#endif
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _BH_MEMORY_H */

View File

@ -40,7 +40,13 @@ int
get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
/**
* Get the exported APIs of extend lib
* Get the exported APIs of extended lib, this API isn't provided by WASM VM,
* it must be provided by developer to register the extended native APIs,
* for example, developer can register his native APIs to extended_native_symbol_defs,
* array, and include file ext_lib_export.h which implements this API.
* And if developer hasn't any native API to register, he can define an empty
* extended_native_symbol_defs array, and then include file ext_lib_export.h to
* implements this API.
*
* @param p_base_lib_apis return the exported API array of extend lib
*

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2019 Taobao (China) Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _WASM_APPLICATION_H
#define _WASM_APPLICATION_H
//#include "wasm_runtime.h"
#ifdef __cplusplus
extern "C" {
#endif
struct WASMModuleInstance;
/**
* Find the unique main function from a WASM module instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the main function is called, false otherwise and exception will be thrown,
* the caller can call wasm_runtime_get_exception to get exception info.
*/
bool
wasm_application_execute_main(struct WASMModuleInstance *module_inst,
int argc, char *argv[]);
/**
* Find the specified function in argv[0] from a WASM module instance
* and execute that function.
*
* @param module_inst the WASM module instance
* @param name the name of the function to execute
* @param argc the number of arguments
* @param argv the arguments array
*
* @return true if the specified function is called, false otherwise and exception will be thrown,
* the caller can call wasm_runtime_get_exception to get exception info.
*/
bool
wasm_application_execute_func(struct WASMModuleInstance *module_inst,
char *name, int argc, char *argv[]);
#ifdef __cplusplus
}
#endif
#endif /* end of _WASM_APPLICATION_H */

View File

@ -152,6 +152,13 @@ wasm_runtime_instantiate(const wasm_module_t module,
void
wasm_runtime_deinstantiate(wasm_module_inst_t module_inst);
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
bool
wasm_runtime_set_ext_memory(wasm_module_inst_t module_inst,
uint8_t *ext_mem_data, uint32_t ext_mem_size,
char *error_buf, uint32_t error_buf_size);
#endif
/**
* Load WASM module instance from AOT file.
*
@ -385,34 +392,36 @@ wasm_runtime_addr_native_to_app(wasm_module_inst_t module_inst,
void *native_ptr);
/**
* Find the unique main function from a WASM module instance
* and execute that function.
* Get the app address range (relative address) that a app address belongs to
*
* @param module_inst the WASM module instance
* @param argc the number of arguments
* @param argv the arguments array
* @param app_offset the app address to retrieve
* @param p_app_start_offset buffer to output the app start offset if not NULL
* @param p_app_end_offset buffer to output the app end offset if not NULL
*
* @return true if the main function is called, false otherwise.
* @return true if success, false otherwise.
*/
bool
wasm_application_execute_main(wasm_module_inst_t module_inst,
int argc, char *argv[]);
wasm_runtime_get_app_addr_range(wasm_module_inst_t module_inst,
int32_t app_offset,
int32_t *p_app_start_offset,
int32_t *p_app_end_offset);
/**
* Find the specified function in argv[0] from WASM module of current instance
* and execute that function.
* Get the native address range (absolute address) that a native address belongs to
*
* @param module_inst the WASM module instance
* @param name the name of the function to execute
* @param argc the number of arguments
* @param argv the arguments array
* @param native_ptr the native address to retrieve
* @param p_native_start_addr buffer to output the native start address if not NULL
* @param p_native_end_addr buffer to output the native end address if not NULL
*
* @return true if the specified function is called, false otherwise.
* @return true if success, false otherwise.
*/
bool
wasm_application_execute_func(wasm_module_inst_t module_inst,
const char *name, int argc, char *argv[]);
wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
uint8_t *native_ptr,
uint8_t **p_native_start_addr,
uint8_t **p_native_end_addr);
#ifdef __cplusplus
}

View File

@ -0,0 +1,25 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L)
set (PLATFORM_LIB_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${PLATFORM_LIB_DIR})
include_directories(${PLATFORM_LIB_DIR}/../include)
file (GLOB_RECURSE source_all ${PLATFORM_LIB_DIR}/*.c)
set (WASM_PLATFORM_LIB_SOURCE ${source_all})

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "wasm_native.h"
void*
wasm_platform_native_func_lookup(const char *module_name,
const char *func_name)
{
return NULL;
}

View File

@ -17,7 +17,9 @@
#ifndef _WASM_PLATFORM_LOG
#define _WASM_PLATFORM_LOG
#define wasm_printf printf
#include "bh_platform.h"
#define wasm_printf bh_printf
#define wasm_vprintf vprintf

View File

@ -0,0 +1,25 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199309L)
set (PLATFORM_LIB_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${PLATFORM_LIB_DIR})
include_directories(${PLATFORM_LIB_DIR}/../include)
file (GLOB_RECURSE source_all ${PLATFORM_LIB_DIR}/*.c)
set (WASM_PLATFORM_LIB_SOURCE ${source_all})

View File

@ -0,0 +1,336 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* for O_DIRECT */
#endif
#include "wasm_native.h"
#include "wasm_runtime.h"
#include "wasm_log.h"
#include "wasm_memory.h"
#include "wasm_platform_log.h"
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <fcntl.h>
#include <errno.h>
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, 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_free(offset) \
wasm_runtime_module_free(module_inst, offset)
static int32
__syscall0_wrapper(WASMModuleInstance *module_inst, int32 arg0)
{
switch (arg0) {
case 199: /* getuid */
/* TODO */
default:
bh_printf("##_syscall0 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall1_wrapper(WASMModuleInstance *module_inst, int32 arg0, int32 arg1)
{
switch (arg0) {
case 6: /* close */
/* TODO */
default:
bh_printf("##_syscall1 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall2_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2)
{
switch (arg0) {
case 183: /* getcwd */
/* TODO */
default:
bh_printf("##_syscall2 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall3_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2, int32 arg3)
{
switch (arg0) {
case 146: /* writev */
{
/* Implement syscall 54 and syscall 146 to support printf()
for non SIDE_MODULE=1 mode */
struct iovec_app {
int32 iov_base_offset;
uint32 iov_len;
} *vec;
int32 vec_offset = arg2, str_offset;
uint32 iov_count = arg3, i;
int32 count = 0;
char *iov_base, *str;
if (!validate_app_addr(vec_offset, sizeof(struct iovec_app)))
return 0;
vec = (struct iovec_app *)addr_app_to_native(vec_offset);
for (i = 0; i < iov_count; i++, vec++) {
if (vec->iov_len > 0) {
if (!validate_app_addr(vec->iov_base_offset, 1))
return 0;
iov_base = (char*)addr_app_to_native(vec->iov_base_offset);
if (!(str_offset = module_malloc(vec->iov_len + 1)))
return 0;
str = addr_app_to_native(str_offset);
memcpy(str, iov_base, vec->iov_len);
str[vec->iov_len] = '\0';
count += wasm_printf("%s", str);
module_free(str_offset);
}
}
return count;
}
case 145: /* readv */
case 3: /* read*/
case 5: /* open */
case 221: /* fcntl */
/* TODO */
default:
bh_printf("##_syscall3 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall4_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4)
{
bh_printf("##_syscall4 called, syscall id: %d\n", arg0);
return 0;
}
static int32
__syscall5_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4, int32 arg5)
{
switch (arg0) {
case 140: /* llseek */
/* TODO */
default:
bh_printf("##_syscall5 called, args[0]: %d\n", arg0);
}
return 0;
}
#define GET_EMCC_SYSCALL_ARGS() \
int32 *args; \
if (!validate_app_addr(args_off, 1)) \
return 0; \
args = addr_app_to_native(args_off) \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id) { \
return __syscall0_wrapper(module_inst, id); \
}
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(module_inst, id, args[0]); \
}
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off){ \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(module_inst, id, args[0], args[1]); \
}
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(module_inst, id, \
args[0], args[1], args[2]); \
}
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(module_inst, id, \
args[0], args[1], args[2], args[3]); \
}
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(module_inst, id, \
args[0], args[1], args[2], \
args[3], args[4]); \
}
EMCC_SYSCALL_WRAPPER0(199)
EMCC_SYSCALL_WRAPPER1(6)
EMCC_SYSCALL_WRAPPER2(183)
EMCC_SYSCALL_WRAPPER3(3)
EMCC_SYSCALL_WRAPPER3(5)
EMCC_SYSCALL_WRAPPER3(54)
EMCC_SYSCALL_WRAPPER3(145)
EMCC_SYSCALL_WRAPPER3(146)
EMCC_SYSCALL_WRAPPER3(221)
EMCC_SYSCALL_WRAPPER5(140)
static int32
getTotalMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMMemoryInstance *memory = module_inst->default_memory;
return NumBytesPerPage * memory->cur_page_count;
}
static int32
enlargeMemory_wrapper(WASMModuleInstance *module_inst)
{
bool ret;
WASMMemoryInstance *memory = module_inst->default_memory;
uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
uint32 *DYNAMICTOP_PTR = (uint32*)(memory->memory_data + addr_data_offset);
uint32 memory_size_expected = *DYNAMICTOP_PTR;
uint32 total_page_count = (memory_size_expected + NumBytesPerPage - 1) / NumBytesPerPage;
if (total_page_count < memory->cur_page_count) {
return 1;
}
else {
ret = wasm_runtime_enlarge_memory(module_inst, total_page_count -
memory->cur_page_count);
return ret ? 1 : 0;
}
}
static void
_abort_wrapper(WASMModuleInstance *module_inst, int32 code)
{
char buf[32];
snprintf(buf, sizeof(buf), "env.abort(%i)", code);
wasm_runtime_set_exception(module_inst, buf);
}
static void
abortOnCannotGrowMemory_wrapper(WASMModuleInstance *module_inst)
{
wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
}
static void
___setErrNo_wrapper(WASMModuleInstance *module_inst, int32 error_no)
{
errno = error_no;
}
/* TODO: add function parameter/result types check */
#define REG_NATIVE_FUNC(module_name, func_name) \
{#module_name, #func_name, func_name##_wrapper}
typedef struct WASMNativeFuncDef {
const char *module_name;
const char *func_name;
void *func_ptr;
} WASMNativeFuncDef;
static WASMNativeFuncDef native_func_defs[] = {
REG_NATIVE_FUNC(env, __syscall0),
REG_NATIVE_FUNC(env, __syscall1),
REG_NATIVE_FUNC(env, __syscall2),
REG_NATIVE_FUNC(env, __syscall3),
REG_NATIVE_FUNC(env, __syscall4),
REG_NATIVE_FUNC(env, __syscall5),
REG_NATIVE_FUNC(env, ___syscall3),
REG_NATIVE_FUNC(env, ___syscall5),
REG_NATIVE_FUNC(env, ___syscall6),
REG_NATIVE_FUNC(env, ___syscall54),
REG_NATIVE_FUNC(env, ___syscall140),
REG_NATIVE_FUNC(env, ___syscall145),
REG_NATIVE_FUNC(env, ___syscall146),
REG_NATIVE_FUNC(env, ___syscall183),
REG_NATIVE_FUNC(env, ___syscall199),
REG_NATIVE_FUNC(env, ___syscall221),
REG_NATIVE_FUNC(env, _abort),
REG_NATIVE_FUNC(env, abortOnCannotGrowMemory),
REG_NATIVE_FUNC(env, enlargeMemory),
REG_NATIVE_FUNC(env, getTotalMemory),
REG_NATIVE_FUNC(env, ___setErrNo),
};
void*
wasm_platform_native_func_lookup(const char *module_name,
const char *func_name)
{
uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef);
WASMNativeFuncDef *func_def = native_func_defs;
WASMNativeFuncDef *func_def_end = func_def + size;
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;
}

View File

@ -35,9 +35,6 @@
#include <errno.h>
#define get_module_inst() \
wasm_runtime_get_current_module_inst()
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, size)
@ -55,46 +52,46 @@
static int32
__syscall0_wrapper(int32 arg0)
__syscall0_wrapper(WASMModuleInstance *module_inst, int32 arg0)
{
switch (arg0) {
case 199: /* getuid */
/* TODO */
default:
printf("##_syscall0 called, syscall id: %d\n", arg0);
bh_printf("##_syscall0 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall1_wrapper(int32 arg0, int32 arg1)
__syscall1_wrapper(WASMModuleInstance *module_inst, int32 arg0, int32 arg1)
{
switch (arg0) {
case 6: /* close */
/* TODO */
default:
printf("##_syscall1 called, syscall id: %d\n", arg0);
bh_printf("##_syscall1 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall2_wrapper(int32 arg0, int32 arg1, int32 arg2)
__syscall2_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2)
{
switch (arg0) {
case 183: /* getcwd */
/* TODO */
default:
printf("##_syscall2 called, syscall id: %d\n", arg0);
bh_printf("##_syscall2 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
__syscall3_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2, int32 arg3)
{
WASMModuleInstance *module_inst = get_module_inst();
switch (arg0) {
case 54: /* ioctl */
{
@ -152,73 +149,83 @@ __syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
case 221: /* fcntl */
/* TODO */
default:
printf("##_syscall3 called, syscall id: %d\n", arg0);
bh_printf("##_syscall3 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
__syscall4_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4)
{
printf("##_syscall4 called, syscall id: %d\n", arg0);
bh_printf("##_syscall4 called, syscall id: %d\n", arg0);
return 0;
}
static int32
__syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
__syscall5_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4, int32 arg5)
{
switch (arg0) {
case 140: /* llseek */
/* TODO */
default:
printf("##_syscall5 called, args[0]: %d\n", arg0);
bh_printf("##_syscall5 called, args[0]: %d\n", arg0);
}
return 0;
}
#define GET_EMCC_SYSCALL_ARGS() \
WASMModuleInstance *module_inst = get_module_inst(); \
int32 *args; \
if (!validate_app_addr(args_off, 1)) \
return 0; \
args = addr_app_to_native(args_off) \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(int32 _id) { \
return __syscall0_wrapper(id); \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id) { \
return __syscall0_wrapper(module_inst, id); \
}
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(id, args[0]); \
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(module_inst, id, args[0]); \
}
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(id, args[0], args[1]); \
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off){ \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(module_inst, id, args[0], args[1]); \
}
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(id, args[0], args[1], args[2]); \
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(module_inst, id, \
args[0], args[1], args[2]); \
}
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(id, args[0], args[1], args[2], args[3]);\
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(module_inst, id, \
args[0], args[1], args[2], args[3]); \
}
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(id, args[0], args[1], args[2], \
args[3], args[4]); \
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(module_inst, id, \
args[0], args[1], args[2], \
args[3], args[4]); \
}
EMCC_SYSCALL_WRAPPER0(199)
@ -237,18 +244,16 @@ EMCC_SYSCALL_WRAPPER3(221)
EMCC_SYSCALL_WRAPPER5(140)
static int32
getTotalMemory_wrapper()
getTotalMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
WASMMemoryInstance *memory = module_inst->default_memory;
return NumBytesPerPage * memory->cur_page_count;
}
static int32
enlargeMemory_wrapper()
enlargeMemory_wrapper(WASMModuleInstance *module_inst)
{
bool ret;
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
WASMMemoryInstance *memory = module_inst->default_memory;
uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
@ -267,9 +272,8 @@ enlargeMemory_wrapper()
}
static void
_abort_wrapper(int32 code)
_abort_wrapper(WASMModuleInstance *module_inst, int32 code)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
char buf[32];
snprintf(buf, sizeof(buf), "env.abort(%i)", code);
@ -277,14 +281,13 @@ _abort_wrapper(int32 code)
}
static void
abortOnCannotGrowMemory_wrapper()
abortOnCannotGrowMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
}
static void
___setErrNo_wrapper(int32 error_no)
___setErrNo_wrapper(WASMModuleInstance *module_inst, int32 error_no)
{
errno = error_no;
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.text
.align 2
.global invokeNative
.type invokeNative,function
/*
* Arguments passed in:
*
* r0 argv
* r1 argc
* r2 function pntr
*/
invokeNative:
stmfd sp!, {r4, r5, r6, r7, lr}
mov r4, r0 /* get argv */
mov r5, r1 /* get argc */
mov ip, r2 /* get function ptr */
cmp r5, #2 /* is argc < 2 ? */
blt return
ldr r0, [r4], #4 /* argv[0] */
ldr r1, [r4], #4 /* argv[1] */
mov r6, #0
cmp r5, #2
beq call_func
ldr r2, [r4], #4
cmp r5, #3
beq call_func
ldr r3, [r4], #4
subs r5, r5, #4 /* now we have r0 ~ r3 */
/* Ensure address is 8 byte aligned */
mov r6, r5, lsl#2
add r6, r6, #7
bic r6, r6, #7
add r6, r6, #4 /* +4 because only odd(5) registers are in stack */
subs sp, sp, r6 /* for stacked args */
mov r7, sp
loop_args:
cmp r5, #0
beq call_func
ldr lr, [r4], #4
str lr, [r7], #4
subs r5, r5, #1
b loop_args
call_func:
blx ip
add sp, sp, r6 /* recover sp */
return:
ldmfd sp!, {r4, r5, r6, r7, lr}
bx lr

View File

@ -0,0 +1,72 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Ivan Volosyuk
//
.text
.align 2
.globl invokeNative
.type invokeNative, @function
invokeNative:
/* rdi - memory */
/* rsi - n fp args */
/* rdx - n mem args */
/* rcx - function ptr */
push %rbp
mov %rsp, %rbp
/* cycle to fill all fp args */
movq 8(%rdi), %xmm0
movq 16(%rdi), %xmm1
movq 24(%rdi), %xmm2
movq 32(%rdi), %xmm3
movq 40(%rdi), %xmm4
movq 48(%rdi), %xmm5
movq 56(%rdi), %xmm6
movq 64(%rdi), %xmm7
mov %rsp, %r10 /* Check that stack is aligned on */
and $8, %r10 /* 16 bytes. This code may be removed */
jz no_abort /* when we are sure that compiler always */
int3 /* calls us with aligned stack */
no_abort:
mov %rdx, %r10 /* Align stack on 16 bytes before pushing */
and $1, %r10 /* stack arguments in case we have an odd */
shl $3, %r10 /* number of stack arguments */
sub %r10, %rsp
/* store memory args */
movq %rcx, %r10 /* func ptr */
movq %rdx, %rcx /* counter */
lea 8+64+48-8(%rdi,%rcx,8), %rdx
sub %rsp, %rdx
cmpq $0, %rcx
jz cycle_end
cycle:
push 0(%rsp,%rdx)
loop cycle
cycle_end:
movq 80(%rdi), %rsi
movq 88(%rdi), %rdx
movq 96(%rdi), %rcx
movq 104(%rdi), %r8
movq 112(%rdi), %r9
movq 72(%rdi), %rdi
call *%r10
leave
ret

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.text
.align 2
.globl invokeNative
.ent invokeNative
.type invokeNative, @function
/**
* On function entry parameters:
* $4 = args
* $5 = arg_num
* $6 = func_ptr
*/
invokeNative:
.frame $fp, 8, $0
.mask 0x00000000, 0
.fmask 0x00000000, 0
/* Fixed part of frame */
subu $sp, 8
/* save registers */
sw $31, 4($sp)
sw $fp, 0($sp)
/* set frame pointer to bottom of fixed frame */
move $fp, $sp
/* allocate enough stack space */
sll $11, $5, 2
subu $sp, $11
/* make 8-byte aligned */
and $sp, ~7
move $9, $sp
move $25, $6 /* $25 = func_ptr */
push_args:
beq $5, 0, done /* arg_num == 0 ? */
lw $8, 0($4)
sw $8, 0($9)
addu $4, 4
addu $9, 4
subu $5, 1 /* arg_index-- */
j push_args
done:
lw $4, 0($sp) /* Load $4..$7 from stack */
lw $5, 4($sp)
lw $6, 8($sp)
lw $7, 12($sp)
ldc1 $f12, 0($sp) /* Load $f12, $f13, $f14, $f15 */
ldc1 $f14, 8($sp)
jalr $25 /* call function */
nop
/* restore saved registers */
move $sp, $fp
lw $31, 4($sp)
lw $fp, 0($sp)
/* pop frame */
addu $sp, $sp, 8
j $31
.end invokeNative

View File

@ -17,11 +17,13 @@ set (VMCORE_LIB_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${VMCORE_LIB_DIR})
include_directories(${VMCORE_LIB_DIR}/../include)
file (GLOB_RECURSE c_source_all ${VMCORE_LIB_DIR}/*.c)
list (REMOVE_ITEM c_source_all ${VMCORE_LIB_DIR}/invokeNative_general.c)
if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES")
file (GLOB_RECURSE source_all ${VMCORE_LIB_DIR}/*.c)
set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_em64.s)
else ()
file (GLOB_RECURSE source_all ${VMCORE_LIB_DIR}/*.c ${VMCORE_LIB_DIR}/*.s)
list (REMOVE_ITEM source_all ${VMCORE_LIB_DIR}/invokeNative_general.c)
set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_ia32.s)
endif ()
set (VMCORE_LIB_SOURCE ${source_all})

View File

@ -18,6 +18,7 @@
#include <stdlib.h>
#include <string.h>
#include "wasm.h"
#include "wasm_application.h"
#include "wasm_interp.h"
#include "wasm_runtime.h"
#include "wasm_thread.h"
@ -293,10 +294,15 @@ wasm_application_execute_func(WASMModuleInstance *module_inst,
break;
case VALUE_TYPE_I64:
{
char buf[16];
union { uint64 val; uint32 parts[2]; } u;
u.parts[0] = argv1[0];
u.parts[1] = argv1[1];
wasm_printf("0x%llx:i64", u.val);
if (sizeof(long) == 4)
snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
else
snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
wasm_printf(buf, u.val);
break;
}
case VALUE_TYPE_F32:

View File

@ -74,6 +74,24 @@ GET_F64_FROM_ADDR (uint32 *addr)
}
#endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
#define CHECK_EXT_MEMORY_SPACE() \
else if (module->ext_mem_data \
&& module->ext_mem_base_offset <= offset1 \
&& offset1 < module->ext_mem_base_offset \
+ module->ext_mem_size) { \
maddr = module->ext_mem_data \
+ (offset1 - module->ext_mem_base_offset); \
if (maddr < module->ext_mem_data) \
goto out_of_bounds; \
maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \
if (maddr1 > module->ext_mem_data_end) \
goto out_of_bounds; \
}
#else
#define CHECK_EXT_MEMORY_SPACE()
#endif
#define CHECK_MEMORY_OVERFLOW() do { \
uint32 offset1 = offset + addr; \
uint8 *maddr1; \
@ -89,7 +107,8 @@ GET_F64_FROM_ADDR (uint32 *addr)
if (maddr1 > memory->end_addr) \
goto out_of_bounds; \
} \
else { \
else if (offset1 < memory->heap_base_offset \
+ (memory->heap_data_end - memory->heap_data)) { \
maddr = memory->heap_data + offset1 - memory->heap_base_offset; \
if (maddr < memory->heap_data) \
goto out_of_bounds; \
@ -97,6 +116,9 @@ GET_F64_FROM_ADDR (uint32 *addr)
if (maddr1 > memory->heap_data_end) \
goto out_of_bounds; \
} \
CHECK_EXT_MEMORY_SPACE() \
else \
goto out_of_bounds; \
} while (0)
static inline uint32
@ -262,7 +284,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
}
if (sign && (shift < maxbits) && (byte & 0x40)) {
/* Sign extend */
result |= - (1 << shift);
result |= - ((uint64)1 << shift);
}
return result;
}
@ -588,7 +610,7 @@ ALLOC_FRAME(WASMThread *self, uint32 size, WASMInterpFrame *prev_frame)
frame->prev_frame = prev_frame;
else {
wasm_runtime_set_exception(self->module_inst,
"WASM interp failed, alloc frame failed.");
"WASM interp failed: stack overflow.");
}
return frame;
@ -600,21 +622,6 @@ FREE_FRAME(WASMThread *self, WASMInterpFrame *frame)
wasm_thread_free_wasm_frame(self, frame);
}
typedef void (*GenericFunctionPointer)();
int64 invokeNative(uint32 *args, uint32 sz, GenericFunctionPointer f);
typedef float64 (*Float64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef float32 (*Float32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int64 (*Int64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int32 (*Int32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(uint32*, uint32, GenericFunctionPointer);
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
static void
wasm_interp_call_func_native(WASMThread *self,
WASMFunctionInstance *cur_func,
@ -622,9 +629,8 @@ wasm_interp_call_func_native(WASMThread *self,
{
unsigned local_cell_num = 2;
WASMInterpFrame *frame;
typedef void (*F)(WASMThread*, uint32 *argv);
union { F f; void *v; } u;
uint32 argv_buf[32], *argv, argc = cur_func->param_cell_num;
uint32 argv_ret[2];
bool ret;
if (!(frame = ALLOC_FRAME
(self, wasm_interp_interp_frame_size(local_cell_num), prev_frame)))
@ -636,60 +642,24 @@ wasm_interp_call_func_native(WASMThread *self,
wasm_thread_set_cur_frame (self, frame);
if (argc <= 32)
argv = argv_buf;
else {
if (!(argv = wasm_malloc(sizeof(uint32) * argc))) {
wasm_runtime_set_exception(self->module_inst,
"WASM call native failed: alloc memory for argv failed.");
return;
}
}
ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked,
cur_func->u.func_import->func_type,
self->module_inst,
frame->lp, cur_func->param_cell_num, argv_ret);
word_copy(argv, frame->lp, argc);
u.v = cur_func->u.func_import->func_ptr_linked;
{
WASMType *func_type = cur_func->u.func_import->func_type;
uint8 ret_type = func_type->result_count
? func_type->types[func_type->param_count]
: VALUE_TYPE_VOID;
GenericFunctionPointer f = (GenericFunctionPointer)(uintptr_t)u.v;
if (func_type->result_count == 0) {
invokeNative_Void(argv, argc, f);
}
else {
switch (ret_type) {
case VALUE_TYPE_I32:
argv[0] = invokeNative_Int32(argv, argc, f);
break;
case VALUE_TYPE_I64:
PUT_I64_TO_ADDR(argv, invokeNative_Int64(argv, argc, f));
break;
case VALUE_TYPE_F32:
*(float32*)argv = invokeNative_Float32(argv, argc, f);
break;
case VALUE_TYPE_F64:
PUT_F64_TO_ADDR(argv, invokeNative_Float64(argv, argc, f));
break;
}
}
}
if (!ret)
return;
if (cur_func->ret_cell_num == 1) {
prev_frame->sp[0] = argv[0];
prev_frame->sp[0] = argv_ret[0];
prev_frame->sp++;
}
else if (cur_func->ret_cell_num == 2) {
prev_frame->sp[0] = argv[0];
prev_frame->sp[1] = argv[1];
prev_frame->sp[0] = argv_ret[0];
prev_frame->sp[1] = argv_ret[1];
prev_frame->sp += 2;
}
if (argc > 32)
wasm_free(argv);
FREE_FRAME(self, frame);
wasm_thread_set_cur_frame(self, prev_frame);
}
@ -731,7 +701,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
uint32 i, depth, cond, count, fidx, tidx, frame_size = 0, all_cell_num = 0;
int32 didx, val;
uint8 *else_addr, *end_addr;
uint8 *maddr;
uint8 *maddr = NULL;
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
@ -768,7 +738,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
BLOCK_TYPE_BLOCK,
&else_addr, &end_addr,
NULL, 0)) {
wasm_runtime_set_exception(module, "find block addr failed");
wasm_runtime_set_exception(module, "find block address failed");
goto got_exception;
}
@ -783,7 +753,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
BLOCK_TYPE_LOOP,
&else_addr, &end_addr,
NULL, 0)) {
wasm_runtime_set_exception(module, "find block addr failed");
wasm_runtime_set_exception(module, "find block address failed");
goto got_exception;
}
@ -798,7 +768,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
BLOCK_TYPE_IF,
&else_addr, &end_addr,
NULL, 0)) {
wasm_runtime_set_exception(module, "find block addr failed");
wasm_runtime_set_exception(module, "find block address failed");
goto got_exception;
}
@ -855,8 +825,9 @@ wasm_interp_call_func_bytecode(WASMThread *self,
depths = depth_buf;
else {
if (!(depths = wasm_malloc(sizeof(uint32) * count))) {
wasm_runtime_set_exception(module, "WASM interp failed, "
"alloc block memory for br_table failed.");
wasm_runtime_set_exception(module,
"WASM interp failed: "
"allocate memory failed.");
goto got_exception;
}
}
@ -931,7 +902,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
HANDLE_OP (WASM_OP_DROP):
{
wasm_runtime_set_exception(module,
"wasm interp failed: unsupported opcode");
"WASM interp failed: unsupported opcode.");
goto got_exception;
}
@ -950,7 +921,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
HANDLE_OP (WASM_OP_SELECT):
{
wasm_runtime_set_exception(module,
"wasm interp failed: unsupported opcode");
"WASM interp failed: unsupported opcode.");
goto got_exception;
}
@ -997,7 +968,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
break;
default:
wasm_runtime_set_exception(module,
"get local type is invalid");
"invalid local type");
goto got_exception;
}
(void)local_count;
@ -1026,7 +997,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
break;
default:
wasm_runtime_set_exception(module,
"set local type is invalid");
"invalid local type");
goto got_exception;
}
(void)local_count;
@ -1054,7 +1025,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
SET_LOCAL_F64(local_idx, GET_F64_FROM_ADDR(frame_sp - 2));
break;
default:
wasm_runtime_set_exception(module, "tee local type is invalid");
wasm_runtime_set_exception(module, "invalid local type");
goto got_exception;
}
(void)local_count;
@ -1085,7 +1056,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
PUSH_F64(*(float64*)get_global_addr(memory, global));
break;
default:
wasm_runtime_set_exception(module, "get global type is invalid");
wasm_runtime_set_exception(module, "invalid global type");
goto got_exception;
}
HANDLE_OP_END ();
@ -1117,7 +1088,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
PUT_F64_TO_ADDR((uint32*)global_addr, POP_F64());
break;
default:
wasm_runtime_set_exception(module, "set global index is overflow");
wasm_runtime_set_exception(module, "invalid global type");
goto got_exception;
}
HANDLE_OP_END ();
@ -1125,70 +1096,98 @@ wasm_interp_call_func_bytecode(WASMThread *self,
/* memory load instructions */
HANDLE_OP (WASM_OP_I32_LOAD):
DEF_OP_LOAD(PUSH_I32(*(int32*)maddr));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD):
DEF_OP_LOAD(PUSH_I64(GET_I64_FROM_ADDR((uint32*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_F32_LOAD):
DEF_OP_LOAD(PUSH_F32(*(float32*)maddr));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_F64_LOAD):
DEF_OP_LOAD(PUSH_F64(GET_F64_FROM_ADDR((uint32*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I32_LOAD8_S):
DEF_OP_LOAD(PUSH_I32(sign_ext_8_32(*(int8*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I32_LOAD8_U):
DEF_OP_LOAD(PUSH_I32((uint32)(*(uint8*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I32_LOAD16_S):
DEF_OP_LOAD(PUSH_I32(sign_ext_16_32(*(int16*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I32_LOAD16_U):
DEF_OP_LOAD(PUSH_I32((uint32)(*(uint16*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD8_S):
DEF_OP_LOAD(PUSH_I64(sign_ext_8_64(*(int8*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD8_U):
DEF_OP_LOAD(PUSH_I64((uint64)(*(uint8*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD16_S):
DEF_OP_LOAD(PUSH_I64(sign_ext_16_64(*(int16*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD16_U):
DEF_OP_LOAD(PUSH_I64((uint64)(*(uint16*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD32_S):
DEF_OP_LOAD(PUSH_I64(sign_ext_32_64(*(int32*)maddr)));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_LOAD32_U):
DEF_OP_LOAD(PUSH_I64((uint64)(*(uint32*)maddr)));
HANDLE_OP_END ();
{
uint32 offset, flags, addr;
GET_OPCODE();
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
CHECK_MEMORY_OVERFLOW();
#if WASM_ENABLE_LABELS_AS_VALUES != 0
static const void *handle_load_table[] = {
&&HANDLE_LOAD_WASM_OP_I32_LOAD,
&&HANDLE_LOAD_WASM_OP_I64_LOAD,
&&HANDLE_LOAD_WASM_OP_F32_LOAD,
&&HANDLE_LOAD_WASM_OP_F64_LOAD,
&&HANDLE_LOAD_WASM_OP_I32_LOAD8_S,
&&HANDLE_LOAD_WASM_OP_I32_LOAD8_U,
&&HANDLE_LOAD_WASM_OP_I32_LOAD16_S,
&&HANDLE_LOAD_WASM_OP_I32_LOAD16_U,
&&HANDLE_LOAD_WASM_OP_I64_LOAD8_S,
&&HANDLE_LOAD_WASM_OP_I64_LOAD8_U,
&&HANDLE_LOAD_WASM_OP_I64_LOAD16_S,
&&HANDLE_LOAD_WASM_OP_I64_LOAD16_U,
&&HANDLE_LOAD_WASM_OP_I64_LOAD32_S,
&&HANDLE_LOAD_WASM_OP_I64_LOAD32_U
};
#define HANDLE_OP_LOAD(opcode) HANDLE_LOAD_##opcode
goto *handle_load_table[opcode - WASM_OP_I32_LOAD];
#else
#define HANDLE_OP_LOAD(opcode) case opcode
switch (opcode)
#endif
{
HANDLE_OP_LOAD(WASM_OP_I32_LOAD):
PUSH_I32(*(int32*)maddr);
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD):
PUSH_I64(GET_I64_FROM_ADDR((uint32*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_F32_LOAD):
PUSH_F32(*(float32*)maddr);
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_F64_LOAD):
PUSH_F64(GET_F64_FROM_ADDR((uint32*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_S):
PUSH_I32(sign_ext_8_32(*(int8*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_U):
PUSH_I32((uint32)(*(uint8*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_S):
PUSH_I32(sign_ext_16_32(*(int16*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_U):
PUSH_I32((uint32)(*(uint16*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_S):
PUSH_I64(sign_ext_8_64(*(int8*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_U):
PUSH_I64((uint64)(*(uint8*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_S):
PUSH_I64(sign_ext_16_64(*(int16*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_U):
PUSH_I64((uint64)(*(uint16*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_S):
PUSH_I64(sign_ext_32_64(*(int32*)maddr));
HANDLE_OP_END();
HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_U):
PUSH_I64((uint64)(*(uint32*)maddr));
HANDLE_OP_END();
}
(void)flags;
HANDLE_OP_END ();
}
/* memory store instructions */
HANDLE_OP (WASM_OP_I32_STORE):
DEF_OP_STORE(uint32, I32, *(int32*)maddr = sval);
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_STORE):
DEF_OP_STORE(uint64, I64, PUT_I64_TO_ADDR((uint32*)maddr, sval));
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_F32_STORE):
{
uint32 offset, flags, addr;
@ -1218,25 +1217,63 @@ wasm_interp_call_func_bytecode(WASMThread *self,
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I32_STORE):
HANDLE_OP (WASM_OP_I32_STORE8):
DEF_OP_STORE(uint32, I32, *(uint8*)maddr = (uint8)sval);
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I32_STORE16):
DEF_OP_STORE(uint32, I32, *(uint16*)maddr = (uint16)sval);
HANDLE_OP_END ();
{
uint32 offset, flags, addr;
uint32 sval;
GET_OPCODE();
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
sval = POP_I32();
addr = POP_I32();
CHECK_MEMORY_OVERFLOW();
switch (opcode) {
case WASM_OP_I32_STORE:
*(int32*)maddr = sval;
break;
case WASM_OP_I32_STORE8:
*(uint8*)maddr = (uint8)sval;
break;
case WASM_OP_I32_STORE16:
*(uint16*)maddr = (uint16)sval;
break;
}
(void)flags;
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_STORE):
HANDLE_OP (WASM_OP_I64_STORE8):
DEF_OP_STORE(uint64, I64, *(uint8*)maddr = (uint8)sval);
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_STORE16):
DEF_OP_STORE(uint64, I64, *(uint16*)maddr = (uint16)sval);
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_I64_STORE32):
DEF_OP_STORE(uint64, I64, *(uint32*)maddr = (uint32)sval);
HANDLE_OP_END ();
{
uint32 offset, flags, addr;
uint64 sval;
GET_OPCODE();
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
sval = POP_I64();
addr = POP_I32();
CHECK_MEMORY_OVERFLOW();
switch (opcode) {
case WASM_OP_I64_STORE:
PUT_I64_TO_ADDR((uint32*)maddr, sval);
break;
case WASM_OP_I64_STORE8:
*(uint8*)maddr = (uint8)sval;
break;
case WASM_OP_I64_STORE16:
*(uint16*)maddr = (uint16)sval;
break;
case WASM_OP_I64_STORE32:
*(uint32*)maddr = (uint32)sval;
break;
}
(void)flags;
HANDLE_OP_END ();
}
/* memory size and memory grow instructions */
HANDLE_OP (WASM_OP_MEMORY_SIZE):
@ -1977,7 +2014,8 @@ wasm_interp_call_func_bytecode(WASMThread *self,
#if WASM_ENABLE_LABELS_AS_VALUES == 0
default:
wasm_runtime_set_exception(module, "wasm interp failed: unsupported opcode");
wasm_runtime_set_exception(module,
"WASM interp failed: unsupported opcode.");
goto got_exception;
}
#endif
@ -2005,7 +2043,8 @@ wasm_interp_call_func_bytecode(WASMThread *self,
HANDLE_OP (WASM_OP_UNUSED_0x26):
HANDLE_OP (WASM_OP_UNUSED_0x27):
{
wasm_runtime_set_exception(module, "wasm interp failed: unsupported opcode");
wasm_runtime_set_exception(module,
"WASM interp failed: unsupported opcode.");
goto got_exception;
}
#endif

View File

@ -72,7 +72,7 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
}
if (sign && (shift < maxbits) && (byte & 0x40)) {
/* Sign extend */
result |= - (1 << shift);
result |= - ((uint64)1 << shift);
}
*p_result = result;
return true;
@ -141,7 +141,8 @@ const_str_set_insert(const uint8 *str, int32 len, WASMModule *module,
if (!c_str) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: alloc memory failed.");
"WASM module load failed: "
"allocate memory failed.");
return NULL;
}
@ -234,7 +235,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->type_count = type_count;
if (!(module->types = wasm_malloc(sizeof(WASMType*) * type_count))) {
set_error_buf(error_buf, error_buf_size,
"Load type section failed: alloc memory failed.");
"Load type section failed: allocate memory failed.");
return false;
}
@ -256,13 +257,20 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
CHECK_BUF(p, p_end, param_count);
p += param_count;
read_leb_uint32(p, p_end, result_count);
wasm_assert(result_count <= 1);
if (result_count > 1) {
set_error_buf(error_buf, error_buf_size,
"Load type section failed: invalid result count.");
return false;
}
CHECK_BUF(p, p_end, result_count);
p = p_org;
if (!(type = module->types[i] = wasm_malloc(offsetof(WASMType, types) +
sizeof(uint8) * (param_count + result_count))))
sizeof(uint8) * (param_count + result_count)))) {
set_error_buf(error_buf, error_buf_size,
"Load type section failed: allocate memory failed.");
return false;
}
/* Resolve param types and result types */
type->param_count = param_count;
@ -413,7 +421,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->import_count = import_count;
if (!(module->imports = wasm_malloc(sizeof(WASMImport) * import_count))) {
set_error_buf(error_buf, error_buf_size,
"Load import section failed: alloc memory failed.");
"Load import section failed: allocate memory failed.");
return false;
}
@ -635,7 +643,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
module->function_count = func_count;
if (!(module->functions = wasm_malloc(sizeof(WASMFunction*) * func_count))) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: alloc memory failed.");
"Load function section failed: allocate memory failed.");
return false;
}
@ -652,7 +660,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
}
read_leb_uint32(p_code, buf_code_end, code_size);
if (code_size == 0) {
if (code_size == 0
|| p_code + code_size > buf_code_end) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: "
"invalid function code size.");
@ -678,7 +687,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
if (!(func = module->functions[i] = wasm_malloc(total_size))) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: alloc memory failed.");
"Load function section failed: "
"allocate memory failed.");
return false;
}
@ -696,7 +706,20 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
local_type_index = 0;
for (j = 0; j < local_set_count; j++) {
read_leb_uint32(p_code, buf_code_end, sub_local_count);
if (local_type_index + sub_local_count <= local_type_index
|| local_type_index + sub_local_count > local_count) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: "
"invalid local count.");
return false;
}
read_leb_uint8(p_code, buf_code_end, type);
if (type < VALUE_TYPE_F64 || type > VALUE_TYPE_I32) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: "
"invalid local type.");
return false;
}
for (k = 0; k < sub_local_count; k++) {
func->local_types[local_type_index++] = type;
}
@ -707,8 +730,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
if (p != p_end) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: "
"invalid section size.");
"Load function section failed: "
"invalid section size.");
return false;
}
@ -735,7 +758,8 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->table_count = table_count;
if (!(module->tables = wasm_malloc(sizeof(WASMTable) * table_count))) {
set_error_buf(error_buf, error_buf_size,
"Load table section failed: alloc memory failed.");
"Load table section failed: "
"allocate memory failed.");
return false;
}
@ -777,7 +801,8 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->memory_count = memory_count;
if (!(module->memories = wasm_malloc(sizeof(WASMMemory) * memory_count))) {
set_error_buf(error_buf, error_buf_size,
"Load memory section failed: alloc memory failed.");
"Load memory section failed: "
"allocate memory failed.");
return false;
}
@ -814,7 +839,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->global_count = global_count;
if (!(module->globals = wasm_malloc(sizeof(WASMGlobal) * global_count))) {
set_error_buf(error_buf, error_buf_size,
"Load global section failed: alloc memory failed.");
"Load global section failed: "
"allocate memory failed.");
return false;
}
@ -859,7 +885,8 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->export_count = export_count;
if (!(module->exports = wasm_malloc(sizeof(WASMExport) * export_count))) {
set_error_buf(error_buf, error_buf_size,
"Load export section failed: alloc memory failed.");
"Load export section failed: "
"allocate memory failed.");
return false;
}
@ -952,7 +979,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
(sizeof(WASMTableSeg) * table_segment_count))) {
set_error_buf(error_buf, error_buf_size,
"Load table segment section failed: "
"alloc memory failed.");
"allocate memory failed.");
return false;
}
@ -974,7 +1001,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
wasm_malloc(sizeof(uint32) * function_count))) {
set_error_buf(error_buf, error_buf_size,
"Load table segment section failed: "
"alloc memory failed.");
"allocate memory failed.");
return false;
}
for (j = 0; j < function_count; j++) {
@ -1012,8 +1039,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
if (!(module->data_segments =
wasm_malloc(sizeof(WASMDataSeg*) * data_seg_count))) {
set_error_buf(error_buf, error_buf_size,
"Load data segment section failed, "
"alloc memory failed.");
"Load data segment section failed: "
"allocate memory failed.");
return false;
}
@ -1031,7 +1058,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
wasm_malloc(sizeof(WASMDataSeg)))) {
set_error_buf(error_buf, error_buf_size,
"Load data segment section failed: "
"alloc memory failed.");
"allocate memory failed.");
return false;
}
@ -1117,12 +1144,6 @@ load_from_sections(WASMModule *module, WASMSection *sections,
section = section->next;
}
if (!buf_code) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: find code section failed.");
return false;
}
section = sections;
while (section) {
buf = section->section_body;
@ -1140,8 +1161,13 @@ load_from_sections(WASMModule *module, WASMSection *sections,
return false;
break;
case SECTION_TYPE_FUNC:
if (!buf_code) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: find code section failed.");
return false;
}
if (!load_function_section(buf, buf_end, buf_code, buf_code_end,
module, error_buf, error_buf_size))
module, error_buf, error_buf_size))
return false;
break;
case SECTION_TYPE_TABLE:
@ -1229,7 +1255,8 @@ create_module(char *error_buf, uint32 error_buf_size)
if (!module) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: alloc memory failed.");
"WASM module load failed: "
"allocate memory failed.");
return NULL;
}
@ -1309,7 +1336,8 @@ create_sections(const uint8 *buf, uint32 size,
if (!(section = wasm_malloc(sizeof(WASMSection)))) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: alloc memory failed.");
"WASM module load failed: "
"allocate memory failed.");
return false;
}
@ -1401,7 +1429,7 @@ wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_bu
if (!module) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: alloc memory failed.");
"WASM module load failed: allocate memory failed.");
return NULL;
}
@ -1855,9 +1883,11 @@ wasm_loader_find_block_addr(WASMModule *module,
break;
default:
LOG_ERROR("WASM loader find block addr failed: invalid opcode %02x.\n",
opcode);
break;
if (error_buf)
snprintf(error_buf, error_buf_size,
"WASM loader find block addr failed: "
"invalid opcode %02x.", opcode);
return false;
}
}
@ -1902,7 +1932,7 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new)
if (!mem_new) { \
set_error_buf(error_buf, error_buf_size, \
"WASM loader prepare bytecode failed: " \
"alloc memory failed"); \
"allocate memory failed."); \
goto fail; \
} \
mem = mem_new; \
@ -2201,6 +2231,24 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num,
} \
} while (0)
static bool
check_memory(WASMModule *module,
char *error_buf, uint32 error_buf_size)
{
if (module->memory_count == 0
&& module->import_memory_count == 0) {
set_error_buf(error_buf, error_buf_size,
"load or store in module without default memory");
return false;
}
return true;
}
#define CHECK_MEMORY() do { \
if (!check_memory(module, error_buf, error_buf_size)) \
goto fail; \
} while (0)
static bool
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
char *error_buf, uint32 error_buf_size)
@ -2235,7 +2283,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
frame_ref_size = 32;
if (!(frame_ref_bottom = frame_ref = wasm_malloc(frame_ref_size))) {
set_error_buf(error_buf, error_buf_size,
"WASM loader prepare bytecode failed: alloc memory failed");
"WASM loader prepare bytecode failed: "
"allocate memory failed");
goto fail;
}
memset(frame_ref_bottom, 0, frame_ref_size);
@ -2244,7 +2293,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
frame_csp_size = sizeof(BranchBlock) * 8;
if (!(frame_csp_bottom = frame_csp = wasm_malloc(frame_csp_size))) {
set_error_buf(error_buf, error_buf_size,
"WASM loader prepare bytecode failed: alloc memory failed");
"WASM loader prepare bytecode failed: "
"allocate memory failed");
goto fail;
}
@ -2337,7 +2387,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
if (!block) {
set_error_buf(error_buf, error_buf_size,
"WASM loader prepare bytecode failed: "
"alloc memory failed");
"allocate memory failed.");
goto fail;
}
@ -2350,7 +2400,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
block)) {
set_error_buf(error_buf, error_buf_size,
"WASM loader prepare bytecode failed: "
"alloc memory failed");
"allocate memory failed.");
wasm_free(block);
goto fail;
}
@ -2482,12 +2532,20 @@ handle_op_br:
WASMType *func_type;
uint32 type_idx;
if (module->table_count == 0
&& module->import_table_count == 0) {
set_error_buf(error_buf, error_buf_size,
"call indirect without default table");
goto fail;
}
read_leb_uint32(p, p_end, type_idx);
read_leb_uint8(p, p_end, u8); /* 0x00 */
POP_I32();
if (type_idx >= module->type_count) {
set_error_buf(error_buf, error_buf_size, "function index is overflow");
set_error_buf(error_buf, error_buf_size,
"function index is overflow");
goto fail;
}
@ -2618,6 +2676,7 @@ handle_op_br:
case WASM_OP_I32_LOAD8_U:
case WASM_OP_I32_LOAD16_S:
case WASM_OP_I32_LOAD16_U:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_I32();
@ -2631,6 +2690,7 @@ handle_op_br:
case WASM_OP_I64_LOAD16_U:
case WASM_OP_I64_LOAD32_S:
case WASM_OP_I64_LOAD32_U:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_I32();
@ -2638,6 +2698,7 @@ handle_op_br:
break;
case WASM_OP_F32_LOAD:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_I32();
@ -2645,6 +2706,7 @@ handle_op_br:
break;
case WASM_OP_F64_LOAD:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_I32();
@ -2654,6 +2716,7 @@ handle_op_br:
case WASM_OP_I32_STORE:
case WASM_OP_I32_STORE8:
case WASM_OP_I32_STORE16:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_I32();
@ -2664,6 +2727,7 @@ handle_op_br:
case WASM_OP_I64_STORE8:
case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_I64();
@ -2671,6 +2735,7 @@ handle_op_br:
break;
case WASM_OP_F32_STORE:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_F32();
@ -2678,6 +2743,7 @@ handle_op_br:
break;
case WASM_OP_F64_STORE:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* align */
read_leb_uint32(p, p_end, u32); /* offset */
POP_F64();
@ -2685,11 +2751,13 @@ handle_op_br:
break;
case WASM_OP_MEMORY_SIZE:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* 0x00 */
PUSH_I32();
break;
case WASM_OP_MEMORY_GROW:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* 0x00 */
POP_I32();
PUSH_I32();
@ -2971,15 +3039,24 @@ handle_op_br:
break;
default:
LOG_ERROR("WASM loader find block addr failed: invalid opcode %02x.\n",
opcode);
break;
if (error_buf != NULL)
snprintf(error_buf, error_buf_size,
"WASM module load failed: "
"invalid opcode %02x.", opcode);
goto fail;
}
if (opcode != WASM_OP_I32_CONST)
is_i32_const = false;
}
if (csp_num > 0) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: "
"function body must end with END opcode.");
goto fail;
}
func->max_stack_cell_num = max_stack_cell_num;
func->max_block_num = max_csp_num;
return_value = true;

View File

@ -70,33 +70,41 @@ wasm_runtime_call_wasm(WASMModuleInstance *module_inst,
WASMFunctionInstance *function,
unsigned argc, uint32 argv[])
{
if (!exec_env) {
if (!module_inst->wasm_stack) {
if (!(module_inst->wasm_stack =
wasm_malloc(module_inst->wasm_stack_size))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
/* Only init stack when no application is running. */
if (!wasm_runtime_get_self()->cur_frame) {
if (!exec_env) {
if (!module_inst->wasm_stack) {
if (!(module_inst->wasm_stack =
wasm_malloc(module_inst->wasm_stack_size))) {
wasm_runtime_set_exception(module_inst,
"allocate memory failed.");
return false;
}
init_wasm_stack(&module_inst->main_tlr.wasm_stack,
module_inst->wasm_stack,
module_inst->wasm_stack_size);
}
}
}
else {
uintptr_t stack = (uintptr_t)exec_env->stack;
uint32 stack_size;
init_wasm_stack(&module_inst->main_tlr.wasm_stack,
module_inst->wasm_stack, module_inst->wasm_stack_size);
}
else {
uintptr_t stack = (uintptr_t)exec_env->stack;
uint32 stack_size;
/* Set to 8 bytes align */
stack = (stack + 7) & ~7;
stack_size = exec_env->stack_size
- (stack - (uintptr_t)exec_env->stack);
/* Set to 8 bytes align */
stack = (stack + 7) & ~7;
stack_size = exec_env->stack_size - (stack - (uintptr_t)exec_env->stack);
if (!exec_env->stack || exec_env->stack_size <= 0
|| exec_env->stack_size < stack - (uintptr_t)exec_env->stack) {
wasm_runtime_set_exception(module_inst,
"Invalid execution stack info.");
return false;
}
if (!exec_env->stack || exec_env->stack_size <= 0
|| exec_env->stack_size < stack - (uintptr_t)exec_env->stack) {
wasm_runtime_set_exception(module_inst, "Invalid execution stack info.");
return false;
}
init_wasm_stack(&module_inst->main_tlr.wasm_stack, (uint8*)stack, stack_size);
init_wasm_stack(&module_inst->main_tlr.wasm_stack,
(uint8*)stack, stack_size);
}
}
wasm_interp_call_wasm(function, argc, argv);
@ -877,8 +885,9 @@ wasm_runtime_instantiate(WASMModule *module,
length = data_seg->data_length;
memory_size = NumBytesPerPage * module_inst->default_memory->cur_page_count;
if (base_offset >= memory_size
|| base_offset + length > memory_size) {
if (length > 0
&& (base_offset >= memory_size
|| base_offset + length > memory_size)) {
set_error_buf(error_buf, error_buf_size,
"Instantiate module failed: data segment out of range.");
wasm_runtime_deinstantiate(module_inst);
@ -946,18 +955,11 @@ wasm_runtime_instantiate(WASMModule *module,
wasm_runtime_set_tlr(&module_inst->main_tlr);
module_inst->main_tlr.handle = ws_self_thread();
/* Execute __post_instantiate function */
if (!execute_post_inst_function(module_inst)) {
const char *exception = wasm_runtime_get_exception(module_inst);
wasm_printf("%s\n", exception);
wasm_runtime_deinstantiate(module_inst);
return NULL;
}
/* Execute start function */
if (!execute_start_function(module_inst)) {
const char *exception = wasm_runtime_get_exception(module_inst);
wasm_printf("%s\n", exception);
/* Execute __post_instantiate and start function */
if (!execute_post_inst_function(module_inst)
|| !execute_start_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
wasm_runtime_deinstantiate(module_inst);
return NULL;
}
@ -991,6 +993,37 @@ wasm_runtime_deinstantiate(WASMModuleInstance *module_inst)
wasm_free(module_inst);
}
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
bool
wasm_runtime_set_ext_memory(WASMModuleInstance *module_inst,
uint8 *ext_mem_data, uint32 ext_mem_size,
char *error_buf, uint32 error_buf_size)
{
if (module_inst->ext_mem_data) {
set_error_buf(error_buf, error_buf_size,
"Set external memory failed: "
"an external memory has been set.");
return false;
}
if (!ext_mem_data
|| ext_mem_size > 1 * BH_GB
|| ext_mem_data + ext_mem_size < ext_mem_data) {
set_error_buf(error_buf, error_buf_size,
"Set external memory failed: "
"invalid input.");
return false;
}
module_inst->ext_mem_data = ext_mem_data;
module_inst->ext_mem_data_end = ext_mem_data + ext_mem_size;
module_inst->ext_mem_size = ext_mem_size;
module_inst->ext_mem_base_offset = DEFAULT_EXT_MEM_BASE_OFFSET;
return true;
}
#endif
bool
wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count)
{
@ -1165,24 +1198,40 @@ wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst,
uint8 *addr;
/* integer overflow check */
if(app_offset < 0 ||
app_offset + size < app_offset) {
if(app_offset + size < app_offset) {
goto fail;
}
memory = module_inst->default_memory;
if (app_offset < memory->heap_base_offset) {
if (0 <= app_offset
&& app_offset < memory->heap_base_offset) {
addr = memory->memory_data + app_offset;
if (!(memory->base_addr <= addr && addr + size <= memory->end_addr))
goto fail;
return true;
}
else {
else if (memory->heap_base_offset < app_offset
&& app_offset < memory->heap_base_offset
+ (memory->heap_data_end - memory->heap_data)) {
addr = memory->heap_data + (app_offset - memory->heap_base_offset);
if (!(memory->heap_data <= addr && addr + size <= memory->heap_data_end))
goto fail;
return true;
}
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
else if (module_inst->ext_mem_data
&& module_inst->ext_mem_base_offset <= app_offset
&& app_offset < module_inst->ext_mem_base_offset
+ module_inst->ext_mem_size) {
addr = module_inst->ext_mem_data
+ (app_offset - module_inst->ext_mem_base_offset);
if (!(module_inst->ext_mem_data <= addr
&& addr + size <= module_inst->ext_mem_data_end))
goto fail;
return true;
}
#endif
fail:
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
@ -1201,7 +1250,13 @@ wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst,
}
if ((memory->base_addr <= addr && addr + size <= memory->end_addr)
|| (memory->heap_data <= addr && addr + size <= memory->heap_data_end))
|| (memory->heap_data <= addr && addr + size <= memory->heap_data_end)
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
|| (module_inst->ext_mem_data
&& module_inst->ext_mem_data <= addr
&& addr + size <= module_inst->ext_mem_data_end)
#endif
)
return true;
fail:
@ -1214,10 +1269,22 @@ wasm_runtime_addr_app_to_native(WASMModuleInstance *module_inst,
int32 app_offset)
{
WASMMemoryInstance *memory = module_inst->default_memory;
if (app_offset < memory->heap_base_offset)
if (0 <= app_offset && app_offset < memory->heap_base_offset)
return memory->memory_data + app_offset;
else
else if (memory->heap_base_offset < app_offset
&& app_offset < memory->heap_base_offset
+ (memory->heap_data_end - memory->heap_data))
return memory->heap_data + (app_offset - memory->heap_base_offset);
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
else if (module_inst->ext_mem_data
&& module_inst->ext_mem_base_offset <= app_offset
&& app_offset < module_inst->ext_mem_base_offset
+ module_inst->ext_mem_size)
return module_inst->ext_mem_data
+ (app_offset - module_inst->ext_mem_base_offset);
#endif
else
return NULL;
}
int32
@ -1228,11 +1295,99 @@ wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst,
if (memory->base_addr <= (uint8*)native_ptr
&& (uint8*)native_ptr < memory->end_addr)
return (uint8*)native_ptr - memory->memory_data;
else
else if (memory->heap_data <= (uint8*)native_ptr
&& (uint8*)native_ptr < memory->heap_data_end)
return memory->heap_base_offset
+ ((uint8*)native_ptr - memory->heap_data);
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
else if (module_inst->ext_mem_data
&& module_inst->ext_mem_data <= (uint8*)native_ptr
&& (uint8*)native_ptr < module_inst->ext_mem_data_end)
return module_inst->ext_mem_base_offset
+ ((uint8*)native_ptr - module_inst->ext_mem_data);
#endif
else
return 0;
}
bool
wasm_runtime_get_app_addr_range(WASMModuleInstance *module_inst,
int32 app_offset,
int32 *p_app_start_offset,
int32 *p_app_end_offset)
{
int32 app_start_offset, app_end_offset;
WASMMemoryInstance *memory = module_inst->default_memory;
if (0 <= app_offset && app_offset < memory->heap_base_offset) {
app_start_offset = 0;
app_end_offset = NumBytesPerPage * memory->cur_page_count;
}
else if (memory->heap_base_offset < app_offset
&& app_offset < memory->heap_base_offset
+ (memory->heap_data_end - memory->heap_data)) {
app_start_offset = memory->heap_base_offset;
app_end_offset = memory->heap_base_offset
+ (memory->heap_data_end - memory->heap_data);
}
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
else if (module_inst->ext_mem_data
&& module_inst->ext_mem_base_offset <= app_offset
&& app_offset < module_inst->ext_mem_base_offset
+ module_inst->ext_mem_size) {
app_start_offset = module_inst->ext_mem_base_offset;
app_end_offset = app_start_offset + module_inst->ext_mem_size;
}
#endif
else
return false;
if (p_app_start_offset)
*p_app_start_offset = app_start_offset;
if (p_app_end_offset)
*p_app_end_offset = app_end_offset;
return true;
}
bool
wasm_runtime_get_native_addr_range(WASMModuleInstance *module_inst,
uint8 *native_ptr,
uint8 **p_native_start_addr,
uint8 **p_native_end_addr)
{
uint8 *native_start_addr, *native_end_addr;
WASMMemoryInstance *memory = module_inst->default_memory;
if (memory->base_addr <= (uint8*)native_ptr
&& (uint8*)native_ptr < memory->end_addr) {
native_start_addr = memory->memory_data;
native_end_addr = memory->memory_data
+ NumBytesPerPage * memory->cur_page_count;
}
else if (memory->heap_data <= (uint8*)native_ptr
&& (uint8*)native_ptr < memory->heap_data_end) {
native_start_addr = memory->heap_data;
native_end_addr = memory->heap_data_end;
}
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
else if (module_inst->ext_mem_data
&& module_inst->ext_mem_data <= (uint8*)native_ptr
&& (uint8*)native_ptr < module_inst->ext_mem_data_end) {
native_start_addr = module_inst->ext_mem_data;
native_end_addr = module_inst->ext_mem_data_end;
}
#endif
else
return false;
if (p_native_start_addr)
*p_native_start_addr = native_start_addr;
if (p_native_end_addr)
*p_native_end_addr = native_end_addr;
return true;
}
uint32
wasm_runtime_get_temp_ret(WASMModuleInstance *module_inst)
{
@ -1272,3 +1427,248 @@ wasm_runtime_load_aot(uint8 *aot_file, uint32 aot_file_size,
return NULL;
}
static inline void
word_copy(uint32 *dest, uint32 *src, unsigned num)
{
for (; num > 0; num--)
*dest++ = *src++;
}
#define PUT_I64_TO_ADDR(addr, value) do { \
union { int64 val; uint32 parts[2]; } u; \
u.val = (value); \
(addr)[0] = u.parts[0]; \
(addr)[1] = u.parts[1]; \
} while (0)
#define PUT_F64_TO_ADDR(addr, value) do { \
union { float64 val; uint32 parts[2]; } u; \
u.val = (value); \
(addr)[0] = u.parts[0]; \
(addr)[1] = u.parts[1]; \
} while (0)
#if !defined(__x86_64__) && !defined(__amd_64__)
typedef void (*GenericFunctionPointer)();
int64 invokeNative(uint32 *args, uint32 sz, GenericFunctionPointer f);
typedef float64 (*Float64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef float32 (*Float32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int64 (*Int64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int32 (*Int32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(uint32*, uint32, GenericFunctionPointer);
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
/* As JavaScript can't represent int64s, emcc compiles C int64 argument
into two WASM i32 arguments, see:
https://github.com/emscripten-core/emscripten/issues/7199
And also JavaScript float point is always 64-bit, emcc compiles
float32 argument into WASM f64 argument.
But clang compiles C int64 argument into WASM i64 argument, and
compiles C float32 argument into WASM f32 argument.
So for the compatability of emcc and clang, we treat i64 as two i32s,
treat f32 as f64 while passing arguments to the native function, and
require the native function uses two i32 arguments instead one i64
argument, and uses double argument instead of float argment. */
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,
uint32 *argv, uint32 argc, uint32 *ret)
{
union { float64 val; int32 parts[2]; } u;
uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0;
uint64 size;
argc1 = func_type->param_count * 2 + 2;
if (argc1 > sizeof(argv_buf) / sizeof(uint32)) {
size = ((uint64)sizeof(uint32)) * argc1;
if (size >= UINT_MAX
|| !(argv1 = wasm_malloc((uint32)size))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
}
}
for (i = 0; i < sizeof(WASMModuleInstance*) / sizeof(uint32); i++)
argv1[j++] = ((uint32*)&module_inst)[i];
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
argv1[j++] = *argv++;
break;
case VALUE_TYPE_I64:
case VALUE_TYPE_F64:
argv1[j++] = *argv++;
argv1[j++] = *argv++;
break;
case VALUE_TYPE_F32:
u.val = *(float32*)argv++;
#if defined(__arm__) || defined(__mips__)
/* 64-bit data must be 8 bytes alined in arm and mips */
if (j & 1)
j++;
#endif
argv1[j++] = u.parts[0];
argv1[j++] = u.parts[1];
break;
default:
wasm_assert(0);
break;
}
}
if (func_type->result_count == 0) {
invokeNative_Void(argv1, argc1, func_ptr);
}
else {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
ret[0] = invokeNative_Int32(argv1, argc1, func_ptr);
break;
case VALUE_TYPE_I64:
PUT_I64_TO_ADDR(ret, invokeNative_Int64(argv1, argc1, func_ptr));
break;
case VALUE_TYPE_F32:
*(float32*)ret = invokeNative_Float32(argv1, argc1, func_ptr);
break;
case VALUE_TYPE_F64:
PUT_F64_TO_ADDR(ret, invokeNative_Float64(argv1, argc1, func_ptr));
break;
}
}
if (argv1 != argv_buf)
wasm_free(argv1);
return true;
}
#else /* else of !defined(__x86_64__) && !defined(__amd_64__) */
typedef void (*GenericFunctionPointer)();
int64 invokeNative(uint64 *args, uint64 n_fps, uint64 n_stacks, GenericFunctionPointer f);
typedef float64 (*Float64FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
typedef float32 (*Float32FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
typedef int64 (*Int64FuncPtr)(uint64*,uint64, uint64, GenericFunctionPointer);
typedef int32 (*Int32FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
#if defined(_WIN32) || defined(_WIN32_)
#define MAX_REG_FLOATS 4
#define MAX_REG_INTS 4
#else
#define MAX_REG_FLOATS 8
#define MAX_REG_INTS 6
#endif
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,
uint32 *argv, uint32 argc, uint32 *ret)
{
uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size;
uint32 *argv_src = argv, i, j, argc1, n_ints = 0, n_stacks = 0;
#if defined(_WIN32) || defined(_WIN32_)
/* important difference in calling conventions */
#define n_fps n_ints
#else
int n_fps = 0;
#endif
argc1 = 1 + MAX_REG_FLOATS + func_type->param_count + 2;
if (argc1 > sizeof(argv_buf) / sizeof(uint64)) {
size = sizeof(uint64) * argc1;
if (size >= UINT32_MAX
|| !(argv1 = wasm_malloc(size))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
}
}
fps = argv1 + 1;
ints = fps + MAX_REG_FLOATS;
stacks = ints + MAX_REG_INTS;
ints[n_ints++] = (uint64)(uintptr_t)module_inst;
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
else
stacks[n_stacks++] = *argv_src++;
break;
case VALUE_TYPE_I64:
for (j = 0; j < 2; j++) {
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
else
stacks[n_stacks++] = *argv_src++;
}
break;
case VALUE_TYPE_F32:
if (n_fps < MAX_REG_FLOATS)
*(float64*)&fps[n_fps++] = *(float32*)argv_src++;
else
*(float64*)&stacks[n_stacks++] = *(float32*)argv_src++;
break;
case VALUE_TYPE_F64:
if (n_fps < MAX_REG_FLOATS)
*(float64*)&fps[n_fps++] = *(float64*)argv_src;
else
*(float64*)&stacks[n_stacks++] = *(float64*)argv_src;
argv_src += 2;
break;
default:
wasm_assert(0);
break;
}
}
if (func_type->result_count == 0) {
invokeNative_Void(argv1, n_fps, n_stacks, func_ptr);
}
else {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
ret[0] = invokeNative_Int32(argv1, n_fps, n_stacks, func_ptr);
break;
case VALUE_TYPE_I64:
PUT_I64_TO_ADDR(ret, invokeNative_Int64(argv1, n_fps, n_stacks, func_ptr));
break;
case VALUE_TYPE_F32:
*(float32*)ret = invokeNative_Float32(argv1, n_fps, n_stacks, func_ptr);
break;
case VALUE_TYPE_F64:
PUT_F64_TO_ADDR(ret, invokeNative_Float64(argv1, n_fps, n_stacks, func_ptr));
break;
default:
wasm_assert(0);
break;
}
}
if (argv1 != argv_buf)
wasm_free(argv1);
return true;
}
#endif /* end of !defined(__x86_64__) && !defined(__amd_64__) */

View File

@ -148,6 +148,13 @@ typedef struct WASMModuleInstance {
uint32 temp_ret;
uint32 llvm_stack;
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
int32 ext_mem_base_offset;
uint8 *ext_mem_data;
uint8 *ext_mem_data_end;
uint32 ext_mem_size;
#endif
/* Default WASM stack size of threads of this Module instance. */
uint32 wasm_stack_size;
@ -308,6 +315,11 @@ int32
wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst,
void *native_ptr);
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,
uint32 *argv, uint32 argc, uint32 *ret);
#ifdef __cplusplus
}
#endif

View File

@ -23,6 +23,9 @@
#include "bh_log.h"
#include "bh_list.h"
typedef void (*bh_print_function_t)(const char* message);
void bh_set_print_function(bh_print_function_t pf);
#define bh_memcpy_s(dest, dlen, src, slen) do { \
int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \
(void)_ret; \

View File

@ -43,7 +43,9 @@
#endif
/* WASM VM log system */
#ifndef WASM_ENABLE_LOG
#define WASM_ENABLE_LOG 1
#endif
/* WASM Interpreter labels-as-values feature */
#define WASM_ENABLE_LABELS_AS_VALUES 1
@ -115,3 +117,17 @@
#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
#endif
#endif
/* External memory space provided by user,
but not wasm memory space and app heap space */
#ifndef WASM_ENABLE_EXT_MEMORY_SPACE
#define WASM_ENABLE_EXT_MEMORY_SPACE 0
#endif
/* Default base offset of external memory space */
#define DEFAULT_EXT_MEM_BASE_OFFSET (-2 * BH_GB)
#ifndef bh_printf
#define bh_printf printf
#endif

View File

@ -15,9 +15,9 @@
*/
#include "bh_config.h"
#include "bh_platform.h"
#include "bh_memory.h"
#include "mem_alloc.h"
#include <stdio.h>
#include <stdlib.h>
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
@ -76,7 +76,7 @@ int bh_memory_init_with_pool(void *mem, unsigned int bytes)
global_pool_size = bytes;
return 0;
}
printf("Init memory with pool (%p, %u) failed.\n", mem, bytes);
bh_printf("Init memory with pool (%p, %u) failed.\n", mem, bytes);
return -1;
}
@ -91,7 +91,7 @@ int bh_memory_init_with_allocator(void *_malloc_func, void *_free_func)
#endif
return 0;
}
printf("Init memory with allocator (%p, %p) failed.\n", _malloc_func,
bh_printf("Init memory with allocator (%p, %p) failed.\n", _malloc_func,
_free_func);
return -1;
}
@ -117,7 +117,7 @@ int bh_memory_pool_size()
void* bh_malloc_internal(unsigned int size)
{
if (memory_mode == MEMORY_MODE_UNKNOWN) {
printf("bh_malloc failed: memory hasn't been initialize.\n");
bh_printf("bh_malloc failed: memory hasn't been initialize.\n");
return NULL;
} else if (memory_mode == MEMORY_MODE_POOL) {
return mem_allocator_malloc(pool_allocator, size);
@ -129,7 +129,7 @@ void* bh_malloc_internal(unsigned int size)
void bh_free_internal(void *ptr)
{
if (memory_mode == MEMORY_MODE_UNKNOWN) {
printf("bh_free failed: memory hasn't been initialize.\n");
bh_printf("bh_free failed: memory hasn't been initialize.\n");
} else if (memory_mode == MEMORY_MODE_POOL) {
mem_allocator_free(pool_allocator, ptr);
} else {
@ -250,7 +250,7 @@ void memory_usage_summarize()
profile = memory_profiles_list;
while (profile) {
printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
bh_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
profile->total_malloc,
profile->malloc_num,
profile->total_free,
@ -267,7 +267,7 @@ void memory_profile_print(const char *file,
const char *func,
int alloc)
{
printf("location:%s@%d:used:%d:contribution:%d\n",
bh_printf("location:%s@%d:used:%d:contribution:%d\n",
func, line, memory_in_use, alloc);
}
@ -328,4 +328,3 @@ void bh_free_profile(const char *file, int line, const char *func, void *ptr)
}
#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */
#endif /* end of MALLOC_MEMORY_FROM_SYSTEM*/

View File

@ -118,7 +118,7 @@ static void unlink_hmu(gc_heap_t *heap, hmu_t *hmu)
}
if (!node) {
printf("[GC_ERROR]couldn't find the node in the normal list");
bh_printf("[GC_ERROR]couldn't find the node in the normal list");
}
} else {
remove_tree_node((hmu_tree_node_t *) hmu);
@ -152,7 +152,7 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
bh_assert(
hmu && (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size);
bh_assert(((gc_uint32) hmu_to_obj(hmu) & 7) == 0);
bh_assert(((gc_uint32)(uintptr_t)hmu_to_obj(hmu) & 7) == 0);
bh_assert(
size > 0
&& ((gc_uint8*) hmu) + size
@ -242,7 +242,7 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
p = node->next;
node->next = p->next;
bh_assert(((gc_int32) hmu_to_obj(p) & 7) == 0);
bh_assert(((gc_int32)(uintptr_t)hmu_to_obj(p) & 7) == 0);
if ((gc_size_t) node_idx
!= init_node_idx&& ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { /* with bigger size*/
@ -392,7 +392,7 @@ gc_object_t _gc_alloc_vo_i_heap(void *vheap,
ret = hmu_to_obj(hmu);
#if BH_ENABLE_MEMORY_PROFILING != 0
printf("HEAP.ALLOC: heap: %p, size: %u", heap, size);
bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size);
#endif
FINISH:
@ -434,7 +434,7 @@ gc_object_t _gc_alloc_jo_i_heap(void *vheap,
ret = hmu_to_obj(hmu);
#if BH_ENABLE_MEMORY_PROFILING != 0
printf("HEAP.ALLOC: heap: %p, size: %u", heap, size);
bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size);
#endif
FINISH:
@ -495,7 +495,7 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS)
heap->total_free_size += size;
#endif
#if BH_ENABLE_MEMORY_PROFILING != 0
printf("HEAP.FREE, heap: %p, size: %u\n",heap, size);
bh_printf("HEAP.FREE, heap: %p, size: %u\n",heap, size);
#endif
if (!hmu_get_pinuse(hmu)) {
@ -538,12 +538,12 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS)
void gc_dump_heap_stats(gc_heap_t *heap)
{
printf("heap: %p, heap start: %p\n", heap, heap->base_addr);
printf(
bh_printf("heap: %p, heap start: %p\n", heap, heap->base_addr);
bh_printf(
"total malloc: totalfree: %u, current: %u, highmark: %u, gc cnt: %u\n",
heap->total_free_size, heap->current_size, heap->highmark_size,
heap->total_gc_count);
printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n",
bh_printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n",
g_total_malloc, g_total_free, g_total_malloc - g_total_free);
}

View File

@ -21,6 +21,7 @@
extern "C" {
#endif
#include "bh_platform.h"
#include "bh_thread.h"
#include "bh_memory.h"
#include "bh_assert.h"
@ -279,4 +280,3 @@ extern int (*gct_vm_gc_finished)(void);
#endif
#endif

View File

@ -30,7 +30,7 @@ int gci_check_platform()
{
#define CHECK(x, y) do { \
if((x) != (y)) { \
printf("Platform checking failed on LINE %d at FILE %s.", \
bh_printf("Platform checking failed on LINE %d at FILE %s.",\
__LINE__, __FILE__); \
return GC_ERROR; \
} \
@ -62,12 +62,12 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
/* check system compatibility*/
if (gci_check_platform() == GC_ERROR) {
printf("Check platform compatibility failed");
bh_printf("Check platform compatibility failed");
return NULL;
}
if (buf_size < 1024) {
printf("[GC_ERROR]heap_init_size(%d) < 1024", buf_size);
bh_printf("[GC_ERROR]heap_init_size(%d) < 1024", buf_size);
return NULL;
}
@ -79,12 +79,12 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
ret = gct_vm_mutex_init(&heap->lock);
if (ret != BHT_OK) {
printf("[GC_ERROR]failed to init lock ");
bh_printf("[GC_ERROR]failed to init lock ");
return NULL;
}
#ifdef BH_FOOTPRINT
printf("\nINIT HEAP 0x%08x %d\n", base_addr, heap_max_size);
bh_printf("\nINIT HEAP 0x%08x %d\n", base_addr, heap_max_size);
#endif
/* init all data structures*/
@ -131,7 +131,7 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
&& HMU_FC_NORMAL_MAX_SIZE < q->size); /*@NOTIFY*/
#if BH_ENABLE_MEMORY_PROFILING != 0
printf("heap is successfully initialized with max_size=%u.",
bh_printf("heap is successfully initialized with max_size=%u.",
heap_max_size);
#endif
return heap;

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_platform.h"
#include "bh_assert.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef BH_TEST
#include <setjmp.h>
#endif
#ifdef BH_TEST
/* for exception throwing */
jmp_buf bh_test_jb;
#endif
void bh_assert_internal(int v, const char *file_name, int line_number,
const char *expr_string)
{
if (v)
return;
if (!file_name)
file_name = "NULL FILENAME";
if (!expr_string)
expr_string = "NULL EXPR_STRING";
printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string,
file_name, line_number);
#ifdef BH_TEST
longjmp(bh_test_jb, 1);
#endif
abort();
}
void bh_debug_internal(const char *file_name, int line_number, const char *fmt,
...)
{
#ifndef JEFF_TEST_VERIFIER
va_list args;
va_start(args, fmt);
bh_assert(file_name);
printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number);
vprintf(fmt, args);
va_end(args);
printf("\n");
#endif
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_definition.h"
#include "bh_platform.h"
int bh_return(int ret)
{
return ret;
}
#define RSIZE_MAX 0x7FFFFFFF
int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n)
{
char *dest = (char*) s1;
char *src = (char*) s2;
if (n == 0) {
return 0;
}
if (s1 == NULL || s1max > RSIZE_MAX) {
return -1;
}
if (s2 == NULL || n > s1max) {
memset(dest, 0, s1max);
return -1;
}
memcpy(dest, src, n);
return 0;
}
int b_strcat_s(char * s1, size_t s1max, const char * s2)
{
if (NULL
== s1|| NULL == s2 || s1max < (strlen(s1) + strlen(s2) + 1) || s1max > RSIZE_MAX) {
return -1;
}
strcat(s1, s2);
return 0;
}
int b_strcpy_s(char * s1, size_t s1max, const char * s2)
{
if (NULL
== s1|| NULL == s2 || s1max < (strlen(s2) + 1) || s1max > RSIZE_MAX) {
return -1;
}
strcpy(s1, s2);
return 0;
}
int fopen_s(FILE ** pFile, const char *filename, const char *mode)
{
if (NULL == pFile || NULL == filename || NULL == mode) {
return -1;
}
*pFile = fopen(filename, mode);
if (NULL == *pFile)
return -1;
return 0;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_platform.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
char *bh_strdup(const char *s)
{
char *s1 = NULL;
if (s && (s1 = bh_malloc(strlen(s) + 1)))
memcpy(s1, s, strlen(s) + 1);
return s1;
}
int bh_platform_init()
{
return 0;
}
char*
bh_read_file_to_buffer(const char *filename, int *ret_size)
{
char *buffer;
int file;
int file_size, read_size;
struct stat stat_buf;
if (!filename || !ret_size) {
printf("Read file to buffer failed: invalid filename or ret size.\n");
return NULL;
}
if ((file = open(filename, O_RDONLY, 0)) == -1) {
printf("Read file to buffer failed: open file %s failed.\n",
filename);
return NULL;
}
if (fstat(file, &stat_buf) != 0) {
printf("Read file to buffer failed: fstat file %s failed.\n",
filename);
close(file);
return NULL;
}
file_size = stat_buf.st_size;
if (!(buffer = bh_malloc(file_size))) {
printf("Read file to buffer failed: alloc memory failed.\n");
close(file);
return NULL;
}
read_size = read(file, buffer, file_size);
close(file);
if (read_size < file_size) {
printf("Read file to buffer failed: read file content failed.\n");
bh_free(buffer);
return NULL;
}
*ret_size = file_size;
return buffer;
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BH_PLATFORM_H
#define _BH_PLATFORM_H
#include "bh_config.h"
#include "bh_types.h"
#include "bh_memory.h"
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include <limits.h>
#include <semaphore.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint64_t uint64;
typedef int64_t int64;
extern void DEBUGME(void);
#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0)
#define BH_PLATFORM "Darwin"
/* NEED qsort */
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0
#define BH_ROUTINE_MODIFIER
#define BHT_TIMEDOUT ETIMEDOUT
#define INVALID_THREAD_ID 0xFFffFFff
typedef pthread_t korp_tid;
typedef pthread_mutex_t korp_mutex;
typedef sem_t korp_sem;
typedef pthread_cond_t korp_cond;
typedef pthread_t korp_thread;
typedef void* (*thread_start_routine_t)(void*);
#define wa_malloc bh_malloc
#define wa_free bh_free
#define wa_strdup bh_strdup
//int snprintf(char *buffer, size_t count, const char *format, ...);
double fmod(double x, double y);
float fmodf(float x, float y);
double sqrt(double x);
#define BH_WAIT_FOREVER 0xFFFFFFFF
#ifndef NULL
# define NULL ((void*) 0)
#endif
/**
* Return the offset of the given field in the given type.
*
* @param Type the type containing the filed
* @param field the field in the type
*
* @return the offset of field in Type
*/
#ifndef offsetof
#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
#endif
#define bh_assert assert
int b_memcpy_s(void * s1, unsigned int s1max, const void * s2,
unsigned int n);
int b_strcat_s(char * s1, size_t s1max, const char * s2);
int b_strcpy_s(char * s1, size_t s1max, const char * s2);
int fopen_s(FILE ** pFile, const char *filename, const char *mode);
char *bh_read_file_to_buffer(const char *filename, int *ret_size);
char *bh_strdup(const char *s);
int bh_platform_init();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_platform.h"
#include <stdio.h>
void bh_log_emit(const char *fmt, va_list ap)
{
vprintf(fmt, ap);
fflush(stdout);
}
int bh_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vfprintf(stream ? stream : stdout, fmt, ap);
va_end(ap);
return ret;
}
int bh_fflush(void *stream)
{
return fflush(stream ? stream : stdout);
}

View File

@ -0,0 +1,405 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_thread.h"
#include "bh_assert.h"
#include "bh_log.h"
#include "bh_memory.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
static bool is_thread_sys_inited = false;
static korp_mutex thread_list_lock;
static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM];
int _vm_thread_sys_init()
{
unsigned i, j;
int ret;
if (is_thread_sys_inited)
return 0;
for (i = 0; i < BH_MAX_TLS_NUM; i++) {
ret = pthread_key_create(&thread_local_storage_key[i], NULL);
if (ret)
goto fail;
}
ret = vm_mutex_init(&thread_list_lock);
if (ret)
goto fail;
is_thread_sys_inited = true;
return 0;
fail: for (j = 0; j < i; j++)
pthread_key_delete(thread_local_storage_key[j]);
return -1;
}
void vm_thread_sys_destroy(void)
{
if (is_thread_sys_inited) {
unsigned i;
for (i = 0; i < BH_MAX_TLS_NUM; i++)
pthread_key_delete(thread_local_storage_key[i]);
vm_mutex_destroy(&thread_list_lock);
is_thread_sys_inited = false;
}
}
typedef struct {
thread_start_routine_t start;
void* stack;
int stack_size;
void* arg;
} thread_wrapper_arg;
static void *vm_thread_wrapper(void *arg)
{
thread_wrapper_arg * targ = arg;
LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ);
targ->stack = (void *)((uintptr_t)(&arg) & ~0xfff);
_vm_tls_put(1, targ);
targ->start(targ->arg);
bh_free(targ);
_vm_tls_put(1, NULL);
return NULL;
}
int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
void *arg, unsigned int stack_size, int prio)
{
pthread_attr_t tattr;
thread_wrapper_arg *targ;
bh_assert(stack_size > 0);
bh_assert(tid);
bh_assert(start);
*tid = INVALID_THREAD_ID;
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
if (pthread_attr_setstacksize(&tattr, stack_size) != 0) {
bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u",
stack_size, PTHREAD_STACK_MIN);
pthread_attr_destroy(&tattr);
return BHT_ERROR;
}
targ = (thread_wrapper_arg*) bh_malloc(sizeof(*targ));
if (!targ) {
pthread_attr_destroy(&tattr);
return BHT_ERROR;
}
targ->start = start;
targ->arg = arg;
targ->stack_size = stack_size;
if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) {
pthread_attr_destroy(&tattr);
bh_free(targ);
return BHT_ERROR;
}
pthread_attr_destroy(&tattr);
return BHT_OK;
}
int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
unsigned int stack_size)
{
return _vm_thread_create_with_prio(tid, start, arg, stack_size,
BH_THREAD_DEFAULT_PRIORITY);
}
korp_tid _vm_self_thread()
{
return (korp_tid) pthread_self();
}
void vm_thread_exit(void * code)
{
bh_free(_vm_tls_get(1));
_vm_tls_put(1, NULL);
pthread_exit(code);
}
void *_vm_tls_get(unsigned idx)
{
bh_assert(idx < BH_MAX_TLS_NUM);
return pthread_getspecific(thread_local_storage_key[idx]);
}
int _vm_tls_put(unsigned idx, void * tls)
{
bh_assert(idx < BH_MAX_TLS_NUM);
pthread_setspecific(thread_local_storage_key[idx], tls);
return BHT_OK;
}
int _vm_mutex_init(korp_mutex *mutex)
{
return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_recursive_mutex_init(korp_mutex *mutex)
{
int ret;
pthread_mutexattr_t mattr;
bh_assert(mutex);
ret = pthread_mutexattr_init(&mattr);
if (ret)
return BHT_ERROR;
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
ret = pthread_mutex_init(mutex, &mattr);
pthread_mutexattr_destroy(&mattr);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_mutex_destroy(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_destroy(mutex);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
/* Returned error (EINVAL, EAGAIN and EDEADLK) from
locking the mutex indicates some logic error present in
the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_lock(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_lock(mutex);
if (0 != ret) {
printf("vm mutex lock failed (ret=%d)!\n", ret);
exit(-1);
}
}
int vm_mutex_trylock(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_trylock(mutex);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
/* Returned error (EINVAL, EAGAIN and EPERM) from
unlocking the mutex indicates some logic error present
in the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_unlock(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_unlock(mutex);
if (0 != ret) {
printf("vm mutex unlock failed (ret=%d)!\n", ret);
exit(-1);
}
}
int _vm_sem_init(korp_sem* sem, unsigned int c)
{
int ret;
bh_assert(sem);
ret = sem_init(sem, 0, c);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_sem_destroy(korp_sem *sem)
{
int ret;
bh_assert(sem);
ret = sem_destroy(sem);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_sem_wait(korp_sem *sem)
{
int ret;
bh_assert(sem);
ret = sem_wait(sem);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
/*int _vm_sem_reltimedwait(korp_sem *sem, int mills)
{
int ret = BHT_OK;
struct timespec timeout;
const int mills_per_sec = 1000;
const int mills_to_nsec = 1E6;
bh_assert(sem);
if (mills == BHT_WAIT_FOREVER) {
ret = sem_wait(sem);
} else {
timeout.tv_sec = mills / mills_per_sec;
timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec;
timeout.tv_sec += time(NULL);
ret = sem_timedwait(sem, &timeout);
}
if (ret != BHT_OK) {
if (errno == BHT_TIMEDOUT) {
ret = BHT_TIMEDOUT;
errno = 0;
} else {
bh_debug("Faliure happens when timed wait is called");
bh_assert(0);
}
}
return ret;
}
*/
int _vm_sem_post(korp_sem *sem)
{
bh_assert(sem);
return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_cond_init(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_init(cond, NULL) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_destroy(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_destroy(cond) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
{
bh_assert(cond);
bh_assert(mutex);
if (pthread_cond_wait(cond, mutex) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec)
{
struct timeval tv;
gettimeofday(&tv, NULL);
ts->tv_sec = tv.tv_sec + msec / 1000;
ts->tv_nsec = tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec;
if (ts->tv_nsec >= 1000000000L) {
ts->tv_sec++;
ts->tv_nsec -= 1000000000L;
}
}
int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
{
int ret;
struct timespec abstime;
if (mills == BHT_WAIT_FOREVER)
ret = pthread_cond_wait(cond, mutex);
else {
msec_nsec_to_abstime(&abstime, mills, 0);
ret = pthread_cond_timedwait(cond, mutex, &abstime);
}
if (ret != BHT_OK && ret != BHT_TIMEDOUT)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_signal(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_signal(cond) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_broadcast(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_broadcast(cond) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_thread_cancel(korp_tid thread)
{
return pthread_cancel(thread);
}
int _vm_thread_join(korp_tid thread, void **value_ptr, int mills)
{
return pthread_join(thread, value_ptr);
}
int _vm_thread_detach(korp_tid thread)
{
return pthread_detach(thread);
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_time.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/timeb.h>
#include <time.h>
/*
* This function returns milliseconds per tick.
* @return milliseconds per tick.
*/
uint64 _bh_time_get_tick_millisecond()
{
return sysconf(_SC_CLK_TCK);
}
/*
* This function returns milliseconds after boot.
* @return milliseconds after boot.
*/
uint64 _bh_time_get_boot_millisecond()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
return 0;
}
return ((uint64) ts.tv_sec) * 1000 + ts.tv_nsec / (1000 * 1000);
}
uint32 bh_get_tick_sec()
{
return _bh_time_get_boot_millisecond() / 1000;
}
/*
* This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time.
* @return milliseconds since from 1970.1.1.
*/
uint64 _bh_time_get_millisecond_from_1970()
{
struct timeb tp;
ftime(&tp);
return ((uint64) tp.time) * 1000 + tp.millitm
- (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + tp.timezone * 60 * 1000;
}
size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time)
{
time_t time_sec = time / 1000;
struct timeb tp;
struct tm *ltp;
ftime(&tp);
time_sec -= tp.timezone * 60;
ltp = localtime(&time_sec);
if (ltp == NULL) {
return 0;
}
return strftime(s, max, format, ltp);
}

View File

@ -0,0 +1,24 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
set (PLATFORM_SHARED_SOURCE ${source_all})

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_platform.h"
#include "bh_assert.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef BH_TEST
#include <setjmp.h>
#endif
#ifdef BH_TEST
/* for exception throwing */
jmp_buf bh_test_jb;
#endif
void bh_assert_internal(int v, const char *file_name, int line_number,
const char *expr_string)
{
if (v)
return;
if (!file_name)
file_name = "NULL FILENAME";
if (!expr_string)
expr_string = "NULL EXPR_STRING";
printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string,
file_name, line_number);
#ifdef BH_TEST
longjmp(bh_test_jb, 1);
#endif
abort();
}
void bh_debug_internal(const char *file_name, int line_number, const char *fmt,
...)
{
#ifndef JEFF_TEST_VERIFIER
va_list args;
va_start(args, fmt);
bh_assert(file_name);
printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number);
vprintf(fmt, args);
va_end(args);
printf("\n");
#endif
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_definition.h"
#include "bh_platform.h"
int bh_return(int ret)
{
return ret;
}
#define RSIZE_MAX 0x7FFFFFFF
int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n)
{
char *dest = (char*) s1;
char *src = (char*) s2;
if (n == 0) {
return 0;
}
if (s1 == NULL || s1max > RSIZE_MAX) {
return -1;
}
if (s2 == NULL || n > s1max) {
memset(dest, 0, s1max);
return -1;
}
memcpy(dest, src, n);
return 0;
}
int b_strcat_s(char * s1, size_t s1max, const char * s2)
{
if (NULL
== s1|| NULL == s2 || s1max < (strlen(s1) + strlen(s2) + 1) || s1max > RSIZE_MAX) {
return -1;
}
strcat(s1, s2);
return 0;
}
int b_strcpy_s(char * s1, size_t s1max, const char * s2)
{
if (NULL
== s1|| NULL == s2 || s1max < (strlen(s2) + 1) || s1max > RSIZE_MAX) {
return -1;
}
strncpy(s1, s2, s1max);
return 0;
}
int fopen_s(FILE ** pFile, const char *filename, const char *mode)
{
if (NULL == pFile || NULL == filename || NULL == mode) {
return -1;
}
*pFile = fopen(filename, mode);
if (NULL == *pFile)
return -1;
return 0;
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_common.h"
#include "bh_platform.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FIXED_BUFFER_SIZE (1<<14)
static bh_print_function_t print_function = NULL;
char *bh_strdup(const char *s)
{
char *s1 = NULL;
if (s && (s1 = bh_malloc(strlen(s) + 1)))
memcpy(s1, s, strlen(s) + 1);
return s1;
}
int bh_platform_init()
{
return 0;
}
int putchar(int c)
{
return 0;
}
int puts(const char *s)
{
return 0;
}
void bh_set_print_function(bh_print_function_t pf)
{
print_function = pf;
}
int bh_printf_sgx(const char *message, ...)
{
if (print_function != NULL) {
char msg[FIXED_BUFFER_SIZE] = { '\0' };
va_list ap;
va_start(ap, message);
vsnprintf(msg, FIXED_BUFFER_SIZE, message, ap);
va_end(ap);
print_function(msg);
}
return 0;
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BH_PLATFORM_H
#define _BH_PLATFORM_H
#include "bh_config.h"
#include "bh_types.h"
#include "bh_memory.h"
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include <limits.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int bh_printf_sgx(const char *message, ...);
typedef uint64_t uint64;
typedef int64_t int64;
#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0)
#define BH_PLATFORM "Linux-SGX"
/* NEED qsort */
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0
#define BH_ROUTINE_MODIFIER
#define BHT_TIMEDOUT ETIMEDOUT
#define INVALID_THREAD_ID 0xFFffFFff
typedef int korp_tid;
typedef int korp_mutex;
typedef int korp_sem;
typedef int korp_cond;
typedef int korp_thread;
typedef void* (*thread_start_routine_t)(void*);
#define wa_malloc bh_malloc
#define wa_free bh_free
#define wa_strdup bh_strdup
int snprintf(char *buffer, size_t count, const char *format, ...);
double fmod(double x, double y);
float fmodf(float x, float y);
double sqrt(double x);
#define BH_WAIT_FOREVER 0xFFFFFFFF
#ifndef NULL
# define NULL ((void*) 0)
#endif
/**
* Return the offset of the given field in the given type.
*
* @param Type the type containing the filed
* @param field the field in the type
*
* @return the offset of field in Type
*/
#ifndef offsetof
#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
#endif
#define bh_assert assert
int b_memcpy_s(void * s1, unsigned int s1max, const void * s2,
unsigned int n);
int b_strcat_s(char * s1, size_t s1max, const char * s2);
int b_strcpy_s(char * s1, size_t s1max, const char * s2);
char *bh_strdup(const char *s);
int bh_platform_init();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_platform.h"
#include <stdio.h>
void bh_log_emit(const char *fmt, va_list ap)
{
vprintf(fmt, ap);
fflush(stdout);
}
int bh_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vfprintf(stream ? stream : stdout, fmt, ap);
va_end(ap);
return ret;
}
int bh_fflush(void *stream)
{
return fflush(stream ? stream : stdout);
}

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_thread.h"
#include "bh_assert.h"
#include "bh_memory.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int _vm_thread_sys_init()
{
return 0;
}
void vm_thread_sys_destroy(void)
{
}
int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
void *arg, unsigned int stack_size, int prio)
{
return BHT_ERROR;
// return BHT_OK;
}
int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
unsigned int stack_size)
{
return _vm_thread_create_with_prio(tid, start, arg, stack_size,
BH_THREAD_DEFAULT_PRIORITY);
}
korp_tid _vm_self_thread()
{
return 0;
}
void vm_thread_exit(void * code)
{
}
// storage for one thread
static void *_tls_store = NULL;
void *_vm_tls_get(unsigned idx)
{
return _tls_store;
}
int _vm_tls_put(unsigned idx, void * tls)
{
_tls_store = tls;
return BHT_OK;
//return BHT_ERROR;
}
int _vm_mutex_init(korp_mutex *mutex)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_recursive_mutex_init(korp_mutex *mutex)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_mutex_destroy(korp_mutex *mutex)
{
return BHT_OK;
//return BHT_ERROR;
}
/* Returned error (EINVAL, EAGAIN and EDEADLK) from
locking the mutex indicates some logic error present in
the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_lock(korp_mutex *mutex)
{
}
int vm_mutex_trylock(korp_mutex *mutex)
{
return BHT_OK;
//return BHT_ERROR;
}
/* Returned error (EINVAL, EAGAIN and EPERM) from
unlocking the mutex indicates some logic error present
in the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_unlock(korp_mutex *mutex)
{
}
int _vm_sem_init(korp_sem* sem, unsigned int c)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_sem_destroy(korp_sem *sem)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_sem_wait(korp_sem *sem)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_sem_reltimedwait(korp_sem *sem, int mills)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_sem_post(korp_sem *sem)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_cond_init(korp_cond *cond)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_cond_destroy(korp_cond *cond)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_cond_signal(korp_cond *cond)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_cond_broadcast(korp_cond *cond)
{
return BHT_OK;
//return BHT_ERROR;
}
int _vm_thread_cancel(korp_tid thread)
{
return 0;
}
int _vm_thread_join(korp_tid thread, void **value_ptr, int mills)
{
return 0;
}
int _vm_thread_detach(korp_tid thread)
{
return 0;
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_time.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/timeb.h>
#include <time.h>
/*
* This function returns milliseconds per tick.
* @return milliseconds per tick.
*/
uint64 _bh_time_get_tick_millisecond()
{
return sysconf(_SC_CLK_TCK);
}
/*
* This function returns milliseconds after boot.
* @return milliseconds after boot.
*/
uint64 _bh_time_get_boot_millisecond()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
return 0;
}
return ((uint64) ts.tv_sec) * 1000 + ts.tv_nsec / (1000 * 1000);
}
uint32 bh_get_tick_sec()
{
return _bh_time_get_boot_millisecond() / 1000;
}
/*
* This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time.
* @return milliseconds since from 1970.1.1.
*/
uint64 _bh_time_get_millisecond_from_1970()
{
struct timeb tp;
ftime(&tp);
return ((uint64) tp.time) * 1000 + tp.millitm
- (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + tp.timezone * 60 * 1000;
}
size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time)
{
time_t time_sec = time / 1000;
struct timeb tp;
struct tm *ltp;
ftime(&tp);
time_sec -= tp.timezone * 60;
ltp = localtime(&time_sec);
if (ltp == NULL) {
return 0;
}
return strftime(s, max, format, ltp);
}

View File

@ -0,0 +1,24 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
set (PLATFORM_SHARED_SOURCE ${source_all})

268
doc/building.md Normal file
View File

@ -0,0 +1,268 @@
Build WAMR Core
=========================
Please follow the instructions below to build the WAMR core on different platforms.
Linux
-------------------------
First of all please install library dependencies of lib gcc.
Use installation commands below for Ubuntu Linux:
``` Bash
sudo apt install lib32gcc-5-dev g++-multilib
```
Or in Fedora:
``` Bash
sudo dnf install glibc-devel.i686
```
After installing dependencies, build the source code:
``` Bash
cd core/iwasm/products/linux/
mkdir build
cd build
cmake ..
make
```
Mac
-------------------------
Make sure to install Xcode from App Store firstly, and install cmake.
If you use Homebrew, install cmake from the command line:
``` Bash
brew install cmake
```
Then build the source codes:
```
cd core/iwasm/products/darwin/
mkdir build
cd build
cmake ..
make
```
VxWorks
-------------------------
VxWorks 7 SR0620 release is validated.
First you need to build a VSB. Make sure *UTILS_UNIX* layer is added in the VSB.
After the VSB is built, export the VxWorks toolchain path by:
```
export <vsb_dir_path>/host/vx-compiler/bin:$PATH
```
Now switch to iwasm source tree to build the source code:
```
cd core/iwasm/products/vxworks/
mkdir build
cd build
cmake ..
make
```
Create a VIP based on the VSB. Make sure the following components are added:
* INCLUDE_POSIX_PTHREADS
* INCLUDE_POSIX_PTHREAD_SCHEDULER
* INCLUDE_SHARED_DATA
* INCLUDE_SHL
Copy the generated iwasm executable, the test WASM binary as well as the needed
shared libraries (libc.so.1, libllvm.so.1 or libgnu.so.1 depending on the VSB,
libunix.so.1) to a supported file system (eg: romfs).
Zephyr
-------------------------
You need to download the Zephyr source code first and embed WAMR into it.
``` Bash
git clone https://github.com/zephyrproject-rtos/zephyr.git
cd zephyr/samples/
cp -a <iwasm_dir>/products/zephyr/simple .
cd simple
ln -s <iwam_dir> iwasm
ln -s <shared_lib_dir> shared-lib
mkdir build && cd build
source ../../../zephyr-env.sh
cmake -GNinja -DBOARD=qemu_x86 ..
ninja
```
AliOS-Things
-------------------------
1. a developerkit board id needed for testing
2. download the AliOS-Things code
``` Bash
git clone https://github.com/alibaba/AliOS-Things.git
```
3. copy <iwasm_root_dir>/products/alios-things directory to AliOS-Things/middleware, and rename it as iwasm
``` Bash
cp -a <iwasm_root_dir>/products/alios-things middleware/iwasm
```
4. create a link to <iwasm_root_dir> in middleware/iwasm/ and rename it to iwasm
``` Bash
ln -s <iwasm_root_dir> middleware/iwasm/iwasm
```
5. create a link to <shared-lib_root_dir> in middleware/iwasm/ and rename it to shared-lib
``` Bash
ln -s <shared-lib_root_dir> middle/iwasm/shared-lib
```
6. modify file app/example/helloworld/helloworld.c, patch as:
``` C
#include <stdbool.h>
#include <aos/kernel.h>
extern bool iwasm_init();
int application_start(int argc, char *argv[])
{
int count = 0;
iwasm_init();
...
}
```
7. modify file app/example/helloworld/aos.mk
``` C
$(NAME)_COMPONENTS := osal_aos iwasm
```
8. build source code
``` Bash
aos make helloworld@developerkit -c config
aos make
```
9. download the binary to developerkit board, check the output from serial port
Docker
-------------------------
[Docker](https://www.docker.com/) will download all the dependencies and build WAMR Core on your behalf.
Make sure you have Docker installed on your machine: [macOS](https://docs.docker.com/docker-for-mac/install/), [Windows](https://docs.docker.com/docker-for-windows/install/) or [Linux](https://docs.docker.com/install/linux/docker-ce/ubuntu/).
Build the Docker image:
``` Bash
docker build --rm -f "Dockerfile" -t wamr:latest .
```
Run the image in interactive mode:
``` Bash
docker run --rm -it wamr:latest
```
You'll now enter the container at `/root`.
Build WASM app
=========================
You can write a simple ```test.c``` as the first sample.
```C
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buf;
printf("Hello world!\n");
buf = malloc(1024);
if (!buf) {
printf("malloc buf failed\n");
return -1;
}
printf("buf ptr: %p\n", buf);
sprintf(buf, "%s", "1234\n");
printf("buf: %s", buf);
free(buf);
return 0;
}
```
There are three methods to build a WASM binary. They are Emscripten, the clang compiler and Docker.
## Use Emscripten tool
A method to build a WASM binary is to use Emscripten tool ```emcc```.
Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below:
```
git clone https://github.com/emscripten-core/emsdk.git
emsdk install latest
emsdk activate latest
```
source ```./emsdk_env.sh```.
The Emscripten website provides other installation methods beyond Linux.
Use the emcc command below to build the WASM C source code into the WASM binary.
``` Bash
emcc -g -O3 *.c -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
-s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 -o test.wasm
```
You will get ```test.wasm``` which is the WASM app binary.
## Use clang compiler
Another method to build a WASM binary is to use clang compiler```clang-8```.
Add source to your system source list from llvm website, for ubuntu16.04, add following lines to /etc/apt/sources.list:
```Bash
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main # 7
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main # 8
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
```
Download and install clang-8 tool-chain using following commands:
```Bash
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install llvm-8 lld-8 clang-8
```
Create a soft link under /usr/bin:
```Bash
cd /usr/bin
sudo ln -s wasm-ld-8 wasm-ld
```
Use the clang-8 command below to build the WASM C source code into the WASM binary.
```Bash
clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main,
--no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c
```
You will get ```test.wasm``` which is the WASM app binary.
## Using Docker
The last method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future.
Use the clang-8 command below to build the WASM C source code into the WASM binary.
```Bash
clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main,
--no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c
```
You will get ```test.wasm``` which is the WASM app binary.
Run WASM app
========================
Assume you are using Linux, the command to run the test.wasm is:
``` Bash
cd iwasm/products/linux/build
./iwasm test.wasm
```
You will get the following output:
```
Hello world!
buf ptr: 0x400002b0
buf: 1234
```
If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute:
```
ninja run
```

40
doc/embed_wamr.md Normal file
View File

@ -0,0 +1,40 @@
Embed WAMR into software production
=====================================
![WAMR embed diagram](./pics/embed.PNG "WAMR embed architecture diagram")
A typical WAMR API usage is shown below (some return value checks are ignored):
``` C
static char global_heap_buf[512 * 1024];
char *buffer;
wasm_module_t module;
wasm_module_inst_t inst;
wasm_function_inst_t func;
wasm_exec_env_t env;
uint32 argv[2];
bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf));
wasm_runtime_init();
buffer = read_wasm_binary_to_buffer(…);
module = wasm_runtime_load(buffer, size, err, err_size);
inst = wasm_runtime_instantiate(module, 0, 0, err, err_size);
func = wasm_runtime_lookup_function(inst, "fib", "(i32)i32");
env = wasm_runtime_create_exec_env(stack_size);
argv[0] = 8;
if (!wasm_runtime_call_wasm(inst, env, func, 1, argv_buf) ) {
wasm_runtime_clear_exception(inst);
}
/* the return value is stored in argv[0] */
printf("fib function return: %d\n", argv[0]);
wasm_runtime_destory_exec_env(env);
wasm_runtime_deinstantiate(inst);
wasm_runtime_unload(module);
wasm_runtime_destroy();
bh_memory_destroy();
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

BIN
doc/pics/vgl_demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
doc/pics/vgl_demo2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Some files were not shown because too many files have changed in this diff Show More