[LLD] Add CLASS syntax to SECTIONS (#95323)
This allows the input section matching algorithm to be separated from output section descriptions. This allows a group of sections to be assigned to multiple output sections, providing an explicit version of --enable-non-contiguous-regions's spilling that doesn't require altering global linker script matching behavior with a flag. It also makes the linker script language more expressive even if spilling is not intended, since input section matching can be done in a different order than sections are placed in an output section. The implementation reuses the backend mechanism provided by --enable-non-contiguous-regions, so it has roughly similar semantics and limitations. In particular, sections cannot be spilled into or out of INSERT, OVERWRITE_SECTIONS, or /DISCARD/. The former two aren't intrinsic, so it may be possible to relax those restrictions later.
This commit is contained in:
committed by
GitHub
parent
88d288489e
commit
7e8a9020b1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user