diff options
Diffstat (limited to 'lld/ELF/ScriptParser.cpp')
-rw-r--r-- | lld/ELF/ScriptParser.cpp | 70 |
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) { |