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

__wasm_longjmp not linked from compiler_rt-wasm-sjlj when using WASM standards flags #22566

Open
samcamwilliams opened this issue Sep 13, 2024 · 5 comments

Comments

@samcamwilliams
Copy link
Contributor

Version of emscripten/emsdk:

root@94a580f5afba:/temp/libcompiler# emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.65 (7f8a05dd4e37cbd7ffde6d624f91fd545f7b52e3)
clang version 20.0.0git (https:/github.com/llvm/llvm-project 547917aebd1e79a8929b53f0ddf3b5185ee4df74)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /emsdk/upstream/bin

This is the version installed by the latest emsdk Docker image.

Failing command line in full:

emcc -O3 -g2 -sWASM=1 -sMEMORY64=1 -sSTANDALONE_WASM=1 -sPURE_WASI=1 -fwasm-exceptions -s STACK_SIZE=33554432 -s INITIAL_MEMORY=50331648 -s DETERMINISTIC=1 -s NODERAWFS=0 -s FORCE_FILESYSTEM=1 -msimd128 --pre-js /opt/pre.js -I /lua-5.3.4/src /tmp/compile.c /lua-5.3.4/src/liblua.a -s EXPORTED_FUNCTIONS=["_malloc", "_main"] -lm -ldl -o process.js -s EXPORTED_RUNTIME_METHODS=["cwrap"]

Full link command and output with -v appended:

 /emsdk/upstream/bin/wasm-ld -o process.wasm -L/opt/aolibc -l:aolibc.a /tmp/emscripten_temp_q176g42i/compile_0.o /lua-5.3.4/src/liblua.a -L/emsdk/upstream/emscripten/cache/sysroot/lib/wasm64-emscripten /emsdk/upstream/emscripten/cache/sysroot/lib/wasm64-emscripten/crt1.o -lGL-getprocaddr -lal -lhtml5 -lstandalonewasm-pure -lstubs -lc -ldlmalloc -lcompiler_rt -lc++-except -lc++abi-except -lunwind-except -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -disable-lsr -mllvm -wasm-enable-eh -mllvm -exception-model=wasm -mwasm64 /tmp/tmpgpo8kinflibemscripten_js_symbols.so --export=malloc --export=main --export=sbrk --export=__trap --export=_emscripten_stack_alloc --export=_emscripten_stack_restore --export=emscripten_stack_get_current --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=__main_argc_argv --export-table -z stack-size=33554432 --no-growable-memory --initial-memory=50331648 --table-base=1 --global-base=1024
 /emsdk/upstream/bin/llvm-objcopy process.wasm process.wasm --remove-section=.debug* --remove-section=producers
 /emsdk/node/18.20.3_64bit/bin/node /emsdk/upstream/emscripten/src/compiler.mjs /tmp/tmppjvvytlf.json
error: undefined symbol: __wasm_longjmp (referenced by root reference (e.g. compiled C/C++ code))
warning: To disable errors for undefined symbols use `-sERROR_ON_UNDEFINED_SYMBOLS=0`
warning: ___wasm_longjmp may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
Error: Aborting compilation due to previous errors

I have been trying to build a 64-bit program with emcc to be as closely bound by the (granted, experimental) standards as possible. I am using -sWASM=1 -sMEMORY64=1 -sSTANDALONE_WASM=1 -sPURE_WASI=1 -fwasm-exceptions as compile-time options to attempt to achieve this. However this leads to emcc attempting to link against -lcompiler_rt rather than libcompiler_rt-wasm-sjlj, yielding the above undefined symbol: __wasm_longjmp issue.

I 'fixed' it by running embuilder --wasm64 build libcompiler_rt-wasm-sjlj, followed by adding -lcompiler_rt-wasm-sjlj to the compilation arguments. I noticed that in embuilder.py it claims that the user is not supposed to need to run it directly, so I assume that emcc is just not selecting the right library for the linker -- or my compile options just don't make sense together. I am relatively new to building with Emscripten so it is possible that I am missing something basic.

Thanks for building Emscripten!

@sbc100
Copy link
Collaborator

sbc100 commented Sep 18, 2024

Yes, IIUC -fwasm-exceptions is supposed to imply -sSUPPORT_LONGJMP=wasm which in turn should select libcompiler_rt-wasm-sjlj. Looks like a bug to me. @aheejin any ideas?

@aheejin
Copy link
Member

aheejin commented Sep 19, 2024

This is due to

emscripten/tools/link.py

Lines 802 to 805 in 893e0a9

if settings.PURE_WASI:
settings.STANDALONE_WASM = 1
settings.WASM_BIGINT = 1
settings.SUPPORT_LONGJMP = 0

PURE_WASI mode cannot use JS so I guess that line was meant to disable Emscripten SjLj support, right? @sbc100 (It was added in #21555)

But it accidentally ended up disabling support for Wasm SjLj as well. I think

if settings.PURE_WASI:
  ...
  if settings.SUPPORT_LONGJMP == 'emscripten':
    settings.SUPPORT_LONGJMP = 0

can fix this.

I can go ahead and make this change, but before that, aren't we supposed to also disable Emscripten EH when PURE_WASI is set? Currently Emscripten EH seems to compile and link without problem even with PURE_WASI set.

@sbc100
Copy link
Collaborator

sbc100 commented Sep 19, 2024

This is due to

emscripten/tools/link.py

Lines 802 to 805 in 893e0a9

if settings.PURE_WASI:
settings.STANDALONE_WASM = 1
settings.WASM_BIGINT = 1
settings.SUPPORT_LONGJMP = 0

PURE_WASI mode cannot use JS so I guess that line was meant to disable Emscripten SjLj support, right? @sbc100 (It was added in #21555)

But it accidentally ended up disabling support for Wasm SjLj as well. I think

if settings.PURE_WASI:
  ...
  if settings.SUPPORT_LONGJMP == 'emscripten':
    settings.SUPPORT_LONGJMP = 0

can fix this.

I can go ahead and make this change, but before that, aren't we supposed to also disable Emscripten EH when PURE_WASI is set? Currently Emscripten EH seems to compile and link without problem even with PURE_WASI set.

I don't think we want to prevent folks from experimenting with Emscripten EH or Emscripten SJLJ in PURE_WASI mode. I think the indent here was to change the defaults. So maybe doing default_settings('SUPPORT_LONGJMP', 0) is the correct fix here?

@aheejin
Copy link
Member

aheejin commented Sep 19, 2024

Then should we disable (JS-based) throwing too, like this?

    if not settings.WASM_EXCEPTIONS:                                             
      default_setting('SUPPORT_LONGJMP', 0)                                      
      default_setting('DISABLE_EXCEPTION_CATCHING', 1)                           
      default_setting('DISABLE_EXCEPTION_THROWING', 1) 

@sbc100
Copy link
Collaborator

sbc100 commented Sep 19, 2024

Then should we disable (JS-based) throwing too, like this?

    if not settings.WASM_EXCEPTIONS:                                             
      default_setting('SUPPORT_LONGJMP', 0)                                      
      default_setting('DISABLE_EXCEPTION_CATCHING', 1)                           
      default_setting('DISABLE_EXCEPTION_THROWING', 1) 

No I think DISABLE_EXCEPTION_CATCHING and DISABLE_EXCEPTION_THROWING have defaults that work fine with PURE_WASI. i.e. catching is disabled, and throwing is enabled, but just traps.

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

3 participants