Replace SharedSymbols with Defined when creating copy relocations.
This is slightly simpler to read IMHO. Now if a symbol has a position
in the file, it is Defined.
The main motivation is that with this a SharedSymbol doesn't need a
section, which reduces the size of SymbolUnion.
With this the peak allocation when linking chromium goes from 568.1 to
564.2 MB.
llvm-svn: 330966
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index d99d382..1c71c52 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -1111,8 +1111,8 @@
if (auto *DS = dyn_cast<Defined>(Sym))
return {DS->Section, false, DS->Value, Loc};
if (auto *SS = dyn_cast<SharedSymbol>(Sym))
- if (!ErrorOnMissingSection || SS->CopyRelSec)
- return {SS->CopyRelSec, false, 0, Loc};
+ if (!ErrorOnMissingSection)
+ return {nullptr, false, 0, Loc};
}
error(Loc + ": symbol not found: " + Name);
diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp
index 4e8e045..c5984c9 100644
--- a/lld/ELF/MapFile.cpp
+++ b/lld/ELF/MapFile.cpp
@@ -38,7 +38,7 @@
using namespace lld;
using namespace lld::elf;
-typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy;
+typedef DenseMap<const SectionBase *, SmallVector<Defined *, 4>> 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<Symbol *> getSymbols() {
- std::vector<Symbol *> V;
- for (InputFile *File : ObjectFiles) {
- for (Symbol *B : File->getSymbols()) {
- if (auto *SS = dyn_cast<SharedSymbol>(B))
- if (SS->CopyRelSec || SS->NeedsPltAddr)
- V.push_back(SS);
+static std::vector<Defined *> getSymbols() {
+ std::vector<Defined *> V;
+ for (InputFile *File : ObjectFiles)
+ for (Symbol *B : File->getSymbols())
if (auto *DR = dyn_cast<Defined>(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<Symbol *> Syms) {
+static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {
SymbolMapTy Ret;
- for (Symbol *S : Syms) {
- if (auto *DR = dyn_cast<Defined>(S)) {
- Ret[DR->Section].push_back(S);
- continue;
- }
-
- SharedSymbol *SS = cast<SharedSymbol>(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<Symbol *> &V = It.second;
- std::stable_sort(V.begin(), V.end(), [](Symbol *A, Symbol *B) {
+ SmallVectorImpl<Defined *> &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<Symbol *, std::string>
-getSymbolStrings(ArrayRef<Symbol *> Syms) {
+getSymbolStrings(ArrayRef<Defined *> Syms) {
std::vector<std::string> 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<Symbol *> Syms = getSymbols();
+ std::vector<Defined *> Syms = getSymbols();
SymbolMapTy SectionSyms = getSectionSyms(Syms);
DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 9f9c6fd..2863699 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/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<Defined>(&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<ELFT>(SS)) {
- Sym->CopyRelSec = Sec;
- Sym->IsUsedInRegularObj = true;
- Sym->Used = true;
- }
+ for (SharedSymbol *Sym : getSymbolsAt<ELFT>(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<SharedSymbol>(Sym);
- if (!SS.CopyRelSec) {
+ if (auto *SS = dyn_cast<SharedSymbol>(&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<ELFT>(SS);
+ addCopyRelSymbol<ELFT>(*SS);
}
Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
return;
@@ -889,8 +898,10 @@
if (!Sym.isInPlt())
addPltEntry<ELFT>(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;
}
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 4c5878b..6f7ac8b 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -97,14 +97,7 @@
}
return VA;
}
- case Symbol::SharedKind: {
- auto &SS = cast<SharedSymbol>(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<Defined>(this))
return DR->Size;
@@ -157,13 +155,6 @@
return Sec->Repl->getOutputSection();
return nullptr;
}
-
- if (auto *S = dyn_cast<SharedSymbol>(this)) {
- if (S->CopyRelSec)
- return S->CopyRelSec->getParent();
- return nullptr;
- }
-
return nullptr;
}
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 51925aa..1f97448 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/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<SharedFile<ELFT>>(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,
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 6102e5f..ac16b85 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1646,6 +1646,8 @@
CommonSec = dyn_cast_or_null<BssSection>(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<Defined>(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<SymbolTableEntry>::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<SharedSymbol>(S.Sym))
- return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr;
return !S.Sym->isDefined();
});
@@ -2359,9 +2356,8 @@
NextIndex = getVerDefNum() + 1;
}
-template <class ELFT>
-void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
- SharedFile<ELFT> &File = SS->getFile<ELFT>();
+template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {
+ auto &File = cast<SharedFile<ELFT>>(*SS->File);
if (SS->VerdefIndex == VER_NDX_GLOBAL) {
SS->VersionId = VER_NDX_GLOBAL;
return;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 22fbf0a..49080e1 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/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;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index e4a0e61..a5e0a44 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1570,9 +1570,9 @@
if (InX::DynSymTab && Sym->includeInDynsym()) {
InX::DynSymTab->addSymbol(Sym);
- if (auto *SS = dyn_cast<SharedSymbol>(Sym))
- if (cast<SharedFile<ELFT>>(Sym->File)->IsNeeded)
- In<ELFT>::VerNeed->addSymbol(SS);
+ if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File))
+ if (File->IsNeeded && !Sym->isUndefined())
+ In<ELFT>::VerNeed->addSymbol(Sym);
}
}
diff --git a/lld/test/ELF/map-file.s b/lld/test/ELF/map-file.s
index 1287a18..fe03270 100644
--- a/lld/test/ELF/map-file.s
+++ b/lld/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 <internal>:(.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 <internal>:(.got.plt)
// CHECK-NEXT: 203000 203000 100 8 .dynamic