wasm-micro-runtime
wasm-micro-runtime copied to clipboard
Runtime Dynamic Linking
Hi,
I was wondering if you have any plan for adding support for runtime linking like dlopen
and dlsym
for webassembly in the future? If not, may I ask what is the main difficulty in your mind?
void* handle = dlopen("library.wasm", 0);
int (*fun_ptr)()= dlsym(handle, "foo");
(*fun_ptr)();
The corresponding web assembly code.
i32.const 1024
i32.const 0
call 1
i32.const 1037
call 2
call_indirect (type 0)
Hi,
The biggest problem of dlsym is: you need to call a function in another module, the function index does not exists in current module, so the call_indirect
instruction can't find the valid function instance to call.
As a workaround, we can use some runtime wrappers to achieve this. When we get the function pointer from dlsym
, we need to use a runtime wrapper to call this function rather than invoke the function pointer directly:
typedef int (*TestFunc)(int);
int main()
{
int ret;
void *handle;
TestFunc test_func;
handle = dlopen("app.wasm", 0);
test_func = (TestFunc)dlsym(handle, "test_func");
// don't use ret = (*test_func)(1);
ret = invoke_test_func(test_func, 1);
}
The invoke_test_func
is a runtime wrapper, it will call the test_func
in the other module instance and return the value. We have a patch to test this functionality, you can have a try.
test-dlsym.tar.gz
You can use the build.sh
to compile app.wasm
and test.wasm
, and then apply the patch to WAMR, rebuild iwasm, and run
iwasm test.wasm
However, this is just a simple test, there are some other problems. For example, you can't pass a buffer to the function from library.wasm
as they are in different module instance, you will need to malloc a space in library.wasm
by using wasm_runtime_module_malloc
and copy the content of the buffer.
Hi,
The biggest problem of dlsym is: you need to call a function in another module, the function index does not exists in current module, so the
call_indirect
instruction can't find the valid function instance to call.As a workaround, we can use some runtime wrappers to achieve this. When we get the function pointer from
dlsym
, we need to use a runtime wrapper to call this function rather than invoke the function pointer directly:typedef int (*TestFunc)(int); int main() { int ret; void *handle; TestFunc test_func; handle = dlopen("app.wasm", 0); test_func = (TestFunc)dlsym(handle, "test_func"); // don't use ret = (*test_func)(1); ret = invoke_test_func(test_func, 1); }
The
invoke_test_func
is a runtime wrapper, it will call thetest_func
in the other module instance and return the value. We have a patch to test this functionality, you can have a try. test-dlsym.tar.gzYou can use the
build.sh
to compileapp.wasm
andtest.wasm
, and then apply the patch to WAMR, rebuild iwasm, and runiwasm test.wasm
However, this is just a simple test, there are some other problems. For example, you can't pass a buffer to the function from
library.wasm
as they are in different module instance, you will need to malloc a space inlibrary.wasm
by usingwasm_runtime_module_malloc
and copy the content of the buffer.
Hi @xujuntwt95329 ,
I use your patch and dlsym
works. nice work.
Besides, I got a question about build.sh
, for the option -nostdlib
. When I build wasm file use default build.sh
in your patch and run it, an error occured:
Exception: fail to call unlinked import function (env, iprintf)
Then I remove -nostdlib
and build again, it works perfectly.
I just wonder how these happened, and the reason for using options -nostdlib
.
Thanks!
Exception: fail to call unlinked import function (env, iprintf)
iprintf
is not a libc API, I guess you mean printf
?
If you pass -nostdlib
option when building wasm module, then you need to build runtime with WAMR_BUILD_LIBC_BUILTIN=1
, in this case, the printf
will be treated as an import function, WAMR's libc-builtin library has provided wrapper for printf
If you remove -nostdlib
option, then the wasm module is compiled as WASI mode, the implementation of printf
is compiled to wasm and statically linked into your wasm module.
Please refer to build wasm app for more details.
Hope this can help you. Thanks!
Exception: fail to call unlinked import function (env, iprintf)
iprintf
is not a libc API, I guess you meanprintf
? If you pass-nostdlib
option when building wasm module, then you need to build runtime withWAMR_BUILD_LIBC_BUILTIN=1
, in this case, theprintf
will be treated as an import function, WAMR's libc-builtin library has provided wrapper forprintf
If you remove
-nostdlib
option, then the wasm module is compiled as WASI mode, the implementation ofprintf
is compiled to wasm and statically linked into your wasm module.Please refer to build wasm app for more details.
Hope this can help you. Thanks!
Sorry for not read the docs carefully, this helps a lot, thanks!
Hi,
The biggest problem of dlsym is: you need to call a function in another module, the function index does not exists in current module, so the
call_indirect
instruction can't find the valid function instance to call.As a workaround, we can use some runtime wrappers to achieve this. When we get the function pointer from
dlsym
, we need to use a runtime wrapper to call this function rather than invoke the function pointer directly:typedef int (*TestFunc)(int); int main() { int ret; void *handle; TestFunc test_func; handle = dlopen("app.wasm", 0); test_func = (TestFunc)dlsym(handle, "test_func"); // don't use ret = (*test_func)(1); ret = invoke_test_func(test_func, 1); }
The
invoke_test_func
is a runtime wrapper, it will call thetest_func
in the other module instance and return the value. We have a patch to test this functionality, you can have a try. test-dlsym.tar.gzYou can use the
build.sh
to compileapp.wasm
andtest.wasm
, and then apply the patch to WAMR, rebuild iwasm, and runiwasm test.wasm
However, this is just a simple test, there are some other problems. For example, you can't pass a buffer to the function from
library.wasm
as they are in different module instance, you will need to malloc a space inlibrary.wasm
by usingwasm_runtime_module_malloc
and copy the content of the buffer.
Hi,
I said your patch works great on my environment, but I find I was wrong. -_-
Now 2 problems encountered:
- in
dlsym_wrapper
, I findwasm_runtime_lookup_function
's return valuefunc
is smaller than((AOTModuleInstance*)app_module_inst)->func_ptrs.ptr
, leads tofunc_index
a negative value (overflow to a very large integer), then things start to go wrong. - sometimes (about 1/7) problem 1 not show up, then, when carry out
wasm_runtime_call_wasm
ininvoke_test_func_wrapper
, I got this error:
func name: unhandled SIGSEGV, si_addr: 0xffffffffffffffe0
Floating point exception (core dumped)
Sorry for cannot upload screenshots about these problems. Hope for some helps.
Thanks!