Skip to content

Commit bd5d0bc

Browse files
committed
[ELF] PROVIDE: fix spurious "symbol not found"
When archive member extraction involving ENTRY happens after `addScriptReferencedSymbolsToSymTable`, `addScriptReferencedSymbolsToSymTable` may fail to define some PROVIDE symbols used by ENTRY. This is an edge case that regressed after llvm#84512. (The interaction with PROVIDE and ENTRY-in-archive was not considered before). Fixes: ebb326a
1 parent cc308f6 commit bd5d0bc

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

lld/ELF/Driver.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2727,13 +2727,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
27272727
// Create dynamic sections for dynamic linking and static PIE.
27282728
config->hasDynSymTab = !ctx.sharedFiles.empty() || config->isPic;
27292729

2730-
script->addScriptReferencedSymbolsToSymTable();
2731-
2732-
// Prevent LTO from removing any definition referenced by -u.
2733-
for (StringRef name : config->undefined)
2734-
if (Defined *sym = dyn_cast_or_null<Defined>(symtab.find(name)))
2735-
sym->isUsedInRegularObj = true;
2736-
27372730
// If an entry symbol is in a static archive, pull out that file now.
27382731
if (Symbol *sym = symtab.find(config->entry))
27392732
handleUndefined(sym, "--entry");
@@ -2742,6 +2735,16 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
27422735
for (StringRef pat : args::getStrings(args, OPT_undefined_glob))
27432736
handleUndefinedGlob(pat);
27442737

2738+
// After potential archive member extraction involving ENTRY and
2739+
// -u/--undefined-glob, check whether PROVIDE symbols should be defined (the
2740+
// RHS may refer to definitions in just extracted object files).
2741+
script->addScriptReferencedSymbolsToSymTable();
2742+
2743+
// Prevent LTO from removing any definition referenced by -u.
2744+
for (StringRef name : config->undefined)
2745+
if (Defined *sym = dyn_cast_or_null<Defined>(symtab.find(name)))
2746+
sym->isUsedInRegularObj = true;
2747+
27452748
// Mark -init and -fini symbols so that the LTO doesn't eliminate them.
27462749
if (Symbol *sym = dyn_cast_or_null<Defined>(symtab.find(config->init)))
27472750
sym->isUsedInRegularObj = true;

lld/test/ELF/linkerscript/symbolreferenced.s

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@
5050
# RUN: not ld.lld -T chain2.t a.o 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
5151
# ERR-COUNT-3: error: chain2.t:1: symbol not found: undef
5252

53+
## _start in a lazy object file references PROVIDE symbols. We extract _start
54+
## earlier to avoid spurious "symbol not found" errors.
55+
# RUN: llvm-mc -filetype=obj -triple=x86_64 undef.s -o undef.o
56+
# RUN: llvm-mc -filetype=obj -triple=x86_64 start.s -o start.o
57+
# RUN: ld.lld -T chain2.t undef.o --start-lib start.o --end-lib -o lazy
58+
# RUN: llvm-nm lazy | FileCheck %s --check-prefix=LAZY
59+
# RUN: ld.lld -e 0 -T chain2.t --undefined-glob '_start*' undef.o --start-lib start.o --end-lib -o lazy
60+
# RUN: llvm-nm lazy | FileCheck %s --check-prefix=LAZY
61+
62+
# LAZY: T _start
63+
# LAZY-NEXT: t f1
64+
# LAZY-NEXT: T f2
65+
# LAZY-NEXT: T newsym
66+
# LAZY-NEXT: T unde
67+
5368
#--- a.s
5469
.global _start
5570
_start:
@@ -89,3 +104,13 @@ PROVIDE(newsym = f1);
89104
PROVIDE(f2 = undef);
90105
PROVIDE_HIDDEN(f1 = f2);
91106
PROVIDE(newsym = f1);
107+
108+
#--- undef.s
109+
.globl undef
110+
undef: ret
111+
112+
#--- start.s
113+
.globl _start
114+
_start: ret
115+
.data
116+
.quad newsym

0 commit comments

Comments
 (0)