[lld][WebAssembly] Don't export deps for unused stub symbols#173422
Conversation
When a stub .so file contains ``` A: B ``` And `A` is defined in bitcode that's pulled in for LTO, but both `A` and `B` are removed in `LTO::linkRegularLTO` due to not being dead: https://github.com/llvm/llvm-project/blob/24297bea9672722d8fbaaff137b301b0becaae9c/llvm/lib/LTO/LTO.cpp#L1042-L1054 Then the symbol `A` becomes undefined after LTO, `processStubLibraries` tries to import `A` from JS, and tries to export its dependency `B`: https://github.com/llvm/llvm-project/blob/24297bea9672722d8fbaaff137b301b0becaae9c/lld/wasm/Driver.cpp#L1108-L1109 But `B` is gone, causing this error: ```console wasm-ld: error: ....: undefined symbol: B. Required by A ``` This PR checks if the symbol is used in regular objects before trying to exporrt its dependences, ensuring the case above doesn't crash the linker.
|
@llvm/pr-subscribers-lld-wasm @llvm/pr-subscribers-lld Author: Heejin Ahn (aheejin) ChangesWhen a stub .so file contains And llvm-project/llvm/lib/LTO/LTO.cpp Lines 1042 to 1054 in 24297be A becomes undefined after LTO, processStubLibraries tries to import A from JS, and tries to export its dependency B: llvm-project/lld/wasm/Driver.cpp Lines 1108 to 1109 in 24297be B is gone, causing this error:
wasm-ld: error: ....: undefined symbol: B. Required by AThis PR checks if the symbol is used in regular objects before trying to exporrt its dependences, ensuring the case above doesn't crash the linker. Full diff: https://github.com/llvm/llvm-project/pull/173422.diff 4 Files Affected:
diff --git a/lld/test/wasm/lto/Inputs/foo.ll b/lld/test/wasm/lto/Inputs/foo.ll
index f3b54cc7d0094..695b552fc6249 100644
--- a/lld/test/wasm/lto/Inputs/foo.ll
+++ b/lld/test/wasm/lto/Inputs/foo.ll
@@ -1,7 +1,17 @@
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-unknown"
-define void @foo() local_unnamed_addr {
+define void @foo() {
+entry:
+ ret void
+}
+
+define void @baz() {
+entry:
+ ret void
+}
+
+define void @quux() {
entry:
ret void
}
diff --git a/lld/test/wasm/lto/Inputs/stub.so b/lld/test/wasm/lto/Inputs/stub.so
index e76c890dbb435..c471b81da5064 100644
--- a/lld/test/wasm/lto/Inputs/stub.so
+++ b/lld/test/wasm/lto/Inputs/stub.so
@@ -1,3 +1,4 @@
#STUB
bar: foo
memcpy: foo
+baz: quux
diff --git a/lld/test/wasm/lto/stub-library.s b/lld/test/wasm/lto/stub-library.s
index 36d6b7b3f38aa..d77296b6cff3d 100644
--- a/lld/test/wasm/lto/stub-library.s
+++ b/lld/test/wasm/lto/stub-library.s
@@ -1,6 +1,10 @@
## The function `bar` is declared in stub.so and depends on `foo` which is
## defined in an LTO object. We also test the case where the LTO object is
## with an archive file.
+## The function `baz` is declared in stub.so and depends on `quux`, and both
+## `baz` and `quux` are defined in an LTO object. When `baz` and `quux` are
+## DCE'd and become undefined in the LTO process, wasm-ld should not try to
+## export the (nonexistent) `quux`.
## This verifies that stub library dependencies (which are required exports) can
## be defined in LTO objects, even when they are within archive files.
@@ -40,3 +44,5 @@ _start:
# CHECK-NEXT: - Name: foo
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: Index: 2
+
+# CHECK-NOT: - Name: quux
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 97e50783985a8..d18126bef766f 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -1105,7 +1105,7 @@ static void processStubLibraries() {
// the names of the stub imports
for (auto [name, deps]: stub_file->symbolDependencies) {
auto* sym = symtab->find(name);
- if (sym && sym->isUndefined()) {
+ if (sym && sym->isUndefined() && sym->isUsedInRegularObj) {
depsAdded |= addStubSymbolDeps(stub_file, sym, deps);
} else {
if (sym && sym->traced)
|
| ret void | ||
| } | ||
|
|
||
| define void @quux() { |
There was a problem hiding this comment.
Can you make a new input file rather than adding to this (since this one is just called foo I think its good it just defines foo)
There was a problem hiding this comment.
What I will create is basically another file with two methods. I can actually reuse this file and foo and baz here (without adding anything to it) but what I need is a different stub file having one line foo: baz (or vice versa). How about creating a new stub file? (You preferred a new file rather than echo'ing it, right?)
The reason I can't reuse the existing stub file is foo is a dependency for both bar and memcpy here:
#STUB
bar: foo
memcpy: foo
Will create a new stub file. Tell me what you think
There was a problem hiding this comment.
Oh sorry, baz is what I added... I thought it was already there. Will create another input file. Ignore the comment above
There was a problem hiding this comment.
I don't think you need to make a new stub file. The stub file and the .ll file are not related explicitly.
Perhsonally I would just create a single new .ll file in under inputs to use for this test and not use the existings Inputs/foo.ll
| @@ -0,0 +1,3 @@ | |||
| #STUB | |||
| bar: | |||
There was a problem hiding this comment.
This entry is necessary not to crash because stub-library.s has a bar declaration. Without this we crash with something like undefined symbol: bar
There was a problem hiding this comment.
Can you explain why we need two different stub .so files?
Why can't you just add foo: baz to the existing stub? Or at least it seems like we should just be able to add a single new entry to repro this issue.
|
|
||
| # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s | ||
| # RUN: mkdir -p %t | ||
| # RUN: llvm-as %S/Inputs/foo.ll -o %t/foo.o |
There was a problem hiding this comment.
Should this bee foobaz.ll here and above?
There was a problem hiding this comment.
Also, I guess the object file and the archive file should get renamed accordingly.
| # RUN: rm -f %t/libfoobaz.a | ||
| # RUN: llvm-ar rcs %t/libfoobaz.a %t/foobaz.o | ||
| # RUN: wasm-ld %t.o %t/libfoobaz.a %p/Inputs/stub2.so -o %t2.wasm | ||
| # RUN: obj2yaml %t2.wasm | FileCheck %s --check-prefix=UNUSED |
There was a problem hiding this comment.
I would hope that we could avoid duplicating all these lines and simply modify the existing lines above to use foobaz.ll instead of foo.ll?
There was a problem hiding this comment.
Then it can't be foo because foo is already being used in stub.so and I need a symbol that's not used anywhere. Anyway, I will remove foo.ll and create another file that contains all functions we need then.
There was a problem hiding this comment.
Then it becomes basically the same as the status before creating foobaz.ll, with only the name of foo.ll changed to something else though. (Also I don't think we need two different stub files then either...)
There was a problem hiding this comment.
Reverted the last two commits and changed foo.ll to funcs.ll: a44a6c0
|
Thanks! |
…3422) When a stub .so file contains ``` A: B ``` And `A` is defined in bitcode that's pulled in for LTO, but both `A` and `B` are removed in `LTO::linkRegularLTO` due to not being dead: https://github.com/llvm/llvm-project/blob/24297bea9672722d8fbaaff137b301b0becaae9c/llvm/lib/LTO/LTO.cpp#L1042-L1054 Then the symbol `A` becomes undefined after LTO, `processStubLibraries` tries to import `A` from JS, and tries to export its dependency `B`: https://github.com/llvm/llvm-project/blob/24297bea9672722d8fbaaff137b301b0becaae9c/lld/wasm/Driver.cpp#L1108-L1109 But `B` is gone, causing this error: ```console wasm-ld: error: ....: undefined symbol: B. Required by A ``` This PR checks if the symbol is used in regular objects before trying to exporrt its dependences, ensuring the case above doesn't crash the linker.
When a stub .so file contains
And
Ais defined in bitcode that's pulled in for LTO, but bothAandBare removed inLTO::linkRegularLTOdue to not being dead:llvm-project/llvm/lib/LTO/LTO.cpp
Lines 1042 to 1054 in 24297be
Abecomes undefined after LTO,processStubLibrariestries to importAfrom JS, and tries to export its dependencyB:llvm-project/lld/wasm/Driver.cpp
Lines 1108 to 1109 in 24297be
Bis gone, causing this error:wasm-ld: error: ....: undefined symbol: B. Required by AThis PR checks if the symbol is used in regular objects before trying to exporrt its dependences, ensuring the case above doesn't crash the linker.