Skip to content

Commit b51bfb4

Browse files
MaskRayDanielCChen
authored andcommitted
[ELF] Make shouldAddProvideSym return values consistent when demoted 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
1 parent be6f5e1 commit b51bfb4

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

lld/ELF/LinkerScript.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1814,6 +1814,13 @@ void LinkerScript::addScriptReferencedSymbolsToSymTable() {
18141814
}
18151815

18161816
bool LinkerScript::shouldAddProvideSym(StringRef symName) {
1817+
// This function is called before and after garbage collection. To prevent
1818+
// undefined references from the RHS, the result of this function for a
1819+
// symbol must be the same for each call. We use isUsedInRegularObj to not
1820+
// change the return value of a demoted symbol. The exportDynamic condition,
1821+
// while not so accurate, allows PROVIDE to define a symbol referenced by a
1822+
// DSO.
18171823
Symbol *sym = elf::ctx.symtab->find(symName);
1818-
return sym && !sym->isDefined() && !sym->isCommon();
1824+
return sym && !sym->isDefined() && !sym->isCommon() &&
1825+
(sym->isUsedInRegularObj || sym->exportDynamic);
18191826
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# REQUIRES: x86
2+
## Test the GC behavior when the PROVIDE symbol is defined by a relocatable file.
3+
4+
# RUN: rm -rf %t && split-file %s %t && cd %t
5+
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
6+
# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
7+
# RUN: ld.lld -T a.t --gc-sections a.o b.o -o a
8+
# RUN: llvm-readelf -s a | FileCheck %s
9+
10+
# CHECK: 1: {{.*}} 0 NOTYPE GLOBAL DEFAULT 1 _start
11+
# CHECK-NEXT:2: {{.*}} 0 NOTYPE GLOBAL DEFAULT 2 f3
12+
# CHECK-NOT: {{.}}
13+
14+
#--- a.s
15+
.global _start, f1, f2, f3, bar
16+
_start:
17+
call f3
18+
19+
.section .text.f1,"ax"; f1:
20+
.section .text.f2,"ax"; f2: # referenced by another relocatable file
21+
.section .text.f3,"ax"; f3: # live
22+
.section .text.bar,"ax"; bar:
23+
24+
.comm comm,4,4
25+
26+
#--- b.s
27+
call f2
28+
29+
#--- a.t
30+
SECTIONS {
31+
. = . + SIZEOF_HEADERS;
32+
PROVIDE(f1 = bar+1);
33+
PROVIDE(f2 = bar+2);
34+
PROVIDE(f3 = bar+3);
35+
PROVIDE(f4 = comm+4);
36+
}

0 commit comments

Comments
 (0)