Enable AoT and wamr-sdk, and change arguments of call wasm API (#157)
* Implement memory profiler, optimize memory usage, modify code indent * Implement memory.grow and limit heap space base offset to 1G; modify iwasm build type to Release and 64 bit by default * Add a new extension library: connection * Fix bug of reading magic number and version in big endian platform * Re-org platform APIs: move most platform APIs from iwasm to shared-lib * Enhance wasm loader to fix some security issues * Fix issue about illegal load of EXC_RETURN into PC on stm32 board * Updates that let a restricted version of the interpreter run in SGX * Enable native/app address validation and conversion for wasm app * Remove wasm_application_exectue_* APIs from wasm_export.h which makes confused * Refine binary size and fix several minor issues Optimize interpreter LOAD/STORE opcodes to decrease the binary size Fix issues when using iwasm library: _bh_log undefined, bh_memory.h not found Remove unused _stdin/_stdout/_stderr global variables resolve in libc wrapper Add macros of global heap size, stack size, heap size for Zephyr main.c Clear compile warning of wasm_application.c * Add more strict security checks for libc wrapper API's * Use one libc wrapper copy for sgx and other platforms; remove bh_printf macro for other platform header files * Enhance security of libc strcpy/sprintf wrapper function * Fix issue of call native for x86_64/arm/mips, add module inst parameter for native wrapper functions * Remove get_module_inst() and fix issue of call native * Refine wgl lib: remove module_inst parameter from widget functions; move function index check to runtime instantiate * Refine interpreter call native process, refine memory boudary check * Fix issues of invokeNative function of arm/mips/general version * Add a switch to build simple sample without gui support * Add BUILD_TARGET setting in makefile to replace cpu compiler flags in source code * Re-org shared lib header files, remove unused info; fix compile issues of vxworks * Add build target general * Remove unused files * Update license header * test push * Restore file * Sync up with internal/feature * Sync up with internal/feature * Rename build_wamr_app to build_wasm_app * Fix small issues of README * Enhance malformed wasm file checking Fix issue of print hex int and implement utf8 string check Fix wasi file read/write right issue Fix minor issue of build wasm app doc * Sync up with internal/feature * Sync up with internal/feature: fix interpreter arm issue, fix read leb issue * Sync up with internal/feature * Fix bug of config.h and rename wasi config.h to ssp_config.h * Sync up with internal/feature * Import wamr aot * update document * update document * Update document, disable WASI in 32bit * update document * remove files * update document * Update document * update document * update document * update samples * Sync up with internal repo
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
|
||||
The mechanism of exporting native API to WASM application
|
||||
Export native API to WASM application
|
||||
=======================================================
|
||||
|
||||
The basic working flow for WASM application calling into the native API is shown in the following diagram:
|
||||
@ -21,16 +21,105 @@ static NativeSymbol extended_native_symbol_defs[] = {
|
||||
};
|
||||
```
|
||||
|
||||
 **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:
|
||||
**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.
|
||||
|
||||
In wasm world:
|
||||
``` C
|
||||
void api_send_request(request_t * request, response_handler_f response_handler,
|
||||
void * user_data)
|
||||
{
|
||||
int size;
|
||||
char *buffer;
|
||||
transaction_t *trans;
|
||||
|
||||
if ((trans = (transaction_t *) malloc(sizeof(transaction_t))) == NULL) {
|
||||
printf(
|
||||
"send request: allocate memory for request transaction failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(trans, 0, sizeof(transaction_t));
|
||||
trans->handler = response_handler;
|
||||
trans->mid = request->mid;
|
||||
trans->time = wasm_get_sys_tick_ms();
|
||||
trans->user_data = user_data;
|
||||
|
||||
// pack request
|
||||
if ((buffer = pack_request(request, &size)) == NULL) {
|
||||
printf("send request: pack request failed!\n");
|
||||
free(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
transaction_add(trans);
|
||||
|
||||
/* if the trans is the 1st one, start the timer */
|
||||
if (trans == g_transactions) {
|
||||
/* assert(g_trans_timer == NULL); */
|
||||
if (g_trans_timer == NULL) {
|
||||
g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS,
|
||||
false,
|
||||
true, transaction_timeout_handler);
|
||||
}
|
||||
}
|
||||
|
||||
// call native API
|
||||
wasm_post_request(buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
```
|
||||
|
||||
In native world:
|
||||
``` C
|
||||
void
|
||||
wasm_post_request(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer = NULL;
|
||||
|
||||
// do boundary check
|
||||
if (!validate_app_addr(buffer_offset, size))
|
||||
return;
|
||||
|
||||
// do address conversion
|
||||
buffer = addr_app_to_native(buffer_offset);
|
||||
|
||||
if (buffer != NULL) {
|
||||
request_t req[1];
|
||||
|
||||
// De-serialize data
|
||||
if (!unpack_request(buffer, size, req))
|
||||
return;
|
||||
|
||||
// set sender to help dispatch the response to the sender app later
|
||||
unsigned int mod_id = app_manager_get_module_id(Module_WASM_App,
|
||||
module_inst);
|
||||
bh_assert(mod_id != ID_NONE);
|
||||
req->sender = mod_id;
|
||||
|
||||
if (req->action == COAP_EVENT) {
|
||||
am_publish_event(req);
|
||||
return;
|
||||
}
|
||||
|
||||
am_dispatch_request(req);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
<img src="./pics/safe.PNG" width="90%">
|
||||
|
||||
|
||||
Steps for exporting native API
|
||||
@ -38,79 +127,77 @@ 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 ```
|
||||
## Step 1: Define the native API for exporting
|
||||
|
||||
Define the function **example_native_func** in your source file, namely `example.c` here:
|
||||
``` C
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] =
|
||||
int example_native_func(wasm_exec_env_t exec_env,
|
||||
int arg1, int arg2)
|
||||
{
|
||||
};
|
||||
|
||||
#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
|
||||
// Your implementation here
|
||||
}
|
||||
```
|
||||
The first function argument must be defined using type **wasm_exec_env_t** which is the WAMR calling convention for native API exporting.
|
||||
|
||||
|
||||
// lib_export_dec.h
|
||||
#ifndef _LIB_EXPORT_DEC_H_
|
||||
#define _LIB_EXPORT_DEC_H_
|
||||
The function prototype should also be declared in a header file so the wasm application can include it.
|
||||
``` C
|
||||
#ifndef _EXAMPLE_H_
|
||||
#define _EXAMPLE_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void customized();
|
||||
void example_native_func(int arg1, int arg2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
## Step 2: Declare the native API exporting
|
||||
|
||||
// ext_lib_export.c
|
||||
#include "lib_export.h"
|
||||
#include "lib_export_dec.h"
|
||||
Declare the function **example_native_func** with macro **EXPORT_WASM_API** in your **.inl** file, namely `example.inl` in this sample.
|
||||
``` C
|
||||
EXPORT_WASM_API(example_native_func),
|
||||
```
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] =
|
||||
{
|
||||
EXPORT_WASM_API(customized)
|
||||
Then include the file **example.inl** in definition of array **extended_native_symbol_defs** in the `ext_lib_export.c`.
|
||||
``` C
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#include "example.inl"
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
## Step 3: Compile the runtime product
|
||||
Add the source file **example.c** and **ext_lib_export.c** into the CMakeList.txt for building runtime with the exported API's:
|
||||
``` cmake
|
||||
set (EXT_API_SOURCE example.c)
|
||||
|
||||
add_executable (sample
|
||||
# other source files
|
||||
# ......
|
||||
${EXT_API_SOURCE}
|
||||
ext_lib_export.c
|
||||
)
|
||||
```
|
||||
|
||||
# Use exported API in wasm application
|
||||
|
||||
We can call the exported native API **example_native_func** in wasm application like this:
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
#include "lib_export_dec.h" // provided by the platform vendor
|
||||
#include "example.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int I;
|
||||
char *buf = “abcd”;
|
||||
customized(); // customized API provided by the platform vendor
|
||||
return i;
|
||||
int a = 0, b = 1;
|
||||
|
||||
example_native_func(a, b);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user