SS->getFile<ELFT>()->IsUsed = true;
}
if (auto *L = dyn_cast<Lazy>(S->body())) {
- // An undefined weak will not fetch archive members, but we have to remember
- // its type. See also comment in addLazyArchive.
+ // An undefined weak will not fetch archive members. See comment on Lazy in
+ // Symbols.h for the details.
if (S->isWeak())
L->Type = Type;
else if (InputFile *F = L->fetch())
if (!S->body()->isUndefined())
return S;
- // Weak undefined symbols should not fetch members from archives. If we were
- // to keep old symbol we would not know that an archive member was available
- // if a strong undefined symbol shows up afterwards in the link. If a strong
- // undefined symbol never shows up, this lazy symbol will get to the end of
- // the link and must be treated as the weak undefined one. We already marked
- // this symbol as used when we added it to the symbol table, but we also need
- // to preserve its type. FIXME: Move the Type field to Symbol.
+ // An undefined weak will not fetch archive members. See comment on Lazy in
+ // Symbols.h for the details.
if (S->isWeak()) {
replaceBody<LazyArchive>(S, F, Sym, S->body()->Type);
return S;
// Returns true if this is a weak undefined symbol.
bool SymbolBody::isUndefWeak() const {
- // A note on isLazy() in the following expression: If you add a weak
- // undefined symbol and then a lazy symbol to the symbol table, the
- // combined result is a lazy weak symbol. isLazy is for that situation.
- //
- // Weak undefined symbols shouldn't fetch archive members (for
- // compatibility with other linkers), but we still want to memorize
- // that there are lazy symbols, because strong undefined symbols
- // could be added later which triggers archive member fetching.
- // Thus, the weak lazy symbol is a valid concept in lld.
+ // See comment on Lazy in Symbols.h for the details.
return !isLocal() && symbol()->isWeak() && (isUndefined() || isLazy());
}
const void *ElfSym;
};
-// This class represents a symbol defined in an archive file. It is
-// created from an archive file header, and it knows how to load an
-// object file from an archive to replace itself with a defined
-// symbol. If the resolver finds both Undefined and Lazy for
-// the same name, it will ask the Lazy to load a file.
+// This represents a symbol that is not yet in the link, but we know where to
+// find it if needed. If the resolver finds both Undefined and Lazy for the same
+// name, it will ask the Lazy to load a file.
+//
+// A special complication is the handling of weak undefined symbols. They should
+// not load a file, but we have to remember we have seen both the weak undefined
+// and the lazy. We represent that with a lazy symbol with a weak binding. This
+// means that code looking for undefined symbols normally also has to take lazy
+// symbols into consideration.
class Lazy : public SymbolBody {
public:
static bool classof(const SymbolBody *S) { return S->isLazy(); }
: SymbolBody(K, Name, /*IsLocal=*/false, llvm::ELF::STV_DEFAULT, Type) {}
};
-// LazyArchive symbols represents symbols in archive files.
+// This class represents a symbol defined in an archive file. It is
+// created from an archive file header, and it knows how to load an
+// object file from an archive to replace itself with a defined
+// symbol.
class LazyArchive : public Lazy {
public:
LazyArchive(const llvm::object::Archive::Symbol S, uint8_t Type);