[lld] r309311 - Merge OutputSectionCommand and OutputSection.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 27 12:22:44 PDT 2017
Author: rafael
Date: Thu Jul 27 12:22:43 2017
New Revision: 309311
URL: http://llvm.org/viewvc/llvm-project?rev=309311&view=rev
Log:
Merge OutputSectionCommand and OutputSection.
This is a bit of a hack, but it is *so* convenient.
Now that we create synthetic linker scripts when none is provided, we
always have to handle paired OutputSection and OutputsectionCommand and
keep a mapping from one to the other.
This patch simplifies things by merging them and creating what used to
be OutputSectionCommands really early.
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/LinkerScript.h
lld/trunk/ELF/MapFile.cpp
lld/trunk/ELF/MapFile.h
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
lld/trunk/ELF/ScriptParser.cpp
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Jul 27 12:22:43 2017
@@ -27,7 +27,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
@@ -85,27 +84,26 @@ static SymbolBody *addRegular(SymbolAssi
return Sym->body();
}
-OutputSectionCommand *
-LinkerScript::createOutputSectionCommand(StringRef Name, StringRef Location) {
- OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name];
- OutputSectionCommand *Cmd;
- if (CmdRef && CmdRef->Location.empty()) {
+OutputSection *LinkerScript::createOutputSection(StringRef Name,
+ StringRef Location) {
+ OutputSection *&SecRef = NameToOutputSection[Name];
+ OutputSection *Sec;
+ if (SecRef && SecRef->Location.empty()) {
// There was a forward reference.
- Cmd = CmdRef;
+ Sec = SecRef;
} else {
- Cmd = make<OutputSectionCommand>(Name);
- if (!CmdRef)
- CmdRef = Cmd;
+ Sec = make<OutputSection>(Name, SHT_PROGBITS, 0);
+ if (!SecRef)
+ SecRef = Sec;
}
- Cmd->Location = Location;
- return Cmd;
+ Sec->Location = Location;
+ return Sec;
}
-OutputSectionCommand *
-LinkerScript::getOrCreateOutputSectionCommand(StringRef Name) {
- OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name];
+OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) {
+ OutputSection *&CmdRef = NameToOutputSection[Name];
if (!CmdRef)
- CmdRef = make<OutputSectionCommand>(Name);
+ CmdRef = make<OutputSection>(Name, SHT_PROGBITS, 0);
return CmdRef;
}
@@ -159,19 +157,6 @@ bool SymbolAssignment::classof(const Bas
return C->Kind == AssignmentKind;
}
-bool OutputSectionCommand::classof(const BaseCommand *C) {
- return C->Kind == OutputSectionKind;
-}
-
-// Fill [Buf, Buf + Size) with Filler.
-// This is used for linker script "=fillexp" command.
-static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
- size_t I = 0;
- for (; I + 4 < Size; I += 4)
- memcpy(Buf + I, &Filler, 4);
- memcpy(Buf + I, &Filler, Size - I);
-}
-
bool InputSectionDescription::classof(const BaseCommand *C) {
return C->Kind == InputSectionKind;
}
@@ -199,19 +184,6 @@ bool LinkerScript::shouldKeep(InputSecti
return false;
}
-// If an input string is in the form of "foo.N" where N is a number,
-// return N. Otherwise, returns 65536, which is one greater than the
-// lowest priority.
-static int getPriority(StringRef S) {
- size_t Pos = S.rfind('.');
- if (Pos == StringRef::npos)
- return 65536;
- int V;
- if (!to_integer(S.substr(Pos + 1), V, 10))
- return 65536;
- return V;
-}
-
// A helper function for the SORT() command.
static std::function<bool(InputSectionBase *, InputSectionBase *)>
getComparator(SortSectionPolicy K) {
@@ -325,7 +297,7 @@ void LinkerScript::discard(ArrayRef<Inpu
}
std::vector<InputSectionBase *>
-LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) {
+LinkerScript::createInputSectionList(OutputSection &OutCmd) {
std::vector<InputSectionBase *> Ret;
for (BaseCommand *Base : OutCmd.Commands) {
@@ -368,12 +340,12 @@ void LinkerScript::processCommands(Outpu
continue;
}
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I])) {
- std::vector<InputSectionBase *> V = createInputSectionList(*Cmd);
+ if (auto *Sec = dyn_cast<OutputSection>(Opt.Commands[I])) {
+ std::vector<InputSectionBase *> V = createInputSectionList(*Sec);
// The output section name `/DISCARD/' is special.
// Any input section assigned to it is discarded.
- if (Cmd->Name == "/DISCARD/") {
+ if (Sec->Name == "/DISCARD/") {
discard(V);
continue;
}
@@ -385,7 +357,7 @@ void LinkerScript::processCommands(Outpu
//
// Because we'll iterate over Commands many more times, the easiest
// way to "make it as if it wasn't present" is to just remove it.
- if (!matchConstraints(V, Cmd->Constraint)) {
+ if (!matchConstraints(V, Sec->Constraint)) {
for (InputSectionBase *S : V)
S->Assigned = false;
Opt.Commands.erase(Opt.Commands.begin() + I);
@@ -395,37 +367,32 @@ void LinkerScript::processCommands(Outpu
// A directive may contain symbol definitions like this:
// ".foo : { ...; bar = .; }". Handle them.
- for (BaseCommand *Base : Cmd->Commands)
+ for (BaseCommand *Base : Sec->Commands)
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base))
addSymbol(OutCmd);
// Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
// is given, input sections are aligned to that value, whether the
// given value is larger or smaller than the original section alignment.
- if (Cmd->SubalignExpr) {
- uint32_t Subalign = Cmd->SubalignExpr().getValue();
+ if (Sec->SubalignExpr) {
+ uint32_t Subalign = Sec->SubalignExpr().getValue();
for (InputSectionBase *S : V)
S->Alignment = Subalign;
}
// Add input sections to an output section.
for (InputSectionBase *S : V)
- Factory.addInputSec(S, Cmd->Name, Cmd->Sec);
- if (OutputSection *Sec = Cmd->Sec) {
- assert(Sec->SectionIndex == INT_MAX);
- Sec->SectionIndex = I;
- if (Cmd->Noload)
- Sec->Type = SHT_NOBITS;
- SecToCommand[Sec] = Cmd;
- }
+ Factory.addInputSec(S, Sec->Name, Sec);
+ assert(Sec->SectionIndex == INT_MAX);
+ Sec->SectionIndex = I;
+ if (Sec->Noload)
+ Sec->Type = SHT_NOBITS;
}
}
CurAddressState = nullptr;
}
void LinkerScript::fabricateDefaultCommands() {
- std::vector<BaseCommand *> Commands;
-
// Define start address
uint64_t StartAddr = -1;
@@ -435,33 +402,15 @@ void LinkerScript::fabricateDefaultComma
for (auto &KV : Config->SectionStartMap)
StartAddr = std::min(StartAddr, KV.second);
- Commands.push_back(make<SymbolAssignment>(
- ".",
- [=] {
- return std::min(StartAddr, Config->ImageBase + elf::getHeaderSize());
- },
- ""));
-
- // For each OutputSection that needs a VA fabricate an OutputSectionCommand
- // with an InputSectionDescription describing the InputSections
- for (OutputSection *Sec : OutputSections) {
- auto *OSCmd = createOutputSectionCommand(Sec->Name, "<internal>");
- OSCmd->Sec = Sec;
- SecToCommand[Sec] = OSCmd;
-
- Commands.push_back(OSCmd);
- if (Sec->Sections.size()) {
- auto *ISD = make<InputSectionDescription>("");
- OSCmd->Commands.push_back(ISD);
- for (InputSection *ISec : Sec->Sections) {
- ISD->Sections.push_back(ISec);
- ISec->Assigned = true;
- }
- }
- }
- // SECTIONS commands run before other non SECTIONS commands
- Commands.insert(Commands.end(), Opt.Commands.begin(), Opt.Commands.end());
- Opt.Commands = std::move(Commands);
+ Opt.Commands.insert(Opt.Commands.begin(),
+ make<SymbolAssignment>(".",
+ [=] {
+ return std::min(
+ StartAddr,
+ Config->ImageBase +
+ elf::getHeaderSize());
+ },
+ ""));
}
// Add sections that didn't match any sections command.
@@ -473,35 +422,21 @@ void LinkerScript::addOrphanSections(Out
StringRef Name = getOutputSectionName(S->Name);
auto End = Opt.Commands.begin() + NumCommands;
auto I = std::find_if(Opt.Commands.begin(), End, [&](BaseCommand *Base) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- return Cmd->Name == Name;
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ return Sec->Name == Name;
return false;
});
- OutputSectionCommand *Cmd;
if (I == End) {
Factory.addInputSec(S, Name);
OutputSection *Sec = S->getOutputSection();
assert(Sec->SectionIndex == INT_MAX);
- OutputSectionCommand *&CmdRef = SecToCommand[Sec];
- if (!CmdRef) {
- CmdRef = createOutputSectionCommand(Sec->Name, "<internal>");
- CmdRef->Sec = Sec;
- Opt.Commands.push_back(CmdRef);
- }
- Cmd = CmdRef;
} else {
- 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;
- }
+ OutputSection *Sec = cast<OutputSection>(*I);
+ Factory.addInputSec(S, Name, Sec);
+ unsigned Index = std::distance(Opt.Commands.begin(), I);
+ assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index);
+ Sec->SectionIndex = Index;
}
- auto *ISD = make<InputSectionDescription>("");
- ISD->Sections.push_back(cast<InputSection>(S));
- Cmd->Commands.push_back(ISD);
}
}
@@ -605,14 +540,14 @@ void LinkerScript::process(BaseCommand &
// This function searches for a memory region to place the given output
// section in. If found, a pointer to the appropriate memory region is
// returned. Otherwise, a nullptr is returned.
-MemoryRegion *LinkerScript::findMemoryRegion(OutputSectionCommand *Cmd) {
+MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {
// If a memory region name was specified in the output section command,
// then try to find that region first.
- if (!Cmd->MemoryRegionName.empty()) {
- auto It = Opt.MemoryRegions.find(Cmd->MemoryRegionName);
+ if (!Sec->MemoryRegionName.empty()) {
+ auto It = Opt.MemoryRegions.find(Sec->MemoryRegionName);
if (It != Opt.MemoryRegions.end())
return &It->second;
- error("memory region '" + Cmd->MemoryRegionName + "' not declared");
+ error("memory region '" + Sec->MemoryRegionName + "' not declared");
return nullptr;
}
@@ -622,7 +557,6 @@ MemoryRegion *LinkerScript::findMemoryRe
if (Opt.MemoryRegions.empty())
return nullptr;
- OutputSection *Sec = Cmd->Sec;
// See if a region can be found by matching section flags.
for (auto &Pair : Opt.MemoryRegions) {
MemoryRegion &M = Pair.second;
@@ -638,22 +572,18 @@ MemoryRegion *LinkerScript::findMemoryRe
// This function assigns offsets to input sections and an output section
// for a single sections command (e.g. ".text { *(.text); }").
-void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
- OutputSection *Sec = Cmd->Sec;
- if (!Sec)
- return;
-
+void LinkerScript::assignOffsets(OutputSection *Sec) {
if (!(Sec->Flags & SHF_ALLOC))
Dot = 0;
- else if (Cmd->AddrExpr)
- setDot(Cmd->AddrExpr, Cmd->Location, false);
+ else if (Sec->AddrExpr)
+ setDot(Sec->AddrExpr, Sec->Location, false);
- if (Cmd->LMAExpr) {
+ if (Sec->LMAExpr) {
uint64_t D = Dot;
- CurAddressState->LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; };
+ CurAddressState->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; };
}
- CurAddressState->MemRegion = Cmd->MemRegion;
+ CurAddressState->MemRegion = Sec->MemRegion;
if (CurAddressState->MemRegion)
Dot = CurAddressState->MemRegionOffset[CurAddressState->MemRegion];
switchTo(Sec);
@@ -663,7 +593,7 @@ void LinkerScript::assignOffsets(OutputS
if (CurAddressState->OutSec->Flags & SHF_COMPRESSED)
return;
- for (BaseCommand *C : Cmd->Commands)
+ for (BaseCommand *C : Sec->Commands)
process(*C);
}
@@ -674,16 +604,16 @@ void LinkerScript::removeEmptyCommands()
// clutter the output.
// We instead remove trivially empty sections. The bfd linker seems even
// more aggressive at removing them.
- auto Pos = std::remove_if(
- Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- return Cmd->Sec == nullptr;
- return false;
- });
+ auto Pos = std::remove_if(Opt.Commands.begin(), Opt.Commands.end(),
+ [&](BaseCommand *Base) {
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ return !Sec->Live;
+ return false;
+ });
Opt.Commands.erase(Pos, Opt.Commands.end());
}
-static bool isAllSectionDescription(const OutputSectionCommand &Cmd) {
+static bool isAllSectionDescription(const OutputSection &Cmd) {
for (BaseCommand *Base : Cmd.Commands)
if (!isa<InputSectionDescription>(*Base))
return false;
@@ -698,32 +628,31 @@ void LinkerScript::adjustSectionsBeforeS
uint64_t Flags = SHF_ALLOC;
for (int I = 0, E = Opt.Commands.size(); I != E; ++I) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]);
- if (!Cmd)
+ auto *Sec = dyn_cast<OutputSection>(Opt.Commands[I]);
+ if (!Sec)
continue;
- if (OutputSection *Sec = Cmd->Sec) {
+ if (Sec->Live) {
Flags = Sec->Flags;
continue;
}
- if (isAllSectionDescription(*Cmd))
+ if (isAllSectionDescription(*Sec))
continue;
- auto *OutSec = make<OutputSection>(Cmd->Name, SHT_PROGBITS, Flags);
- OutSec->SectionIndex = I;
- Cmd->Sec = OutSec;
- SecToCommand[OutSec] = Cmd;
+ Sec->Live = true;
+ Sec->SectionIndex = I;
+ Sec->Flags = Flags;
}
}
void LinkerScript::adjustSectionsAfterSorting() {
// Try and find an appropriate memory region to assign offsets in.
for (BaseCommand *Base : Opt.Commands) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) {
- Cmd->MemRegion = findMemoryRegion(Cmd);
+ if (auto *Sec = dyn_cast<OutputSection>(Base)) {
+ Sec->MemRegion = findMemoryRegion(Sec);
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
- if (Cmd->AlignExpr && Cmd->Sec)
- Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue());
+ if (Sec->AlignExpr)
+ Sec->updateAlignment(Sec->AlignExpr().getValue());
}
}
@@ -743,18 +672,17 @@ void LinkerScript::adjustSectionsAfterSo
// Walk the commands and propagate the program headers to commands that don't
// explicitly specify them.
for (BaseCommand *Base : Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- if (!Cmd)
+ auto *Sec = dyn_cast<OutputSection>(Base);
+ if (!Sec)
continue;
- if (Cmd->Phdrs.empty()) {
- OutputSection *Sec = Cmd->Sec;
+ if (Sec->Phdrs.empty()) {
// To match the bfd linker script behaviour, only propagate program
// headers to sections that are allocated.
- if (Sec && (Sec->Flags & SHF_ALLOC))
- Cmd->Phdrs = DefPhdrs;
+ if (Sec->Flags & SHF_ALLOC)
+ Sec->Phdrs = DefPhdrs;
} else {
- DefPhdrs = Cmd->Phdrs;
+ DefPhdrs = Sec->Phdrs;
}
}
@@ -763,11 +691,9 @@ void LinkerScript::adjustSectionsAfterSo
void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
uint64_t Min = std::numeric_limits<uint64_t>::max();
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
Min = std::min<uint64_t>(Min, Sec->Addr);
- }
auto It = llvm::find_if(
Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_LOAD; });
@@ -785,19 +711,16 @@ void LinkerScript::allocateHeaders(std::
assert(FirstPTLoad->First == Out::ElfHeader);
OutputSection *ActualFirst = nullptr;
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections) {
if (Sec->FirstInPtLoad == Out::ElfHeader) {
ActualFirst = Sec;
break;
}
}
if (ActualFirst) {
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec->FirstInPtLoad == Out::ElfHeader)
Sec->FirstInPtLoad = ActualFirst;
- }
FirstPTLoad->First = ActualFirst;
} else {
Phdrs.erase(It);
@@ -839,8 +762,7 @@ void LinkerScript::assignAddresses() {
continue;
}
- auto *Cmd = cast<OutputSectionCommand>(Base);
- assignOffsets(Cmd);
+ assignOffsets(cast<OutputSection>(Base));
}
CurAddressState = nullptr;
}
@@ -868,10 +790,9 @@ std::vector<PhdrEntry *> LinkerScript::c
}
// Add output sections to program headers.
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
+ for (OutputSection *Sec : OutputSections) {
// Assign headers specified by linker script
- for (size_t Id : getPhdrIndices(Cmd)) {
- OutputSection *Sec = Cmd->Sec;
+ for (size_t Id : getPhdrIndices(Sec)) {
Ret[Id]->add(Sec);
if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
Ret[Id]->p_flags |= Sec->getPhdrFlags();
@@ -891,273 +812,6 @@ bool LinkerScript::ignoreInterpSection()
return true;
}
-OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const {
- auto I = SecToCommand.find(Sec);
- if (I == SecToCommand.end())
- return nullptr;
- return I->second;
-}
-
-void OutputSectionCommand::sort(std::function<int(InputSectionBase *S)> Order) {
- typedef std::pair<unsigned, InputSection *> Pair;
- auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
-
- std::vector<Pair> V;
- assert(Commands.size() == 1);
- auto *ISD = cast<InputSectionDescription>(Commands[0]);
- for (InputSection *S : ISD->Sections)
- V.push_back({Order(S), S});
- std::stable_sort(V.begin(), V.end(), Comp);
- ISD->Sections.clear();
- for (Pair &P : V)
- ISD->Sections.push_back(P.second);
-}
-
-// Returns true if S matches /Filename.?\.o$/.
-static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
- if (!S.endswith(".o"))
- return false;
- S = S.drop_back(2);
- if (S.endswith(Filename))
- return true;
- return !S.empty() && S.drop_back().endswith(Filename);
-}
-
-static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }
-static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }
-
-// .ctors and .dtors are sorted by this priority from highest to lowest.
-//
-// 1. The section was contained in crtbegin (crtbegin contains
-// some sentinel value in its .ctors and .dtors so that the runtime
-// can find the beginning of the sections.)
-//
-// 2. The section has an optional priority value in the form of ".ctors.N"
-// or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
-// they are compared as string rather than number.
-//
-// 3. The section is just ".ctors" or ".dtors".
-//
-// 4. The section was contained in crtend, which contains an end marker.
-//
-// In an ideal world, we don't need this function because .init_array and
-// .ctors are duplicate features (and .init_array is newer.) However, there
-// are too many real-world use cases of .ctors, so we had no choice to
-// support that with this rather ad-hoc semantics.
-static bool compCtors(const InputSection *A, const InputSection *B) {
- bool BeginA = isCrtbegin(A->File->getName());
- bool BeginB = isCrtbegin(B->File->getName());
- if (BeginA != BeginB)
- return BeginA;
- bool EndA = isCrtend(A->File->getName());
- bool EndB = isCrtend(B->File->getName());
- if (EndA != EndB)
- return EndB;
- StringRef X = A->Name;
- StringRef Y = B->Name;
- assert(X.startswith(".ctors") || X.startswith(".dtors"));
- assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
- X = X.substr(6);
- Y = Y.substr(6);
- if (X.empty() && Y.empty())
- return false;
- return X < Y;
-}
-
-// Sorts input sections by the special rules for .ctors and .dtors.
-// Unfortunately, the rules are different from the one for .{init,fini}_array.
-// Read the comment above.
-void OutputSectionCommand::sortCtorsDtors() {
- assert(Commands.size() == 1);
- auto *ISD = cast<InputSectionDescription>(Commands[0]);
- std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors);
-}
-
-// Sorts input sections by section name suffixes, so that .foo.N comes
-// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
-// We want to keep the original order if the priorities are the same
-// because the compiler keeps the original initialization order in a
-// translation unit and we need to respect that.
-// For more detail, read the section of the GCC's manual about init_priority.
-void OutputSectionCommand::sortInitFini() {
- // Sort sections by priority.
- sort([](InputSectionBase *S) { return getPriority(S->Name); });
-}
-
-uint32_t OutputSectionCommand::getFiller() {
- if (Filler)
- return *Filler;
- if (Sec->Flags & SHF_EXECINSTR)
- return Target->TrapInstr;
- return 0;
-}
-
-static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
- if (Size == 1)
- *Buf = Data;
- else if (Size == 2)
- write16(Buf, Data, Config->Endianness);
- else if (Size == 4)
- write32(Buf, Data, Config->Endianness);
- else if (Size == 8)
- write64(Buf, Data, Config->Endianness);
- else
- llvm_unreachable("unsupported Size argument");
-}
-
-static bool compareByFilePosition(InputSection *A, InputSection *B) {
- // Synthetic doesn't have link order dependecy, stable_sort will keep it last
- if (A->kind() == InputSectionBase::Synthetic ||
- B->kind() == InputSectionBase::Synthetic)
- return false;
- InputSection *LA = A->getLinkOrderDep();
- InputSection *LB = B->getLinkOrderDep();
- OutputSection *AOut = LA->getParent();
- OutputSection *BOut = LB->getParent();
- if (AOut != BOut)
- return AOut->SectionIndex < BOut->SectionIndex;
- return LA->OutSecOff < LB->OutSecOff;
-}
-
-template <class ELFT>
-static void finalizeShtGroup(OutputSection *OS,
- ArrayRef<InputSection *> Sections) {
- assert(Config->Relocatable && Sections.size() == 1);
-
- // sh_link field for SHT_GROUP sections should contain the section index of
- // the symbol table.
- OS->Link = InX::SymTab->getParent()->SectionIndex;
-
- // sh_info then contain index of an entry in symbol table section which
- // provides signature of the section group.
- ObjFile<ELFT> *Obj = Sections[0]->getFile<ELFT>();
- ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
- OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]);
-}
-
-template <class ELFT> void OutputSectionCommand::finalize() {
- // Link order may be distributed across several InputSectionDescriptions
- // but sort must consider them all at once.
- std::vector<InputSection **> ScriptSections;
- std::vector<InputSection *> Sections;
- for (BaseCommand *Base : Commands)
- if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
- for (InputSection *&IS : ISD->Sections) {
- ScriptSections.push_back(&IS);
- Sections.push_back(IS);
- }
-
- if ((Sec->Flags & SHF_LINK_ORDER)) {
- std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
- for (int I = 0, N = Sections.size(); I < N; ++I)
- *ScriptSections[I] = Sections[I];
-
- // We must preserve the link order dependency of sections with the
- // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
- // need to translate the InputSection sh_link to the OutputSection sh_link,
- // all InputSections in the OutputSection have the same dependency.
- if (auto *D = Sections.front()->getLinkOrderDep())
- Sec->Link = D->getParent()->SectionIndex;
- }
-
- uint32_t Type = Sec->Type;
- if (Type == SHT_GROUP) {
- finalizeShtGroup<ELFT>(Sec, Sections);
- return;
- }
-
- if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
- return;
-
- InputSection *First = Sections[0];
- if (isa<SyntheticSection>(First))
- return;
-
- Sec->Link = InX::SymTab->getParent()->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();
- Sec->Info = S->getOutputSection()->SectionIndex;
- Sec->Flags |= SHF_INFO_LINK;
-}
-
-// Compress section contents if this section contains debug info.
-template <class ELFT> void OutputSectionCommand::maybeCompress() {
- typedef typename ELFT::Chdr Elf_Chdr;
-
- // Compress only DWARF debug sections.
- if (!Config->CompressDebugSections || (Sec->Flags & SHF_ALLOC) ||
- !Name.startswith(".debug_"))
- return;
-
- // Create a section header.
- Sec->ZDebugHeader.resize(sizeof(Elf_Chdr));
- auto *Hdr = reinterpret_cast<Elf_Chdr *>(Sec->ZDebugHeader.data());
- Hdr->ch_type = ELFCOMPRESS_ZLIB;
- Hdr->ch_size = Sec->Size;
- Hdr->ch_addralign = Sec->Alignment;
-
- // Write section contents to a temporary buffer and compress it.
- std::vector<uint8_t> Buf(Sec->Size);
- writeTo<ELFT>(Buf.data());
- if (Error E = zlib::compress(toStringRef(Buf), Sec->CompressedData))
- fatal("compress failed: " + llvm::toString(std::move(E)));
-
- // Update section headers.
- Sec->Size = sizeof(Elf_Chdr) + Sec->CompressedData.size();
- Sec->Flags |= SHF_COMPRESSED;
-}
-
-template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
- if (Sec->Type == SHT_NOBITS)
- return;
-
- Sec->Loc = Buf;
-
- // If -compress-debug-section is specified and if this is a debug seciton,
- // we've already compressed section contents. If that's the case,
- // just write it down.
- if (!Sec->CompressedData.empty()) {
- memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size());
- memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(),
- Sec->CompressedData.size());
- return;
- }
-
- // Write leading padding.
- std::vector<InputSection *> Sections;
- for (BaseCommand *Cmd : Commands)
- if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
- for (InputSection *IS : ISD->Sections)
- if (IS->Live)
- Sections.push_back(IS);
- uint32_t Filler = getFiller();
- if (Filler)
- fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler);
-
- parallelForEachN(0, Sections.size(), [=](size_t I) {
- InputSection *IS = Sections[I];
- IS->writeTo<ELFT>(Buf);
-
- // Fill gaps between sections.
- if (Filler) {
- uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
- uint8_t *End;
- if (I + 1 == Sections.size())
- End = Buf + Sec->Size;
- else
- End = Buf + Sections[I + 1]->OutSecOff;
- fill(Start, End - Start, Filler);
- }
- });
-
- // Linker scripts may have BYTE()-family commands with which you
- // can write arbitrary bytes to the output. Process them if any.
- for (BaseCommand *Base : Commands)
- if (auto *Data = dyn_cast<BytesDataCommand>(Base))
- writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
-}
-
ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
if (S == ".")
return {CurAddressState->OutSec, Dot - CurAddressState->OutSec->Addr, Loc};
@@ -1177,7 +831,7 @@ static const size_t NoPhdr = -1;
// 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(OutputSectionCommand *Cmd) {
+std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Cmd) {
std::vector<size_t> Ret;
for (StringRef PhdrName : Cmd->Phdrs) {
size_t Index = getPhdrIndex(Cmd->Location, PhdrName);
@@ -1202,18 +856,3 @@ size_t LinkerScript::getPhdrIndex(const
error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");
return NoPhdr;
}
-
-template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf);
-template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf);
-template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf);
-template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf);
-
-template void OutputSectionCommand::maybeCompress<ELF32LE>();
-template void OutputSectionCommand::maybeCompress<ELF32BE>();
-template void OutputSectionCommand::maybeCompress<ELF64LE>();
-template void OutputSectionCommand::maybeCompress<ELF64BE>();
-
-template void OutputSectionCommand::finalize<ELF32LE>();
-template void OutputSectionCommand::finalize<ELF32BE>();
-template void OutputSectionCommand::finalize<ELF64LE>();
-template void OutputSectionCommand::finalize<ELF64BE>();
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Jul 27 12:22:43 2017
@@ -114,37 +114,6 @@ struct MemoryRegion {
uint32_t NegFlags;
};
-struct OutputSectionCommand : BaseCommand {
- OutputSectionCommand(StringRef Name)
- : BaseCommand(OutputSectionKind), Name(Name) {}
-
- static bool classof(const BaseCommand *C);
-
- OutputSection *Sec = nullptr;
- MemoryRegion *MemRegion = nullptr;
- StringRef Name;
- Expr AddrExpr;
- Expr AlignExpr;
- Expr LMAExpr;
- Expr SubalignExpr;
- std::vector<BaseCommand *> Commands;
- std::vector<StringRef> Phdrs;
- llvm::Optional<uint32_t> Filler;
- ConstraintKind Constraint = ConstraintKind::NoConstraint;
- std::string Location;
- std::string MemoryRegionName;
- bool Noload = false;
-
- template <class ELFT> void finalize();
- template <class ELFT> void writeTo(uint8_t *Buf);
- template <class ELFT> void maybeCompress();
- uint32_t getFiller();
-
- void sort(std::function<int(InputSectionBase *S)> Order);
- void sortInitFini();
- void sortCtorsDtors();
-};
-
// This struct represents one section match pattern in SECTIONS() command.
// It can optionally have negative match pattern for EXCLUDED_FILE command.
// Also it may be surrounded with SORT() command, so contains sorting rules.
@@ -236,8 +205,7 @@ class LinkerScript final {
std::function<uint64_t()> LMAOffset;
AddressState(const ScriptConfiguration &Opt);
};
- llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
- llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand;
+ llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection;
void assignSymbol(SymbolAssignment *Cmd, bool InSec);
void setDot(Expr E, const Twine &Loc, bool InSec);
@@ -245,13 +213,12 @@ class LinkerScript final {
std::vector<InputSection *>
computeInputSections(const InputSectionDescription *);
- std::vector<InputSectionBase *>
- createInputSectionList(OutputSectionCommand &Cmd);
+ std::vector<InputSectionBase *> createInputSectionList(OutputSection &Cmd);
- std::vector<size_t> getPhdrIndices(OutputSectionCommand *Cmd);
+ std::vector<size_t> getPhdrIndices(OutputSection *Sec);
size_t getPhdrIndex(const Twine &Loc, StringRef PhdrName);
- MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
+ MemoryRegion *findMemoryRegion(OutputSection *Sec);
void switchTo(OutputSection *Sec);
uint64_t advance(uint64_t Size, unsigned Align);
@@ -265,11 +232,9 @@ class LinkerScript final {
public:
bool ErrorOnMissingSection = false;
- OutputSectionCommand *createOutputSectionCommand(StringRef Name,
- StringRef Location);
- OutputSectionCommand *getOrCreateOutputSectionCommand(StringRef Name);
+ OutputSection *createOutputSection(StringRef Name, StringRef Location);
+ OutputSection *getOrCreateOutputSection(StringRef Name);
- OutputSectionCommand *getCmd(OutputSection *Sec) const;
bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
uint64_t getDot() { return Dot; }
void discard(ArrayRef<InputSectionBase *> V);
@@ -287,7 +252,7 @@ public:
bool ignoreInterpSection();
bool shouldKeep(InputSectionBase *S);
- void assignOffsets(OutputSectionCommand *Cmd);
+ void assignOffsets(OutputSection *Sec);
void assignAddresses();
void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);
void addSymbol(SymbolAssignment *Cmd);
Modified: lld/trunk/ELF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/MapFile.cpp (original)
+++ lld/trunk/ELF/MapFile.cpp Thu Jul 27 12:22:43 2017
@@ -99,8 +99,7 @@ getSymbolStrings(ArrayRef<DefinedRegular
return Ret;
}
-template <class ELFT>
-void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) {
+template <class ELFT> void elf::writeMapFile() {
if (Config->MapFile.empty())
return;
@@ -123,13 +122,12 @@ void elf::writeMapFile(llvm::ArrayRef<Ou
<< " Align Out In Symbol\n";
// Print out file contents.
- for (OutputSectionCommand *Cmd : Script) {
- OutputSection *OSec = Cmd->Sec;
+ for (OutputSection *OSec : OutputSections) {
writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment);
OS << OSec->Name << '\n';
// Dump symbols for each input section.
- for (BaseCommand *Base : Cmd->Commands) {
+ for (BaseCommand *Base : OSec->Commands) {
auto *ISD = dyn_cast<InputSectionDescription>(Base);
if (!ISD)
continue;
@@ -144,7 +142,7 @@ void elf::writeMapFile(llvm::ArrayRef<Ou
}
}
-template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionCommand *>);
-template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionCommand *>);
-template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionCommand *>);
-template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionCommand *>);
+template void elf::writeMapFile<ELF32LE>();
+template void elf::writeMapFile<ELF32BE>();
+template void elf::writeMapFile<ELF64LE>();
+template void elf::writeMapFile<ELF64BE>();
Modified: lld/trunk/ELF/MapFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/MapFile.h (original)
+++ lld/trunk/ELF/MapFile.h Thu Jul 27 12:22:43 2017
@@ -14,9 +14,8 @@
namespace lld {
namespace elf {
-struct OutputSectionCommand;
-template <class ELFT>
-void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script);
+class OutputSection;
+template <class ELFT> void writeMapFile();
} // namespace elf
} // namespace lld
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Jul 27 12:22:43 2017
@@ -17,6 +17,7 @@
#include "Target.h"
#include "Threads.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/Compression.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SHA1.h"
@@ -42,7 +43,6 @@ OutputSection *Out::InitArray;
OutputSection *Out::FiniArray;
std::vector<OutputSection *> elf::OutputSections;
-std::vector<OutputSectionCommand *> elf::OutputSectionCommands;
uint32_t OutputSection::getPhdrFlags() const {
uint32_t Ret = PF_R;
@@ -68,10 +68,13 @@ void OutputSection::writeHeaderTo(typena
}
OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
- : SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
+ : BaseCommand(OutputSectionKind),
+ SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
/*Info*/ 0,
/*Link*/ 0),
- SectionIndex(INT_MAX) {}
+ SectionIndex(INT_MAX) {
+ Live = false;
+}
static uint64_t updateOffset(uint64_t Off, InputSection *S) {
Off = alignTo(Off, S->Alignment);
@@ -81,7 +84,7 @@ static uint64_t updateOffset(uint64_t Of
void OutputSection::addSection(InputSection *S) {
assert(S->Live);
- Sections.push_back(S);
+ Live = true;
S->Parent = this;
this->updateAlignment(S->Alignment);
@@ -99,6 +102,14 @@ void OutputSection::addSection(InputSect
// Probably we sholuld handle that as an error. But for now we just
// pick the largest sh_entsize.
this->Entsize = std::max(this->Entsize, S->Entsize);
+
+ if (!S->Assigned) {
+ S->Assigned = true;
+ if (Commands.empty() || !isa<InputSectionDescription>(Commands.back()))
+ Commands.push_back(make<InputSectionDescription>(""));
+ auto *ISD = cast<InputSectionDescription>(Commands.back());
+ ISD->Sections.push_back(S);
+ }
}
static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) {
@@ -220,7 +231,7 @@ void OutputSectionFactory::addInputSec(I
return;
}
- if (Sec) {
+ if (Sec && Sec->Live) {
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
error("incompatible section flags for " + Sec->Name + "\n>>> " +
toString(IS) + ": 0x" + utohexstr(IS->Flags) +
@@ -238,8 +249,12 @@ void OutputSectionFactory::addInputSec(I
}
Sec->Flags |= IS->Flags;
} else {
- Sec = make<OutputSection>(OutsecName, IS->Type, IS->Flags);
- OutputSections.push_back(Sec);
+ if (!Sec) {
+ Sec = Script->createOutputSection(OutsecName, "<internal>");
+ Script->Opt.Commands.push_back(Sec);
+ }
+ Sec->Type = IS->Type;
+ Sec->Flags = IS->Flags;
}
Sec->addSection(cast<InputSection>(IS));
@@ -271,7 +286,307 @@ uint64_t elf::getHeaderSize() {
return Out::ElfHeader->Size + Out::ProgramHeaders->Size;
}
+bool OutputSection::classof(const BaseCommand *C) {
+ return C->Kind == OutputSectionKind;
+}
+
+void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) {
+ typedef std::pair<unsigned, InputSection *> Pair;
+ auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
+
+ std::vector<Pair> V;
+ assert(Commands.size() == 1);
+ auto *ISD = cast<InputSectionDescription>(Commands[0]);
+ for (InputSection *S : ISD->Sections)
+ V.push_back({Order(S), S});
+ std::stable_sort(V.begin(), V.end(), Comp);
+ ISD->Sections.clear();
+ for (Pair &P : V)
+ ISD->Sections.push_back(P.second);
+}
+
+// Fill [Buf, Buf + Size) with Filler.
+// This is used for linker script "=fillexp" command.
+static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
+ size_t I = 0;
+ for (; I + 4 < Size; I += 4)
+ memcpy(Buf + I, &Filler, 4);
+ memcpy(Buf + I, &Filler, Size - I);
+}
+
+// Compress section contents if this section contains debug info.
+template <class ELFT> void OutputSection::maybeCompress() {
+ typedef typename ELFT::Chdr Elf_Chdr;
+
+ // Compress only DWARF debug sections.
+ if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) ||
+ !Name.startswith(".debug_"))
+ return;
+
+ // Create a section header.
+ ZDebugHeader.resize(sizeof(Elf_Chdr));
+ auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data());
+ Hdr->ch_type = ELFCOMPRESS_ZLIB;
+ Hdr->ch_size = Size;
+ Hdr->ch_addralign = Alignment;
+
+ // Write section contents to a temporary buffer and compress it.
+ std::vector<uint8_t> Buf(Size);
+ writeTo<ELFT>(Buf.data());
+ if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
+ fatal("compress failed: " + llvm::toString(std::move(E)));
+
+ // Update section headers.
+ Size = sizeof(Elf_Chdr) + CompressedData.size();
+ Flags |= SHF_COMPRESSED;
+}
+
+static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
+ if (Size == 1)
+ *Buf = Data;
+ else if (Size == 2)
+ write16(Buf, Data, Config->Endianness);
+ else if (Size == 4)
+ write32(Buf, Data, Config->Endianness);
+ else if (Size == 8)
+ write64(Buf, Data, Config->Endianness);
+ else
+ llvm_unreachable("unsupported Size argument");
+}
+
+template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
+ if (Type == SHT_NOBITS)
+ return;
+
+ Loc = Buf;
+
+ // If -compress-debug-section is specified and if this is a debug seciton,
+ // we've already compressed section contents. If that's the case,
+ // just write it down.
+ if (!CompressedData.empty()) {
+ memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size());
+ memcpy(Buf + ZDebugHeader.size(), CompressedData.data(),
+ CompressedData.size());
+ return;
+ }
+
+ // Write leading padding.
+ std::vector<InputSection *> Sections;
+ for (BaseCommand *Cmd : Commands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
+ for (InputSection *IS : ISD->Sections)
+ if (IS->Live)
+ Sections.push_back(IS);
+ uint32_t Filler = getFiller();
+ if (Filler)
+ fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);
+
+ parallelForEachN(0, Sections.size(), [=](size_t I) {
+ InputSection *IS = Sections[I];
+ IS->writeTo<ELFT>(Buf);
+
+ // Fill gaps between sections.
+ if (Filler) {
+ uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
+ uint8_t *End;
+ if (I + 1 == Sections.size())
+ End = Buf + Size;
+ else
+ End = Buf + Sections[I + 1]->OutSecOff;
+ fill(Start, End - Start, Filler);
+ }
+ });
+
+ // Linker scripts may have BYTE()-family commands with which you
+ // can write arbitrary bytes to the output. Process them if any.
+ for (BaseCommand *Base : Commands)
+ if (auto *Data = dyn_cast<BytesDataCommand>(Base))
+ writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
+}
+
+static bool compareByFilePosition(InputSection *A, InputSection *B) {
+ // Synthetic doesn't have link order dependecy, stable_sort will keep it last
+ if (A->kind() == InputSectionBase::Synthetic ||
+ B->kind() == InputSectionBase::Synthetic)
+ return false;
+ InputSection *LA = A->getLinkOrderDep();
+ InputSection *LB = B->getLinkOrderDep();
+ OutputSection *AOut = LA->getParent();
+ OutputSection *BOut = LB->getParent();
+ if (AOut != BOut)
+ return AOut->SectionIndex < BOut->SectionIndex;
+ return LA->OutSecOff < LB->OutSecOff;
+}
+
+template <class ELFT>
+static void finalizeShtGroup(OutputSection *OS,
+ ArrayRef<InputSection *> Sections) {
+ assert(Config->Relocatable && Sections.size() == 1);
+
+ // sh_link field for SHT_GROUP sections should contain the section index of
+ // the symbol table.
+ OS->Link = InX::SymTab->getParent()->SectionIndex;
+
+ // sh_info then contain index of an entry in symbol table section which
+ // provides signature of the section group.
+ ObjFile<ELFT> *Obj = Sections[0]->getFile<ELFT>();
+ ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
+ OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]);
+}
+
+template <class ELFT> void OutputSection::finalize() {
+ // Link order may be distributed across several InputSectionDescriptions
+ // but sort must consider them all at once.
+ std::vector<InputSection **> ScriptSections;
+ std::vector<InputSection *> Sections;
+ for (BaseCommand *Base : Commands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
+ for (InputSection *&IS : ISD->Sections) {
+ ScriptSections.push_back(&IS);
+ Sections.push_back(IS);
+ }
+
+ if ((Flags & SHF_LINK_ORDER)) {
+ std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
+ for (int I = 0, N = Sections.size(); I < N; ++I)
+ *ScriptSections[I] = Sections[I];
+
+ // We must preserve the link order dependency of sections with the
+ // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
+ // need to translate the InputSection sh_link to the OutputSection sh_link,
+ // all InputSections in the OutputSection have the same dependency.
+ if (auto *D = Sections.front()->getLinkOrderDep())
+ Link = D->getParent()->SectionIndex;
+ }
+
+ if (Type == SHT_GROUP) {
+ finalizeShtGroup<ELFT>(this, Sections);
+ return;
+ }
+
+ if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
+ return;
+
+ InputSection *First = Sections[0];
+ if (isa<SyntheticSection>(First))
+ return;
+
+ Link = InX::SymTab->getParent()->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();
+ Info = S->getOutputSection()->SectionIndex;
+ Flags |= SHF_INFO_LINK;
+}
+
+// Returns true if S matches /Filename.?\.o$/.
+static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
+ if (!S.endswith(".o"))
+ return false;
+ S = S.drop_back(2);
+ if (S.endswith(Filename))
+ return true;
+ return !S.empty() && S.drop_back().endswith(Filename);
+}
+
+static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }
+static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }
+
+// .ctors and .dtors are sorted by this priority from highest to lowest.
+//
+// 1. The section was contained in crtbegin (crtbegin contains
+// some sentinel value in its .ctors and .dtors so that the runtime
+// can find the beginning of the sections.)
+//
+// 2. The section has an optional priority value in the form of ".ctors.N"
+// or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
+// they are compared as string rather than number.
+//
+// 3. The section is just ".ctors" or ".dtors".
+//
+// 4. The section was contained in crtend, which contains an end marker.
+//
+// In an ideal world, we don't need this function because .init_array and
+// .ctors are duplicate features (and .init_array is newer.) However, there
+// are too many real-world use cases of .ctors, so we had no choice to
+// support that with this rather ad-hoc semantics.
+static bool compCtors(const InputSection *A, const InputSection *B) {
+ bool BeginA = isCrtbegin(A->File->getName());
+ bool BeginB = isCrtbegin(B->File->getName());
+ if (BeginA != BeginB)
+ return BeginA;
+ bool EndA = isCrtend(A->File->getName());
+ bool EndB = isCrtend(B->File->getName());
+ if (EndA != EndB)
+ return EndB;
+ StringRef X = A->Name;
+ StringRef Y = B->Name;
+ assert(X.startswith(".ctors") || X.startswith(".dtors"));
+ assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
+ X = X.substr(6);
+ Y = Y.substr(6);
+ if (X.empty() && Y.empty())
+ return false;
+ return X < Y;
+}
+
+// Sorts input sections by the special rules for .ctors and .dtors.
+// Unfortunately, the rules are different from the one for .{init,fini}_array.
+// Read the comment above.
+void OutputSection::sortCtorsDtors() {
+ assert(Commands.size() == 1);
+ auto *ISD = cast<InputSectionDescription>(Commands[0]);
+ std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors);
+}
+
+// If an input string is in the form of "foo.N" where N is a number,
+// return N. Otherwise, returns 65536, which is one greater than the
+// lowest priority.
+int elf::getPriority(StringRef S) {
+ size_t Pos = S.rfind('.');
+ if (Pos == StringRef::npos)
+ return 65536;
+ int V;
+ if (!to_integer(S.substr(Pos + 1), V, 10))
+ return 65536;
+ return V;
+}
+
+// Sorts input sections by section name suffixes, so that .foo.N comes
+// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
+// We want to keep the original order if the priorities are the same
+// because the compiler keeps the original initialization order in a
+// translation unit and we need to respect that.
+// For more detail, read the section of the GCC's manual about init_priority.
+void OutputSection::sortInitFini() {
+ // Sort sections by priority.
+ sort([](InputSectionBase *S) { return getPriority(S->Name); });
+}
+
+uint32_t OutputSection::getFiller() {
+ if (Filler)
+ return *Filler;
+ if (Flags & SHF_EXECINSTR)
+ return Target->TrapInstr;
+ return 0;
+}
+
template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr);
template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr);
template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr);
template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr);
+
+template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf);
+template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf);
+template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf);
+template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf);
+
+template void OutputSection::maybeCompress<ELF32LE>();
+template void OutputSection::maybeCompress<ELF32BE>();
+template void OutputSection::maybeCompress<ELF64LE>();
+template void OutputSection::maybeCompress<ELF64BE>();
+
+template void OutputSection::finalize<ELF32LE>();
+template void OutputSection::finalize<ELF32BE>();
+template void OutputSection::finalize<ELF64LE>();
+template void OutputSection::finalize<ELF64BE>();
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Jul 27 12:22:43 2017
@@ -12,6 +12,7 @@
#include "Config.h"
#include "InputSection.h"
+#include "LinkerScript.h"
#include "Relocations.h"
#include "lld/Core/LLVM.h"
@@ -38,13 +39,14 @@ class DefinedRegular;
// It is composed of multiple InputSections.
// The writer creates multiple OutputSections and assign them unique,
// non-overlapping file offsets and VAs.
-class OutputSection final : public SectionBase {
+class OutputSection final : public BaseCommand, public SectionBase {
public:
OutputSection(StringRef Name, uint32_t Type, uint64_t Flags);
static bool classof(const SectionBase *S) {
return S->kind() == SectionBase::Output;
}
+ static bool classof(const BaseCommand *C);
uint64_t getLMA() const { return Addr + LMAOffset; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
@@ -80,7 +82,6 @@ public:
uint32_t ShName = 0;
void addSection(InputSection *S);
- std::vector<InputSection *> Sections;
// Used for implementation of --compress-debug-sections option.
std::vector<uint8_t> ZDebugHeader;
@@ -88,8 +89,33 @@ public:
// Location in the output buffer.
uint8_t *Loc = nullptr;
+
+ // The following members are normally only used in linker scripts.
+ MemoryRegion *MemRegion = nullptr;
+ Expr AddrExpr;
+ Expr AlignExpr;
+ Expr LMAExpr;
+ Expr SubalignExpr;
+ std::vector<BaseCommand *> Commands;
+ std::vector<StringRef> Phdrs;
+ llvm::Optional<uint32_t> Filler;
+ ConstraintKind Constraint = ConstraintKind::NoConstraint;
+ std::string Location;
+ std::string MemoryRegionName;
+ bool Noload = false;
+
+ template <class ELFT> void finalize();
+ template <class ELFT> void writeTo(uint8_t *Buf);
+ template <class ELFT> void maybeCompress();
+ uint32_t getFiller();
+
+ void sort(std::function<int(InputSectionBase *S)> Order);
+ void sortInitFini();
+ void sortCtorsDtors();
};
+int getPriority(StringRef S);
+
// All output sections that are handled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
@@ -146,7 +172,6 @@ uint64_t getHeaderSize();
void reportDiscarded(InputSectionBase *IS);
extern std::vector<OutputSection *> OutputSections;
-extern std::vector<OutputSectionCommand *> OutputSectionCommands;
} // namespace elf
} // namespace lld
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Jul 27 12:22:43 2017
@@ -1006,7 +1006,7 @@ void ThunkCreator::mergeThunks() {
}
}
-static uint32_t findEndOfFirstNonExec(OutputSectionCommand &Cmd) {
+static uint32_t findEndOfFirstNonExec(OutputSection &Cmd) {
for (BaseCommand *Base : Cmd.Commands)
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
for (auto *IS : ISD->Sections)
@@ -1015,11 +1015,11 @@ static uint32_t findEndOfFirstNonExec(Ou
return 0;
}
-ThunkSection *ThunkCreator::getOSThunkSec(OutputSectionCommand *Cmd,
+ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *Cmd,
std::vector<InputSection *> *ISR) {
if (CurTS == nullptr) {
uint32_t Off = findEndOfFirstNonExec(*Cmd);
- CurTS = addThunkSection(Cmd->Sec, ISR, Off);
+ CurTS = addThunkSection(Cmd, ISR, Off);
}
return CurTS;
}
@@ -1028,10 +1028,9 @@ ThunkSection *ThunkCreator::getISThunkSe
ThunkSection *TS = ThunkedSections.lookup(IS);
if (TS)
return TS;
- auto *TOS = IS->getParent();
// Find InputSectionRange within TOS that IS is in
- OutputSectionCommand *C = Script->getCmd(TOS);
+ OutputSection *C = IS->getParent();
std::vector<InputSection *> *Range = nullptr;
for (BaseCommand *BC : C->Commands)
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
@@ -1043,15 +1042,15 @@ ThunkSection *ThunkCreator::getISThunkSe
break;
}
}
- TS = addThunkSection(TOS, Range, IS->OutSecOff);
+ TS = addThunkSection(C, Range, IS->OutSecOff);
ThunkedSections[IS] = TS;
return TS;
}
-ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
+ThunkSection *ThunkCreator::addThunkSection(OutputSection *Cmd,
std::vector<InputSection *> *ISR,
uint64_t Off) {
- auto *TS = make<ThunkSection>(OS, Off);
+ auto *TS = make<ThunkSection>(Cmd, Off);
ThunkSections[ISR].push_back(TS);
return TS;
}
@@ -1074,19 +1073,18 @@ std::pair<Thunk *, bool> ThunkCreator::g
// Call Fn on every executable InputSection accessed via the linker script
// InputSectionDescription::Sections.
void ThunkCreator::forEachExecInputSection(
- ArrayRef<OutputSectionCommand *> OutputSections,
- std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
+ ArrayRef<OutputSection *> OutputSections,
+ std::function<void(OutputSection *, std::vector<InputSection *> *,
InputSection *)>
Fn) {
- for (OutputSectionCommand *Cmd : OutputSections) {
- OutputSection *OS = Cmd->Sec;
+ for (OutputSection *OS : OutputSections) {
if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
continue;
- for (BaseCommand *BC : Cmd->Commands)
+ for (BaseCommand *BC : OS->Commands)
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
CurTS = nullptr;
for (InputSection *IS : ISD->Sections)
- Fn(Cmd, &ISD->Sections, IS);
+ Fn(OS, &ISD->Sections, IS);
}
}
}
@@ -1101,8 +1099,7 @@ void ThunkCreator::forEachExecInputSecti
//
// FIXME: All Thunks are assumed to be in range of the relocation. Range
// extension Thunks are not yet supported.
-bool ThunkCreator::createThunks(
- ArrayRef<OutputSectionCommand *> OutputSections) {
+bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
if (Pass > 0)
ThunkSections.clear();
@@ -1112,7 +1109,7 @@ bool ThunkCreator::createThunks(
// We separate the creation of ThunkSections from the insertion of the
// ThunkSections back into the OutputSection as ThunkSections are not always
// inserted into the same OutputSection as the caller.
- forEachExecInputSection(OutputSections, [&](OutputSectionCommand *Cmd,
+ forEachExecInputSection(OutputSections, [&](OutputSection *Cmd,
std::vector<InputSection *> *ISR,
InputSection *IS) {
for (Relocation &Rel : IS->Relocations) {
@@ -1127,7 +1124,7 @@ bool ThunkCreator::createThunks(
// Find or create a ThunkSection for the new Thunk
ThunkSection *TS;
if (auto *TIS = T->getTargetInputSection())
- TS = getISThunkSec(TIS, Cmd->Sec);
+ TS = getISThunkSec(TIS, Cmd);
else
TS = getOSThunkSec(Cmd, ISR);
TS->addThunk(T);
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Thu Jul 27 12:22:43 2017
@@ -21,7 +21,7 @@ class SymbolBody;
class InputSection;
class InputSectionBase;
class OutputSection;
-struct OutputSectionCommand;
+class OutputSection;
// List of target-independent relocation types. Relocations read
// from files are converted to these types so that the main code
@@ -125,7 +125,7 @@ class Thunk;
class ThunkCreator {
public:
// Return true if Thunks have been added to OutputSections
- bool createThunks(ArrayRef<OutputSectionCommand *> OutputSections);
+ bool createThunks(ArrayRef<OutputSection *> OutputSections);
// The number of completed passes of createThunks this permits us
// to do one time initialization on Pass 0 and put a limit on the
@@ -134,16 +134,16 @@ public:
private:
void mergeThunks();
- ThunkSection *getOSThunkSec(OutputSectionCommand *Cmd,
+ ThunkSection *getOSThunkSec(OutputSection *Cmd,
std::vector<InputSection *> *ISR);
ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
void forEachExecInputSection(
- ArrayRef<OutputSectionCommand *> OutputSections,
- std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
+ ArrayRef<OutputSection *> OutputSections,
+ std::function<void(OutputSection *, std::vector<InputSection *> *,
InputSection *)>
Fn);
std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
- ThunkSection *addThunkSection(OutputSection *OS,
+ ThunkSection *addThunkSection(OutputSection *Cmd,
std::vector<InputSection *> *, uint64_t Off);
// Record all the available Thunks for a Symbol
llvm::DenseMap<SymbolBody *, std::vector<Thunk *>> ThunkedSymbols;
Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Thu Jul 27 12:22:43 2017
@@ -55,7 +55,7 @@ public:
private:
void addFile(StringRef Path);
- OutputSection *checkSection(OutputSectionCommand *Cmd, StringRef Loccation);
+ OutputSection *checkSection(OutputSection *Cmd, StringRef Loccation);
void readAsNeeded();
void readEntry();
@@ -76,8 +76,8 @@ private:
BytesDataCommand *readBytesDataCommand(StringRef Tok);
uint32_t readFill();
uint32_t parseFill(StringRef Tok);
- void readSectionAddressType(OutputSectionCommand *Cmd);
- OutputSectionCommand *readOutputSectionDescription(StringRef OutSec);
+ void readSectionAddressType(OutputSection *Cmd);
+ OutputSection *readOutputSectionDescription(StringRef OutSec);
std::vector<StringRef> readOutputSectionPhdrs();
InputSectionDescription *readInputSectionDescription(StringRef Tok);
StringMatcher readFilePatterns();
@@ -581,7 +581,7 @@ uint32_t ScriptParser::readFill() {
//
// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
// https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
-void ScriptParser::readSectionAddressType(OutputSectionCommand *Cmd) {
+void ScriptParser::readSectionAddressType(OutputSection *Cmd) {
if (consume("(")) {
if (consume("NOLOAD")) {
expect(")");
@@ -601,10 +601,9 @@ void ScriptParser::readSectionAddressTyp
}
}
-OutputSectionCommand *
-ScriptParser::readOutputSectionDescription(StringRef OutSec) {
- OutputSectionCommand *Cmd =
- Script->createOutputSectionCommand(OutSec, getCurrentLocation());
+OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
+ OutputSection *Cmd =
+ Script->createOutputSection(OutSec, getCurrentLocation());
if (peek() != ":")
readSectionAddressType(Cmd);
@@ -857,14 +856,11 @@ StringRef ScriptParser::readParenLiteral
return Tok;
}
-OutputSection *ScriptParser::checkSection(OutputSectionCommand *Cmd,
+OutputSection *ScriptParser::checkSection(OutputSection *Cmd,
StringRef Location) {
if (Cmd->Location.empty() && Script->ErrorOnMissingSection)
error(Location + ": undefined section " + Cmd->Name);
- if (Cmd->Sec)
- return Cmd->Sec;
- static OutputSection Dummy("", 0, 0);
- return &Dummy;
+ return Cmd;
}
Expr ScriptParser::readPrimary() {
@@ -895,7 +891,7 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "ADDR") {
StringRef Name = readParenLiteral();
- OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+ OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
return [=]() -> ExprValue {
return {checkSection(Cmd, Location), 0, Location};
};
@@ -916,7 +912,7 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "ALIGNOF") {
StringRef Name = readParenLiteral();
- OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+ OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
return [=] { return checkSection(Cmd, Location)->Alignment; };
}
if (Tok == "ASSERT")
@@ -962,7 +958,7 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "LOADADDR") {
StringRef Name = readParenLiteral();
- OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+ OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
return [=] { return checkSection(Cmd, Location)->getLMA(); };
}
if (Tok == "ORIGIN") {
@@ -981,11 +977,11 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "SIZEOF") {
StringRef Name = readParenLiteral();
- OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+ OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
// Linker script does not create an output section if its content is empty.
// We want to allow SIZEOF(.foo) where .foo is a section which happened to
// be empty.
- return [=] { return Cmd->Sec ? Cmd->Sec->Size : 0; };
+ return [=] { return Cmd->Size; };
}
if (Tok == "SIZEOF_HEADERS")
return [=] { return elf::getHeaderSize(); };
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Jul 27 12:22:43 2017
@@ -2282,7 +2282,7 @@ void ARMExidxSentinelSection::writeTo(ui
// sentinel last. We need to find the InputSection that precedes the
// sentinel. By construction the Sentinel is in the last
// InputSectionDescription as the InputSection that precedes it.
- OutputSectionCommand *C = Script->getCmd(getParent());
+ OutputSection *C = getParent();
auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(),
[](const BaseCommand *Base) {
return isa<InputSectionDescription>(Base);
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Jul 27 12:22:43 2017
@@ -46,7 +46,6 @@ public:
void run();
private:
- void clearOutputSections();
void createSyntheticSections();
void copyLocalSymbols();
void addSectionSymbols();
@@ -79,8 +78,7 @@ private:
void addStartEndSymbols();
void addStartStopSymbols(OutputSection *Sec);
uint64_t getEntryAddr();
- OutputSection *findSectionInScript(StringRef Name);
- OutputSectionCommand *findSectionCommand(StringRef Name);
+ OutputSection *findSection(StringRef Name);
std::vector<PhdrEntry *> Phdrs;
@@ -150,15 +148,6 @@ template <class ELFT> static void combin
V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
}
-template <class ELFT> void Writer<ELFT>::clearOutputSections() {
- // Clear the OutputSections to make sure it is not used anymore. Any
- // code from this point on should be using the linker script
- // commands.
- for (OutputSection *Sec : OutputSections)
- Sec->Sections.clear();
- OutputSections.clear();
-}
-
// The main function of the writer.
template <class ELFT> void Writer<ELFT>::run() {
// Create linker-synthesized sections such as .got or .plt.
@@ -188,7 +177,6 @@ template <class ELFT> void Writer<ELFT>:
Script->processCommands(Factory);
createSections();
}
- clearOutputSections();
if (Config->Discard != DiscardPolicy::All)
copyLocalSymbols();
@@ -210,9 +198,8 @@ template <class ELFT> void Writer<ELFT>:
// If -compressed-debug-sections is specified, we need to compress
// .debug_* sections. Do it right now because it changes the size of
// output sections.
- parallelForEach(
- OutputSectionCommands.begin(), OutputSectionCommands.end(),
- [](OutputSectionCommand *Cmd) { Cmd->maybeCompress<ELFT>(); });
+ parallelForEach(OutputSections.begin(), OutputSections.end(),
+ [](OutputSection *Sec) { Sec->maybeCompress<ELFT>(); });
Script->assignAddresses();
Script->allocateHeaders(Phdrs);
@@ -230,8 +217,8 @@ template <class ELFT> void Writer<ELFT>:
setPhdrs();
if (Config->Relocatable) {
- for (OutputSectionCommand *Cmd : OutputSectionCommands)
- Cmd->Sec->Addr = 0;
+ for (OutputSection *Sec : OutputSections)
+ Sec->Addr = 0;
} else {
fixPredefinedSymbols();
}
@@ -258,7 +245,7 @@ template <class ELFT> void Writer<ELFT>:
return;
// Handle -Map option.
- writeMapFile<ELFT>(OutputSectionCommands);
+ writeMapFile<ELFT>();
if (ErrorCount)
return;
@@ -496,15 +483,15 @@ template <class ELFT> void Writer<ELFT>:
// Create one STT_SECTION symbol for each output section we might
// have a relocation with.
for (BaseCommand *Base : Script->Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- if (!Cmd)
+ auto *Sec = dyn_cast<OutputSection>(Base);
+ if (!Sec)
continue;
- auto I = llvm::find_if(Cmd->Commands, [](BaseCommand *Base) {
+ auto I = llvm::find_if(Sec->Commands, [](BaseCommand *Base) {
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
return !ISD->Sections.empty();
return false;
});
- if (I == Cmd->Commands.end())
+ if (I == Sec->Commands.end())
continue;
InputSection *IS = cast<InputSectionDescription>(*I)->Sections[0];
if (isa<SyntheticSection>(IS) || IS->Type == SHT_REL ||
@@ -735,8 +722,8 @@ static unsigned getSectionRank(const Out
}
static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) {
- const OutputSection *A = cast<OutputSectionCommand>(ACmd)->Sec;
- const OutputSection *B = cast<OutputSectionCommand>(BCmd)->Sec;
+ const OutputSection *A = cast<OutputSection>(ACmd);
+ const OutputSection *B = cast<OutputSection>(BCmd);
if (A->SortRank != B->SortRank)
return A->SortRank < B->SortRank;
if (!(A->SortRank & RF_NOT_ADDR_SET))
@@ -867,13 +854,13 @@ template <class ELFT> void Writer<ELFT>:
// Sort input sections by section name suffixes for
// __attribute__((init_priority(N))).
-static void sortInitFini(OutputSectionCommand *Cmd) {
+static void sortInitFini(OutputSection *Cmd) {
if (Cmd)
Cmd->sortInitFini();
}
// Sort input sections by the special rule for .ctors and .dtors.
-static void sortCtorsDtors(OutputSectionCommand *Cmd) {
+static void sortCtorsDtors(OutputSection *Cmd) {
if (Cmd)
Cmd->sortCtorsDtors();
}
@@ -905,8 +892,8 @@ template <class ELFT> static void sortBy
// Sort sections by priority.
for (BaseCommand *Base : Script->Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- Cmd->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
}
template <class ELFT>
@@ -932,30 +919,34 @@ void Writer<ELFT>::forEachRelSec(std::fu
}
template <class ELFT> void Writer<ELFT>::createSections() {
+ std::vector<BaseCommand *> Old = Script->Opt.Commands;
+ Script->Opt.Commands.clear();
for (InputSectionBase *IS : InputSections)
if (IS)
Factory.addInputSec(IS, getOutputSectionName(IS->Name));
+ Script->Opt.Commands.insert(Script->Opt.Commands.end(), Old.begin(),
+ Old.end());
Script->fabricateDefaultCommands();
sortBySymbolsOrder<ELFT>();
- sortInitFini(findSectionCommand(".init_array"));
- sortInitFini(findSectionCommand(".fini_array"));
- sortCtorsDtors(findSectionCommand(".ctors"));
- sortCtorsDtors(findSectionCommand(".dtors"));
+ sortInitFini(findSection(".init_array"));
+ sortInitFini(findSection(".fini_array"));
+ sortCtorsDtors(findSection(".ctors"));
+ sortCtorsDtors(findSection(".dtors"));
}
// 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 int getRankProximity(OutputSection *A, OutputSection *B) {
+static int getRankProximityAux(OutputSection *A, OutputSection *B) {
return countLeadingZeros(A->SortRank ^ B->SortRank);
}
static int getRankProximity(OutputSection *A, BaseCommand *B) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(B))
- if (Cmd->Sec)
- return getRankProximity(A, Cmd->Sec);
+ if (auto *Sec = dyn_cast<OutputSection>(B))
+ if (Sec->Live)
+ return getRankProximityAux(A, Sec);
return -1;
}
@@ -974,7 +965,7 @@ static int getRankProximity(OutputSectio
// rw_sec : { *(rw_sec) }
// would mean that the RW PT_LOAD would become unaligned.
static bool shouldSkip(BaseCommand *Cmd) {
- if (isa<OutputSectionCommand>(Cmd))
+ if (isa<OutputSection>(Cmd))
return false;
if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd))
return Assign->Name != ".";
@@ -988,7 +979,7 @@ template <typename ELFT>
static std::vector<BaseCommand *>::iterator
findOrphanPos(std::vector<BaseCommand *>::iterator B,
std::vector<BaseCommand *>::iterator E) {
- OutputSection *Sec = cast<OutputSectionCommand>(*E)->Sec;
+ OutputSection *Sec = cast<OutputSection>(*E);
// Find the first element that has as close a rank as possible.
auto I = std::max_element(B, E, [=](BaseCommand *A, BaseCommand *B) {
@@ -1000,16 +991,16 @@ findOrphanPos(std::vector<BaseCommand *>
// Consider all existing sections with the same proximity.
int Proximity = getRankProximity(Sec, *I);
for (; I != E; ++I) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(*I);
- if (!Cmd || !Cmd->Sec)
+ auto *CurSec = dyn_cast<OutputSection>(*I);
+ if (!CurSec || !CurSec->Live)
continue;
- if (getRankProximity(Sec, Cmd->Sec) != Proximity ||
- Sec->SortRank < Cmd->Sec->SortRank)
+ if (getRankProximity(Sec, CurSec) != Proximity ||
+ Sec->SortRank < CurSec->SortRank)
break;
}
auto J = std::find_if(
llvm::make_reverse_iterator(I), llvm::make_reverse_iterator(B),
- [](BaseCommand *Cmd) { return isa<OutputSectionCommand>(Cmd); });
+ [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); });
I = J.base();
while (I != E && shouldSkip(*I))
++I;
@@ -1026,18 +1017,15 @@ template <class ELFT> void Writer<ELFT>:
return;
for (BaseCommand *Base : Script->Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (OutputSection *Sec = Cmd->Sec)
- Sec->SortRank = getSectionRank(Sec);
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ Sec->SortRank = getSectionRank(Sec);
if (!Script->Opt.HasSections) {
- // We know that all the OutputSectionCommands are contiguous in
+ // We know that all the OutputSections are contiguous in
// this case.
auto E = Script->Opt.Commands.end();
auto I = Script->Opt.Commands.begin();
- auto IsSection = [](BaseCommand *Base) {
- return isa<OutputSectionCommand>(Base);
- };
+ auto IsSection = [](BaseCommand *Base) { return isa<OutputSection>(Base); };
I = std::find_if(I, E, IsSection);
E = std::find_if(llvm::make_reverse_iterator(E),
llvm::make_reverse_iterator(I), IsSection)
@@ -1088,8 +1076,8 @@ template <class ELFT> void Writer<ELFT>:
auto I = Script->Opt.Commands.begin();
auto E = Script->Opt.Commands.end();
auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- return Cmd->Sec && Cmd->Sec->SectionIndex == INT_MAX;
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ return Sec->Live && Sec->SectionIndex == INT_MAX;
return false;
});
@@ -1109,13 +1097,13 @@ template <class ELFT> void Writer<ELFT>:
while (NonScriptI != E) {
auto Pos = findOrphanPos<ELFT>(I, NonScriptI);
- OutputSection *Orphan = cast<OutputSectionCommand>(*NonScriptI)->Sec;
+ OutputSection *Orphan = cast<OutputSection>(*NonScriptI);
// As an optimization, find all sections with the same sort rank
// and insert them with one rotate.
unsigned Rank = Orphan->SortRank;
auto End = std::find_if(NonScriptI + 1, E, [=](BaseCommand *Cmd) {
- return cast<OutputSectionCommand>(Cmd)->Sec->SortRank != Rank;
+ return cast<OutputSection>(Cmd)->SortRank != Rank;
});
std::rotate(Pos, NonScriptI, End);
NonScriptI = End;
@@ -1149,9 +1137,8 @@ static void removeUnusedSyntheticSection
if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable)
continue;
- OutputSectionCommand *Cmd = Script->getCmd(OS);
- std::vector<BaseCommand *>::iterator Empty = Cmd->Commands.end();
- for (auto I = Cmd->Commands.begin(), E = Cmd->Commands.end(); I != E; ++I) {
+ std::vector<BaseCommand *>::iterator Empty = OS->Commands.end();
+ for (auto I = OS->Commands.begin(), E = OS->Commands.end(); I != E; ++I) {
BaseCommand *B = *I;
if (auto *ISD = dyn_cast<InputSectionDescription>(B)) {
auto P = std::find(ISD->Sections.begin(), ISD->Sections.end(), SS);
@@ -1161,17 +1148,17 @@ static void removeUnusedSyntheticSection
Empty = I;
}
}
- if (Empty != Cmd->Commands.end())
- Cmd->Commands.erase(Empty);
+ if (Empty != OS->Commands.end())
+ OS->Commands.erase(Empty);
// If there are no other sections in the output section, remove it from the
// output.
- if (Cmd->Commands.empty()) {
+ if (OS->Commands.empty()) {
// Also remove script commands matching the output section.
auto &Cmds = Script->Opt.Commands;
- auto I = std::remove_if(Cmds.begin(), Cmds.end(), [&](BaseCommand *Cmd) {
- if (auto *OSCmd = dyn_cast<OutputSectionCommand>(Cmd))
- return OSCmd->Sec == OS;
+ auto I = std::remove_if(Cmds.begin(), Cmds.end(), [&](BaseCommand *Cmd2) {
+ if (auto *Sec = dyn_cast<OutputSection>(Cmd2))
+ return Sec == OS;
return false;
});
Cmds.erase(I, Cmds.end());
@@ -1181,10 +1168,10 @@ static void removeUnusedSyntheticSection
// Create output section objects and add them to OutputSections.
template <class ELFT> void Writer<ELFT>::finalizeSections() {
- Out::DebugInfo = findSectionInScript(".debug_info");
- Out::PreinitArray = findSectionInScript(".preinit_array");
- Out::InitArray = findSectionInScript(".init_array");
- Out::FiniArray = findSectionInScript(".fini_array");
+ Out::DebugInfo = findSection(".debug_info");
+ Out::PreinitArray = findSection(".preinit_array");
+ Out::InitArray = findSection(".init_array");
+ Out::FiniArray = findSection(".fini_array");
// The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
// symbols for sections, so that the runtime can get the start and end
@@ -1192,9 +1179,8 @@ template <class ELFT> void Writer<ELFT>:
if (!Config->Relocatable) {
addStartEndSymbols();
for (BaseCommand *Base : Script->Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (Cmd->Sec)
- addStartStopSymbols(Cmd->Sec);
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ addStartStopSymbols(Sec);
}
// Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
@@ -1250,16 +1236,16 @@ template <class ELFT> void Writer<ELFT>:
sortSections();
// Now that we have the final list, create a list of all the
- // OutputSectionCommands for convenience.
+ // OutputSections for convenience.
for (BaseCommand *Base : Script->Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- OutputSectionCommands.push_back(Cmd);
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ OutputSections.push_back(Sec);
// Prefer command line supplied address over other constraints.
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- auto I = Config->SectionStartMap.find(Cmd->Name);
+ for (OutputSection *Sec : OutputSections) {
+ auto I = Config->SectionStartMap.find(Sec->Name);
if (I != Config->SectionStartMap.end())
- Cmd->AddrExpr = [=] { return I->second; };
+ Sec->AddrExpr = [=] { return I->second; };
}
// This is a bit of a hack. A value of 0 means undef, so we set it
@@ -1268,8 +1254,7 @@ template <class ELFT> void Writer<ELFT>:
Out::ElfHeader->SectionIndex = 1;
unsigned I = 1;
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections) {
Sec->SectionIndex = I++;
Sec->ShName = InX::ShStrTab->addString(Sec->Name);
}
@@ -1307,10 +1292,10 @@ template <class ELFT> void Writer<ELFT>:
// when no more Thunks are added
ThunkCreator TC;
Script->assignAddresses();
- if (TC.createThunks(OutputSectionCommands)) {
+ if (TC.createThunks(OutputSections)) {
applySynthetic({InX::MipsGot},
[](SyntheticSection *SS) { SS->updateAllocSize(); });
- if (TC.createThunks(OutputSectionCommands))
+ if (TC.createThunks(OutputSections))
fatal("All non-range thunks should be created in first call");
}
}
@@ -1318,8 +1303,8 @@ template <class ELFT> void Writer<ELFT>:
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
- for (OutputSectionCommand *Cmd : OutputSectionCommands)
- Cmd->finalize<ELFT>();
+ for (OutputSection *Sec : OutputSections)
+ Sec->finalize<ELFT>();
// createThunks may have added local symbols to the static symbol table
applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab},
@@ -1329,18 +1314,12 @@ template <class ELFT> void Writer<ELFT>:
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
// ARM ABI requires .ARM.exidx to be terminated by some piece of data.
// We have the terminater synthetic section class. Add that at the end.
- OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx");
- if (!Cmd || !Cmd->Sec || Config->Relocatable)
+ OutputSection *Cmd = findSection(".ARM.exidx");
+ if (!Cmd || !Cmd->Live || Config->Relocatable)
return;
auto *Sentinel = make<ARMExidxSentinelSection>();
- Cmd->Sec->addSection(Sentinel);
- // Add the sentinel to the last of these too.
- auto ISD = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(),
- [](const BaseCommand *Base) {
- return isa<InputSectionDescription>(Base);
- });
- cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel);
+ Cmd->addSection(Sentinel);
}
// The linker is expected to define SECNAME_start and SECNAME_end
@@ -1364,7 +1343,7 @@ template <class ELFT> void Writer<ELFT>:
Define("__init_array_start", "__init_array_end", Out::InitArray);
Define("__fini_array_start", "__fini_array_end", Out::FiniArray);
- if (OutputSection *Sec = findSectionInScript(".ARM.exidx"))
+ if (OutputSection *Sec = findSection(".ARM.exidx"))
Define("__exidx_start", "__exidx_end", Sec);
}
@@ -1382,19 +1361,11 @@ void Writer<ELFT>::addStartStopSymbols(O
addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
}
-template <class ELFT>
-OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) {
+template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
for (BaseCommand *Base : Script->Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (Cmd->Name == Name)
- return Cmd;
- return nullptr;
-}
-
-template <class ELFT>
-OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) {
- if (OutputSectionCommand *Cmd = findSectionCommand(Name))
- return Cmd->Sec;
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ if (Sec->Name == Name)
+ return Sec;
return nullptr;
}
@@ -1435,8 +1406,8 @@ template <class ELFT> std::vector<PhdrEn
AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders);
// PT_INTERP must be the second entry if exists.
- if (OutputSection *Sec = findSectionInScript(".interp"))
- AddHdr(PT_INTERP, Sec->getPhdrFlags())->add(Sec);
+ if (OutputSection *Cmd = findSection(".interp"))
+ AddHdr(PT_INTERP, Cmd->getPhdrFlags())->add(Cmd);
// Add the first PT_LOAD segment for regular output sections.
uint64_t Flags = computeFlags(PF_R);
@@ -1446,8 +1417,7 @@ template <class ELFT> std::vector<PhdrEn
Load->add(Out::ElfHeader);
Load->add(Out::ProgramHeaders);
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections) {
if (!(Sec->Flags & SHF_ALLOC))
break;
if (!needsPtLoad(Sec))
@@ -1459,7 +1429,7 @@ template <class ELFT> std::vector<PhdrEn
// different flags or is loaded at a discontiguous address using AT linker
// script command.
uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
- if (Cmd->LMAExpr || Flags != NewFlags) {
+ if (Sec->LMAExpr || Flags != NewFlags) {
Load = AddHdr(PT_LOAD, NewFlags);
Flags = NewFlags;
}
@@ -1469,11 +1439,9 @@ template <class ELFT> std::vector<PhdrEn
// Add a TLS segment if any.
PhdrEntry *TlsHdr = make<PhdrEntry>(PT_TLS, PF_R);
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_TLS)
TlsHdr->add(Sec);
- }
if (TlsHdr->First)
Ret.push_back(TlsHdr);
@@ -1485,11 +1453,9 @@ template <class ELFT> std::vector<PhdrEn
// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (needsPtLoad(Sec) && isRelroSection(Sec))
RelRo->add(Sec);
- }
if (RelRo->First)
Ret.push_back(RelRo);
@@ -1501,8 +1467,8 @@ template <class ELFT> std::vector<PhdrEn
// PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
// the dynamic linker fill the segment with random data.
- if (OutputSection *Sec = findSectionInScript(".openbsd.randomdata"))
- AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags())->add(Sec);
+ if (OutputSection *Cmd = findSection(".openbsd.randomdata"))
+ AddHdr(PT_OPENBSD_RANDOMIZE, Cmd->getPhdrFlags())->add(Cmd);
// PT_GNU_STACK is a special section to tell the loader to make the
// pages for the stack non-executable. If you really want an executable
@@ -1524,10 +1490,9 @@ template <class ELFT> std::vector<PhdrEn
// Create one PT_NOTE per a group of contiguous .note sections.
PhdrEntry *Note = nullptr;
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections) {
if (Sec->Type == SHT_NOTE) {
- if (!Note || Cmd->LMAExpr)
+ if (!Note || Sec->LMAExpr)
Note = AddHdr(PT_NOTE, PF_R);
Note->add(Sec);
} else {
@@ -1541,15 +1506,15 @@ template <class ELFT>
void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry *> &Phdrs) {
if (Config->EMachine != EM_ARM)
return;
- auto I = llvm::find_if(OutputSectionCommands, [](OutputSectionCommand *Cmd) {
- return Cmd->Sec->Type == SHT_ARM_EXIDX;
+ auto I = llvm::find_if(OutputSections, [](OutputSection *Cmd) {
+ return Cmd->Type == SHT_ARM_EXIDX;
});
- if (I == OutputSectionCommands.end())
+ if (I == OutputSections.end())
return;
// PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME
PhdrEntry *ARMExidx = make<PhdrEntry>(PT_ARM_EXIDX, PF_R);
- ARMExidx->add((*I)->Sec);
+ ARMExidx->add(*I);
Phdrs.push_back(ARMExidx);
}
@@ -1557,8 +1522,7 @@ void Writer<ELFT>::addPtArmExid(std::vec
// first section after PT_GNU_RELRO have to be page aligned so that the dynamic
// linker can set the permissions.
template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
- auto PageAlign = [](OutputSection *Sec) {
- OutputSectionCommand *Cmd = Script->getCmd(Sec);
+ auto PageAlign = [](OutputSection *Cmd) {
if (Cmd && !Cmd->AddrExpr)
Cmd->AddrExpr = [=] {
return alignTo(Script->getDot(), Config->MaxPageSize);
@@ -1576,14 +1540,13 @@ template <class ELFT> void Writer<ELFT>:
PageAlign(P->First);
// Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
// have to align it to a page.
- auto End = OutputSectionCommands.end();
- auto I =
- std::find(OutputSectionCommands.begin(), End, Script->getCmd(P->Last));
+ auto End = OutputSections.end();
+ auto I = std::find(OutputSections.begin(), End, P->Last);
if (I == End || (I + 1) == End)
continue;
- OutputSection *Sec = (*(I + 1))->Sec;
- if (needsPtLoad(Sec))
- PageAlign(Sec);
+ OutputSection *Cmd = (*(I + 1));
+ if (needsPtLoad(Cmd))
+ PageAlign(Cmd);
}
}
@@ -1591,41 +1554,39 @@ template <class ELFT> void Writer<ELFT>:
// its new file offset. The file offset must be the same with its
// virtual address (modulo the page size) so that the loader can load
// executables without any address adjustment.
-static uint64_t getFileAlignment(uint64_t Off, OutputSection *Sec) {
- OutputSection *First = Sec->FirstInPtLoad;
+static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) {
+ OutputSection *First = Cmd->FirstInPtLoad;
// If the section is not in a PT_LOAD, we just have to align it.
if (!First)
- return alignTo(Off, Sec->Alignment);
+ return alignTo(Off, Cmd->Alignment);
// The first section in a PT_LOAD has to have congruent offset and address
// module the page size.
- if (Sec == First)
- return alignTo(Off, std::max<uint64_t>(Sec->Alignment, Config->MaxPageSize),
- Sec->Addr);
+ if (Cmd == First)
+ return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize),
+ Cmd->Addr);
// If two sections share the same PT_LOAD the file offset is calculated
// using this formula: Off2 = Off1 + (VA2 - VA1).
- return First->Offset + Sec->Addr - First->Addr;
+ return First->Offset + Cmd->Addr - First->Addr;
}
-static uint64_t setOffset(OutputSection *Sec, uint64_t Off) {
- if (Sec->Type == SHT_NOBITS) {
- Sec->Offset = Off;
+static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) {
+ if (Cmd->Type == SHT_NOBITS) {
+ Cmd->Offset = Off;
return Off;
}
- Off = getFileAlignment(Off, Sec);
- Sec->Offset = Off;
- return Off + Sec->Size;
+ Off = getFileAlignment(Off, Cmd);
+ Cmd->Offset = Off;
+ return Off + Cmd->Size;
}
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
uint64_t Off = 0;
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
Off = setOffset(Sec, Off);
- }
FileSize = alignTo(Off, Config->Wordsize);
}
@@ -1635,12 +1596,11 @@ template <class ELFT> void Writer<ELFT>:
Off = setOffset(Out::ElfHeader, Off);
Off = setOffset(Out::ProgramHeaders, Off);
- for (OutputSectionCommand *Cmd : OutputSectionCommands)
- Off = setOffset(Cmd->Sec, Off);
+ for (OutputSection *Sec : OutputSections)
+ Off = setOffset(Sec, Off);
SectionHeaderOff = alignTo(Off, Config->Wordsize);
- FileSize =
- SectionHeaderOff + (OutputSectionCommands.size() + 1) * sizeof(Elf_Shdr);
+ FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
}
// Finalize the program headers. We call this function after we assign
@@ -1696,7 +1656,7 @@ template <class ELFT> uint64_t Writer<EL
return Addr;
// Case 4
- if (OutputSection *Sec = findSectionInScript(".text")) {
+ if (OutputSection *Sec = findSection(".text")) {
if (Config->WarnMissingEntry)
warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +
utohexstr(Sec->Addr));
@@ -1738,9 +1698,9 @@ template <class ELFT> void Writer<ELFT>:
LastRO = P;
}
- auto Set = [](DefinedRegular *S, OutputSection *Sec, uint64_t Value) {
+ auto Set = [](DefinedRegular *S, OutputSection *Cmd, uint64_t Value) {
if (S) {
- S->Section = Sec;
+ S->Section = Cmd;
S->Value = Value;
}
};
@@ -1759,15 +1719,15 @@ template <class ELFT> void Writer<ELFT>:
}
if (ElfSym::Bss)
- ElfSym::Bss->Section = findSectionInScript(".bss");
+ ElfSym::Bss->Section = findSection(".bss");
// Setup MIPS _gp_disp/__gnu_local_gp symbols which should
// be equal to the _gp symbol's value.
if (Config->EMachine == EM_MIPS && !ElfSym::MipsGp->Value) {
// Find GP-relative section with the lowest address
// and use this address to calculate default _gp value.
- for (const OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *OS = Cmd->Sec;
+ for (const OutputSection *Cmd : OutputSections) {
+ const OutputSection *OS = Cmd;
if (OS->Flags & SHF_MIPS_GPREL) {
ElfSym::MipsGp->Value = OS->Addr + 0x7ff0;
break;
@@ -1794,7 +1754,7 @@ template <class ELFT> void Writer<ELFT>:
EHdr->e_ehsize = sizeof(Elf_Ehdr);
EHdr->e_phnum = Phdrs.size();
EHdr->e_shentsize = sizeof(Elf_Shdr);
- EHdr->e_shnum = OutputSectionCommands.size() + 1;
+ EHdr->e_shnum = OutputSections.size() + 1;
EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex;
if (Config->EMachine == EM_ARM)
@@ -1826,8 +1786,8 @@ template <class ELFT> void Writer<ELFT>:
// Write the section header table. Note that the first table entry is null.
auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
- for (OutputSectionCommand *Cmd : OutputSectionCommands)
- Cmd->Sec->writeHeaderTo<ELFT>(++SHdrs);
+ for (OutputSection *Sec : OutputSections)
+ Sec->writeHeaderTo<ELFT>(++SHdrs);
}
// Open a result file.
@@ -1850,11 +1810,9 @@ template <class ELFT> void Writer<ELFT>:
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
uint8_t *Buf = Buffer->getBufferStart();
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
- Cmd->writeTo<ELFT>(Buf + Sec->Offset);
- }
+ Sec->writeTo<ELFT>(Buf + Sec->Offset);
}
// Write section contents to a mmap'ed file.
@@ -1863,8 +1821,8 @@ template <class ELFT> void Writer<ELFT>:
// PPC64 needs to process relocations in the .opd section
// before processing relocations in code-containing sections.
- if (auto *OpdCmd = findSectionCommand(".opd")) {
- Out::Opd = OpdCmd->Sec;
+ if (auto *OpdCmd = findSection(".opd")) {
+ Out::Opd = OpdCmd;
Out::OpdBuf = Buf + Out::Opd->Offset;
OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset);
}
@@ -1877,25 +1835,19 @@ template <class ELFT> void Writer<ELFT>:
// In -r or -emit-relocs mode, write the relocation sections first as in
// ELf_Rel targets we might find out that we need to modify the relocated
// section while doing it.
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
- Cmd->writeTo<ELFT>(Buf + Sec->Offset);
- }
+ Sec->writeTo<ELFT>(Buf + Sec->Offset);
- for (OutputSectionCommand *Cmd : OutputSectionCommands) {
- OutputSection *Sec = Cmd->Sec;
+ for (OutputSection *Sec : OutputSections)
if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
Sec->Type != SHT_RELA)
- Cmd->writeTo<ELFT>(Buf + Sec->Offset);
- }
+ Sec->writeTo<ELFT>(Buf + Sec->Offset);
// The .eh_frame_hdr depends on .eh_frame section contents, therefore
// it should be written after .eh_frame is written.
- if (EhFrameHdr) {
- OutputSectionCommand *Cmd = Script->getCmd(EhFrameHdr);
- Cmd->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
- }
+ if (EhFrameHdr)
+ EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
}
template <class ELFT> void Writer<ELFT>::writeBuildId() {
More information about the llvm-commits
mailing list