Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -1111,8 +1111,8 @@ if (auto *DS = dyn_cast(Sym)) return {DS->Section, false, DS->Value, Loc}; if (auto *SS = dyn_cast(Sym)) - if (!ErrorOnMissingSection || SS->CopyRelSec) - return {SS->CopyRelSec, false, 0, Loc}; + if (!ErrorOnMissingSection) + return {nullptr, false, 0, Loc}; } error(Loc + ": symbol not found: " + Name); Index: ELF/MapFile.cpp =================================================================== --- ELF/MapFile.cpp +++ ELF/MapFile.cpp @@ -38,7 +38,7 @@ using namespace lld; using namespace lld::elf; -typedef DenseMap> SymbolMapTy; +typedef DenseMap> SymbolMapTy; static const std::string Indent8 = " "; // 8 spaces static const std::string Indent16 = " "; // 16 spaces @@ -53,44 +53,29 @@ } // Returns a list of all symbols that we want to print out. -static std::vector getSymbols() { - std::vector V; - for (InputFile *File : ObjectFiles) { - for (Symbol *B : File->getSymbols()) { - if (auto *SS = dyn_cast(B)) - if (SS->CopyRelSec || SS->NeedsPltAddr) - V.push_back(SS); +static std::vector getSymbols() { + std::vector V; + for (InputFile *File : ObjectFiles) + for (Symbol *B : File->getSymbols()) if (auto *DR = dyn_cast(B)) - if (DR->File == File && !DR->isSection() && DR->Section && - DR->Section->Live) + if (!DR->isSection() && DR->Section && DR->Section->Live && + (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss)) V.push_back(DR); - } - } return V; } // Returns a map from sections to their symbols. -static SymbolMapTy getSectionSyms(ArrayRef Syms) { +static SymbolMapTy getSectionSyms(ArrayRef Syms) { SymbolMapTy Ret; - for (Symbol *S : Syms) { - if (auto *DR = dyn_cast(S)) { - Ret[DR->Section].push_back(S); - continue; - } - - SharedSymbol *SS = cast(S); - if (SS->CopyRelSec) - Ret[SS->CopyRelSec].push_back(S); - else - Ret[InX::Plt].push_back(S); - } + for (Defined *DR : Syms) + Ret[DR->Section].push_back(DR); // Sort symbols by address. We want to print out symbols in the // order in the output file rather than the order they appeared // in the input files. for (auto &It : Ret) { - SmallVectorImpl &V = It.second; - std::stable_sort(V.begin(), V.end(), [](Symbol *A, Symbol *B) { + SmallVectorImpl &V = It.second; + std::stable_sort(V.begin(), V.end(), [](Defined *A, Defined *B) { return A->getVA() < B->getVA(); }); } @@ -101,7 +86,7 @@ // Demangling symbols (which is what toString() does) is slow, so // we do that in batch using parallel-for. static DenseMap -getSymbolStrings(ArrayRef Syms) { +getSymbolStrings(ArrayRef Syms) { std::vector Str(Syms.size()); parallelForEachN(0, Syms.size(), [&](size_t I) { raw_string_ostream OS(Str[I]); @@ -169,7 +154,7 @@ } // Collect symbol info that we want to print out. - std::vector Syms = getSymbols(); + std::vector Syms = getSymbols(); SymbolMapTy SectionSyms = getSectionSyms(Syms); DenseMap SymStr = getSymbolStrings(Syms); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -461,6 +461,21 @@ return Ret; } +static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value, + uint64_t Size) { + Symbol Old = Sym; + replaceSymbol(&Sym, Sym.File, Sym.getName(), Sym.Binding, + Sym.StOther, Sym.Type, Value, Size, Sec); + Sym.PltIndex = Old.PltIndex; + Sym.GotIndex = Old.GotIndex; + Sym.VerdefIndex = Old.VerdefIndex; + Sym.IsInGlobalMipsGot = Old.IsInGlobalMipsGot; + Sym.IsPreemptible = true; + Sym.ExportDynamic = true; + Sym.IsUsedInRegularObj = true; + Sym.Used = true; +} + // Reserve space in .bss or .bss.rel.ro for copy relocation. // // The copy relocation is pretty much a hack. If you use a copy relocation @@ -522,11 +537,8 @@ // Look through the DSO's dynamic symbol table for aliases and create a // dynamic symbol for each one. This causes the copy relocation to correctly // interpose any aliases. - for (SharedSymbol *Sym : getSymbolsAt(SS)) { - Sym->CopyRelSec = Sec; - Sym->IsUsedInRegularObj = true; - Sym->Used = true; - } + for (SharedSymbol *Sym : getSymbolsAt(SS)) + replaceWithDefined(*Sym, Sec, 0, Sym->Size); InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS); } @@ -828,10 +840,8 @@ } // If the symbol is undefined we already reported any relevant errors. - if (!Sym.isShared()) { - assert(Sym.isUndefined()); + if (Sym.isUndefined()) return; - } if (!canDefineSymbolInExecutable(Sym)) { error("cannot preempt symbol: " + toString(Sym) + @@ -841,14 +851,13 @@ if (Sym.isObject()) { // Produce a copy relocation. - auto &SS = cast(Sym); - if (!SS.CopyRelSec) { + if (auto *SS = dyn_cast(&Sym)) { if (!Config->ZCopyreloc) error("unresolvable relocation " + toString(Type) + - " against symbol '" + toString(SS) + + " against symbol '" + toString(*SS) + "'; recompile with -fPIC or remove '-z nocopyreloc'" + getLocation(Sec, Sym, Offset)); - addCopyRelSymbol(SS); + addCopyRelSymbol(*SS); } Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); return; @@ -889,8 +898,10 @@ if (!Sym.isInPlt()) addPltEntry(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel, Sym); + if (!Sym.isDefined()) + replaceWithDefined(Sym, InX::Plt, Sym.getPltOffset(), 0); Sym.NeedsPltAddr = true; - Sec.Relocations.push_back({toPlt(Expr), Type, Offset, Addend, &Sym}); + Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); return; } Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -72,6 +72,9 @@ uint32_t PltIndex = -1; uint32_t GlobalDynIndex = -1; + // This field is a index to the symbol's version definition. + uint32_t VerdefIndex = -1; + // Version definition index. uint16_t VersionId; @@ -146,6 +149,7 @@ uint64_t getGotPltOffset() const; uint64_t getGotPltVA() const; uint64_t getPltVA() const; + uint64_t getPltOffset() const; uint64_t getSize() const; OutputSection *getOutputSection() const; @@ -225,8 +229,9 @@ SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, uint32_t Alignment, uint32_t VerdefIndex) - : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value), - Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) { + : Symbol(SharedKind, &File, Name, Binding, StOther, Type), + Alignment(Alignment), Value(Value), Size(Size) { + this->VerdefIndex = VerdefIndex; // GNU ifunc is a mechanism to allow user-supplied functions to // resolve PLT slot values at load-time. This is contrary to the // regular symbol resolution scheme in which symbols are resolved just @@ -251,16 +256,10 @@ return *cast>(File); } - // If not null, there is a copy relocation to this section. - InputSection *CopyRelSec = nullptr; + uint32_t Alignment; uint64_t Value; // st_value uint64_t Size; // st_size - - // This field is a index to the symbol's version definition. - uint32_t VerdefIndex; - - uint32_t Alignment; }; // LazyArchive and LazyObject represent a symbols that is not yet in the link, Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -97,14 +97,7 @@ } return VA; } - case Symbol::SharedKind: { - auto &SS = cast(Sym); - if (SS.CopyRelSec) - return SS.CopyRelSec->getVA(0); - if (SS.NeedsPltAddr) - return Sym.getPltVA(); - return 0; - } + case Symbol::SharedKind: case Symbol::UndefinedKind: return 0; case Symbol::LazyArchiveKind: @@ -143,6 +136,11 @@ return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex); } +uint64_t Symbol::getPltOffset() const { + assert(!this->IsInIplt); + return Target->getPltEntryOffset(PltIndex); +} + uint64_t Symbol::getSize() const { if (const auto *DR = dyn_cast(this)) return DR->Size; @@ -157,13 +155,6 @@ return Sec->Repl->getOutputSection(); return nullptr; } - - if (auto *S = dyn_cast(this)) { - if (S->CopyRelSec) - return S->CopyRelSec->getParent(); - return nullptr; - } - return nullptr; } Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -670,7 +670,7 @@ public: VersionNeedSection(); - void addSymbol(SharedSymbol *SS); + void addSymbol(Symbol *Sym); void finalizeContents() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1646,6 +1646,8 @@ CommonSec = dyn_cast_or_null(D->Section); if (CommonSec) ESym->st_shndx = SHN_COMMON; + else if (Sym->NeedsPltAddr) + ESym->st_shndx = SHN_UNDEF; else if (const OutputSection *OutSec = Sym->getOutputSection()) ESym->st_shndx = OutSec->SectionIndex; else if (isa(Sym)) @@ -1688,8 +1690,7 @@ if (isMicroMips()) { // Set STO_MIPS_MICROMIPS flag and less-significant bit for // defined microMIPS symbols and shared symbols with PLT record. - if ((Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) || - (Sym->isShared() && Sym->NeedsPltAddr)) { + if (Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) { if (StrTabSec.isDynamic()) ESym->st_value |= 1; ESym->st_other |= STO_MIPS_MICROMIPS; @@ -1831,10 +1832,6 @@ // its type correctly. std::vector::iterator Mid = std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) { - // Shared symbols that this executable preempts are special. The dynamic - // linker has to look them up, so they have to be in the hash table. - if (auto *SS = dyn_cast(S.Sym)) - return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr; return !S.Sym->isDefined(); }); @@ -2359,9 +2356,8 @@ NextIndex = getVerDefNum() + 1; } -template -void VersionNeedSection::addSymbol(SharedSymbol *SS) { - SharedFile &File = SS->getFile(); +template void VersionNeedSection::addSymbol(Symbol *SS) { + auto &File = cast>(*SS->File); if (SS->VerdefIndex == VER_NDX_GLOBAL) { SS->VersionId = VER_NDX_GLOBAL; return; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1570,9 +1570,9 @@ if (InX::DynSymTab && Sym->includeInDynsym()) { InX::DynSymTab->addSymbol(Sym); - if (auto *SS = dyn_cast(Sym)) - if (cast>(Sym->File)->IsNeeded) - In::VerNeed->addSymbol(SS); + if (auto *File = dyn_cast_or_null>(Sym->File)) + if (File->IsNeeded && !Sym->isUndefined()) + In::VerNeed->addSymbol(Sym); } } Index: test/ELF/map-file.s =================================================================== --- test/ELF/map-file.s +++ test/ELF/map-file.s @@ -73,8 +73,8 @@ // CHECK-NEXT: 20102c 20102c 0 1 baz // CHECK-NEXT: 201030 201030 30 16 .plt // CHECK-NEXT: 201030 201030 30 16 :(.plt) -// CHECK-NEXT: 201040 0 0 1 sharedFunc1 -// CHECK-NEXT: 201050 0 0 1 sharedFunc2 +// CHECK-NEXT: 201040 201040 0 1 sharedFunc1 +// CHECK-NEXT: 201050 201050 0 1 sharedFunc2 // CHECK-NEXT: 202000 202000 28 8 .got.plt // CHECK-NEXT: 202000 202000 28 8 :(.got.plt) // CHECK-NEXT: 203000 203000 100 8 .dynamic