10b57cec5SDimitry Andric //===- ScriptParser.cpp ---------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a recursive-descendent parser for linker scripts.
100b57cec5SDimitry Andric // Parsed results are stored to Config and Script global objects.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "ScriptParser.h"
150b57cec5SDimitry Andric #include "Config.h"
160b57cec5SDimitry Andric #include "Driver.h"
1781ad6265SDimitry Andric #include "InputFiles.h"
180b57cec5SDimitry Andric #include "LinkerScript.h"
190b57cec5SDimitry Andric #include "OutputSections.h"
200b57cec5SDimitry Andric #include "ScriptLexer.h"
2181ad6265SDimitry Andric #include "SymbolTable.h"
220b57cec5SDimitry Andric #include "Symbols.h"
230b57cec5SDimitry Andric #include "Target.h"
2404eeddc0SDimitry Andric #include "lld/Common/CommonLinkerContext.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
260b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
270b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
280b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
290b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
300b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
310b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
320b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
33e8d8bef9SDimitry Andric #include "llvm/Support/MathExtras.h"
340b57cec5SDimitry Andric #include "llvm/Support/Path.h"
3581ad6265SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
36e8d8bef9SDimitry Andric #include "llvm/Support/TimeProfiler.h"
370b57cec5SDimitry Andric #include <cassert>
380b57cec5SDimitry Andric #include <limits>
39*0fca6ea1SDimitry Andric #include <optional>
400b57cec5SDimitry Andric #include <vector>
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric using namespace llvm::ELF;
440b57cec5SDimitry Andric using namespace llvm::support::endian;
455ffd83dbSDimitry Andric using namespace lld;
465ffd83dbSDimitry Andric using namespace lld::elf;
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric namespace {
490b57cec5SDimitry Andric class ScriptParser final : ScriptLexer {
500b57cec5SDimitry Andric public:
ScriptParser(MemoryBufferRef mb)510b57cec5SDimitry Andric ScriptParser(MemoryBufferRef mb) : ScriptLexer(mb) {
520b57cec5SDimitry Andric // Initialize IsUnderSysroot
530b57cec5SDimitry Andric if (config->sysroot == "")
540b57cec5SDimitry Andric return;
550b57cec5SDimitry Andric StringRef path = mb.getBufferIdentifier();
560b57cec5SDimitry Andric for (; !path.empty(); path = sys::path::parent_path(path)) {
570b57cec5SDimitry Andric if (!sys::fs::equivalent(config->sysroot, path))
580b57cec5SDimitry Andric continue;
590b57cec5SDimitry Andric isUnderSysroot = true;
600b57cec5SDimitry Andric return;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric void readLinkerScript();
650b57cec5SDimitry Andric void readVersionScript();
660b57cec5SDimitry Andric void readDynamicList();
670b57cec5SDimitry Andric void readDefsym(StringRef name);
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric private:
700b57cec5SDimitry Andric void addFile(StringRef path);
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric void readAsNeeded();
730b57cec5SDimitry Andric void readEntry();
740b57cec5SDimitry Andric void readExtern();
750b57cec5SDimitry Andric void readGroup();
760b57cec5SDimitry Andric void readInclude();
770b57cec5SDimitry Andric void readInput();
780b57cec5SDimitry Andric void readMemory();
790b57cec5SDimitry Andric void readOutput();
800b57cec5SDimitry Andric void readOutputArch();
810b57cec5SDimitry Andric void readOutputFormat();
82fe6060f1SDimitry Andric void readOverwriteSections();
830b57cec5SDimitry Andric void readPhdrs();
840b57cec5SDimitry Andric void readRegionAlias();
850b57cec5SDimitry Andric void readSearchDir();
860b57cec5SDimitry Andric void readSections();
870b57cec5SDimitry Andric void readTarget();
880b57cec5SDimitry Andric void readVersion();
890b57cec5SDimitry Andric void readVersionScriptCommand();
90*0fca6ea1SDimitry Andric void readNoCrossRefs(bool to);
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric SymbolAssignment *readSymbolAssignment(StringRef name);
930b57cec5SDimitry Andric ByteCommand *readByteCommand(StringRef tok);
940b57cec5SDimitry Andric std::array<uint8_t, 4> readFill();
95*0fca6ea1SDimitry Andric bool readSectionDirective(OutputSection *cmd, StringRef tok);
960b57cec5SDimitry Andric void readSectionAddressType(OutputSection *cmd);
9781ad6265SDimitry Andric OutputDesc *readOverlaySectionDescription();
9881ad6265SDimitry Andric OutputDesc *readOutputSectionDescription(StringRef outSec);
9904eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> readOverlay();
10004eeddc0SDimitry Andric SmallVector<StringRef, 0> readOutputSectionPhdrs();
1015ffd83dbSDimitry Andric std::pair<uint64_t, uint64_t> readInputSectionFlags();
1020b57cec5SDimitry Andric InputSectionDescription *readInputSectionDescription(StringRef tok);
1030b57cec5SDimitry Andric StringMatcher readFilePatterns();
10404eeddc0SDimitry Andric SmallVector<SectionPattern, 0> readInputSectionsList();
1055ffd83dbSDimitry Andric InputSectionDescription *readInputSectionRules(StringRef filePattern,
1065ffd83dbSDimitry Andric uint64_t withFlags,
1075ffd83dbSDimitry Andric uint64_t withoutFlags);
1080b57cec5SDimitry Andric unsigned readPhdrType();
109e8d8bef9SDimitry Andric SortSectionPolicy peekSortKind();
1100b57cec5SDimitry Andric SortSectionPolicy readSortKind();
1110b57cec5SDimitry Andric SymbolAssignment *readProvideHidden(bool provide, bool hidden);
1120b57cec5SDimitry Andric SymbolAssignment *readAssignment(StringRef tok);
1130b57cec5SDimitry Andric void readSort();
1140b57cec5SDimitry Andric Expr readAssert();
1150b57cec5SDimitry Andric Expr readConstant();
1160b57cec5SDimitry Andric Expr getPageSize();
1170b57cec5SDimitry Andric
1185ffd83dbSDimitry Andric Expr readMemoryAssignment(StringRef, StringRef, StringRef);
1194824e7fdSDimitry Andric void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
1204824e7fdSDimitry Andric uint32_t &negFlags, uint32_t &negInvFlags);
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric Expr combine(StringRef op, Expr l, Expr r);
1230b57cec5SDimitry Andric Expr readExpr();
1240b57cec5SDimitry Andric Expr readExpr1(Expr lhs, int minPrec);
1250b57cec5SDimitry Andric StringRef readParenLiteral();
1260b57cec5SDimitry Andric Expr readPrimary();
1270b57cec5SDimitry Andric Expr readTernary(Expr cond);
1280b57cec5SDimitry Andric Expr readParenExpr();
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric // For parsing version script.
13104eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> readVersionExtern();
1320b57cec5SDimitry Andric void readAnonymousDeclaration();
1330b57cec5SDimitry Andric void readVersionDeclaration(StringRef verStr);
1340b57cec5SDimitry Andric
13504eeddc0SDimitry Andric std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
1360b57cec5SDimitry Andric readSymbols();
1370b57cec5SDimitry Andric
138349cc55cSDimitry Andric // True if a script being read is in the --sysroot directory.
1390b57cec5SDimitry Andric bool isUnderSysroot = false;
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric // A set to detect an INCLUDE() cycle.
1420b57cec5SDimitry Andric StringSet<> seen;
143*0fca6ea1SDimitry Andric
144*0fca6ea1SDimitry Andric // If we are currently parsing a PROVIDE|PROVIDE_HIDDEN command,
145*0fca6ea1SDimitry Andric // then this member is set to the PROVIDE symbol name.
146*0fca6ea1SDimitry Andric std::optional<llvm::StringRef> activeProvideSym;
1470b57cec5SDimitry Andric };
1480b57cec5SDimitry Andric } // namespace
1490b57cec5SDimitry Andric
unquote(StringRef s)1500b57cec5SDimitry Andric static StringRef unquote(StringRef s) {
15106c3fb27SDimitry Andric if (s.starts_with("\""))
1520b57cec5SDimitry Andric return s.substr(1, s.size() - 2);
1530b57cec5SDimitry Andric return s;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric // Some operations only support one non absolute value. Move the
1570b57cec5SDimitry Andric // absolute one to the right hand side for convenience.
moveAbsRight(ExprValue & a,ExprValue & b)1580b57cec5SDimitry Andric static void moveAbsRight(ExprValue &a, ExprValue &b) {
1590b57cec5SDimitry Andric if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
1600b57cec5SDimitry Andric std::swap(a, b);
1610b57cec5SDimitry Andric if (!b.isAbsolute())
162*0fca6ea1SDimitry Andric script->recordError(
163*0fca6ea1SDimitry Andric a.loc + ": at least one side of the expression must be absolute");
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
add(ExprValue a,ExprValue b)1660b57cec5SDimitry Andric static ExprValue add(ExprValue a, ExprValue b) {
1670b57cec5SDimitry Andric moveAbsRight(a, b);
1680b57cec5SDimitry Andric return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric
sub(ExprValue a,ExprValue b)1710b57cec5SDimitry Andric static ExprValue sub(ExprValue a, ExprValue b) {
1720b57cec5SDimitry Andric // The distance between two symbols in sections is absolute.
1730b57cec5SDimitry Andric if (!a.isAbsolute() && !b.isAbsolute())
1740b57cec5SDimitry Andric return a.getValue() - b.getValue();
1750b57cec5SDimitry Andric return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric
bitAnd(ExprValue a,ExprValue b)1780b57cec5SDimitry Andric static ExprValue bitAnd(ExprValue a, ExprValue b) {
1790b57cec5SDimitry Andric moveAbsRight(a, b);
1800b57cec5SDimitry Andric return {a.sec, a.forceAbsolute,
1810b57cec5SDimitry Andric (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
bitXor(ExprValue a,ExprValue b)18406c3fb27SDimitry Andric static ExprValue bitXor(ExprValue a, ExprValue b) {
18506c3fb27SDimitry Andric moveAbsRight(a, b);
18606c3fb27SDimitry Andric return {a.sec, a.forceAbsolute,
18706c3fb27SDimitry Andric (a.getValue() ^ b.getValue()) - a.getSecAddr(), a.loc};
18806c3fb27SDimitry Andric }
18906c3fb27SDimitry Andric
bitOr(ExprValue a,ExprValue b)1900b57cec5SDimitry Andric static ExprValue bitOr(ExprValue a, ExprValue b) {
1910b57cec5SDimitry Andric moveAbsRight(a, b);
1920b57cec5SDimitry Andric return {a.sec, a.forceAbsolute,
1930b57cec5SDimitry Andric (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
readDynamicList()1960b57cec5SDimitry Andric void ScriptParser::readDynamicList() {
1970b57cec5SDimitry Andric expect("{");
19804eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
19904eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
2000b57cec5SDimitry Andric std::tie(locals, globals) = readSymbols();
2010b57cec5SDimitry Andric expect(";");
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric if (!atEOF()) {
2040b57cec5SDimitry Andric setError("EOF expected, but got " + next());
2050b57cec5SDimitry Andric return;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric if (!locals.empty()) {
2080b57cec5SDimitry Andric setError("\"local:\" scope not supported in --dynamic-list");
2090b57cec5SDimitry Andric return;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric for (SymbolVersion v : globals)
2130b57cec5SDimitry Andric config->dynamicList.push_back(v);
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric
readVersionScript()2160b57cec5SDimitry Andric void ScriptParser::readVersionScript() {
2170b57cec5SDimitry Andric readVersionScriptCommand();
2180b57cec5SDimitry Andric if (!atEOF())
2190b57cec5SDimitry Andric setError("EOF expected, but got " + next());
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric
readVersionScriptCommand()2220b57cec5SDimitry Andric void ScriptParser::readVersionScriptCommand() {
2230b57cec5SDimitry Andric if (consume("{")) {
2240b57cec5SDimitry Andric readAnonymousDeclaration();
2250b57cec5SDimitry Andric return;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric while (!atEOF() && !errorCount() && peek() != "}") {
2290b57cec5SDimitry Andric StringRef verStr = next();
2300b57cec5SDimitry Andric if (verStr == "{") {
2310b57cec5SDimitry Andric setError("anonymous version definition is used in "
2320b57cec5SDimitry Andric "combination with other version definitions");
2330b57cec5SDimitry Andric return;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric expect("{");
2360b57cec5SDimitry Andric readVersionDeclaration(verStr);
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric
readVersion()2400b57cec5SDimitry Andric void ScriptParser::readVersion() {
2410b57cec5SDimitry Andric expect("{");
2420b57cec5SDimitry Andric readVersionScriptCommand();
2430b57cec5SDimitry Andric expect("}");
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
readLinkerScript()2460b57cec5SDimitry Andric void ScriptParser::readLinkerScript() {
2470b57cec5SDimitry Andric while (!atEOF()) {
2480b57cec5SDimitry Andric StringRef tok = next();
2490b57cec5SDimitry Andric if (tok == ";")
2500b57cec5SDimitry Andric continue;
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric if (tok == "ENTRY") {
2530b57cec5SDimitry Andric readEntry();
2540b57cec5SDimitry Andric } else if (tok == "EXTERN") {
2550b57cec5SDimitry Andric readExtern();
2560b57cec5SDimitry Andric } else if (tok == "GROUP") {
2570b57cec5SDimitry Andric readGroup();
2580b57cec5SDimitry Andric } else if (tok == "INCLUDE") {
2590b57cec5SDimitry Andric readInclude();
2600b57cec5SDimitry Andric } else if (tok == "INPUT") {
2610b57cec5SDimitry Andric readInput();
2620b57cec5SDimitry Andric } else if (tok == "MEMORY") {
2630b57cec5SDimitry Andric readMemory();
2640b57cec5SDimitry Andric } else if (tok == "OUTPUT") {
2650b57cec5SDimitry Andric readOutput();
2660b57cec5SDimitry Andric } else if (tok == "OUTPUT_ARCH") {
2670b57cec5SDimitry Andric readOutputArch();
2680b57cec5SDimitry Andric } else if (tok == "OUTPUT_FORMAT") {
2690b57cec5SDimitry Andric readOutputFormat();
270fe6060f1SDimitry Andric } else if (tok == "OVERWRITE_SECTIONS") {
271fe6060f1SDimitry Andric readOverwriteSections();
2720b57cec5SDimitry Andric } else if (tok == "PHDRS") {
2730b57cec5SDimitry Andric readPhdrs();
2740b57cec5SDimitry Andric } else if (tok == "REGION_ALIAS") {
2750b57cec5SDimitry Andric readRegionAlias();
2760b57cec5SDimitry Andric } else if (tok == "SEARCH_DIR") {
2770b57cec5SDimitry Andric readSearchDir();
2780b57cec5SDimitry Andric } else if (tok == "SECTIONS") {
2790b57cec5SDimitry Andric readSections();
2800b57cec5SDimitry Andric } else if (tok == "TARGET") {
2810b57cec5SDimitry Andric readTarget();
2820b57cec5SDimitry Andric } else if (tok == "VERSION") {
2830b57cec5SDimitry Andric readVersion();
284*0fca6ea1SDimitry Andric } else if (tok == "NOCROSSREFS") {
285*0fca6ea1SDimitry Andric readNoCrossRefs(/*to=*/false);
286*0fca6ea1SDimitry Andric } else if (tok == "NOCROSSREFS_TO") {
287*0fca6ea1SDimitry Andric readNoCrossRefs(/*to=*/true);
2880b57cec5SDimitry Andric } else if (SymbolAssignment *cmd = readAssignment(tok)) {
2890b57cec5SDimitry Andric script->sectionCommands.push_back(cmd);
2900b57cec5SDimitry Andric } else {
2910b57cec5SDimitry Andric setError("unknown directive: " + tok);
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
readDefsym(StringRef name)2960b57cec5SDimitry Andric void ScriptParser::readDefsym(StringRef name) {
2970b57cec5SDimitry Andric if (errorCount())
2980b57cec5SDimitry Andric return;
2990b57cec5SDimitry Andric Expr e = readExpr();
3000b57cec5SDimitry Andric if (!atEOF())
3010b57cec5SDimitry Andric setError("EOF expected, but got " + next());
3027a6dacacSDimitry Andric auto *cmd = make<SymbolAssignment>(
3037a6dacacSDimitry Andric name, e, 0, getCurrentMB().getBufferIdentifier().str());
3040b57cec5SDimitry Andric script->sectionCommands.push_back(cmd);
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
readNoCrossRefs(bool to)307*0fca6ea1SDimitry Andric void ScriptParser::readNoCrossRefs(bool to) {
308*0fca6ea1SDimitry Andric expect("(");
309*0fca6ea1SDimitry Andric NoCrossRefCommand cmd{{}, to};
310*0fca6ea1SDimitry Andric while (!errorCount() && !consume(")"))
311*0fca6ea1SDimitry Andric cmd.outputSections.push_back(unquote(next()));
312*0fca6ea1SDimitry Andric if (cmd.outputSections.size() < 2)
313*0fca6ea1SDimitry Andric warn(getCurrentLocation() + ": ignored with fewer than 2 output sections");
314*0fca6ea1SDimitry Andric else
315*0fca6ea1SDimitry Andric script->noCrossRefs.push_back(std::move(cmd));
316*0fca6ea1SDimitry Andric }
317*0fca6ea1SDimitry Andric
addFile(StringRef s)3180b57cec5SDimitry Andric void ScriptParser::addFile(StringRef s) {
31906c3fb27SDimitry Andric if (isUnderSysroot && s.starts_with("/")) {
3200b57cec5SDimitry Andric SmallString<128> pathData;
3210b57cec5SDimitry Andric StringRef path = (config->sysroot + s).toStringRef(pathData);
322fe6060f1SDimitry Andric if (sys::fs::exists(path))
323bdd1243dSDimitry Andric ctx.driver.addFile(saver().save(path), /*withLOption=*/false);
324fe6060f1SDimitry Andric else
325fe6060f1SDimitry Andric setError("cannot find " + s + " inside " + config->sysroot);
3260b57cec5SDimitry Andric return;
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric
32906c3fb27SDimitry Andric if (s.starts_with("/")) {
3305ffd83dbSDimitry Andric // Case 1: s is an absolute path. Just open it.
331bdd1243dSDimitry Andric ctx.driver.addFile(s, /*withLOption=*/false);
33206c3fb27SDimitry Andric } else if (s.starts_with("=")) {
3335ffd83dbSDimitry Andric // Case 2: relative to the sysroot.
3340b57cec5SDimitry Andric if (config->sysroot.empty())
335bdd1243dSDimitry Andric ctx.driver.addFile(s.substr(1), /*withLOption=*/false);
3360b57cec5SDimitry Andric else
337bdd1243dSDimitry Andric ctx.driver.addFile(saver().save(config->sysroot + "/" + s.substr(1)),
3380b57cec5SDimitry Andric /*withLOption=*/false);
33906c3fb27SDimitry Andric } else if (s.starts_with("-l")) {
3405ffd83dbSDimitry Andric // Case 3: search in the list of library paths.
341bdd1243dSDimitry Andric ctx.driver.addLibrary(s.substr(2));
3425ffd83dbSDimitry Andric } else {
3435ffd83dbSDimitry Andric // Case 4: s is a relative path. Search in the directory of the script file.
3445ffd83dbSDimitry Andric std::string filename = std::string(getCurrentMB().getBufferIdentifier());
3455ffd83dbSDimitry Andric StringRef directory = sys::path::parent_path(filename);
3465ffd83dbSDimitry Andric if (!directory.empty()) {
3475ffd83dbSDimitry Andric SmallString<0> path(directory);
3485ffd83dbSDimitry Andric sys::path::append(path, s);
3495ffd83dbSDimitry Andric if (sys::fs::exists(path)) {
350bdd1243dSDimitry Andric ctx.driver.addFile(path, /*withLOption=*/false);
3515ffd83dbSDimitry Andric return;
3525ffd83dbSDimitry Andric }
3535ffd83dbSDimitry Andric }
3545ffd83dbSDimitry Andric // Then search in the current working directory.
3555ffd83dbSDimitry Andric if (sys::fs::exists(s)) {
356bdd1243dSDimitry Andric ctx.driver.addFile(s, /*withLOption=*/false);
3570b57cec5SDimitry Andric } else {
3585ffd83dbSDimitry Andric // Finally, search in the list of library paths.
359bdd1243dSDimitry Andric if (std::optional<std::string> path = findFromSearchPaths(s))
360bdd1243dSDimitry Andric ctx.driver.addFile(saver().save(*path), /*withLOption=*/true);
3610b57cec5SDimitry Andric else
3620b57cec5SDimitry Andric setError("unable to find " + s);
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric }
3655ffd83dbSDimitry Andric }
3660b57cec5SDimitry Andric
readAsNeeded()3670b57cec5SDimitry Andric void ScriptParser::readAsNeeded() {
3680b57cec5SDimitry Andric expect("(");
3690b57cec5SDimitry Andric bool orig = config->asNeeded;
3700b57cec5SDimitry Andric config->asNeeded = true;
3710b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
3720b57cec5SDimitry Andric addFile(unquote(next()));
3730b57cec5SDimitry Andric config->asNeeded = orig;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric
readEntry()3760b57cec5SDimitry Andric void ScriptParser::readEntry() {
3770b57cec5SDimitry Andric // -e <symbol> takes predecence over ENTRY(<symbol>).
3780b57cec5SDimitry Andric expect("(");
3790b57cec5SDimitry Andric StringRef tok = next();
3800b57cec5SDimitry Andric if (config->entry.empty())
38181ad6265SDimitry Andric config->entry = unquote(tok);
3820b57cec5SDimitry Andric expect(")");
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
readExtern()3850b57cec5SDimitry Andric void ScriptParser::readExtern() {
3860b57cec5SDimitry Andric expect("(");
3870b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
3880b57cec5SDimitry Andric config->undefined.push_back(unquote(next()));
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
readGroup()3910b57cec5SDimitry Andric void ScriptParser::readGroup() {
3920b57cec5SDimitry Andric bool orig = InputFile::isInGroup;
3930b57cec5SDimitry Andric InputFile::isInGroup = true;
3940b57cec5SDimitry Andric readInput();
3950b57cec5SDimitry Andric InputFile::isInGroup = orig;
3960b57cec5SDimitry Andric if (!orig)
3970b57cec5SDimitry Andric ++InputFile::nextGroupId;
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric
readInclude()4000b57cec5SDimitry Andric void ScriptParser::readInclude() {
4010b57cec5SDimitry Andric StringRef tok = unquote(next());
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric if (!seen.insert(tok).second) {
4040b57cec5SDimitry Andric setError("there is a cycle in linker script INCLUDEs");
4050b57cec5SDimitry Andric return;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric
408bdd1243dSDimitry Andric if (std::optional<std::string> path = searchScript(tok)) {
409bdd1243dSDimitry Andric if (std::optional<MemoryBufferRef> mb = readFile(*path))
4100b57cec5SDimitry Andric tokenize(*mb);
4110b57cec5SDimitry Andric return;
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric setError("cannot find linker script " + tok);
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric
readInput()4160b57cec5SDimitry Andric void ScriptParser::readInput() {
4170b57cec5SDimitry Andric expect("(");
4180b57cec5SDimitry Andric while (!errorCount() && !consume(")")) {
4190b57cec5SDimitry Andric if (consume("AS_NEEDED"))
4200b57cec5SDimitry Andric readAsNeeded();
4210b57cec5SDimitry Andric else
4220b57cec5SDimitry Andric addFile(unquote(next()));
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric
readOutput()4260b57cec5SDimitry Andric void ScriptParser::readOutput() {
4270b57cec5SDimitry Andric // -o <file> takes predecence over OUTPUT(<file>).
4280b57cec5SDimitry Andric expect("(");
4290b57cec5SDimitry Andric StringRef tok = next();
4300b57cec5SDimitry Andric if (config->outputFile.empty())
4310b57cec5SDimitry Andric config->outputFile = unquote(tok);
4320b57cec5SDimitry Andric expect(")");
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric
readOutputArch()4350b57cec5SDimitry Andric void ScriptParser::readOutputArch() {
4360b57cec5SDimitry Andric // OUTPUT_ARCH is ignored for now.
4370b57cec5SDimitry Andric expect("(");
4380b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
4390b57cec5SDimitry Andric skip();
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric
parseBfdName(StringRef s)4420b57cec5SDimitry Andric static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
4430b57cec5SDimitry Andric return StringSwitch<std::pair<ELFKind, uint16_t>>(s)
4440b57cec5SDimitry Andric .Case("elf32-i386", {ELF32LEKind, EM_386})
44581ad6265SDimitry Andric .Case("elf32-avr", {ELF32LEKind, EM_AVR})
4460b57cec5SDimitry Andric .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})
4470b57cec5SDimitry Andric .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})
44806c3fb27SDimitry Andric .Case("elf32-bigarm", {ELF32BEKind, EM_ARM})
4490b57cec5SDimitry Andric .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64})
4500b57cec5SDimitry Andric .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64})
4510b57cec5SDimitry Andric .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64})
452fe6060f1SDimitry Andric .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64})
4530b57cec5SDimitry Andric .Case("elf32-powerpc", {ELF32BEKind, EM_PPC})
454e8d8bef9SDimitry Andric .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC})
4550b57cec5SDimitry Andric .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64})
4560b57cec5SDimitry Andric .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64})
4570b57cec5SDimitry Andric .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64})
4580b57cec5SDimitry Andric .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS})
4590b57cec5SDimitry Andric .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS})
4600b57cec5SDimitry Andric .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS})
4610b57cec5SDimitry Andric .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})
4620b57cec5SDimitry Andric .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS})
4630b57cec5SDimitry Andric .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})
4640b57cec5SDimitry Andric .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV})
4650b57cec5SDimitry Andric .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
4665ffd83dbSDimitry Andric .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9})
467e8d8bef9SDimitry Andric .Case("elf32-msp430", {ELF32LEKind, EM_MSP430})
46806c3fb27SDimitry Andric .Case("elf32-loongarch", {ELF32LEKind, EM_LOONGARCH})
46906c3fb27SDimitry Andric .Case("elf64-loongarch", {ELF64LEKind, EM_LOONGARCH})
47074626c16SDimitry Andric .Case("elf64-s390", {ELF64BEKind, EM_S390})
471*0fca6ea1SDimitry Andric .Cases("elf32-hexagon", "elf32-littlehexagon", {ELF32LEKind, EM_HEXAGON})
4720b57cec5SDimitry Andric .Default({ELFNoneKind, EM_NONE});
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
475fe6060f1SDimitry Andric // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose
476fe6060f1SDimitry Andric // big if -EB is specified, little if -EL is specified, or default if neither is
477fe6060f1SDimitry Andric // specified.
readOutputFormat()4780b57cec5SDimitry Andric void ScriptParser::readOutputFormat() {
4790b57cec5SDimitry Andric expect("(");
4800b57cec5SDimitry Andric
481*0fca6ea1SDimitry Andric StringRef s = unquote(next());
482fe6060f1SDimitry Andric if (!consume(")")) {
483fe6060f1SDimitry Andric expect(",");
484*0fca6ea1SDimitry Andric StringRef tmp = unquote(next());
485fe6060f1SDimitry Andric if (config->optEB)
486*0fca6ea1SDimitry Andric s = tmp;
487fe6060f1SDimitry Andric expect(",");
488*0fca6ea1SDimitry Andric tmp = unquote(next());
489fe6060f1SDimitry Andric if (config->optEL)
490*0fca6ea1SDimitry Andric s = tmp;
491fe6060f1SDimitry Andric consume(")");
492fe6060f1SDimitry Andric }
493*0fca6ea1SDimitry Andric // If more than one OUTPUT_FORMAT is specified, only the first is checked.
494*0fca6ea1SDimitry Andric if (!config->bfdname.empty())
495*0fca6ea1SDimitry Andric return;
496*0fca6ea1SDimitry Andric config->bfdname = s;
497*0fca6ea1SDimitry Andric
498*0fca6ea1SDimitry Andric if (s == "binary") {
499*0fca6ea1SDimitry Andric config->oFormatBinary = true;
500*0fca6ea1SDimitry Andric return;
501*0fca6ea1SDimitry Andric }
502*0fca6ea1SDimitry Andric
5030b57cec5SDimitry Andric if (s.consume_back("-freebsd"))
5040b57cec5SDimitry Andric config->osabi = ELFOSABI_FREEBSD;
5050b57cec5SDimitry Andric
5060b57cec5SDimitry Andric std::tie(config->ekind, config->emachine) = parseBfdName(s);
5070b57cec5SDimitry Andric if (config->emachine == EM_NONE)
5085ffd83dbSDimitry Andric setError("unknown output format name: " + config->bfdname);
5090b57cec5SDimitry Andric if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips")
5100b57cec5SDimitry Andric config->mipsN32Abi = true;
511e8d8bef9SDimitry Andric if (config->emachine == EM_MSP430)
512e8d8bef9SDimitry Andric config->osabi = ELFOSABI_STANDALONE;
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric
readPhdrs()5150b57cec5SDimitry Andric void ScriptParser::readPhdrs() {
5160b57cec5SDimitry Andric expect("{");
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
5190b57cec5SDimitry Andric PhdrsCommand cmd;
5200b57cec5SDimitry Andric cmd.name = next();
5210b57cec5SDimitry Andric cmd.type = readPhdrType();
5220b57cec5SDimitry Andric
5230b57cec5SDimitry Andric while (!errorCount() && !consume(";")) {
5240b57cec5SDimitry Andric if (consume("FILEHDR"))
5250b57cec5SDimitry Andric cmd.hasFilehdr = true;
5260b57cec5SDimitry Andric else if (consume("PHDRS"))
5270b57cec5SDimitry Andric cmd.hasPhdrs = true;
5280b57cec5SDimitry Andric else if (consume("AT"))
5290b57cec5SDimitry Andric cmd.lmaExpr = readParenExpr();
5300b57cec5SDimitry Andric else if (consume("FLAGS"))
5310b57cec5SDimitry Andric cmd.flags = readParenExpr()().getValue();
5320b57cec5SDimitry Andric else
5330b57cec5SDimitry Andric setError("unexpected header attribute: " + next());
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric
5360b57cec5SDimitry Andric script->phdrsCommands.push_back(cmd);
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric
readRegionAlias()5400b57cec5SDimitry Andric void ScriptParser::readRegionAlias() {
5410b57cec5SDimitry Andric expect("(");
5420b57cec5SDimitry Andric StringRef alias = unquote(next());
5430b57cec5SDimitry Andric expect(",");
5440b57cec5SDimitry Andric StringRef name = next();
5450b57cec5SDimitry Andric expect(")");
5460b57cec5SDimitry Andric
5470b57cec5SDimitry Andric if (script->memoryRegions.count(alias))
5480b57cec5SDimitry Andric setError("redefinition of memory region '" + alias + "'");
5490b57cec5SDimitry Andric if (!script->memoryRegions.count(name))
5500b57cec5SDimitry Andric setError("memory region '" + name + "' is not defined");
5510b57cec5SDimitry Andric script->memoryRegions.insert({alias, script->memoryRegions[name]});
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric
readSearchDir()5540b57cec5SDimitry Andric void ScriptParser::readSearchDir() {
5550b57cec5SDimitry Andric expect("(");
5560b57cec5SDimitry Andric StringRef tok = next();
5570b57cec5SDimitry Andric if (!config->nostdlib)
5580b57cec5SDimitry Andric config->searchPaths.push_back(unquote(tok));
5590b57cec5SDimitry Andric expect(")");
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric
5620b57cec5SDimitry Andric // This reads an overlay description. Overlays are used to describe output
5630b57cec5SDimitry Andric // sections that use the same virtual memory range and normally would trigger
5640b57cec5SDimitry Andric // linker's sections sanity check failures.
5650b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
readOverlay()56604eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
5671db9f3b2SDimitry Andric Expr addrExpr;
5681db9f3b2SDimitry Andric if (consume(":")) {
5691db9f3b2SDimitry Andric addrExpr = [] { return script->getDot(); };
5701db9f3b2SDimitry Andric } else {
5711db9f3b2SDimitry Andric addrExpr = readExpr();
5720b57cec5SDimitry Andric expect(":");
5731db9f3b2SDimitry Andric }
5741db9f3b2SDimitry Andric // When AT is omitted, LMA should equal VMA. script->getDot() when evaluating
5751db9f3b2SDimitry Andric // lmaExpr will ensure this, even if the start address is specified.
5761db9f3b2SDimitry Andric Expr lmaExpr =
5771db9f3b2SDimitry Andric consume("AT") ? readParenExpr() : [] { return script->getDot(); };
5780b57cec5SDimitry Andric expect("{");
5790b57cec5SDimitry Andric
58004eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> v;
5810b57cec5SDimitry Andric OutputSection *prev = nullptr;
5820b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
5830b57cec5SDimitry Andric // VA is the same for all sections. The LMAs are consecutive in memory
5840b57cec5SDimitry Andric // starting from the base load address specified.
58581ad6265SDimitry Andric OutputDesc *osd = readOverlaySectionDescription();
58681ad6265SDimitry Andric osd->osec.addrExpr = addrExpr;
5871db9f3b2SDimitry Andric if (prev) {
58881ad6265SDimitry Andric osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
5891db9f3b2SDimitry Andric } else {
59081ad6265SDimitry Andric osd->osec.lmaExpr = lmaExpr;
5911db9f3b2SDimitry Andric // Use first section address for subsequent sections as initial addrExpr
5921db9f3b2SDimitry Andric // can be DOT. Ensure the first section, even if empty, is not discarded.
5931db9f3b2SDimitry Andric osd->osec.usedInExpression = true;
5941db9f3b2SDimitry Andric addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
5951db9f3b2SDimitry Andric }
59681ad6265SDimitry Andric v.push_back(osd);
59781ad6265SDimitry Andric prev = &osd->osec;
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric // According to the specification, at the end of the overlay, the location
6010b57cec5SDimitry Andric // counter should be equal to the overlay base address plus size of the
6020b57cec5SDimitry Andric // largest section seen in the overlay.
6030b57cec5SDimitry Andric // Here we want to create the Dot assignment command to achieve that.
6040b57cec5SDimitry Andric Expr moveDot = [=] {
6050b57cec5SDimitry Andric uint64_t max = 0;
6064824e7fdSDimitry Andric for (SectionCommand *cmd : v)
60781ad6265SDimitry Andric max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
6080b57cec5SDimitry Andric return addrExpr().getValue() + max;
6090b57cec5SDimitry Andric };
6105f757f3fSDimitry Andric v.push_back(make<SymbolAssignment>(".", moveDot, 0, getCurrentLocation()));
6110b57cec5SDimitry Andric return v;
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric
readOverwriteSections()614fe6060f1SDimitry Andric void ScriptParser::readOverwriteSections() {
615fe6060f1SDimitry Andric expect("{");
616fe6060f1SDimitry Andric while (!errorCount() && !consume("}"))
617fe6060f1SDimitry Andric script->overwriteSections.push_back(readOutputSectionDescription(next()));
618fe6060f1SDimitry Andric }
619fe6060f1SDimitry Andric
readSections()6200b57cec5SDimitry Andric void ScriptParser::readSections() {
6210b57cec5SDimitry Andric expect("{");
62204eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> v;
6230b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
6240b57cec5SDimitry Andric StringRef tok = next();
6250b57cec5SDimitry Andric if (tok == "OVERLAY") {
6264824e7fdSDimitry Andric for (SectionCommand *cmd : readOverlay())
6270b57cec5SDimitry Andric v.push_back(cmd);
6280b57cec5SDimitry Andric continue;
6290b57cec5SDimitry Andric } else if (tok == "INCLUDE") {
6300b57cec5SDimitry Andric readInclude();
6310b57cec5SDimitry Andric continue;
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric
6344824e7fdSDimitry Andric if (SectionCommand *cmd = readAssignment(tok))
6350b57cec5SDimitry Andric v.push_back(cmd);
6360b57cec5SDimitry Andric else
6370b57cec5SDimitry Andric v.push_back(readOutputSectionDescription(tok));
6380b57cec5SDimitry Andric }
63981ad6265SDimitry Andric
64081ad6265SDimitry Andric // If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
64181ad6265SDimitry Andric // the relro fields should be cleared.
6425f757f3fSDimitry Andric if (!script->seenRelroEnd)
64381ad6265SDimitry Andric for (SectionCommand *cmd : v)
64481ad6265SDimitry Andric if (auto *osd = dyn_cast<OutputDesc>(cmd))
64581ad6265SDimitry Andric osd->osec.relro = false;
64681ad6265SDimitry Andric
6475ffd83dbSDimitry Andric script->sectionCommands.insert(script->sectionCommands.end(), v.begin(),
6485ffd83dbSDimitry Andric v.end());
6490b57cec5SDimitry Andric
6505ffd83dbSDimitry Andric if (atEOF() || !consume("INSERT")) {
6515ffd83dbSDimitry Andric script->hasSectionsCommand = true;
6520b57cec5SDimitry Andric return;
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric
6555ffd83dbSDimitry Andric bool isAfter = false;
6565ffd83dbSDimitry Andric if (consume("AFTER"))
6575ffd83dbSDimitry Andric isAfter = true;
6585ffd83dbSDimitry Andric else if (!consume("BEFORE"))
6595ffd83dbSDimitry Andric setError("expected AFTER/BEFORE, but got '" + next() + "'");
6605ffd83dbSDimitry Andric StringRef where = next();
66104eeddc0SDimitry Andric SmallVector<StringRef, 0> names;
6624824e7fdSDimitry Andric for (SectionCommand *cmd : v)
66381ad6265SDimitry Andric if (auto *os = dyn_cast<OutputDesc>(cmd))
66481ad6265SDimitry Andric names.push_back(os->osec.name);
665fe6060f1SDimitry Andric if (!names.empty())
666fe6060f1SDimitry Andric script->insertCommands.push_back({std::move(names), isAfter, where});
6670b57cec5SDimitry Andric }
6680b57cec5SDimitry Andric
readTarget()6690b57cec5SDimitry Andric void ScriptParser::readTarget() {
6700b57cec5SDimitry Andric // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers,
6710b57cec5SDimitry Andric // we accept only a limited set of BFD names (i.e. "elf" or "binary")
6720b57cec5SDimitry Andric // for --format. We recognize only /^elf/ and "binary" in the linker
6730b57cec5SDimitry Andric // script as well.
6740b57cec5SDimitry Andric expect("(");
67581ad6265SDimitry Andric StringRef tok = unquote(next());
6760b57cec5SDimitry Andric expect(")");
6770b57cec5SDimitry Andric
67806c3fb27SDimitry Andric if (tok.starts_with("elf"))
6790b57cec5SDimitry Andric config->formatBinary = false;
6800b57cec5SDimitry Andric else if (tok == "binary")
6810b57cec5SDimitry Andric config->formatBinary = true;
6820b57cec5SDimitry Andric else
6830b57cec5SDimitry Andric setError("unknown target: " + tok);
6840b57cec5SDimitry Andric }
6850b57cec5SDimitry Andric
precedence(StringRef op)6860b57cec5SDimitry Andric static int precedence(StringRef op) {
6870b57cec5SDimitry Andric return StringSwitch<int>(op)
68806c3fb27SDimitry Andric .Cases("*", "/", "%", 11)
68906c3fb27SDimitry Andric .Cases("+", "-", 10)
69006c3fb27SDimitry Andric .Cases("<<", ">>", 9)
69106c3fb27SDimitry Andric .Cases("<", "<=", ">", ">=", 8)
69206c3fb27SDimitry Andric .Cases("==", "!=", 7)
69306c3fb27SDimitry Andric .Case("&", 6)
69406c3fb27SDimitry Andric .Case("^", 5)
69581ad6265SDimitry Andric .Case("|", 4)
69681ad6265SDimitry Andric .Case("&&", 3)
69781ad6265SDimitry Andric .Case("||", 2)
69881ad6265SDimitry Andric .Case("?", 1)
6990b57cec5SDimitry Andric .Default(-1);
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric
readFilePatterns()7020b57cec5SDimitry Andric StringMatcher ScriptParser::readFilePatterns() {
7035ffd83dbSDimitry Andric StringMatcher Matcher;
7045ffd83dbSDimitry Andric
7050b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
7065ffd83dbSDimitry Andric Matcher.addPattern(SingleStringMatcher(next()));
7075ffd83dbSDimitry Andric return Matcher;
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric
peekSortKind()710e8d8bef9SDimitry Andric SortSectionPolicy ScriptParser::peekSortKind() {
711e8d8bef9SDimitry Andric return StringSwitch<SortSectionPolicy>(peek())
71206c3fb27SDimitry Andric .Case("REVERSE", SortSectionPolicy::Reverse)
713e8d8bef9SDimitry Andric .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name)
714e8d8bef9SDimitry Andric .Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment)
715e8d8bef9SDimitry Andric .Case("SORT_BY_INIT_PRIORITY", SortSectionPolicy::Priority)
716e8d8bef9SDimitry Andric .Case("SORT_NONE", SortSectionPolicy::None)
717e8d8bef9SDimitry Andric .Default(SortSectionPolicy::Default);
718e8d8bef9SDimitry Andric }
719e8d8bef9SDimitry Andric
readSortKind()7200b57cec5SDimitry Andric SortSectionPolicy ScriptParser::readSortKind() {
721e8d8bef9SDimitry Andric SortSectionPolicy ret = peekSortKind();
722e8d8bef9SDimitry Andric if (ret != SortSectionPolicy::Default)
723e8d8bef9SDimitry Andric skip();
724e8d8bef9SDimitry Andric return ret;
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric // Reads SECTIONS command contents in the following form:
7280b57cec5SDimitry Andric //
7290b57cec5SDimitry Andric // <contents> ::= <elem>*
7300b57cec5SDimitry Andric // <elem> ::= <exclude>? <glob-pattern>
7310b57cec5SDimitry Andric // <exclude> ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")"
7320b57cec5SDimitry Andric //
7330b57cec5SDimitry Andric // For example,
7340b57cec5SDimitry Andric //
7350b57cec5SDimitry Andric // *(.foo EXCLUDE_FILE (a.o) .bar EXCLUDE_FILE (b.o) .baz)
7360b57cec5SDimitry Andric //
7370b57cec5SDimitry Andric // is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o".
7380b57cec5SDimitry Andric // The semantics of that is section .foo in any file, section .bar in
7390b57cec5SDimitry Andric // any file but a.o, and section .baz in any file but b.o.
readInputSectionsList()74004eeddc0SDimitry Andric SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
74104eeddc0SDimitry Andric SmallVector<SectionPattern, 0> ret;
7420b57cec5SDimitry Andric while (!errorCount() && peek() != ")") {
7430b57cec5SDimitry Andric StringMatcher excludeFilePat;
7440b57cec5SDimitry Andric if (consume("EXCLUDE_FILE")) {
7450b57cec5SDimitry Andric expect("(");
7460b57cec5SDimitry Andric excludeFilePat = readFilePatterns();
7470b57cec5SDimitry Andric }
7480b57cec5SDimitry Andric
7495ffd83dbSDimitry Andric StringMatcher SectionMatcher;
750e8d8bef9SDimitry Andric // Break if the next token is ), EXCLUDE_FILE, or SORT*.
751*0fca6ea1SDimitry Andric while (!errorCount() && peekSortKind() == SortSectionPolicy::Default) {
752*0fca6ea1SDimitry Andric StringRef s = peek();
753*0fca6ea1SDimitry Andric if (s == ")" || s == "EXCLUDE_FILE")
754*0fca6ea1SDimitry Andric break;
755*0fca6ea1SDimitry Andric // Detect common mistakes when certain non-wildcard meta characters are
756*0fca6ea1SDimitry Andric // used without a closing ')'.
757*0fca6ea1SDimitry Andric if (!s.empty() && strchr("(){}", s[0])) {
758*0fca6ea1SDimitry Andric skip();
759*0fca6ea1SDimitry Andric setError("section pattern is expected");
760*0fca6ea1SDimitry Andric break;
761*0fca6ea1SDimitry Andric }
7625ffd83dbSDimitry Andric SectionMatcher.addPattern(unquote(next()));
763*0fca6ea1SDimitry Andric }
7640b57cec5SDimitry Andric
7655ffd83dbSDimitry Andric if (!SectionMatcher.empty())
7665ffd83dbSDimitry Andric ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)});
767e8d8bef9SDimitry Andric else if (excludeFilePat.empty())
768e8d8bef9SDimitry Andric break;
7690b57cec5SDimitry Andric else
7700b57cec5SDimitry Andric setError("section pattern is expected");
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric return ret;
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric
7750b57cec5SDimitry Andric // Reads contents of "SECTIONS" directive. That directive contains a
7760b57cec5SDimitry Andric // list of glob patterns for input sections. The grammar is as follows.
7770b57cec5SDimitry Andric //
7780b57cec5SDimitry Andric // <patterns> ::= <section-list>
7790b57cec5SDimitry Andric // | <sort> "(" <section-list> ")"
7800b57cec5SDimitry Andric // | <sort> "(" <sort> "(" <section-list> ")" ")"
7810b57cec5SDimitry Andric //
7820b57cec5SDimitry Andric // <sort> ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT"
7830b57cec5SDimitry Andric // | "SORT_BY_INIT_PRIORITY" | "SORT_NONE"
7840b57cec5SDimitry Andric //
7850b57cec5SDimitry Andric // <section-list> is parsed by readInputSectionsList().
7860b57cec5SDimitry Andric InputSectionDescription *
readInputSectionRules(StringRef filePattern,uint64_t withFlags,uint64_t withoutFlags)7875ffd83dbSDimitry Andric ScriptParser::readInputSectionRules(StringRef filePattern, uint64_t withFlags,
7885ffd83dbSDimitry Andric uint64_t withoutFlags) {
7895ffd83dbSDimitry Andric auto *cmd =
7905ffd83dbSDimitry Andric make<InputSectionDescription>(filePattern, withFlags, withoutFlags);
7910b57cec5SDimitry Andric expect("(");
7920b57cec5SDimitry Andric
7930b57cec5SDimitry Andric while (!errorCount() && !consume(")")) {
7940b57cec5SDimitry Andric SortSectionPolicy outer = readSortKind();
7950b57cec5SDimitry Andric SortSectionPolicy inner = SortSectionPolicy::Default;
79604eeddc0SDimitry Andric SmallVector<SectionPattern, 0> v;
7970b57cec5SDimitry Andric if (outer != SortSectionPolicy::Default) {
7980b57cec5SDimitry Andric expect("(");
7990b57cec5SDimitry Andric inner = readSortKind();
8000b57cec5SDimitry Andric if (inner != SortSectionPolicy::Default) {
8010b57cec5SDimitry Andric expect("(");
8020b57cec5SDimitry Andric v = readInputSectionsList();
8030b57cec5SDimitry Andric expect(")");
8040b57cec5SDimitry Andric } else {
8050b57cec5SDimitry Andric v = readInputSectionsList();
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric expect(")");
8080b57cec5SDimitry Andric } else {
8090b57cec5SDimitry Andric v = readInputSectionsList();
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric for (SectionPattern &pat : v) {
8130b57cec5SDimitry Andric pat.sortInner = inner;
8140b57cec5SDimitry Andric pat.sortOuter = outer;
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andric std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns));
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric return cmd;
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric
8220b57cec5SDimitry Andric InputSectionDescription *
readInputSectionDescription(StringRef tok)8230b57cec5SDimitry Andric ScriptParser::readInputSectionDescription(StringRef tok) {
8240b57cec5SDimitry Andric // Input section wildcard can be surrounded by KEEP.
8250b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep
8265ffd83dbSDimitry Andric uint64_t withFlags = 0;
8275ffd83dbSDimitry Andric uint64_t withoutFlags = 0;
8280b57cec5SDimitry Andric if (tok == "KEEP") {
8290b57cec5SDimitry Andric expect("(");
8305ffd83dbSDimitry Andric if (consume("INPUT_SECTION_FLAGS"))
8315ffd83dbSDimitry Andric std::tie(withFlags, withoutFlags) = readInputSectionFlags();
8325ffd83dbSDimitry Andric InputSectionDescription *cmd =
8335ffd83dbSDimitry Andric readInputSectionRules(next(), withFlags, withoutFlags);
8340b57cec5SDimitry Andric expect(")");
8350b57cec5SDimitry Andric script->keptSections.push_back(cmd);
8360b57cec5SDimitry Andric return cmd;
8370b57cec5SDimitry Andric }
8385ffd83dbSDimitry Andric if (tok == "INPUT_SECTION_FLAGS") {
8395ffd83dbSDimitry Andric std::tie(withFlags, withoutFlags) = readInputSectionFlags();
8405ffd83dbSDimitry Andric tok = next();
8415ffd83dbSDimitry Andric }
8425ffd83dbSDimitry Andric return readInputSectionRules(tok, withFlags, withoutFlags);
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric
readSort()8450b57cec5SDimitry Andric void ScriptParser::readSort() {
8460b57cec5SDimitry Andric expect("(");
8470b57cec5SDimitry Andric expect("CONSTRUCTORS");
8480b57cec5SDimitry Andric expect(")");
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric
readAssert()8510b57cec5SDimitry Andric Expr ScriptParser::readAssert() {
8520b57cec5SDimitry Andric expect("(");
8530b57cec5SDimitry Andric Expr e = readExpr();
8540b57cec5SDimitry Andric expect(",");
8550b57cec5SDimitry Andric StringRef msg = unquote(next());
8560b57cec5SDimitry Andric expect(")");
8570b57cec5SDimitry Andric
8580b57cec5SDimitry Andric return [=] {
8590b57cec5SDimitry Andric if (!e().getValue())
86085868e8aSDimitry Andric errorOrWarn(msg);
8610b57cec5SDimitry Andric return script->getDot();
8620b57cec5SDimitry Andric };
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric
86581ad6265SDimitry Andric #define ECase(X) \
86681ad6265SDimitry Andric { #X, X }
86781ad6265SDimitry Andric constexpr std::pair<const char *, unsigned> typeMap[] = {
86881ad6265SDimitry Andric ECase(SHT_PROGBITS), ECase(SHT_NOTE), ECase(SHT_NOBITS),
86981ad6265SDimitry Andric ECase(SHT_INIT_ARRAY), ECase(SHT_FINI_ARRAY), ECase(SHT_PREINIT_ARRAY),
87081ad6265SDimitry Andric };
87181ad6265SDimitry Andric #undef ECase
87281ad6265SDimitry Andric
8730b57cec5SDimitry Andric // Tries to read the special directive for an output section definition which
87481ad6265SDimitry Andric // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)", "(OVERLAY)", and
87581ad6265SDimitry Andric // "(TYPE=<value>)".
readSectionDirective(OutputSection * cmd,StringRef tok)876*0fca6ea1SDimitry Andric bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
877*0fca6ea1SDimitry Andric if (tok != "NOLOAD" && tok != "COPY" && tok != "INFO" && tok != "OVERLAY" &&
878*0fca6ea1SDimitry Andric tok != "TYPE")
8790b57cec5SDimitry Andric return false;
8800b57cec5SDimitry Andric
8810b57cec5SDimitry Andric if (consume("NOLOAD")) {
882e837bb5cSDimitry Andric cmd->type = SHT_NOBITS;
88381ad6265SDimitry Andric cmd->typeIsSet = true;
88481ad6265SDimitry Andric } else if (consume("TYPE")) {
88581ad6265SDimitry Andric expect("=");
88681ad6265SDimitry Andric StringRef value = peek();
88781ad6265SDimitry Andric auto it = llvm::find_if(typeMap, [=](auto e) { return e.first == value; });
88881ad6265SDimitry Andric if (it != std::end(typeMap)) {
88981ad6265SDimitry Andric // The value is a recognized literal SHT_*.
89081ad6265SDimitry Andric cmd->type = it->second;
89181ad6265SDimitry Andric skip();
89206c3fb27SDimitry Andric } else if (value.starts_with("SHT_")) {
89381ad6265SDimitry Andric setError("unknown section type " + value);
89481ad6265SDimitry Andric } else {
89581ad6265SDimitry Andric // Otherwise, read an expression.
89681ad6265SDimitry Andric cmd->type = readExpr()().getValue();
89781ad6265SDimitry Andric }
89881ad6265SDimitry Andric cmd->typeIsSet = true;
8990b57cec5SDimitry Andric } else {
9000b57cec5SDimitry Andric skip(); // This is "COPY", "INFO" or "OVERLAY".
9010b57cec5SDimitry Andric cmd->nonAlloc = true;
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric expect(")");
9040b57cec5SDimitry Andric return true;
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric
9070b57cec5SDimitry Andric // Reads an expression and/or the special directive for an output
9080b57cec5SDimitry Andric // section definition. Directive is one of following: "(NOLOAD)",
9090b57cec5SDimitry Andric // "(COPY)", "(INFO)" or "(OVERLAY)".
9100b57cec5SDimitry Andric //
9110b57cec5SDimitry Andric // An output section name can be followed by an address expression
9120b57cec5SDimitry Andric // and/or directive. This grammar is not LL(1) because "(" can be
9130b57cec5SDimitry Andric // interpreted as either the beginning of some expression or beginning
9140b57cec5SDimitry Andric // of directive.
9150b57cec5SDimitry Andric //
9160b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
9170b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
readSectionAddressType(OutputSection * cmd)9180b57cec5SDimitry Andric void ScriptParser::readSectionAddressType(OutputSection *cmd) {
919*0fca6ea1SDimitry Andric if (consume("(")) {
92081ad6265SDimitry Andric // Temporarily set inExpr to support TYPE=<value> without spaces.
921*0fca6ea1SDimitry Andric SaveAndRestore saved(inExpr, true);
922*0fca6ea1SDimitry Andric if (readSectionDirective(cmd, peek()))
9230b57cec5SDimitry Andric return;
9240b57cec5SDimitry Andric cmd->addrExpr = readExpr();
925*0fca6ea1SDimitry Andric expect(")");
926*0fca6ea1SDimitry Andric } else {
927*0fca6ea1SDimitry Andric cmd->addrExpr = readExpr();
928*0fca6ea1SDimitry Andric }
929*0fca6ea1SDimitry Andric
930*0fca6ea1SDimitry Andric if (consume("(")) {
931*0fca6ea1SDimitry Andric SaveAndRestore saved(inExpr, true);
932*0fca6ea1SDimitry Andric StringRef tok = peek();
933*0fca6ea1SDimitry Andric if (!readSectionDirective(cmd, tok))
934*0fca6ea1SDimitry Andric setError("unknown section directive: " + tok);
935*0fca6ea1SDimitry Andric }
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric
checkAlignment(Expr e,std::string & loc)9380b57cec5SDimitry Andric static Expr checkAlignment(Expr e, std::string &loc) {
9390b57cec5SDimitry Andric return [=] {
9400b57cec5SDimitry Andric uint64_t alignment = std::max((uint64_t)1, e().getValue());
9410b57cec5SDimitry Andric if (!isPowerOf2_64(alignment)) {
9420b57cec5SDimitry Andric error(loc + ": alignment must be power of 2");
9430b57cec5SDimitry Andric return (uint64_t)1; // Return a dummy value.
9440b57cec5SDimitry Andric }
9450b57cec5SDimitry Andric return alignment;
9460b57cec5SDimitry Andric };
9470b57cec5SDimitry Andric }
9480b57cec5SDimitry Andric
readOverlaySectionDescription()94981ad6265SDimitry Andric OutputDesc *ScriptParser::readOverlaySectionDescription() {
95081ad6265SDimitry Andric OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation());
95181ad6265SDimitry Andric osd->osec.inOverlay = true;
9520b57cec5SDimitry Andric expect("{");
9535ffd83dbSDimitry Andric while (!errorCount() && !consume("}")) {
9545ffd83dbSDimitry Andric uint64_t withFlags = 0;
9555ffd83dbSDimitry Andric uint64_t withoutFlags = 0;
9565ffd83dbSDimitry Andric if (consume("INPUT_SECTION_FLAGS"))
9575ffd83dbSDimitry Andric std::tie(withFlags, withoutFlags) = readInputSectionFlags();
95881ad6265SDimitry Andric osd->osec.commands.push_back(
9595ffd83dbSDimitry Andric readInputSectionRules(next(), withFlags, withoutFlags));
9605ffd83dbSDimitry Andric }
96106c3fb27SDimitry Andric osd->osec.phdrs = readOutputSectionPhdrs();
96281ad6265SDimitry Andric return osd;
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric
readOutputSectionDescription(StringRef outSec)96581ad6265SDimitry Andric OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
96606c3fb27SDimitry Andric OutputDesc *cmd =
96706c3fb27SDimitry Andric script->createOutputSection(unquote(outSec), getCurrentLocation());
96881ad6265SDimitry Andric OutputSection *osec = &cmd->osec;
96981ad6265SDimitry Andric // Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
9705f757f3fSDimitry Andric osec->relro = script->seenDataAlign && !script->seenRelroEnd;
9710b57cec5SDimitry Andric
9720b57cec5SDimitry Andric size_t symbolsReferenced = script->referencedSymbols.size();
9730b57cec5SDimitry Andric
9740b57cec5SDimitry Andric if (peek() != ":")
97581ad6265SDimitry Andric readSectionAddressType(osec);
9760b57cec5SDimitry Andric expect(":");
9770b57cec5SDimitry Andric
9780b57cec5SDimitry Andric std::string location = getCurrentLocation();
9790b57cec5SDimitry Andric if (consume("AT"))
98081ad6265SDimitry Andric osec->lmaExpr = readParenExpr();
9810b57cec5SDimitry Andric if (consume("ALIGN"))
98281ad6265SDimitry Andric osec->alignExpr = checkAlignment(readParenExpr(), location);
9830b57cec5SDimitry Andric if (consume("SUBALIGN"))
98481ad6265SDimitry Andric osec->subalignExpr = checkAlignment(readParenExpr(), location);
9850b57cec5SDimitry Andric
9860b57cec5SDimitry Andric // Parse constraints.
9870b57cec5SDimitry Andric if (consume("ONLY_IF_RO"))
98881ad6265SDimitry Andric osec->constraint = ConstraintKind::ReadOnly;
9890b57cec5SDimitry Andric if (consume("ONLY_IF_RW"))
99081ad6265SDimitry Andric osec->constraint = ConstraintKind::ReadWrite;
9910b57cec5SDimitry Andric expect("{");
9920b57cec5SDimitry Andric
9930b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
9940b57cec5SDimitry Andric StringRef tok = next();
9950b57cec5SDimitry Andric if (tok == ";") {
9960b57cec5SDimitry Andric // Empty commands are allowed. Do nothing here.
9970b57cec5SDimitry Andric } else if (SymbolAssignment *assign = readAssignment(tok)) {
99881ad6265SDimitry Andric osec->commands.push_back(assign);
9990b57cec5SDimitry Andric } else if (ByteCommand *data = readByteCommand(tok)) {
100081ad6265SDimitry Andric osec->commands.push_back(data);
10010b57cec5SDimitry Andric } else if (tok == "CONSTRUCTORS") {
10020b57cec5SDimitry Andric // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
10030b57cec5SDimitry Andric // by name. This is for very old file formats such as ECOFF/XCOFF.
10040b57cec5SDimitry Andric // For ELF, we should ignore.
10050b57cec5SDimitry Andric } else if (tok == "FILL") {
10060b57cec5SDimitry Andric // We handle the FILL command as an alias for =fillexp section attribute,
10070b57cec5SDimitry Andric // which is different from what GNU linkers do.
10080b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
10095ffd83dbSDimitry Andric if (peek() != "(")
10105ffd83dbSDimitry Andric setError("( expected, but got " + peek());
101181ad6265SDimitry Andric osec->filler = readFill();
10120b57cec5SDimitry Andric } else if (tok == "SORT") {
10130b57cec5SDimitry Andric readSort();
10140b57cec5SDimitry Andric } else if (tok == "INCLUDE") {
10150b57cec5SDimitry Andric readInclude();
101681ad6265SDimitry Andric } else if (tok == "(" || tok == ")") {
101781ad6265SDimitry Andric setError("expected filename pattern");
10180b57cec5SDimitry Andric } else if (peek() == "(") {
101981ad6265SDimitry Andric osec->commands.push_back(readInputSectionDescription(tok));
10200b57cec5SDimitry Andric } else {
10210b57cec5SDimitry Andric // We have a file name and no input sections description. It is not a
10220b57cec5SDimitry Andric // commonly used syntax, but still acceptable. In that case, all sections
10230b57cec5SDimitry Andric // from the file will be included.
10245ffd83dbSDimitry Andric // FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not
10255ffd83dbSDimitry Andric // handle this case here as it will already have been matched by the
10265ffd83dbSDimitry Andric // case above.
10270b57cec5SDimitry Andric auto *isd = make<InputSectionDescription>(tok);
10285ffd83dbSDimitry Andric isd->sectionPatterns.push_back({{}, StringMatcher("*")});
102981ad6265SDimitry Andric osec->commands.push_back(isd);
10300b57cec5SDimitry Andric }
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric
10330b57cec5SDimitry Andric if (consume(">"))
103481ad6265SDimitry Andric osec->memoryRegionName = std::string(next());
10350b57cec5SDimitry Andric
10360b57cec5SDimitry Andric if (consume("AT")) {
10370b57cec5SDimitry Andric expect(">");
103881ad6265SDimitry Andric osec->lmaRegionName = std::string(next());
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric
104181ad6265SDimitry Andric if (osec->lmaExpr && !osec->lmaRegionName.empty())
10420b57cec5SDimitry Andric error("section can't have both LMA and a load region");
10430b57cec5SDimitry Andric
104481ad6265SDimitry Andric osec->phdrs = readOutputSectionPhdrs();
10450b57cec5SDimitry Andric
104606c3fb27SDimitry Andric if (peek() == "=" || peek().starts_with("=")) {
10470b57cec5SDimitry Andric inExpr = true;
10480b57cec5SDimitry Andric consume("=");
104981ad6265SDimitry Andric osec->filler = readFill();
10500b57cec5SDimitry Andric inExpr = false;
10510b57cec5SDimitry Andric }
10520b57cec5SDimitry Andric
10530b57cec5SDimitry Andric // Consume optional comma following output section command.
10540b57cec5SDimitry Andric consume(",");
10550b57cec5SDimitry Andric
10560b57cec5SDimitry Andric if (script->referencedSymbols.size() > symbolsReferenced)
105781ad6265SDimitry Andric osec->expressionsUseSymbols = true;
10580b57cec5SDimitry Andric return cmd;
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric
10610b57cec5SDimitry Andric // Reads a `=<fillexp>` expression and returns its value as a big-endian number.
10620b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html
10630b57cec5SDimitry Andric // We do not support using symbols in such expressions.
10640b57cec5SDimitry Andric //
10650b57cec5SDimitry Andric // When reading a hexstring, ld.bfd handles it as a blob of arbitrary
10660b57cec5SDimitry Andric // size, while ld.gold always handles it as a 32-bit big-endian number.
10670b57cec5SDimitry Andric // We are compatible with ld.gold because it's easier to implement.
10685ffd83dbSDimitry Andric // Also, we require that expressions with operators must be wrapped into
10695ffd83dbSDimitry Andric // round brackets. We did it to resolve the ambiguity when parsing scripts like:
10705ffd83dbSDimitry Andric // SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } }
readFill()10710b57cec5SDimitry Andric std::array<uint8_t, 4> ScriptParser::readFill() {
10725ffd83dbSDimitry Andric uint64_t value = readPrimary()().val;
10730b57cec5SDimitry Andric if (value > UINT32_MAX)
10740b57cec5SDimitry Andric setError("filler expression result does not fit 32-bit: 0x" +
10750b57cec5SDimitry Andric Twine::utohexstr(value));
10760b57cec5SDimitry Andric
10770b57cec5SDimitry Andric std::array<uint8_t, 4> buf;
10780b57cec5SDimitry Andric write32be(buf.data(), (uint32_t)value);
10790b57cec5SDimitry Andric return buf;
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric
readProvideHidden(bool provide,bool hidden)10820b57cec5SDimitry Andric SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
10830b57cec5SDimitry Andric expect("(");
108481ad6265SDimitry Andric StringRef name = next(), eq = peek();
108581ad6265SDimitry Andric if (eq != "=") {
108681ad6265SDimitry Andric setError("= expected, but got " + next());
108781ad6265SDimitry Andric while (!atEOF() && next() != ")")
108881ad6265SDimitry Andric ;
108981ad6265SDimitry Andric return nullptr;
109081ad6265SDimitry Andric }
1091*0fca6ea1SDimitry Andric llvm::SaveAndRestore saveActiveProvideSym(activeProvideSym);
1092*0fca6ea1SDimitry Andric if (provide)
1093*0fca6ea1SDimitry Andric activeProvideSym = name;
109481ad6265SDimitry Andric SymbolAssignment *cmd = readSymbolAssignment(name);
10950b57cec5SDimitry Andric cmd->provide = provide;
10960b57cec5SDimitry Andric cmd->hidden = hidden;
10970b57cec5SDimitry Andric expect(")");
10980b57cec5SDimitry Andric return cmd;
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric
readAssignment(StringRef tok)11010b57cec5SDimitry Andric SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
11020b57cec5SDimitry Andric // Assert expression returns Dot, so this is equal to ".=."
11030b57cec5SDimitry Andric if (tok == "ASSERT")
11045f757f3fSDimitry Andric return make<SymbolAssignment>(".", readAssert(), 0, getCurrentLocation());
11050b57cec5SDimitry Andric
11060b57cec5SDimitry Andric size_t oldPos = pos;
11070b57cec5SDimitry Andric SymbolAssignment *cmd = nullptr;
11085f757f3fSDimitry Andric bool savedSeenRelroEnd = script->seenRelroEnd;
110981ad6265SDimitry Andric const StringRef op = peek();
111006c3fb27SDimitry Andric if (op.starts_with("=")) {
111181ad6265SDimitry Andric // Support = followed by an expression without whitespace.
1112bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
11130b57cec5SDimitry Andric cmd = readSymbolAssignment(tok);
111406c3fb27SDimitry Andric } else if ((op.size() == 2 && op[1] == '=' && strchr("*/+-&^|", op[0])) ||
111581ad6265SDimitry Andric op == "<<=" || op == ">>=") {
111681ad6265SDimitry Andric cmd = readSymbolAssignment(tok);
111781ad6265SDimitry Andric } else if (tok == "PROVIDE") {
1118bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
11190b57cec5SDimitry Andric cmd = readProvideHidden(true, false);
112081ad6265SDimitry Andric } else if (tok == "HIDDEN") {
1121bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
11220b57cec5SDimitry Andric cmd = readProvideHidden(false, true);
112381ad6265SDimitry Andric } else if (tok == "PROVIDE_HIDDEN") {
1124bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
11250b57cec5SDimitry Andric cmd = readProvideHidden(true, true);
112681ad6265SDimitry Andric }
11270b57cec5SDimitry Andric
11280b57cec5SDimitry Andric if (cmd) {
11295f757f3fSDimitry Andric cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && script->seenRelroEnd;
11300b57cec5SDimitry Andric cmd->commandString =
11310b57cec5SDimitry Andric tok.str() + " " +
11320b57cec5SDimitry Andric llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
11330b57cec5SDimitry Andric expect(";");
11340b57cec5SDimitry Andric }
11350b57cec5SDimitry Andric return cmd;
11360b57cec5SDimitry Andric }
11370b57cec5SDimitry Andric
readSymbolAssignment(StringRef name)11380b57cec5SDimitry Andric SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
1139fe6060f1SDimitry Andric name = unquote(name);
11400b57cec5SDimitry Andric StringRef op = next();
114181ad6265SDimitry Andric assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" ||
114206c3fb27SDimitry Andric op == "&=" || op == "^=" || op == "|=" || op == "<<=" || op == ">>=");
11435f757f3fSDimitry Andric // Note: GNU ld does not support %=.
11440b57cec5SDimitry Andric Expr e = readExpr();
114581ad6265SDimitry Andric if (op != "=") {
11460b57cec5SDimitry Andric std::string loc = getCurrentLocation();
114781ad6265SDimitry Andric e = [=, c = op[0]]() -> ExprValue {
114881ad6265SDimitry Andric ExprValue lhs = script->getSymbolValue(name, loc);
114981ad6265SDimitry Andric switch (c) {
115081ad6265SDimitry Andric case '*':
115181ad6265SDimitry Andric return lhs.getValue() * e().getValue();
115281ad6265SDimitry Andric case '/':
115381ad6265SDimitry Andric if (uint64_t rv = e().getValue())
115481ad6265SDimitry Andric return lhs.getValue() / rv;
115581ad6265SDimitry Andric error(loc + ": division by zero");
115681ad6265SDimitry Andric return 0;
115781ad6265SDimitry Andric case '+':
115881ad6265SDimitry Andric return add(lhs, e());
115981ad6265SDimitry Andric case '-':
116081ad6265SDimitry Andric return sub(lhs, e());
116181ad6265SDimitry Andric case '<':
116206c3fb27SDimitry Andric return lhs.getValue() << e().getValue() % 64;
116381ad6265SDimitry Andric case '>':
116406c3fb27SDimitry Andric return lhs.getValue() >> e().getValue() % 64;
116581ad6265SDimitry Andric case '&':
116681ad6265SDimitry Andric return lhs.getValue() & e().getValue();
116706c3fb27SDimitry Andric case '^':
116806c3fb27SDimitry Andric return lhs.getValue() ^ e().getValue();
116981ad6265SDimitry Andric case '|':
117081ad6265SDimitry Andric return lhs.getValue() | e().getValue();
117181ad6265SDimitry Andric default:
117281ad6265SDimitry Andric llvm_unreachable("");
117381ad6265SDimitry Andric }
117481ad6265SDimitry Andric };
11750b57cec5SDimitry Andric }
11765f757f3fSDimitry Andric return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
11775f757f3fSDimitry Andric getCurrentLocation());
11780b57cec5SDimitry Andric }
11790b57cec5SDimitry Andric
11800b57cec5SDimitry Andric // This is an operator-precedence parser to parse a linker
11810b57cec5SDimitry Andric // script expression.
readExpr()11820b57cec5SDimitry Andric Expr ScriptParser::readExpr() {
11830b57cec5SDimitry Andric // Our lexer is context-aware. Set the in-expression bit so that
11840b57cec5SDimitry Andric // they apply different tokenization rules.
1185*0fca6ea1SDimitry Andric SaveAndRestore saved(inExpr, true);
11860b57cec5SDimitry Andric Expr e = readExpr1(readPrimary(), 0);
11870b57cec5SDimitry Andric return e;
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric
combine(StringRef op,Expr l,Expr r)11900b57cec5SDimitry Andric Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
11910b57cec5SDimitry Andric if (op == "+")
11920b57cec5SDimitry Andric return [=] { return add(l(), r()); };
11930b57cec5SDimitry Andric if (op == "-")
11940b57cec5SDimitry Andric return [=] { return sub(l(), r()); };
11950b57cec5SDimitry Andric if (op == "*")
11960b57cec5SDimitry Andric return [=] { return l().getValue() * r().getValue(); };
11970b57cec5SDimitry Andric if (op == "/") {
11980b57cec5SDimitry Andric std::string loc = getCurrentLocation();
11990b57cec5SDimitry Andric return [=]() -> uint64_t {
12000b57cec5SDimitry Andric if (uint64_t rv = r().getValue())
12010b57cec5SDimitry Andric return l().getValue() / rv;
12020b57cec5SDimitry Andric error(loc + ": division by zero");
12030b57cec5SDimitry Andric return 0;
12040b57cec5SDimitry Andric };
12050b57cec5SDimitry Andric }
12060b57cec5SDimitry Andric if (op == "%") {
12070b57cec5SDimitry Andric std::string loc = getCurrentLocation();
12080b57cec5SDimitry Andric return [=]() -> uint64_t {
12090b57cec5SDimitry Andric if (uint64_t rv = r().getValue())
12100b57cec5SDimitry Andric return l().getValue() % rv;
12110b57cec5SDimitry Andric error(loc + ": modulo by zero");
12120b57cec5SDimitry Andric return 0;
12130b57cec5SDimitry Andric };
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric if (op == "<<")
121606c3fb27SDimitry Andric return [=] { return l().getValue() << r().getValue() % 64; };
12170b57cec5SDimitry Andric if (op == ">>")
121806c3fb27SDimitry Andric return [=] { return l().getValue() >> r().getValue() % 64; };
12190b57cec5SDimitry Andric if (op == "<")
12200b57cec5SDimitry Andric return [=] { return l().getValue() < r().getValue(); };
12210b57cec5SDimitry Andric if (op == ">")
12220b57cec5SDimitry Andric return [=] { return l().getValue() > r().getValue(); };
12230b57cec5SDimitry Andric if (op == ">=")
12240b57cec5SDimitry Andric return [=] { return l().getValue() >= r().getValue(); };
12250b57cec5SDimitry Andric if (op == "<=")
12260b57cec5SDimitry Andric return [=] { return l().getValue() <= r().getValue(); };
12270b57cec5SDimitry Andric if (op == "==")
12280b57cec5SDimitry Andric return [=] { return l().getValue() == r().getValue(); };
12290b57cec5SDimitry Andric if (op == "!=")
12300b57cec5SDimitry Andric return [=] { return l().getValue() != r().getValue(); };
12310b57cec5SDimitry Andric if (op == "||")
12320b57cec5SDimitry Andric return [=] { return l().getValue() || r().getValue(); };
12330b57cec5SDimitry Andric if (op == "&&")
12340b57cec5SDimitry Andric return [=] { return l().getValue() && r().getValue(); };
12350b57cec5SDimitry Andric if (op == "&")
12360b57cec5SDimitry Andric return [=] { return bitAnd(l(), r()); };
123706c3fb27SDimitry Andric if (op == "^")
123806c3fb27SDimitry Andric return [=] { return bitXor(l(), r()); };
12390b57cec5SDimitry Andric if (op == "|")
12400b57cec5SDimitry Andric return [=] { return bitOr(l(), r()); };
12410b57cec5SDimitry Andric llvm_unreachable("invalid operator");
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric
12440b57cec5SDimitry Andric // This is a part of the operator-precedence parser. This function
12450b57cec5SDimitry Andric // assumes that the remaining token stream starts with an operator.
readExpr1(Expr lhs,int minPrec)12460b57cec5SDimitry Andric Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
12470b57cec5SDimitry Andric while (!atEOF() && !errorCount()) {
12480b57cec5SDimitry Andric // Read an operator and an expression.
12490b57cec5SDimitry Andric StringRef op1 = peek();
12500b57cec5SDimitry Andric if (precedence(op1) < minPrec)
12510b57cec5SDimitry Andric break;
12520b57cec5SDimitry Andric skip();
1253*0fca6ea1SDimitry Andric if (op1 == "?")
1254*0fca6ea1SDimitry Andric return readTernary(lhs);
12550b57cec5SDimitry Andric Expr rhs = readPrimary();
12560b57cec5SDimitry Andric
12570b57cec5SDimitry Andric // Evaluate the remaining part of the expression first if the
12580b57cec5SDimitry Andric // next operator has greater precedence than the previous one.
12590b57cec5SDimitry Andric // For example, if we have read "+" and "3", and if the next
12600b57cec5SDimitry Andric // operator is "*", then we'll evaluate 3 * ... part first.
12610b57cec5SDimitry Andric while (!atEOF()) {
12620b57cec5SDimitry Andric StringRef op2 = peek();
12630b57cec5SDimitry Andric if (precedence(op2) <= precedence(op1))
12640b57cec5SDimitry Andric break;
12650b57cec5SDimitry Andric rhs = readExpr1(rhs, precedence(op2));
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric
12680b57cec5SDimitry Andric lhs = combine(op1, lhs, rhs);
12690b57cec5SDimitry Andric }
12700b57cec5SDimitry Andric return lhs;
12710b57cec5SDimitry Andric }
12720b57cec5SDimitry Andric
getPageSize()12730b57cec5SDimitry Andric Expr ScriptParser::getPageSize() {
12740b57cec5SDimitry Andric std::string location = getCurrentLocation();
12750b57cec5SDimitry Andric return [=]() -> uint64_t {
12760b57cec5SDimitry Andric if (target)
12770b57cec5SDimitry Andric return config->commonPageSize;
12780b57cec5SDimitry Andric error(location + ": unable to calculate page size");
12790b57cec5SDimitry Andric return 4096; // Return a dummy value.
12800b57cec5SDimitry Andric };
12810b57cec5SDimitry Andric }
12820b57cec5SDimitry Andric
readConstant()12830b57cec5SDimitry Andric Expr ScriptParser::readConstant() {
12840b57cec5SDimitry Andric StringRef s = readParenLiteral();
12850b57cec5SDimitry Andric if (s == "COMMONPAGESIZE")
12860b57cec5SDimitry Andric return getPageSize();
12870b57cec5SDimitry Andric if (s == "MAXPAGESIZE")
12880b57cec5SDimitry Andric return [] { return config->maxPageSize; };
12890b57cec5SDimitry Andric setError("unknown constant: " + s);
12900b57cec5SDimitry Andric return [] { return 0; };
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric
12930b57cec5SDimitry Andric // Parses Tok as an integer. It recognizes hexadecimal (prefixed with
12940b57cec5SDimitry Andric // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
12950b57cec5SDimitry Andric // have "K" (Ki) or "M" (Mi) suffixes.
parseInt(StringRef tok)1296bdd1243dSDimitry Andric static std::optional<uint64_t> parseInt(StringRef tok) {
12970b57cec5SDimitry Andric // Hexadecimal
12980b57cec5SDimitry Andric uint64_t val;
129906c3fb27SDimitry Andric if (tok.starts_with_insensitive("0x")) {
13000b57cec5SDimitry Andric if (!to_integer(tok.substr(2), val, 16))
1301bdd1243dSDimitry Andric return std::nullopt;
13020b57cec5SDimitry Andric return val;
13030b57cec5SDimitry Andric }
130406c3fb27SDimitry Andric if (tok.ends_with_insensitive("H")) {
13050b57cec5SDimitry Andric if (!to_integer(tok.drop_back(), val, 16))
1306bdd1243dSDimitry Andric return std::nullopt;
13070b57cec5SDimitry Andric return val;
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric
13100b57cec5SDimitry Andric // Decimal
131106c3fb27SDimitry Andric if (tok.ends_with_insensitive("K")) {
13120b57cec5SDimitry Andric if (!to_integer(tok.drop_back(), val, 10))
1313bdd1243dSDimitry Andric return std::nullopt;
13140b57cec5SDimitry Andric return val * 1024;
13150b57cec5SDimitry Andric }
131606c3fb27SDimitry Andric if (tok.ends_with_insensitive("M")) {
13170b57cec5SDimitry Andric if (!to_integer(tok.drop_back(), val, 10))
1318bdd1243dSDimitry Andric return std::nullopt;
13190b57cec5SDimitry Andric return val * 1024 * 1024;
13200b57cec5SDimitry Andric }
13210b57cec5SDimitry Andric if (!to_integer(tok, val, 10))
1322bdd1243dSDimitry Andric return std::nullopt;
13230b57cec5SDimitry Andric return val;
13240b57cec5SDimitry Andric }
13250b57cec5SDimitry Andric
readByteCommand(StringRef tok)13260b57cec5SDimitry Andric ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
13270b57cec5SDimitry Andric int size = StringSwitch<int>(tok)
13280b57cec5SDimitry Andric .Case("BYTE", 1)
13290b57cec5SDimitry Andric .Case("SHORT", 2)
13300b57cec5SDimitry Andric .Case("LONG", 4)
13310b57cec5SDimitry Andric .Case("QUAD", 8)
13320b57cec5SDimitry Andric .Default(-1);
13330b57cec5SDimitry Andric if (size == -1)
13340b57cec5SDimitry Andric return nullptr;
13350b57cec5SDimitry Andric
13360b57cec5SDimitry Andric size_t oldPos = pos;
13370b57cec5SDimitry Andric Expr e = readParenExpr();
13380b57cec5SDimitry Andric std::string commandString =
13390b57cec5SDimitry Andric tok.str() + " " +
13400b57cec5SDimitry Andric llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
13410b57cec5SDimitry Andric return make<ByteCommand>(e, size, commandString);
13420b57cec5SDimitry Andric }
13430b57cec5SDimitry Andric
parseFlag(StringRef tok)1344bdd1243dSDimitry Andric static std::optional<uint64_t> parseFlag(StringRef tok) {
1345bdd1243dSDimitry Andric if (std::optional<uint64_t> asInt = parseInt(tok))
13465ffd83dbSDimitry Andric return asInt;
13475ffd83dbSDimitry Andric #define CASE_ENT(enum) #enum, ELF::enum
1348bdd1243dSDimitry Andric return StringSwitch<std::optional<uint64_t>>(tok)
13495ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_WRITE))
13505ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_ALLOC))
13515ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_EXECINSTR))
13525ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_MERGE))
13535ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_STRINGS))
13545ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_INFO_LINK))
13555ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_LINK_ORDER))
13565ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_OS_NONCONFORMING))
13575ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_GROUP))
13585ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_TLS))
13595ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_COMPRESSED))
13605ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_EXCLUDE))
13615ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_ARM_PURECODE))
1362bdd1243dSDimitry Andric .Default(std::nullopt);
13635ffd83dbSDimitry Andric #undef CASE_ENT
13645ffd83dbSDimitry Andric }
13655ffd83dbSDimitry Andric
13665ffd83dbSDimitry Andric // Reads the '(' <flags> ')' list of section flags in
13675ffd83dbSDimitry Andric // INPUT_SECTION_FLAGS '(' <flags> ')' in the
13685ffd83dbSDimitry Andric // following form:
13695ffd83dbSDimitry Andric // <flags> ::= <flag>
13705ffd83dbSDimitry Andric // | <flags> & flag
13715ffd83dbSDimitry Andric // <flag> ::= Recognized Flag Name, or Integer value of flag.
13725ffd83dbSDimitry Andric // If the first character of <flag> is a ! then this means without flag,
13735ffd83dbSDimitry Andric // otherwise with flag.
13745ffd83dbSDimitry Andric // Example: SHF_EXECINSTR & !SHF_WRITE means with flag SHF_EXECINSTR and
13755ffd83dbSDimitry Andric // without flag SHF_WRITE.
readInputSectionFlags()13765ffd83dbSDimitry Andric std::pair<uint64_t, uint64_t> ScriptParser::readInputSectionFlags() {
13775ffd83dbSDimitry Andric uint64_t withFlags = 0;
13785ffd83dbSDimitry Andric uint64_t withoutFlags = 0;
13795ffd83dbSDimitry Andric expect("(");
13805ffd83dbSDimitry Andric while (!errorCount()) {
13815ffd83dbSDimitry Andric StringRef tok = unquote(next());
13825ffd83dbSDimitry Andric bool without = tok.consume_front("!");
1383bdd1243dSDimitry Andric if (std::optional<uint64_t> flag = parseFlag(tok)) {
13845ffd83dbSDimitry Andric if (without)
13855ffd83dbSDimitry Andric withoutFlags |= *flag;
13865ffd83dbSDimitry Andric else
13875ffd83dbSDimitry Andric withFlags |= *flag;
13885ffd83dbSDimitry Andric } else {
13895ffd83dbSDimitry Andric setError("unrecognised flag: " + tok);
13905ffd83dbSDimitry Andric }
13915ffd83dbSDimitry Andric if (consume(")"))
13925ffd83dbSDimitry Andric break;
13935ffd83dbSDimitry Andric if (!consume("&")) {
13945ffd83dbSDimitry Andric next();
13955ffd83dbSDimitry Andric setError("expected & or )");
13965ffd83dbSDimitry Andric }
13975ffd83dbSDimitry Andric }
13985ffd83dbSDimitry Andric return std::make_pair(withFlags, withoutFlags);
13995ffd83dbSDimitry Andric }
14005ffd83dbSDimitry Andric
readParenLiteral()14010b57cec5SDimitry Andric StringRef ScriptParser::readParenLiteral() {
14020b57cec5SDimitry Andric expect("(");
14030b57cec5SDimitry Andric bool orig = inExpr;
14040b57cec5SDimitry Andric inExpr = false;
14050b57cec5SDimitry Andric StringRef tok = next();
14060b57cec5SDimitry Andric inExpr = orig;
14070b57cec5SDimitry Andric expect(")");
14080b57cec5SDimitry Andric return tok;
14090b57cec5SDimitry Andric }
14100b57cec5SDimitry Andric
checkIfExists(const OutputSection & osec,StringRef location)141181ad6265SDimitry Andric static void checkIfExists(const OutputSection &osec, StringRef location) {
141281ad6265SDimitry Andric if (osec.location.empty() && script->errorOnMissingSection)
1413*0fca6ea1SDimitry Andric script->recordError(location + ": undefined section " + osec.name);
14140b57cec5SDimitry Andric }
14150b57cec5SDimitry Andric
isValidSymbolName(StringRef s)1416fe6060f1SDimitry Andric static bool isValidSymbolName(StringRef s) {
1417fe6060f1SDimitry Andric auto valid = [](char c) {
1418fe6060f1SDimitry Andric return isAlnum(c) || c == '$' || c == '.' || c == '_';
1419fe6060f1SDimitry Andric };
1420fe6060f1SDimitry Andric return !s.empty() && !isDigit(s[0]) && llvm::all_of(s, valid);
1421fe6060f1SDimitry Andric }
1422fe6060f1SDimitry Andric
readPrimary()14230b57cec5SDimitry Andric Expr ScriptParser::readPrimary() {
14240b57cec5SDimitry Andric if (peek() == "(")
14250b57cec5SDimitry Andric return readParenExpr();
14260b57cec5SDimitry Andric
14270b57cec5SDimitry Andric if (consume("~")) {
14280b57cec5SDimitry Andric Expr e = readPrimary();
14290b57cec5SDimitry Andric return [=] { return ~e().getValue(); };
14300b57cec5SDimitry Andric }
14310b57cec5SDimitry Andric if (consume("!")) {
14320b57cec5SDimitry Andric Expr e = readPrimary();
14330b57cec5SDimitry Andric return [=] { return !e().getValue(); };
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric if (consume("-")) {
14360b57cec5SDimitry Andric Expr e = readPrimary();
14370b57cec5SDimitry Andric return [=] { return -e().getValue(); };
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric
14400b57cec5SDimitry Andric StringRef tok = next();
14410b57cec5SDimitry Andric std::string location = getCurrentLocation();
14420b57cec5SDimitry Andric
14430b57cec5SDimitry Andric // Built-in functions are parsed here.
14440b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
14450b57cec5SDimitry Andric if (tok == "ABSOLUTE") {
14460b57cec5SDimitry Andric Expr inner = readParenExpr();
14470b57cec5SDimitry Andric return [=] {
14480b57cec5SDimitry Andric ExprValue i = inner();
14490b57cec5SDimitry Andric i.forceAbsolute = true;
14500b57cec5SDimitry Andric return i;
14510b57cec5SDimitry Andric };
14520b57cec5SDimitry Andric }
14530b57cec5SDimitry Andric if (tok == "ADDR") {
145406c3fb27SDimitry Andric StringRef name = unquote(readParenLiteral());
145581ad6265SDimitry Andric OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
145681ad6265SDimitry Andric osec->usedInExpression = true;
14570b57cec5SDimitry Andric return [=]() -> ExprValue {
145881ad6265SDimitry Andric checkIfExists(*osec, location);
145981ad6265SDimitry Andric return {osec, false, 0, location};
14600b57cec5SDimitry Andric };
14610b57cec5SDimitry Andric }
14620b57cec5SDimitry Andric if (tok == "ALIGN") {
14630b57cec5SDimitry Andric expect("(");
14640b57cec5SDimitry Andric Expr e = readExpr();
14650b57cec5SDimitry Andric if (consume(")")) {
14660b57cec5SDimitry Andric e = checkAlignment(e, location);
1467972a253aSDimitry Andric return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
14680b57cec5SDimitry Andric }
14690b57cec5SDimitry Andric expect(",");
14700b57cec5SDimitry Andric Expr e2 = checkAlignment(readExpr(), location);
14710b57cec5SDimitry Andric expect(")");
14720b57cec5SDimitry Andric return [=] {
14730b57cec5SDimitry Andric ExprValue v = e();
14740b57cec5SDimitry Andric v.alignment = e2().getValue();
14750b57cec5SDimitry Andric return v;
14760b57cec5SDimitry Andric };
14770b57cec5SDimitry Andric }
14780b57cec5SDimitry Andric if (tok == "ALIGNOF") {
147906c3fb27SDimitry Andric StringRef name = unquote(readParenLiteral());
148081ad6265SDimitry Andric OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
14810b57cec5SDimitry Andric return [=] {
148281ad6265SDimitry Andric checkIfExists(*osec, location);
1483bdd1243dSDimitry Andric return osec->addralign;
14840b57cec5SDimitry Andric };
14850b57cec5SDimitry Andric }
14860b57cec5SDimitry Andric if (tok == "ASSERT")
14870b57cec5SDimitry Andric return readAssert();
14880b57cec5SDimitry Andric if (tok == "CONSTANT")
14890b57cec5SDimitry Andric return readConstant();
14900b57cec5SDimitry Andric if (tok == "DATA_SEGMENT_ALIGN") {
14910b57cec5SDimitry Andric expect("(");
14920b57cec5SDimitry Andric Expr e = readExpr();
14930b57cec5SDimitry Andric expect(",");
14940b57cec5SDimitry Andric readExpr();
14950b57cec5SDimitry Andric expect(")");
14965f757f3fSDimitry Andric script->seenDataAlign = true;
14970b57cec5SDimitry Andric return [=] {
1498972a253aSDimitry Andric uint64_t align = std::max(uint64_t(1), e().getValue());
1499972a253aSDimitry Andric return (script->getDot() + align - 1) & -align;
15000b57cec5SDimitry Andric };
15010b57cec5SDimitry Andric }
15020b57cec5SDimitry Andric if (tok == "DATA_SEGMENT_END") {
15030b57cec5SDimitry Andric expect("(");
15040b57cec5SDimitry Andric expect(".");
15050b57cec5SDimitry Andric expect(")");
15060b57cec5SDimitry Andric return [] { return script->getDot(); };
15070b57cec5SDimitry Andric }
15080b57cec5SDimitry Andric if (tok == "DATA_SEGMENT_RELRO_END") {
15090b57cec5SDimitry Andric // GNU linkers implements more complicated logic to handle
15100b57cec5SDimitry Andric // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
15110b57cec5SDimitry Andric // just align to the next page boundary for simplicity.
15120b57cec5SDimitry Andric expect("(");
15130b57cec5SDimitry Andric readExpr();
15140b57cec5SDimitry Andric expect(",");
15150b57cec5SDimitry Andric readExpr();
15160b57cec5SDimitry Andric expect(")");
15175f757f3fSDimitry Andric script->seenRelroEnd = true;
15185f757f3fSDimitry Andric return [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
15190b57cec5SDimitry Andric }
15200b57cec5SDimitry Andric if (tok == "DEFINED") {
1521fe6060f1SDimitry Andric StringRef name = unquote(readParenLiteral());
15225f757f3fSDimitry Andric // Return 1 if s is defined. If the definition is only found in a linker
15235f757f3fSDimitry Andric // script, it must happen before this DEFINED.
15245f757f3fSDimitry Andric auto order = ctx.scriptSymOrderCounter++;
1525e8d8bef9SDimitry Andric return [=] {
15265f757f3fSDimitry Andric Symbol *s = symtab.find(name);
15275f757f3fSDimitry Andric return s && s->isDefined() && ctx.scriptSymOrder.lookup(s) < order ? 1
15285f757f3fSDimitry Andric : 0;
1529e8d8bef9SDimitry Andric };
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric if (tok == "LENGTH") {
15320b57cec5SDimitry Andric StringRef name = readParenLiteral();
15330b57cec5SDimitry Andric if (script->memoryRegions.count(name) == 0) {
15340b57cec5SDimitry Andric setError("memory region not defined: " + name);
15350b57cec5SDimitry Andric return [] { return 0; };
15360b57cec5SDimitry Andric }
15375ffd83dbSDimitry Andric return script->memoryRegions[name]->length;
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric if (tok == "LOADADDR") {
154006c3fb27SDimitry Andric StringRef name = unquote(readParenLiteral());
154181ad6265SDimitry Andric OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
154281ad6265SDimitry Andric osec->usedInExpression = true;
15430b57cec5SDimitry Andric return [=] {
154481ad6265SDimitry Andric checkIfExists(*osec, location);
154581ad6265SDimitry Andric return osec->getLMA();
15460b57cec5SDimitry Andric };
15470b57cec5SDimitry Andric }
1548e8d8bef9SDimitry Andric if (tok == "LOG2CEIL") {
1549e8d8bef9SDimitry Andric expect("(");
1550e8d8bef9SDimitry Andric Expr a = readExpr();
1551e8d8bef9SDimitry Andric expect(")");
1552e8d8bef9SDimitry Andric return [=] {
1553e8d8bef9SDimitry Andric // LOG2CEIL(0) is defined to be 0.
1554e8d8bef9SDimitry Andric return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1)));
1555e8d8bef9SDimitry Andric };
1556e8d8bef9SDimitry Andric }
15570b57cec5SDimitry Andric if (tok == "MAX" || tok == "MIN") {
15580b57cec5SDimitry Andric expect("(");
15590b57cec5SDimitry Andric Expr a = readExpr();
15600b57cec5SDimitry Andric expect(",");
15610b57cec5SDimitry Andric Expr b = readExpr();
15620b57cec5SDimitry Andric expect(")");
15630b57cec5SDimitry Andric if (tok == "MIN")
15640b57cec5SDimitry Andric return [=] { return std::min(a().getValue(), b().getValue()); };
15650b57cec5SDimitry Andric return [=] { return std::max(a().getValue(), b().getValue()); };
15660b57cec5SDimitry Andric }
15670b57cec5SDimitry Andric if (tok == "ORIGIN") {
15680b57cec5SDimitry Andric StringRef name = readParenLiteral();
15690b57cec5SDimitry Andric if (script->memoryRegions.count(name) == 0) {
15700b57cec5SDimitry Andric setError("memory region not defined: " + name);
15710b57cec5SDimitry Andric return [] { return 0; };
15720b57cec5SDimitry Andric }
15735ffd83dbSDimitry Andric return script->memoryRegions[name]->origin;
15740b57cec5SDimitry Andric }
15750b57cec5SDimitry Andric if (tok == "SEGMENT_START") {
15760b57cec5SDimitry Andric expect("(");
15770b57cec5SDimitry Andric skip();
15780b57cec5SDimitry Andric expect(",");
15790b57cec5SDimitry Andric Expr e = readExpr();
15800b57cec5SDimitry Andric expect(")");
15810b57cec5SDimitry Andric return [=] { return e(); };
15820b57cec5SDimitry Andric }
15830b57cec5SDimitry Andric if (tok == "SIZEOF") {
158406c3fb27SDimitry Andric StringRef name = unquote(readParenLiteral());
158581ad6265SDimitry Andric OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
15860b57cec5SDimitry Andric // Linker script does not create an output section if its content is empty.
15870b57cec5SDimitry Andric // We want to allow SIZEOF(.foo) where .foo is a section which happened to
15880b57cec5SDimitry Andric // be empty.
15890b57cec5SDimitry Andric return [=] { return cmd->size; };
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric if (tok == "SIZEOF_HEADERS")
15925ffd83dbSDimitry Andric return [=] { return elf::getHeaderSize(); };
15930b57cec5SDimitry Andric
15940b57cec5SDimitry Andric // Tok is the dot.
15950b57cec5SDimitry Andric if (tok == ".")
15960b57cec5SDimitry Andric return [=] { return script->getSymbolValue(tok, location); };
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andric // Tok is a literal number.
1599bdd1243dSDimitry Andric if (std::optional<uint64_t> val = parseInt(tok))
16000b57cec5SDimitry Andric return [=] { return *val; };
16010b57cec5SDimitry Andric
16020b57cec5SDimitry Andric // Tok is a symbol name.
160306c3fb27SDimitry Andric if (tok.starts_with("\""))
1604fe6060f1SDimitry Andric tok = unquote(tok);
1605349cc55cSDimitry Andric else if (!isValidSymbolName(tok))
16060b57cec5SDimitry Andric setError("malformed number: " + tok);
1607*0fca6ea1SDimitry Andric if (activeProvideSym)
1608*0fca6ea1SDimitry Andric script->provideMap[*activeProvideSym].push_back(tok);
1609*0fca6ea1SDimitry Andric else
16100b57cec5SDimitry Andric script->referencedSymbols.push_back(tok);
16110b57cec5SDimitry Andric return [=] { return script->getSymbolValue(tok, location); };
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric
readTernary(Expr cond)16140b57cec5SDimitry Andric Expr ScriptParser::readTernary(Expr cond) {
16150b57cec5SDimitry Andric Expr l = readExpr();
16160b57cec5SDimitry Andric expect(":");
16170b57cec5SDimitry Andric Expr r = readExpr();
16180b57cec5SDimitry Andric return [=] { return cond().getValue() ? l() : r(); };
16190b57cec5SDimitry Andric }
16200b57cec5SDimitry Andric
readParenExpr()16210b57cec5SDimitry Andric Expr ScriptParser::readParenExpr() {
16220b57cec5SDimitry Andric expect("(");
16230b57cec5SDimitry Andric Expr e = readExpr();
16240b57cec5SDimitry Andric expect(")");
16250b57cec5SDimitry Andric return e;
16260b57cec5SDimitry Andric }
16270b57cec5SDimitry Andric
readOutputSectionPhdrs()162804eeddc0SDimitry Andric SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
162904eeddc0SDimitry Andric SmallVector<StringRef, 0> phdrs;
163006c3fb27SDimitry Andric while (!errorCount() && peek().starts_with(":")) {
16310b57cec5SDimitry Andric StringRef tok = next();
16320b57cec5SDimitry Andric phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));
16330b57cec5SDimitry Andric }
16340b57cec5SDimitry Andric return phdrs;
16350b57cec5SDimitry Andric }
16360b57cec5SDimitry Andric
16370b57cec5SDimitry Andric // Read a program header type name. The next token must be a
16380b57cec5SDimitry Andric // name of a program header type or a constant (e.g. "0x3").
readPhdrType()16390b57cec5SDimitry Andric unsigned ScriptParser::readPhdrType() {
16400b57cec5SDimitry Andric StringRef tok = next();
1641bdd1243dSDimitry Andric if (std::optional<uint64_t> val = parseInt(tok))
16420b57cec5SDimitry Andric return *val;
16430b57cec5SDimitry Andric
16440b57cec5SDimitry Andric unsigned ret = StringSwitch<unsigned>(tok)
16450b57cec5SDimitry Andric .Case("PT_NULL", PT_NULL)
16460b57cec5SDimitry Andric .Case("PT_LOAD", PT_LOAD)
16470b57cec5SDimitry Andric .Case("PT_DYNAMIC", PT_DYNAMIC)
16480b57cec5SDimitry Andric .Case("PT_INTERP", PT_INTERP)
16490b57cec5SDimitry Andric .Case("PT_NOTE", PT_NOTE)
16500b57cec5SDimitry Andric .Case("PT_SHLIB", PT_SHLIB)
16510b57cec5SDimitry Andric .Case("PT_PHDR", PT_PHDR)
16520b57cec5SDimitry Andric .Case("PT_TLS", PT_TLS)
16530b57cec5SDimitry Andric .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
16540b57cec5SDimitry Andric .Case("PT_GNU_STACK", PT_GNU_STACK)
16550b57cec5SDimitry Andric .Case("PT_GNU_RELRO", PT_GNU_RELRO)
1656*0fca6ea1SDimitry Andric .Case("PT_OPENBSD_MUTABLE", PT_OPENBSD_MUTABLE)
16570b57cec5SDimitry Andric .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE)
1658*0fca6ea1SDimitry Andric .Case("PT_OPENBSD_SYSCALLS", PT_OPENBSD_SYSCALLS)
16590b57cec5SDimitry Andric .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED)
16600b57cec5SDimitry Andric .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
16610b57cec5SDimitry Andric .Default(-1);
16620b57cec5SDimitry Andric
16630b57cec5SDimitry Andric if (ret == (unsigned)-1) {
16640b57cec5SDimitry Andric setError("invalid program header type: " + tok);
16650b57cec5SDimitry Andric return PT_NULL;
16660b57cec5SDimitry Andric }
16670b57cec5SDimitry Andric return ret;
16680b57cec5SDimitry Andric }
16690b57cec5SDimitry Andric
16700b57cec5SDimitry Andric // Reads an anonymous version declaration.
readAnonymousDeclaration()16710b57cec5SDimitry Andric void ScriptParser::readAnonymousDeclaration() {
167204eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
167304eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
16740b57cec5SDimitry Andric std::tie(locals, globals) = readSymbols();
167585868e8aSDimitry Andric for (const SymbolVersion &pat : locals)
16766e75b2fbSDimitry Andric config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat);
167785868e8aSDimitry Andric for (const SymbolVersion &pat : globals)
16786e75b2fbSDimitry Andric config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat);
16790b57cec5SDimitry Andric
16800b57cec5SDimitry Andric expect(";");
16810b57cec5SDimitry Andric }
16820b57cec5SDimitry Andric
16830b57cec5SDimitry Andric // Reads a non-anonymous version definition,
16840b57cec5SDimitry Andric // e.g. "VerStr { global: foo; bar; local: *; };".
readVersionDeclaration(StringRef verStr)16850b57cec5SDimitry Andric void ScriptParser::readVersionDeclaration(StringRef verStr) {
16860b57cec5SDimitry Andric // Read a symbol list.
168704eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
168804eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
16890b57cec5SDimitry Andric std::tie(locals, globals) = readSymbols();
16900b57cec5SDimitry Andric
16910b57cec5SDimitry Andric // Create a new version definition and add that to the global symbols.
16920b57cec5SDimitry Andric VersionDefinition ver;
16930b57cec5SDimitry Andric ver.name = verStr;
16946e75b2fbSDimitry Andric ver.nonLocalPatterns = std::move(globals);
16956e75b2fbSDimitry Andric ver.localPatterns = std::move(locals);
169685868e8aSDimitry Andric ver.id = config->versionDefinitions.size();
16970b57cec5SDimitry Andric config->versionDefinitions.push_back(ver);
16980b57cec5SDimitry Andric
16990b57cec5SDimitry Andric // Each version may have a parent version. For example, "Ver2"
17000b57cec5SDimitry Andric // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"
17010b57cec5SDimitry Andric // as a parent. This version hierarchy is, probably against your
17020b57cec5SDimitry Andric // instinct, purely for hint; the runtime doesn't care about it
17030b57cec5SDimitry Andric // at all. In LLD, we simply ignore it.
17045ffd83dbSDimitry Andric if (next() != ";")
17050b57cec5SDimitry Andric expect(";");
17060b57cec5SDimitry Andric }
17070b57cec5SDimitry Andric
hasWildcard(StringRef s)17085ffd83dbSDimitry Andric bool elf::hasWildcard(StringRef s) {
17090b57cec5SDimitry Andric return s.find_first_of("?*[") != StringRef::npos;
17100b57cec5SDimitry Andric }
17110b57cec5SDimitry Andric
17120b57cec5SDimitry Andric // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
171304eeddc0SDimitry Andric std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
readSymbols()17140b57cec5SDimitry Andric ScriptParser::readSymbols() {
171504eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
171604eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
171704eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> *v = &globals;
17180b57cec5SDimitry Andric
17190b57cec5SDimitry Andric while (!errorCount()) {
17200b57cec5SDimitry Andric if (consume("}"))
17210b57cec5SDimitry Andric break;
17220b57cec5SDimitry Andric if (consumeLabel("local")) {
17230b57cec5SDimitry Andric v = &locals;
17240b57cec5SDimitry Andric continue;
17250b57cec5SDimitry Andric }
17260b57cec5SDimitry Andric if (consumeLabel("global")) {
17270b57cec5SDimitry Andric v = &globals;
17280b57cec5SDimitry Andric continue;
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric
17310b57cec5SDimitry Andric if (consume("extern")) {
173204eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> ext = readVersionExtern();
17330b57cec5SDimitry Andric v->insert(v->end(), ext.begin(), ext.end());
17340b57cec5SDimitry Andric } else {
17350b57cec5SDimitry Andric StringRef tok = next();
17360b57cec5SDimitry Andric v->push_back({unquote(tok), false, hasWildcard(tok)});
17370b57cec5SDimitry Andric }
17380b57cec5SDimitry Andric expect(";");
17390b57cec5SDimitry Andric }
17400b57cec5SDimitry Andric return {locals, globals};
17410b57cec5SDimitry Andric }
17420b57cec5SDimitry Andric
17430b57cec5SDimitry Andric // Reads an "extern C++" directive, e.g.,
17440b57cec5SDimitry Andric // "extern "C++" { ns::*; "f(int, double)"; };"
17450b57cec5SDimitry Andric //
17460b57cec5SDimitry Andric // The last semicolon is optional. E.g. this is OK:
17470b57cec5SDimitry Andric // "extern "C++" { ns::*; "f(int, double)" };"
readVersionExtern()174804eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
17490b57cec5SDimitry Andric StringRef tok = next();
17500b57cec5SDimitry Andric bool isCXX = tok == "\"C++\"";
17510b57cec5SDimitry Andric if (!isCXX && tok != "\"C\"")
17520b57cec5SDimitry Andric setError("Unknown language");
17530b57cec5SDimitry Andric expect("{");
17540b57cec5SDimitry Andric
175504eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> ret;
17560b57cec5SDimitry Andric while (!errorCount() && peek() != "}") {
17570b57cec5SDimitry Andric StringRef tok = next();
17580b57cec5SDimitry Andric ret.push_back(
175906c3fb27SDimitry Andric {unquote(tok), isCXX, !tok.starts_with("\"") && hasWildcard(tok)});
17600b57cec5SDimitry Andric if (consume("}"))
17610b57cec5SDimitry Andric return ret;
17620b57cec5SDimitry Andric expect(";");
17630b57cec5SDimitry Andric }
17640b57cec5SDimitry Andric
17650b57cec5SDimitry Andric expect("}");
17660b57cec5SDimitry Andric return ret;
17670b57cec5SDimitry Andric }
17680b57cec5SDimitry Andric
readMemoryAssignment(StringRef s1,StringRef s2,StringRef s3)17695ffd83dbSDimitry Andric Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
17700b57cec5SDimitry Andric StringRef s3) {
17710b57cec5SDimitry Andric if (!consume(s1) && !consume(s2) && !consume(s3)) {
17720b57cec5SDimitry Andric setError("expected one of: " + s1 + ", " + s2 + ", or " + s3);
17735ffd83dbSDimitry Andric return [] { return 0; };
17740b57cec5SDimitry Andric }
17750b57cec5SDimitry Andric expect("=");
17765ffd83dbSDimitry Andric return readExpr();
17770b57cec5SDimitry Andric }
17780b57cec5SDimitry Andric
17790b57cec5SDimitry Andric // Parse the MEMORY command as specified in:
17800b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/MEMORY.html
17810b57cec5SDimitry Andric //
17820b57cec5SDimitry Andric // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
readMemory()17830b57cec5SDimitry Andric void ScriptParser::readMemory() {
17840b57cec5SDimitry Andric expect("{");
17850b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
17860b57cec5SDimitry Andric StringRef tok = next();
17870b57cec5SDimitry Andric if (tok == "INCLUDE") {
17880b57cec5SDimitry Andric readInclude();
17890b57cec5SDimitry Andric continue;
17900b57cec5SDimitry Andric }
17910b57cec5SDimitry Andric
17920b57cec5SDimitry Andric uint32_t flags = 0;
17934824e7fdSDimitry Andric uint32_t invFlags = 0;
17940b57cec5SDimitry Andric uint32_t negFlags = 0;
17954824e7fdSDimitry Andric uint32_t negInvFlags = 0;
17960b57cec5SDimitry Andric if (consume("(")) {
17974824e7fdSDimitry Andric readMemoryAttributes(flags, invFlags, negFlags, negInvFlags);
17980b57cec5SDimitry Andric expect(")");
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric expect(":");
18010b57cec5SDimitry Andric
18025ffd83dbSDimitry Andric Expr origin = readMemoryAssignment("ORIGIN", "org", "o");
18030b57cec5SDimitry Andric expect(",");
18045ffd83dbSDimitry Andric Expr length = readMemoryAssignment("LENGTH", "len", "l");
18050b57cec5SDimitry Andric
18060b57cec5SDimitry Andric // Add the memory region to the region map.
18074824e7fdSDimitry Andric MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags,
18084824e7fdSDimitry Andric negFlags, negInvFlags);
18090b57cec5SDimitry Andric if (!script->memoryRegions.insert({tok, mr}).second)
18100b57cec5SDimitry Andric setError("region '" + tok + "' already defined");
18110b57cec5SDimitry Andric }
18120b57cec5SDimitry Andric }
18130b57cec5SDimitry Andric
18140b57cec5SDimitry Andric // This function parses the attributes used to match against section
18150b57cec5SDimitry Andric // flags when placing output sections in a memory region. These flags
18160b57cec5SDimitry Andric // are only used when an explicit memory region name is not used.
readMemoryAttributes(uint32_t & flags,uint32_t & invFlags,uint32_t & negFlags,uint32_t & negInvFlags)18174824e7fdSDimitry Andric void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
18184824e7fdSDimitry Andric uint32_t &negFlags,
18194824e7fdSDimitry Andric uint32_t &negInvFlags) {
18200b57cec5SDimitry Andric bool invert = false;
18210b57cec5SDimitry Andric
18220b57cec5SDimitry Andric for (char c : next().lower()) {
18234824e7fdSDimitry Andric if (c == '!') {
18240b57cec5SDimitry Andric invert = !invert;
18254824e7fdSDimitry Andric std::swap(flags, negFlags);
18264824e7fdSDimitry Andric std::swap(invFlags, negInvFlags);
18274824e7fdSDimitry Andric continue;
18280b57cec5SDimitry Andric }
18294824e7fdSDimitry Andric if (c == 'w')
18304824e7fdSDimitry Andric flags |= SHF_WRITE;
18314824e7fdSDimitry Andric else if (c == 'x')
18324824e7fdSDimitry Andric flags |= SHF_EXECINSTR;
18334824e7fdSDimitry Andric else if (c == 'a')
18344824e7fdSDimitry Andric flags |= SHF_ALLOC;
18354824e7fdSDimitry Andric else if (c == 'r')
18364824e7fdSDimitry Andric invFlags |= SHF_WRITE;
18374824e7fdSDimitry Andric else
18384824e7fdSDimitry Andric setError("invalid memory region attribute");
18394824e7fdSDimitry Andric }
18404824e7fdSDimitry Andric
18414824e7fdSDimitry Andric if (invert) {
18424824e7fdSDimitry Andric std::swap(flags, negFlags);
18434824e7fdSDimitry Andric std::swap(invFlags, negInvFlags);
18444824e7fdSDimitry Andric }
18450b57cec5SDimitry Andric }
18460b57cec5SDimitry Andric
readLinkerScript(MemoryBufferRef mb)18475ffd83dbSDimitry Andric void elf::readLinkerScript(MemoryBufferRef mb) {
1848e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read linker script",
1849e8d8bef9SDimitry Andric mb.getBufferIdentifier());
18500b57cec5SDimitry Andric ScriptParser(mb).readLinkerScript();
18510b57cec5SDimitry Andric }
18520b57cec5SDimitry Andric
readVersionScript(MemoryBufferRef mb)18535ffd83dbSDimitry Andric void elf::readVersionScript(MemoryBufferRef mb) {
1854e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read version script",
1855e8d8bef9SDimitry Andric mb.getBufferIdentifier());
18560b57cec5SDimitry Andric ScriptParser(mb).readVersionScript();
18570b57cec5SDimitry Andric }
18580b57cec5SDimitry Andric
readDynamicList(MemoryBufferRef mb)18595ffd83dbSDimitry Andric void elf::readDynamicList(MemoryBufferRef mb) {
1860e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read dynamic list", mb.getBufferIdentifier());
18615ffd83dbSDimitry Andric ScriptParser(mb).readDynamicList();
18620b57cec5SDimitry Andric }
186385868e8aSDimitry Andric
readDefsym(StringRef name,MemoryBufferRef mb)18645ffd83dbSDimitry Andric void elf::readDefsym(StringRef name, MemoryBufferRef mb) {
1865e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read defsym input", name);
18665ffd83dbSDimitry Andric ScriptParser(mb).readDefsym(name);
18675ffd83dbSDimitry Andric }
1868