Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -1112,9 +1112,9 @@ if (Symbol *Sym = Symtab->find(Name)) { if (auto *DS = dyn_cast(Sym)) return {DS->Section, false, DS->Value, Loc}; - if (isa(Sym)) - if (!ErrorOnMissingSection) - return {nullptr, false, 0, Loc}; + if (auto *SS = dyn_cast(Sym)) + if (!ErrorOnMissingSection || SS->CopyRelSec) + return {SS->CopyRelSec, 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,29 +53,44 @@ } // 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()) +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); if (auto *DR = dyn_cast(B)) - if (!DR->isSection() && DR->Section && DR->Section->Live && - (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss)) + if (DR->File == File && !DR->isSection() && DR->Section && + DR->Section->Live) 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 (Defined *DR : Syms) - Ret[DR->Section].push_back(DR); + 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[In.Plt].push_back(S); + } // 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(), [](Defined *A, Defined *B) { + SmallVectorImpl &V = It.second; + std::stable_sort(V.begin(), V.end(), [](Symbol *A, Symbol *B) { return A->getVA() < B->getVA(); }); } @@ -86,7 +101,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]); @@ -154,7 +169,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 @@ -474,25 +474,6 @@ return Ret; } -// When a symbol is copy relocated or we create a canonical plt entry, it is -// effectively a defined symbol. In the case of copy relocation the symbol is -// in .bss and in the case of a canonical plt entry it is in .plt. This function -// replaces the existing symbol with a Defined pointing to the appropriate -// location. -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.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 @@ -554,8 +535,11 @@ // 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)) - replaceWithDefined(*Sym, Sec, 0, Sym->Size); + for (SharedSymbol *Sym : getSymbolsAt(SS)) { + Sym->CopyRelSec = Sec; + Sym->IsUsedInRegularObj = true; + Sym->Used = true; + } In.RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS); } @@ -869,8 +853,10 @@ } // If the symbol is undefined we already reported any relevant errors. - if (Sym.isUndefined()) + if (!Sym.isShared()) { + assert(Sym.isUndefined()); return; + } if (!canDefineSymbolInExecutable(Sym)) { error("cannot preempt symbol: " + toString(Sym) + @@ -880,13 +866,14 @@ if (Sym.isObject()) { // Produce a copy relocation. - if (auto *SS = dyn_cast(&Sym)) { + auto &SS = cast(Sym); + if (!SS.CopyRelSec) { 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; @@ -925,11 +912,10 @@ "' cannot be preempted; recompile with -fPIE" + getLocation(Sec, Sym, Offset)); if (!Sym.isInPlt()) - addPltEntry(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); - if (!Sym.isDefined()) - replaceWithDefined(Sym, In.Plt, Sym.getPltOffset(), 0); + addPltEntry(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, + Sym); Sym.NeedsPltAddr = true; - Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + Sec.Relocations.push_back({toPlt(Expr), Type, Offset, Addend, &Sym}); return; } Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -72,9 +72,6 @@ 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; @@ -158,7 +155,6 @@ uint64_t getGotPltOffset() const; uint64_t getGotPltVA() const; uint64_t getPltVA() const; - uint64_t getPltOffset() const; uint64_t getSize() const; OutputSection *getOutputSection() const; @@ -241,9 +237,8 @@ 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), - Alignment(Alignment), Value(Value), Size(Size) { - this->VerdefIndex = VerdefIndex; + : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value), + Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) { // 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 @@ -268,10 +263,16 @@ return *cast>(File); } - uint32_t Alignment; + // If not null, there is a copy relocation to this section. + InputSection *CopyRelSec = nullptr; 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 @@ -103,7 +103,14 @@ } return VA; } - case Symbol::SharedKind: + 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::UndefinedKind: return 0; case Symbol::LazyArchiveKind: @@ -143,11 +150,6 @@ return In.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; @@ -160,6 +162,13 @@ 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 @@ -805,7 +805,7 @@ public: VersionNeedSection(); - void addSymbol(Symbol *Sym); + void addSymbol(SharedSymbol *SS); void finalizeContents() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1948,12 +1948,12 @@ static uint32_t getSymSectionIndex(Symbol *Sym) { if (getCommonSec(Sym)) return SHN_COMMON; - if (!isa(Sym) || Sym->NeedsPltAddr) - return SHN_UNDEF; if (const OutputSection *OS = Sym->getOutputSection()) return OS->SectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX : OS->SectionIndex; - return SHN_ABS; + if (isa(Sym)) + return SHN_ABS; + return SHN_UNDEF; } // Write the internal symbol table contents to the output symbol table. @@ -2197,6 +2197,10 @@ // 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(); }); @@ -2722,8 +2726,9 @@ NextIndex = getVerDefNum() + 1; } -template void VersionNeedSection::addSymbol(Symbol *SS) { - auto &File = cast>(*SS->File); +template +void VersionNeedSection::addSymbol(SharedSymbol *SS) { + SharedFile &File = SS->getFile(); if (SS->VerdefIndex == VER_NDX_GLOBAL) { SS->VersionId = VER_NDX_GLOBAL; return; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1595,9 +1595,9 @@ if (In.DynSymTab && Sym->includeInDynsym()) { In.DynSymTab->addSymbol(Sym); - if (auto *File = dyn_cast_or_null>(Sym->File)) - if (File->IsNeeded && !Sym->isUndefined()) - InX::VerNeed->addSymbol(Sym); + if (auto *SS = dyn_cast(Sym)) + if (cast>(Sym->File)->IsNeeded) + InX::VerNeed->addSymbol(SS); } } 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 201040 0 1 sharedFunc1 -// CHECK-NEXT: 201050 201050 0 1 sharedFunc2 +// CHECK-NEXT: 201040 0 0 1 sharedFunc1 +// CHECK-NEXT: 201050 0 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