aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/ScriptParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/ScriptParser.cpp')
-rw-r--r--lld/ELF/ScriptParser.cpp70
1 files changed, 39 insertions, 31 deletions
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index ad3b3e61ad59..d3b0296acab0 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -93,7 +93,7 @@ private:
void readSectionAddressType(OutputSection *cmd);
OutputSection *readOverlaySectionDescription();
OutputSection *readOutputSectionDescription(StringRef outSec);
- std::vector<BaseCommand *> readOverlay();
+ std::vector<SectionCommand *> readOverlay();
std::vector<StringRef> readOutputSectionPhdrs();
std::pair<uint64_t, uint64_t> readInputSectionFlags();
InputSectionDescription *readInputSectionDescription(StringRef tok);
@@ -113,7 +113,8 @@ private:
Expr getPageSize();
Expr readMemoryAssignment(StringRef, StringRef, StringRef);
- std::pair<uint32_t, uint32_t> readMemoryAttributes();
+ void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
+ uint32_t &negFlags, uint32_t &negInvFlags);
Expr combine(StringRef op, Expr l, Expr r);
Expr readExpr();
@@ -518,7 +519,7 @@ void ScriptParser::readSearchDir() {
// 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() {
+std::vector<SectionCommand *> 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.
@@ -528,7 +529,7 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
Expr lmaExpr = readParenExpr();
expect("{");
- std::vector<BaseCommand *> v;
+ std::vector<SectionCommand *> v;
OutputSection *prev = nullptr;
while (!errorCount() && !consume("}")) {
// VA is the same for all sections. The LMAs are consecutive in memory
@@ -549,7 +550,7 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
// Here we want to create the Dot assignment command to achieve that.
Expr moveDot = [=] {
uint64_t max = 0;
- for (BaseCommand *cmd : v)
+ for (SectionCommand *cmd : v)
max = std::max(max, cast<OutputSection>(cmd)->size);
return addrExpr().getValue() + max;
};
@@ -565,11 +566,11 @@ void ScriptParser::readOverwriteSections() {
void ScriptParser::readSections() {
expect("{");
- std::vector<BaseCommand *> v;
+ std::vector<SectionCommand *> v;
while (!errorCount() && !consume("}")) {
StringRef tok = next();
if (tok == "OVERLAY") {
- for (BaseCommand *cmd : readOverlay())
+ for (SectionCommand *cmd : readOverlay())
v.push_back(cmd);
continue;
} else if (tok == "INCLUDE") {
@@ -577,7 +578,7 @@ void ScriptParser::readSections() {
continue;
}
- if (BaseCommand *cmd = readAssignment(tok))
+ if (SectionCommand *cmd = readAssignment(tok))
v.push_back(cmd);
else
v.push_back(readOutputSectionDescription(tok));
@@ -597,7 +598,7 @@ void ScriptParser::readSections() {
setError("expected AFTER/BEFORE, but got '" + next() + "'");
StringRef where = next();
std::vector<StringRef> names;
- for (BaseCommand *cmd : v)
+ for (SectionCommand *cmd : v)
if (auto *os = dyn_cast<OutputSection>(cmd))
names.push_back(os->name);
if (!names.empty())
@@ -848,7 +849,7 @@ OutputSection *ScriptParser::readOverlaySectionDescription() {
uint64_t withoutFlags = 0;
if (consume("INPUT_SECTION_FLAGS"))
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
- cmd->sectionCommands.push_back(
+ cmd->commands.push_back(
readInputSectionRules(next(), withFlags, withoutFlags));
}
return cmd;
@@ -884,9 +885,9 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
if (tok == ";") {
// Empty commands are allowed. Do nothing here.
} else if (SymbolAssignment *assign = readAssignment(tok)) {
- cmd->sectionCommands.push_back(assign);
+ cmd->commands.push_back(assign);
} else if (ByteCommand *data = readByteCommand(tok)) {
- cmd->sectionCommands.push_back(data);
+ cmd->commands.push_back(data);
} else if (tok == "CONSTRUCTORS") {
// CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
// by name. This is for very old file formats such as ECOFF/XCOFF.
@@ -903,7 +904,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
} else if (tok == "INCLUDE") {
readInclude();
} else if (peek() == "(") {
- cmd->sectionCommands.push_back(readInputSectionDescription(tok));
+ cmd->commands.push_back(readInputSectionDescription(tok));
} else {
// We have a file name and no input sections description. It is not a
// commonly used syntax, but still acceptable. In that case, all sections
@@ -913,7 +914,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
// case above.
auto *isd = make<InputSectionDescription>(tok);
isd->sectionPatterns.push_back({{}, StringMatcher("*")});
- cmd->sectionCommands.push_back(isd);
+ cmd->commands.push_back(isd);
}
}
@@ -1614,9 +1615,11 @@ void ScriptParser::readMemory() {
}
uint32_t flags = 0;
+ uint32_t invFlags = 0;
uint32_t negFlags = 0;
+ uint32_t negInvFlags = 0;
if (consume("(")) {
- std::tie(flags, negFlags) = readMemoryAttributes();
+ readMemoryAttributes(flags, invFlags, negFlags, negInvFlags);
expect(")");
}
expect(":");
@@ -1626,7 +1629,8 @@ void ScriptParser::readMemory() {
Expr length = readMemoryAssignment("LENGTH", "len", "l");
// Add the memory region to the region map.
- MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, negFlags);
+ MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags,
+ negFlags, negInvFlags);
if (!script->memoryRegions.insert({tok, mr}).second)
setError("region '" + tok + "' already defined");
}
@@ -1635,30 +1639,34 @@ void ScriptParser::readMemory() {
// This function parses the attributes used to match against section
// flags when placing output sections in a memory region. These flags
// are only used when an explicit memory region name is not used.
-std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() {
- uint32_t flags = 0;
- uint32_t negFlags = 0;
+void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
+ uint32_t &negFlags,
+ uint32_t &negInvFlags) {
bool invert = false;
for (char c : next().lower()) {
- uint32_t flag = 0;
- if (c == '!')
+ if (c == '!') {
invert = !invert;
- else if (c == 'w')
- flag = SHF_WRITE;
+ std::swap(flags, negFlags);
+ std::swap(invFlags, negInvFlags);
+ continue;
+ }
+ if (c == 'w')
+ flags |= SHF_WRITE;
else if (c == 'x')
- flag = SHF_EXECINSTR;
+ flags |= SHF_EXECINSTR;
else if (c == 'a')
- flag = SHF_ALLOC;
- else if (c != 'r')
+ flags |= SHF_ALLOC;
+ else if (c == 'r')
+ invFlags |= SHF_WRITE;
+ else
setError("invalid memory region attribute");
+ }
- if (invert)
- negFlags |= flag;
- else
- flags |= flag;
+ if (invert) {
+ std::swap(flags, negFlags);
+ std::swap(invFlags, negInvFlags);
}
- return {flags, negFlags};
}
void elf::readLinkerScript(MemoryBufferRef mb) {