[LLD][COFF] Fix handling of weak aliases referencing lazy symbols (#112243)

The assumption that a symbol is either `Defined` or `Undefined` is not
always true for some cases. For example, `mangleMaybe` may create a weak
alias to a lazy archive symbol.
This commit is contained in:
Jacek Caban 2024-10-15 22:58:13 +02:00 committed by GitHub
parent 34cdd67c85
commit ba898dba48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 28 additions and 7 deletions

View File

@ -1340,7 +1340,7 @@ void LinkerDriver::maybeCreateECExportThunk(StringRef name, Symbol *&sym) {
if (!sym)
return;
if (auto undef = dyn_cast<Undefined>(sym))
def = undef->getWeakAlias();
def = undef->getDefinedWeakAlias();
else
def = dyn_cast<Defined>(sym);
if (!def)
@ -1376,7 +1376,7 @@ void LinkerDriver::createECExportThunks() {
continue;
Defined *targetSym;
if (auto undef = dyn_cast<Undefined>(sym))
targetSym = undef->getWeakAlias();
targetSym = undef->getDefinedWeakAlias();
else
targetSym = dyn_cast<Defined>(sym);
if (!targetSym)

View File

@ -112,12 +112,12 @@ DefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
ImportThunkChunk *chunk)
: Defined(DefinedImportThunkKind, name), wrappedSym(s), data(chunk) {}
Defined *Undefined::getWeakAlias() {
Symbol *Undefined::getWeakAlias() {
// A weak alias may be a weak alias to another symbol, so check recursively.
DenseSet<Symbol *> weakChain;
for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
if (auto *d = dyn_cast<Defined>(a))
return d;
if (!isa<Undefined>(a))
return a;
if (!weakChain.insert(a).second)
break; // We have a cycle.
}
@ -125,7 +125,7 @@ Defined *Undefined::getWeakAlias() {
}
bool Undefined::resolveWeakAlias() {
Defined *d = getWeakAlias();
Defined *d = getDefinedWeakAlias();
if (!d)
return false;

View File

@ -340,7 +340,10 @@ public:
// If this symbol is external weak, try to resolve it to a defined
// symbol by searching the chain of fallback symbols. Returns the symbol if
// successful, otherwise returns null.
Defined *getWeakAlias();
Symbol *getWeakAlias();
Defined *getDefinedWeakAlias() {
return dyn_cast_or_null<Defined>(getWeakAlias());
}
// If this symbol is external weak, replace this object with aliased symbol.
bool resolveWeakAlias();

18
lld/test/COFF/weak-lazy.s Normal file
View File

@ -0,0 +1,18 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=i686-windows %s -o %t.obj
# RUN: llvm-lib -machine:x86 -out:%t-func.lib %t.obj
# -export:func creates a weak alias to a lazy symbol. Make sure we can handle that when processing -export:func2=func.
# RUN: lld-link -dll -noentry -machine:x86 -out:%t.dll %t-func.lib -export:func -export:func2=func
.text
.def @feat.00;
.scl 3;
.type 0;
.endef
.globl @feat.00
.set @feat.00, 1
.globl _func@0
_func@0:
retl