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,24 @@ return Ret; } +static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value, + uint64_t Size) { + uint32_t GotPltIndex = Sym.GotPltIndex; + uint32_t PltIndex = Sym.PltIndex; + uint32_t GotIndex = Sym.GotIndex; + uint32_t VerdefIndex = Sym.VerdefIndex; + bool IsInGlobalMipsGot = Sym.IsInGlobalMipsGot; + replaceSymbol(&Sym, Sym.File, Sym.getName(), Sym.Binding, + Sym.StOther, Sym.Type, Value, Size, Sec); + Sym.GotPltIndex = GotPltIndex; + Sym.PltIndex = PltIndex; + Sym.GotIndex = GotIndex; + Sym.VerdefIndex = VerdefIndex; + Sym.IsInGlobalMipsGot = IsInGlobalMipsGot; + Sym.IsPreemptible = true; + Sym.ExportDynamic = 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 @@ -523,7 +541,7 @@ // dynamic symbol for each one. This causes the copy relocation to correctly // interpose any aliases. for (SharedSymbol *Sym : getSymbolsAt(SS)) { - Sym->CopyRelSec = Sec; + replaceWithDefined(*Sym, Sec, 0, Sym->Size); Sym->IsUsedInRegularObj = true; Sym->Used = true; } @@ -762,12 +780,12 @@ // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. template -static RelExpr processRelocAux(InputSectionBase &Sec, RelExpr Expr, - RelType Type, uint64_t Offset, Symbol &Sym, - const RelTy &Rel, int64_t Addend) { +static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type, + uint64_t Offset, Symbol &Sym, const RelTy &Rel, + int64_t Addend) { if (isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Offset)) { Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); - return Expr; + return; } bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText; if (CanWrite) { @@ -777,7 +795,7 @@ if (!IsPreemptibleValue) { InX::RelaDyn->addReloc(Target->RelativeRel, &Sec, Offset, &Sym, Addend, Expr, Type); - return Expr; + return; } else if (RelType Rel = Target->getDynRel(Type)) { InX::RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, R_ADDEND, Type); @@ -798,7 +816,7 @@ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 if (Config->EMachine == EM_MIPS) InX::MipsGot->addEntry(Sym, Addend, Expr); - return Expr; + return; } } @@ -806,7 +824,7 @@ // executable, give up on it and produce a non preemptible 0. if (!Config->Shared && Sym.isUndefWeak()) { Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); - return Expr; + return; } if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) { @@ -816,7 +834,7 @@ " in readonly segment; recompile object files with -fPIC " "or pass '-Wl,-z,notext' to allow text relocations in the output" + getLocation(Sec, Sym, Offset)); - return Expr; + return; } // Copy relocations are only possible if we are creating an executable. @@ -824,34 +842,31 @@ errorOrWarn("relocation " + toString(Type) + " cannot be used against symbol " + toString(Sym) + "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); - return Expr; + return; } // If the symbol is undefined we already reported any relevant errors. - if (!Sym.isShared()) { - assert(Sym.isUndefined()); - return Expr; - } + if (Sym.isUndefined()) + return; if (!canDefineSymbolInExecutable(Sym)) { error("cannot preempt symbol: " + toString(Sym) + getLocation(Sec, Sym, Offset)); - return Expr; + return; } 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 Expr; + return; } if (Sym.isFunc()) { @@ -886,15 +901,18 @@ errorOrWarn("symbol '" + toString(Sym) + "' cannot be preempted; recompile with -fPIE" + getLocation(Sec, Sym, Offset)); + 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; - Expr = toPlt(Expr); Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); - return Expr; + return; } errorOrWarn("symbol '" + toString(Sym) + "' has no type" + getLocation(Sec, Sym, Offset)); - return Expr; } template @@ -963,7 +981,6 @@ return; } - Expr = processRelocAux(Sec, Expr, Type, Offset, Sym, Rel, Addend); // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. if (needsPlt(Expr) && !Sym.isInPlt()) { if (Sym.isGnuIFunc() && !Sym.IsPreemptible) @@ -992,6 +1009,8 @@ addGotEntry(Sym); } } + + processRelocAux(Sec, Expr, Type, Offset, Sym, Rel, Addend); } template Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -73,6 +73,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; @@ -147,6 +150,7 @@ uint64_t getGotPltOffset() const; uint64_t getGotPltVA() const; uint64_t getPltVA() const; + uint64_t getPltOffset() const; uint64_t getSize() const; OutputSection *getOutputSection() const; @@ -226,8 +230,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 @@ -252,16 +257,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: @@ -141,6 +134,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; @@ -155,13 +153,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/got32-i386-pie-rw.s =================================================================== --- test/ELF/got32-i386-pie-rw.s +++ test/ELF/got32-i386-pie-rw.s @@ -7,8 +7,8 @@ # CHECK: .foobar PROGBITS 00001000 # CHECK: .got PROGBITS [[GOT:[0-9a-z]*]] -# CHECK: 00001002 00000008 R_386_RELATIVE -# CHECK: [[GOT]] 00000008 R_386_RELATIVE +# CHECK-DAG: 00001002 00000008 R_386_RELATIVE +# CHECK-DAG: [[GOT]] 00000008 R_386_RELATIVE foo: .section .foobar, "awx" 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