Thread local storage link issue with Rust/wasm-ld/Emscripten #92676
Labels
A-LLVM
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
C-bug
Category: This is a bug.
O-wasm
Target: WASM (WebAssembly), http://webassembly.org/
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
I am trying to narrow down the cause of a problem which occurs when trying to enable threads on a Rust program compiling to the
wasm32-unknown-emscripten
target. A simple example:...which compiles, but fails with a
wasm-ld
linker error shown below. I have a small github repository with the source files and the capture of the error messages. I've extracted the failingwasm-ld
command that yields the error, an placed it in the file linker_command.sh, which I've tried to ensure you can use without having to deal with Rust (or even have Rust installed). All of the compiled object files are included in the repository. The error can be seen in the snippet below, with additional information provided by the--verbose
option. (Before running the script, you will have to set a couple of variable at the top of the script to point to your installation of emsdk and wasm-ld)...note the lack of a
.tbss
section reported above, but there is a.tdata
and a.bss
section. The error message indicates that the symbols in question are not marked as thread local storage, but when usingwasm-objdump
, it seems like there are signs that the symbols are a part of thread local storage. With the-x
option (raw output in dump-x.txt and dump-x_rustfilt.txt):...you will notice segment 13 has both .tbss and [TLS] mentioned and with
wasm-objdump -d -r
(dump-d.txt and dump-d_rustfilt.txt):(where the files ending in rustfilt have been passed through the rust name demangler).
The
wasm-ld
error message comes fromscanRelocations
function in Relocations.cpp at line #120.That function uses the isTLS() method, which uses
WASM_SYMBOL_TLS
. There are only a select few places where that flag appears:...the one from InputFiles.cpp is part of the ObjFile::createDefined method which has the following:
...and when you look at where
seg->implicitTLS
gets set:...but when stepping through the code with the debugger, I see that
seg->isTLS()
appears to be true for the segment that theExample::VAR1::__getit::__KEY::h9fd2473e7b8be3ac
symbol is in, so it doesn't set the implicitTLS flag, and thus presumably wouldn't set theflags |= WASM_SYMBOL_TLS;
and therefore isTLS() wouldn't ever be true on the symbol itself, and you always would get the linker error in Relocations.cpp. The "flags" for that symbol are 2 as can be seen from the screenshot above. But the "always failing" assumption must be false, since Emscripten can work with thread local data, as shown by this C program, which does essentially the same thing as the Rust program, and uses both.tdata
and.tbss
sections without issue (see the example assembly below) (build by usingmake wasm
in that directory (and see the other targets))....and the fact that there are other symbols that are marked as "R_WASM_MEMORY_ADDR_TLS_SLEB" in the rust originated object file, but that don't report linking problems. From the '-x' wasm-objdump file:
I thought it might be related to the this issue which sounds like there was a problem because the debug symbols weren't part of the thread local storage, but the same link error occurs when building without debugging symbols. (The object files for the
--release
build are here as well).Anyone have thoughts on a good place to start diving into this issue more? Would it be more productive to try and determine why the --verbose output of wasm-ld doesn't have the .tbss section listed? Maybe start looking into MIR? If there is another more appropriate place to ask about this issue, please let me know. It seems like it may be sort of a cross-cutting issue. I did find the following comment interesting in rustc_codegen_llvm/src/consts.rs
...only because it mentions thread local storage and link errors, so that might just be a red herring.
The versions of the various programs:
...although I've tried with earlier emscripten 2.0.34 and 3.0.0, along with earlier versions of stable and nightly rust, all with the same results.
To generate the object files from the rust source, compile the stub:
...and then invoke the command:
(If anyone is interested stepping through wasm-ld, there is also a vscode launch configuration file in the repository that will help with setting the arguments to lld, but you'll need to edit it to reflect the location the object files on your computer.)
The text was updated successfully, but these errors were encountered: