Index: lld/ELF/Config.h =================================================================== --- lld/ELF/Config.h +++ lld/ELF/Config.h @@ -24,7 +24,6 @@ namespace elf { class InputFile; -struct Symbol; enum ELFKind { ELFNoneKind, Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -992,7 +992,7 @@ if (auto *F = dyn_cast(File)) if (All || Libs.count(path::filename(F->getName()))) for (SymbolBody *Sym : F->getSymbols()) - Sym->symbol()->VersionId = VER_NDX_LOCAL; + Sym->VersionId = VER_NDX_LOCAL; } // Do actual linking. Note that when this function is called, Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -557,16 +557,14 @@ switch (Sym->st_shndx) { case SHN_UNDEF: - return Symtab - ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, - /*CanOmitFromDynSym=*/false, this) - ->body(); + return Symtab->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, + Type, + /*CanOmitFromDynSym=*/false, this); case SHN_COMMON: if (Value == 0 || Value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + Name + "' has invalid alignment: " + Twine(Value)); - return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, this) - ->body(); + return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, this); } switch (Binding) { @@ -576,13 +574,11 @@ case STB_WEAK: case STB_GNU_UNIQUE: if (Sec == &InputSection::Discarded) - return Symtab - ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, - /*CanOmitFromDynSym=*/false, this) - ->body(); - return Symtab - ->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, this) - ->body(); + return Symtab->addUndefined(Name, /*IsLocal=*/false, Binding, + StOther, Type, + /*CanOmitFromDynSym=*/false, this); + return Symtab->addRegular(Name, StOther, Type, Value, Size, Binding, + Sec, this); } } @@ -593,8 +589,7 @@ template void ArchiveFile::parse() { Symbols.reserve(File->getNumberOfSymbols()); for (const Archive::Symbol &Sym : File->symbols()) - Symbols.push_back( - Symtab->addLazyArchive(Sym.getName(), this, Sym)->body()); + Symbols.push_back(Symtab->addLazyArchive(Sym.getName(), this, Sym)); } // Returns a buffer pointing to a member file containing a given symbol. @@ -854,9 +849,9 @@ } template -static Symbol *createBitcodeSymbol(const std::vector &KeptComdats, - const lto::InputFile::Symbol &ObjSym, - BitcodeFile *F) { +static SymbolBody *createBitcodeSymbol(const std::vector &KeptComdats, + const lto::InputFile::Symbol &ObjSym, + BitcodeFile *F) { StringRef NameRef = Saver.save(ObjSym.getName()); uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL; @@ -889,8 +884,7 @@ KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second); for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) - Symbols.push_back( - createBitcodeSymbol(KeptComdats, ObjSym, this)->body()); + Symbols.push_back(createBitcodeSymbol(KeptComdats, ObjSym, this)); } static ELFKind getELFKind(MemoryBufferRef MB) { Index: lld/ELF/LTO.cpp =================================================================== --- lld/ELF/LTO.cpp +++ lld/ELF/LTO.cpp @@ -108,8 +108,8 @@ } BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) { - for (Symbol *Sym : Symtab->getSymbols()) { - StringRef Name = Sym->body()->getName(); + for (SymbolBody *Sym : Symtab->getSymbols()) { + StringRef Name = Sym->getName(); for (StringRef Prefix : {"__start_", "__stop_"}) if (Name.startswith(Prefix)) UsedStartStop.insert(Name.substr(Prefix.size())); @@ -118,9 +118,9 @@ BitcodeCompiler::~BitcodeCompiler() = default; -static void undefine(Symbol *S) { - replaceBody(S, nullptr, S->body()->getName(), /*IsLocal=*/false, - STV_DEFAULT, S->body()->Type); +static void undefine(SymbolBody *S) { + replaceBody(S, nullptr, S->getName(), /*IsLocal=*/false, + STV_DEFAULT, S->Type); } void BitcodeCompiler::add(BitcodeFile &F) { @@ -136,8 +136,7 @@ // Provide a resolution to the LTO API for each symbol. for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { - SymbolBody *B = Syms[SymNum]; - Symbol *Sym = B->symbol(); + SymbolBody *Sym = Syms[SymNum]; lto::SymbolResolution &R = Resols[SymNum]; ++SymNum; @@ -146,7 +145,7 @@ // flags an undefined in IR with a definition in ASM as prevailing. // Once IRObjectFile is fixed to report only one symbol this hack can // be removed. - R.Prevailing = !ObjSym.isUndefined() && B->getFile() == &F; + R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F; // We ask LTO to preserve following global symbols: // 1) All symbols when doing relocatable link, so that them can be used @@ -165,7 +164,7 @@ // still not final: // 1) Aliased (with --defsym) or wrapped (with --wrap) symbols. // 2) Symbols redefined in linker script. - R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(B->getName()); + R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(Sym->getName()); } checkError(LTOObj->add(std::move(F.Obj), Resols)); } Index: lld/ELF/LinkerScript.cpp =================================================================== --- lld/ELF/LinkerScript.cpp +++ lld/ELF/LinkerScript.cpp @@ -127,7 +127,7 @@ return; // Define a symbol. - Symbol *Sym; + SymbolBody *Sym; uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, @@ -151,7 +151,7 @@ replaceBody(Sym, nullptr, Cmd->Name, /*IsLocal=*/false, Visibility, STT_NOTYPE, SymValue, 0, Sec); - Cmd->Sym = cast(Sym->body()); + Cmd->Sym = cast(Sym); } // This function is called from assignAddresses, while we are Index: lld/ELF/MarkLive.cpp =================================================================== --- lld/ELF/MarkLive.cpp +++ lld/ELF/MarkLive.cpp @@ -228,9 +228,9 @@ // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. - for (Symbol *S : Symtab->getSymbols()) + for (SymbolBody *S : Symtab->getSymbols()) if (S->includeInDynsym()) - MarkSymbol(S->body()); + MarkSymbol(S); // Preserve special sections and those which are specified in linker // script KEEP command. Index: lld/ELF/Relocations.cpp =================================================================== --- lld/ELF/Relocations.cpp +++ lld/ELF/Relocations.cpp @@ -543,7 +543,7 @@ for (SharedSymbol *Sym : getSymbolsAt(SS)) { Sym->CopyRelSec = Sec; Sym->IsPreemptible = false; - Sym->symbol()->IsUsedInRegularObj = true; + Sym->IsUsedInRegularObj = true; } In::RelaDyn->addReloc({Target->CopyRel, Sec, 0, false, SS, 0}); @@ -716,11 +716,11 @@ if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) return false; - if (Sym.isLocal() || !Sym.isUndefined() || Sym.symbol()->isWeak()) + if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak()) return false; - bool CanBeExternal = Sym.symbol()->computeBinding() != STB_LOCAL && - Sym.getVisibility() == STV_DEFAULT; + bool CanBeExternal = + Sym.computeBinding() != STB_LOCAL && Sym.getVisibility() == STV_DEFAULT; if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) return false; Index: lld/ELF/SymbolTable.h =================================================================== --- lld/ELF/SymbolTable.h +++ lld/ELF/SymbolTable.h @@ -19,8 +19,6 @@ namespace lld { namespace elf { -struct Symbol; - // SymbolTable is a bucket of all known symbols, including defined, // undefined, or lazy symbols (the last one is symbols in archive // files whose archive members are not yet loaded). @@ -41,22 +39,22 @@ template void addSymbolWrap(StringRef Name); void applySymbolRenames(); - ArrayRef getSymbols() const { return SymVector; } + ArrayRef getSymbols() const { return SymVector; } template DefinedRegular *addAbsolute(StringRef Name, uint8_t Visibility = llvm::ELF::STV_HIDDEN, uint8_t Binding = llvm::ELF::STB_GLOBAL); - template Symbol *addUndefined(StringRef Name); + template SymbolBody *addUndefined(StringRef Name); template - Symbol *addUndefined(StringRef Name, bool IsLocal, uint8_t Binding, - uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, - InputFile *File); + SymbolBody *addUndefined(StringRef Name, bool IsLocal, uint8_t Binding, + uint8_t StOther, uint8_t Type, + bool CanOmitFromDynSym, InputFile *File); template - Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, - uint64_t Value, uint64_t Size, uint8_t Binding, - SectionBase *Section, InputFile *File); + SymbolBody *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, + uint64_t Value, uint64_t Size, uint8_t Binding, + SectionBase *Section, InputFile *File); template void addShared(StringRef Name, SharedFile *F, @@ -64,22 +62,23 @@ const typename ELFT::Verdef *Verdef); template - Symbol *addLazyArchive(StringRef Name, ArchiveFile *F, - const llvm::object::Archive::Symbol S); + SymbolBody *addLazyArchive(StringRef Name, ArchiveFile *F, + const llvm::object::Archive::Symbol S); template void addLazyObject(StringRef Name, LazyObjFile &Obj); - Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, - uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File); + SymbolBody *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, + uint8_t Type, bool CanOmitFromDynSym, + BitcodeFile *File); - Symbol *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment, - uint8_t Binding, uint8_t StOther, uint8_t Type, - InputFile *File); + SymbolBody *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment, + uint8_t Binding, uint8_t StOther, uint8_t Type, + InputFile *File); - std::pair insert(StringRef Name); - std::pair insert(StringRef Name, uint8_t Type, - uint8_t Visibility, bool CanOmitFromDynSym, - InputFile *File); + std::pair insert(StringRef Name); + std::pair insert(StringRef Name, uint8_t Type, + uint8_t Visibility, + bool CanOmitFromDynSym, InputFile *File); template void fetchIfLazy(StringRef Name); template void scanShlibUndefined(); @@ -94,7 +93,7 @@ private: std::vector findByVersion(SymbolVersion Ver); std::vector findAllByVersion(SymbolVersion Ver); - void defsym(Symbol *Dst, Symbol *Src); + void defsym(SymbolBody *Dst, SymbolBody *Src); llvm::StringMap> &getDemangledSyms(); void handleAnonymousVersion(); @@ -116,7 +115,7 @@ // FIXME: Experiment with passing in a custom hashing or sorting the symbols // once symbol resolution is finished. llvm::DenseMap Symtab; - std::vector SymVector; + std::vector SymVector; // Comdat groups define "link once" sections. If two comdat groups have the // same name, only one of them is linked, and the other is ignored. This set @@ -133,8 +132,8 @@ llvm::Optional>> DemangledSyms; struct SymbolRenaming { - Symbol *Dst; - Symbol *Src; + SymbolBody *Dst; + SymbolBody *Src; uint8_t Binding; }; @@ -142,7 +141,7 @@ std::vector Defsyms; // For -wrap. - std::vector> WrapSymbols; + std::vector> WrapSymbols; // For LTO. std::unique_ptr LTO; Index: lld/ELF/SymbolTable.cpp =================================================================== --- lld/ELF/SymbolTable.cpp +++ lld/ELF/SymbolTable.cpp @@ -136,9 +136,9 @@ template DefinedRegular *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility, uint8_t Binding) { - Symbol *Sym = addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, - nullptr, nullptr); - return cast(Sym->body()); + SymbolBody *Sym = addRegular(Name, Visibility, STT_NOTYPE, 0, 0, + Binding, nullptr, nullptr); + return cast(Sym); } // Set a flag for --trace-symbol so that we can print out a log message @@ -150,12 +150,11 @@ // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. // Used to implement --wrap. template void SymbolTable::addSymbolWrap(StringRef Name) { - SymbolBody *B = find(Name); - if (!B) + SymbolBody *Sym = find(Name); + if (!Sym) return; - Symbol *Sym = B->symbol(); - Symbol *Real = addUndefined(Saver.save("__real_" + Name)); - Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); + SymbolBody *Real = addUndefined(Saver.save("__real_" + Name)); + SymbolBody *Wrap = addUndefined(Saver.save("__wrap_" + Name)); defsym(Real, Sym); defsym(Sym, Wrap); @@ -172,7 +171,7 @@ return; } - defsym(addUndefined(Alias), B->symbol()); + defsym(addUndefined(Alias), B); } // Apply symbol renames created by -wrap and -defsym. The renames are created @@ -190,13 +189,13 @@ // __wrap_foo point to, we just want have __real_foo in the symbol table. // First make a copy of __real_foo - std::vector Origs; + std::vector Origs; for (const auto &P : WrapSymbols) - Origs.push_back(*P.second); + Origs.emplace_back(*(SymbolUnion *)P.second); // Replace __real_foo with foo and foo with __wrap_foo for (SymbolRenaming &S : Defsyms) { - S.Dst->body()->copyFrom(S.Src->body()); + S.Dst->copyFrom(S.Src); S.Dst->File = S.Src->File; S.Dst->Binding = S.Binding; } @@ -205,16 +204,16 @@ // __real_foo into it. for (unsigned I = 0, N = WrapSymbols.size(); I < N; ++I) { // We now have two copies of __wrap_foo. Drop one. - Symbol *Wrap = WrapSymbols[I].first; + SymbolBody *Wrap = WrapSymbols[I].first; Wrap->IsUsedInRegularObj = false; - Symbol *Real = &Origs[I]; + auto *Real = (SymbolBody *)&Origs[I]; // If __real_foo was undefined, we don't want it in the symbol table. - if (!Real->body()->isInCurrentOutput()) + if (!Real->isInCurrentOutput()) continue; - auto *NewSym = make(); - memcpy(NewSym, Real, sizeof(Symbol)); + auto *NewSym = (SymbolBody *)make(); + memcpy(NewSym, Real, sizeof(SymbolUnion)); SymVector.push_back(NewSym); } } @@ -228,7 +227,7 @@ } // Find an existing symbol or create and insert a new one. -std::pair SymbolTable::insert(StringRef Name) { +std::pair SymbolTable::insert(StringRef Name) { // @@ means the symbol is the default version. In that // case @@ will be used to resolve references to . // @@ -249,9 +248,9 @@ V = SymIndex((int)SymVector.size(), true); } - Symbol *Sym; + SymbolBody *Sym; if (IsNew) { - Sym = make(); + Sym = (SymbolBody *)make(); Sym->InVersionScript = false; Sym->Binding = STB_WEAK; Sym->Visibility = STV_DEFAULT; @@ -269,11 +268,11 @@ // Find an existing symbol or create and insert a new one, then apply the given // attributes. -std::pair SymbolTable::insert(StringRef Name, uint8_t Type, - uint8_t Visibility, - bool CanOmitFromDynSym, - InputFile *File) { - Symbol *S; +std::pair SymbolTable::insert(StringRef Name, uint8_t Type, + uint8_t Visibility, + bool CanOmitFromDynSym, + InputFile *File) { + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); @@ -286,17 +285,16 @@ if (!File || File->kind() == InputFile::ObjKind) S->IsUsedInRegularObj = true; - if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && - ((Type == STT_TLS) != S->body()->isTls())) { - error("TLS attribute mismatch: " + toString(*S->body()) + - "\n>>> defined in " + toString(S->File) + "\n>>> defined in " + - toString(File)); + if (!WasInserted && S->Type != SymbolBody::UnknownType && + ((Type == STT_TLS) != S->isTls())) { + error("TLS attribute mismatch: " + toString(*S) + "\n>>> defined in " + + toString(S->File) + "\n>>> defined in " + toString(File)); } return {S, WasInserted}; } -template Symbol *SymbolTable::addUndefined(StringRef Name) { +template SymbolBody *SymbolTable::addUndefined(StringRef Name) { return addUndefined(Name, /*IsLocal=*/false, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); @@ -305,30 +303,29 @@ static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; } template -Symbol *SymbolTable::addUndefined(StringRef Name, bool IsLocal, uint8_t Binding, - uint8_t StOther, uint8_t Type, - bool CanOmitFromDynSym, InputFile *File) { - Symbol *S; +SymbolBody *SymbolTable::addUndefined(StringRef Name, bool IsLocal, + uint8_t Binding, uint8_t StOther, + uint8_t Type, bool CanOmitFromDynSym, + InputFile *File) { + SymbolBody *S; bool WasInserted; uint8_t Visibility = getVisibility(StOther); std::tie(S, WasInserted) = insert(Name, Type, Visibility, CanOmitFromDynSym, File); // An undefined symbol with non default visibility must be satisfied // in the same DSO. - if (WasInserted || - (isa(S->body()) && Visibility != STV_DEFAULT)) { + if (WasInserted || (isa(S) && Visibility != STV_DEFAULT)) { S->Binding = Binding; replaceBody(S, File, Name, IsLocal, StOther, Type); return S; } if (Binding != STB_WEAK) { - SymbolBody *B = S->body(); - if (!B->isInCurrentOutput()) + if (!S->isInCurrentOutput()) S->Binding = Binding; - if (auto *SS = dyn_cast(B)) + if (auto *SS = dyn_cast(S)) SS->getFile()->IsUsed = true; } - if (auto *L = dyn_cast(S->body())) { + if (auto *L = dyn_cast(S)) { // An undefined weak will not fetch archive members. See comment on Lazy in // Symbols.h for the details. if (S->isWeak()) @@ -345,9 +342,9 @@ // FIXME: If users can transition to using // .symver foo,foo@@@VER // we can delete this hack. -static int compareVersion(Symbol *S, StringRef Name) { +static int compareVersion(SymbolBody *S, StringRef Name) { bool A = Name.contains("@@"); - bool B = S->body()->getName().contains("@@"); + bool B = S->getName().contains("@@"); if (A && !B) return 1; if (!A && B) @@ -358,17 +355,14 @@ // We have a new defined symbol with the specified binding. Return 1 if the new // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are // strong defined symbols. -static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding, +static int compareDefined(SymbolBody *S, bool WasInserted, uint8_t Binding, StringRef Name) { if (WasInserted) return 1; - SymbolBody *Body = S->body(); - if (!Body->isInCurrentOutput()) + if (!S->isInCurrentOutput()) return 1; - if (int R = compareVersion(S, Name)) return R; - if (Binding == STB_WEAK) return -1; if (S->isWeak()) @@ -379,21 +373,21 @@ // We have a new non-common defined symbol with the specified binding. Return 1 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there // is a conflict. If the new symbol wins, also update the binding. -static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, - bool IsAbsolute, uint64_t Value, - StringRef Name) { +static int compareDefinedNonCommon(SymbolBody *S, bool WasInserted, + uint8_t Binding, bool IsAbsolute, + uint64_t Value, StringRef Name) { if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) { if (Cmp > 0) S->Binding = Binding; return Cmp; } - SymbolBody *B = S->body(); - if (isa(B)) { + if (isa(S)) { // Non-common symbols take precedence over common symbols. if (Config->WarnCommon) - warn("common " + S->body()->getName() + " is overridden"); + warn("common " + S->getName() + " is overridden"); return 1; - } else if (auto *R = dyn_cast(B)) { + } + if (auto *R = dyn_cast(S)) { if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute && R->Value == Value) return -1; @@ -401,10 +395,11 @@ return 0; } -Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment, - uint8_t Binding, uint8_t StOther, uint8_t Type, - InputFile *File) { - Symbol *S; +SymbolBody *SymbolTable::addCommon(StringRef N, uint64_t Size, + uint32_t Alignment, uint8_t Binding, + uint8_t StOther, uint8_t Type, + InputFile *File) { + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); @@ -413,16 +408,16 @@ S->Binding = Binding; replaceBody(S, File, N, Size, Alignment, StOther, Type); } else if (Cmp == 0) { - auto *C = dyn_cast(S->body()); + auto *C = dyn_cast(S); if (!C) { // Non-common symbols take precedence over common symbols. if (Config->WarnCommon) - warn("common " + S->body()->getName() + " is overridden"); + warn("common " + S->getName() + " is overridden"); return S; } if (Config->WarnCommon) - warn("multiple common of " + S->body()->getName()); + warn("multiple common of " + S->getName()); Alignment = C->Alignment = std::max(C->Alignment, Alignment); if (Size > C->Size) @@ -477,10 +472,11 @@ } template -Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, - uint64_t Value, uint64_t Size, uint8_t Binding, - SectionBase *Section, InputFile *File) { - Symbol *S; +SymbolBody *SymbolTable::addRegular(StringRef Name, uint8_t StOther, + uint8_t Type, uint64_t Value, uint64_t Size, + uint8_t Binding, SectionBase *Section, + InputFile *File) { + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); @@ -490,8 +486,8 @@ replaceBody(S, File, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section); else if (Cmp == 0) - reportDuplicate(S->body(), - dyn_cast_or_null(Section), Value); + reportDuplicate(S, dyn_cast_or_null(Section), + Value); return S; } @@ -502,7 +498,7 @@ // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT // as the visibility, which will leave the visibility in the symbol table // unchanged. - Symbol *S; + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, File); @@ -510,11 +506,10 @@ if (Sym.getVisibility() == STV_DEFAULT) S->ExportDynamic = true; - SymbolBody *Body = S->body(); // An undefined symbol with non default visibility must be satisfied // in the same DSO. - if (WasInserted || ((Body->isUndefined() || Body->isLazy()) && - Body->getVisibility() == STV_DEFAULT)) { + if (WasInserted || ((S->isUndefined() || S->isLazy()) && + S->getVisibility() == STV_DEFAULT)) { replaceBody(S, File, Name, Sym.st_other, Sym.getType(), Sym.st_value, Sym.st_size, Alignment, Verdef); if (!S->isWeak()) @@ -522,10 +517,10 @@ } } -Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, - uint8_t StOther, uint8_t Type, - bool CanOmitFromDynSym, BitcodeFile *F) { - Symbol *S; +SymbolBody *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, + uint8_t StOther, uint8_t Type, + bool CanOmitFromDynSym, BitcodeFile *F) { + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F); @@ -535,7 +530,7 @@ replaceBody(S, F, Name, /*IsLocal=*/false, StOther, Type, 0, 0, nullptr); else if (Cmp == 0) - reportDuplicate(S->body(), F); + reportDuplicate(S, F); return S; } @@ -546,10 +541,10 @@ SymIndex V = It->second; if (V.Idx == -1) return nullptr; - return SymVector[V.Idx]->body(); + return SymVector[V.Idx]; } -void SymbolTable::defsym(Symbol *Dst, Symbol *Src) { +void SymbolTable::defsym(SymbolBody *Dst, SymbolBody *Src) { // We want to tell LTO not to inline Dst symbol because LTO doesn't // know the final symbol contents after renaming. Dst->CanInline = false; @@ -561,22 +556,22 @@ } template -Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F, - const object::Archive::Symbol Sym) { - Symbol *S; +SymbolBody *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F, + const object::Archive::Symbol Sym) { + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); if (WasInserted) { replaceBody(S, F, Sym, SymbolBody::UnknownType); return S; } - if (!S->body()->isUndefined()) + if (!S->isUndefined()) return S; // An undefined weak will not fetch archive members. See comment on Lazy in // Symbols.h for the details. if (S->isWeak()) { - replaceBody(S, F, Sym, S->body()->Type); + replaceBody(S, F, Sym, S->Type); return S; } std::pair MBInfo = F->getMember(&Sym); @@ -587,19 +582,19 @@ template void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) { - Symbol *S; + SymbolBody *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); if (WasInserted) { replaceBody(S, &Obj, Name, SymbolBody::UnknownType); return; } - if (!S->body()->isUndefined()) + if (!S->isUndefined()) return; // See comment for addLazyArchive above. if (S->isWeak()) - replaceBody(S, &Obj, Name, S->body()->Type); + replaceBody(S, &Obj, Name, S->Type); else if (InputFile *F = Obj.fetch()) addFile(F); } @@ -609,7 +604,7 @@ if (SymbolBody *B = find(Name)) { // Mark the symbol not to be eliminated by LTO // even if it is a bitcode symbol. - B->symbol()->IsUsedInRegularObj = true; + B->IsUsedInRegularObj = true; if (auto *L = dyn_cast_or_null(B)) if (InputFile *File = L->fetch()) addFile(File); @@ -629,13 +624,13 @@ SymbolBody *Sym = find(U); if (!Sym || !Sym->isDefined()) continue; - Sym->symbol()->ExportDynamic = true; + Sym->ExportDynamic = true; // If -dynamic-list is given, the default version is set to // VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym. // Set to VER_NDX_GLOBAL so the symbol will be handled as if it were // specified by -dynamic-list. - Sym->symbol()->VersionId = VER_NDX_GLOBAL; + Sym->VersionId = VER_NDX_GLOBAL; } } } @@ -656,14 +651,13 @@ StringMap> &SymbolTable::getDemangledSyms() { if (!DemangledSyms) { DemangledSyms.emplace(); - for (Symbol *Sym : SymVector) { - SymbolBody *B = Sym->body(); - if (!B->isInCurrentOutput()) + for (SymbolBody *Sym : SymVector) { + if (!Sym->isInCurrentOutput()) continue; - if (Optional S = demangle(B->getName())) - (*DemangledSyms)[*S].push_back(B); + if (Optional S = demangle(Sym->getName())) + (*DemangledSyms)[*S].push_back(Sym); else - (*DemangledSyms)[B->getName()].push_back(B); + (*DemangledSyms)[Sym->getName()].push_back(Sym); } } return *DemangledSyms; @@ -689,11 +683,9 @@ return Res; } - for (Symbol *Sym : SymVector) { - SymbolBody *B = Sym->body(); - if (B->isInCurrentOutput() && M.match(B->getName())) - Res.push_back(B); - } + for (SymbolBody *Sym : SymVector) + if (Sym->isInCurrentOutput() && M.match(Sym->getName())) + Res.push_back(Sym); return Res; } @@ -722,8 +714,8 @@ for (SymbolBody *B : Syms) { if (!Config->Shared) - B->symbol()->ExportDynamic = true; - else if (B->symbol()->includeInDynsym()) + B->ExportDynamic = true; + else if (B->includeInDynsym()) B->IsPreemptible = true; } } @@ -746,14 +738,13 @@ } // Assign the version. - for (SymbolBody *B : Syms) { + for (SymbolBody *Sym : Syms) { // Skip symbols containing version info because symbol versions // specified by symbol names take precedence over version scripts. // See parseSymbolVersion(). - if (B->getName().contains('@')) + if (Sym->getName().contains('@')) continue; - Symbol *Sym = B->symbol(); if (Sym->InVersionScript) warn("duplicate symbol '" + Ver.Name + "' in version script"); Sym->VersionId = VersionId; @@ -769,8 +760,8 @@ // so we set a version to a symbol only if no version has been assigned // to the symbol. This behavior is compatible with GNU. for (SymbolBody *B : findAllByVersion(Ver)) - if (B->symbol()->VersionId == Config->DefaultSymbolVersion) - B->symbol()->VersionId = VersionId; + if (B->VersionId == Config->DefaultSymbolVersion) + B->VersionId = VersionId; } // This function processes version scripts by updating VersionId @@ -801,8 +792,8 @@ // Symbol themselves might know their versions because symbols // can contain versions in the form of @. // Let them parse and update their names to exclude version suffix. - for (Symbol *Sym : SymVector) - Sym->body()->parseSymbolVersion(); + for (SymbolBody *Sym : SymVector) + Sym->parseSymbolVersion(); } template void SymbolTable::addSymbolWrap(StringRef); @@ -810,23 +801,27 @@ template void SymbolTable::addSymbolWrap(StringRef); template void SymbolTable::addSymbolWrap(StringRef); -template Symbol *SymbolTable::addUndefined(StringRef); -template Symbol *SymbolTable::addUndefined(StringRef); -template Symbol *SymbolTable::addUndefined(StringRef); -template Symbol *SymbolTable::addUndefined(StringRef); - -template Symbol *SymbolTable::addUndefined(StringRef, bool, uint8_t, - uint8_t, uint8_t, bool, - InputFile *); -template Symbol *SymbolTable::addUndefined(StringRef, bool, uint8_t, - uint8_t, uint8_t, bool, - InputFile *); -template Symbol *SymbolTable::addUndefined(StringRef, bool, uint8_t, - uint8_t, uint8_t, bool, - InputFile *); -template Symbol *SymbolTable::addUndefined(StringRef, bool, uint8_t, - uint8_t, uint8_t, bool, - InputFile *); +template SymbolBody *SymbolTable::addUndefined(StringRef); +template SymbolBody *SymbolTable::addUndefined(StringRef); +template SymbolBody *SymbolTable::addUndefined(StringRef); +template SymbolBody *SymbolTable::addUndefined(StringRef); + +template SymbolBody *SymbolTable::addUndefined(StringRef, bool, + uint8_t, uint8_t, + uint8_t, bool, + InputFile *); +template SymbolBody *SymbolTable::addUndefined(StringRef, bool, + uint8_t, uint8_t, + uint8_t, bool, + InputFile *); +template SymbolBody *SymbolTable::addUndefined(StringRef, bool, + uint8_t, uint8_t, + uint8_t, bool, + InputFile *); +template SymbolBody *SymbolTable::addUndefined(StringRef, bool, + uint8_t, uint8_t, + uint8_t, bool, + InputFile *); template void SymbolTable::addSymbolAlias(StringRef, StringRef); template void SymbolTable::addSymbolAlias(StringRef, StringRef); @@ -838,18 +833,18 @@ template void SymbolTable::addCombinedLTOObject(); template void SymbolTable::addCombinedLTOObject(); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); +template SymbolBody * +SymbolTable::addRegular(StringRef, uint8_t, uint8_t, uint64_t, + uint64_t, uint8_t, SectionBase *, InputFile *); +template SymbolBody * +SymbolTable::addRegular(StringRef, uint8_t, uint8_t, uint64_t, + uint64_t, uint8_t, SectionBase *, InputFile *); +template SymbolBody * +SymbolTable::addRegular(StringRef, uint8_t, uint8_t, uint64_t, + uint64_t, uint8_t, SectionBase *, InputFile *); +template SymbolBody * +SymbolTable::addRegular(StringRef, uint8_t, uint8_t, uint64_t, + uint64_t, uint8_t, SectionBase *, InputFile *); template DefinedRegular *SymbolTable::addAbsolute(StringRef, uint8_t, uint8_t); @@ -860,16 +855,16 @@ template DefinedRegular *SymbolTable::addAbsolute(StringRef, uint8_t, uint8_t); -template Symbol * +template SymbolBody * SymbolTable::addLazyArchive(StringRef, ArchiveFile *, const object::Archive::Symbol); -template Symbol * +template SymbolBody * SymbolTable::addLazyArchive(StringRef, ArchiveFile *, const object::Archive::Symbol); -template Symbol * +template SymbolBody * SymbolTable::addLazyArchive(StringRef, ArchiveFile *, const object::Archive::Symbol); -template Symbol * +template SymbolBody * SymbolTable::addLazyArchive(StringRef, ArchiveFile *, const object::Archive::Symbol); Index: lld/ELF/Symbols.h =================================================================== --- lld/ELF/Symbols.h +++ lld/ELF/Symbols.h @@ -34,8 +34,6 @@ class OutputSection; template class SharedFile; -struct Symbol; - // The base class for real symbol classes. class SymbolBody { public: @@ -51,13 +49,51 @@ }; SymbolBody(Kind K) : SymbolKind(K) {} + Kind kind() const { return static_cast(SymbolKind); } - Symbol *symbol(); - const Symbol *symbol() const { - return const_cast(this)->symbol(); - } + // Symbol binding. This is not overwritten by replaceSymbol to track + // changes during resolution. In particular: + // - An undefined weak is still weak when it resolves to a shared library. + // - An undefined weak will not fetch archive members, but we have to + // remember it is weak. + uint8_t Binding; - Kind kind() const { return static_cast(SymbolKind); } + // Version definition index. + uint16_t VersionId; + + // Symbol visibility. This is the computed minimum visibility of all + // observed non-DSO symbols. + unsigned Visibility : 2; + + // True if the symbol was used for linking and thus need to be added to the + // output file's symbol table. This is true for all symbols except for + // unreferenced DSO symbols and bitcode symbols that are unreferenced except + // by other bitcode objects. + unsigned IsUsedInRegularObj : 1; + + // If this flag is true and the symbol has protected or default visibility, it + // will appear in .dynsym. This flag is set by interposable DSO symbols in + // executables, by most symbols in DSOs and executables built with + // --export-dynamic, and by dynamic lists. + unsigned ExportDynamic : 1; + + // False if LTO shouldn't inline whatever this symbol points to. If a symbol + // is overwritten after LTO, LTO shouldn't inline the symbol because it + // doesn't know the final contents of the symbol. + unsigned CanInline : 1; + + // True if this symbol is specified by --trace-symbol option. + unsigned Traced : 1; + + // This symbol version was found in a version script. + unsigned InVersionScript : 1; + + // The file from which this symbol was created. + InputFile *File = nullptr; + + bool includeInDynsym() const; + uint8_t computeBinding() const; + bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } bool isUndefined() const { return SymbolKind == UndefinedKind; } bool isDefined() const { return SymbolKind <= DefinedLast; } @@ -344,89 +380,47 @@ static DefinedRegular *MipsLocalGp; }; -// A real symbol object, SymbolBody, is usually stored within a Symbol. There's -// always one Symbol for each symbol name. The resolver updates the SymbolBody -// stored in the Body field of this object as it resolves symbols. Symbol also -// holds computed properties of symbol names. -struct Symbol { - // Symbol binding. This is on the Symbol to track changes during resolution. - // In particular: - // An undefined weak is still weak when it resolves to a shared library. - // An undefined weak will not fetch archive members, but we have to remember - // it is weak. - uint8_t Binding; - - // Version definition index. - uint16_t VersionId; - - // Symbol visibility. This is the computed minimum visibility of all - // observed non-DSO symbols. - unsigned Visibility : 2; - - // True if the symbol was used for linking and thus need to be added to the - // output file's symbol table. This is true for all symbols except for - // unreferenced DSO symbols and bitcode symbols that are unreferenced except - // by other bitcode objects. - unsigned IsUsedInRegularObj : 1; - - // If this flag is true and the symbol has protected or default visibility, it - // will appear in .dynsym. This flag is set by interposable DSO symbols in - // executables, by most symbols in DSOs and executables built with - // --export-dynamic, and by dynamic lists. - unsigned ExportDynamic : 1; - - // False if LTO shouldn't inline whatever this symbol points to. If a symbol - // is overwritten after LTO, LTO shouldn't inline the symbol because it - // doesn't know the final contents of the symbol. - unsigned CanInline : 1; - - // True if this symbol is specified by --trace-symbol option. - unsigned Traced : 1; - - // This symbol version was found in a version script. - unsigned InVersionScript : 1; - - // The file from which this symbol was created. - InputFile *File = nullptr; - - bool includeInDynsym() const; - uint8_t computeBinding() const; - bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } - - // This field is used to store the Symbol's SymbolBody. This instantiation of - // AlignedCharArrayUnion gives us a struct with a char array field that is - // large and aligned enough to store any derived class of SymbolBody. - llvm::AlignedCharArrayUnion - Body; - - SymbolBody *body() { return reinterpret_cast(Body.buffer); } - const SymbolBody *body() const { return const_cast(this)->body(); } +// A buffer class that is large enough to hold any SymbolBody-derived +// object. We allocate memory using this class and instantiate a symbol +// using the placement new. +union SymbolUnion { + alignas(DefinedRegular) char A[sizeof(DefinedRegular)]; + alignas(DefinedCommon) char B[sizeof(DefinedCommon)]; + alignas(Undefined) char C[sizeof(Undefined)]; + alignas(SharedSymbol) char D[sizeof(SharedSymbol)]; + alignas(LazyArchive) char E[sizeof(LazyArchive)]; + alignas(LazyObject) char F[sizeof(LazyObject)]; }; -void printTraceSymbol(Symbol *Sym); +void printTraceSymbol(SymbolBody *Sym); template -void replaceBody(Symbol *S, InputFile *File, ArgT &&... Arg) { - static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); - static_assert(alignof(T) <= alignof(decltype(S->Body)), - "Body not aligned enough"); +void replaceBody(SymbolBody *S, InputFile *File, ArgT &&... Arg) { + static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small"); + static_assert(alignof(T) <= alignof(SymbolUnion), + "SymbolUnion not aligned enough"); assert(static_cast(static_cast(nullptr)) == nullptr && "Not a SymbolBody"); + + SymbolBody Sym = *S; + + new (S) T(std::forward(Arg)...); S->File = File; - new (S->Body.buffer) T(std::forward(Arg)...); + + S->Binding = Sym.Binding; + S->VersionId = Sym.VersionId; + S->Visibility = Sym.Visibility; + S->IsUsedInRegularObj = Sym.IsUsedInRegularObj; + S->ExportDynamic = Sym.ExportDynamic; + S->CanInline = Sym.CanInline; + S->Traced = Sym.Traced; + S->InVersionScript = Sym.InVersionScript; // Print out a log message if --trace-symbol was specified. // This is for debugging. if (S->Traced) printTraceSymbol(S); } - -inline Symbol *SymbolBody::symbol() { - assert(!isLocal()); - return reinterpret_cast(reinterpret_cast(this) - - offsetof(Symbol, Body)); -} } // namespace elf std::string toString(const elf::SymbolBody &B); Index: lld/ELF/Symbols.cpp =================================================================== --- lld/ELF/Symbols.cpp +++ lld/ELF/Symbols.cpp @@ -113,7 +113,7 @@ return 0; case SymbolBody::LazyArchiveKind: case SymbolBody::LazyObjectKind: - assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"); + assert(Body.IsUsedInRegularObj && "lazy symbol reached writer"); return 0; } llvm_unreachable("invalid symbol kind"); @@ -122,7 +122,7 @@ // Returns true if this is a weak undefined symbol. bool SymbolBody::isUndefWeak() const { // See comment on Lazy in Symbols.h for the details. - return !isLocal() && symbol()->isWeak() && (isUndefined() || isLazy()); + return !isLocal() && isWeak() && (isUndefined() || isLazy()); } InputFile *SymbolBody::getFile() const { @@ -133,15 +133,24 @@ // SymbolBody, or having a special absolute section if needed. return Sec ? cast(Sec)->File : nullptr; } - return symbol()->File; + return File; } // Overwrites all attributes with Other's so that this symbol becomes // an alias to Other. This is useful for handling some options such as // --wrap. void SymbolBody::copyFrom(SymbolBody *Other) { - memcpy(symbol()->Body.buffer, Other->symbol()->Body.buffer, - sizeof(Symbol::Body)); + SymbolBody Sym = *this; + memcpy(this, Other, sizeof(SymbolUnion)); + + Binding = Sym.Binding; + VersionId = Sym.VersionId; + Visibility = Sym.Visibility; + IsUsedInRegularObj = Sym.IsUsedInRegularObj; + ExportDynamic = Sym.ExportDynamic; + CanInline = Sym.CanInline; + Traced = Sym.Traced; + InVersionScript = Sym.InVersionScript; } uint64_t SymbolBody::getVA(int64_t Addend) const { @@ -235,9 +244,9 @@ continue; if (IsDefault) - symbol()->VersionId = Ver.Id; + VersionId = Ver.Id; else - symbol()->VersionId = Ver.Id | VERSYM_HIDDEN; + VersionId = Ver.Id | VERSYM_HIDDEN; return; } @@ -287,44 +296,43 @@ InputFile *LazyObject::fetch() { return getFile()->fetch(); } -uint8_t Symbol::computeBinding() const { +uint8_t SymbolBody::computeBinding() const { if (Config->Relocatable) return Binding; if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) return STB_LOCAL; - if (VersionId == VER_NDX_LOCAL && body()->isInCurrentOutput()) + if (VersionId == VER_NDX_LOCAL && isInCurrentOutput()) return STB_LOCAL; if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE) return STB_GLOBAL; return Binding; } -bool Symbol::includeInDynsym() const { +bool SymbolBody::includeInDynsym() const { if (!Config->HasDynSymTab) return false; if (computeBinding() == STB_LOCAL) return false; - if (!body()->isInCurrentOutput()) + if (!isInCurrentOutput()) return true; return ExportDynamic; } // Print out a log message for --trace-symbol. -void elf::printTraceSymbol(Symbol *Sym) { - SymbolBody *B = Sym->body(); +void elf::printTraceSymbol(SymbolBody *Sym) { std::string S; - if (B->isUndefined()) + if (Sym->isUndefined()) S = ": reference to "; - else if (B->isCommon()) + else if (Sym->isCommon()) S = ": common definition of "; - else if (B->isLazy()) + else if (Sym->isLazy()) S = ": lazy definition of "; - else if (B->isShared()) + else if (Sym->isShared()) S = ": shared definition of "; else S = ": definition of "; - message(toString(Sym->File) + S + B->getName()); + message(toString(Sym->File) + S + Sym->getName()); } // Returns a symbol for an error message. Index: lld/ELF/SyntheticSections.cpp =================================================================== --- lld/ELF/SyntheticSections.cpp +++ lld/ELF/SyntheticSections.cpp @@ -66,8 +66,8 @@ // Create a .bss section for each common symbol and replace the common symbol // with a DefinedRegular symbol. template void elf::createCommonSections() { - for (Symbol *S : Symtab->getSymbols()) { - auto *Sym = dyn_cast(S->body()); + for (SymbolBody *S : Symtab->getSymbols()) { + auto *Sym = dyn_cast(S); if (!Sym) continue; @@ -1533,8 +1533,7 @@ // move all local symbols before global symbols. auto It = std::stable_partition( Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { - return S.Symbol->isLocal() || - S.Symbol->symbol()->computeBinding() == STB_LOCAL; + return S.Symbol->isLocal() || S.Symbol->computeBinding() == STB_LOCAL; }); size_t NumLocals = It - Symbols.begin(); getParent()->Info = NumLocals + 1; @@ -1591,8 +1590,8 @@ if (Body->isLocal()) { ESym->setBindingAndType(STB_LOCAL, Body->Type); } else { - ESym->setBindingAndType(Body->symbol()->computeBinding(), Body->Type); - ESym->setVisibility(Body->symbol()->Visibility); + ESym->setBindingAndType(Body->computeBinding(), Body->Type); + ESym->setVisibility(Body->Visibility); } ESym->st_name = Ent.StrTabOffset; @@ -2284,7 +2283,7 @@ template void VersionTableSection::writeTo(uint8_t *Buf) { auto *OutVersym = reinterpret_cast(Buf) + 1; for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { - OutVersym->vs_index = S.Symbol->symbol()->VersionId; + OutVersym->vs_index = S.Symbol->VersionId; ++OutVersym; } } @@ -2307,7 +2306,7 @@ void VersionNeedSection::addSymbol(SharedSymbol *SS) { auto *Ver = reinterpret_cast(SS->Verdef); if (!Ver) { - SS->symbol()->VersionId = VER_NDX_GLOBAL; + SS->VersionId = VER_NDX_GLOBAL; return; } @@ -2327,7 +2326,7 @@ Ver->getAux()->vda_name); NV.Index = NextIndex++; } - SS->symbol()->VersionId = NV.Index; + SS->VersionId = NV.Index; } template void VersionNeedSection::writeTo(uint8_t *Buf) { Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -433,7 +433,7 @@ } static bool includeInSymtab(const SymbolBody &B) { - if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj) + if (!B.isLocal() && !B.IsUsedInRegularObj) return false; if (auto *D = dyn_cast(&B)) { @@ -751,10 +751,10 @@ SymbolBody *S = Symtab->find(Name); if (!S || S->isInCurrentOutput()) return nullptr; - Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, - /*Size=*/0, Binding, Sec, - /*File=*/nullptr); - return cast(Sym->body()); + SymbolBody *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, + /*Size=*/0, Binding, Sec, + /*File=*/nullptr); + return cast(Sym); } // The beginning and the ending of .rel[a].plt section are marked @@ -1214,11 +1214,11 @@ static bool computeIsPreemptible(const SymbolBody &B) { assert(!B.isLocal()); // Only symbols that appear in dynsym can be preempted. - if (!B.symbol()->includeInDynsym()) + if (!B.includeInDynsym()) return false; // Only default visibility symbols can be preempted. - if (B.symbol()->Visibility != STV_DEFAULT) + if (B.Visibility != STV_DEFAULT) return false; // At this point copy relocations have not been created yet, so any @@ -1274,8 +1274,8 @@ applySynthetic({InX::EhFrame}, [](SyntheticSection *SS) { SS->finalizeContents(); }); - for (Symbol *S : Symtab->getSymbols()) - S->body()->IsPreemptible |= computeIsPreemptible(*S->body()); + for (SymbolBody *S : Symtab->getSymbols()) + S->IsPreemptible |= computeIsPreemptible(*S); // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. @@ -1289,18 +1289,16 @@ // Now that we have defined all possible global symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. - for (Symbol *S : Symtab->getSymbols()) { - SymbolBody *Body = S->body(); - - if (!includeInSymtab(*Body)) + for (SymbolBody *Sym : Symtab->getSymbols()) { + if (!includeInSymtab(*Sym)) continue; if (InX::SymTab) - InX::SymTab->addSymbol(Body); + InX::SymTab->addSymbol(Sym); - if (InX::DynSymTab && S->includeInDynsym()) { - InX::DynSymTab->addSymbol(Body); - if (auto *SS = dyn_cast(Body)) - if (cast>(S->File)->isNeeded()) + if (InX::DynSymTab && Sym->includeInDynsym()) { + InX::DynSymTab->addSymbol(Sym); + if (auto *SS = dyn_cast(Sym)) + if (cast>(Sym->File)->isNeeded()) In::VerNeed->addSymbol(SS); } } Index: lld/docs/NewLLD.rst =================================================================== --- lld/docs/NewLLD.rst +++ lld/docs/NewLLD.rst @@ -140,13 +140,13 @@ The linker can be understood as the interactions between them. Once you understand their functions, the code of the linker should look obvious to you. -* SymbolBody +* Symbol - SymbolBody is a class to represent symbols. + This class represents a symbol. They are created for symbols in object files or archive files. The linker creates linker-defined symbols as well. - There are basically three types of SymbolBodies: Defined, Undefined, or Lazy. + There are basically three types of Symbols: Defined, Undefined, or Lazy. - Defined symbols are for all symbols that are considered as "resolved", including real defined symbols, COMDAT symbols, common symbols, @@ -156,26 +156,17 @@ - Lazy symbols represent symbols we found in archive file headers which can turn into Defined if we read archieve members. -* Symbol + There's only one Symbol instance for each unique symbol name. This uniqueness + is guaranteed by the symbol table. As the resolver reads symbols from input + files, it replaces an existing Symbol with the "best" Symbol for its symbol + name using the placement new. - A Symbol is a container for a SymbolBody. There's only one Symbol for each - unique symbol name (this uniqueness is guaranteed by the symbol table). - Each global symbol has only one SymbolBody at any one time, which is - the SymbolBody stored within a memory region of the Symbol large enough - to store any SymbolBody. - - As the resolver reads symbols from input files, it replaces the Symbol's - SymbolBody with the "best" SymbolBody for its symbol name by constructing - the new SymbolBody in place on top of the existing SymbolBody. For example, - if the resolver is given a defined symbol, and the SymbolBody with its name - is undefined, it will construct a Defined SymbolBody over the Undefined - SymbolBody. - - This means that each SymbolBody pointer always points to the best SymbolBody, - and it is possible to get from a SymbolBody to a Symbol, or vice versa, - by adding or subtracting a fixed offset. This memory layout helps reduce - the cache miss rate through high locality and a small number of required - pointer indirections. + The above mechanism allows you to use pointers to Symbols as a very cheap way + to access name resolution results. Assume for example that you have a pointer + P to an undefined symbol before name resolution. If P is resolved to a defined + symbol by the resolver, P will "automatically" point to the defined symbol, + because the undefined symbol P pointed to will have been replaced by the + defined symbol in-place. * SymbolTable @@ -221,8 +212,7 @@ InputFile is a superclass of file readers. We have a different subclass for each input file type, such as regular object file, archive file, etc. - They are responsible for creating and owning SymbolBodies and - InputSections/Chunks. + They are responsible for creating and owning Symbols and InputSections/Chunks. * Writer