Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to control the exported symbols of a side module? #23107

Open
EvanZhao1003 opened this issue Dec 9, 2024 · 3 comments
Open

How to control the exported symbols of a side module? #23107

EvanZhao1003 opened this issue Dec 9, 2024 · 3 comments

Comments

@EvanZhao1003
Copy link

EvanZhao1003 commented Dec 9, 2024

I used the -fvisibility=hidden option, but it doesn't seem to work completely.

side.cpp

#include<sstream>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif

extern "C"
{

EMSCRIPTEN_KEEPALIVE int Test()
{
	std::stringbuf buf;
	return buf.str().size();
}

}
em++ side.cpp -s SIDE_MODULE=2 -o side.wasm -fvisibility=hidden -v
version:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.73 (ac676d5e437525d15df5fd46bc2c208ec6d376a3)
clang version 20.0.0git (https:/github.com/llvm/llvm-project 1d810ece2b2c8fab77720493864257f0ea3336a9)

check the exported symbol in wat format

(export "__wasm_call_ctors" (func $0))
 (export "Test" (func $1))
 (export "_ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev" (func $4))

It's strange, is _ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev a system library symbol? Why is it being exported in the side module?

em++ main.cpp -s MAIN_MODULE=2 -o main.js -s AUTOLOAD_DYLIBS=0 side.wasm -fvisibility=hidden 
If I link it to a main module, I got 
(import "GOT.func" "_ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev" (global $gimport$4 (mut i32)))

If I instantiate main module without side.wasm, I got an undefined symbol error of _ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev

If there is a way to control the exported symbols of a side module? I want my side module to export only the symbols I need so that the initialization of the main module does not depend on any side module. This way, I can load the side modules on demand later.

@sbc100
Copy link
Collaborator

sbc100 commented Dec 9, 2024

_ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev is likely a template instantiation, which means it doesn't exist in libc++ per-say but in each of the object file that instantiates that particular template.

Because of the C++ one definition rule each module (or each TU) that instinstantatesantiates a template must define it as a weak symbol. This way it can exist in mulitple modules and the dynamic linker will pick just one of them at runtime. In this case the side module exports this definition and then also imports it via the GOT.func import. This is because the side module doesn't know if its definition will be the chosen one. i.e. the definition for that symbol could some from another module.

@EvanZhao1003
Copy link
Author

_ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev is likely a template instantiation, which means it doesn't exist in libc++ per-say but in each of the object file that instantiates that particular template.

Because of the C++ one definition rule each module (or each TU) that instinstantatesantiates a template must define it as a weak symbol. This way it can exist in mulitple modules and the dynamic linker will pick just one of them at runtime. In this case the side module exports this definition and then also imports it via the GOT.func import. This is because the side module doesn't know if its definition will be the chosen one. i.e. the definition for that symbol could some from another module.

c++filt _ZNSt3__215basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev 
std::__2::basic_stringbuf<char, std::__2::char_traits<char>, std::__2::allocator<char> >::~basic_stringbuf()

I understand what you mean, thank you for your explanation. However, I think the main module should at least initialize successfully on its own since I used the AUTOLOAD_DYLIBS=0 option. It should only throw an error later if a symbol is needed but the side module hasn't been loaded yet.

@sbc100
Copy link
Collaborator

sbc100 commented Dec 9, 2024

It should only throw an error later if a symbol is needed but the side module hasn't been loaded yet.

That does sounds correct yes. Sounds like a different issue, but one that is probably worth fixing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants