英文:
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 
_initializethat just calls__wasm_call_ctors - call 
_initializefrom the runtime as a 1st thing once the WASM module
is loaded 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论