-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
When compiling rust with threads, parse exception: attempted pop from empty stack / beyond block start boundary #15722
Comments
Thanks for the bug report! What version of emscripten are you using? I tried reproducing this problem with my local development version but I got a bunch of unrelated wasm-ld errors. |
@sbc100 these are the linker errors I'm seeing: Errorswasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.13.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::io::stdio::OUTPUT_CAPTURE::__getit::__KEY::h1012c9102a13ce23` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.13.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::io::stdio::OUTPUT_CAPTURE::__getit::__KEY::h1012c9102a13ce23` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.13.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::io::stdio::OUTPUT_CAPTURE::__getit::__KEY::h1012c9102a13ce23` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.13.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::io::stdio::OUTPUT_CAPTURE::__getit::__KEY::h1012c9102a13ce23` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::STATE::h169d526b77f4357a (.0.0.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::STATE::h169d526b77f4357a (.0.0.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::STATE::h169d526b77f4357a (.0.0.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::STATE::h169d526b77f4357a (.0.0.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::STATE::h169d526b77f4357a (.0.0.llvm.11106815098784871829)` wasm-ld: error: /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib(std-bb9bd8e6be0c4a41.std.27211dd0-cgu.2.rcgu.o): relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol `std::sys_common::thread_info::THREAD_INFO::__getit::VAL::ha754faf8838943fe (.llvm.11106815098784871829)` wasm-ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors) emcc: error: '/usr/local/google/home/tlively/code/llvm-local/bin/wasm-ld -o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.wasm /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.0.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.1.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.10.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.11.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.12.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.13.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.14.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.15.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.2.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.3.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.4.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.5.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.6.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.7.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.8.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.rust_emscripten_bug.1a649d5b-cgu.9.rcgu.o /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/rust_emscripten_bug.45h9o81x6uy5xph2.rcgu.o -L/usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps -L/usr/local/google/home/tlively/code/rust-emscripten-bug/target/release/deps -L/usr/local/google/home/tlively/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/wasm32-unknown-emscripten/lib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd-bb9bd8e6be0c4a41.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libpanic_unwind-25d50f5331cee422.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libstd_detect-d25150c87dd99d00.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/librustc_demangle-a30115b140842a8e.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libhashbrown-2559fafd0d42a7e1.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/librustc_std_workspace_alloc-843536d29cb089db.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libunwind-4284a5761490eb82.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libcfg_if-023e08fc339a59ec.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/liblibc-24e7f8b4a46aac29.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/liballoc-e6221b06d7026b33.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/librustc_std_workspace_core-554b671000871935.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libcore-80f108c08196e677.rlib /usr/local/google/home/tlively/code/rust-emscripten-bug/target/wasm32-unknown-emscripten/release/deps/libcompiler_builtins-6da11e675034d1a4.rlib -lc-mt-debug -L/usr/local/google/home/tlively/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/wasm32-unknown-emscripten/lib -L/usr/local/google/home/tlively/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/wasm32-unknown-emscripten/lib/self-contained --fatal-warnings -L/usr/local/google/home/tlively/code/emscripten/cache/sysroot/lib/wasm32-emscripten /usr/local/google/home/tlively/code/emscripten/cache/sysroot/lib/wasm32-emscripten/crtbegin.o -lGL-mt -lal -lhtml5 -lstubs-debug -lc-mt-debug -lcompiler_rt-mt -lc++-mt -lc++abi-mt -ldlmalloc-mt -lc_rt-mt -lsockets-mt -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-cxx-exceptions -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --import-undefined --import-memory --shared-memory --strip-debug --export-if-defined=main --export-if-defined=rust_eh_personality --export-if-defined=emscripten_stack_get_end --export-if-defined=emscripten_stack_get_free --export-if-defined=emscripten_stack_init --export-if-defined=stackSave --export-if-defined=stackRestore --export-if-defined=stackAlloc --export-if-defined=__wasm_call_ctors --export-if-defined=fflush --export-if-defined=__errno_location --export-if-defined=__emscripten_init_main_thread --export-if-defined=emscripten_dispatch_to_thread_ --export-if-defined=_emscripten_main_thread_futex --export-if-defined=_emscripten_thread_init --export-if-defined=_emscripten_thread_exit --export-if-defined=_emscripten_thread_free_data --export-if-defined=emscripten_current_thread_process_queued_calls --export-if-defined=_emscripten_allow_main_runtime_queued_calls --export-if-defined=emscripten_futex_wake --export-if-defined=emscripten_get_global_libc --export-if-defined=emscripten_main_browser_thread_id --export-if-defined=emscripten_main_thread_process_queued_calls --export-if-defined=emscripten_run_in_main_runtime_thread_js --export-if-defined=emscripten_stack_set_limits --export-if-defined=emscripten_sync_run_in_main_thread_2 --export-if-defined=emscripten_sync_run_in_main_thread_4 --export-if-defined=emscripten_tls_init --export-if-defined=pthread_self --export-if-defined=pthread_testcancel --export-if-defined=exit --export-if-defined=memalign --export-if-defined=emscripten_proxy_main --export-if-defined=malloc --export-if-defined=free --export-if-defined=__cxa_is_pointer_type --export-if-defined=__cxa_can_catch --export-if-defined=setThrew --export-if-defined=ntohs --export-if-defined=htons --export-if-defined=htonl --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-table -z stack-size=5242880 --initial-memory=2146435072 --no-entry --max-memory=2146435072 --global-base=1024' failed (returned 1)Does that look like a known issue? |
Its hard to tell if this is a linker error or an actual code gen issue. Relocations of type R_WASM_MEMORY_ADDR_TLS_SLEB should only be made against TLS symbols. So if the symbols in questions are supposed to be TLS then the relocation are correct but the symbols are not being marked correctly. If the converse is true and the symbols in questions are not supposed to be TLS then the codegen should be be creating relocations of type R_WASM_MEMORY_ADDR_TLS_SLEB. I suppose it could be a bug in lld's ability to devine which symbols are TLS. Support for an explicit TLS symbol flag was added just a few months ago in https://reviews.llvm.org/D109426. Prior to that we would decide if a symbol was TLS or not purely based on the name of the data segment in which is was defined. Perhaps you could attach on of the object files generating these error (e.g. std-bb9bd8e6be0c4a41.std.27211dd0-cgu.13.rcgu.o) and tell me if the symbol in question should be TLS or how (e.g. |
I was using 2.0.27. I got the same errors you got when using the latest version |
@sbc100 Can I hijack this thread a bit? I've come across the same linker error message about thread local storage when trying to see if threads might work on Rust with its
...and I've also included the object file it references (tls.tls.d9f5019e-cgu.0.rcgu.o) along with the assembly file ("tls.s"). Those symbols are supposed to be part of the thread local storage, so it sounds like the symbols aren't getting marked correctly somewhere along the line. There is some more background that I've been able to gather over at: Thread Local Storage, wasm-ld, thread_local!, and Emscripten, and here. This is using the following version of Emscripten:
Let me know if there is a more appropriate place to post this question. Thanks! |
It seems like it's just a binaryen issue at this point; looks like even changing linker opts to -O1 instead of -O2 or higher is enough to work around the parsing error mentioned in the beginning. |
@RReverser Does that wasm file parse ok in wabt? (similar errors in the past have been wasm-ld bugs in my experience, and not parsed ok in wabt) If it does parse then it is likely a binaryen error, and I can take a look at that if you attach the wasm file. |
Heh it doesn't:
I guess it is wasm-ld then :( |
Actually this is probably a bug in the LLVM backend, since wasm-ld doesn't change function contents except for relocations. |
I haven't followed this closely at all, but is the following patch applied? |
Yeah it was long merged, and it was about a linking error which I no longer see.
FWIW this was wrong. -O1 at link time simply suppresses the error (because Emscripten doesn't need to parse Wasm), but the Wasm is still corrupted. The only thing that does help for now is if I build the Rust module in In November I also left some further comments with my investigation on the rust-lang/rust variant of this issue that pointed to invalid number of arguments among other things: rust-lang/rust#91628 I have no idea where to go from here and can't reproduce this with any minimal repros so far either (the one linked in the beginning of the post doesn't seem to exhibit this issue anymore). |
It may be sufficient to have any reproducer, even if it's not minimal. If you can get LLVM IR out of rustc that exhibits the bad code gen, that should be enough to go on. |
So as I mentioned earlier, if I build Rust crate alone to a This looks promising, at least it did narrow down the issue to somewhere in stdlib, so it's indeed not a linker issue:
I'll try to get the LLVM IR now. |
Got the LLVM IR, confirmed that it produces invalid Wasm object via Then, I decided to try reducing it via target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-emscripten"
@__cxa_thread_atexit_impl = extern_weak global i8
define void @_ZN3std3sys4unix17thread_local_dtor13register_dtor17hb4d1ef11a2635878E() personality ptr null {
bb1:
%_7 = tail call i32 @__cxa_thread_atexit_impl(ptr null, ptr null, ptr null)
ret void
}
; uselistorder directives
uselistorder ptr null, { 1, 2, 3, 4, 5, 0 } That
This is what wasm-objdump (one of few tools that handle this broken Wasm) shows inside:
And I can see that the same |
The I guess this is a classic problem of mismatching function pointers in Wasm? Although it's not clear to me why it doesn't cause issues under other circumstances / for other projects, and that code has been there since 2016 so surely it would've been caught by now... Or is the problem elsewhere? |
Prior to commit 9b98d42, Perhaps that should be re-added as a stub for all builds? Similar to what is done for emscripten/system/lib/libcxxabi/src/cxa_exception_emscripten.cpp Lines 18 to 33 in 888f452
|
Ok so it's indeed #[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten)
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
use crate::mem;
use crate::sys_common::thread_local_dtor::register_dtor_fallback;
extern "C" {
#[linkage = "extern_weak"]
static __dso_handle: *mut u8;
}
register_dtor_fallback(t, dtor);
} and reran with same I'm a bit surprised because the original log has a lot of functions with mismatching signatures, but perhaps parser / validator is just in a broken state after first error and those other messages should be ignored. |
Nice, so you have a rust-side fix? |
No, it's just a hotfix to see if removing the function would help. I'm not sure if it's the right thing to do in general though - I assume we do want to call The actual problem seems to be to do with either the function pointer conversion, or with the weak linkage declarator producing the problematic LLVM IR above. I think it's still something that LLVM should take care of or at least throw an error earlier in the process... |
What I'm still most confused about is
I even tried minimal repros that use all the same feature flags, link with threads etc., but they don't exhibit this problem. Not sure what's different in this project :/ |
If we ignore the Rust source for now, is this LLVM IR
expected to produce a broken Wasm? Is there anything LLVM can do here - like figure out that |
Given that Emscripten doesn't have I'd love to understand the underlying issue with weak linkage though, as it seems the same could've happened on any other weak function declaration. |
- Fixes rust-lang#91628. - Fixes emscripten-core/emscripten#15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++. r? @alexcrichton
Made a PR here: rust-lang/rust#106779 |
IIUC we do include |
What you could do instead perhaps is provide a weak definition of |
We have this pass to fix up a similar issue that can arise with bitcasts between function types: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp. I wonder if the weak linkage makes the i8 global callable as a function without a cast? I would be surprised if that were allowed normally. My guess is that we could fix this in LLVM side by adding a similar pass or adding functionality to that pass. |
After a further thought, this is probably not a good idea since that would cause TLS destructors to
Curious, why does this symbol appear in the data section (
With the provided $ cat thread_atexit.c
int ___cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso)
{
return 0;
}
#define weak_alias(old, new) \
extern __typeof(old) new __attribute__((__weak__, __alias__(#old)))
weak_alias(___cxa_thread_atexit_impl, __cxa_thread_atexit_impl);
$ clang --target=wasm32 -emit-llvm -c -S -o thread_atexit.ll thread_atexit.c
$ llc -march=wasm32 -filetype=obj -o thread_atexit.a thread_atexit.ll
$ llc -march=wasm32 -filetype=obj -o std-8348dc5e440aab06.a ~/Downloads/std-8348dc5e440aab06.ll
$ wasm-ld --no-entry --export-all -o test.wasm std-8348dc5e440aab06.a thread_atexit.a
wasm-ld: error: symbol type mismatch: __cxa_thread_atexit_impl
>>> defined as WASM_SYMBOL_TYPE_DATA in std-8348dc5e440aab06.a
>>> defined as WASM_SYMBOL_TYPE_FUNCTION in thread_atexit.a |
The first answer to that question is that its because the IR specifies it as a global: |
Pretty sure that's the result of the same bitcast issue - because it's declared as a void/data pointer and not a function pointer, which are treated differently in Wasm, it ends up as a data reference and not function reference. |
@tlively That solution sounds most promising long-term. |
@sbc100 Okay I'm confused - here you say we include it, but in #18501 (comment) you said
So... does Emscripten implement it or not? |
Sorry, I was confused. Emscripten implements However, nowhere does it implement |
Ah, okay, thanks for the clarification. So the Rust PR is still a valid fix (if somewhat limited compared to the LLVM bitcode one) for this then. |
I tried to craft a minimal repro in C that replicates what Rust is doing / what that LLVM IR is demonstrating, and I think this is it (well, you can also remove the __attribute__((weak))
extern void maybe_func;
int main() {
int(*func)() = &maybe_func;
if (func) {
func();
}
} Compiling with
Godbolt link for LLVM IR: https://clang.godbolt.org/z/odzKMsrPx |
Great work narrowing down the issue. Could you file an LLVM bug at https://github.com/llvm/llvm-project for this? |
This is rather unusual C code though. Normally one would write
So unusual, in fact, that I don't think we have seen that in all the millions of lines of C/C++ that emscripten is fed. I don't think I've ever seen a non-function declared with a a void (just void without the *). I assume this doesn't work in C++? |
BTW, you don't need to
Also, FWIW C++ rejects this:
|
Indeed, that's what I assumed but wanted to replicate anyway after our DM chat to understand whether this code would be simply unusual enough to never occur or actually impossible to represent in C. |
Ah yeah, but then you need to allow undefined symbols via command line instead.
Interesting. Void, like the weak attribute, is not important though, it was just closer to the repro LLVM IR. E.g. this also fails similarly in both C and C++: extern char maybe_func;
int main() {
int(*func)() = (int(*)())&maybe_func;
if (func) {
func();
}
} |
Sure, will do later today. |
Created here: llvm/llvm-project#60003 |
Avoid __cxa_thread_atexit_impl on Emscripten - Fixes rust-lang#91628. - Fixes emscripten-core/emscripten#15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++.
Avoid __cxa_thread_atexit_impl on Emscripten - Fixes rust-lang#91628. - Fixes emscripten-core/emscripten#15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++.
Avoid __cxa_thread_atexit_impl on Emscripten - Fixes rust-lang#91628. - Fixes emscripten-core/emscripten#15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++.
Closing as this is fixed on the Rust side now (will be available on stable from Rust 1.69), and the LLVM issue is tracked separately. |
- Fixes rust-lang/rust#91628. - Fixes emscripten-core/emscripten#15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++. r? @alexcrichton
Avoid __cxa_thread_atexit_impl on Emscripten - Fixes rust-lang/rust#91628. - Fixes emscripten-core/emscripten#15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++.
Sorry if this is too specific to Rust, but I thought someone might have a clue as to what is going on. When compiling Rust with threads enabled with emscripten I get the following error:
Full error from rustc
I narrowed down the code causing this and it seems related to Rust's auto-dereferencing. This is the section of code, and you can see the type of parameter
s
in the closure is multiple nested references (&&&str
or&&str
). Rust's compiler will auto-dereference them to the appropriate type&str
. This code does not compile.However, when I use a reference pattern to dereference the closure parameter, the code compiles and works as expected:
I also tested this theory by trying to compile the following code and it fails with the same error:
Note that this error only occurs when compiling Rust with threads.
You can view the repo with the full reproduction here.
The text was updated successfully, but these errors were encountered: