mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-07 12:16:24 +00:00
Enable register native with iwasm (#1120)
Enable register native with iwasm application, add sample and update document.
This commit is contained in:
parent
9013a474bc
commit
2007ba38cf
|
@ -129,11 +129,19 @@ int main(int argc, char **argv)
|
|||
}
|
||||
```
|
||||
|
||||
## Build native lib into shared library and register it with `iwasm` application
|
||||
|
||||
Developer can also build the native library into a shared library and register it with iwasm application:
|
||||
```bash
|
||||
iwasm --native-lib=<lib file> <wasm file>
|
||||
```
|
||||
|
||||
Refer to [native lib sample](../samples/native-lib) for more details.
|
||||
|
||||
|
||||
## Buffer address conversion and boundary check
|
||||
|
||||
A WebAssembly sandbox ensures applications only access to its own memory with a private address space. When passing a pointer address from WASM to native, the address value must be converted to native address before the native function can access it. It is also the native world's responsibility to check the buffer length is not over its sandbox boundary.
|
||||
A WebAssembly sandbox ensures applications only access to its own memory with a private address space. When passing a pointer address from WASM to native, the address value must be converted to native address before the native function can access it. It is also the native world's responsibility to check the buffer length is not over its sandbox boundary.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "bh_read_file.h"
|
||||
|
@ -39,13 +42,18 @@ print_help()
|
|||
printf(" --dir=<dir> Grant wasi access to the given host directories\n");
|
||||
printf(" to the program, for example:\n");
|
||||
printf(" --dir=<dir1> --dir=<dir2>\n");
|
||||
printf(" --addr-pool= Grant wasi access to the given network addresses in\n");
|
||||
printf(" --addr-pool=<addrs> Grant wasi access to the given network addresses in\n");
|
||||
printf(" CIRD notation to the program, seperated with ',',\n");
|
||||
printf(" for example:\n");
|
||||
printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n");
|
||||
#endif
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
printf(" --native-lib=<lib> Register native libraries to the WASM module, which\n");
|
||||
printf(" are shared object (.so) files, for example:\n");
|
||||
printf(" --native-lib=test1.so --native-lib=test2.so\n");
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
printf(" --module-path= Indicate a module search path. default is current\n"
|
||||
printf(" --module-path=<path> Indicate a module search path. default is current\n"
|
||||
" directory('./')\n");
|
||||
#endif
|
||||
#if WASM_ENABLE_LIB_PTHREAD != 0
|
||||
|
@ -174,13 +182,57 @@ validate_env_str(char *env)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0
|
||||
#ifdef __NuttX__
|
||||
static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE * BH_KB] = { 0 };
|
||||
#else
|
||||
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
typedef uint32 (*get_native_lib_func)(char **p_module_name,
|
||||
NativeSymbol **p_native_symbols);
|
||||
|
||||
static uint32
|
||||
load_and_register_native_libs(const char **native_lib_list,
|
||||
uint32 native_lib_count,
|
||||
void **native_handle_list)
|
||||
{
|
||||
uint32 i, native_handle_count = 0, n_native_symbols;
|
||||
NativeSymbol *native_symbols;
|
||||
char *module_name;
|
||||
void *handle;
|
||||
|
||||
for (i = 0; i < native_lib_count; i++) {
|
||||
/* open the native library */
|
||||
if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL))
|
||||
&& !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) {
|
||||
LOG_WARNING("warning: failed to load native library %s",
|
||||
native_lib_list[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* lookup get_native_lib func */
|
||||
get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib");
|
||||
if (!get_native_lib) {
|
||||
LOG_WARNING("warning: failed to lookup `get_native_lib` function "
|
||||
"from native lib %s",
|
||||
native_lib_list[i]);
|
||||
dlclose(handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
n_native_symbols = get_native_lib(&module_name, &native_symbols);
|
||||
|
||||
/* register native symbols */
|
||||
if (!(n_native_symbols > 0 && module_name && native_symbols
|
||||
&& wasm_runtime_register_natives(module_name, native_symbols,
|
||||
n_native_symbols))) {
|
||||
LOG_WARNING("warning: failed to register native lib %s",
|
||||
native_lib_list[i]);
|
||||
dlclose(handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
native_handle_list[native_handle_count++] = handle;
|
||||
}
|
||||
|
||||
return native_handle_count;
|
||||
}
|
||||
#endif /* end of defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) */
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static char *
|
||||
|
@ -224,6 +276,14 @@ moudle_destroyer(uint8 *buffer, uint32 size)
|
|||
}
|
||||
#endif /* WASM_ENABLE_MULTI_MODULE */
|
||||
|
||||
#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0
|
||||
#ifdef __NuttX__
|
||||
static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE * BH_KB] = { 0 };
|
||||
#else
|
||||
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -249,6 +309,12 @@ main(int argc, char *argv[])
|
|||
const char *addr_pool[8] = { NULL };
|
||||
uint32 addr_pool_size = 0;
|
||||
#endif
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
const char *native_lib_list[8] = { NULL };
|
||||
uint32 native_lib_count = 0;
|
||||
void *native_handle_list[8] = { NULL };
|
||||
uint32 native_handle_count = 0, native_handle_idx;
|
||||
#endif
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
char *ip_addr = NULL;
|
||||
/* int platform_port = 0; */
|
||||
|
@ -337,6 +403,18 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
#endif /* WASM_ENABLE_LIBC_WASI */
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
else if (!strncmp(argv[0], "--native-lib=", 13)) {
|
||||
if (argv[0][13] == '\0')
|
||||
return print_help();
|
||||
if (native_lib_count >= sizeof(native_lib_list) / sizeof(char *)) {
|
||||
printf("Only allow max native lib number %d\n",
|
||||
(int)(sizeof(native_lib_list) / sizeof(char *)));
|
||||
return -1;
|
||||
}
|
||||
native_lib_list[native_lib_count++] = argv[0] + 13;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
else if (!strncmp(argv[0],
|
||||
"--module-path=", strlen("--module-path="))) {
|
||||
|
@ -407,6 +485,11 @@ main(int argc, char *argv[])
|
|||
bh_log_set_verbose_level(log_verbose_level);
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
native_handle_count = load_and_register_native_libs(
|
||||
native_lib_list, native_lib_count, native_handle_list);
|
||||
#endif
|
||||
|
||||
/* load WASM byte buffer from WASM bin file */
|
||||
if (!(wasm_file_buf =
|
||||
(uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
|
||||
|
@ -481,6 +564,13 @@ fail2:
|
|||
os_munmap(wasm_file_buf, wasm_file_size);
|
||||
|
||||
fail1:
|
||||
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
|
||||
/* unload the native libraries */
|
||||
for (native_handle_idx = 0; native_handle_idx < native_handle_count;
|
||||
native_handle_idx++)
|
||||
dlclose(native_handle_list[native_handle_idx]);
|
||||
#endif
|
||||
|
||||
/* destroy runtime environment */
|
||||
wasm_runtime_destroy();
|
||||
return 0;
|
||||
|
|
|
@ -40,7 +40,7 @@ print_help()
|
|||
printf(" --dir=<dir1> --dir=<dir2>\n");
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
printf(" --module-path= Indicate a module search path. default is current\n"
|
||||
printf(" --module-path=<path> Indicate a module search path. default is current\n"
|
||||
" directory('./')\n");
|
||||
#endif
|
||||
#if WASM_ENABLE_LIB_PTHREAD != 0
|
||||
|
|
|
@ -70,5 +70,5 @@ set (RUNTIME_SOURCE_ALL
|
|||
${UNCOMMON_SHARED_SOURCE}
|
||||
)
|
||||
add_executable (iwasm ${RUNTIME_SOURCE_ALL})
|
||||
target_link_libraries(iwasm vmlib -lpthread -lm)
|
||||
target_link_libraries(iwasm vmlib -lpthread -lm -ldl)
|
||||
|
||||
|
|
76
samples/native-lib/CMakeLists.txt
Normal file
76
samples/native-lib/CMakeLists.txt
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(native_lib)
|
||||
|
||||
################ runtime settings ##############
|
||||
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||
if (APPLE)
|
||||
add_definitions(-DBH_PLATFORM_DARWIN)
|
||||
endif ()
|
||||
|
||||
# Reset default linker flags
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||
|
||||
# WAMR features switch
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported are:
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
|
||||
set (WAMR_BUILD_TARGET "AARCH64")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||
set (WAMR_BUILD_TARGET "RISCV64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Build as X86_64 by default in 64-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_64")
|
||||
else ()
|
||||
# Build as X86_32 by default in 32-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_32")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE Release)
|
||||
endif ()
|
||||
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
set (WAMR_BUILD_FAST_INTERP 1)
|
||||
|
||||
# compiling and linking flags
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -fPIE")
|
||||
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif ()
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
|
||||
|
||||
# build out vmlib
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
################ wamr runtime ###################
|
||||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
set (RUNTIME_SOURCE_ALL
|
||||
${WAMR_ROOT_DIR}/product-mini/platforms/posix/main.c
|
||||
${UNCOMMON_SHARED_SOURCE}
|
||||
)
|
||||
|
||||
add_executable (iwasm ${RUNTIME_SOURCE_ALL})
|
||||
|
||||
target_link_libraries(iwasm vmlib -lpthread -lm -ldl)
|
||||
|
||||
################ native libraries ###############
|
||||
add_library (test_add SHARED test_add.c)
|
||||
add_library (test_sqrt SHARED test_sqrt.c)
|
||||
|
||||
################ wasm application ###############
|
||||
add_subdirectory(wasm-app)
|
59
samples/native-lib/README.md
Normal file
59
samples/native-lib/README.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
# "native-lib" sample introduction
|
||||
|
||||
This sample demonstrates how to write required interfaces in native library, build it into a shared library and register the shared library to iwasm.
|
||||
|
||||
The native library should provide `get_native_lib` API for iwasm to return the native library info, including the module name, the native symbol list and the native symbol count, so that iwasm can use them to regiter the native library, for example:
|
||||
|
||||
```C
|
||||
static int
|
||||
foo_wrapper(wasm_exec_env_t *exec_env, int x, int y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
#define REG_NATIVE_FUNC(func_name, signature) \
|
||||
{ #func_name, func_name##_wrapper, signature, NULL }
|
||||
|
||||
static NativeSymbol native_symbols[] = {
|
||||
REG_NATIVE_FUNC(foo, "(ii)i")
|
||||
};
|
||||
|
||||
uint32_t
|
||||
get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols)
|
||||
{
|
||||
*p_module_name = "env";
|
||||
*p_native_symbols = native_symbols;
|
||||
return sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
}
|
||||
```
|
||||
|
||||
## Preparation
|
||||
|
||||
Please install WASI SDK, download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`.
|
||||
|
||||
## Build the sample
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
`iwasm`, one wasm module `test.wasm` and two shared libraries `libtest_add.so`, `libtest_sqrt.so`
|
||||
will be generated.
|
||||
|
||||
## Run workload
|
||||
|
||||
```bash
|
||||
cd build
|
||||
./iwasm --native-lib=libtest_add.so --native-lib=libtest_sqrt.so wasm-app/test.wasm
|
||||
```
|
||||
|
||||
The output is:
|
||||
|
||||
```bash
|
||||
Hello World!
|
||||
10 + 20 = 30
|
||||
sqrt(10, 20) = 500
|
||||
```
|
32
samples/native-lib/test_add.c
Normal file
32
samples/native-lib/test_add.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "wasm_export.h"
|
||||
|
||||
static int
|
||||
test_add_wrapper(wasm_exec_env_t *exec_env, int x, int y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#define REG_NATIVE_FUNC(func_name, signature) \
|
||||
{ #func_name, func_name##_wrapper, signature, NULL }
|
||||
|
||||
static NativeSymbol native_symbols[] = {
|
||||
REG_NATIVE_FUNC(test_add, "(ii)i")
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
uint32_t
|
||||
get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols)
|
||||
{
|
||||
*p_module_name = "env";
|
||||
*p_native_symbols = native_symbols;
|
||||
return sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
}
|
32
samples/native-lib/test_sqrt.c
Normal file
32
samples/native-lib/test_sqrt.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "wasm_export.h"
|
||||
|
||||
static int
|
||||
test_sqrt_wrapper(wasm_exec_env_t *exec_env, int x, int y)
|
||||
{
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#define REG_NATIVE_FUNC(func_name, signature) \
|
||||
{ #func_name, func_name##_wrapper, signature, NULL }
|
||||
|
||||
static NativeSymbol native_symbols[] = {
|
||||
REG_NATIVE_FUNC(test_sqrt, "(ii)i")
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
uint32_t
|
||||
get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols)
|
||||
{
|
||||
*p_module_name = "env";
|
||||
*p_native_symbols = native_symbols;
|
||||
return sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
}
|
35
samples/native-lib/wasm-app/CMakeLists.txt
Normal file
35
samples/native-lib/wasm-app/CMakeLists.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(wasm-app)
|
||||
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
||||
|
||||
if (APPLE)
|
||||
set (HAVE_FLAG_SEARCH_PATHS_FIRST 0)
|
||||
set (CMAKE_C_LINK_FLAGS "")
|
||||
set (CMAKE_CXX_LINK_FLAGS "")
|
||||
endif ()
|
||||
|
||||
set (CMAKE_SYSTEM_PROCESSOR wasm32)
|
||||
set (CMAKE_SYSROOT ${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot)
|
||||
|
||||
if (NOT DEFINED WASI_SDK_DIR)
|
||||
set (WASI_SDK_DIR "/opt/wasi-sdk")
|
||||
endif ()
|
||||
|
||||
set (CMAKE_C_FLAGS "-nostdlib")
|
||||
set (CMAKE_C_COMPILER_TARGET "wasm32")
|
||||
set (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang")
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS
|
||||
"-Wl,--max-memory=131072 -z stack-size=8192 \
|
||||
-Wl,--no-entry,--strip-all \
|
||||
-Wl,--export=__main_argc_argv \
|
||||
-Wl,--export=__heap_base,--export=__data_end \
|
||||
-Wl,--allow-undefined"
|
||||
)
|
||||
|
||||
add_executable(test.wasm main.c)
|
||||
target_link_libraries(test.wasm)
|
29
samples/native-lib/wasm-app/main.c
Normal file
29
samples/native-lib/wasm-app/main.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
test_add(int x, int y);
|
||||
|
||||
int
|
||||
test_sqrt(int x, int y);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int x = 10, y = 20, res;
|
||||
|
||||
printf("Hello World!\n");
|
||||
|
||||
res = test_add(x, y);
|
||||
printf("%d + %d = %d\n", x, y, res);
|
||||
|
||||
res = test_sqrt(x, y);
|
||||
printf("sqrt(%d, %d) = %d\n", x, y, res);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -162,4 +162,4 @@ set (RUNTIME_SOURCE_ALL
|
|||
${UNCOMMON_SHARED_SOURCE}
|
||||
)
|
||||
add_executable (iwasm ${RUNTIME_SOURCE_ALL})
|
||||
target_link_libraries(iwasm vmlib -lpthread -lm)
|
||||
target_link_libraries(iwasm vmlib -lpthread -lm -ldl)
|
||||
|
|
Loading…
Reference in New Issue
Block a user