英文:
How to prevent wasi-sdk clang++ from inserting __wasm_call_ctors call to every exported function?
问题
I'm building C++ WASM application using wasi-sdk (versions 17 and 20 tested) clang++ as a compiler. I'm running the WASM code using WAMR in a custom embedded runtime. I use WAMR build-in libc instead of wasi-sdk's one. The application does not have main()
- it exports few functions that the runtime calls when necessary. The problem I have is that clang++ inserts calls to constructors of static objects to all of my entry points.
Sample code:
struct Bar
{
Bar() {}
};
Bar bar;
extern "C" void foo() {}
The build command I use is:
/opt/wasi-sdk/bin/clang++ -Wl,--no-entry -Wl,--allow-undefined -Wl,--export=foo -nostdlib -lc++ -lc++abi test.cpp
This results WASM code that calls c'tors every time (showing only foo export):
(func $foo (type 0)
return)
(func $foo.command_export (type 0)
call $__wasm_call_ctors <<< this is the problem
call $foo)
(export "foo" (func $foo.command_export))
-nostdlib -lc++ -lc++abi
are needed to get rid of wasi-sdk libc but still provide its C++ standard library. If I compile without these flags, the export is as expected:
(export "foo" (func $foo))
Question: how to prevent clang++ from inserting calls to static object c'tors?
英文:
I'm building C++ WASM application using wasi-sdk (versions 17 and 20 tested) clang++ as a compiler. I'm running the WASM code using WAMR in a custom embedded runtime. I use WAMR build-in libc instead of wasi-sdk's one. The application does not have main()
- it exports few functions that the runtime calls when necessary. The problem I have is that clang++ inserts calls to constructors of static objects to all of my entry points.
Sample code:
<!-- language: c++ -->
struct Bar
{
Bar() {}
};
Bar bar;
extern "C" void foo() {}
The build command I use is:
/opt/wasi-sdk/bin/clang++ -Wl,--no-entry -Wl,--allow-undefined -Wl,--export=foo -nostdlib -lc++ -lc++abi test.cpp
This results WASM code that calls c'tors every time (showing only foo export):
(func $foo (type 0)
return)
(func $foo.command_export (type 0)
call $__wasm_call_ctors <<< this is the problem
call $foo)
(export "foo" (func $foo.command_export)))
-nostdlib -lc++ -lc++abi are needed to get rid of wasi-sdk libc, but still provide it's C++ standard library. If I compile without these flags the export is as expected:
(export "foo" (func $foo)))
Question: how to prevent clang++ from inserting calls to static object c'tors?
答案1
得分: 1
问题在于 -Wl,--no-entry
移除了通常调用 __wasm_call_ctors
的 _start
函数。由于静态构造函数现在不再被调用,clang 决定在每个导出的函数中插入这些包装函数,以确保静态构造函数被调用。显然,这是一项特性 - 在这里有一个关于此的好讨论:https://reviews.llvm.org/D62922。
因此,解决方案是:
- 使用链接器标志
-mexec-model=reactor -nostdlib -lc++ -lc++abi
- 提供名为
_initialize
的 wasm 函数,该函数只调用__wasm_call_ctors
- 一旦加载 WASM 模块,从运行时作为第一步调用
_initialize
英文:
The problem was that -Wl,--no-entry
removed _start
function that normally calls __wasm_call_ctors
. As static c'tors were now not called, clang decided to insert those wrappers to each and every exported function to ensure statics constructors are called. Apparently this is a feature - here's a good discussion about this: https://reviews.llvm.org/D62922.
So the solution is to
- use linker flags
-mexec-model=reactor -nostdlib -lc++ -lc++abi
- provide wasm function
_initialize
that just calls__wasm_call_ctors
- call
_initialize
from the runtime as a 1st thing once the WASM module
is loaded
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论