-
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
Thread local storage link issue with Rust/wasm-ld/Emscripten #15891
Comments
I think the idea is that modern object files that mark the tls segment with WASM_SEG_FLAG_TLS should also mark all the symbols within that segment as WASM_SYMBOL_TLS. So the linker should not need to inject this flag since it should already exist on the symbol. Perhaps we should be asserting that all symbols in bss segments are marked as WASM_SYMBOL_TLS. As to how this symbol came to not have that flag, we would need to look into how and when that flag gets added in llvm. In short, I think the bug here is in the object file generation rather than in the linker (assume the symbol is indeed missing the WASM_SYMBOL_TLS flag). |
Thanks for the input. I've opened an issue on this over at: rust-lang/rust#92676 so I suppose we can close it here. |
I bumped into the error Note: I don't encounter this when building the same project with Rust's standard linker. Perhaps this hints at a miscommunication between Rust and wasm-ld 14.0 when shared memory is involved? |
CC @tlively and @RReverser who have worked on rust/emscripten integration |
To be clear this is how I reproduce this issue: I'm using nightly Rust and I built
(Replace This produces a bunch of errors like the following:
Edit: My reproduction doesn't involve Emscripten, but this seems like the most relevant place to discuss for now. |
I wonder if Rust's version of LLVM predates the R_WASM_MEMORY_ADDR_TLS_SLEB relocation type. @sbc100, is that something you added somewhat recently? |
The problem here is that rust is (I suppose correctly) using R_WASM_MEMORY_ADDR_TLS_SLEB but that the symbol its being used against is not being detected as being a TLS symbol. We added explicit TLS symbol flags fairly recently (About 5 months ago: https://reviews.llvm.org/D109426), but that change was supposed to include support for older object files: |
I've now got the example repro case failing locally and am looking into it. @gregbuchholz if you are on discord perhaps we can work together on this? |
Fix is (hopefully) in https://reviews.llvm.org/D118414 |
That is awesome! After applying that patch, it did indeed fix the problem. Thanks @sbc100 (and everyone else) for all of your effort on this issue, but more so on all the work that you have done on emscripten, it is truly appreciated! |
The fix in wasm-ld is described in this github issue: emscripten-core/emscripten#15891
The issue preventing the compilation of this program was corrected in wasm-ld, as described in: emscripten-core/emscripten#15891
This is the first trial to get threads working after the issue with wasm-ld was solved: emscripten-core/emscripten#15891
@gregbuchholz Hi, I came here from reading your thread https://internals.rust-lang.org/t/enabling-threads-on-wasm32-unknown-enscripten/15755/6. On latest Rust I'm still seeing the How did you get it to work? |
Anyone figure this out? |
I haven't messed with this for a year it looks like, but do you get error messages with example over at: https://github.com/gregbuchholz/thread_local_storage ? It seems like there was a patched version of emscripten needed to get things to compile. I don't know when (or if) that got rolled into a released version of emscripten. And then there was some sort of regression with the rust compiler, where an older version worked, but a newer version stopped working. I didn't keep up with things after that. I think getting multi-threaded emscripten wasm & rust working is just something that needs a little persistence with digging into things, I don't think there were any major hurdles that make it nigh impossible. You might check my other github repositories, since they are pretty much all examples dealing with getting rust/SDL/emscripten/wasm working together. Good luck. |
In older versions of llvm (e.g. llvm 13), symbols were not individually flagged as TLS. In this case, the indent was to implicitly mark any symbols defined in TLS segments as TLS. However, we were not performing this implicit conversion if the segment was explicitly marked as TLS As it happens, llvm 13 was branched between the addition of the segment flag and the addition of the symbol flag. See: - segment flag added: https://reviews.llvm.org/D102202 - symbol flag added: https://reviews.llvm.org/D109426 Testing this is tricky because the assembler will imply the TLS status of the symbol based on the segment its declared in, so we are forced to use a yaml file here. Fixes: emscripten-core/emscripten#15891 Differential Revision: https://reviews.llvm.org/D118414
Sorry for not responding earlier, I'm basically running into #15722 / rust-lang/rust#91628 and couldn't find a workaround except for building in debug mode (slow & huge binary) yet. |
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. It compiles, but fails with awasm-ld
linker error. 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? 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.
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 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: