summaryrefslogtreecommitdiffstats
path: root/lld/ELF/ScriptParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/ScriptParser.cpp')
-rw-r--r--lld/ELF/ScriptParser.cpp62
1 files changed, 62 insertions, 0 deletions
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 707e1047972..1d6a2174832 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -80,7 +80,9 @@ private:
uint32_t readFill();
uint32_t parseFill(StringRef Tok);
void readSectionAddressType(OutputSection *Cmd);
+ OutputSection *readOverlaySectionDescription();
OutputSection *readOutputSectionDescription(StringRef OutSec);
+ std::vector<BaseCommand *> readOverlay();
std::vector<StringRef> readOutputSectionPhdrs();
InputSectionDescription *readInputSectionDescription(StringRef Tok);
StringMatcher readFilePatterns();
@@ -436,6 +438,49 @@ void ScriptParser::readSearchDir() {
expect(")");
}
+// This reads an overlay description. Overlays are used to describe output
+// sections that use the same virtual memory range and normally would trigger
+// linker's sections sanity check failures.
+// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
+std::vector<BaseCommand *> ScriptParser::readOverlay() {
+ // VA and LMA expressions are optional, though for simplicity of
+ // implementation we assume they are not. That is what OVERLAY was designed
+ // for first of all: to allow sections with overlapping VAs at different LMAs.
+ Expr AddrExpr = readExpr();
+ expect(":");
+ expect("AT");
+ Expr LMAExpr = readParenExpr();
+ expect("{");
+
+ std::vector<BaseCommand *> V;
+ OutputSection *Prev = nullptr;
+ while (!errorCount() && !consume("}")) {
+ // VA is the same for all sections. The LMAs are consecutive in memory
+ // starting from the base load address specified.
+ OutputSection *OS = readOverlaySectionDescription();
+ OS->AddrExpr = AddrExpr;
+ if (Prev)
+ OS->LMAExpr = [=] { return Prev->getLMA() + Prev->Size; };
+ else
+ OS->LMAExpr = LMAExpr;
+ V.push_back(OS);
+ Prev = OS;
+ }
+
+ // According to the specification, at the end of the overlay, the location
+ // counter should be equal to the overlay base address plus size of the
+ // largest section seen in the overlay.
+ // Here we want to create the Dot assignment command to achieve that.
+ Expr MoveDot = [=] {
+ uint64_t Max = 0;
+ for (BaseCommand *Cmd : V)
+ Max = std::max(Max, cast<OutputSection>(Cmd)->Size);
+ return AddrExpr().getValue() + Max;
+ };
+ V.push_back(make<SymbolAssignment>(".", MoveDot, getCurrentLocation()));
+ return V;
+}
+
void ScriptParser::readSections() {
Script->HasSectionsCommand = true;
@@ -448,6 +493,12 @@ void ScriptParser::readSections() {
std::vector<BaseCommand *> V;
while (!errorCount() && !consume("}")) {
StringRef Tok = next();
+ if (Tok == "OVERLAY") {
+ for (BaseCommand *Cmd : readOverlay())
+ V.push_back(Cmd);
+ continue;
+ }
+
if (BaseCommand *Cmd = readAssignment(Tok))
V.push_back(Cmd);
else
@@ -673,6 +724,17 @@ static Expr checkAlignment(Expr E, std::string &Loc) {
};
}
+OutputSection *ScriptParser::readOverlaySectionDescription() {
+ OutputSection *Cmd =
+ Script->createOutputSection(next(), getCurrentLocation());
+ Cmd->InOverlay = true;
+ expect("{");
+ while (!errorCount() && !consume("}"))
+ Cmd->SectionCommands.push_back(readInputSectionRules(next()));
+ Cmd->Phdrs = readOutputSectionPhdrs();
+ return Cmd;
+}
+
OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
OutputSection *Cmd =
Script->createOutputSection(OutSec, getCurrentLocation());
OpenPOWER on IntegriCloud