-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[ELF] Make shouldAddProvideSym return values consistent when demoted to Undefined #111945
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
[ELF] Make shouldAddProvideSym return values consistent when demoted to Undefined #111945
Conversation
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: Fangrui Song (MaskRay) ChangesCase: Due to demoteDefined,
When Fix this by adding a Full diff: https://github.com/llvm/llvm-project/pull/111945.diff 2 Files Affected:
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index f3f95ec589bd82..2247d592c8bca3 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -1811,6 +1811,11 @@ void LinkerScript::addScriptReferencedSymbolsToSymTable() {
}
bool LinkerScript::shouldAddProvideSym(StringRef symName) {
+ // A Defined may be demoted to Undefined but the return value must stay the
+ // same. Use isUsedInRegularObj to ensure this. The exportDynamic condition,
+ // while not so accurate, allows PROVIDE to define a symbol referenced by a
+ // DSO.
Symbol *sym = elf::ctx.symtab->find(symName);
- return sym && !sym->isDefined() && !sym->isCommon();
+ return sym && !sym->isDefined() && !sym->isCommon() &&
+ (sym->isUsedInRegularObj || sym->exportDynamic);
}
diff --git a/lld/test/ELF/linkerscript/provide-defined.s b/lld/test/ELF/linkerscript/provide-defined.s
new file mode 100644
index 00000000000000..6ebfd706c16e1b
--- /dev/null
+++ b/lld/test/ELF/linkerscript/provide-defined.s
@@ -0,0 +1,33 @@
+# REQUIRES: x86
+## Test the GC behavior when the PROVIDE symbol is defined by a relocatable file.
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
+# RUN: ld.lld -T a.t --gc-sections a.o b.o -o a
+# RUN: llvm-readelf -s a | FileCheck %s
+
+# CHECK: 1: {{.*}} 0 NOTYPE GLOBAL DEFAULT 1 _start
+# CHECK-NEXT:2: {{.*}} 0 NOTYPE GLOBAL DEFAULT 2 f3
+# CHECK-NOT: {{.}}
+
+#--- a.s
+.global _start, f1, f2, f3, bar
+_start:
+ call f3
+
+.section .text.f1,"ax"; f1:
+.section .text.f2,"ax"; f2:
+.section .text.f3,"ax"; f3:
+.section .text.bar,"ax"; bar:
+
+#--- b.s
+ call f2
+
+#--- a.t
+SECTIONS {
+ . = . + SIZEOF_HEADERS;
+ PROVIDE(f1 = bar+1);
+ PROVIDE(f2 = bar+2);
+ PROVIDE(f3 = bar+3);
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. One small suggestion for the comment.
lld/ELF/LinkerScript.cpp
Outdated
@@ -1811,6 +1811,11 @@ void LinkerScript::addScriptReferencedSymbolsToSymTable() { | |||
} | |||
|
|||
bool LinkerScript::shouldAddProvideSym(StringRef symName) { | |||
// A Defined may be demoted to Undefined but the return value must stay the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got a bit confused about whether the return value was this function's return value or the symbol's value. After thinking it through it is definitely the former.
A suggestion:
This function is called before and after garbage collection. To prevent undefined references the result of this function for a symbol must be the same for each call. We use isUsedInRegularObj to
prevent garbage collection demoting a Defined to an Undefnined. The exportDynamic condition, while not so accurate, allows PROVIDE to define a symbol referenced by a DSO.
Created using spr 1.3.5-bogner
Thanks for the review and comment suggestion. Adopted |
Created using spr 1.3.5-bogner
…to Undefined Case: `PROVIDE(f1 = bar);` when both `f1` and `bar` are in separate sections that would be discarded by GC. Due to `demoteDefined`, `shouldAddProvideSym(f1)` may initially return false (when Defined) and then return true (been demoted to Undefined). ``` addScriptReferencedSymbolsToSymTable shouldAddProvideSym(f1): false // the RHS (bar) is not added to `referencedSymbols` and may be GCed declareSymbols shouldAddProvideSym(f1): false markLive demoteSymbolsAndComputeIsPreemptible // demoted f1 to Undefined processSymbolAssignments addSymbol shouldAddProvideSym(f1): true ``` The inconsistency can cause `cmd->expression()` in `addSymbol` to be evaluated, leading to `symbol not found: bar` errors (since `bar` in the RHS is not in `referencedSymbols` and is GCed) (llvm#111478). Fix this by adding a `sym->isUsedInRegularObj` condition, making `shouldAddProvideSym(f1)` values consistent. In addition, we need a `sym->exportDynamic` condition to keep provide-shared.s working. Fixes: ebb326a Pull Request: llvm#111945 (cherry picked from commit 1c6688a)
hi, I've bisected an lld crash to this PR, reproducer tar is in https://crbug.com/373447237 if you could take a look |
This is a -shared link that uses As a workaround, you can remove
|
The inaccurate #111945 condition fixes a PROVIDE regression (#111478) but introduces another regression: in a DSO link, if a symbol referenced only by bitcode files is defined as PROVIDE_HIDDEN, lld would not set the visibility correctly, leading to an assertion failure in DynamicReloc::getSymIndex (https://reviews.llvm.org/D123985). This is because `(sym->isUsedInRegularObj || sym->exportDynamic)` is initially false (bitcode undef does not set `isUsedInRegularObj`) then true (in `addSymbol`, after LTO compilation). Fix this by making the condition accurate: use a map to track defined symbols. Reviewers: smithp35 Reviewed By: smithp35 Pull Request: #112386
#112386 fixes the crash, so we don't need a workaround? |
workaround not needed:) |
…to Undefined Case: `PROVIDE(f1 = bar);` when both `f1` and `bar` are in separate sections that would be discarded by GC. Due to `demoteDefined`, `shouldAddProvideSym(f1)` may initially return false (when Defined) and then return true (been demoted to Undefined). ``` addScriptReferencedSymbolsToSymTable shouldAddProvideSym(f1): false // the RHS (bar) is not added to `referencedSymbols` and may be GCed declareSymbols shouldAddProvideSym(f1): false markLive demoteSymbolsAndComputeIsPreemptible // demoted f1 to Undefined processSymbolAssignments addSymbol shouldAddProvideSym(f1): true ``` The inconsistency can cause `cmd->expression()` in `addSymbol` to be evaluated, leading to `symbol not found: bar` errors (since `bar` in the RHS is not in `referencedSymbols` and is GCed) (llvm#111478). Fix this by adding a `sym->isUsedInRegularObj` condition, making `shouldAddProvideSym(f1)` values consistent. In addition, we need a `sym->exportDynamic` condition to keep provide-shared.s working. Fixes: ebb326a Pull Request: llvm#111945
The inaccurate llvm#111945 condition fixes a PROVIDE regression (llvm#111478) but introduces another regression: in a DSO link, if a symbol referenced only by bitcode files is defined as PROVIDE_HIDDEN, lld would not set the visibility correctly, leading to an assertion failure in DynamicReloc::getSymIndex (https://reviews.llvm.org/D123985). This is because `(sym->isUsedInRegularObj || sym->exportDynamic)` is initially false (bitcode undef does not set `isUsedInRegularObj`) then true (in `addSymbol`, after LTO compilation). Fix this by making the condition accurate: use a map to track defined symbols. Reviewers: smithp35 Reviewed By: smithp35 Pull Request: llvm#112386
Case:
PROVIDE(f1 = bar);
when bothf1
andbar
are in separatesections that would be discarded by GC.
Due to
demoteDefined
,shouldAddProvideSym(f1)
may initially returnfalse (when Defined) and then return true (been demoted to Undefined).
The inconsistency can cause
cmd->expression()
inaddSymbol
to beevaluated, leading to
symbol not found: bar
errors (sincebar
in theRHS is not in
referencedSymbols
and is GCed) (#111478).Fix this by adding a
sym->isUsedInRegularObj
condition, makingshouldAddProvideSym(f1)
values consistent. In addition, we need asym->exportDynamic
condition to keep provide-shared.s working.Fixes: ebb326a