summaryrefslogtreecommitdiff
path: root/lld/ELF/ScriptParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/ScriptParser.cpp')
-rw-r--r--lld/ELF/ScriptParser.cpp57
1 files changed, 52 insertions, 5 deletions
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 107b4c6e7af0..bdbce396cba1 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -87,6 +87,8 @@ private:
OutputDesc *readOverlaySectionDescription();
OutputDesc *readOutputSectionDescription(StringRef outSec);
SmallVector<SectionCommand *, 0> readOverlay();
+ SectionClassDesc *readSectionClassDescription();
+ StringRef readSectionClassName();
SmallVector<StringRef, 0> readOutputSectionPhdrs();
std::pair<uint64_t, uint64_t> readInputSectionFlags();
InputSectionDescription *readInputSectionDescription(StringRef tok);
@@ -605,6 +607,33 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
return v;
}
+SectionClassDesc *ScriptParser::readSectionClassDescription() {
+ StringRef name = readSectionClassName();
+ SectionClassDesc *desc = make<SectionClassDesc>(name);
+ if (!script->sectionClasses.insert({CachedHashStringRef(name), desc}).second)
+ setError("section class '" + name + "' already defined");
+ expect("{");
+ while (auto tok = till("}")) {
+ if (tok == "(" || tok == ")") {
+ setError("expected filename pattern");
+ } else if (peek() == "(") {
+ InputSectionDescription *isd = readInputSectionDescription(tok);
+ if (!isd->classRef.empty())
+ setError("section class '" + name + "' references class '" +
+ isd->classRef + "'");
+ desc->sc.commands.push_back(isd);
+ }
+ }
+ return desc;
+}
+
+StringRef ScriptParser::readSectionClassName() {
+ expect("(");
+ StringRef name = unquote(next());
+ expect(")");
+ return name;
+}
+
void ScriptParser::readOverwriteSections() {
expect("{");
while (auto tok = till("}"))
@@ -619,7 +648,12 @@ void ScriptParser::readSections() {
for (SectionCommand *cmd : readOverlay())
v.push_back(cmd);
continue;
- } else if (tok == "INCLUDE") {
+ }
+ if (tok == "CLASS") {
+ v.push_back(readSectionClassDescription());
+ continue;
+ }
+ if (tok == "INCLUDE") {
readInclude();
continue;
}
@@ -822,8 +856,14 @@ ScriptParser::readInputSectionDescription(StringRef tok) {
expect("(");
if (consume("INPUT_SECTION_FLAGS"))
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
- InputSectionDescription *cmd =
- readInputSectionRules(next(), withFlags, withoutFlags);
+
+ tok = next();
+ InputSectionDescription *cmd;
+ if (tok == "CLASS")
+ cmd = make<InputSectionDescription>(StringRef{}, withFlags, withoutFlags,
+ readSectionClassName());
+ else
+ cmd = readInputSectionRules(tok, withFlags, withoutFlags);
expect(")");
script->keptSections.push_back(cmd);
return cmd;
@@ -832,6 +872,9 @@ ScriptParser::readInputSectionDescription(StringRef tok) {
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
tok = next();
}
+ if (tok == "CLASS")
+ return make<InputSectionDescription>(StringRef{}, withFlags, withoutFlags,
+ readSectionClassName());
return readInputSectionRules(tok, withFlags, withoutFlags);
}
@@ -951,8 +994,12 @@ OutputDesc *ScriptParser::readOverlaySectionDescription() {
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
tok = till("");
}
- osd->osec.commands.push_back(
- readInputSectionRules(tok, withFlags, withoutFlags));
+ if (tok == "CLASS")
+ osd->osec.commands.push_back(make<InputSectionDescription>(
+ StringRef{}, withFlags, withoutFlags, readSectionClassName()));
+ else
+ osd->osec.commands.push_back(
+ readInputSectionRules(tok, withFlags, withoutFlags));
}
osd->osec.phdrs = readOutputSectionPhdrs();
return osd;