summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-04-28 20:22:47 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-04-28 20:22:47 +0000
commitb3bc1ed0d414bb63fbf00427508989272d7fea86 (patch)
treef2d2a121ce72fcd3815183daf122cecbb9699478
parent2d82590f640e4c014d7908b330d3681c951b1dcb (diff)
downloadbcm5719-llvm-b3bc1ed0d414bb63fbf00427508989272d7fea86.tar.gz
bcm5719-llvm-b3bc1ed0d414bb63fbf00427508989272d7fea86.zip
Remove LinkerScript::flush.
This patch replaces flush with a last ditch attempt at synchronizing the section list with the linker script "AST". The synchronization is a bit of a hack and should in time be avoided by creating the AST earlier so that modifications can be made directly to it instead of modifying the section list and synchronizing it back. This is the main step for fixing https://bugs.llvm.org/show_bug.cgi?id=32816. With this in place I think the only missing thing would be to have processCommands assign section indexes as dummy offsets so that the sort in OutputSection::finalize works. With this LinkerScript::assignAddresses becomes much simpler, which should help with the thunk work. llvm-svn: 301678
-rw-r--r--lld/ELF/LinkerScript.cpp94
-rw-r--r--lld/ELF/LinkerScript.h5
-rw-r--r--lld/ELF/Writer.cpp2
3 files changed, 67 insertions, 34 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 74b5aa0f1fc..13f0f55a0b7 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -475,10 +475,15 @@ 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
- Factory.addInputSec(S, Name, cast<OutputSectionCommand>(*I)->Sec);
+ } 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);
+ }
}
}
@@ -487,8 +492,6 @@ 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;
@@ -520,19 +523,9 @@ 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;
@@ -583,7 +576,7 @@ void LinkerScript::process(BaseCommand &Base) {
if (!Sec->Live)
continue;
- assert(CurOutSec == Sec->OutSec || AlreadyOutputOS.count(Sec->OutSec));
+ assert(CurOutSec == Sec->OutSec);
output(cast<InputSection>(Sec));
}
}
@@ -642,19 +635,8 @@ void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
Dot = CurMemRegion->Offset;
switchTo(Sec);
- // 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);
+ for (BaseCommand *Cmd : Cmd->Commands)
+ process(*Cmd);
}
void LinkerScript::removeEmptyCommands() {
@@ -824,15 +806,24 @@ 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;
}
@@ -850,6 +841,49 @@ 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 61942b2db35..dd96d335a66 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -228,7 +228,6 @@ protected:
MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
void switchTo(OutputSection *Sec);
- void flush();
void output(InputSection *Sec);
void process(BaseCommand &Base);
@@ -242,9 +241,6 @@ 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; }
@@ -271,6 +267,7 @@ 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 f4d41ebfa78..e2ab48433a5 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -254,6 +254,7 @@ 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
@@ -1080,6 +1081,7 @@ 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