-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[wasm-ld] Inconsistency: combineOutputSegments() merges InputChunks with differing COMDATs, but writeBody() asserts #134809
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
Comments
cc @sbc100 My questions here end up being
|
I see this (73332d7#diff-e826be2acc8b58c5d040525dc8a509e90810d3edcd93190d4810e476919ef9aa) which probably adds this llvm-project/lld/wasm/Writer.cpp Lines 1041 to 1047 in 739062d
But not sure if this is enough to do the job in my case (as can be seen in the linking step for clang-repl I have shared which should enable pic but not relocatable ... so the check doesn't affect my case) DRY RUN
|
@llvm/issue-subscribers-lld-wasm Author: Anutosh Bhat (anutosh491)
**Context**
This is a part of the effort on running clang-repl in the browser. Check xeus-cpp-lite In a cell block, I am trying to process multiple c++ definitions
As a final part we have a linking step that produces the side module (incr_module_xx.wasm for each cell that is processed) Problem : Basically I end up with a situation where we're using wasm-ld to execute a linking process (with Now what I see is when And when we run CombineOutputSegments, I see segments having inputchunks with different comdats being combined without any assert or error raised I am guessing this is justified because llvm-project/lld/wasm/Writer.cpp Lines 1075 to 1080 in e7365d3
But then as we are using --emit-relocs, we end up calling And here we have the following llvm-project/lld/wasm/SyntheticSections.cpp Lines 738 to 741 in f0bdeb4
Hence I end up with this error
while trying to run expressions with Disclaimer i) I see this happens only when we have |
I think you are most likely just running into bug / limitation of We should fix the assert. But also not that you can skip the section combining if use the extended const feature: llvm-project/lld/wasm/Writer.cpp Lines 1757 to 1766 in e7365d3
To enable a feature like that you just need to build at least on of your object files with that feature enabled, or link with |
Hey Sam, Thanks a lot for your reply. I would like to take 2 steps back and explain as to how I ended up trying --emit-relocs on top of the flags we already have in wasm.cpp (cause I wasn't facing this issue with while using clang-repl in the browser with llvm 19 and I see it with the latest llvm 20 releases) So when using wasm-ld with verbose (probably can add it to the flags above) I see the following in i) llvm 19.1.7
ii) llvm 20.1.0
This happens in the This bring me to llvm-project/lld/wasm/Writer.cpp Lines 685 to 687 in b416e7f
I was having i) enable --emit-relocs Hence I started exploring emit-relocs (cause I don't really want to enable init_memory and not have any passive segments) So basically I want to avoid this llvm-project/lld/wasm/Writer.cpp Lines 1152 to 1160 in b416e7f
So I thought of using emit-relocs here. |
I can try helping here. If I understand correctly what we need to do here is add a patch to Let me know if that's what we're looking for and I'll try adding a quick patch which you could review. |
Ohh I hadn't explored this just yet (and is a bit new to me) What is recommended usually in such cases ? I ask this from a perspective of running clang-repl in the browser. As you know while doing this So technically in such cases I guess I just need to focus on the So as this is an iterative process where we keep on generting wasm modules and loading them I probably need some guidance on what's the goto option here ! |
Why do you care if emitBssSegments is true or now? Ideally you would it to be false since it makes the binaries smaller. |
Ideally the linker would not combine the output segments. Output section combining is only needed in certain cases due to lack the extended const proposal. Hopefully once that feature becomes more widespread we can enable the feature by default and output section combining will be disabled by default at that point. |
Maybe I can try explaining the problem at hand. So firstly the use case of running clang-repl in the browser is being tested currently in down stream project like CppInterop and xeus-cpp. And now that we are moving to llvm 20, I see the following errors Let's consider two tests for started (abstraction of tests in cppinterop that work with llvm 19)
Now what should happen (running test1) i) CreateIntepreter : creates the interpreter and this basically creates incr_module_0.wasm (some initialization step) . This doesn't have any segment or anything hence hasPassiveInitializedSegments shouldn't do anything. llvm-project/lld/wasm/Writer.cpp Lines 1152 to 1160 in b416e7f
Nothing wrong untill now !! But as soon as we go to Test 2 .... the tests are failing with
Reason: Again going back to
I don't know how initMemory is still alive (I would guess we are completely in a new state space/dimension where a previously active So test 2 fails inside
So each test in itself is running perfectly fine. Its just that i don't understand why initMemory is still alive. Technically it shouldn't be and only This is the reason I have been trying to avoid hasPassiveInitializedSegments as a whole. |
This can be seen here inside xeus-cpp-lite too Ignore the first log there is which I added for debugging. But apart from that the same error. Explaining what is happening here ( kinda opposite .... we process first then create interpreter call)
Not sure why this is happening. The same doesn't happen with our current link based on llvm 19 (obviously because here we're using |
So technically the above case (#134809 (comment)) is something like this
So here hasPassiveInitializedSegments ends up being false but initMemory is active from the previous case. Cause So if I just possibly add this
The failures I am facing go away. I probably should check if hasPassiveInitializedSegments is false above and based on that turn of initMemory or something for starters. So yeah everything basically boils down to clearing the state of the execution above/previously and hopefully having a clear slate while executing the linking next in link. Do you know of why this might not be happening ? |
If I am thinking correctly probably for the above case (and for relevant cases), we might not be resetting cc @sbc100 |
Okay I realized, WasmSym act a shared global singleton, maintaining its identity across different modules and hence once a symbol is markedasLive it will remain live and affect the upcoming module. I made a PR trying to change this behaviour #134970 |
do you think atleast for starters we should add a patch in combineOutputSegments just like the one in writeBody to atleast assert the difference between comdats if llvm-project/lld/wasm/SyntheticSections.cpp Lines 738 to 741 in f0bdeb4
This atleast starts introducing some consistency. Cause otherwise we're allowing a possibly faulty combine knowingly and then later raising an assert for it saying we are wrong (whereas this should probably not be allowed in the first step itself isn't it ?) Can make a quick patch addressing this as per what you think ! |
…134970) Towards ##134809 (comment) This change moves WasmSym from a static global struct to an instance owned by Ctx, allowing it to be reset cleanly between linker runs. This enables safe support for multiple invocations of wasm-ld within the same process Changes done - Converted WasmSym from a static struct to a regular struct with instance members. - Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx. - Reset wasmSym in Ctx::reset() to clear state between links. - Replaced all WasmSym:: references with ctx.wasmSym->. - Removed global symbol definitions from Symbols.cpp that are no longer needed. Clearing wasmSym in ctx.reset() ensures a clean slate for each link invocation, preventing symbol leakage across runs—critical when using wasm-ld/lld as a reentrant library where global state can cause subtle, hard-to-debug errors. --------- Co-authored-by: Vassil Vassilev <[email protected]>
…lvm#134970) Towards #llvm#134809 (comment) This change moves WasmSym from a static global struct to an instance owned by Ctx, allowing it to be reset cleanly between linker runs. This enables safe support for multiple invocations of wasm-ld within the same process Changes done - Converted WasmSym from a static struct to a regular struct with instance members. - Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx. - Reset wasmSym in Ctx::reset() to clear state between links. - Replaced all WasmSym:: references with ctx.wasmSym->. - Removed global symbol definitions from Symbols.cpp that are no longer needed. Clearing wasmSym in ctx.reset() ensures a clean slate for each link invocation, preventing symbol leakage across runs—critical when using wasm-ld/lld as a reentrant library where global state can cause subtle, hard-to-debug errors. --------- Co-authored-by: Vassil Vassilev <[email protected]>
I think something the above (#134809 (comment)) could be added to ensure consistency. |
… context (#134970) Towards #llvm/llvm-project#134809 (comment) This change moves WasmSym from a static global struct to an instance owned by Ctx, allowing it to be reset cleanly between linker runs. This enables safe support for multiple invocations of wasm-ld within the same process Changes done - Converted WasmSym from a static struct to a regular struct with instance members. - Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx. - Reset wasmSym in Ctx::reset() to clear state between links. - Replaced all WasmSym:: references with ctx.wasmSym->. - Removed global symbol definitions from Symbols.cpp that are no longer needed. Clearing wasmSym in ctx.reset() ensures a clean slate for each link invocation, preventing symbol leakage across runs—critical when using wasm-ld/lld as a reentrant library where global state can cause subtle, hard-to-debug errors. --------- Co-authored-by: Vassil Vassilev <[email protected]>
…lvm#134970) Towards #llvm#134809 (comment) This change moves WasmSym from a static global struct to an instance owned by Ctx, allowing it to be reset cleanly between linker runs. This enables safe support for multiple invocations of wasm-ld within the same process Changes done - Converted WasmSym from a static struct to a regular struct with instance members. - Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx. - Reset wasmSym in Ctx::reset() to clear state between links. - Replaced all WasmSym:: references with ctx.wasmSym->. - Removed global symbol definitions from Symbols.cpp that are no longer needed. Clearing wasmSym in ctx.reset() ensures a clean slate for each link invocation, preventing symbol leakage across runs—critical when using wasm-ld/lld as a reentrant library where global state can cause subtle, hard-to-debug errors. --------- Co-authored-by: Vassil Vassilev <[email protected]>
…lvm#134970) Towards #llvm#134809 (comment) This change moves WasmSym from a static global struct to an instance owned by Ctx, allowing it to be reset cleanly between linker runs. This enables safe support for multiple invocations of wasm-ld within the same process Changes done - Converted WasmSym from a static struct to a regular struct with instance members. - Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx. - Reset wasmSym in Ctx::reset() to clear state between links. - Replaced all WasmSym:: references with ctx.wasmSym->. - Removed global symbol definitions from Symbols.cpp that are no longer needed. Clearing wasmSym in ctx.reset() ensures a clean slate for each link invocation, preventing symbol leakage across runs—critical when using wasm-ld/lld as a reentrant library where global state can cause subtle, hard-to-debug errors. --------- Co-authored-by: Vassil Vassilev <[email protected]>
…lvm#134970) Towards #llvm#134809 (comment) This change moves WasmSym from a static global struct to an instance owned by Ctx, allowing it to be reset cleanly between linker runs. This enables safe support for multiple invocations of wasm-ld within the same process Changes done - Converted WasmSym from a static struct to a regular struct with instance members. - Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx. - Reset wasmSym in Ctx::reset() to clear state between links. - Replaced all WasmSym:: references with ctx.wasmSym->. - Removed global symbol definitions from Symbols.cpp that are no longer needed. Clearing wasmSym in ctx.reset() ensures a clean slate for each link invocation, preventing symbol leakage across runs—critical when using wasm-ld/lld as a reentrant library where global state can cause subtle, hard-to-debug errors. --------- Co-authored-by: Vassil Vassilev <[email protected]>
Context
This is a part of the effort on running clang-repl in the browser. Check xeus-cpp-lite
In a cell block, I am trying to process multiple c++ definitions
As a final part we have a linking step that produces the side module (incr_module_xx.wasm for each cell that is processed)
Problem :
Basically I end up with a situation where we're using wasm-ld to execute a linking process (with
--emit-relocs
being provided as a flag)Now what I see is when
createOutputSegments
is run we end up with inputchunks with 3 different comdats (_ZL4var0
,_ZL5cvar0
orempty
)And when we run CombineOutputSegments, I see segments having inputchunks with different comdats being combined without any assert or error raised
I am guessing this is justified because
llvm-project/lld/wasm/Writer.cpp
Lines 1075 to 1080 in e7365d3
But then as we are using --emit-relocs, we end up calling
LinkingSection::writeBody()
afterfinalizeSections
And here we have the following
llvm-project/lld/wasm/SyntheticSections.cpp
Lines 738 to 741 in f0bdeb4
Hence I end up with this error
while trying to run expressions with
const
in xeus-cpp-liteDisclaimer
i) I see this happens only when we have
#ifndef NDEBUG
and I'm building llvm withMinSizeRel
. Probably I wouldn't have encountered this withRelease
.The text was updated successfully, but these errors were encountered: