Enable register native with iwasm (#1120)

Enable register native with iwasm application, add sample and update document.
This commit is contained in:
Wenyong Huang 2022-04-27 11:12:50 +08:00 committed by GitHub
parent 9013a474bc
commit 2007ba38cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 374 additions and 13 deletions

View File

@ -129,6 +129,14 @@ 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

View File

@ -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;

View File

@ -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

View File

@ -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)

View 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)

View 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
```

View 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);
}

View 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);
}

View 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)

View 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;
}

View File

@ -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)