aboutsummaryrefslogtreecommitdiff
path: root/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'ELF')
-rw-r--r--ELF/Config.h1
-rw-r--r--ELF/Driver.cpp8
-rw-r--r--ELF/GdbIndex.h2
-rw-r--r--ELF/ICF.cpp2
-rw-r--r--ELF/InputFiles.cpp6
-rw-r--r--ELF/InputSection.cpp56
-rw-r--r--ELF/LinkerScript.cpp84
-rw-r--r--ELF/LinkerScript.h11
-rw-r--r--ELF/MapFile.cpp2
-rw-r--r--ELF/OutputSections.cpp13
-rw-r--r--ELF/OutputSections.h1
-rw-r--r--ELF/Relocations.cpp80
-rw-r--r--ELF/ScriptParser.cpp24
-rw-r--r--ELF/Strings.cpp4
-rw-r--r--ELF/Symbols.cpp9
-rw-r--r--ELF/Symbols.h2
-rw-r--r--ELF/SyntheticSections.cpp217
-rw-r--r--ELF/SyntheticSections.h51
-rw-r--r--ELF/Target.cpp60
-rw-r--r--ELF/Threads.h21
-rw-r--r--ELF/Thunks.cpp18
-rw-r--r--ELF/Writer.cpp472
-rw-r--r--ELF/Writer.h2
23 files changed, 574 insertions, 572 deletions
diff --git a/ELF/Config.h b/ELF/Config.h
index 0321c84e7106..57a0e5a5ec73 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -73,7 +73,6 @@ struct VersionDefinition {
// Most fields are initialized by the driver.
struct Configuration {
InputFile *FirstElf = nullptr;
- bool HasStaticTlsModel = false;
uint8_t OSABI = 0;
llvm::CachePruningPolicy ThinLTOCachePolicy;
llvm::StringMap<uint64_t> SectionStartMap;
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index c2cfe3c4129e..737c6a6bf114 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -284,7 +284,7 @@ static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) {
int V = Default;
if (auto *Arg = Args.getLastArg(Key)) {
StringRef S = Arg->getValue();
- if (S.getAsInteger(10, V))
+ if (!to_integer(S, V, 10))
error(Arg->getSpelling() + ": number expected, but got " + S);
}
return V;
@@ -311,7 +311,7 @@ static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key,
if (Pos != StringRef::npos && Key == Value.substr(0, Pos)) {
Value = Value.substr(Pos + 1);
uint64_t Result;
- if (Value.getAsInteger(0, Result))
+ if (!to_integer(Value, Result))
error("invalid " + Key + ": " + Value);
return Result;
}
@@ -522,7 +522,7 @@ static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) {
uint64_t VA = 0;
if (S.startswith("0x"))
S = S.drop_front(2);
- if (S.getAsInteger(16, VA))
+ if (!to_integer(S, VA, 16))
error("invalid argument: " + toString(Arg));
return VA;
}
@@ -886,7 +886,7 @@ static uint64_t getImageBase(opt::InputArgList &Args) {
StringRef S = Arg->getValue();
uint64_t V;
- if (S.getAsInteger(0, V)) {
+ if (!to_integer(S, V)) {
error("-image-base: number expected, but got " + S);
return 0;
}
diff --git a/ELF/GdbIndex.h b/ELF/GdbIndex.h
index a36b92714def..03fec64f9bd5 100644
--- a/ELF/GdbIndex.h
+++ b/ELF/GdbIndex.h
@@ -21,7 +21,7 @@ class InputSection;
// Struct represents single entry of address area of gdb index.
struct AddressEntry {
- InputSectionBase *Section;
+ InputSection *Section;
uint64_t LowAddress;
uint64_t HighAddress;
size_t CuIndex;
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
index dcf01ea80011..3722d4e3ed2f 100644
--- a/ELF/ICF.cpp
+++ b/ELF/ICF.cpp
@@ -325,7 +325,7 @@ void ICF<ELFT>::forEachClass(std::function<void(size_t, size_t)> Fn) {
// Split sections into 256 shards and call Fn in parallel.
size_t NumShards = 256;
size_t Step = Sections.size() / NumShards;
- parallelFor(0, NumShards, [&](size_t I) {
+ parallelForEachN(0, NumShards, [&](size_t I) {
forEachClassRange(I * Step, (I + 1) * Step, Fn);
});
forEachClassRange(Step * NumShards, Sections.size(), Fn);
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 5f94fc9338a4..fe036a644f41 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -383,9 +383,9 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
// we see. The eglibc ARM dynamic loaders require the presence of an
// attribute section for dlopen to work.
// In a full implementation we would merge all attribute sections.
- if (In<ELFT>::ARMAttributes == nullptr) {
- In<ELFT>::ARMAttributes = make<InputSection>(this, &Sec, Name);
- return In<ELFT>::ARMAttributes;
+ if (InX::ARMAttributes == nullptr) {
+ InX::ARMAttributes = make<InputSection>(this, &Sec, Name);
+ return InX::ARMAttributes;
}
return &InputSection::Discarded;
case SHT_RELA:
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index c082f128a9bc..87896ec96b29 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -324,7 +324,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
// section, but for --emit-relocs it is an virtual address.
P->r_offset = RelocatedSection->OutSec->Addr +
RelocatedSection->getOffset(Rel.r_offset);
- P->setSymbolAndType(In<ELFT>::SymTab->getSymbolIndex(&Body), Type,
+ P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type,
Config->IsMips64EL);
if (Body.Type == STT_SECTION) {
@@ -400,40 +400,40 @@ getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
return Body.getVA(A);
case R_GOT:
case R_RELAX_TLS_GD_TO_IE_ABS:
- return Body.getGotVA<ELFT>() + A;
+ return Body.getGotVA() + A;
case R_GOTONLY_PC:
- return In<ELFT>::Got->getVA() + A - P;
+ return InX::Got->getVA() + A - P;
case R_GOTONLY_PC_FROM_END:
- return In<ELFT>::Got->getVA() + A - P + In<ELFT>::Got->getSize();
+ return InX::Got->getVA() + A - P + InX::Got->getSize();
case R_GOTREL:
- return Body.getVA(A) - In<ELFT>::Got->getVA();
+ return Body.getVA(A) - InX::Got->getVA();
case R_GOTREL_FROM_END:
- return Body.getVA(A) - In<ELFT>::Got->getVA() - In<ELFT>::Got->getSize();
+ return Body.getVA(A) - InX::Got->getVA() - InX::Got->getSize();
case R_GOT_FROM_END:
case R_RELAX_TLS_GD_TO_IE_END:
- return Body.getGotOffset() + A - In<ELFT>::Got->getSize();
+ return Body.getGotOffset() + A - InX::Got->getSize();
case R_GOT_OFF:
return Body.getGotOffset() + A;
case R_GOT_PAGE_PC:
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
- return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P);
+ return getAArch64Page(Body.getGotVA() + A) - getAArch64Page(P);
case R_GOT_PC:
case R_RELAX_TLS_GD_TO_IE:
- return Body.getGotVA<ELFT>() + A - P;
+ return Body.getGotVA() + A - P;
case R_HINT:
case R_NONE:
case R_TLSDESC_CALL:
llvm_unreachable("cannot relocate hint relocs");
case R_MIPS_GOTREL:
- return Body.getVA(A) - In<ELFT>::MipsGot->getGp();
+ return Body.getVA(A) - InX::MipsGot->getGp();
case R_MIPS_GOT_GP:
- return In<ELFT>::MipsGot->getGp() + A;
+ return InX::MipsGot->getGp() + A;
case R_MIPS_GOT_GP_PC: {
// R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target
// is _gp_disp symbol. In that case we should use the following
// formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- uint64_t V = In<ELFT>::MipsGot->getGp() + A - P;
+ uint64_t V = InX::MipsGot->getGp() + A - P;
if (Type == R_MIPS_LO16)
V += 4;
return V;
@@ -442,24 +442,21 @@ getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
// If relocation against MIPS local symbol requires GOT entry, this entry
// should be initialized by 'page address'. This address is high 16-bits
// of sum the symbol's value and the addend.
- return In<ELFT>::MipsGot->getVA() +
- In<ELFT>::MipsGot->getPageEntryOffset(Body, A) -
- In<ELFT>::MipsGot->getGp();
+ return InX::MipsGot->getVA() + InX::MipsGot->getPageEntryOffset(Body, A) -
+ InX::MipsGot->getGp();
case R_MIPS_GOT_OFF:
case R_MIPS_GOT_OFF32:
// In case of MIPS if a GOT relocation has non-zero addend this addend
// should be applied to the GOT entry content not to the GOT entry offset.
// That is why we use separate expression type.
- return In<ELFT>::MipsGot->getVA() +
- In<ELFT>::MipsGot->getBodyEntryOffset(Body, A) -
- In<ELFT>::MipsGot->getGp();
+ return InX::MipsGot->getVA() + InX::MipsGot->getBodyEntryOffset(Body, A) -
+ InX::MipsGot->getGp();
case R_MIPS_TLSGD:
- return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
- In<ELFT>::MipsGot->getGlobalDynOffset(Body) -
- In<ELFT>::MipsGot->getGp();
+ return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() +
+ InX::MipsGot->getGlobalDynOffset(Body) - InX::MipsGot->getGp();
case R_MIPS_TLSLD:
- return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
- In<ELFT>::MipsGot->getTlsIndexOff() - In<ELFT>::MipsGot->getGp();
+ return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() +
+ InX::MipsGot->getTlsIndexOff() - InX::MipsGot->getGp();
case R_PAGE_PC:
case R_PLT_PAGE_PC:
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
@@ -523,19 +520,18 @@ getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
case R_SIZE:
return Body.getSize<ELFT>() + A;
case R_TLSDESC:
- return In<ELFT>::Got->getGlobalDynAddr(Body) + A;
+ return InX::Got->getGlobalDynAddr(Body) + A;
case R_TLSDESC_PAGE:
- return getAArch64Page(In<ELFT>::Got->getGlobalDynAddr(Body) + A) -
+ return getAArch64Page(InX::Got->getGlobalDynAddr(Body) + A) -
getAArch64Page(P);
case R_TLSGD:
- return In<ELFT>::Got->getGlobalDynOffset(Body) + A -
- In<ELFT>::Got->getSize();
+ return InX::Got->getGlobalDynOffset(Body) + A - InX::Got->getSize();
case R_TLSGD_PC:
- return In<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
+ return InX::Got->getGlobalDynAddr(Body) + A - P;
case R_TLSLD:
- return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize();
+ return InX::Got->getTlsIndexOff() + A - InX::Got->getSize();
case R_TLSLD_PC:
- return In<ELFT>::Got->getTlsIndexVA() + A - P;
+ return InX::Got->getTlsIndexVA() + A - P;
}
llvm_unreachable("Invalid expression");
}
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index d7858e173c7b..161909abf00d 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -48,8 +48,12 @@ using namespace lld::elf;
LinkerScript *elf::Script;
uint64_t ExprValue::getValue() const {
- if (Sec)
- return Sec->getOffset(Val) + Sec->getOutputSection()->Addr;
+ if (Sec) {
+ if (Sec->getOutputSection())
+ return Sec->getOffset(Val) + Sec->getOutputSection()->Addr;
+ error("unable to evaluate expression: input section " + Sec->Name +
+ " has no output section assigned");
+ }
return Val;
}
@@ -411,6 +415,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
if (OutputSection *Sec = Cmd->Sec) {
assert(Sec->SectionIndex == INT_MAX);
Sec->SectionIndex = I;
+ SecToCommand[Sec] = Cmd;
}
}
}
@@ -440,6 +445,7 @@ void LinkerScript::fabricateDefaultCommands() {
auto *OSCmd = make<OutputSectionCommand>(Sec->Name);
OSCmd->Sec = Sec;
+ SecToCommand[Sec] = OSCmd;
// Prefer user supplied address over additional alignment constraint
auto I = Config->SectionStartMap.find(Sec->Name);
@@ -484,6 +490,7 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
auto *Cmd = cast<OutputSectionCommand>(*I);
Factory.addInputSec(S, Name, Cmd->Sec);
if (OutputSection *Sec = Cmd->Sec) {
+ SecToCommand[Sec] = Cmd;
unsigned Index = std::distance(Opt.Commands.begin(), I);
assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index);
Sec->SectionIndex = Index;
@@ -699,6 +706,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
OutSec->SectionIndex = I;
OutputSections->push_back(OutSec);
Cmd->Sec = OutSec;
+ SecToCommand[OutSec] = Cmd;
}
}
@@ -822,16 +830,14 @@ void LinkerScript::placeOrphanSections() {
// If there is no command corresponding to this output section,
// create one and put a InputSectionDescription in it so that both
// representations agree on which input sections to use.
- auto Pos = std::find_if(CmdIter, E, [&](BaseCommand *Base) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- return Cmd && Cmd->Name == Name;
- });
- if (Pos == E) {
- auto *Cmd = make<OutputSectionCommand>(Name);
+ OutputSectionCommand *Cmd = getCmd(Sec);
+ if (!Cmd) {
+ Cmd = make<OutputSectionCommand>(Name);
Opt.Commands.insert(CmdIter, Cmd);
++CmdIndex;
Cmd->Sec = Sec;
+ SecToCommand[Sec] = Cmd;
auto *ISD = make<InputSectionDescription>("");
for (InputSection *IS : Sec->Sections)
ISD->Sections.push_back(IS);
@@ -841,7 +847,11 @@ void LinkerScript::placeOrphanSections() {
}
// Continue from where we found it.
- CmdIndex = (Pos - Opt.Commands.begin()) + 1;
+ while (*CmdIter != Cmd) {
+ ++CmdIter;
+ ++CmdIndex;
+ }
+ ++CmdIndex;
}
}
@@ -1000,7 +1010,7 @@ std::vector<PhdrEntry> LinkerScript::createPhdrs() {
break;
// Assign headers specified by linker script
- for (size_t Id : getPhdrIndices(Sec->Name)) {
+ for (size_t Id : getPhdrIndices(Sec)) {
Ret[Id].add(Sec);
if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
Ret[Id].p_flags |= Sec->getPhdrFlags();
@@ -1020,11 +1030,16 @@ bool LinkerScript::ignoreInterpSection() {
return true;
}
-Optional<uint32_t> LinkerScript::getFiller(StringRef Name) {
- for (BaseCommand *Base : Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (Cmd->Name == Name)
- return Cmd->Filler;
+OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const {
+ auto I = SecToCommand.find(Sec);
+ if (I == SecToCommand.end())
+ return nullptr;
+ return I->second;
+}
+
+Optional<uint32_t> LinkerScript::getFiller(OutputSection *Sec) {
+ if (OutputSectionCommand *Cmd = getCmd(Sec))
+ return Cmd->Filler;
return None;
}
@@ -1042,26 +1057,16 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
}
void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) {
- auto I = std::find_if(Opt.Commands.begin(), Opt.Commands.end(),
- [=](BaseCommand *Base) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (Cmd->Sec == Sec)
- return true;
- return false;
- });
- if (I == Opt.Commands.end())
- return;
- auto *Cmd = cast<OutputSectionCommand>(*I);
- for (BaseCommand *Base : Cmd->Commands)
- if (auto *Data = dyn_cast<BytesDataCommand>(Base))
- writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
+ if (OutputSectionCommand *Cmd = getCmd(Sec))
+ for (BaseCommand *Base : Cmd->Commands)
+ if (auto *Data = dyn_cast<BytesDataCommand>(Base))
+ writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
}
-bool LinkerScript::hasLMA(StringRef Name) {
- for (BaseCommand *Base : Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (Cmd->LMAExpr && Cmd->Name == Name)
- return true;
+bool LinkerScript::hasLMA(OutputSection *Sec) {
+ if (OutputSectionCommand *Cmd = getCmd(Sec))
+ if (Cmd->LMAExpr)
+ return true;
return false;
}
@@ -1080,15 +1085,10 @@ ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
bool LinkerScript::isDefined(StringRef S) { return findSymbol(S) != nullptr; }
-// Returns indices of ELF headers containing specific section, identified
-// by Name. Each index is a zero based number of ELF header listed within
-// PHDRS {} script block.
-std::vector<size_t> LinkerScript::getPhdrIndices(StringRef SectionName) {
- for (BaseCommand *Base : Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- if (!Cmd || Cmd->Name != SectionName)
- continue;
-
+// Returns indices of ELF headers containing specific section. Each index is a
+// zero based number of ELF header listed within PHDRS {} script block.
+std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Sec) {
+ if (OutputSectionCommand *Cmd = getCmd(Sec)) {
std::vector<size_t> Ret;
for (StringRef PhdrName : Cmd->Phdrs)
Ret.push_back(getPhdrIndex(Cmd->Location, PhdrName));
diff --git a/ELF/LinkerScript.h b/ELF/LinkerScript.h
index 7bcd21c87602..d0a4d83d72b0 100644
--- a/ELF/LinkerScript.h
+++ b/ELF/LinkerScript.h
@@ -211,8 +211,9 @@ struct ScriptConfiguration {
std::vector<llvm::StringRef> ReferencedSymbols;
};
-class LinkerScript {
-protected:
+class LinkerScript final {
+ llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
+ OutputSectionCommand *getCmd(OutputSection *Sec) const;
void assignSymbol(SymbolAssignment *Cmd, bool InSec);
void setDot(Expr E, const Twine &Loc, bool InSec);
@@ -222,7 +223,7 @@ protected:
std::vector<InputSectionBase *>
createInputSectionList(OutputSectionCommand &Cmd);
- std::vector<size_t> getPhdrIndices(StringRef SectionName);
+ std::vector<size_t> getPhdrIndices(OutputSection *Sec);
size_t getPhdrIndex(const Twine &Loc, StringRef PhdrName);
MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
@@ -262,8 +263,8 @@ public:
std::vector<PhdrEntry> createPhdrs();
bool ignoreInterpSection();
- llvm::Optional<uint32_t> getFiller(StringRef Name);
- bool hasLMA(StringRef Name);
+ llvm::Optional<uint32_t> getFiller(OutputSection *Sec);
+ bool hasLMA(OutputSection *Sec);
bool shouldKeep(InputSectionBase *S);
void assignOffsets(OutputSectionCommand *Cmd);
void placeOrphanSections();
diff --git a/ELF/MapFile.cpp b/ELF/MapFile.cpp
index af5bc3c2c813..23c63e845c9a 100644
--- a/ELF/MapFile.cpp
+++ b/ELF/MapFile.cpp
@@ -84,7 +84,7 @@ template <class ELFT>
DenseMap<DefinedRegular *, std::string>
getSymbolStrings(ArrayRef<DefinedRegular *> Syms) {
std::vector<std::string> Str(Syms.size());
- parallelFor(0, Syms.size(), [&](size_t I) {
+ parallelForEachN(0, Syms.size(), [&](size_t I) {
raw_string_ostream OS(Str[I]);
writeHeader<ELFT>(OS, Syms[I]->getVA(), Syms[I]->template getSize<ELFT>(),
0);
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index cb9c57657af3..dcefd03766d7 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -133,7 +133,7 @@ template <class ELFT> void OutputSection::finalize() {
if (isa<SyntheticSection>(First))
return;
- this->Link = In<ELFT>::SymTab->OutSec->SectionIndex;
+ this->Link = InX::SymTab->OutSec->SectionIndex;
// sh_info for SHT_REL[A] sections should contain the section header index of
// the section to which the relocation applies.
InputSectionBase *S = First->getRelocatedSection();
@@ -273,7 +273,7 @@ uint32_t OutputSection::getFiller() {
// linker script. If nothing is specified and this is an executable section,
// fall back to trap instructions to prevent bad diassembly and detect invalid
// jumps to padding.
- if (Optional<uint32_t> Filler = Script->getFiller(Name))
+ if (Optional<uint32_t> Filler = Script->getFiller(this))
return *Filler;
if (Flags & SHF_EXECINSTR)
return Target->TrapInstr;
@@ -297,7 +297,7 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
if (Filler)
fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);
- parallelFor(0, Sections.size(), [=](size_t I) {
+ parallelForEachN(0, Sections.size(), [=](size_t I) {
InputSection *Sec = Sections[I];
Sec->writeTo<ELFT>(Buf);
@@ -429,8 +429,11 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type))
Sec->Type = SHT_PROGBITS;
else
- error("Section has different type from others with the same name " +
- toString(IS));
+ error("section type mismatch for " + IS->Name +
+ "\n>>> " + toString(IS) + ": " +
+ getELFSectionTypeName(Config->EMachine, IS->Type) +
+ "\n>>> output section " + Sec->Name + ": " +
+ getELFSectionTypeName(Config->EMachine, Sec->Type));
}
Sec->Flags |= Flags;
} else {
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index 6405fb38c6d6..413871b60cf7 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -50,6 +50,7 @@ public:
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
unsigned SectionIndex;
+ unsigned SortRank;
uint32_t getPhdrFlags() const;
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index f5db931e9755..ea7477e03842 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -106,21 +106,21 @@ static unsigned handleMipsTlsRelocation(uint32_t Type, SymbolBody &Body,
InputSectionBase &C, uint64_t Offset,
int64_t Addend, RelExpr Expr) {
if (Expr == R_MIPS_TLSLD) {
- if (In<ELFT>::MipsGot->addTlsIndex() && Config->Pic)
- In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::MipsGot,
- In<ELFT>::MipsGot->getTlsIndexOff(), false,
+ if (InX::MipsGot->addTlsIndex() && Config->Pic)
+ In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::MipsGot,
+ InX::MipsGot->getTlsIndexOff(), false,
nullptr, 0});
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
return 1;
}
if (Expr == R_MIPS_TLSGD) {
- if (In<ELFT>::MipsGot->addDynTlsEntry(Body) && Body.isPreemptible()) {
- uint64_t Off = In<ELFT>::MipsGot->getGlobalDynOffset(Body);
+ if (InX::MipsGot->addDynTlsEntry(Body) && Body.isPreemptible()) {
+ uint64_t Off = InX::MipsGot->getGlobalDynOffset(Body);
In<ELFT>::RelaDyn->addReloc(
- {Target->TlsModuleIndexRel, In<ELFT>::MipsGot, Off, false, &Body, 0});
+ {Target->TlsModuleIndexRel, InX::MipsGot, Off, false, &Body, 0});
if (Body.isPreemptible())
- In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::MipsGot,
+ In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, InX::MipsGot,
Off + Config->Wordsize, false, &Body, 0});
}
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
@@ -156,17 +156,17 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body,
auto AddTlsReloc = [&](uint64_t Off, uint32_t Type, SymbolBody *Dest,
bool Dyn) {
if (Dyn)
- In<ELFT>::RelaDyn->addReloc({Type, In<ELFT>::Got, Off, false, Dest, 0});
+ In<ELFT>::RelaDyn->addReloc({Type, InX::Got, Off, false, Dest, 0});
else
- In<ELFT>::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
+ InX::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
};
// Local Dynamic is for access to module local TLS variables, while still
// being suitable for being dynamically loaded via dlopen.
// GOT[e0] is the module index, with a special value of 0 for the current
// module. GOT[e1] is unused. There only needs to be one module index entry.
- if (Expr == R_TLSLD_PC && In<ELFT>::Got->addTlsIndex()) {
- AddTlsReloc(In<ELFT>::Got->getTlsIndexOff(), Target->TlsModuleIndexRel,
+ if (Expr == R_TLSLD_PC && InX::Got->addTlsIndex()) {
+ AddTlsReloc(InX::Got->getTlsIndexOff(), Target->TlsModuleIndexRel,
NeedDynId ? nullptr : &Body, NeedDynId);
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
return 1;
@@ -176,8 +176,8 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body,
// the module index and offset of symbol in TLS block we can fill these in
// using static GOT relocations.
if (Expr == R_TLSGD_PC) {
- if (In<ELFT>::Got->addDynTlsEntry(Body)) {
- uint64_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
+ if (InX::Got->addDynTlsEntry(Body)) {
+ uint64_t Off = InX::Got->getGlobalDynOffset(Body);
AddTlsReloc(Off, Target->TlsModuleIndexRel, &Body, NeedDynId);
AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Body,
NeedDynOff);
@@ -207,10 +207,10 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
bool IsPreemptible = isPreemptible(Body, Type);
if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) &&
Config->Shared) {
- if (In<ELFT>::Got->addDynTlsEntry(Body)) {
- uint64_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
- In<ELFT>::RelaDyn->addReloc({Target->TlsDescRel, In<ELFT>::Got, Off,
- !IsPreemptible, &Body, 0});
+ if (InX::Got->addDynTlsEntry(Body)) {
+ uint64_t Off = InX::Got->getGlobalDynOffset(Body);
+ In<ELFT>::RelaDyn->addReloc(
+ {Target->TlsDescRel, InX::Got, Off, !IsPreemptible, &Body, 0});
}
if (Expr != R_TLSDESC_CALL)
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
@@ -224,10 +224,10 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
{R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body});
return 2;
}
- if (In<ELFT>::Got->addTlsIndex())
- In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got,
- In<ELFT>::Got->getTlsIndexOff(), false,
- nullptr, 0});
+ if (InX::Got->addTlsIndex())
+ In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::Got,
+ InX::Got->getTlsIndexOff(), false, nullptr,
+ 0});
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
return 1;
}
@@ -242,19 +242,19 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD,
R_TLSGD_PC>(Expr)) {
if (Config->Shared) {
- if (In<ELFT>::Got->addDynTlsEntry(Body)) {
- uint64_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
+ if (InX::Got->addDynTlsEntry(Body)) {
+ uint64_t Off = InX::Got->getGlobalDynOffset(Body);
In<ELFT>::RelaDyn->addReloc(
- {Target->TlsModuleIndexRel, In<ELFT>::Got, Off, false, &Body, 0});
+ {Target->TlsModuleIndexRel, InX::Got, Off, false, &Body, 0});
// If the symbol is preemptible we need the dynamic linker to write
// the offset too.
uint64_t OffsetOff = Off + Config->Wordsize;
if (IsPreemptible)
- In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got,
- OffsetOff, false, &Body, 0});
+ In<ELFT>::RelaDyn->addReloc(
+ {Target->TlsOffsetRel, InX::Got, OffsetOff, false, &Body, 0});
else
- In<ELFT>::Got->Relocations.push_back(
+ InX::Got->Relocations.push_back(
{R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Body});
}
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
@@ -268,8 +268,8 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
{Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type,
Offset, Addend, &Body});
if (!Body.isInGot()) {
- In<ELFT>::Got->addEntry(Body);
- In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::Got,
+ InX::Got->addEntry(Body);
+ In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, InX::Got,
Body.getGotOffset(), false, &Body, 0});
}
} else {
@@ -518,7 +518,7 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
// See if this symbol is in a read-only segment. If so, preserve the symbol's
// memory protection by reserving space in the .bss.rel.ro section.
bool IsReadOnly = isReadOnly<ELFT>(SS);
- BssSection *Sec = IsReadOnly ? In<ELFT>::BssRelRo : In<ELFT>::Bss;
+ BssSection *Sec = IsReadOnly ? InX::BssRelRo : InX::Bss;
uint64_t Off = Sec->reserveSpace(SymSize, SS->getAlignment<ELFT>());
// Look through the DSO's dynamic symbol table for aliases and create a
@@ -774,7 +774,7 @@ static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt,
template <class ELFT>
static void addGotEntry(SymbolBody &Sym, bool Preemptible) {
- In<ELFT>::Got->addEntry(Sym);
+ InX::Got->addEntry(Sym);
uint64_t Off = Sym.getGotOffset();
uint32_t DynType;
@@ -792,10 +792,10 @@ static void addGotEntry(SymbolBody &Sym, bool Preemptible) {
bool Constant = !Preemptible && !(Config->Pic && !isAbsolute(Sym));
if (!Constant)
In<ELFT>::RelaDyn->addReloc(
- {DynType, In<ELFT>::Got, Off, !Preemptible, &Sym, 0});
+ {DynType, InX::Got, Off, !Preemptible, &Sym, 0});
if (Constant || (!Config->IsRela && !Preemptible))
- In<ELFT>::Got->Relocations.push_back({Expr, DynType, Off, 0, &Sym});
+ InX::Got->Relocations.push_back({Expr, DynType, Off, 0, &Sym});
}
// The reason we have to do this early scan is as follows
@@ -856,7 +856,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
// needs it to be created. Here we request for that.
if (isRelExprOneOf<R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL,
R_GOTREL_FROM_END, R_PPC_TOC>(Expr))
- In<ELFT>::Got->HasGotOffRel = true;
+ InX::Got->HasGotOffRel = true;
// Read an addend.
int64_t Addend = computeAddend<ELFT>(Rel, Sec.Data.data());
@@ -874,11 +874,11 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
// If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
if (needsPlt(Expr) && !Body.isInPlt()) {
if (Body.isGnuIFunc() && !Preemptible)
- addPltEntry(InX::Iplt, In<ELFT>::IgotPlt, In<ELFT>::RelaIplt,
+ addPltEntry(InX::Iplt, InX::IgotPlt, In<ELFT>::RelaIplt,
Target->IRelativeRel, Body, true);
else
- addPltEntry(InX::Plt, In<ELFT>::GotPlt, In<ELFT>::RelaPlt,
- Target->PltRel, Body, !Preemptible);
+ addPltEntry(InX::Plt, InX::GotPlt, In<ELFT>::RelaPlt, Target->PltRel,
+ Body, !Preemptible);
}
// Create a GOT slot if a relocation needs GOT.
@@ -891,9 +891,9 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed description:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- In<ELFT>::MipsGot->addEntry(Body, Addend, Expr);
+ InX::MipsGot->addEntry(Body, Addend, Expr);
if (Body.isTls() && Body.isPreemptible())
- In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::MipsGot,
+ In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, InX::MipsGot,
Body.getGotOffset(), false, &Body, 0});
} else if (!Body.isInGot()) {
addGotEntry<ELFT>(Body, Preemptible);
@@ -927,7 +927,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
// a dynamic relocation.
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19
if (Config->EMachine == EM_MIPS)
- In<ELFT>::MipsGot->addEntry(Body, Addend, Expr);
+ InX::MipsGot->addEntry(Body, Addend, Expr);
continue;
}
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
index 032ecd50f3e3..f1bc245c9256 100644
--- a/ELF/ScriptParser.cpp
+++ b/ELF/ScriptParser.cpp
@@ -639,7 +639,7 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) {
// We are compatible with ld.gold because it's easier to implement.
uint32_t ScriptParser::parseFill(StringRef Tok) {
uint32_t V = 0;
- if (Tok.getAsInteger(0, V))
+ if (!to_integer(Tok, V))
setError("invalid filler expression: " + Tok);
uint32_t Buf;
@@ -778,23 +778,23 @@ static Optional<uint64_t> parseInt(StringRef Tok) {
// Hexadecimal
uint64_t Val;
- if (Tok.startswith_lower("0x") && !Tok.substr(2).getAsInteger(16, Val))
+ if (Tok.startswith_lower("0x") && to_integer(Tok.substr(2), Val, 16))
return Val;
- if (Tok.endswith_lower("H") && !Tok.drop_back().getAsInteger(16, Val))
+ if (Tok.endswith_lower("H") && to_integer(Tok.drop_back(), Val, 16))
return Val;
// Decimal
if (Tok.endswith_lower("K")) {
- if (Tok.drop_back().getAsInteger(10, Val))
+ if (!to_integer(Tok.drop_back(), Val, 10))
return None;
return Val * 1024;
}
if (Tok.endswith_lower("M")) {
- if (Tok.drop_back().getAsInteger(10, Val))
+ if (!to_integer(Tok.drop_back(), Val, 10))
return None;
return Val * 1024 * 1024;
}
- if (Tok.getAsInteger(10, Val))
+ if (!to_integer(Tok, Val, 10))
return None;
return Val;
}
@@ -900,10 +900,22 @@ Expr ScriptParser::readPrimary() {
StringRef Name = readParenLiteral();
return [=] { return Script->isDefined(Name) ? 1 : 0; };
}
+ if (Tok == "LENGTH") {
+ StringRef Name = readParenLiteral();
+ if (Script->Opt.MemoryRegions.count(Name) == 0)
+ setError("memory region not defined: " + Name);
+ return [=] { return Script->Opt.MemoryRegions[Name].Length; };
+ }
if (Tok == "LOADADDR") {
StringRef Name = readParenLiteral();
return [=] { return Script->getOutputSection(Location, Name)->getLMA(); };
}
+ if (Tok == "ORIGIN") {
+ StringRef Name = readParenLiteral();
+ if (Script->Opt.MemoryRegions.count(Name) == 0)
+ setError("memory region not defined: " + Name);
+ return [=] { return Script->Opt.MemoryRegions[Name].Origin; };
+ }
if (Tok == "SEGMENT_START") {
expect("(");
skip();
diff --git a/ELF/Strings.cpp b/ELF/Strings.cpp
index 29760b492ba9..2e88bfba0fc1 100644
--- a/ELF/Strings.cpp
+++ b/ELF/Strings.cpp
@@ -46,7 +46,7 @@ int elf::getPriority(StringRef S) {
if (Pos == StringRef::npos)
return 65536;
int V;
- if (S.substr(Pos + 1).getAsInteger(10, V))
+ if (!to_integer(S.substr(Pos + 1), V, 10))
return 65536;
return V;
}
@@ -68,7 +68,7 @@ std::vector<uint8_t> elf::parseHex(StringRef S) {
StringRef B = S.substr(0, 2);
S = S.substr(2);
uint8_t H;
- if (B.getAsInteger(16, H)) {
+ if (!to_integer(B, H, 16)) {
error("not a hexadecimal value: " + B);
return {};
}
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 2090b33e8cd6..7ce1f5354b1b 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -163,8 +163,8 @@ uint64_t SymbolBody::getVA(int64_t Addend) const {
return OutVA + Addend;
}
-template <class ELFT> typename ELFT::uint SymbolBody::getGotVA() const {
- return In<ELFT>::Got->getVA() + getGotOffset();
+uint64_t SymbolBody::getGotVA() const {
+ return InX::Got->getVA() + getGotOffset();
}
uint64_t SymbolBody::getGotOffset() const {
@@ -370,11 +370,6 @@ std::string lld::toString(const SymbolBody &B) {
return B.getName();
}
-template uint32_t SymbolBody::template getGotVA<ELF32LE>() const;
-template uint32_t SymbolBody::template getGotVA<ELF32BE>() const;
-template uint64_t SymbolBody::template getGotVA<ELF64LE>() const;
-template uint64_t SymbolBody::template getGotVA<ELF64BE>() const;
-
template uint32_t SymbolBody::template getSize<ELF32LE>() const;
template uint32_t SymbolBody::template getSize<ELF32BE>() const;
template uint64_t SymbolBody::template getSize<ELF64LE>() const;
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index 39a0c0f7b4df..030527f63744 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -78,7 +78,7 @@ public:
uint64_t getVA(int64_t Addend = 0) const;
uint64_t getGotOffset() const;
- template <class ELFT> typename ELFT::uint getGotVA() const;
+ uint64_t getGotVA() const;
uint64_t getGotPltOffset() const;
uint64_t getGotPltVA() const;
uint64_t getPltVA() const;
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 9c585e41e9f0..5a2c2c37efd8 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -186,7 +186,7 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) {
Options->size = getSize();
if (!Config->Relocatable)
- Reginfo.ri_gp_value = In<ELFT>::MipsGot->getGp();
+ Reginfo.ri_gp_value = InX::MipsGot->getGp();
memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo));
}
@@ -244,7 +244,7 @@ MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo Reginfo)
template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *Buf) {
if (!Config->Relocatable)
- Reginfo.ri_gp_value = In<ELFT>::MipsGot->getGp();
+ Reginfo.ri_gp_value = InX::MipsGot->getGp();
memcpy(Buf, &Reginfo, sizeof(Reginfo));
}
@@ -293,13 +293,12 @@ InputSection *elf::createInterpSection() {
return Sec;
}
-template <class ELFT>
SymbolBody *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
uint64_t Size, InputSectionBase *Section) {
auto *S = make<DefinedRegular>(Name, /*IsLocal*/ true, STV_DEFAULT, Type,
Value, Size, Section, nullptr);
- if (In<ELFT>::SymTab)
- In<ELFT>::SymTab->addSymbol(S);
+ if (InX::SymTab)
+ InX::SymTab->addSymbol(S);
return S;
}
@@ -356,7 +355,7 @@ void BuildIdSection::computeHash(
std::vector<uint8_t> Hashes(Chunks.size() * HashSize);
// Compute hash values.
- parallelFor(0, Chunks.size(), [&](size_t I) {
+ parallelForEachN(0, Chunks.size(), [&](size_t I) {
HashFn(Hashes.data() + I * HashSize, Chunks[I]);
});
@@ -618,17 +617,16 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
}
}
-template <class ELFT>
-GotSection<ELFT>::GotSection()
+GotBaseSection::GotBaseSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
Target->GotEntrySize, ".got") {}
-template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
+void GotBaseSection::addEntry(SymbolBody &Sym) {
Sym.GotIndex = NumEntries;
++NumEntries;
}
-template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
+bool GotBaseSection::addDynTlsEntry(SymbolBody &Sym) {
if (Sym.GlobalDynIndex != -1U)
return false;
Sym.GlobalDynIndex = NumEntries;
@@ -639,7 +637,7 @@ template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
// Reserves TLS entries for a TLS module ID and a TLS block offset.
// In total it takes two GOT slots.
-template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
+bool GotBaseSection::addTlsIndex() {
if (TlsIndexOff != uint32_t(-1))
return false;
TlsIndexOff = NumEntries * Config->Wordsize;
@@ -647,21 +645,19 @@ template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
return true;
}
-template <class ELFT>
-uint64_t GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
+uint64_t GotBaseSection::getGlobalDynAddr(const SymbolBody &B) const {
return this->getVA() + B.GlobalDynIndex * Config->Wordsize;
}
-template <class ELFT>
-uint64_t GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const {
+uint64_t GotBaseSection::getGlobalDynOffset(const SymbolBody &B) const {
return B.GlobalDynIndex * Config->Wordsize;
}
-template <class ELFT> void GotSection<ELFT>::finalizeContents() {
+void GotBaseSection::finalizeContents() {
Size = NumEntries * Config->Wordsize;
}
-template <class ELFT> bool GotSection<ELFT>::empty() const {
+bool GotBaseSection::empty() const {
// If we have a relocation that is relative to GOT (such as GOTOFFREL),
// we need to emit a GOT even if it's empty.
return NumEntries == 0 && !HasGotOffRel;
@@ -1028,24 +1024,15 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() {
// Add strings to .dynstr early so that .dynstr's size will be
// fixed early.
for (StringRef S : Config->AuxiliaryList)
- add({DT_AUXILIARY, In<ELFT>::DynStrTab->addString(S)});
+ add({DT_AUXILIARY, InX::DynStrTab->addString(S)});
if (!Config->Rpath.empty())
add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
- In<ELFT>::DynStrTab->addString(Config->Rpath)});
+ InX::DynStrTab->addString(Config->Rpath)});
for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles())
if (F->isNeeded())
- add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->SoName)});
+ add({DT_NEEDED, InX::DynStrTab->addString(F->SoName)});
if (!Config->SoName.empty())
- add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)});
-
- if (!Config->Shared && !Config->Relocatable)
- add({DT_DEBUG, (uint64_t)0});
-}
-
-// Add remaining entries to complete .dynamic contents.
-template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
- if (this->Size)
- return; // Already finalized.
+ add({DT_SONAME, InX::DynStrTab->addString(Config->SoName)});
// Set DT_FLAGS and DT_FLAGS_1.
uint32_t DtFlags = 0;
@@ -1064,15 +1051,22 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
DtFlags |= DF_ORIGIN;
DtFlags1 |= DF_1_ORIGIN;
}
- if (Config->HasStaticTlsModel)
- DtFlags |= DF_STATIC_TLS;
if (DtFlags)
add({DT_FLAGS, DtFlags});
if (DtFlags1)
add({DT_FLAGS_1, DtFlags1});
- this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
+ if (!Config->Shared && !Config->Relocatable)
+ add({DT_DEBUG, (uint64_t)0});
+}
+
+// Add remaining entries to complete .dynamic contents.
+template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
+ if (this->Size)
+ return; // Already finalized.
+
+ this->Link = InX::DynStrTab->OutSec->SectionIndex;
if (In<ELFT>::RelaDyn->OutSec->Size > 0) {
bool IsRela = Config->IsRela;
add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn});
@@ -1093,18 +1087,18 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
add({DT_JMPREL, In<ELFT>::RelaPlt});
add({DT_PLTRELSZ, In<ELFT>::RelaPlt->OutSec->Size});
add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
- In<ELFT>::GotPlt});
+ InX::GotPlt});
add({DT_PLTREL, uint64_t(Config->IsRela ? DT_RELA : DT_REL)});
}
- add({DT_SYMTAB, In<ELFT>::DynSymTab});
+ add({DT_SYMTAB, InX::DynSymTab});
add({DT_SYMENT, sizeof(Elf_Sym)});
- add({DT_STRTAB, In<ELFT>::DynStrTab});
- add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()});
+ add({DT_STRTAB, InX::DynStrTab});
+ add({DT_STRSZ, InX::DynStrTab->getSize()});
if (!Config->ZText)
add({DT_TEXTREL, (uint64_t)0});
- if (In<ELFT>::GnuHashTab)
- add({DT_GNU_HASH, In<ELFT>::GnuHashTab});
+ if (InX::GnuHashTab)
+ add({DT_GNU_HASH, InX::GnuHashTab});
if (In<ELFT>::HashTab)
add({DT_HASH, In<ELFT>::HashTab});
@@ -1142,15 +1136,15 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
add({DT_MIPS_RLD_VERSION, 1});
add({DT_MIPS_FLAGS, RHF_NOTPOT});
add({DT_MIPS_BASE_ADDRESS, Config->ImageBase});
- add({DT_MIPS_SYMTABNO, In<ELFT>::DynSymTab->getNumSymbols()});
- add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getLocalEntriesNum()});
- if (const SymbolBody *B = In<ELFT>::MipsGot->getFirstGlobalEntry())
+ add({DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()});
+ add({DT_MIPS_LOCAL_GOTNO, InX::MipsGot->getLocalEntriesNum()});
+ if (const SymbolBody *B = InX::MipsGot->getFirstGlobalEntry())
add({DT_MIPS_GOTSYM, B->DynsymIndex});
else
- add({DT_MIPS_GOTSYM, In<ELFT>::DynSymTab->getNumSymbols()});
- add({DT_PLTGOT, In<ELFT>::MipsGot});
- if (In<ELFT>::MipsRldMap)
- add({DT_MIPS_RLD_MAP, In<ELFT>::MipsRldMap});
+ add({DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()});
+ add({DT_PLTGOT, InX::MipsGot});
+ if (InX::MipsRldMap)
+ add({DT_MIPS_RLD_MAP, InX::MipsRldMap});
}
this->OutSec->Link = this->Link;
@@ -1235,11 +1229,11 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
if (Config->IsRela)
P->r_addend = Rel.getAddend();
P->r_offset = Rel.getOffset();
- if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In<ELFT>::MipsGot)
+ if (Config->EMachine == EM_MIPS && Rel.getInputSec() == InX::MipsGot)
// Dynamic relocation against MIPS GOT section make deal TLS entries
// allocated in the end of the GOT. We need to adjust the offset to take
// in account 'local' and 'global' GOT entries.
- P->r_offset += In<ELFT>::MipsGot->getTlsOffset();
+ P->r_offset += InX::MipsGot->getTlsOffset();
P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->IsMips64EL);
}
@@ -1259,22 +1253,19 @@ template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
}
template <class ELFT> void RelocationSection<ELFT>::finalizeContents() {
- this->Link = In<ELFT>::DynSymTab ? In<ELFT>::DynSymTab->OutSec->SectionIndex
- : In<ELFT>::SymTab->OutSec->SectionIndex;
+ this->Link = InX::DynSymTab ? InX::DynSymTab->OutSec->SectionIndex
+ : InX::SymTab->OutSec->SectionIndex;
// Set required output section properties.
this->OutSec->Link = this->Link;
}
-template <class ELFT>
-SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec)
+SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec)
: SyntheticSection(StrTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0,
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
Config->Wordsize,
StrTabSec.isDynamic() ? ".dynsym" : ".symtab"),
- StrTabSec(StrTabSec) {
- this->Entsize = sizeof(Elf_Sym);
-}
+ StrTabSec(StrTabSec) {}
// Orders symbols according to their positions in the GOT,
// in compliance with MIPS ABI rules.
@@ -1296,7 +1287,7 @@ static bool sortMipsSymbols(const SymbolTableEntry &L,
// symbols precede global symbols, so we sort symbol entries in this
// function. (For .dynsym, we don't do that because symbols for
// dynamic linking are inherently all globals.)
-template <class ELFT> void SymbolTableSection<ELFT>::finalizeContents() {
+void SymbolTableBaseSection::finalizeContents() {
this->OutSec->Link = StrTabSec.OutSec->SectionIndex;
// If it is a .dynsym, there should be no local symbols, but we need
@@ -1306,9 +1297,9 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalizeContents() {
// Because the first symbol entry is a null entry, 1 is the first.
this->OutSec->Info = 1;
- if (In<ELFT>::GnuHashTab) {
+ if (InX::GnuHashTab) {
// NB: It also sorts Symbols to meet the GNU hash table requirements.
- In<ELFT>::GnuHashTab->addSymbols(Symbols);
+ InX::GnuHashTab->addSymbols(Symbols);
} else if (Config->EMachine == EM_MIPS) {
std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
}
@@ -1320,7 +1311,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalizeContents() {
}
}
-template <class ELFT> void SymbolTableSection<ELFT>::postThunkContents() {
+void SymbolTableBaseSection::postThunkContents() {
if (this->Type == SHT_DYNSYM)
return;
// move all local symbols before global symbols.
@@ -1333,7 +1324,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::postThunkContents() {
this->OutSec->Info = NumLocals + 1;
}
-template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
+void SymbolTableBaseSection::addSymbol(SymbolBody *B) {
// Adding a local symbol to a .dynsym is a bug.
assert(this->Type != SHT_DYNSYM || !B->isLocal());
@@ -1341,8 +1332,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
Symbols.push_back({B, StrTabSec.addString(B->getName(), HashIt)});
}
-template <class ELFT>
-size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) {
+size_t SymbolTableBaseSection::getSymbolIndex(SymbolBody *Body) {
auto I = llvm::find_if(Symbols, [&](const SymbolTableEntry &E) {
if (E.Symbol == Body)
return true;
@@ -1358,6 +1348,12 @@ size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) {
return I - Symbols.begin() + 1;
}
+template <class ELFT>
+SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec)
+ : SymbolTableBaseSection(StrTabSec) {
+ this->Entsize = sizeof(Elf_Sym);
+}
+
// Write the internal symbol table contents to the output symbol table.
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
// The first entry is a null entry as per the ELF spec.
@@ -1450,13 +1446,12 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
// DSOs very quickly. If you are sure that your dynamic linker knows
// about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a
// safe bet is to specify -hash-style=both for backward compatibilty.
-template <class ELFT>
-GnuHashTableSection<ELFT>::GnuHashTableSection()
+GnuHashTableSection::GnuHashTableSection()
: SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, Config->Wordsize, ".gnu.hash") {
}
-template <class ELFT> void GnuHashTableSection<ELFT>::finalizeContents() {
- this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
+void GnuHashTableSection::finalizeContents() {
+ this->OutSec->Link = InX::DynSymTab->OutSec->SectionIndex;
// Computes bloom filter size in word size. We want to allocate 8
// bits for each symbol. It must be a power of two.
@@ -1471,11 +1466,10 @@ template <class ELFT> void GnuHashTableSection<ELFT>::finalizeContents() {
Size += Symbols.size() * 4; // Hash values
}
-template <class ELFT>
-void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) {
+void GnuHashTableSection::writeTo(uint8_t *Buf) {
// Write a header.
write32(Buf, NBuckets, Config->Endianness);
- write32(Buf + 4, In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size(),
+ write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size(),
Config->Endianness);
write32(Buf + 8, MaskWords, Config->Endianness);
write32(Buf + 12, getShift2(), Config->Endianness);
@@ -1494,8 +1488,7 @@ void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) {
//
// [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2),
// p.9, https://www.akkadia.org/drepper/dsohowto.pdf
-template <class ELFT>
-void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *Buf) {
+void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) {
const unsigned C = Config->Wordsize * 8;
for (const Entry &Sym : Symbols) {
size_t I = (Sym.Hash / C) & (MaskWords - 1);
@@ -1506,8 +1499,7 @@ void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *Buf) {
}
}
-template <class ELFT>
-void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) {
+void GnuHashTableSection::writeHashTable(uint8_t *Buf) {
// Group symbols by hash value.
std::vector<std::vector<Entry>> Syms(NBuckets);
for (const Entry &Ent : Symbols)
@@ -1560,8 +1552,7 @@ static size_t getBucketSize(size_t NumSymbols) {
// Add symbols to this symbol hash table. Note that this function
// destructively sort a given vector -- which is needed because
// GNU-style hash table places some sorting requirements.
-template <class ELFT>
-void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolTableEntry> &V) {
+void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) {
// We cannot use 'auto' for Mid because GCC 6.1 cannot deduce
// its type correctly.
std::vector<SymbolTableEntry>::iterator Mid =
@@ -1594,15 +1585,15 @@ HashTableSection<ELFT>::HashTableSection()
}
template <class ELFT> void HashTableSection<ELFT>::finalizeContents() {
- this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
+ this->OutSec->Link = InX::DynSymTab->OutSec->SectionIndex;
unsigned NumEntries = 2; // nbucket and nchain.
- NumEntries += In<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
+ NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries.
// Create as many buckets as there are symbols.
// FIXME: This is simplistic. We can try to optimize it, but implementing
// support for SHT_GNU_HASH is probably even more profitable.
- NumEntries += In<ELFT>::DynSymTab->getNumSymbols();
+ NumEntries += InX::DynSymTab->getNumSymbols();
this->Size = NumEntries * 4;
}
@@ -1610,7 +1601,7 @@ template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
// A 32-bit integer type in the target endianness.
typedef typename ELFT::Word Elf_Word;
- unsigned NumSymbols = In<ELFT>::DynSymTab->getNumSymbols();
+ unsigned NumSymbols = InX::DynSymTab->getNumSymbols();
auto *P = reinterpret_cast<Elf_Word *>(Buf);
*P++ = NumSymbols; // nbucket
@@ -1619,7 +1610,7 @@ template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
Elf_Word *Buckets = P;
Elf_Word *Chains = P + NumSymbols;
- for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
+ for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) {
SymbolBody *Body = S.Symbol;
StringRef Name = Body->getName();
unsigned I = Body->DynsymIndex;
@@ -1706,13 +1697,14 @@ readCuList(DWARFContext &Dwarf, InputSection *Sec) {
return Ret;
}
-static InputSectionBase *findSection(ArrayRef<InputSectionBase *> Arr,
- uint64_t Offset) {
+static InputSection *findSection(ArrayRef<InputSectionBase *> Arr,
+ uint64_t Offset) {
for (InputSectionBase *S : Arr)
- if (S && S != &InputSection::Discarded)
- if (Offset >= S->getOffsetInFile() &&
- Offset < S->getOffsetInFile() + S->getSize())
- return S;
+ if (auto *IS = dyn_cast_or_null<InputSection>(S))
+ if (IS != &InputSection::Discarded && IS->Live &&
+ Offset >= IS->getOffsetInFile() &&
+ Offset < IS->getOffsetInFile() + IS->getSize())
+ return IS;
return nullptr;
}
@@ -1725,10 +1717,10 @@ readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) {
CU->collectAddressRanges(Ranges);
ArrayRef<InputSectionBase *> Sections = Sec->File->getSections();
- for (std::pair<uint64_t, uint64_t> &R : Ranges)
- if (InputSectionBase *S = findSection(Sections, R.first))
- Ret.push_back({S, R.first - S->getOffsetInFile(),
- R.second - S->getOffsetInFile(), CurrentCU});
+ for (DWARFAddressRange &R : Ranges)
+ if (InputSection *S = findSection(Sections, R.LowPC))
+ Ret.push_back({S, R.LowPC - S->getOffsetInFile(),
+ R.HighPC - S->getOffsetInFile(), CurrentCU});
++CurrentCU;
}
return Ret;
@@ -1951,11 +1943,11 @@ static StringRef getFileDefName() {
}
template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() {
- FileDefNameOff = In<ELFT>::DynStrTab->addString(getFileDefName());
+ FileDefNameOff = InX::DynStrTab->addString(getFileDefName());
for (VersionDefinition &V : Config->VersionDefinitions)
- V.NameOff = In<ELFT>::DynStrTab->addString(V.Name);
+ V.NameOff = InX::DynStrTab->addString(V.Name);
- this->OutSec->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
+ this->OutSec->Link = InX::DynStrTab->OutSec->SectionIndex;
// sh_info should be set to the number of definitions. This fact is missed in
// documentation, but confirmed by binutils community:
@@ -2008,16 +2000,16 @@ VersionTableSection<ELFT>::VersionTableSection()
template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() {
// At the moment of june 2016 GNU docs does not mention that sh_link field
// should be set, but Sun docs do. Also readelf relies on this field.
- this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
+ this->OutSec->Link = InX::DynSymTab->OutSec->SectionIndex;
}
template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const {
- return sizeof(Elf_Versym) * (In<ELFT>::DynSymTab->getSymbols().size() + 1);
+ return sizeof(Elf_Versym) * (InX::DynSymTab->getSymbols().size() + 1);
}
template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
- for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
+ for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) {
OutVersym->vs_index = S.Symbol->symbol()->VersionId;
++OutVersym;
}
@@ -2051,14 +2043,14 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
// to create one by adding it to our needed list and creating a dynstr entry
// for the soname.
if (File->VerdefMap.empty())
- Needed.push_back({File, In<ELFT>::DynStrTab->addString(File->SoName)});
+ Needed.push_back({File, InX::DynStrTab->addString(File->SoName)});
typename SharedFile<ELFT>::NeededVer &NV = File->VerdefMap[Ver];
// If we don't already know that we need an Elf_Vernaux for this Elf_Verdef,
// prepare to create one by allocating a version identifier and creating a
// dynstr entry for the version name.
if (NV.Index == 0) {
- NV.StrTab = In<ELFT>::DynStrTab->addString(File->getStringTable().data() +
- Ver->getAux()->vda_name);
+ NV.StrTab = InX::DynStrTab->addString(File->getStringTable().data() +
+ Ver->getAux()->vda_name);
NV.Index = NextIndex++;
}
SS->symbol()->VersionId = NV.Index;
@@ -2100,7 +2092,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
}
template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
- this->OutSec->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
+ this->OutSec->Link = InX::DynStrTab->OutSec->SectionIndex;
this->OutSec->Info = Needed.size();
}
@@ -2187,7 +2179,7 @@ MipsRldMapSection::MipsRldMapSection()
void MipsRldMapSection::writeTo(uint8_t *Buf) {
// Apply filler from linker script.
- Optional<uint32_t> Fill = Script->getFiller(this->Name);
+ Optional<uint32_t> Fill = Script->getFiller(this->OutSec);
if (!Fill || *Fill == 0)
return;
@@ -2245,10 +2237,14 @@ BssSection *InX::Bss;
BssSection *InX::BssRelRo;
BuildIdSection *InX::BuildId;
InputSection *InX::Common;
+SyntheticSection *InX::Dynamic;
StringTableSection *InX::DynStrTab;
+SymbolTableBaseSection *InX::DynSymTab;
InputSection *InX::Interp;
GdbIndexSection *InX::GdbIndex;
+GotBaseSection *InX::Got;
GotPltSection *InX::GotPlt;
+GnuHashTableSection *InX::GnuHashTab;
IgotPltSection *InX::IgotPlt;
MipsGotSection *InX::MipsGot;
MipsRldMapSection *InX::MipsRldMap;
@@ -2256,6 +2252,7 @@ PltSection *InX::Plt;
PltSection *InX::Iplt;
StringTableSection *InX::ShStrTab;
StringTableSection *InX::StrTab;
+SymbolTableBaseSection *InX::SymTab;
template void PltSection::addEntry<ELF32LE>(SymbolBody &Sym);
template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym);
@@ -2272,19 +2269,6 @@ template MergeInputSection *elf::createCommentSection<ELF32BE>();
template MergeInputSection *elf::createCommentSection<ELF64LE>();
template MergeInputSection *elf::createCommentSection<ELF64BE>();
-template SymbolBody *elf::addSyntheticLocal<ELF32LE>(StringRef, uint8_t,
- uint64_t, uint64_t,
- InputSectionBase *);
-template SymbolBody *elf::addSyntheticLocal<ELF32BE>(StringRef, uint8_t,
- uint64_t, uint64_t,
- InputSectionBase *);
-template SymbolBody *elf::addSyntheticLocal<ELF64LE>(StringRef, uint8_t,
- uint64_t, uint64_t,
- InputSectionBase *);
-template SymbolBody *elf::addSyntheticLocal<ELF64BE>(StringRef, uint8_t,
- uint64_t, uint64_t,
- InputSectionBase *);
-
template class elf::MipsAbiFlagsSection<ELF32LE>;
template class elf::MipsAbiFlagsSection<ELF32BE>;
template class elf::MipsAbiFlagsSection<ELF64LE>;
@@ -2320,11 +2304,6 @@ template class elf::SymbolTableSection<ELF32BE>;
template class elf::SymbolTableSection<ELF64LE>;
template class elf::SymbolTableSection<ELF64BE>;
-template class elf::GnuHashTableSection<ELF32LE>;
-template class elf::GnuHashTableSection<ELF32BE>;
-template class elf::GnuHashTableSection<ELF64LE>;
-template class elf::GnuHashTableSection<ELF64BE>;
-
template class elf::HashTableSection<ELF32LE>;
template class elf::HashTableSection<ELF32BE>;
template class elf::HashTableSection<ELF64LE>;
diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h
index 1098c58a3baf..0477c601a7df 100644
--- a/ELF/SyntheticSections.h
+++ b/ELF/SyntheticSections.h
@@ -104,10 +104,9 @@ private:
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
-template <class ELFT> class GotSection final : public SyntheticSection {
+class GotBaseSection : public SyntheticSection {
public:
- GotSection();
- void writeTo(uint8_t *Buf) override;
+ GotBaseSection();
size_t getSize() const override { return Size; }
void finalizeContents() override;
bool empty() const override;
@@ -125,12 +124,17 @@ public:
// that relies on its address.
bool HasGotOffRel = false;
-private:
+protected:
size_t NumEntries = 0;
uint32_t TlsIndexOff = -1;
uint64_t Size = 0;
};
+template <class ELFT> class GotSection final : public GotBaseSection {
+public:
+ void writeTo(uint8_t *Buf) override;
+};
+
// .note.gnu.build-id section.
class BuildIdSection : public SyntheticSection {
// First 16 bytes are a header.
@@ -401,31 +405,35 @@ struct SymbolTableEntry {
size_t StrTabOffset;
};
-template <class ELFT> class SymbolTableSection final : public SyntheticSection {
+class SymbolTableBaseSection : public SyntheticSection {
public:
- typedef typename ELFT::Sym Elf_Sym;
-
- SymbolTableSection(StringTableSection &StrTabSec);
-
+ SymbolTableBaseSection(StringTableSection &StrTabSec);
void finalizeContents() override;
void postThunkContents() override;
- void writeTo(uint8_t *Buf) override;
- size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
+ size_t getSize() const override { return getNumSymbols() * Entsize; }
void addSymbol(SymbolBody *Body);
unsigned getNumSymbols() const { return Symbols.size() + 1; }
size_t getSymbolIndex(SymbolBody *Body);
ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
-private:
+protected:
// A vector of symbols and their string table offsets.
std::vector<SymbolTableEntry> Symbols;
StringTableSection &StrTabSec;
};
+template <class ELFT>
+class SymbolTableSection final : public SymbolTableBaseSection {
+ typedef typename ELFT::Sym Elf_Sym;
+
+public:
+ SymbolTableSection(StringTableSection &StrTabSec);
+ void writeTo(uint8_t *Buf) override;
+};
+
// Outputs GNU Hash section. For detailed explanation see:
// https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
-template <class ELFT>
class GnuHashTableSection final : public SyntheticSection {
public:
GnuHashTableSection();
@@ -739,7 +747,7 @@ private:
template <class ELFT> InputSection *createCommonSection();
InputSection *createInterpSection();
template <class ELFT> MergeInputSection *createCommentSection();
-template <class ELFT>
+
SymbolBody *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
uint64_t Size, InputSectionBase *Section);
@@ -750,9 +758,13 @@ struct InX {
static BssSection *BssRelRo;
static BuildIdSection *BuildId;
static InputSection *Common;
+ static SyntheticSection *Dynamic;
static StringTableSection *DynStrTab;
+ static SymbolTableBaseSection *DynSymTab;
+ static GnuHashTableSection *GnuHashTab;
static InputSection *Interp;
static GdbIndexSection *GdbIndex;
+ static GotBaseSection *Got;
static GotPltSection *GotPlt;
static IgotPltSection *IgotPlt;
static MipsGotSection *MipsGot;
@@ -761,36 +773,27 @@ struct InX {
static PltSection *Iplt;
static StringTableSection *ShStrTab;
static StringTableSection *StrTab;
+ static SymbolTableBaseSection *SymTab;
};
template <class ELFT> struct In : public InX {
- static DynamicSection<ELFT> *Dynamic;
- static SymbolTableSection<ELFT> *DynSymTab;
static EhFrameHeader<ELFT> *EhFrameHdr;
- static GnuHashTableSection<ELFT> *GnuHashTab;
- static GotSection<ELFT> *Got;
static EhFrameSection<ELFT> *EhFrame;
static HashTableSection<ELFT> *HashTab;
static RelocationSection<ELFT> *RelaDyn;
static RelocationSection<ELFT> *RelaPlt;
static RelocationSection<ELFT> *RelaIplt;
- static SymbolTableSection<ELFT> *SymTab;
static VersionDefinitionSection<ELFT> *VerDef;
static VersionTableSection<ELFT> *VerSym;
static VersionNeedSection<ELFT> *VerNeed;
};
-template <class ELFT> DynamicSection<ELFT> *In<ELFT>::Dynamic;
-template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::DynSymTab;
template <class ELFT> EhFrameHeader<ELFT> *In<ELFT>::EhFrameHdr;
-template <class ELFT> GnuHashTableSection<ELFT> *In<ELFT>::GnuHashTab;
-template <class ELFT> GotSection<ELFT> *In<ELFT>::Got;
template <class ELFT> EhFrameSection<ELFT> *In<ELFT>::EhFrame;
template <class ELFT> HashTableSection<ELFT> *In<ELFT>::HashTab;
template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaDyn;
template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt;
template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaIplt;
-template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::SymTab;
template <class ELFT> VersionDefinitionSection<ELFT> *In<ELFT>::VerDef;
template <class ELFT> VersionTableSection<ELFT> *In<ELFT>::VerSym;
template <class ELFT> VersionNeedSection<ELFT> *In<ELFT>::VerNeed;
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index 4643c1a919aa..781d7fe3bc3f 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -351,15 +351,6 @@ X86TargetInfo::X86TargetInfo() {
RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S,
const uint8_t *Loc) const {
- // There are 4 different TLS variable models with varying degrees of
- // flexibility and performance. LocalExec and InitialExec models are fast but
- // less-flexible models. They cannot be used for dlopen(). If they are in use,
- // we set DF_STATIC_TLS in the ELF header so that the runtime can reject such
- // DSOs.
- if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 || Type == R_386_TLS_IE ||
- Type == R_386_TLS_GOTIE)
- Config->HasStaticTlsModel = true;
-
switch (Type) {
case R_386_8:
case R_386_16:
@@ -429,7 +420,7 @@ RelExpr X86TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
}
void X86TargetInfo::writeGotPltHeader(uint8_t *Buf) const {
- write32le(Buf, In<ELF32LE>::Dynamic->getVA());
+ write32le(Buf, InX::Dynamic->getVA());
}
void X86TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {
@@ -460,8 +451,8 @@ void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
};
memcpy(Buf, V, sizeof(V));
- uint32_t Ebx = In<ELF32LE>::Got->getVA() + In<ELF32LE>::Got->getSize();
- uint32_t GotPlt = In<ELF32LE>::GotPlt->getVA() - Ebx;
+ uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize();
+ uint32_t GotPlt = InX::GotPlt->getVA() - Ebx;
write32le(Buf + 2, GotPlt + 4);
write32le(Buf + 8, GotPlt + 8);
return;
@@ -473,7 +464,7 @@ void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
0x90, 0x90, 0x90, 0x90 // nop
};
memcpy(Buf, PltData, sizeof(PltData));
- uint32_t GotPlt = In<ELF32LE>::GotPlt->getVA();
+ uint32_t GotPlt = InX::GotPlt->getVA();
write32le(Buf + 2, GotPlt + 4);
write32le(Buf + 8, GotPlt + 8);
}
@@ -490,7 +481,7 @@ void X86TargetInfo::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
if (Config->Pic) {
// jmp *foo@GOT(%ebx)
- uint32_t Ebx = In<ELF32LE>::Got->getVA() + In<ELF32LE>::Got->getSize();
+ uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize();
Buf[1] = 0xa3;
write32le(Buf + 2, GotPltEntryAddr - Ebx);
} else {
@@ -718,7 +709,7 @@ void X86_64TargetInfo<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
// required, but it is documented in the psabi and the glibc dynamic linker
// seems to use it (note that this is relevant for linking ld.so, not any
// other program).
- write64le(Buf, In<ELFT>::Dynamic->getVA());
+ write64le(Buf, InX::Dynamic->getVA());
}
template <class ELFT>
@@ -736,8 +727,8 @@ void X86_64TargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
0x0f, 0x1f, 0x40, 0x00 // nop
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t GotPlt = In<ELFT>::GotPlt->getVA();
- uint64_t Plt = In<ELFT>::Plt->getVA();
+ uint64_t GotPlt = InX::GotPlt->getVA();
+ uint64_t Plt = InX::Plt->getVA();
write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8
write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16
}
@@ -760,7 +751,8 @@ void X86_64TargetInfo<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
template <class ELFT>
bool X86_64TargetInfo<ELFT>::isPicRel(uint32_t Type) const {
- return Type != R_X86_64_PC32 && Type != R_X86_64_32;
+ return Type != R_X86_64_PC32 && Type != R_X86_64_32 &&
+ Type != R_X86_64_TPOFF32;
}
template <class ELFT>
@@ -1140,7 +1132,7 @@ uint64_t getPPC64TocBase() {
// TOC starts where the first of these sections starts. We always create a
// .got when we see a relocation that uses it, so for us the start is always
// the .got.
- uint64_t TocVA = In<ELF64BE>::Got->getVA();
+ uint64_t TocVA = InX::Got->getVA();
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
// thus permitting a full 64 Kbytes segment. Note that the glibc startup
@@ -1369,7 +1361,7 @@ bool AArch64TargetInfo::isPicRel(uint32_t Type) const {
}
void AArch64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
- write64le(Buf, In<ELF64LE>::Plt->getVA());
+ write64le(Buf, InX::Plt->getVA());
}
// Page(Expr) is the page address of the expression Expr, defined
@@ -1392,8 +1384,8 @@ void AArch64TargetInfo::writePltHeader(uint8_t *Buf) const {
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t Got = In<ELF64LE>::GotPlt->getVA();
- uint64_t Plt = In<ELF64LE>::Plt->getVA();
+ uint64_t Got = InX::GotPlt->getVA();
+ uint64_t Plt = InX::Plt->getVA();
relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
getAArch64Page(Got + 16) - getAArch64Page(Plt + 4));
relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16);
@@ -1746,7 +1738,7 @@ uint32_t ARMTargetInfo::getDynRel(uint32_t Type) const {
}
void ARMTargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
- write32le(Buf, In<ELF32LE>::Plt->getVA());
+ write32le(Buf, InX::Plt->getVA());
}
void ARMTargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
@@ -1763,15 +1755,15 @@ void ARMTargetInfo::writePltHeader(uint8_t *Buf) const {
0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t GotPlt = In<ELF32LE>::GotPlt->getVA();
- uint64_t L1 = In<ELF32LE>::Plt->getVA() + 8;
+ uint64_t GotPlt = InX::GotPlt->getVA();
+ uint64_t L1 = InX::Plt->getVA() + 8;
write32le(Buf + 16, GotPlt - L1 - 8);
}
void ARMTargetInfo::addPltHeaderSymbols(InputSectionBase *ISD) const {
auto *IS = cast<InputSection>(ISD);
- addSyntheticLocal<ELF32LE>("$a", STT_NOTYPE, 0, 0, IS);
- addSyntheticLocal<ELF32LE>("$d", STT_NOTYPE, 16, 0, IS);
+ addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS);
+ addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS);
}
void ARMTargetInfo::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
@@ -1793,8 +1785,8 @@ void ARMTargetInfo::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
void ARMTargetInfo::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const {
auto *IS = cast<InputSection>(ISD);
- addSyntheticLocal<ELF32LE>("$a", STT_NOTYPE, Off, 0, IS);
- addSyntheticLocal<ELF32LE>("$d", STT_NOTYPE, Off + 12, 0, IS);
+ addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS);
+ addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);
}
bool ARMTargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
@@ -1874,7 +1866,8 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
// BLX (always unconditional) instruction to an ARM Target, select an
// unconditional BL.
write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff));
- // fall through as BL encoding is shared with B
+ // fall through as BL encoding is shared with B
+ LLVM_FALLTHROUGH;
case R_ARM_JUMP24:
case R_ARM_PC24:
case R_ARM_PLT32:
@@ -1908,7 +1901,8 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
}
// Bit 12 is 0 for BLX, 1 for BL
write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12);
- // Fall through as rest of encoding is the same as B.W
+ // Fall through as rest of encoding is the same as B.W
+ LLVM_FALLTHROUGH;
case R_ARM_THM_JUMP24:
// Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
// FIXME: Use of I1 and I2 require v6T2ops
@@ -2132,7 +2126,7 @@ uint32_t MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const {
template <class ELFT>
void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
- write32<ELFT::TargetEndianness>(Buf, In<ELFT>::Plt->getVA());
+ write32<ELFT::TargetEndianness>(Buf, InX::Plt->getVA());
}
template <endianness E, uint8_t BSIZE, uint8_t SHIFT>
@@ -2201,7 +2195,7 @@ void MipsTargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
write32<E>(Buf + 24, 0x0320f809); // jalr $25
write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2
- uint64_t GotPlt = In<ELFT>::GotPlt->getVA();
+ uint64_t GotPlt = InX::GotPlt->getVA();
writeMipsHi16<E>(Buf, GotPlt);
writeMipsLo16<E>(Buf + 4, GotPlt);
writeMipsLo16<E>(Buf + 8, GotPlt);
diff --git a/ELF/Threads.h b/ELF/Threads.h
index 897432e69f8e..e01afd4d3fc9 100644
--- a/ELF/Threads.h
+++ b/ELF/Threads.h
@@ -61,8 +61,7 @@
#include "Config.h"
-#include "lld/Core/Parallel.h"
-#include <algorithm>
+#include "llvm/Support/Parallel.h"
#include <functional>
namespace lld {
@@ -71,19 +70,17 @@ namespace elf {
template <class IterTy, class FuncTy>
void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn) {
if (Config->Threads)
- parallel_for_each(Begin, End, Fn);
+ for_each(llvm::parallel::par, Begin, End, Fn);
else
- std::for_each(Begin, End, Fn);
+ for_each(llvm::parallel::seq, Begin, End, Fn);
}
-inline void parallelFor(size_t Begin, size_t End,
- std::function<void(size_t)> Fn) {
- if (Config->Threads) {
- parallel_for(Begin, End, Fn);
- } else {
- for (size_t I = Begin; I < End; ++I)
- Fn(I);
- }
+inline void parallelForEachN(size_t Begin, size_t End,
+ std::function<void(size_t)> Fn) {
+ if (Config->Threads)
+ for_each_n(llvm::parallel::par, Begin, End, Fn);
+ else
+ for_each_n(llvm::parallel::seq, Begin, End, Fn);
}
}
}
diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp
index 307ca5df2288..80ea69663c01 100644
--- a/ELF/Thunks.cpp
+++ b/ELF/Thunks.cpp
@@ -124,10 +124,10 @@ void ARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection &IS) const {
template <class ELFT>
void ARMV7ABSLongThunk<ELFT>::addSymbols(ThunkSection &IS) {
- this->ThunkSym = addSyntheticLocal<ELFT>(
+ this->ThunkSym = addSyntheticLocal(
Saver.save("__ARMv7ABSLongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
- addSyntheticLocal<ELFT>("$a", STT_NOTYPE, this->Offset, 0, &IS);
+ addSyntheticLocal("$a", STT_NOTYPE, this->Offset, 0, &IS);
}
template <class ELFT>
@@ -145,10 +145,10 @@ void ThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection &IS) const {
template <class ELFT>
void ThumbV7ABSLongThunk<ELFT>::addSymbols(ThunkSection &IS) {
- this->ThunkSym = addSyntheticLocal<ELFT>(
+ this->ThunkSym = addSyntheticLocal(
Saver.save("__Thumbv7ABSLongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
- addSyntheticLocal<ELFT>("$t", STT_NOTYPE, this->Offset, 0, &IS);
+ addSyntheticLocal("$t", STT_NOTYPE, this->Offset, 0, &IS);
}
template <class ELFT>
@@ -168,10 +168,10 @@ void ARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection &IS) const {
template <class ELFT>
void ARMV7PILongThunk<ELFT>::addSymbols(ThunkSection &IS) {
- this->ThunkSym = addSyntheticLocal<ELFT>(
+ this->ThunkSym = addSyntheticLocal(
Saver.save("__ARMV7PILongThunk_" + this->Destination.getName()), STT_FUNC,
this->Offset, size(), &IS);
- addSyntheticLocal<ELFT>("$a", STT_NOTYPE, this->Offset, 0, &IS);
+ addSyntheticLocal("$a", STT_NOTYPE, this->Offset, 0, &IS);
}
template <class ELFT>
@@ -191,10 +191,10 @@ void ThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection &IS) const {
template <class ELFT>
void ThumbV7PILongThunk<ELFT>::addSymbols(ThunkSection &IS) {
- this->ThunkSym = addSyntheticLocal<ELFT>(
+ this->ThunkSym = addSyntheticLocal(
Saver.save("__ThumbV7PILongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
- addSyntheticLocal<ELFT>("$t", STT_NOTYPE, this->Offset, 0, &IS);
+ addSyntheticLocal("$t", STT_NOTYPE, this->Offset, 0, &IS);
}
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
@@ -212,7 +212,7 @@ void MipsThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection &) const {
}
template <class ELFT> void MipsThunk<ELFT>::addSymbols(ThunkSection &IS) {
- this->ThunkSym = addSyntheticLocal<ELFT>(
+ this->ThunkSym = addSyntheticLocal(
Saver.save("__LA25Thunk_" + this->Destination.getName()), STT_FUNC,
this->Offset, size(), &IS);
}
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 7f00e37ce7b0..4cdfce76202c 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -164,11 +164,10 @@ static void combineMergableSections() {
uint64_t Flags = MS->Flags & ~(uint64_t)(SHF_GROUP | SHF_COMPRESSED);
uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
- auto I =
- llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {
- return Sec->Name == OutsecName && Sec->Flags == Flags &&
- Sec->Alignment == Alignment;
- });
+ auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {
+ return Sec->Name == OutsecName && Sec->Flags == Flags &&
+ Sec->Alignment == Alignment;
+ });
if (I == MergeSections.end()) {
MergeSyntheticSection *Syn =
make<MergeSyntheticSection>(OutsecName, MS->Type, Flags, Alignment);
@@ -312,11 +311,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); };
- In<ELFT>::DynStrTab = make<StringTableSection>(".dynstr", true);
- In<ELFT>::Dynamic = make<DynamicSection<ELFT>>();
+ InX::DynStrTab = make<StringTableSection>(".dynstr", true);
+ InX::Dynamic = make<DynamicSection<ELFT>>();
In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>(
Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
- In<ELFT>::ShStrTab = make<StringTableSection>(".shstrtab", false);
+ InX::ShStrTab = make<StringTableSection>(".shstrtab", false);
Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);
Out::ElfHeader->Size = sizeof(Elf_Ehdr);
@@ -324,41 +323,41 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Out::ProgramHeaders->updateAlignment(Config->Wordsize);
if (needsInterpSection<ELFT>()) {
- In<ELFT>::Interp = createInterpSection();
- Add(In<ELFT>::Interp);
+ InX::Interp = createInterpSection();
+ Add(InX::Interp);
} else {
- In<ELFT>::Interp = nullptr;
+ InX::Interp = nullptr;
}
if (!Config->Relocatable)
Add(createCommentSection<ELFT>());
if (Config->Strip != StripPolicy::All) {
- In<ELFT>::StrTab = make<StringTableSection>(".strtab", false);
- In<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
+ InX::StrTab = make<StringTableSection>(".strtab", false);
+ InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab);
}
if (Config->BuildId != BuildIdKind::None) {
- In<ELFT>::BuildId = make<BuildIdSection>();
- Add(In<ELFT>::BuildId);
+ InX::BuildId = make<BuildIdSection>();
+ Add(InX::BuildId);
}
- In<ELFT>::Common = createCommonSection<ELFT>();
- if (In<ELFT>::Common)
+ InX::Common = createCommonSection<ELFT>();
+ if (InX::Common)
Add(InX::Common);
- In<ELFT>::Bss = make<BssSection>(".bss");
- Add(In<ELFT>::Bss);
- In<ELFT>::BssRelRo = make<BssSection>(".bss.rel.ro");
- Add(In<ELFT>::BssRelRo);
+ InX::Bss = make<BssSection>(".bss");
+ Add(InX::Bss);
+ InX::BssRelRo = make<BssSection>(".bss.rel.ro");
+ Add(InX::BssRelRo);
// Add MIPS-specific sections.
bool HasDynSymTab = !Symtab<ELFT>::X->getSharedFiles().empty() ||
Config->Pic || Config->ExportDynamic;
if (Config->EMachine == EM_MIPS) {
if (!Config->Shared && HasDynSymTab) {
- In<ELFT>::MipsRldMap = make<MipsRldMapSection>();
- Add(In<ELFT>::MipsRldMap);
+ InX::MipsRldMap = make<MipsRldMapSection>();
+ Add(InX::MipsRldMap);
}
if (auto *Sec = MipsAbiFlagsSection<ELFT>::create())
Add(Sec);
@@ -369,8 +368,8 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
}
if (HasDynSymTab) {
- In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
- Add(In<ELFT>::DynSymTab);
+ InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab);
+ Add(InX::DynSymTab);
In<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
Add(In<ELFT>::VerSym);
@@ -384,8 +383,8 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(In<ELFT>::VerNeed);
if (Config->GnuHash) {
- In<ELFT>::GnuHashTab = make<GnuHashTableSection<ELFT>>();
- Add(In<ELFT>::GnuHashTab);
+ InX::GnuHashTab = make<GnuHashTableSection>();
+ Add(InX::GnuHashTab);
}
if (Config->SysvHash) {
@@ -393,29 +392,29 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(In<ELFT>::HashTab);
}
- Add(In<ELFT>::Dynamic);
- Add(In<ELFT>::DynStrTab);
+ Add(InX::Dynamic);
+ Add(InX::DynStrTab);
Add(In<ELFT>::RelaDyn);
}
// Add .got. MIPS' .got is so different from the other archs,
// it has its own class.
if (Config->EMachine == EM_MIPS) {
- In<ELFT>::MipsGot = make<MipsGotSection>();
- Add(In<ELFT>::MipsGot);
+ InX::MipsGot = make<MipsGotSection>();
+ Add(InX::MipsGot);
} else {
- In<ELFT>::Got = make<GotSection<ELFT>>();
- Add(In<ELFT>::Got);
+ InX::Got = make<GotSection<ELFT>>();
+ Add(InX::Got);
}
- In<ELFT>::GotPlt = make<GotPltSection>();
- Add(In<ELFT>::GotPlt);
- In<ELFT>::IgotPlt = make<IgotPltSection>();
- Add(In<ELFT>::IgotPlt);
+ InX::GotPlt = make<GotPltSection>();
+ Add(InX::GotPlt);
+ InX::IgotPlt = make<IgotPltSection>();
+ Add(InX::IgotPlt);
if (Config->GdbIndex) {
- In<ELFT>::GdbIndex = make<GdbIndexSection>();
- Add(In<ELFT>::GdbIndex);
+ InX::GdbIndex = make<GdbIndexSection>();
+ Add(InX::GdbIndex);
}
// We always need to add rel[a].plt to output if it has entries.
@@ -431,10 +430,10 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
false /*Sort*/);
Add(In<ELFT>::RelaIplt);
- In<ELFT>::Plt = make<PltSection>(Target->PltHeaderSize);
- Add(In<ELFT>::Plt);
- In<ELFT>::Iplt = make<PltSection>(0);
- Add(In<ELFT>::Iplt);
+ InX::Plt = make<PltSection>(Target->PltHeaderSize);
+ Add(InX::Plt);
+ InX::Iplt = make<PltSection>(0);
+ Add(InX::Iplt);
if (!Config->Relocatable) {
if (Config->EhFrameHdr) {
@@ -445,11 +444,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(In<ELFT>::EhFrame);
}
- if (In<ELFT>::SymTab)
- Add(In<ELFT>::SymTab);
- Add(In<ELFT>::ShStrTab);
- if (In<ELFT>::StrTab)
- Add(In<ELFT>::StrTab);
+ if (InX::SymTab)
+ Add(InX::SymTab);
+ Add(InX::ShStrTab);
+ if (InX::StrTab)
+ Add(InX::StrTab);
}
static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,
@@ -504,7 +503,7 @@ static bool includeInSymtab(const SymbolBody &B) {
// Local symbols are not in the linker's symbol table. This function scans
// each object file's symbol table to copy local symbols to the output.
template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
- if (!In<ELFT>::SymTab)
+ if (!InX::SymTab)
return;
for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
for (SymbolBody *B : F->getLocalSymbols()) {
@@ -522,7 +521,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
SectionBase *Sec = DR->Section;
if (!shouldKeepInSymtab(Sec, B->getName(), *B))
continue;
- In<ELFT>::SymTab->addSymbol(B);
+ InX::SymTab->addSymbol(B);
}
}
}
@@ -542,43 +541,17 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
auto *Sym =
make<DefinedRegular>("", /*IsLocal=*/true, /*StOther=*/0, STT_SECTION,
/*Value=*/0, /*Size=*/0, IS, nullptr);
- In<ELFT>::SymTab->addSymbol(Sym);
+ InX::SymTab->addSymbol(Sym);
}
}
-// PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
-// we would like to make sure appear is a specific order to maximize their
-// coverage by a single signed 16-bit offset from the TOC base pointer.
-// Conversely, the special .tocbss section should be first among all SHT_NOBITS
-// sections. This will put it next to the loaded special PPC64 sections (and,
-// thus, within reach of the TOC base pointer).
-static int getPPC64SectionRank(StringRef SectionName) {
- return StringSwitch<int>(SectionName)
- .Case(".tocbss", 0)
- .Case(".branch_lt", 2)
- .Case(".toc", 3)
- .Case(".toc1", 4)
- .Case(".opd", 5)
- .Default(1);
-}
-
-// All sections with SHF_MIPS_GPREL flag should be grouped together
-// because data in these sections is addressable with a gp relative address.
-static int getMipsSectionRank(const OutputSection *S) {
- if ((S->Flags & SHF_MIPS_GPREL) == 0)
- return 0;
- if (S->Name == ".got")
- return 1;
- return 2;
-}
-
// Today's loaders have a feature to make segments read-only after
// processing dynamic relocations to enhance security. PT_GNU_RELRO
// is defined for that.
//
// This function returns true if a section needs to be put into a
// PT_GNU_RELRO segment.
-template <class ELFT> bool elf::isRelroSection(const OutputSection *Sec) {
+bool elf::isRelroSection(const OutputSection *Sec) {
if (!Config->ZRelro)
return false;
@@ -613,27 +586,27 @@ template <class ELFT> bool elf::isRelroSection(const OutputSection *Sec) {
// .got contains pointers to external symbols. They are resolved by
// the dynamic linker when a module is loaded into memory, and after
// that they are not expected to change. So, it can be in RELRO.
- if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec)
+ if (InX::Got && Sec == InX::Got->OutSec)
return true;
// .got.plt contains pointers to external function symbols. They are
// by default resolved lazily, so we usually cannot put it into RELRO.
// However, if "-z now" is given, the lazy symbol resolution is
// disabled, which enables us to put it into RELRO.
- if (Sec == In<ELFT>::GotPlt->OutSec)
+ if (Sec == InX::GotPlt->OutSec)
return Config->ZNow;
// .dynamic section contains data for the dynamic linker, and
// there's no need to write to it at runtime, so it's better to put
// it into RELRO.
- if (Sec == In<ELFT>::Dynamic->OutSec)
+ if (Sec == InX::Dynamic->OutSec)
return true;
// .bss.rel.ro is used for copy relocations for read-only symbols.
// Since the dynamic linker needs to process copy relocations, the
// section cannot be read-only, but once initialized, they shouldn't
// change.
- if (Sec == In<ELFT>::BssRelRo->OutSec)
+ if (Sec == InX::BssRelRo->OutSec)
return true;
// Sections with some special names are put into RELRO. This is a
@@ -645,105 +618,149 @@ template <class ELFT> bool elf::isRelroSection(const OutputSection *Sec) {
S == ".eh_frame" || S == ".openbsd.randomdata";
}
-template <class ELFT>
-static bool compareSectionsNonScript(const OutputSection *A,
- const OutputSection *B) {
+// We compute a rank for each section. The rank indicates where the
+// section should be placed in the file. Instead of using simple
+// numbers (0,1,2...), we use a series of flags. One for each decision
+// point when placing the section.
+// Using flags has two key properties:
+// * It is easy to check if a give branch was taken.
+// * It is easy two see how similar two ranks are (see getRankProximity).
+enum RankFlags {
+ RF_NOT_ADDR_SET = 1 << 16,
+ RF_NOT_INTERP = 1 << 15,
+ RF_NOT_ALLOC = 1 << 14,
+ RF_WRITE = 1 << 13,
+ RF_EXEC = 1 << 12,
+ RF_NON_TLS_BSS = 1 << 11,
+ RF_NON_TLS_BSS_RO = 1 << 10,
+ RF_NOT_TLS = 1 << 9,
+ RF_BSS = 1 << 8,
+ RF_PPC_NOT_TOCBSS = 1 << 7,
+ RF_PPC_OPD = 1 << 6,
+ RF_PPC_TOCL = 1 << 5,
+ RF_PPC_TOC = 1 << 4,
+ RF_PPC_BRANCH_LT = 1 << 3,
+ RF_MIPS_GPREL = 1 << 2,
+ RF_MIPS_NOT_GOT = 1 << 1
+};
+
+static unsigned getSectionRank(const OutputSection *Sec) {
+ unsigned Rank = 0;
+
+ // We want to put section specified by -T option first, so we
+ // can start assigning VA starting from them later.
+ if (Config->SectionStartMap.count(Sec->Name))
+ return Rank;
+ Rank |= RF_NOT_ADDR_SET;
+
// Put .interp first because some loaders want to see that section
// on the first page of the executable file when loaded into memory.
- bool AIsInterp = A->Name == ".interp";
- bool BIsInterp = B->Name == ".interp";
- if (AIsInterp != BIsInterp)
- return AIsInterp;
+ if (Sec->Name == ".interp")
+ return Rank;
+ Rank |= RF_NOT_INTERP;
// Allocatable sections go first to reduce the total PT_LOAD size and
// so debug info doesn't change addresses in actual code.
- bool AIsAlloc = A->Flags & SHF_ALLOC;
- bool BIsAlloc = B->Flags & SHF_ALLOC;
- if (AIsAlloc != BIsAlloc)
- return AIsAlloc;
-
- // We don't have any special requirements for the relative order of two non
- // allocatable sections.
- if (!AIsAlloc)
- return false;
-
- // We want to put section specified by -T option first, so we
- // can start assigning VA starting from them later.
- auto AAddrSetI = Config->SectionStartMap.find(A->Name);
- auto BAddrSetI = Config->SectionStartMap.find(B->Name);
- bool AHasAddrSet = AAddrSetI != Config->SectionStartMap.end();
- bool BHasAddrSet = BAddrSetI != Config->SectionStartMap.end();
- if (AHasAddrSet != BHasAddrSet)
- return AHasAddrSet;
- if (AHasAddrSet)
- return AAddrSetI->second < BAddrSetI->second;
+ if (!(Sec->Flags & SHF_ALLOC))
+ return Rank | RF_NOT_ALLOC;
// We want the read only sections first so that they go in the PT_LOAD
// covering the program headers at the start of the file.
- bool AIsWritable = A->Flags & SHF_WRITE;
- bool BIsWritable = B->Flags & SHF_WRITE;
- if (AIsWritable != BIsWritable)
- return BIsWritable;
+ if (Sec->Flags & SHF_WRITE)
+ Rank |= RF_WRITE;
- if (!Config->SingleRoRx) {
+ if (Sec->Flags & SHF_EXECINSTR) {
// For a corresponding reason, put non exec sections first (the program
// header PT_LOAD is not executable).
// We only do that if we are not using linker scripts, since with linker
// scripts ro and rx sections are in the same PT_LOAD, so their relative
// order is not important. The same applies for -no-rosegment.
- bool AIsExec = A->Flags & SHF_EXECINSTR;
- bool BIsExec = B->Flags & SHF_EXECINSTR;
- if (AIsExec != BIsExec)
- return BIsExec;
+ if ((Rank & RF_WRITE) || !Config->SingleRoRx)
+ Rank |= RF_EXEC;
}
// If we got here we know that both A and B are in the same PT_LOAD.
- bool AIsTls = A->Flags & SHF_TLS;
- bool BIsTls = B->Flags & SHF_TLS;
- bool AIsNoBits = A->Type == SHT_NOBITS;
- bool BIsNoBits = B->Type == SHT_NOBITS;
+ bool IsTls = Sec->Flags & SHF_TLS;
+ bool IsNoBits = Sec->Type == SHT_NOBITS;
// The first requirement we have is to put (non-TLS) nobits sections last. The
// reason is that the only thing the dynamic linker will see about them is a
// p_memsz that is larger than p_filesz. Seeing that it zeros the end of the
// PT_LOAD, so that has to correspond to the nobits sections.
- bool AIsNonTlsNoBits = AIsNoBits && !AIsTls;
- bool BIsNonTlsNoBits = BIsNoBits && !BIsTls;
- if (AIsNonTlsNoBits != BIsNonTlsNoBits)
- return BIsNonTlsNoBits;
+ bool IsNonTlsNoBits = IsNoBits && !IsTls;
+ if (IsNonTlsNoBits)
+ Rank |= RF_NON_TLS_BSS;
// We place nobits RelRo sections before plain r/w ones, and non-nobits RelRo
// sections after r/w ones, so that the RelRo sections are contiguous.
- bool AIsRelRo = isRelroSection<ELFT>(A);
- bool BIsRelRo = isRelroSection<ELFT>(B);
- if (AIsRelRo != BIsRelRo)
- return AIsNonTlsNoBits ? AIsRelRo : BIsRelRo;
+ bool IsRelRo = isRelroSection(Sec);
+ if (IsNonTlsNoBits && !IsRelRo)
+ Rank |= RF_NON_TLS_BSS_RO;
+ if (!IsNonTlsNoBits && IsRelRo)
+ Rank |= RF_NON_TLS_BSS_RO;
// The TLS initialization block needs to be a single contiguous block in a R/W
// PT_LOAD, so stick TLS sections directly before the other RelRo R/W
// sections. The TLS NOBITS sections are placed here as they don't take up
// virtual address space in the PT_LOAD.
- if (AIsTls != BIsTls)
- return AIsTls;
+ if (!IsTls)
+ Rank |= RF_NOT_TLS;
// Within the TLS initialization block, the non-nobits sections need to appear
// first.
- if (AIsNoBits != BIsNoBits)
- return BIsNoBits;
+ if (IsNoBits)
+ Rank |= RF_BSS;
+
+ // // Some architectures have additional ordering restrictions for sections
+ // // within the same PT_LOAD.
+ if (Config->EMachine == EM_PPC64) {
+ // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections
+ // that we would like to make sure appear is a specific order to maximize
+ // their coverage by a single signed 16-bit offset from the TOC base
+ // pointer. Conversely, the special .tocbss section should be first among
+ // all SHT_NOBITS sections. This will put it next to the loaded special
+ // PPC64 sections (and, thus, within reach of the TOC base pointer).
+ StringRef Name = Sec->Name;
+ if (Name != ".tocbss")
+ Rank |= RF_PPC_NOT_TOCBSS;
+
+ if (Name == ".opd")
+ Rank |= RF_PPC_OPD;
+
+ if (Name == ".toc1")
+ Rank |= RF_PPC_TOCL;
+
+ if (Name == ".toc")
+ Rank |= RF_PPC_TOC;
+
+ if (Name == ".branch_lt")
+ Rank |= RF_PPC_BRANCH_LT;
+ }
+ if (Config->EMachine == EM_MIPS) {
+ // All sections with SHF_MIPS_GPREL flag should be grouped together
+ // because data in these sections is addressable with a gp relative address.
+ if (Sec->Flags & SHF_MIPS_GPREL)
+ Rank |= RF_MIPS_GPREL;
- // Some architectures have additional ordering restrictions for sections
- // within the same PT_LOAD.
- if (Config->EMachine == EM_PPC64)
- return getPPC64SectionRank(A->Name) < getPPC64SectionRank(B->Name);
- if (Config->EMachine == EM_MIPS)
- return getMipsSectionRank(A) < getMipsSectionRank(B);
+ if (Sec->Name != ".got")
+ Rank |= RF_MIPS_NOT_GOT;
+ }
+ return Rank;
+}
+
+static bool compareSectionsNonScript(const OutputSection *A,
+ const OutputSection *B) {
+ if (A->SortRank != B->SortRank)
+ return A->SortRank < B->SortRank;
+ if (!(A->SortRank & RF_NOT_ADDR_SET))
+ return Config->SectionStartMap.lookup(A->Name) <
+ Config->SectionStartMap.lookup(B->Name);
return false;
}
// Output section ordering is determined by this function.
-template <class ELFT>
static bool compareSections(const OutputSection *A, const OutputSection *B) {
// For now, put sections mentioned in a linker script
// first. Sections not on linker script will have a SectionIndex of
@@ -753,7 +770,7 @@ static bool compareSections(const OutputSection *A, const OutputSection *B) {
if (AIndex != BIndex)
return AIndex < BIndex;
- return compareSectionsNonScript<ELFT>(A, B);
+ return compareSectionsNonScript(A, B);
}
// Program header entry
@@ -802,7 +819,7 @@ addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val,
// need these symbols, since IRELATIVE relocs are resolved through GOT
// and PLT. For details, see http://www.airs.com/blog/archives/403.
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
- if (In<ELFT>::DynSymTab)
+ if (InX::DynSymTab)
return;
StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
@@ -855,16 +872,19 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
// static linking the linker is required to optimize away any references to
// __tls_get_addr, so it's not defined anywhere. Create a hidden definition
// to avoid the undefined symbol error.
- if (!In<ELFT>::DynSymTab)
+ if (!InX::DynSymTab)
Symtab<ELFT>::X->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
+ // differs from the behavior implemented by GNU linker which only define
+ // this symbol if ELF headers are in the memory mapped segment.
+ addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
+
// If linker script do layout we do not need to create any standart symbols.
if (Script->Opt.HasSections)
return;
- // __ehdr_start is the location of ELF file headers.
- addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
-
auto Add = [](StringRef S) {
return addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT);
};
@@ -960,18 +980,36 @@ template <class ELFT> void Writer<ELFT>::createSections() {
Sec->assignOffsets();
}
-static bool canSharePtLoad(const OutputSection &S1, const OutputSection &S2) {
- if (!(S1.Flags & SHF_ALLOC) || !(S2.Flags & SHF_ALLOC))
- return false;
-
- bool S1IsWrite = S1.Flags & SHF_WRITE;
- bool S2IsWrite = S2.Flags & SHF_WRITE;
- if (S1IsWrite != S2IsWrite)
- return false;
+// We want to find how similar two ranks are.
+// The more branches in getSectionRank that match, the more similar they are.
+// Since each branch corresponds to a bit flag, we can just use
+// countLeadingZeros.
+static unsigned getRankProximity(OutputSection *A, OutputSection *B) {
+ return countLeadingZeros(A->SortRank ^ B->SortRank);
+}
- if (!S1IsWrite)
- return true; // RO and RX share a PT_LOAD with linker scripts.
- return (S1.Flags & SHF_EXECINSTR) == (S2.Flags & SHF_EXECINSTR);
+// We want to place orphan sections so that they share as much
+// characteristics with their neighbors as possible. For example, if
+// both are rw, or both are tls.
+template <typename ELFT>
+static std::vector<OutputSection *>::iterator
+findOrphanPos(std::vector<OutputSection *>::iterator B,
+ std::vector<OutputSection *>::iterator E) {
+ OutputSection *Sec = *E;
+
+ // Find the first element that has as close a rank as possible.
+ auto I = std::max_element(B, E, [=](OutputSection *A, OutputSection *B) {
+ return getRankProximity(Sec, A) < getRankProximity(Sec, B);
+ });
+ if (I == E)
+ return E;
+
+ // Consider all existing sections with the same proximity.
+ unsigned Proximity = getRankProximity(Sec, *I);
+ while (I != E && getRankProximity(Sec, *I) == Proximity &&
+ Sec->SortRank >= (*I)->SortRank)
+ ++I;
+ return I;
}
template <class ELFT> void Writer<ELFT>::sortSections() {
@@ -979,12 +1017,18 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// relative order for SHF_LINK_ORDER sections.
if (Config->Relocatable)
return;
+
+ if (Script->Opt.HasSections)
+ Script->adjustSectionsBeforeSorting();
+
+ for (OutputSection *Sec : OutputSections)
+ Sec->SortRank = getSectionRank(Sec);
+
if (!Script->Opt.HasSections) {
std::stable_sort(OutputSections.begin(), OutputSections.end(),
- compareSectionsNonScript<ELFT>);
+ compareSectionsNonScript);
return;
}
- Script->adjustSectionsBeforeSorting();
// The order of the sections in the script is arbitrary and may not agree with
// compareSectionsNonScript. This means that we cannot easily define a
@@ -1004,14 +1048,13 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// .d (ro) # not in script
//
// The way we define an order then is:
- // * First put script sections at the start and sort the script and
- // non-script sections independently.
+ // * First put script sections at the start and sort the script sections.
// * Move each non-script section to its preferred position. We try
// to put each section in the last position where it it can share
// a PT_LOAD.
std::stable_sort(OutputSections.begin(), OutputSections.end(),
- compareSections<ELFT>);
+ compareSections);
auto I = OutputSections.begin();
auto E = OutputSections.end();
@@ -1019,31 +1062,16 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
std::find_if(OutputSections.begin(), E,
[](OutputSection *S) { return S->SectionIndex == INT_MAX; });
while (NonScriptI != E) {
- auto BestPos = std::max_element(
- I, NonScriptI, [&](OutputSection *&A, OutputSection *&B) {
- bool ACanSharePtLoad = canSharePtLoad(**NonScriptI, *A);
- bool BCanSharePtLoad = canSharePtLoad(**NonScriptI, *B);
- if (ACanSharePtLoad != BCanSharePtLoad)
- return BCanSharePtLoad;
-
- bool ACmp = compareSectionsNonScript<ELFT>(*NonScriptI, A);
- bool BCmp = compareSectionsNonScript<ELFT>(*NonScriptI, B);
- if (ACmp != BCmp)
- return BCmp; // FIXME: missing test
-
- size_t PosA = &A - &OutputSections[0];
- size_t PosB = &B - &OutputSections[0];
- return ACmp ? PosA > PosB : PosA < PosB;
- });
-
- // max_element only returns NonScriptI if the range is empty. If the range
- // is not empty we should consider moving the the element forward one
- // position.
- if (BestPos != NonScriptI &&
- !compareSectionsNonScript<ELFT>(*NonScriptI, *BestPos))
- ++BestPos;
- std::rotate(BestPos, NonScriptI, NonScriptI + 1);
- ++NonScriptI;
+ auto Pos = findOrphanPos<ELFT>(I, NonScriptI);
+
+ // As an optimization, find all sections with the same sort rank
+ // and insert them with one rotate.
+ unsigned Rank = (*NonScriptI)->SortRank;
+ auto End = std::find_if(NonScriptI + 1, E, [=](OutputSection *Sec) {
+ return Sec->SortRank != Rank;
+ });
+ std::rotate(Pos, NonScriptI, End);
+ NonScriptI = End;
}
Script->adjustSectionsAfterSorting();
@@ -1103,8 +1131,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// It should be okay as no one seems to care about the type.
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
- if (In<ELFT>::DynSymTab)
- addRegular<ELFT>("_DYNAMIC", In<ELFT>::Dynamic, 0);
+ if (InX::DynSymTab)
+ addRegular<ELFT>("_DYNAMIC", InX::Dynamic, 0);
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
@@ -1119,10 +1147,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// we can correctly decide if a dynamic relocation is needed.
forEachRelSec(scanRelocations<ELFT>);
- if (In<ELFT>::Plt && !In<ELFT>::Plt->empty())
- In<ELFT>::Plt->addSymbols();
- if (In<ELFT>::Iplt && !In<ELFT>::Iplt->empty())
- In<ELFT>::Iplt->addSymbols();
+ if (InX::Plt && !InX::Plt->empty())
+ InX::Plt->addSymbols();
+ if (InX::Iplt && !InX::Iplt->empty())
+ InX::Iplt->addSymbols();
// Now that we have defined all possible global symbols including linker-
// synthesized ones. Visit all symbols to give the finishing touches.
@@ -1131,11 +1159,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!includeInSymtab(*Body))
continue;
- if (In<ELFT>::SymTab)
- In<ELFT>::SymTab->addSymbol(Body);
+ if (InX::SymTab)
+ InX::SymTab->addSymbol(Body);
- if (In<ELFT>::DynSymTab && S->includeInDynsym()) {
- In<ELFT>::DynSymTab->addSymbol(Body);
+ if (InX::DynSymTab && S->includeInDynsym()) {
+ InX::DynSymTab->addSymbol(Body);
if (auto *SS = dyn_cast<SharedSymbol>(Body))
if (cast<SharedFile<ELFT>>(SS->File)->isNeeded())
In<ELFT>::VerNeed->addSymbol(SS);
@@ -1161,7 +1189,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
unsigned I = 1;
for (OutputSection *Sec : OutputSections) {
Sec->SectionIndex = I++;
- Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->Name);
+ Sec->ShName = InX::ShStrTab->addString(Sec->Name);
}
// Binary and relocatable output does not have PHDRS.
@@ -1175,15 +1203,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one.
- applySynthetic({In<ELFT>::DynSymTab, In<ELFT>::Bss, In<ELFT>::BssRelRo,
- In<ELFT>::GnuHashTab, In<ELFT>::HashTab, In<ELFT>::SymTab,
- In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::VerDef,
- In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::Got,
- In<ELFT>::MipsGot, In<ELFT>::IgotPlt, In<ELFT>::GotPlt,
- In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
- In<ELFT>::Plt, In<ELFT>::Iplt, In<ELFT>::Plt,
- In<ELFT>::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed,
- In<ELFT>::Dynamic},
+ applySynthetic({InX::DynSymTab, InX::Bss, InX::BssRelRo,
+ InX::GnuHashTab, In<ELFT>::HashTab, InX::SymTab,
+ InX::ShStrTab, InX::StrTab, In<ELFT>::VerDef,
+ InX::DynStrTab, InX::GdbIndex, InX::Got,
+ InX::MipsGot, InX::IgotPlt, InX::GotPlt,
+ In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
+ InX::Plt, InX::Iplt, In<ELFT>::EhFrameHdr,
+ In<ELFT>::VerSym, In<ELFT>::VerNeed, InX::Dynamic},
[](SyntheticSection *SS) { SS->finalizeContents(); });
// Some architectures use small displacements for jump instructions.
@@ -1198,7 +1225,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// when no more Thunks are added
ThunkCreator<ELFT> TC;
if (TC.createThunks(OutputSections))
- applySynthetic({In<ELFT>::MipsGot},
+ applySynthetic({InX::MipsGot},
[](SyntheticSection *SS) { SS->updateAllocSize(); });
}
// Fill other section headers. The dynamic table is finalized
@@ -1214,7 +1241,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
[](OutputSection *S) { S->maybeCompress<ELFT>(); });
// createThunks may have added local symbols to the static symbol table
- applySynthetic({In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab},
+ applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab},
[](SyntheticSection *SS) { SS->postThunkContents(); });
}
@@ -1332,7 +1359,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
// different flags or is loaded at a discontiguous address using AT linker
// script command.
uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
- if (Script->hasLMA(Sec->Name) || Flags != NewFlags) {
+ if (Script->hasLMA(Sec) || Flags != NewFlags) {
Load = AddHdr(PT_LOAD, NewFlags);
Flags = NewFlags;
}
@@ -1349,15 +1376,15 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
Ret.push_back(std::move(TlsHdr));
// Add an entry for .dynamic.
- if (In<ELFT>::DynSymTab)
- AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags())
- ->add(In<ELFT>::Dynamic->OutSec);
+ if (InX::DynSymTab)
+ AddHdr(PT_DYNAMIC, InX::Dynamic->OutSec->getPhdrFlags())
+ ->add(InX::Dynamic->OutSec);
// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
PhdrEntry RelRo(PT_GNU_RELRO, PF_R);
for (OutputSection *Sec : OutputSections)
- if (needsPtLoad(Sec) && isRelroSection<ELFT>(Sec))
+ if (needsPtLoad(Sec) && isRelroSection(Sec))
RelRo.add(Sec);
if (RelRo.First)
Ret.push_back(std::move(RelRo));
@@ -1395,7 +1422,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
PhdrEntry *Note = nullptr;
for (OutputSection *Sec : OutputSections) {
if (Sec->Type == SHT_NOTE) {
- if (!Note || Script->hasLMA(Sec->Name))
+ if (!Note || Script->hasLMA(Sec))
Note = AddHdr(PT_NOTE, PF_R);
Note->add(Sec);
} else {
@@ -1547,7 +1574,7 @@ template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() {
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Entry))
return B->getVA();
uint64_t Addr;
- if (!Config->Entry.getAsInteger(0, Addr))
+ if (to_integer(Config->Entry, Addr))
return Addr;
// Case 4
@@ -1649,7 +1676,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
EHdr->e_phnum = Phdrs.size();
EHdr->e_shentsize = sizeof(Elf_Shdr);
EHdr->e_shnum = OutputSections.size() + 1;
- EHdr->e_shstrndx = In<ELFT>::ShStrTab->OutSec->SectionIndex;
+ EHdr->e_shstrndx = InX::ShStrTab->OutSec->SectionIndex;
if (Config->EMachine == EM_ARM)
// We don't currently use any features incompatible with EF_ARM_EABI_VER5,
@@ -1743,21 +1770,16 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
}
template <class ELFT> void Writer<ELFT>::writeBuildId() {
- if (!In<ELFT>::BuildId || !In<ELFT>::BuildId->OutSec)
+ if (!InX::BuildId || !InX::BuildId->OutSec)
return;
// Compute a hash of all sections of the output file.
uint8_t *Start = Buffer->getBufferStart();
uint8_t *End = Start + FileSize;
- In<ELFT>::BuildId->writeBuildId({Start, End});
+ InX::BuildId->writeBuildId({Start, End});
}
template void elf::writeResult<ELF32LE>();
template void elf::writeResult<ELF32BE>();
template void elf::writeResult<ELF64LE>();
template void elf::writeResult<ELF64BE>();
-
-template bool elf::isRelroSection<ELF32LE>(const OutputSection *);
-template bool elf::isRelroSection<ELF32BE>(const OutputSection *);
-template bool elf::isRelroSection<ELF64LE>(const OutputSection *);
-template bool elf::isRelroSection<ELF64BE>(const OutputSection *);
diff --git a/ELF/Writer.h b/ELF/Writer.h
index 8b965f7beddb..17fbda394a20 100644
--- a/ELF/Writer.h
+++ b/ELF/Writer.h
@@ -24,7 +24,7 @@ template <class ELFT> class ObjectFile;
template <class ELFT> class SymbolTable;
template <class ELFT> void writeResult();
template <class ELFT> void markLive();
-template <class ELFT> bool isRelroSection(const OutputSection *Sec);
+bool isRelroSection(const OutputSection *Sec);
// This describes a program header entry.
// Each contains type, access flags and range of output sections that will be