Skip to content

Commit ba898db

Browse files
authored
[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.
1 parent 34cdd67 commit ba898db

File tree

4 files changed

+28
-7
lines changed

4 files changed

+28
-7
lines changed

lld/COFF/Driver.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,7 @@ void LinkerDriver::maybeCreateECExportThunk(StringRef name, Symbol *&sym) {
13401340
if (!sym)
13411341
return;
13421342
if (auto undef = dyn_cast<Undefined>(sym))
1343-
def = undef->getWeakAlias();
1343+
def = undef->getDefinedWeakAlias();
13441344
else
13451345
def = dyn_cast<Defined>(sym);
13461346
if (!def)
@@ -1376,7 +1376,7 @@ void LinkerDriver::createECExportThunks() {
13761376
continue;
13771377
Defined *targetSym;
13781378
if (auto undef = dyn_cast<Undefined>(sym))
1379-
targetSym = undef->getWeakAlias();
1379+
targetSym = undef->getDefinedWeakAlias();
13801380
else
13811381
targetSym = dyn_cast<Defined>(sym);
13821382
if (!targetSym)

lld/COFF/Symbols.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,20 +112,20 @@ DefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
112112
ImportThunkChunk *chunk)
113113
: Defined(DefinedImportThunkKind, name), wrappedSym(s), data(chunk) {}
114114

115-
Defined *Undefined::getWeakAlias() {
115+
Symbol *Undefined::getWeakAlias() {
116116
// A weak alias may be a weak alias to another symbol, so check recursively.
117117
DenseSet<Symbol *> weakChain;
118118
for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
119-
if (auto *d = dyn_cast<Defined>(a))
120-
return d;
119+
if (!isa<Undefined>(a))
120+
return a;
121121
if (!weakChain.insert(a).second)
122122
break; // We have a cycle.
123123
}
124124
return nullptr;
125125
}
126126

127127
bool Undefined::resolveWeakAlias() {
128-
Defined *d = getWeakAlias();
128+
Defined *d = getDefinedWeakAlias();
129129
if (!d)
130130
return false;
131131

lld/COFF/Symbols.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,10 @@ class Undefined : public Symbol {
340340
// If this symbol is external weak, try to resolve it to a defined
341341
// symbol by searching the chain of fallback symbols. Returns the symbol if
342342
// successful, otherwise returns null.
343-
Defined *getWeakAlias();
343+
Symbol *getWeakAlias();
344+
Defined *getDefinedWeakAlias() {
345+
return dyn_cast_or_null<Defined>(getWeakAlias());
346+
}
344347

345348
// If this symbol is external weak, replace this object with aliased symbol.
346349
bool resolveWeakAlias();

lld/test/COFF/weak-lazy.s

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# REQUIRES: x86
2+
3+
# RUN: llvm-mc -filetype=obj -triple=i686-windows %s -o %t.obj
4+
# RUN: llvm-lib -machine:x86 -out:%t-func.lib %t.obj
5+
6+
# -export:func creates a weak alias to a lazy symbol. Make sure we can handle that when processing -export:func2=func.
7+
# RUN: lld-link -dll -noentry -machine:x86 -out:%t.dll %t-func.lib -export:func -export:func2=func
8+
9+
.text
10+
.def @feat.00;
11+
.scl 3;
12+
.type 0;
13+
.endef
14+
.globl @feat.00
15+
.set @feat.00, 1
16+
.globl _func@0
17+
_func@0:
18+
retl

0 commit comments

Comments
 (0)