summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Driver.cpp11
-rw-r--r--lld/ELF/LinkerScript.cpp98
-rw-r--r--lld/ELF/LinkerScript.h53
-rw-r--r--lld/ELF/MarkLive.cpp2
-rw-r--r--lld/ELF/OutputSections.cpp2
-rw-r--r--lld/ELF/Writer.cpp12
6 files changed, 87 insertions, 91 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index c71cfca7017..f72fa3dd28e 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -36,12 +36,14 @@ LinkerDriver *elf::Driver;
bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
HasError = false;
ErrorOS = &Error;
+
Configuration C;
LinkerDriver D;
- LinkerScript LS;
+ ScriptConfiguration SC;
Config = &C;
Driver = &D;
- Script = &LS;
+ ScriptConfig = &SC;
+
Driver->main(Args);
return !HasError;
}
@@ -108,7 +110,7 @@ void LinkerDriver::addFile(StringRef Path) {
switch (identify_magic(MBRef.getBuffer())) {
case file_magic::unknown:
- Script->read(MBRef);
+ readLinkerScript(MBRef);
return;
case file_magic::archive:
if (WholeArchive) {
@@ -415,8 +417,11 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
SymbolTable<ELFT> Symtab;
+
std::unique_ptr<TargetInfo> TI(createTarget());
Target = TI.get();
+ LinkerScript<ELFT> LS;
+ Script<ELFT>::X = &LS;
Config->Rela = ELFT::Is64Bits;
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 9a47ee6bccb..10008568d9f 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -33,7 +33,7 @@ using namespace llvm::object;
using namespace lld;
using namespace lld::elf;
-LinkerScript *elf::Script;
+ScriptConfiguration *elf::ScriptConfig;
static uint64_t getInteger(StringRef S) {
uint64_t V;
@@ -147,25 +147,26 @@ static uint64_t evaluate(ArrayRef<StringRef> Tokens, uint64_t Dot) {
}
template <class ELFT>
-SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) {
- for (SectionRule &R : Sections)
+SectionRule *LinkerScript<ELFT>::find(InputSectionBase<ELFT> *S) {
+ for (SectionRule &R : Opt.Sections)
if (R.match(S))
return &R;
return nullptr;
}
template <class ELFT>
-StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) {
+StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) {
SectionRule *R = find(S);
return R ? R->Dest : "";
}
template <class ELFT>
-bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) {
+bool LinkerScript<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) {
return getOutputSection(S) == "/DISCARD/";
}
-template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) {
+template <class ELFT>
+bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) {
SectionRule *R = find(S);
return R && R->Keep;
}
@@ -180,7 +181,7 @@ findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) {
}
template <class ELFT>
-void LinkerScript::assignAddresses(
+void LinkerScript<ELFT>::assignAddresses(
std::vector<OutputSectionBase<ELFT> *> &Sections) {
typedef typename ELFT::uint uintX_t;
@@ -191,9 +192,9 @@ void LinkerScript::assignAddresses(
// https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
for (OutputSectionBase<ELFT> *Sec : Sections) {
StringRef Name = Sec->getName();
- auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name);
- if (I == SectionOrder.end())
- Commands.push_back({SectionKind, {}, Name});
+ auto I = std::find(Opt.SectionOrder.begin(), Opt.SectionOrder.end(), Name);
+ if (I == Opt.SectionOrder.end())
+ Opt.Commands.push_back({SectionKind, {}, Name});
}
// Assign addresses as instructed by linker script SECTIONS sub-commands.
@@ -201,7 +202,7 @@ void LinkerScript::assignAddresses(
uintX_t VA =
Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
- for (SectionsCommand &Cmd : Commands) {
+ for (SectionsCommand &Cmd : Opt.Commands) {
if (Cmd.Kind == ExprKind) {
VA = evaluate(Cmd.Expr, VA);
continue;
@@ -228,9 +229,10 @@ void LinkerScript::assignAddresses(
}
}
-ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
- auto I = Filler.find(Name);
- if (I == Filler.end())
+template <class ELFT>
+ArrayRef<uint8_t> LinkerScript<ELFT>::getFiller(StringRef Name) {
+ auto I = Opt.Filler.find(Name);
+ if (I == Opt.Filler.end())
return {};
return I->second;
}
@@ -238,10 +240,11 @@ ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
// A compartor to sort output sections. Returns -1 or 1 if both
// A and B are mentioned in linker scripts. Otherwise, returns 0
// to use the default rule which is implemented in Writer.cpp.
-int LinkerScript::compareSections(StringRef A, StringRef B) {
- auto E = SectionOrder.end();
- auto I = std::find(SectionOrder.begin(), E, A);
- auto J = std::find(SectionOrder.begin(), E, B);
+template <class ELFT>
+int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
+ auto E = Opt.SectionOrder.end();
+ auto I = std::find(Opt.SectionOrder.begin(), E, A);
+ auto J = std::find(Opt.SectionOrder.begin(), E, B);
if (I == E || J == E)
return 0;
return I < J ? -1 : 1;
@@ -275,12 +278,11 @@ template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
return matchStr(SectionPattern, S->getSectionName());
}
-class elf::ScriptParser final : public elf::ScriptParserBase {
+class elf::ScriptParser : public ScriptParserBase {
typedef void (ScriptParser::*Handler)();
public:
- ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
- : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {}
+ ScriptParser(StringRef S, bool B) : ScriptParserBase(S), IsUnderSysroot(B) {}
void run() override;
@@ -303,8 +305,9 @@ private:
void readOutputSectionDescription();
void readSectionPatterns(StringRef OutSec, bool Keep);
- StringSaver Saver;
const static StringMap<Handler> Cmd;
+ ScriptConfiguration &Opt = *ScriptConfig;
+ StringSaver Saver = {ScriptConfig->Alloc};
bool IsUnderSysroot;
};
@@ -460,7 +463,7 @@ void ScriptParser::readSearchDir() {
}
void ScriptParser::readSections() {
- Script->DoLayout = true;
+ Opt.DoLayout = true;
expect("{");
while (!Error && !skip("}")) {
StringRef Tok = peek();
@@ -474,14 +477,14 @@ void ScriptParser::readSections() {
void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
expect("(");
while (!Error && !skip(")"))
- Script->Sections.emplace_back(OutSec, next(), Keep);
+ Opt.Sections.emplace_back(OutSec, next(), Keep);
}
void ScriptParser::readLocationCounterValue() {
expect(".");
expect("=");
- Script->Commands.push_back({ExprKind, {}, ""});
- SectionsCommand &Cmd = Script->Commands.back();
+ Opt.Commands.push_back({ExprKind, {}, ""});
+ SectionsCommand &Cmd = Opt.Commands.back();
while (!Error) {
StringRef Tok = next();
if (Tok == ";")
@@ -494,8 +497,8 @@ void ScriptParser::readLocationCounterValue() {
void ScriptParser::readOutputSectionDescription() {
StringRef OutSec = next();
- Script->SectionOrder.push_back(OutSec);
- Script->Commands.push_back({SectionKind, {}, OutSec});
+ Opt.SectionOrder.push_back(OutSec);
+ Opt.Commands.push_back({SectionKind, {}, OutSec});
expect(":");
expect("{");
while (!Error && !skip("}")) {
@@ -518,7 +521,7 @@ void ScriptParser::readOutputSectionDescription() {
return;
}
Tok = Tok.substr(3);
- Script->Filler[OutSec] = parseHex(Tok);
+ Opt.Filler[OutSec] = parseHex(Tok);
next();
}
}
@@ -532,32 +535,13 @@ static bool isUnderSysroot(StringRef Path) {
return false;
}
-// Entry point. The other functions or classes are private to this file.
-void LinkerScript::read(MemoryBufferRef MB) {
+// Entry point.
+void elf::readLinkerScript(MemoryBufferRef MB) {
StringRef Path = MB.getBufferIdentifier();
- ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
-}
-
-template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
-template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
-template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
-template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
-
-template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
-template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
-template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
-template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
-
-template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
-template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
-template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
-template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);
-
-template void
-LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &);
-template void
-LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &);
-template void
-LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &);
-template void
-LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &);
+ ScriptParser(MB.getBuffer(), isUnderSysroot(Path)).run();
+}
+
+template class elf::LinkerScript<ELF32LE>;
+template class elf::LinkerScript<ELF32BE>;
+template class elf::LinkerScript<ELF64LE>;
+template class elf::LinkerScript<ELF64BE>;
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 2deae33ef6e..bdc217e836a 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -19,6 +19,10 @@
namespace lld {
namespace elf {
+// Parses a linker script. Calling this function updates
+// Config and ScriptConfig.
+void readLinkerScript(MemoryBufferRef MB);
+
class ScriptParser;
template <class ELFT> class InputSectionBase;
template <class ELFT> class OutputSectionBase;
@@ -52,28 +56,8 @@ struct SectionsCommand {
StringRef SectionName;
};
-// This is a runner of the linker script.
-class LinkerScript {
- friend class ScriptParser;
-
-public:
- // Parses a linker script. Calling this function may update
- // this object and Config.
- void read(MemoryBufferRef MB);
-
- template <class ELFT> StringRef getOutputSection(InputSectionBase<ELFT> *S);
- ArrayRef<uint8_t> getFiller(StringRef Name);
- template <class ELFT> bool isDiscarded(InputSectionBase<ELFT> *S);
- template <class ELFT> bool shouldKeep(InputSectionBase<ELFT> *S);
- template <class ELFT>
- void assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S);
- int compareSections(StringRef A, StringRef B);
-
- bool DoLayout = false;
-
-private:
- template <class ELFT> SectionRule *find(InputSectionBase<ELFT> *S);
-
+// ScriptConfiguration holds linker script parse results.
+struct ScriptConfiguration {
// SECTIONS commands.
std::vector<SectionRule> Sections;
@@ -86,10 +70,33 @@ private:
// Used to assign addresses to sections.
std::vector<SectionsCommand> Commands;
+ bool DoLayout = false;
+
llvm::BumpPtrAllocator Alloc;
};
-extern LinkerScript *Script;
+extern ScriptConfiguration *ScriptConfig;
+
+// This is a runner of the linker script.
+template <class ELFT> class LinkerScript {
+public:
+ StringRef getOutputSection(InputSectionBase<ELFT> *S);
+ ArrayRef<uint8_t> getFiller(StringRef Name);
+ bool isDiscarded(InputSectionBase<ELFT> *S);
+ bool shouldKeep(InputSectionBase<ELFT> *S);
+ void assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S);
+ int compareSections(StringRef A, StringRef B);
+
+private:
+ SectionRule *find(InputSectionBase<ELFT> *S);
+
+ ScriptConfiguration &Opt = *ScriptConfig;
+};
+
+// Variable template is a C++14 feature, so we can't template
+// a global variable. Use a struct to workaround.
+template <class ELFT> struct Script { static LinkerScript<ELFT> *X; };
+template <class ELFT> LinkerScript<ELFT> *Script<ELFT>::X;
} // namespace elf
} // namespace lld
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index ade0dceeb2c..155fe3f5823 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -126,7 +126,7 @@ template <class ELFT> void elf::markLive(SymbolTable<ELFT> *Symtab) {
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles())
for (InputSectionBase<ELFT> *Sec : F->getSections())
if (Sec && Sec != &InputSection<ELFT>::Discarded)
- if (isReserved(Sec) || Script->shouldKeep<ELFT>(Sec))
+ if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec))
Enqueue(Sec);
// Mark all reachable sections.
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index acbdd31cb1a..9052aec88f8 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -908,7 +908,7 @@ static void fill(uint8_t *Buf, size_t Size, ArrayRef<uint8_t> A) {
}
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
- ArrayRef<uint8_t> Filler = Script->getFiller(this->Name);
+ ArrayRef<uint8_t> Filler = Script<ELFT>::X->getFiller(this->Name);
if (!Filler.empty())
fill(Buf, this->getSize(), Filler);
if (Config->Threads) {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 5d98ff7c99b..8fb71c53d6d 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -220,8 +220,8 @@ template <class ELFT> void Writer<ELFT>::run() {
} else {
createPhdrs();
fixHeaders();
- if (Script->DoLayout) {
- Script->assignAddresses(OutputSections);
+ if (ScriptConfig->DoLayout) {
+ Script<ELFT>::X->assignAddresses(OutputSections);
} else {
fixSectionAlignments();
assignAddresses();
@@ -776,7 +776,7 @@ static bool compareSections(OutputSectionBase<ELFT> *A,
OutputSectionBase<ELFT> *B) {
typedef typename ELFT::uint uintX_t;
- int Comp = Script->compareSections(A->getName(), B->getName());
+ int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName());
if (Comp != 0)
return Comp < 0;
@@ -918,7 +918,7 @@ void Writer<ELFT>::addCopyRelSymbol(SharedSymbol<ELFT> *SS) {
template <class ELFT>
StringRef Writer<ELFT>::getOutputSectionName(InputSectionBase<ELFT> *S) const {
- StringRef Dest = Script->getOutputSection<ELFT>(S);
+ StringRef Dest = Script<ELFT>::X->getOutputSection(S);
if (!Dest.empty())
return Dest;
@@ -943,7 +943,7 @@ void reportDiscarded(InputSectionBase<ELFT> *IS,
template <class ELFT>
bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {
return !S || S == &InputSection<ELFT>::Discarded || !S->Live ||
- Script->isDiscarded(S);
+ Script<ELFT>::X->isDiscarded(S);
}
template <class ELFT>
@@ -1545,7 +1545,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// sections. These are special, we do not include them into output sections
// list, but have them to simplify the code.
template <class ELFT> void Writer<ELFT>::fixHeaders() {
- uintX_t BaseVA = Script->DoLayout ? 0 : Target->getVAStart();
+ uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart();
Out<ELFT>::ElfHeader->setVA(BaseVA);
Out<ELFT>::ElfHeader->setFileOffset(0);
uintX_t Off = Out<ELFT>::ElfHeader->getSize();
OpenPOWER on IntegriCloud