Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lld/ELF/ScriptParser.cpp
Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | private: | ||||
void readExtern(); | void readExtern(); | ||||
void readGroup(); | void readGroup(); | ||||
void readInclude(); | void readInclude(); | ||||
void readInput(); | void readInput(); | ||||
void readMemory(); | void readMemory(); | ||||
void readOutput(); | void readOutput(); | ||||
void readOutputArch(); | void readOutputArch(); | ||||
void readOutputFormat(); | void readOutputFormat(); | ||||
void readOverwriteSections(); | |||||
void readPhdrs(); | void readPhdrs(); | ||||
void readRegionAlias(); | void readRegionAlias(); | ||||
void readSearchDir(); | void readSearchDir(); | ||||
void readSections(); | void readSections(); | ||||
void readTarget(); | void readTarget(); | ||||
void readVersion(); | void readVersion(); | ||||
void readVersionScriptCommand(); | void readVersionScriptCommand(); | ||||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | while (!atEOF()) { | ||||
} else if (tok == "MEMORY") { | } else if (tok == "MEMORY") { | ||||
readMemory(); | readMemory(); | ||||
} else if (tok == "OUTPUT") { | } else if (tok == "OUTPUT") { | ||||
readOutput(); | readOutput(); | ||||
} else if (tok == "OUTPUT_ARCH") { | } else if (tok == "OUTPUT_ARCH") { | ||||
readOutputArch(); | readOutputArch(); | ||||
} else if (tok == "OUTPUT_FORMAT") { | } else if (tok == "OUTPUT_FORMAT") { | ||||
readOutputFormat(); | readOutputFormat(); | ||||
} else if (tok == "OVERWRITE_SECTIONS") { | |||||
readOverwriteSections(); | |||||
} else if (tok == "PHDRS") { | } else if (tok == "PHDRS") { | ||||
readPhdrs(); | readPhdrs(); | ||||
} else if (tok == "REGION_ALIAS") { | } else if (tok == "REGION_ALIAS") { | ||||
readRegionAlias(); | readRegionAlias(); | ||||
} else if (tok == "SEARCH_DIR") { | } else if (tok == "SEARCH_DIR") { | ||||
readSearchDir(); | readSearchDir(); | ||||
} else if (tok == "SECTIONS") { | } else if (tok == "SECTIONS") { | ||||
readSections(); | readSections(); | ||||
Show All 11 Lines | |||||
void ScriptParser::readDefsym(StringRef name) { | void ScriptParser::readDefsym(StringRef name) { | ||||
if (errorCount()) | if (errorCount()) | ||||
return; | return; | ||||
Expr e = readExpr(); | Expr e = readExpr(); | ||||
if (!atEOF()) | if (!atEOF()) | ||||
setError("EOF expected, but got " + next()); | setError("EOF expected, but got " + next()); | ||||
SymbolAssignment *cmd = make<SymbolAssignment>(name, e, getCurrentLocation()); | SymbolAssignment *cmd = make<SymbolAssignment>(name, e, getCurrentLocation()); | ||||
script->sectionCommands.push_back(cmd); | script->sectionCommands.push_back(cmd); | ||||
peter.smith: expect("SECTIONS") will do a good job of preventing other linker script commands, but it may… | |||||
} | } | ||||
void ScriptParser::addFile(StringRef s) { | void ScriptParser::addFile(StringRef s) { | ||||
if (isUnderSysroot && s.startswith("/")) { | if (isUnderSysroot && s.startswith("/")) { | ||||
SmallString<128> pathData; | SmallString<128> pathData; | ||||
StringRef path = (config->sysroot + s).toStringRef(pathData); | StringRef path = (config->sysroot + s).toStringRef(pathData); | ||||
if (sys::fs::exists(path)) { | if (sys::fs::exists(path)) { | ||||
driver->addFile(saver.save(path), /*withLOption=*/false); | driver->addFile(saver.save(path), /*withLOption=*/false); | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | Expr moveDot = [=] { | ||||
for (BaseCommand *cmd : v) | for (BaseCommand *cmd : v) | ||||
max = std::max(max, cast<OutputSection>(cmd)->size); | max = std::max(max, cast<OutputSection>(cmd)->size); | ||||
return addrExpr().getValue() + max; | return addrExpr().getValue() + max; | ||||
}; | }; | ||||
v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation())); | v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation())); | ||||
return v; | return v; | ||||
} | } | ||||
void ScriptParser::readOverwriteSections() { | |||||
expect("{"); | |||||
while (!errorCount() && !consume("}")) | |||||
script->overwriteSections.push_back(readOutputSectionDescription(next())); | |||||
} | |||||
void ScriptParser::readSections() { | void ScriptParser::readSections() { | ||||
expect("{"); | expect("{"); | ||||
std::vector<BaseCommand *> v; | std::vector<BaseCommand *> v; | ||||
while (!errorCount() && !consume("}")) { | while (!errorCount() && !consume("}")) { | ||||
StringRef tok = next(); | StringRef tok = next(); | ||||
if (tok == "OVERLAY") { | if (tok == "OVERLAY") { | ||||
for (BaseCommand *cmd : readOverlay()) | for (BaseCommand *cmd : readOverlay()) | ||||
v.push_back(cmd); | v.push_back(cmd); | ||||
Show All 19 Lines | void ScriptParser::readSections() { | ||||
bool isAfter = false; | bool isAfter = false; | ||||
if (consume("AFTER")) | if (consume("AFTER")) | ||||
isAfter = true; | isAfter = true; | ||||
else if (!consume("BEFORE")) | else if (!consume("BEFORE")) | ||||
setError("expected AFTER/BEFORE, but got '" + next() + "'"); | setError("expected AFTER/BEFORE, but got '" + next() + "'"); | ||||
StringRef where = next(); | StringRef where = next(); | ||||
for (BaseCommand *cmd : v) | for (BaseCommand *cmd : v) | ||||
if (auto *os = dyn_cast<OutputSection>(cmd)) | if (auto *os = dyn_cast<OutputSection>(cmd)) | ||||
script->insertCommands.push_back({os, isAfter, where}); | script->insertCommands.push_back({os->name, isAfter, where}); | ||||
} | } | ||||
void ScriptParser::readTarget() { | void ScriptParser::readTarget() { | ||||
// TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, | // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, | ||||
// we accept only a limited set of BFD names (i.e. "elf" or "binary") | // we accept only a limited set of BFD names (i.e. "elf" or "binary") | ||||
// for --format. We recognize only /^elf/ and "binary" in the linker | // for --format. We recognize only /^elf/ and "binary" in the linker | ||||
// script as well. | // script as well. | ||||
expect("("); | expect("("); | ||||
▲ Show 20 Lines • Show All 1,070 Lines • Show Last 20 Lines |
expect("SECTIONS") will do a good job of preventing other linker script commands, but it may leave people wondering why? Would it be possible to do something like: