summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/LinkerScript.cpp94
-rw-r--r--lld/ELF/LinkerScript.h5
-rw-r--r--lld/ELF/Writer.cpp2
3 files changed, 34 insertions, 67 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index be6a0ca9027..74b5aa0f1fc 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -475,15 +475,10 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
return Cmd->Name == Name;
return false;
});
- if (I == Opt.Commands.end()) {
+ if (I == Opt.Commands.end())
Factory.addInputSec(S, Name);
- } else {
- auto *Cmd = cast<OutputSectionCommand>(*I);
- Factory.addInputSec(S, Name, Cmd->Sec);
- auto *ISD = make<InputSectionDescription>("");
- ISD->Sections.push_back(S);
- Cmd->Commands.push_back(ISD);
- }
+ else
+ Factory.addInputSec(S, Name, cast<OutputSectionCommand>(*I)->Sec);
}
}
@@ -492,6 +487,8 @@ static bool isTbss(OutputSection *Sec) {
}
void LinkerScript::output(InputSection *S) {
+ if (!AlreadyOutputIS.insert(S).second)
+ return;
bool IsTbss = isTbss(CurOutSec);
uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot;
@@ -523,9 +520,19 @@ void LinkerScript::output(InputSection *S) {
Dot = Pos;
}
+void LinkerScript::flush() {
+ assert(CurOutSec);
+ if (!AlreadyOutputOS.insert(CurOutSec).second)
+ return;
+ for (InputSection *I : CurOutSec->Sections)
+ output(I);
+}
+
void LinkerScript::switchTo(OutputSection *Sec) {
if (CurOutSec == Sec)
return;
+ if (AlreadyOutputOS.count(Sec))
+ return;
CurOutSec = Sec;
@@ -576,7 +583,7 @@ void LinkerScript::process(BaseCommand &Base) {
if (!Sec->Live)
continue;
- assert(CurOutSec == Sec->OutSec);
+ assert(CurOutSec == Sec->OutSec || AlreadyOutputOS.count(Sec->OutSec));
output(cast<InputSection>(Sec));
}
}
@@ -635,8 +642,19 @@ void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
Dot = CurMemRegion->Offset;
switchTo(Sec);
- for (BaseCommand *C : Cmd->Commands)
- process(*C);
+ // flush() may add orphan sections, so the order of flush() and
+ // symbol assignments is important. We want to call flush() first so
+ // that symbols pointing the end of the current section points to
+ // the location after orphan sections.
+ auto Mid =
+ std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(),
+ [](BaseCommand *Cmd) { return !isa<SymbolAssignment>(Cmd); })
+ .base();
+ for (auto I = Cmd->Commands.begin(); I != Mid; ++I)
+ process(**I);
+ flush();
+ for (auto I = Mid, E = Cmd->Commands.end(); I != E; ++I)
+ process(**I);
}
void LinkerScript::removeEmptyCommands() {
@@ -806,24 +824,15 @@ void LinkerScript::placeOrphanSections() {
++CmdIndex;
}
- // 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);
+ Cmd->Sec = Sec;
Opt.Commands.insert(CmdIter, Cmd);
++CmdIndex;
-
- Cmd->Sec = Sec;
- auto *ISD = make<InputSectionDescription>("");
- for (InputSection *IS : Sec->Sections)
- ISD->Sections.push_back(IS);
- Cmd->Commands.push_back(ISD);
-
continue;
}
@@ -841,49 +850,6 @@ void LinkerScript::processNonSectionCommands() {
}
}
-// Do a last effort at synchronizing the linker script "AST" and the section
-// list. This is needed to account for last minute changes, like adding a
-// .ARM.exidx terminator and sorting SHF_LINK_ORDER sections.
-//
-// FIXME: We should instead create the "AST" earlier and the above changes would
-// be done directly in the "AST".
-//
-// This can only handle new sections being added and sections being reordered.
-void LinkerScript::synchronize() {
- for (BaseCommand *Base : Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- if (!Cmd)
- continue;
- ArrayRef<InputSection *> Sections = Cmd->Sec->Sections;
- std::vector<InputSectionBase **> ScriptSections;
- for (BaseCommand *Base : Cmd->Commands) {
- auto *ISD = dyn_cast<InputSectionDescription>(Base);
- if (!ISD)
- continue;
- for (InputSectionBase *&IS : ISD->Sections)
- if (IS->Live)
- ScriptSections.push_back(&IS);
- }
- std::vector<InputSectionBase *> Missing;
- for (InputSection *IS : Sections)
- if (std::find_if(ScriptSections.begin(), ScriptSections.end(),
- [=](InputSectionBase **Base) { return *Base == IS; }) ==
- ScriptSections.end())
- Missing.push_back(IS);
- if (!Missing.empty()) {
- auto ISD = make<InputSectionDescription>("");
- ISD->Sections = Missing;
- Cmd->Commands.push_back(ISD);
- for (InputSectionBase *&IS : ISD->Sections)
- if (IS->Live)
- ScriptSections.push_back(&IS);
- }
- assert(ScriptSections.size() == Sections.size());
- for (int I = 0, N = Sections.size(); I < N; ++I)
- *ScriptSections[I] = Sections[I];
- }
-}
-
void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = 0;
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index dd96d335a66..61942b2db35 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -228,6 +228,7 @@ protected:
MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
void switchTo(OutputSection *Sec);
+ void flush();
void output(InputSection *Sec);
void process(BaseCommand &Base);
@@ -241,6 +242,9 @@ protected:
OutputSection *CurOutSec = nullptr;
MemoryRegion *CurMemRegion = nullptr;
+ llvm::DenseSet<OutputSection *> AlreadyOutputOS;
+ llvm::DenseSet<InputSectionBase *> AlreadyOutputIS;
+
public:
bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
uint64_t getDot() { return Dot; }
@@ -267,7 +271,6 @@ public:
void assignOffsets(OutputSectionCommand *Cmd);
void placeOrphanSections();
void processNonSectionCommands();
- void synchronize();
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
int getSectionIndex(StringRef Name);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index e2ab48433a5..f4d41ebfa78 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -254,7 +254,6 @@ template <class ELFT> void Writer<ELFT>::run() {
fixSectionAlignments();
Script->fabricateDefaultCommands(Config->MaxPageSize);
}
- Script->synchronize();
Script->assignAddresses(Phdrs);
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
@@ -1081,7 +1080,6 @@ static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) {
SS->OutSec->Sections.erase(std::find(SS->OutSec->Sections.begin(),
SS->OutSec->Sections.end(), SS));
- SS->Live = false;
// If there are no other sections in the output section, remove it from the
// output.
if (SS->OutSec->Sections.empty())
OpenPOWER on IntegriCloud