Index: ELF/Arch/MipsArchTree.cpp =================================================================== --- ELF/Arch/MipsArchTree.cpp +++ ELF/Arch/MipsArchTree.cpp @@ -283,7 +283,7 @@ template uint32_t elf::getMipsEFlags() { std::vector V; - for (elf::ObjectFile *F : Symtab::X->getObjectFiles()) + for (elf::ObjectFile *F : ObjectFile::Instances) V.push_back({F->getName(), F->getObj().getHeader()->e_flags}); if (V.empty()) return 0; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -80,6 +80,8 @@ Config = make(); Driver = make(); Script = make(); + SymbolTable Symtab; + elf::Symtab = &Symtab; Config->Argv = {Args.begin(), Args.end()}; Driver->main(Args, CanExitEarly); @@ -948,8 +950,6 @@ // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template void LinkerDriver::link(opt::InputArgList &Args) { - SymbolTable Symtab; - elf::Symtab::X = &Symtab; Target = getTarget(); Config->MaxPageSize = getMaxPageSize(Args); @@ -979,64 +979,64 @@ // Handle --trace-symbol. for (auto *Arg : Args.filtered(OPT_trace_symbol)) - Symtab.trace(Arg->getValue()); + Symtab->trace(Arg->getValue()); // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. for (InputFile *F : Files) - Symtab.addFile(F); + Symtab->addFile(F); // If an entry symbol is in a static archive, pull out that file now // to complete the symbol table. After this, no new names except a // few linker-synthesized ones will be added to the symbol table. - if (Symtab.find(Config->Entry)) - Symtab.addUndefined(Config->Entry); + if (Symtab->find(Config->Entry)) + Symtab->addUndefined(Config->Entry); // Return if there were name resolution errors. if (ErrorCount) return; // Handle the `--undefined ` options. - Symtab.scanUndefinedFlags(); + Symtab->scanUndefinedFlags(); // Handle undefined symbols in DSOs. - Symtab.scanShlibUndefined(); + Symtab->scanShlibUndefined(); // Handle the -exclude-libs option. if (Args.hasArg(OPT_exclude_libs)) excludeLibs(Args, Files); // Apply version scripts. - Symtab.scanVersionScript(); + Symtab->scanVersionScript(); // Create wrapped symbols for -wrap option. for (auto *Arg : Args.filtered(OPT_wrap)) - Symtab.addSymbolWrap(Arg->getValue()); + Symtab->addSymbolWrap(Arg->getValue()); // Create alias symbols for -defsym option. for (std::pair &Def : getDefsym(Args)) - Symtab.addSymbolAlias(Def.first, Def.second); + Symtab->addSymbolAlias(Def.first, Def.second); - Symtab.addCombinedLTOObject(); + Symtab->addCombinedLTOObject(); if (ErrorCount) return; // Some symbols (such as __ehdr_start) are defined lazily only when there // are undefined symbols for them, so we add these to trigger that logic. for (StringRef Sym : Script->Opt.ReferencedSymbols) - Symtab.addUndefined(Sym); + Symtab->addUndefined(Sym); // Apply symbol renames for -wrap and -defsym - Symtab.applySymbolRenames(); + Symtab->applySymbolRenames(); // Now that we have a complete list of input files. // Beyond this point, no new files are added. // Aggregate all input sections into one place. - for (elf::ObjectFile *F : Symtab.getObjectFiles()) + for (elf::ObjectFile *F : ObjectFile::Instances) for (InputSectionBase *S : F->getSections()) if (S && S != &InputSection::Discarded) InputSections.push_back(S); - for (BinaryFile *F : Symtab.getBinaryFiles()) + for (BinaryFile *F : BinaryFile::Instances) for (InputSectionBase *S : F->getSections()) InputSections.push_back(cast(S)); Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -155,6 +155,8 @@ return F->kind() == Base::ObjectKind; } + static std::vector *> Instances; + ArrayRef getSymbols(); ArrayRef getLocalSymbols(); @@ -216,6 +218,9 @@ llvm::once_flag InitDwarfLine; }; +template +std::vector *> ObjectFile::Instances; + // LazyObjectFile is analogous to ArchiveFile in the sense that // the file contains lazy symbols. The difference is that // LazyObjectFile wraps a single file instead of multiple files. @@ -277,6 +282,7 @@ void parse(llvm::DenseSet &ComdatGroups); ArrayRef getSymbols() { return Symbols; } std::unique_ptr Obj; + static std::vector Instances; private: std::vector Symbols; @@ -299,6 +305,8 @@ public: std::string SoName; + static std::vector *> Instances; + const Elf_Shdr *getSection(const Elf_Sym &Sym) const; llvm::ArrayRef getUndefinedSymbols() { return Undefs; } @@ -330,11 +338,15 @@ bool isNeeded() const { return !AsNeeded || IsUsed; } }; +template +std::vector *> SharedFile::Instances; + class BinaryFile : public InputFile { public: explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } template void parse(); + static std::vector Instances; }; InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -587,15 +587,15 @@ switch (Sym->st_shndx) { case SHN_UNDEF: - return elf::Symtab::X - ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, - /*CanOmitFromDynSym=*/false, this) + return elf::Symtab + ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, + /*CanOmitFromDynSym=*/false, this) ->body(); case SHN_COMMON: if (Value == 0 || Value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + Name + "' has invalid alignment: " + Twine(Value)); - return elf::Symtab::X + return elf::Symtab ->addCommon(Name, Size, Value, Binding, StOther, Type, this) ->body(); } @@ -607,12 +607,12 @@ case STB_WEAK: case STB_GNU_UNIQUE: if (Sec == &InputSection::Discarded) - return elf::Symtab::X - ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, - /*CanOmitFromDynSym=*/false, this) + return elf::Symtab + ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, + /*CanOmitFromDynSym=*/false, this) ->body(); - return elf::Symtab::X - ->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, this) + return elf::Symtab + ->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, this) ->body(); } } @@ -624,7 +624,7 @@ template void ArchiveFile::parse() { Symbols.reserve(File->getNumberOfSymbols()); for (const Archive::Symbol &Sym : File->symbols()) - Symbols.push_back(Symtab::X->addLazyArchive(this, Sym)); + Symbols.push_back(Symtab->addLazyArchive(this, Sym)); } // Returns a buffer pointing to a member file containing a given symbol. @@ -787,14 +787,14 @@ VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex]; if (!Hidden) - elf::Symtab::X->addShared(this, Name, Sym, V); + elf::Symtab->addShared(this, Name, Sym, V); // Also add the symbol with the versioned name to handle undefined symbols // with explicit versions. if (V) { StringRef VerName = this->StringTable.data() + V->getAux()->vda_name; Name = Saver.save(Name + "@" + VerName); - elf::Symtab::X->addShared(this, Name, Sym, V); + elf::Symtab->addShared(this, Name, Sym, V); } } } @@ -833,6 +833,8 @@ } } +std::vector BitcodeFile::Instances; + BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, uint64_t OffsetInArchive) : InputFile(BitcodeKind, MB) { @@ -881,22 +883,20 @@ int C = ObjSym.getComdatIndex(); if (C != -1 && !KeptComdats[C]) - return Symtab::X->addUndefined(NameRef, /*IsLocal=*/false, Binding, - Visibility, Type, CanOmitFromDynSym, - F); + return Symtab->addUndefined(NameRef, /*IsLocal=*/false, Binding, + Visibility, Type, CanOmitFromDynSym, F); if (ObjSym.isUndefined()) - return Symtab::X->addUndefined(NameRef, /*IsLocal=*/false, Binding, - Visibility, Type, CanOmitFromDynSym, - F); + return Symtab->addUndefined(NameRef, /*IsLocal=*/false, Binding, + Visibility, Type, CanOmitFromDynSym, F); if (ObjSym.isCommon()) - return Symtab::X->addCommon(NameRef, ObjSym.getCommonSize(), - ObjSym.getCommonAlignment(), Binding, - Visibility, STT_OBJECT, F); + return Symtab->addCommon(NameRef, ObjSym.getCommonSize(), + ObjSym.getCommonAlignment(), Binding, Visibility, + STT_OBJECT, F); - return Symtab::X->addBitcode(NameRef, Binding, Visibility, Type, - CanOmitFromDynSym, F); + return Symtab->addBitcode(NameRef, Binding, Visibility, Type, + CanOmitFromDynSym, F); } template @@ -929,6 +929,8 @@ return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; } +std::vector BinaryFile::Instances; + template void BinaryFile::parse() { ArrayRef Data = toArrayRef(MB.getBuffer()); auto *Section = @@ -944,15 +946,13 @@ if (!isalnum(S[I])) S[I] = '_'; - elf::Symtab::X->addRegular(Saver.save(S + "_start"), STV_DEFAULT, - STT_OBJECT, 0, 0, STB_GLOBAL, Section, - nullptr); - elf::Symtab::X->addRegular(Saver.save(S + "_end"), STV_DEFAULT, - STT_OBJECT, Data.size(), 0, STB_GLOBAL, - Section, nullptr); - elf::Symtab::X->addRegular(Saver.save(S + "_size"), STV_DEFAULT, - STT_OBJECT, Data.size(), 0, STB_GLOBAL, - nullptr, nullptr); + elf::Symtab->addRegular(Saver.save(S + "_start"), STV_DEFAULT, + STT_OBJECT, 0, 0, STB_GLOBAL, Section, nullptr); + elf::Symtab->addRegular(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT, + Data.size(), 0, STB_GLOBAL, Section, nullptr); + elf::Symtab->addRegular(Saver.save(S + "_size"), STV_DEFAULT, + STT_OBJECT, Data.size(), 0, STB_GLOBAL, nullptr, + nullptr); } static bool isBitcode(MemoryBufferRef MB) { @@ -1010,7 +1010,7 @@ template void LazyObjectFile::parse() { for (StringRef Sym : getSymbols()) - Symtab::X->addLazyObject(Sym, *this); + Symtab->addLazyObject(Sym, *this); } template std::vector LazyObjectFile::getElfSymbols() { Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -69,9 +69,9 @@ template static SymbolBody *addRegular(SymbolAssignment *Cmd) { Symbol *Sym; uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; - std::tie(Sym, std::ignore) = Symtab::X->insert( - Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, - /*File*/ nullptr); + std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, + /*CanOmitFromDynSym*/ false, + /*File*/ nullptr); Sym->Binding = STB_GLOBAL; ExprValue Value = Cmd->Expression(); SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; @@ -142,21 +142,6 @@ } } -static SymbolBody *findSymbol(StringRef S) { - switch (Config->EKind) { - case ELF32LEKind: - return Symtab::X->find(S); - case ELF32BEKind: - return Symtab::X->find(S); - case ELF64LEKind: - return Symtab::X->find(S); - case ELF64BEKind: - return Symtab::X->find(S); - default: - llvm_unreachable("unknown Config->EKind"); - } -} - static SymbolBody *addRegularSymbol(SymbolAssignment *Cmd) { switch (Config->EKind) { case ELF32LEKind: @@ -178,7 +163,7 @@ // If a symbol was in PROVIDE(), we need to define it only when // it is a referenced undefined symbol. - SymbolBody *B = findSymbol(Cmd->Name); + SymbolBody *B = Symtab->find(Cmd->Name); if (Cmd->Provide && (!B || B->isDefined())) return; @@ -1189,7 +1174,7 @@ ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { if (S == ".") return {CurAddressState->OutSec, Dot - CurAddressState->OutSec->Addr, Loc}; - if (SymbolBody *B = findSymbol(S)) { + if (SymbolBody *B = Symtab->find(S)) { if (auto *D = dyn_cast(B)) return {D->Section, D->Value, Loc}; if (auto *C = dyn_cast(B)) @@ -1199,7 +1184,7 @@ return 0; } -bool LinkerScript::isDefined(StringRef S) { return findSymbol(S) != nullptr; } +bool LinkerScript::isDefined(StringRef S) { return Symtab->find(S) != nullptr; } static const size_t NoPhdr = -1; Index: ELF/MapFile.cpp =================================================================== --- ELF/MapFile.cpp +++ ELF/MapFile.cpp @@ -51,7 +51,7 @@ // Returns a list of all symbols that we want to print out. template std::vector getSymbols() { std::vector V; - for (elf::ObjectFile *File : Symtab::X->getObjectFiles()) + for (elf::ObjectFile *File : ObjectFile::Instances) for (SymbolBody *B : File->getSymbols()) if (B->File == File && !B->isSection()) if (auto *Sym = dyn_cast(B)) Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -225,17 +225,17 @@ }; // Add GC root symbols. - MarkSymbol(Symtab::X->find(Config->Entry)); - MarkSymbol(Symtab::X->find(Config->Init)); - MarkSymbol(Symtab::X->find(Config->Fini)); + MarkSymbol(Symtab->find(Config->Entry)); + MarkSymbol(Symtab->find(Config->Init)); + MarkSymbol(Symtab->find(Config->Fini)); for (StringRef S : Config->Undefined) - MarkSymbol(Symtab::X->find(S)); + MarkSymbol(Symtab->find(S)); for (StringRef S : Script->Opt.ReferencedSymbols) - MarkSymbol(Symtab::X->find(S)); + MarkSymbol(Symtab->find(S)); // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. - for (const Symbol *S : Symtab::X->getSymbols()) + for (const Symbol *S : Symtab->getSymbols()) if (S->includeInDynsym()) MarkSymbol(S->body()); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -461,7 +461,7 @@ if (S.st_shndx != Shndx || S.st_value != Value) continue; StringRef Name = check(S.getName(File->getStringTable())); - SymbolBody *Sym = Symtab::X->find(Name); + SymbolBody *Sym = Symtab->find(Name); if (auto *Alias = dyn_cast_or_null(Sym)) Ret.push_back(Alias); } Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -33,41 +33,43 @@ // to replace the lazy symbol. The logic is implemented in the // add*() functions, which are called by input files as they are parsed. There // is one add* function per symbol type. -template class SymbolTable { - typedef typename ELFT::Sym Elf_Sym; - +class SymbolTable { public: - void addFile(InputFile *File); - void addCombinedLTOObject(); - void addSymbolAlias(StringRef Alias, StringRef Name); - void addSymbolWrap(StringRef Name); + template void addFile(InputFile *File); + template void addCombinedLTOObject(); + template void addSymbolAlias(StringRef Alias, StringRef Name); + template void addSymbolWrap(StringRef Name); void applySymbolRenames(); ArrayRef getSymbols() const { return SymVector; } - ArrayRef *> getObjectFiles() const { return ObjectFiles; } - ArrayRef getBinaryFiles() const { return BinaryFiles; } - ArrayRef *> getSharedFiles() const { return SharedFiles; } + template DefinedRegular *addAbsolute(StringRef Name, uint8_t Visibility = llvm::ELF::STV_HIDDEN, uint8_t Binding = llvm::ELF::STB_GLOBAL); + template DefinedRegular *addIgnored(StringRef Name, uint8_t Visibility = llvm::ELF::STV_HIDDEN); - Symbol *addUndefined(StringRef Name); + template Symbol *addUndefined(StringRef Name); + template Symbol *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); - void addShared(SharedFile *F, StringRef Name, const Elf_Sym &Sym, + template + void addShared(SharedFile *F, StringRef Name, + const typename ELFT::Sym &Sym, const typename ELFT::Verdef *Verdef); + template Symbol *addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S); - void addLazyObject(StringRef Name, LazyObjectFile &Obj); + template void addLazyObject(StringRef Name, LazyObjectFile &Obj); + Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File); @@ -80,8 +82,8 @@ uint8_t Visibility, bool CanOmitFromDynSym, InputFile *File); - void scanUndefinedFlags(); - void scanShlibUndefined(); + template void scanUndefinedFlags(); + template void scanShlibUndefined(); void scanVersionScript(); SymbolBody *find(StringRef Name); @@ -120,11 +122,6 @@ // is used to uniquify them. llvm::DenseSet ComdatGroups; - std::vector *> ObjectFiles; - std::vector *> SharedFiles; - std::vector BitcodeFiles; - std::vector BinaryFiles; - // Set of .so files to not link the same shared object file more than once. llvm::DenseSet SoNames; @@ -138,9 +135,7 @@ std::unique_ptr LTO; }; -template struct Symtab { static SymbolTable *X; }; -template SymbolTable *Symtab::X; - +extern SymbolTable *Symtab; } // namespace elf } // namespace lld Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -29,6 +29,8 @@ using namespace lld; using namespace lld::elf; +SymbolTable *elf::Symtab; + // All input object files must be for the same architecture // (e.g. it does not make sense to link x86 object files with // MIPS object files.) This function checks for that error. @@ -51,7 +53,7 @@ } // Add symbols in File to the symbol table. -template void SymbolTable::addFile(InputFile *File) { +template void SymbolTable::addFile(InputFile *File) { if (!Config->FirstElf && isa>(File)) Config->FirstElf = File; @@ -60,7 +62,7 @@ // Binary file if (auto *F = dyn_cast(File)) { - BinaryFiles.push_back(F); + BinaryFile::Instances.push_back(F); F->parse(); return; } @@ -86,21 +88,21 @@ F->parseSoName(); if (ErrorCount || !SoNames.insert(F->SoName).second) return; - SharedFiles.push_back(F); + SharedFile::Instances.push_back(F); F->parseRest(); return; } // LLVM bitcode file if (auto *F = dyn_cast(File)) { - BitcodeFiles.push_back(F); + BitcodeFile::Instances.push_back(F); F->parse(ComdatGroups); return; } // Regular object file auto *F = cast>(File); - ObjectFiles.push_back(F); + ObjectFile::Instances.push_back(F); F->parse(ComdatGroups); } @@ -111,58 +113,56 @@ // using LLVM functions and replaces bitcode symbols with the results. // Because all bitcode files that consist of a program are passed // to the compiler at once, it can do whole-program optimization. -template void SymbolTable::addCombinedLTOObject() { - if (BitcodeFiles.empty()) +template void SymbolTable::addCombinedLTOObject() { + if (BitcodeFile::Instances.empty()) return; // Compile bitcode files and replace bitcode symbols. LTO.reset(new BitcodeCompiler); - for (BitcodeFile *F : BitcodeFiles) + for (BitcodeFile *F : BitcodeFile::Instances) LTO->add(*F); for (InputFile *File : LTO->compile()) { ObjectFile *Obj = cast>(File); DenseSet DummyGroups; Obj->parse(DummyGroups); - ObjectFiles.push_back(Obj); + ObjectFile::Instances.push_back(Obj); } } template -DefinedRegular *SymbolTable::addAbsolute(StringRef Name, - uint8_t Visibility, - uint8_t Binding) { - Symbol *Sym = - addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); +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()); } // Add Name as an "ignored" symbol. An ignored symbol is a regular // linker-synthesized defined symbol, but is only defined if needed. template -DefinedRegular *SymbolTable::addIgnored(StringRef Name, - uint8_t Visibility) { +DefinedRegular *SymbolTable::addIgnored(StringRef Name, uint8_t Visibility) { SymbolBody *S = find(Name); if (!S || S->isInCurrentDSO()) return nullptr; - return addAbsolute(Name, Visibility); + return addAbsolute(Name, Visibility); } // Set a flag for --trace-symbol so that we can print out a log message // if a new symbol with the same name is inserted into the symbol table. -template void SymbolTable::trace(StringRef Name) { +void SymbolTable::trace(StringRef Name) { Symtab.insert({CachedHashStringRef(Name), {-1, true}}); } // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. // Used to implement --wrap. -template void SymbolTable::addSymbolWrap(StringRef Name) { +template void SymbolTable::addSymbolWrap(StringRef Name) { SymbolBody *B = find(Name); if (!B) return; Symbol *Sym = B->symbol(); - Symbol *Real = addUndefined(Saver.save("__real_" + Name)); - Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); + Symbol *Real = addUndefined(Saver.save("__real_" + Name)); + Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); // Tell LTO not to eliminate this symbol Wrap->IsUsedInRegularObj = true; @@ -173,14 +173,14 @@ // Creates alias for symbol. Used to implement --defsym=ALIAS=SYM. template -void SymbolTable::addSymbolAlias(StringRef Alias, StringRef Name) { +void SymbolTable::addSymbolAlias(StringRef Alias, StringRef Name) { SymbolBody *B = find(Name); if (!B) { error("-defsym: undefined symbol: " + Name); return; } Symbol *Sym = B->symbol(); - Symbol *AliasSym = addUndefined(Alias); + Symbol *AliasSym = addUndefined(Alias); // Tell LTO not to eliminate this symbol Sym->IsUsedInRegularObj = true; @@ -191,7 +191,7 @@ // before LTO in addSymbolWrap() and addSymbolAlias() to have a chance to inform // LTO (if LTO is running) not to include these symbols in IPO. Now that the // symbols are finalized, we can perform the replacement. -template void SymbolTable::applySymbolRenames() { +void SymbolTable::applySymbolRenames() { for (auto &KV : Config->RenamedSymbols) { Symbol *Dst = KV.first; Symbol *Src = KV.second.Target; @@ -209,8 +209,7 @@ } // Find an existing symbol or create and insert a new one. -template -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 . size_t Pos = Name.find("@@"); @@ -246,10 +245,10 @@ // Find an existing symbol or create and insert a new one, then apply the given // attributes. -template -std::pair -SymbolTable::insert(StringRef Name, uint8_t Type, uint8_t Visibility, - bool CanOmitFromDynSym, InputFile *File) { +std::pair SymbolTable::insert(StringRef Name, uint8_t Type, + uint8_t Visibility, + bool CanOmitFromDynSym, + InputFile *File) { bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind; Symbol *S; bool WasInserted; @@ -274,19 +273,18 @@ return {S, WasInserted}; } -template Symbol *SymbolTable::addUndefined(StringRef Name) { - return addUndefined(Name, /*IsLocal=*/false, STB_GLOBAL, STV_DEFAULT, - /*Type*/ 0, - /*CanOmitFromDynSym*/ false, /*File*/ nullptr); +template Symbol *SymbolTable::addUndefined(StringRef Name) { + return addUndefined(Name, /*IsLocal=*/false, STB_GLOBAL, STV_DEFAULT, + /*Type*/ 0, + /*CanOmitFromDynSym*/ false, /*File*/ nullptr); } 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 *SymbolTable::addUndefined(StringRef Name, bool IsLocal, uint8_t Binding, + uint8_t StOther, uint8_t Type, + bool CanOmitFromDynSym, InputFile *File) { Symbol *S; bool WasInserted; uint8_t Visibility = getVisibility(StOther); @@ -313,7 +311,7 @@ if (S->isWeak()) L->Type = Type; else if (InputFile *F = L->fetch()) - addFile(F); + addFile(F); } return S; } @@ -380,11 +378,9 @@ return 0; } -template -Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, - uint32_t Alignment, uint8_t Binding, - uint8_t StOther, uint8_t Type, - InputFile *File) { +Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment, + uint8_t Binding, uint8_t StOther, uint8_t Type, + InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), @@ -457,10 +453,9 @@ } 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 *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; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), @@ -477,9 +472,9 @@ } template -void SymbolTable::addShared(SharedFile *File, StringRef Name, - const Elf_Sym &Sym, - const typename ELFT::Verdef *Verdef) { +void SymbolTable::addShared(SharedFile *File, StringRef Name, + const typename ELFT::Sym &Sym, + const typename ELFT::Verdef *Verdef) { // 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. @@ -503,10 +498,9 @@ } } -template -Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, - uint8_t StOther, uint8_t Type, - bool CanOmitFromDynSym, BitcodeFile *F) { +Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, + uint8_t StOther, uint8_t Type, + bool CanOmitFromDynSym, BitcodeFile *F) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = @@ -521,7 +515,7 @@ return S; } -template SymbolBody *SymbolTable::find(StringRef Name) { +SymbolBody *SymbolTable::find(StringRef Name) { auto It = Symtab.find(CachedHashStringRef(Name)); if (It == Symtab.end()) return nullptr; @@ -531,8 +525,7 @@ return SymVector[V.Idx]->body(); } -template -SymbolBody *SymbolTable::findInCurrentDSO(StringRef Name) { +SymbolBody *SymbolTable::findInCurrentDSO(StringRef Name) { if (SymbolBody *S = find(Name)) if (S->isInCurrentDSO()) return S; @@ -540,8 +533,8 @@ } template -Symbol *SymbolTable::addLazyArchive(ArchiveFile *F, - const object::Archive::Symbol Sym) { +Symbol *SymbolTable::addLazyArchive(ArchiveFile *F, + const object::Archive::Symbol Sym) { Symbol *S; bool WasInserted; StringRef Name = Sym.getName(); @@ -566,12 +559,12 @@ } std::pair MBInfo = F->getMember(&Sym); if (!MBInfo.first.getBuffer().empty()) - addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second)); + addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second)); return S; } template -void SymbolTable::addLazyObject(StringRef Name, LazyObjectFile &Obj) { +void SymbolTable::addLazyObject(StringRef Name, LazyObjectFile &Obj) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); @@ -586,15 +579,15 @@ if (S->isWeak()) replaceBody(S, Name, Obj, S->body()->Type); else if (InputFile *F = Obj.fetch()) - addFile(F); + addFile(F); } // Process undefined (-u) flags by loading lazy symbols named by those flags. -template void SymbolTable::scanUndefinedFlags() { +template void SymbolTable::scanUndefinedFlags() { for (StringRef S : Config->Undefined) if (auto *L = dyn_cast_or_null(find(S))) if (InputFile *File = L->fetch()) - addFile(File); + addFile(File); } // This function takes care of the case in which shared libraries depend on @@ -604,8 +597,8 @@ // We need to put such symbols to the main program's .dynsym so that // shared libraries can find them. // Except this, we ignore undefined symbols in DSOs. -template void SymbolTable::scanShlibUndefined() { - for (SharedFile *File : SharedFiles) { +template void SymbolTable::scanShlibUndefined() { + for (SharedFile *File : SharedFile::Instances) { for (StringRef U : File->getUndefinedSymbols()) { SymbolBody *Sym = find(U); if (!Sym || !Sym->isDefined()) @@ -634,8 +627,7 @@ // other than trying to match a pattern against all demangled symbols. // So, if "extern C++" feature is used, we need to demangle all known // symbols. -template -StringMap> &SymbolTable::getDemangledSyms() { +StringMap> &SymbolTable::getDemangledSyms() { if (!DemangledSyms) { DemangledSyms.emplace(); for (Symbol *Sym : SymVector) { @@ -651,8 +643,7 @@ return *DemangledSyms; } -template -std::vector SymbolTable::findByVersion(SymbolVersion Ver) { +std::vector SymbolTable::findByVersion(SymbolVersion Ver) { if (Ver.IsExternCpp) return getDemangledSyms().lookup(Ver.Name); if (SymbolBody *B = find(Ver.Name)) @@ -661,9 +652,7 @@ return {}; } -template -std::vector -SymbolTable::findAllByVersion(SymbolVersion Ver) { +std::vector SymbolTable::findAllByVersion(SymbolVersion Ver) { std::vector Res; StringMatcher M(Ver.Name); @@ -685,7 +674,7 @@ // If there's only one anonymous version definition in a version // script file, the script does not actually define any symbol version, // but just specifies symbols visibilities. -template void SymbolTable::handleAnonymousVersion() { +void SymbolTable::handleAnonymousVersion() { for (SymbolVersion &Ver : Config->VersionScriptGlobals) assignExactVersion(Ver, VER_NDX_GLOBAL, "global"); for (SymbolVersion &Ver : Config->VersionScriptGlobals) @@ -698,10 +687,8 @@ // Set symbol versions to symbols. This function handles patterns // containing no wildcard characters. -template -void SymbolTable::assignExactVersion(SymbolVersion Ver, - uint16_t VersionId, - StringRef VersionName) { +void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId, + StringRef VersionName) { if (Ver.HasWildcard) return; @@ -730,9 +717,7 @@ } } -template -void SymbolTable::assignWildcardVersion(SymbolVersion Ver, - uint16_t VersionId) { +void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) { if (!Ver.HasWildcard) return; @@ -746,7 +731,7 @@ // This function processes version scripts by updating VersionId // member of symbols. -template void SymbolTable::scanVersionScript() { +void SymbolTable::scanVersionScript() { // Handle edge cases first. handleAnonymousVersion(); @@ -775,7 +760,90 @@ Sym->body()->parseSymbolVersion(); } -template class elf::SymbolTable; -template class elf::SymbolTable; -template class elf::SymbolTable; -template class elf::SymbolTable; +template void SymbolTable::addSymbolWrap(StringRef); +template void SymbolTable::addSymbolWrap(StringRef); +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 void SymbolTable::addSymbolAlias(StringRef, StringRef); +template void SymbolTable::addSymbolAlias(StringRef, StringRef); +template void SymbolTable::addSymbolAlias(StringRef, StringRef); +template void SymbolTable::addSymbolAlias(StringRef, StringRef); + +template void SymbolTable::addCombinedLTOObject(); +template void SymbolTable::addCombinedLTOObject(); +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 DefinedRegular *SymbolTable::addAbsolute(StringRef, uint8_t, + uint8_t); +template DefinedRegular *SymbolTable::addAbsolute(StringRef, uint8_t, + uint8_t); +template DefinedRegular *SymbolTable::addAbsolute(StringRef, uint8_t, + uint8_t); +template DefinedRegular *SymbolTable::addAbsolute(StringRef, uint8_t, + uint8_t); + +template DefinedRegular *SymbolTable::addIgnored(StringRef, uint8_t); +template DefinedRegular *SymbolTable::addIgnored(StringRef, uint8_t); +template DefinedRegular *SymbolTable::addIgnored(StringRef, uint8_t); +template DefinedRegular *SymbolTable::addIgnored(StringRef, uint8_t); + +template Symbol * +SymbolTable::addLazyArchive(ArchiveFile *, + const object::Archive::Symbol); +template Symbol * +SymbolTable::addLazyArchive(ArchiveFile *, + const object::Archive::Symbol); +template Symbol * +SymbolTable::addLazyArchive(ArchiveFile *, + const object::Archive::Symbol); +template Symbol * +SymbolTable::addLazyArchive(ArchiveFile *, + const object::Archive::Symbol); + +template void SymbolTable::addLazyObject(StringRef, LazyObjectFile &); +template void SymbolTable::addLazyObject(StringRef, LazyObjectFile &); +template void SymbolTable::addLazyObject(StringRef, LazyObjectFile &); +template void SymbolTable::addLazyObject(StringRef, LazyObjectFile &); + +template void SymbolTable::addShared(SharedFile *, StringRef, + const typename ELF32LE::Sym &, + const typename ELF32LE::Verdef *); +template void SymbolTable::addShared(SharedFile *, StringRef, + const typename ELF32BE::Sym &, + const typename ELF32BE::Verdef *); +template void SymbolTable::addShared(SharedFile *, StringRef, + const typename ELF64LE::Sym &, + const typename ELF64LE::Verdef *); +template void SymbolTable::addShared(SharedFile *, StringRef, + const typename ELF64BE::Sym &, + const typename ELF64BE::Verdef *); + +template void SymbolTable::scanUndefinedFlags(); +template void SymbolTable::scanUndefinedFlags(); +template void SymbolTable::scanUndefinedFlags(); +template void SymbolTable::scanUndefinedFlags(); + +template void SymbolTable::scanShlibUndefined(); +template void SymbolTable::scanShlibUndefined(); +template void SymbolTable::scanShlibUndefined(); +template void SymbolTable::scanShlibUndefined(); Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -56,7 +56,7 @@ template static std::vector getCommonSymbols() { std::vector V; - for (Symbol *S : Symtab::X->getSymbols()) + for (Symbol *S : Symtab->getSymbols()) if (auto *B = dyn_cast(S->body())) V.push_back(B); return V; @@ -1027,7 +1027,7 @@ if (!Config->Rpath.empty()) add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, InX::DynStrTab->addString(Config->Rpath)}); - for (SharedFile *F : Symtab::X->getSharedFiles()) + for (SharedFile *F : SharedFile::Instances) if (F->isNeeded()) add({DT_NEEDED, InX::DynStrTab->addString(F->SoName)}); if (!Config->SoName.empty()) @@ -1132,9 +1132,9 @@ add({DT_FINI_ARRAYSZ, Out::FiniArray, Entry::SecSize}); } - if (SymbolBody *B = Symtab::X->findInCurrentDSO(Config->Init)) + if (SymbolBody *B = Symtab->findInCurrentDSO(Config->Init)) add({DT_INIT, B}); - if (SymbolBody *B = Symtab::X->findInCurrentDSO(Config->Fini)) + if (SymbolBody *B = Symtab->findInCurrentDSO(Config->Fini)) add({DT_FINI, B}); bool HasVerNeed = In::VerNeed->getNeedNum() != 0; Index: ELF/Writer.h =================================================================== --- ELF/Writer.h +++ ELF/Writer.h @@ -21,7 +21,7 @@ class OutputSection; class InputSectionBase; template class ObjectFile; -template class SymbolTable; +class SymbolTable; template void writeResult(); template void markLive(); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -118,7 +118,7 @@ } template static bool needsInterpSection() { - return !Symtab::X->getSharedFiles().empty() && + return !SharedFile::Instances.empty() && !Config->DynamicLinker.empty() && !Script->ignoreInterpSection(); } @@ -318,8 +318,8 @@ Add(InX::BssRelRo); // Add MIPS-specific sections. - bool HasDynSymTab = !Symtab::X->getSharedFiles().empty() || - Config->Pic || Config->ExportDynamic; + bool HasDynSymTab = !SharedFile::Instances.empty() || Config->Pic || + Config->ExportDynamic; if (Config->EMachine == EM_MIPS) { if (!Config->Shared && HasDynSymTab) { InX::MipsRldMap = make(); @@ -471,7 +471,7 @@ template void Writer::copyLocalSymbols() { if (!InX::SymTab) return; - for (elf::ObjectFile *F : Symtab::X->getObjectFiles()) { + for (elf::ObjectFile *F : ObjectFile::Instances) { for (SymbolBody *B : F->getLocalSymbols()) { if (!B->IsLocal) fatal(toString(F) + @@ -760,16 +760,16 @@ uint8_t Binding = STB_WEAK) { // The linker generated symbols are added as STB_WEAK to allow user defined // ones to override them. - return Symtab::X->addRegular(Name, StOther, STT_NOTYPE, Value, - /*Size=*/0, Binding, Sec, - /*File=*/nullptr); + return Symtab->addRegular(Name, StOther, STT_NOTYPE, Value, + /*Size=*/0, Binding, Sec, + /*File=*/nullptr); } template static DefinedRegular * addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { - SymbolBody *S = Symtab::X->find(Name); + SymbolBody *S = Symtab->find(Name); if (!S) return nullptr; if (S->isInCurrentDSO()) @@ -803,21 +803,21 @@ // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = Symtab::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); + ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. - if (Symtab::X->find("_gp_disp")) + if (Symtab->find("_gp_disp")) ElfSym::MipsGpDisp = - Symtab::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL); + Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op // in case of using -mno-shared option. // https://sourceware.org/ml/binutils/2004-12/msg00094.html - if (Symtab::X->find("__gnu_local_gp")) + if (Symtab->find("__gnu_local_gp")) ElfSym::MipsLocalGp = - Symtab::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); + Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to @@ -833,7 +833,7 @@ // __tls_get_addr, so it's not defined anywhere. Create a hidden definition // to avoid the undefined symbol error. if (!InX::DynSymTab) - Symtab::X->addIgnored("__tls_get_addr"); + Symtab->addIgnored("__tls_get_addr"); // __ehdr_start is the location of ELF file headers. Note that we define // this symbol unconditionally even when using a linker script, which @@ -893,7 +893,7 @@ // Build a map from sections to their priorities. DenseMap SectionOrder; - for (elf::ObjectFile *File : Symtab::X->getObjectFiles()) { + for (elf::ObjectFile *File : ObjectFile::Instances) { for (SymbolBody *Body : File->getSymbols()) { auto *D = dyn_cast(Body); if (!D || !D->Section) @@ -1224,7 +1224,7 @@ // 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::X->getSymbols()) { + for (Symbol *S : Symtab->getSymbols()) { SymbolBody *Body = S->body(); if (!includeInSymtab(*Body)) @@ -1689,7 +1689,7 @@ template uint64_t Writer::getEntryAddr() { // Case 1, 2 or 3. As a special case, if the symbol is actually // a number, we'll use that number as an address. - if (SymbolBody *B = Symtab::X->find(Config->Entry)) + if (SymbolBody *B = Symtab->find(Config->Entry)) return B->getVA(); uint64_t Addr; if (to_integer(Config->Entry, Addr))