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>
390b57cec5SDimitry Andric #include <vector>
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric using namespace llvm;
420b57cec5SDimitry Andric using namespace llvm::ELF;
430b57cec5SDimitry Andric using namespace llvm::support::endian;
445ffd83dbSDimitry Andric using namespace lld;
455ffd83dbSDimitry Andric using namespace lld::elf;
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric namespace {
480b57cec5SDimitry Andric class ScriptParser final : ScriptLexer {
490b57cec5SDimitry Andric public:
ScriptParser(MemoryBufferRef mb)500b57cec5SDimitry Andric ScriptParser(MemoryBufferRef mb) : ScriptLexer(mb) {
510b57cec5SDimitry Andric // Initialize IsUnderSysroot
520b57cec5SDimitry Andric if (config->sysroot == "")
530b57cec5SDimitry Andric return;
540b57cec5SDimitry Andric StringRef path = mb.getBufferIdentifier();
550b57cec5SDimitry Andric for (; !path.empty(); path = sys::path::parent_path(path)) {
560b57cec5SDimitry Andric if (!sys::fs::equivalent(config->sysroot, path))
570b57cec5SDimitry Andric continue;
580b57cec5SDimitry Andric isUnderSysroot = true;
590b57cec5SDimitry Andric return;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric void readLinkerScript();
640b57cec5SDimitry Andric void readVersionScript();
650b57cec5SDimitry Andric void readDynamicList();
660b57cec5SDimitry Andric void readDefsym(StringRef name);
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric private:
690b57cec5SDimitry Andric void addFile(StringRef path);
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric void readAsNeeded();
720b57cec5SDimitry Andric void readEntry();
730b57cec5SDimitry Andric void readExtern();
740b57cec5SDimitry Andric void readGroup();
750b57cec5SDimitry Andric void readInclude();
760b57cec5SDimitry Andric void readInput();
770b57cec5SDimitry Andric void readMemory();
780b57cec5SDimitry Andric void readOutput();
790b57cec5SDimitry Andric void readOutputArch();
800b57cec5SDimitry Andric void readOutputFormat();
81fe6060f1SDimitry Andric void readOverwriteSections();
820b57cec5SDimitry Andric void readPhdrs();
830b57cec5SDimitry Andric void readRegionAlias();
840b57cec5SDimitry Andric void readSearchDir();
850b57cec5SDimitry Andric void readSections();
860b57cec5SDimitry Andric void readTarget();
870b57cec5SDimitry Andric void readVersion();
880b57cec5SDimitry Andric void readVersionScriptCommand();
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric SymbolAssignment *readSymbolAssignment(StringRef name);
910b57cec5SDimitry Andric ByteCommand *readByteCommand(StringRef tok);
920b57cec5SDimitry Andric std::array<uint8_t, 4> readFill();
930b57cec5SDimitry Andric bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
940b57cec5SDimitry Andric void readSectionAddressType(OutputSection *cmd);
9581ad6265SDimitry Andric OutputDesc *readOverlaySectionDescription();
9681ad6265SDimitry Andric OutputDesc *readOutputSectionDescription(StringRef outSec);
9704eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> readOverlay();
9804eeddc0SDimitry Andric SmallVector<StringRef, 0> readOutputSectionPhdrs();
995ffd83dbSDimitry Andric std::pair<uint64_t, uint64_t> readInputSectionFlags();
1000b57cec5SDimitry Andric InputSectionDescription *readInputSectionDescription(StringRef tok);
1010b57cec5SDimitry Andric StringMatcher readFilePatterns();
10204eeddc0SDimitry Andric SmallVector<SectionPattern, 0> readInputSectionsList();
1035ffd83dbSDimitry Andric InputSectionDescription *readInputSectionRules(StringRef filePattern,
1045ffd83dbSDimitry Andric uint64_t withFlags,
1055ffd83dbSDimitry Andric uint64_t withoutFlags);
1060b57cec5SDimitry Andric unsigned readPhdrType();
107e8d8bef9SDimitry Andric SortSectionPolicy peekSortKind();
1080b57cec5SDimitry Andric SortSectionPolicy readSortKind();
1090b57cec5SDimitry Andric SymbolAssignment *readProvideHidden(bool provide, bool hidden);
1100b57cec5SDimitry Andric SymbolAssignment *readAssignment(StringRef tok);
1110b57cec5SDimitry Andric void readSort();
1120b57cec5SDimitry Andric Expr readAssert();
1130b57cec5SDimitry Andric Expr readConstant();
1140b57cec5SDimitry Andric Expr getPageSize();
1150b57cec5SDimitry Andric
1165ffd83dbSDimitry Andric Expr readMemoryAssignment(StringRef, StringRef, StringRef);
1174824e7fdSDimitry Andric void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
1184824e7fdSDimitry Andric uint32_t &negFlags, uint32_t &negInvFlags);
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric Expr combine(StringRef op, Expr l, Expr r);
1210b57cec5SDimitry Andric Expr readExpr();
1220b57cec5SDimitry Andric Expr readExpr1(Expr lhs, int minPrec);
1230b57cec5SDimitry Andric StringRef readParenLiteral();
1240b57cec5SDimitry Andric Expr readPrimary();
1250b57cec5SDimitry Andric Expr readTernary(Expr cond);
1260b57cec5SDimitry Andric Expr readParenExpr();
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric // For parsing version script.
12904eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> readVersionExtern();
1300b57cec5SDimitry Andric void readAnonymousDeclaration();
1310b57cec5SDimitry Andric void readVersionDeclaration(StringRef verStr);
1320b57cec5SDimitry Andric
13304eeddc0SDimitry Andric std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
1340b57cec5SDimitry Andric readSymbols();
1350b57cec5SDimitry Andric
136349cc55cSDimitry Andric // True if a script being read is in the --sysroot directory.
1370b57cec5SDimitry Andric bool isUnderSysroot = false;
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric // A set to detect an INCLUDE() cycle.
1400b57cec5SDimitry Andric StringSet<> seen;
1410b57cec5SDimitry Andric };
1420b57cec5SDimitry Andric } // namespace
1430b57cec5SDimitry Andric
unquote(StringRef s)1440b57cec5SDimitry Andric static StringRef unquote(StringRef s) {
145fe013be4SDimitry Andric if (s.starts_with("\""))
1460b57cec5SDimitry Andric return s.substr(1, s.size() - 2);
1470b57cec5SDimitry Andric return s;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric // Some operations only support one non absolute value. Move the
1510b57cec5SDimitry Andric // absolute one to the right hand side for convenience.
moveAbsRight(ExprValue & a,ExprValue & b)1520b57cec5SDimitry Andric static void moveAbsRight(ExprValue &a, ExprValue &b) {
1530b57cec5SDimitry Andric if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
1540b57cec5SDimitry Andric std::swap(a, b);
1550b57cec5SDimitry Andric if (!b.isAbsolute())
1560b57cec5SDimitry Andric error(a.loc + ": at least one side of the expression must be absolute");
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
add(ExprValue a,ExprValue b)1590b57cec5SDimitry Andric static ExprValue add(ExprValue a, ExprValue b) {
1600b57cec5SDimitry Andric moveAbsRight(a, b);
1610b57cec5SDimitry Andric return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
sub(ExprValue a,ExprValue b)1640b57cec5SDimitry Andric static ExprValue sub(ExprValue a, ExprValue b) {
1650b57cec5SDimitry Andric // The distance between two symbols in sections is absolute.
1660b57cec5SDimitry Andric if (!a.isAbsolute() && !b.isAbsolute())
1670b57cec5SDimitry Andric return a.getValue() - b.getValue();
1680b57cec5SDimitry Andric return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric
bitAnd(ExprValue a,ExprValue b)1710b57cec5SDimitry Andric static ExprValue bitAnd(ExprValue a, ExprValue b) {
1720b57cec5SDimitry Andric moveAbsRight(a, b);
1730b57cec5SDimitry Andric return {a.sec, a.forceAbsolute,
1740b57cec5SDimitry Andric (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric
bitXor(ExprValue a,ExprValue b)177fe013be4SDimitry Andric static ExprValue bitXor(ExprValue a, ExprValue b) {
178fe013be4SDimitry Andric moveAbsRight(a, b);
179fe013be4SDimitry Andric return {a.sec, a.forceAbsolute,
180fe013be4SDimitry Andric (a.getValue() ^ b.getValue()) - a.getSecAddr(), a.loc};
181fe013be4SDimitry Andric }
182fe013be4SDimitry Andric
bitOr(ExprValue a,ExprValue b)1830b57cec5SDimitry Andric static ExprValue bitOr(ExprValue a, ExprValue b) {
1840b57cec5SDimitry Andric moveAbsRight(a, b);
1850b57cec5SDimitry Andric return {a.sec, a.forceAbsolute,
1860b57cec5SDimitry Andric (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
readDynamicList()1890b57cec5SDimitry Andric void ScriptParser::readDynamicList() {
1900b57cec5SDimitry Andric expect("{");
19104eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
19204eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
1930b57cec5SDimitry Andric std::tie(locals, globals) = readSymbols();
1940b57cec5SDimitry Andric expect(";");
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric if (!atEOF()) {
1970b57cec5SDimitry Andric setError("EOF expected, but got " + next());
1980b57cec5SDimitry Andric return;
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric if (!locals.empty()) {
2010b57cec5SDimitry Andric setError("\"local:\" scope not supported in --dynamic-list");
2020b57cec5SDimitry Andric return;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric for (SymbolVersion v : globals)
2060b57cec5SDimitry Andric config->dynamicList.push_back(v);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
readVersionScript()2090b57cec5SDimitry Andric void ScriptParser::readVersionScript() {
2100b57cec5SDimitry Andric readVersionScriptCommand();
2110b57cec5SDimitry Andric if (!atEOF())
2120b57cec5SDimitry Andric setError("EOF expected, but got " + next());
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
readVersionScriptCommand()2150b57cec5SDimitry Andric void ScriptParser::readVersionScriptCommand() {
2160b57cec5SDimitry Andric if (consume("{")) {
2170b57cec5SDimitry Andric readAnonymousDeclaration();
2180b57cec5SDimitry Andric return;
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric while (!atEOF() && !errorCount() && peek() != "}") {
2220b57cec5SDimitry Andric StringRef verStr = next();
2230b57cec5SDimitry Andric if (verStr == "{") {
2240b57cec5SDimitry Andric setError("anonymous version definition is used in "
2250b57cec5SDimitry Andric "combination with other version definitions");
2260b57cec5SDimitry Andric return;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric expect("{");
2290b57cec5SDimitry Andric readVersionDeclaration(verStr);
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric
readVersion()2330b57cec5SDimitry Andric void ScriptParser::readVersion() {
2340b57cec5SDimitry Andric expect("{");
2350b57cec5SDimitry Andric readVersionScriptCommand();
2360b57cec5SDimitry Andric expect("}");
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric
readLinkerScript()2390b57cec5SDimitry Andric void ScriptParser::readLinkerScript() {
2400b57cec5SDimitry Andric while (!atEOF()) {
2410b57cec5SDimitry Andric StringRef tok = next();
2420b57cec5SDimitry Andric if (tok == ";")
2430b57cec5SDimitry Andric continue;
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric if (tok == "ENTRY") {
2460b57cec5SDimitry Andric readEntry();
2470b57cec5SDimitry Andric } else if (tok == "EXTERN") {
2480b57cec5SDimitry Andric readExtern();
2490b57cec5SDimitry Andric } else if (tok == "GROUP") {
2500b57cec5SDimitry Andric readGroup();
2510b57cec5SDimitry Andric } else if (tok == "INCLUDE") {
2520b57cec5SDimitry Andric readInclude();
2530b57cec5SDimitry Andric } else if (tok == "INPUT") {
2540b57cec5SDimitry Andric readInput();
2550b57cec5SDimitry Andric } else if (tok == "MEMORY") {
2560b57cec5SDimitry Andric readMemory();
2570b57cec5SDimitry Andric } else if (tok == "OUTPUT") {
2580b57cec5SDimitry Andric readOutput();
2590b57cec5SDimitry Andric } else if (tok == "OUTPUT_ARCH") {
2600b57cec5SDimitry Andric readOutputArch();
2610b57cec5SDimitry Andric } else if (tok == "OUTPUT_FORMAT") {
2620b57cec5SDimitry Andric readOutputFormat();
263fe6060f1SDimitry Andric } else if (tok == "OVERWRITE_SECTIONS") {
264fe6060f1SDimitry Andric readOverwriteSections();
2650b57cec5SDimitry Andric } else if (tok == "PHDRS") {
2660b57cec5SDimitry Andric readPhdrs();
2670b57cec5SDimitry Andric } else if (tok == "REGION_ALIAS") {
2680b57cec5SDimitry Andric readRegionAlias();
2690b57cec5SDimitry Andric } else if (tok == "SEARCH_DIR") {
2700b57cec5SDimitry Andric readSearchDir();
2710b57cec5SDimitry Andric } else if (tok == "SECTIONS") {
2720b57cec5SDimitry Andric readSections();
2730b57cec5SDimitry Andric } else if (tok == "TARGET") {
2740b57cec5SDimitry Andric readTarget();
2750b57cec5SDimitry Andric } else if (tok == "VERSION") {
2760b57cec5SDimitry Andric readVersion();
2770b57cec5SDimitry Andric } else if (SymbolAssignment *cmd = readAssignment(tok)) {
2780b57cec5SDimitry Andric script->sectionCommands.push_back(cmd);
2790b57cec5SDimitry Andric } else {
2800b57cec5SDimitry Andric setError("unknown directive: " + tok);
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric
readDefsym(StringRef name)2850b57cec5SDimitry Andric void ScriptParser::readDefsym(StringRef name) {
2860b57cec5SDimitry Andric if (errorCount())
2870b57cec5SDimitry Andric return;
2880b57cec5SDimitry Andric Expr e = readExpr();
2890b57cec5SDimitry Andric if (!atEOF())
2900b57cec5SDimitry Andric setError("EOF expected, but got " + next());
291a58f00eaSDimitry Andric auto *cmd = make<SymbolAssignment>(
292a58f00eaSDimitry Andric name, e, 0, getCurrentMB().getBufferIdentifier().str());
2930b57cec5SDimitry Andric script->sectionCommands.push_back(cmd);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
addFile(StringRef s)2960b57cec5SDimitry Andric void ScriptParser::addFile(StringRef s) {
297fe013be4SDimitry Andric if (isUnderSysroot && s.starts_with("/")) {
2980b57cec5SDimitry Andric SmallString<128> pathData;
2990b57cec5SDimitry Andric StringRef path = (config->sysroot + s).toStringRef(pathData);
300fe6060f1SDimitry Andric if (sys::fs::exists(path))
301bdd1243dSDimitry Andric ctx.driver.addFile(saver().save(path), /*withLOption=*/false);
302fe6060f1SDimitry Andric else
303fe6060f1SDimitry Andric setError("cannot find " + s + " inside " + config->sysroot);
3040b57cec5SDimitry Andric return;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
307fe013be4SDimitry Andric if (s.starts_with("/")) {
3085ffd83dbSDimitry Andric // Case 1: s is an absolute path. Just open it.
309bdd1243dSDimitry Andric ctx.driver.addFile(s, /*withLOption=*/false);
310fe013be4SDimitry Andric } else if (s.starts_with("=")) {
3115ffd83dbSDimitry Andric // Case 2: relative to the sysroot.
3120b57cec5SDimitry Andric if (config->sysroot.empty())
313bdd1243dSDimitry Andric ctx.driver.addFile(s.substr(1), /*withLOption=*/false);
3140b57cec5SDimitry Andric else
315bdd1243dSDimitry Andric ctx.driver.addFile(saver().save(config->sysroot + "/" + s.substr(1)),
3160b57cec5SDimitry Andric /*withLOption=*/false);
317fe013be4SDimitry Andric } else if (s.starts_with("-l")) {
3185ffd83dbSDimitry Andric // Case 3: search in the list of library paths.
319bdd1243dSDimitry Andric ctx.driver.addLibrary(s.substr(2));
3205ffd83dbSDimitry Andric } else {
3215ffd83dbSDimitry Andric // Case 4: s is a relative path. Search in the directory of the script file.
3225ffd83dbSDimitry Andric std::string filename = std::string(getCurrentMB().getBufferIdentifier());
3235ffd83dbSDimitry Andric StringRef directory = sys::path::parent_path(filename);
3245ffd83dbSDimitry Andric if (!directory.empty()) {
3255ffd83dbSDimitry Andric SmallString<0> path(directory);
3265ffd83dbSDimitry Andric sys::path::append(path, s);
3275ffd83dbSDimitry Andric if (sys::fs::exists(path)) {
328bdd1243dSDimitry Andric ctx.driver.addFile(path, /*withLOption=*/false);
3295ffd83dbSDimitry Andric return;
3305ffd83dbSDimitry Andric }
3315ffd83dbSDimitry Andric }
3325ffd83dbSDimitry Andric // Then search in the current working directory.
3335ffd83dbSDimitry Andric if (sys::fs::exists(s)) {
334bdd1243dSDimitry Andric ctx.driver.addFile(s, /*withLOption=*/false);
3350b57cec5SDimitry Andric } else {
3365ffd83dbSDimitry Andric // Finally, search in the list of library paths.
337bdd1243dSDimitry Andric if (std::optional<std::string> path = findFromSearchPaths(s))
338bdd1243dSDimitry Andric ctx.driver.addFile(saver().save(*path), /*withLOption=*/true);
3390b57cec5SDimitry Andric else
3400b57cec5SDimitry Andric setError("unable to find " + s);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric }
3435ffd83dbSDimitry Andric }
3440b57cec5SDimitry Andric
readAsNeeded()3450b57cec5SDimitry Andric void ScriptParser::readAsNeeded() {
3460b57cec5SDimitry Andric expect("(");
3470b57cec5SDimitry Andric bool orig = config->asNeeded;
3480b57cec5SDimitry Andric config->asNeeded = true;
3490b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
3500b57cec5SDimitry Andric addFile(unquote(next()));
3510b57cec5SDimitry Andric config->asNeeded = orig;
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric
readEntry()3540b57cec5SDimitry Andric void ScriptParser::readEntry() {
3550b57cec5SDimitry Andric // -e <symbol> takes predecence over ENTRY(<symbol>).
3560b57cec5SDimitry Andric expect("(");
3570b57cec5SDimitry Andric StringRef tok = next();
3580b57cec5SDimitry Andric if (config->entry.empty())
35981ad6265SDimitry Andric config->entry = unquote(tok);
3600b57cec5SDimitry Andric expect(")");
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric
readExtern()3630b57cec5SDimitry Andric void ScriptParser::readExtern() {
3640b57cec5SDimitry Andric expect("(");
3650b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
3660b57cec5SDimitry Andric config->undefined.push_back(unquote(next()));
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
readGroup()3690b57cec5SDimitry Andric void ScriptParser::readGroup() {
3700b57cec5SDimitry Andric bool orig = InputFile::isInGroup;
3710b57cec5SDimitry Andric InputFile::isInGroup = true;
3720b57cec5SDimitry Andric readInput();
3730b57cec5SDimitry Andric InputFile::isInGroup = orig;
3740b57cec5SDimitry Andric if (!orig)
3750b57cec5SDimitry Andric ++InputFile::nextGroupId;
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
readInclude()3780b57cec5SDimitry Andric void ScriptParser::readInclude() {
3790b57cec5SDimitry Andric StringRef tok = unquote(next());
3800b57cec5SDimitry Andric
3810b57cec5SDimitry Andric if (!seen.insert(tok).second) {
3820b57cec5SDimitry Andric setError("there is a cycle in linker script INCLUDEs");
3830b57cec5SDimitry Andric return;
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric
386bdd1243dSDimitry Andric if (std::optional<std::string> path = searchScript(tok)) {
387bdd1243dSDimitry Andric if (std::optional<MemoryBufferRef> mb = readFile(*path))
3880b57cec5SDimitry Andric tokenize(*mb);
3890b57cec5SDimitry Andric return;
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric setError("cannot find linker script " + tok);
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric
readInput()3940b57cec5SDimitry Andric void ScriptParser::readInput() {
3950b57cec5SDimitry Andric expect("(");
3960b57cec5SDimitry Andric while (!errorCount() && !consume(")")) {
3970b57cec5SDimitry Andric if (consume("AS_NEEDED"))
3980b57cec5SDimitry Andric readAsNeeded();
3990b57cec5SDimitry Andric else
4000b57cec5SDimitry Andric addFile(unquote(next()));
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric
readOutput()4040b57cec5SDimitry Andric void ScriptParser::readOutput() {
4050b57cec5SDimitry Andric // -o <file> takes predecence over OUTPUT(<file>).
4060b57cec5SDimitry Andric expect("(");
4070b57cec5SDimitry Andric StringRef tok = next();
4080b57cec5SDimitry Andric if (config->outputFile.empty())
4090b57cec5SDimitry Andric config->outputFile = unquote(tok);
4100b57cec5SDimitry Andric expect(")");
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric
readOutputArch()4130b57cec5SDimitry Andric void ScriptParser::readOutputArch() {
4140b57cec5SDimitry Andric // OUTPUT_ARCH is ignored for now.
4150b57cec5SDimitry Andric expect("(");
4160b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
4170b57cec5SDimitry Andric skip();
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric
parseBfdName(StringRef s)4200b57cec5SDimitry Andric static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
4210b57cec5SDimitry Andric return StringSwitch<std::pair<ELFKind, uint16_t>>(s)
4220b57cec5SDimitry Andric .Case("elf32-i386", {ELF32LEKind, EM_386})
42381ad6265SDimitry Andric .Case("elf32-avr", {ELF32LEKind, EM_AVR})
4240b57cec5SDimitry Andric .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})
4250b57cec5SDimitry Andric .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})
426fe013be4SDimitry Andric .Case("elf32-bigarm", {ELF32BEKind, EM_ARM})
4270b57cec5SDimitry Andric .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64})
4280b57cec5SDimitry Andric .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64})
4290b57cec5SDimitry Andric .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64})
430fe6060f1SDimitry Andric .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64})
4310b57cec5SDimitry Andric .Case("elf32-powerpc", {ELF32BEKind, EM_PPC})
432e8d8bef9SDimitry Andric .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC})
4330b57cec5SDimitry Andric .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64})
4340b57cec5SDimitry Andric .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64})
4350b57cec5SDimitry Andric .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64})
4360b57cec5SDimitry Andric .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS})
4370b57cec5SDimitry Andric .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS})
4380b57cec5SDimitry Andric .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS})
4390b57cec5SDimitry Andric .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})
4400b57cec5SDimitry Andric .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS})
4410b57cec5SDimitry Andric .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})
4420b57cec5SDimitry Andric .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV})
4430b57cec5SDimitry Andric .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
4445ffd83dbSDimitry Andric .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9})
445e8d8bef9SDimitry Andric .Case("elf32-msp430", {ELF32LEKind, EM_MSP430})
446fe013be4SDimitry Andric .Case("elf32-loongarch", {ELF32LEKind, EM_LOONGARCH})
447fe013be4SDimitry Andric .Case("elf64-loongarch", {ELF64LEKind, EM_LOONGARCH})
448*4b8be30bSDimitry Andric .Case("elf64-s390", {ELF64BEKind, EM_S390})
4490b57cec5SDimitry Andric .Default({ELFNoneKind, EM_NONE});
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric
452fe6060f1SDimitry Andric // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose
453fe6060f1SDimitry Andric // big if -EB is specified, little if -EL is specified, or default if neither is
454fe6060f1SDimitry Andric // specified.
readOutputFormat()4550b57cec5SDimitry Andric void ScriptParser::readOutputFormat() {
4560b57cec5SDimitry Andric expect("(");
4570b57cec5SDimitry Andric
458fe6060f1SDimitry Andric StringRef s;
4595ffd83dbSDimitry Andric config->bfdname = unquote(next());
460fe6060f1SDimitry Andric if (!consume(")")) {
461fe6060f1SDimitry Andric expect(",");
462fe6060f1SDimitry Andric s = unquote(next());
463fe6060f1SDimitry Andric if (config->optEB)
464fe6060f1SDimitry Andric config->bfdname = s;
465fe6060f1SDimitry Andric expect(",");
466fe6060f1SDimitry Andric s = unquote(next());
467fe6060f1SDimitry Andric if (config->optEL)
468fe6060f1SDimitry Andric config->bfdname = s;
469fe6060f1SDimitry Andric consume(")");
470fe6060f1SDimitry Andric }
471fe6060f1SDimitry Andric s = config->bfdname;
4720b57cec5SDimitry Andric if (s.consume_back("-freebsd"))
4730b57cec5SDimitry Andric config->osabi = ELFOSABI_FREEBSD;
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric std::tie(config->ekind, config->emachine) = parseBfdName(s);
4760b57cec5SDimitry Andric if (config->emachine == EM_NONE)
4775ffd83dbSDimitry Andric setError("unknown output format name: " + config->bfdname);
4780b57cec5SDimitry Andric if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips")
4790b57cec5SDimitry Andric config->mipsN32Abi = true;
480e8d8bef9SDimitry Andric if (config->emachine == EM_MSP430)
481e8d8bef9SDimitry Andric config->osabi = ELFOSABI_STANDALONE;
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric
readPhdrs()4840b57cec5SDimitry Andric void ScriptParser::readPhdrs() {
4850b57cec5SDimitry Andric expect("{");
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
4880b57cec5SDimitry Andric PhdrsCommand cmd;
4890b57cec5SDimitry Andric cmd.name = next();
4900b57cec5SDimitry Andric cmd.type = readPhdrType();
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric while (!errorCount() && !consume(";")) {
4930b57cec5SDimitry Andric if (consume("FILEHDR"))
4940b57cec5SDimitry Andric cmd.hasFilehdr = true;
4950b57cec5SDimitry Andric else if (consume("PHDRS"))
4960b57cec5SDimitry Andric cmd.hasPhdrs = true;
4970b57cec5SDimitry Andric else if (consume("AT"))
4980b57cec5SDimitry Andric cmd.lmaExpr = readParenExpr();
4990b57cec5SDimitry Andric else if (consume("FLAGS"))
5000b57cec5SDimitry Andric cmd.flags = readParenExpr()().getValue();
5010b57cec5SDimitry Andric else
5020b57cec5SDimitry Andric setError("unexpected header attribute: " + next());
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andric script->phdrsCommands.push_back(cmd);
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
readRegionAlias()5090b57cec5SDimitry Andric void ScriptParser::readRegionAlias() {
5100b57cec5SDimitry Andric expect("(");
5110b57cec5SDimitry Andric StringRef alias = unquote(next());
5120b57cec5SDimitry Andric expect(",");
5130b57cec5SDimitry Andric StringRef name = next();
5140b57cec5SDimitry Andric expect(")");
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric if (script->memoryRegions.count(alias))
5170b57cec5SDimitry Andric setError("redefinition of memory region '" + alias + "'");
5180b57cec5SDimitry Andric if (!script->memoryRegions.count(name))
5190b57cec5SDimitry Andric setError("memory region '" + name + "' is not defined");
5200b57cec5SDimitry Andric script->memoryRegions.insert({alias, script->memoryRegions[name]});
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric
readSearchDir()5230b57cec5SDimitry Andric void ScriptParser::readSearchDir() {
5240b57cec5SDimitry Andric expect("(");
5250b57cec5SDimitry Andric StringRef tok = next();
5260b57cec5SDimitry Andric if (!config->nostdlib)
5270b57cec5SDimitry Andric config->searchPaths.push_back(unquote(tok));
5280b57cec5SDimitry Andric expect(")");
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric
5310b57cec5SDimitry Andric // This reads an overlay description. Overlays are used to describe output
5320b57cec5SDimitry Andric // sections that use the same virtual memory range and normally would trigger
5330b57cec5SDimitry Andric // linker's sections sanity check failures.
5340b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
readOverlay()53504eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
536cdc20ff6SDimitry Andric Expr addrExpr;
537cdc20ff6SDimitry Andric if (consume(":")) {
538cdc20ff6SDimitry Andric addrExpr = [] { return script->getDot(); };
539cdc20ff6SDimitry Andric } else {
540cdc20ff6SDimitry Andric addrExpr = readExpr();
5410b57cec5SDimitry Andric expect(":");
542cdc20ff6SDimitry Andric }
543cdc20ff6SDimitry Andric // When AT is omitted, LMA should equal VMA. script->getDot() when evaluating
544cdc20ff6SDimitry Andric // lmaExpr will ensure this, even if the start address is specified.
545cdc20ff6SDimitry Andric Expr lmaExpr =
546cdc20ff6SDimitry Andric consume("AT") ? readParenExpr() : [] { return script->getDot(); };
5470b57cec5SDimitry Andric expect("{");
5480b57cec5SDimitry Andric
54904eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> v;
5500b57cec5SDimitry Andric OutputSection *prev = nullptr;
5510b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
5520b57cec5SDimitry Andric // VA is the same for all sections. The LMAs are consecutive in memory
5530b57cec5SDimitry Andric // starting from the base load address specified.
55481ad6265SDimitry Andric OutputDesc *osd = readOverlaySectionDescription();
55581ad6265SDimitry Andric osd->osec.addrExpr = addrExpr;
556cdc20ff6SDimitry Andric if (prev) {
55781ad6265SDimitry Andric osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
558cdc20ff6SDimitry Andric } else {
55981ad6265SDimitry Andric osd->osec.lmaExpr = lmaExpr;
560cdc20ff6SDimitry Andric // Use first section address for subsequent sections as initial addrExpr
561cdc20ff6SDimitry Andric // can be DOT. Ensure the first section, even if empty, is not discarded.
562cdc20ff6SDimitry Andric osd->osec.usedInExpression = true;
563cdc20ff6SDimitry Andric addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
564cdc20ff6SDimitry Andric }
56581ad6265SDimitry Andric v.push_back(osd);
56681ad6265SDimitry Andric prev = &osd->osec;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andric // According to the specification, at the end of the overlay, the location
5700b57cec5SDimitry Andric // counter should be equal to the overlay base address plus size of the
5710b57cec5SDimitry Andric // largest section seen in the overlay.
5720b57cec5SDimitry Andric // Here we want to create the Dot assignment command to achieve that.
5730b57cec5SDimitry Andric Expr moveDot = [=] {
5740b57cec5SDimitry Andric uint64_t max = 0;
5754824e7fdSDimitry Andric for (SectionCommand *cmd : v)
57681ad6265SDimitry Andric max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
5770b57cec5SDimitry Andric return addrExpr().getValue() + max;
5780b57cec5SDimitry Andric };
579c9157d92SDimitry Andric v.push_back(make<SymbolAssignment>(".", moveDot, 0, getCurrentLocation()));
5800b57cec5SDimitry Andric return v;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric
readOverwriteSections()583fe6060f1SDimitry Andric void ScriptParser::readOverwriteSections() {
584fe6060f1SDimitry Andric expect("{");
585fe6060f1SDimitry Andric while (!errorCount() && !consume("}"))
586fe6060f1SDimitry Andric script->overwriteSections.push_back(readOutputSectionDescription(next()));
587fe6060f1SDimitry Andric }
588fe6060f1SDimitry Andric
readSections()5890b57cec5SDimitry Andric void ScriptParser::readSections() {
5900b57cec5SDimitry Andric expect("{");
59104eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> v;
5920b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
5930b57cec5SDimitry Andric StringRef tok = next();
5940b57cec5SDimitry Andric if (tok == "OVERLAY") {
5954824e7fdSDimitry Andric for (SectionCommand *cmd : readOverlay())
5960b57cec5SDimitry Andric v.push_back(cmd);
5970b57cec5SDimitry Andric continue;
5980b57cec5SDimitry Andric } else if (tok == "INCLUDE") {
5990b57cec5SDimitry Andric readInclude();
6000b57cec5SDimitry Andric continue;
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric
6034824e7fdSDimitry Andric if (SectionCommand *cmd = readAssignment(tok))
6040b57cec5SDimitry Andric v.push_back(cmd);
6050b57cec5SDimitry Andric else
6060b57cec5SDimitry Andric v.push_back(readOutputSectionDescription(tok));
6070b57cec5SDimitry Andric }
60881ad6265SDimitry Andric
60981ad6265SDimitry Andric // If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
61081ad6265SDimitry Andric // the relro fields should be cleared.
611c9157d92SDimitry Andric if (!script->seenRelroEnd)
61281ad6265SDimitry Andric for (SectionCommand *cmd : v)
61381ad6265SDimitry Andric if (auto *osd = dyn_cast<OutputDesc>(cmd))
61481ad6265SDimitry Andric osd->osec.relro = false;
61581ad6265SDimitry Andric
6165ffd83dbSDimitry Andric script->sectionCommands.insert(script->sectionCommands.end(), v.begin(),
6175ffd83dbSDimitry Andric v.end());
6180b57cec5SDimitry Andric
6195ffd83dbSDimitry Andric if (atEOF() || !consume("INSERT")) {
6205ffd83dbSDimitry Andric script->hasSectionsCommand = true;
6210b57cec5SDimitry Andric return;
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric
6245ffd83dbSDimitry Andric bool isAfter = false;
6255ffd83dbSDimitry Andric if (consume("AFTER"))
6265ffd83dbSDimitry Andric isAfter = true;
6275ffd83dbSDimitry Andric else if (!consume("BEFORE"))
6285ffd83dbSDimitry Andric setError("expected AFTER/BEFORE, but got '" + next() + "'");
6295ffd83dbSDimitry Andric StringRef where = next();
63004eeddc0SDimitry Andric SmallVector<StringRef, 0> names;
6314824e7fdSDimitry Andric for (SectionCommand *cmd : v)
63281ad6265SDimitry Andric if (auto *os = dyn_cast<OutputDesc>(cmd))
63381ad6265SDimitry Andric names.push_back(os->osec.name);
634fe6060f1SDimitry Andric if (!names.empty())
635fe6060f1SDimitry Andric script->insertCommands.push_back({std::move(names), isAfter, where});
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric
readTarget()6380b57cec5SDimitry Andric void ScriptParser::readTarget() {
6390b57cec5SDimitry Andric // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers,
6400b57cec5SDimitry Andric // we accept only a limited set of BFD names (i.e. "elf" or "binary")
6410b57cec5SDimitry Andric // for --format. We recognize only /^elf/ and "binary" in the linker
6420b57cec5SDimitry Andric // script as well.
6430b57cec5SDimitry Andric expect("(");
64481ad6265SDimitry Andric StringRef tok = unquote(next());
6450b57cec5SDimitry Andric expect(")");
6460b57cec5SDimitry Andric
647fe013be4SDimitry Andric if (tok.starts_with("elf"))
6480b57cec5SDimitry Andric config->formatBinary = false;
6490b57cec5SDimitry Andric else if (tok == "binary")
6500b57cec5SDimitry Andric config->formatBinary = true;
6510b57cec5SDimitry Andric else
6520b57cec5SDimitry Andric setError("unknown target: " + tok);
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric
precedence(StringRef op)6550b57cec5SDimitry Andric static int precedence(StringRef op) {
6560b57cec5SDimitry Andric return StringSwitch<int>(op)
657fe013be4SDimitry Andric .Cases("*", "/", "%", 11)
658fe013be4SDimitry Andric .Cases("+", "-", 10)
659fe013be4SDimitry Andric .Cases("<<", ">>", 9)
660fe013be4SDimitry Andric .Cases("<", "<=", ">", ">=", 8)
661fe013be4SDimitry Andric .Cases("==", "!=", 7)
662fe013be4SDimitry Andric .Case("&", 6)
663fe013be4SDimitry Andric .Case("^", 5)
66481ad6265SDimitry Andric .Case("|", 4)
66581ad6265SDimitry Andric .Case("&&", 3)
66681ad6265SDimitry Andric .Case("||", 2)
66781ad6265SDimitry Andric .Case("?", 1)
6680b57cec5SDimitry Andric .Default(-1);
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric
readFilePatterns()6710b57cec5SDimitry Andric StringMatcher ScriptParser::readFilePatterns() {
6725ffd83dbSDimitry Andric StringMatcher Matcher;
6735ffd83dbSDimitry Andric
6740b57cec5SDimitry Andric while (!errorCount() && !consume(")"))
6755ffd83dbSDimitry Andric Matcher.addPattern(SingleStringMatcher(next()));
6765ffd83dbSDimitry Andric return Matcher;
6770b57cec5SDimitry Andric }
6780b57cec5SDimitry Andric
peekSortKind()679e8d8bef9SDimitry Andric SortSectionPolicy ScriptParser::peekSortKind() {
680e8d8bef9SDimitry Andric return StringSwitch<SortSectionPolicy>(peek())
681fe013be4SDimitry Andric .Case("REVERSE", SortSectionPolicy::Reverse)
682e8d8bef9SDimitry Andric .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name)
683e8d8bef9SDimitry Andric .Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment)
684e8d8bef9SDimitry Andric .Case("SORT_BY_INIT_PRIORITY", SortSectionPolicy::Priority)
685e8d8bef9SDimitry Andric .Case("SORT_NONE", SortSectionPolicy::None)
686e8d8bef9SDimitry Andric .Default(SortSectionPolicy::Default);
687e8d8bef9SDimitry Andric }
688e8d8bef9SDimitry Andric
readSortKind()6890b57cec5SDimitry Andric SortSectionPolicy ScriptParser::readSortKind() {
690e8d8bef9SDimitry Andric SortSectionPolicy ret = peekSortKind();
691e8d8bef9SDimitry Andric if (ret != SortSectionPolicy::Default)
692e8d8bef9SDimitry Andric skip();
693e8d8bef9SDimitry Andric return ret;
6940b57cec5SDimitry Andric }
6950b57cec5SDimitry Andric
6960b57cec5SDimitry Andric // Reads SECTIONS command contents in the following form:
6970b57cec5SDimitry Andric //
6980b57cec5SDimitry Andric // <contents> ::= <elem>*
6990b57cec5SDimitry Andric // <elem> ::= <exclude>? <glob-pattern>
7000b57cec5SDimitry Andric // <exclude> ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")"
7010b57cec5SDimitry Andric //
7020b57cec5SDimitry Andric // For example,
7030b57cec5SDimitry Andric //
7040b57cec5SDimitry Andric // *(.foo EXCLUDE_FILE (a.o) .bar EXCLUDE_FILE (b.o) .baz)
7050b57cec5SDimitry Andric //
7060b57cec5SDimitry Andric // is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o".
7070b57cec5SDimitry Andric // The semantics of that is section .foo in any file, section .bar in
7080b57cec5SDimitry Andric // any file but a.o, and section .baz in any file but b.o.
readInputSectionsList()70904eeddc0SDimitry Andric SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
71004eeddc0SDimitry Andric SmallVector<SectionPattern, 0> ret;
7110b57cec5SDimitry Andric while (!errorCount() && peek() != ")") {
7120b57cec5SDimitry Andric StringMatcher excludeFilePat;
7130b57cec5SDimitry Andric if (consume("EXCLUDE_FILE")) {
7140b57cec5SDimitry Andric expect("(");
7150b57cec5SDimitry Andric excludeFilePat = readFilePatterns();
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric
7185ffd83dbSDimitry Andric StringMatcher SectionMatcher;
719e8d8bef9SDimitry Andric // Break if the next token is ), EXCLUDE_FILE, or SORT*.
720e8d8bef9SDimitry Andric while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE" &&
721e8d8bef9SDimitry Andric peekSortKind() == SortSectionPolicy::Default)
7225ffd83dbSDimitry Andric SectionMatcher.addPattern(unquote(next()));
7230b57cec5SDimitry Andric
7245ffd83dbSDimitry Andric if (!SectionMatcher.empty())
7255ffd83dbSDimitry Andric ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)});
726e8d8bef9SDimitry Andric else if (excludeFilePat.empty())
727e8d8bef9SDimitry Andric break;
7280b57cec5SDimitry Andric else
7290b57cec5SDimitry Andric setError("section pattern is expected");
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric return ret;
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric
7340b57cec5SDimitry Andric // Reads contents of "SECTIONS" directive. That directive contains a
7350b57cec5SDimitry Andric // list of glob patterns for input sections. The grammar is as follows.
7360b57cec5SDimitry Andric //
7370b57cec5SDimitry Andric // <patterns> ::= <section-list>
7380b57cec5SDimitry Andric // | <sort> "(" <section-list> ")"
7390b57cec5SDimitry Andric // | <sort> "(" <sort> "(" <section-list> ")" ")"
7400b57cec5SDimitry Andric //
7410b57cec5SDimitry Andric // <sort> ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT"
7420b57cec5SDimitry Andric // | "SORT_BY_INIT_PRIORITY" | "SORT_NONE"
7430b57cec5SDimitry Andric //
7440b57cec5SDimitry Andric // <section-list> is parsed by readInputSectionsList().
7450b57cec5SDimitry Andric InputSectionDescription *
readInputSectionRules(StringRef filePattern,uint64_t withFlags,uint64_t withoutFlags)7465ffd83dbSDimitry Andric ScriptParser::readInputSectionRules(StringRef filePattern, uint64_t withFlags,
7475ffd83dbSDimitry Andric uint64_t withoutFlags) {
7485ffd83dbSDimitry Andric auto *cmd =
7495ffd83dbSDimitry Andric make<InputSectionDescription>(filePattern, withFlags, withoutFlags);
7500b57cec5SDimitry Andric expect("(");
7510b57cec5SDimitry Andric
7520b57cec5SDimitry Andric while (!errorCount() && !consume(")")) {
7530b57cec5SDimitry Andric SortSectionPolicy outer = readSortKind();
7540b57cec5SDimitry Andric SortSectionPolicy inner = SortSectionPolicy::Default;
75504eeddc0SDimitry Andric SmallVector<SectionPattern, 0> v;
7560b57cec5SDimitry Andric if (outer != SortSectionPolicy::Default) {
7570b57cec5SDimitry Andric expect("(");
7580b57cec5SDimitry Andric inner = readSortKind();
7590b57cec5SDimitry Andric if (inner != SortSectionPolicy::Default) {
7600b57cec5SDimitry Andric expect("(");
7610b57cec5SDimitry Andric v = readInputSectionsList();
7620b57cec5SDimitry Andric expect(")");
7630b57cec5SDimitry Andric } else {
7640b57cec5SDimitry Andric v = readInputSectionsList();
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric expect(")");
7670b57cec5SDimitry Andric } else {
7680b57cec5SDimitry Andric v = readInputSectionsList();
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric
7710b57cec5SDimitry Andric for (SectionPattern &pat : v) {
7720b57cec5SDimitry Andric pat.sortInner = inner;
7730b57cec5SDimitry Andric pat.sortOuter = outer;
7740b57cec5SDimitry Andric }
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns));
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric return cmd;
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric InputSectionDescription *
readInputSectionDescription(StringRef tok)7820b57cec5SDimitry Andric ScriptParser::readInputSectionDescription(StringRef tok) {
7830b57cec5SDimitry Andric // Input section wildcard can be surrounded by KEEP.
7840b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep
7855ffd83dbSDimitry Andric uint64_t withFlags = 0;
7865ffd83dbSDimitry Andric uint64_t withoutFlags = 0;
7870b57cec5SDimitry Andric if (tok == "KEEP") {
7880b57cec5SDimitry Andric expect("(");
7895ffd83dbSDimitry Andric if (consume("INPUT_SECTION_FLAGS"))
7905ffd83dbSDimitry Andric std::tie(withFlags, withoutFlags) = readInputSectionFlags();
7915ffd83dbSDimitry Andric InputSectionDescription *cmd =
7925ffd83dbSDimitry Andric readInputSectionRules(next(), withFlags, withoutFlags);
7930b57cec5SDimitry Andric expect(")");
7940b57cec5SDimitry Andric script->keptSections.push_back(cmd);
7950b57cec5SDimitry Andric return cmd;
7960b57cec5SDimitry Andric }
7975ffd83dbSDimitry Andric if (tok == "INPUT_SECTION_FLAGS") {
7985ffd83dbSDimitry Andric std::tie(withFlags, withoutFlags) = readInputSectionFlags();
7995ffd83dbSDimitry Andric tok = next();
8005ffd83dbSDimitry Andric }
8015ffd83dbSDimitry Andric return readInputSectionRules(tok, withFlags, withoutFlags);
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric
readSort()8040b57cec5SDimitry Andric void ScriptParser::readSort() {
8050b57cec5SDimitry Andric expect("(");
8060b57cec5SDimitry Andric expect("CONSTRUCTORS");
8070b57cec5SDimitry Andric expect(")");
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric
readAssert()8100b57cec5SDimitry Andric Expr ScriptParser::readAssert() {
8110b57cec5SDimitry Andric expect("(");
8120b57cec5SDimitry Andric Expr e = readExpr();
8130b57cec5SDimitry Andric expect(",");
8140b57cec5SDimitry Andric StringRef msg = unquote(next());
8150b57cec5SDimitry Andric expect(")");
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andric return [=] {
8180b57cec5SDimitry Andric if (!e().getValue())
81985868e8aSDimitry Andric errorOrWarn(msg);
8200b57cec5SDimitry Andric return script->getDot();
8210b57cec5SDimitry Andric };
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric
82481ad6265SDimitry Andric #define ECase(X) \
82581ad6265SDimitry Andric { #X, X }
82681ad6265SDimitry Andric constexpr std::pair<const char *, unsigned> typeMap[] = {
82781ad6265SDimitry Andric ECase(SHT_PROGBITS), ECase(SHT_NOTE), ECase(SHT_NOBITS),
82881ad6265SDimitry Andric ECase(SHT_INIT_ARRAY), ECase(SHT_FINI_ARRAY), ECase(SHT_PREINIT_ARRAY),
82981ad6265SDimitry Andric };
83081ad6265SDimitry Andric #undef ECase
83181ad6265SDimitry Andric
8320b57cec5SDimitry Andric // Tries to read the special directive for an output section definition which
83381ad6265SDimitry Andric // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)", "(OVERLAY)", and
83481ad6265SDimitry Andric // "(TYPE=<value>)".
83581ad6265SDimitry Andric // Tok1 and Tok2 are next 2 tokens peeked. See comment for
83681ad6265SDimitry Andric // readSectionAddressType below.
readSectionDirective(OutputSection * cmd,StringRef tok1,StringRef tok2)8370b57cec5SDimitry Andric bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2) {
8380b57cec5SDimitry Andric if (tok1 != "(")
8390b57cec5SDimitry Andric return false;
84081ad6265SDimitry Andric if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" &&
84181ad6265SDimitry Andric tok2 != "OVERLAY" && tok2 != "TYPE")
8420b57cec5SDimitry Andric return false;
8430b57cec5SDimitry Andric
8440b57cec5SDimitry Andric expect("(");
8450b57cec5SDimitry Andric if (consume("NOLOAD")) {
846e837bb5cSDimitry Andric cmd->type = SHT_NOBITS;
84781ad6265SDimitry Andric cmd->typeIsSet = true;
84881ad6265SDimitry Andric } else if (consume("TYPE")) {
84981ad6265SDimitry Andric expect("=");
85081ad6265SDimitry Andric StringRef value = peek();
85181ad6265SDimitry Andric auto it = llvm::find_if(typeMap, [=](auto e) { return e.first == value; });
85281ad6265SDimitry Andric if (it != std::end(typeMap)) {
85381ad6265SDimitry Andric // The value is a recognized literal SHT_*.
85481ad6265SDimitry Andric cmd->type = it->second;
85581ad6265SDimitry Andric skip();
856fe013be4SDimitry Andric } else if (value.starts_with("SHT_")) {
85781ad6265SDimitry Andric setError("unknown section type " + value);
85881ad6265SDimitry Andric } else {
85981ad6265SDimitry Andric // Otherwise, read an expression.
86081ad6265SDimitry Andric cmd->type = readExpr()().getValue();
86181ad6265SDimitry Andric }
86281ad6265SDimitry Andric cmd->typeIsSet = true;
8630b57cec5SDimitry Andric } else {
8640b57cec5SDimitry Andric skip(); // This is "COPY", "INFO" or "OVERLAY".
8650b57cec5SDimitry Andric cmd->nonAlloc = true;
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric expect(")");
8680b57cec5SDimitry Andric return true;
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric // Reads an expression and/or the special directive for an output
8720b57cec5SDimitry Andric // section definition. Directive is one of following: "(NOLOAD)",
8730b57cec5SDimitry Andric // "(COPY)", "(INFO)" or "(OVERLAY)".
8740b57cec5SDimitry Andric //
8750b57cec5SDimitry Andric // An output section name can be followed by an address expression
8760b57cec5SDimitry Andric // and/or directive. This grammar is not LL(1) because "(" can be
8770b57cec5SDimitry Andric // interpreted as either the beginning of some expression or beginning
8780b57cec5SDimitry Andric // of directive.
8790b57cec5SDimitry Andric //
8800b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
8810b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
readSectionAddressType(OutputSection * cmd)8820b57cec5SDimitry Andric void ScriptParser::readSectionAddressType(OutputSection *cmd) {
88381ad6265SDimitry Andric // Temporarily set inExpr to support TYPE=<value> without spaces.
88481ad6265SDimitry Andric bool saved = std::exchange(inExpr, true);
88581ad6265SDimitry Andric bool isDirective = readSectionDirective(cmd, peek(), peek2());
88681ad6265SDimitry Andric inExpr = saved;
88781ad6265SDimitry Andric if (isDirective)
8880b57cec5SDimitry Andric return;
8890b57cec5SDimitry Andric
8900b57cec5SDimitry Andric cmd->addrExpr = readExpr();
8910b57cec5SDimitry Andric if (peek() == "(" && !readSectionDirective(cmd, "(", peek2()))
8920b57cec5SDimitry Andric setError("unknown section directive: " + peek2());
8930b57cec5SDimitry Andric }
8940b57cec5SDimitry Andric
checkAlignment(Expr e,std::string & loc)8950b57cec5SDimitry Andric static Expr checkAlignment(Expr e, std::string &loc) {
8960b57cec5SDimitry Andric return [=] {
8970b57cec5SDimitry Andric uint64_t alignment = std::max((uint64_t)1, e().getValue());
8980b57cec5SDimitry Andric if (!isPowerOf2_64(alignment)) {
8990b57cec5SDimitry Andric error(loc + ": alignment must be power of 2");
9000b57cec5SDimitry Andric return (uint64_t)1; // Return a dummy value.
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric return alignment;
9030b57cec5SDimitry Andric };
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric
readOverlaySectionDescription()90681ad6265SDimitry Andric OutputDesc *ScriptParser::readOverlaySectionDescription() {
90781ad6265SDimitry Andric OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation());
90881ad6265SDimitry Andric osd->osec.inOverlay = true;
9090b57cec5SDimitry Andric expect("{");
9105ffd83dbSDimitry Andric while (!errorCount() && !consume("}")) {
9115ffd83dbSDimitry Andric uint64_t withFlags = 0;
9125ffd83dbSDimitry Andric uint64_t withoutFlags = 0;
9135ffd83dbSDimitry Andric if (consume("INPUT_SECTION_FLAGS"))
9145ffd83dbSDimitry Andric std::tie(withFlags, withoutFlags) = readInputSectionFlags();
91581ad6265SDimitry Andric osd->osec.commands.push_back(
9165ffd83dbSDimitry Andric readInputSectionRules(next(), withFlags, withoutFlags));
9175ffd83dbSDimitry Andric }
918fe013be4SDimitry Andric osd->osec.phdrs = readOutputSectionPhdrs();
91981ad6265SDimitry Andric return osd;
9200b57cec5SDimitry Andric }
9210b57cec5SDimitry Andric
readOutputSectionDescription(StringRef outSec)92281ad6265SDimitry Andric OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
923fe013be4SDimitry Andric OutputDesc *cmd =
924fe013be4SDimitry Andric script->createOutputSection(unquote(outSec), getCurrentLocation());
92581ad6265SDimitry Andric OutputSection *osec = &cmd->osec;
92681ad6265SDimitry Andric // Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
927c9157d92SDimitry Andric osec->relro = script->seenDataAlign && !script->seenRelroEnd;
9280b57cec5SDimitry Andric
9290b57cec5SDimitry Andric size_t symbolsReferenced = script->referencedSymbols.size();
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andric if (peek() != ":")
93281ad6265SDimitry Andric readSectionAddressType(osec);
9330b57cec5SDimitry Andric expect(":");
9340b57cec5SDimitry Andric
9350b57cec5SDimitry Andric std::string location = getCurrentLocation();
9360b57cec5SDimitry Andric if (consume("AT"))
93781ad6265SDimitry Andric osec->lmaExpr = readParenExpr();
9380b57cec5SDimitry Andric if (consume("ALIGN"))
93981ad6265SDimitry Andric osec->alignExpr = checkAlignment(readParenExpr(), location);
9400b57cec5SDimitry Andric if (consume("SUBALIGN"))
94181ad6265SDimitry Andric osec->subalignExpr = checkAlignment(readParenExpr(), location);
9420b57cec5SDimitry Andric
9430b57cec5SDimitry Andric // Parse constraints.
9440b57cec5SDimitry Andric if (consume("ONLY_IF_RO"))
94581ad6265SDimitry Andric osec->constraint = ConstraintKind::ReadOnly;
9460b57cec5SDimitry Andric if (consume("ONLY_IF_RW"))
94781ad6265SDimitry Andric osec->constraint = ConstraintKind::ReadWrite;
9480b57cec5SDimitry Andric expect("{");
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
9510b57cec5SDimitry Andric StringRef tok = next();
9520b57cec5SDimitry Andric if (tok == ";") {
9530b57cec5SDimitry Andric // Empty commands are allowed. Do nothing here.
9540b57cec5SDimitry Andric } else if (SymbolAssignment *assign = readAssignment(tok)) {
95581ad6265SDimitry Andric osec->commands.push_back(assign);
9560b57cec5SDimitry Andric } else if (ByteCommand *data = readByteCommand(tok)) {
95781ad6265SDimitry Andric osec->commands.push_back(data);
9580b57cec5SDimitry Andric } else if (tok == "CONSTRUCTORS") {
9590b57cec5SDimitry Andric // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
9600b57cec5SDimitry Andric // by name. This is for very old file formats such as ECOFF/XCOFF.
9610b57cec5SDimitry Andric // For ELF, we should ignore.
9620b57cec5SDimitry Andric } else if (tok == "FILL") {
9630b57cec5SDimitry Andric // We handle the FILL command as an alias for =fillexp section attribute,
9640b57cec5SDimitry Andric // which is different from what GNU linkers do.
9650b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
9665ffd83dbSDimitry Andric if (peek() != "(")
9675ffd83dbSDimitry Andric setError("( expected, but got " + peek());
96881ad6265SDimitry Andric osec->filler = readFill();
9690b57cec5SDimitry Andric } else if (tok == "SORT") {
9700b57cec5SDimitry Andric readSort();
9710b57cec5SDimitry Andric } else if (tok == "INCLUDE") {
9720b57cec5SDimitry Andric readInclude();
97381ad6265SDimitry Andric } else if (tok == "(" || tok == ")") {
97481ad6265SDimitry Andric setError("expected filename pattern");
9750b57cec5SDimitry Andric } else if (peek() == "(") {
97681ad6265SDimitry Andric osec->commands.push_back(readInputSectionDescription(tok));
9770b57cec5SDimitry Andric } else {
9780b57cec5SDimitry Andric // We have a file name and no input sections description. It is not a
9790b57cec5SDimitry Andric // commonly used syntax, but still acceptable. In that case, all sections
9800b57cec5SDimitry Andric // from the file will be included.
9815ffd83dbSDimitry Andric // FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not
9825ffd83dbSDimitry Andric // handle this case here as it will already have been matched by the
9835ffd83dbSDimitry Andric // case above.
9840b57cec5SDimitry Andric auto *isd = make<InputSectionDescription>(tok);
9855ffd83dbSDimitry Andric isd->sectionPatterns.push_back({{}, StringMatcher("*")});
98681ad6265SDimitry Andric osec->commands.push_back(isd);
9870b57cec5SDimitry Andric }
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric
9900b57cec5SDimitry Andric if (consume(">"))
99181ad6265SDimitry Andric osec->memoryRegionName = std::string(next());
9920b57cec5SDimitry Andric
9930b57cec5SDimitry Andric if (consume("AT")) {
9940b57cec5SDimitry Andric expect(">");
99581ad6265SDimitry Andric osec->lmaRegionName = std::string(next());
9960b57cec5SDimitry Andric }
9970b57cec5SDimitry Andric
99881ad6265SDimitry Andric if (osec->lmaExpr && !osec->lmaRegionName.empty())
9990b57cec5SDimitry Andric error("section can't have both LMA and a load region");
10000b57cec5SDimitry Andric
100181ad6265SDimitry Andric osec->phdrs = readOutputSectionPhdrs();
10020b57cec5SDimitry Andric
1003fe013be4SDimitry Andric if (peek() == "=" || peek().starts_with("=")) {
10040b57cec5SDimitry Andric inExpr = true;
10050b57cec5SDimitry Andric consume("=");
100681ad6265SDimitry Andric osec->filler = readFill();
10070b57cec5SDimitry Andric inExpr = false;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric
10100b57cec5SDimitry Andric // Consume optional comma following output section command.
10110b57cec5SDimitry Andric consume(",");
10120b57cec5SDimitry Andric
10130b57cec5SDimitry Andric if (script->referencedSymbols.size() > symbolsReferenced)
101481ad6265SDimitry Andric osec->expressionsUseSymbols = true;
10150b57cec5SDimitry Andric return cmd;
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric
10180b57cec5SDimitry Andric // Reads a `=<fillexp>` expression and returns its value as a big-endian number.
10190b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html
10200b57cec5SDimitry Andric // We do not support using symbols in such expressions.
10210b57cec5SDimitry Andric //
10220b57cec5SDimitry Andric // When reading a hexstring, ld.bfd handles it as a blob of arbitrary
10230b57cec5SDimitry Andric // size, while ld.gold always handles it as a 32-bit big-endian number.
10240b57cec5SDimitry Andric // We are compatible with ld.gold because it's easier to implement.
10255ffd83dbSDimitry Andric // Also, we require that expressions with operators must be wrapped into
10265ffd83dbSDimitry Andric // round brackets. We did it to resolve the ambiguity when parsing scripts like:
10275ffd83dbSDimitry Andric // SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } }
readFill()10280b57cec5SDimitry Andric std::array<uint8_t, 4> ScriptParser::readFill() {
10295ffd83dbSDimitry Andric uint64_t value = readPrimary()().val;
10300b57cec5SDimitry Andric if (value > UINT32_MAX)
10310b57cec5SDimitry Andric setError("filler expression result does not fit 32-bit: 0x" +
10320b57cec5SDimitry Andric Twine::utohexstr(value));
10330b57cec5SDimitry Andric
10340b57cec5SDimitry Andric std::array<uint8_t, 4> buf;
10350b57cec5SDimitry Andric write32be(buf.data(), (uint32_t)value);
10360b57cec5SDimitry Andric return buf;
10370b57cec5SDimitry Andric }
10380b57cec5SDimitry Andric
readProvideHidden(bool provide,bool hidden)10390b57cec5SDimitry Andric SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
10400b57cec5SDimitry Andric expect("(");
104181ad6265SDimitry Andric StringRef name = next(), eq = peek();
104281ad6265SDimitry Andric if (eq != "=") {
104381ad6265SDimitry Andric setError("= expected, but got " + next());
104481ad6265SDimitry Andric while (!atEOF() && next() != ")")
104581ad6265SDimitry Andric ;
104681ad6265SDimitry Andric return nullptr;
104781ad6265SDimitry Andric }
104881ad6265SDimitry Andric SymbolAssignment *cmd = readSymbolAssignment(name);
10490b57cec5SDimitry Andric cmd->provide = provide;
10500b57cec5SDimitry Andric cmd->hidden = hidden;
10510b57cec5SDimitry Andric expect(")");
10520b57cec5SDimitry Andric return cmd;
10530b57cec5SDimitry Andric }
10540b57cec5SDimitry Andric
readAssignment(StringRef tok)10550b57cec5SDimitry Andric SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
10560b57cec5SDimitry Andric // Assert expression returns Dot, so this is equal to ".=."
10570b57cec5SDimitry Andric if (tok == "ASSERT")
1058c9157d92SDimitry Andric return make<SymbolAssignment>(".", readAssert(), 0, getCurrentLocation());
10590b57cec5SDimitry Andric
10600b57cec5SDimitry Andric size_t oldPos = pos;
10610b57cec5SDimitry Andric SymbolAssignment *cmd = nullptr;
1062c9157d92SDimitry Andric bool savedSeenRelroEnd = script->seenRelroEnd;
106381ad6265SDimitry Andric const StringRef op = peek();
1064fe013be4SDimitry Andric if (op.starts_with("=")) {
106581ad6265SDimitry Andric // Support = followed by an expression without whitespace.
1066bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
10670b57cec5SDimitry Andric cmd = readSymbolAssignment(tok);
1068fe013be4SDimitry Andric } else if ((op.size() == 2 && op[1] == '=' && strchr("*/+-&^|", op[0])) ||
106981ad6265SDimitry Andric op == "<<=" || op == ">>=") {
107081ad6265SDimitry Andric cmd = readSymbolAssignment(tok);
107181ad6265SDimitry Andric } else if (tok == "PROVIDE") {
1072bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
10730b57cec5SDimitry Andric cmd = readProvideHidden(true, false);
107481ad6265SDimitry Andric } else if (tok == "HIDDEN") {
1075bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
10760b57cec5SDimitry Andric cmd = readProvideHidden(false, true);
107781ad6265SDimitry Andric } else if (tok == "PROVIDE_HIDDEN") {
1078bdd1243dSDimitry Andric SaveAndRestore saved(inExpr, true);
10790b57cec5SDimitry Andric cmd = readProvideHidden(true, true);
108081ad6265SDimitry Andric }
10810b57cec5SDimitry Andric
10820b57cec5SDimitry Andric if (cmd) {
1083c9157d92SDimitry Andric cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && script->seenRelroEnd;
10840b57cec5SDimitry Andric cmd->commandString =
10850b57cec5SDimitry Andric tok.str() + " " +
10860b57cec5SDimitry Andric llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
10870b57cec5SDimitry Andric expect(";");
10880b57cec5SDimitry Andric }
10890b57cec5SDimitry Andric return cmd;
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric
readSymbolAssignment(StringRef name)10920b57cec5SDimitry Andric SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
1093fe6060f1SDimitry Andric name = unquote(name);
10940b57cec5SDimitry Andric StringRef op = next();
109581ad6265SDimitry Andric assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" ||
1096fe013be4SDimitry Andric op == "&=" || op == "^=" || op == "|=" || op == "<<=" || op == ">>=");
1097c9157d92SDimitry Andric // Note: GNU ld does not support %=.
10980b57cec5SDimitry Andric Expr e = readExpr();
109981ad6265SDimitry Andric if (op != "=") {
11000b57cec5SDimitry Andric std::string loc = getCurrentLocation();
110181ad6265SDimitry Andric e = [=, c = op[0]]() -> ExprValue {
110281ad6265SDimitry Andric ExprValue lhs = script->getSymbolValue(name, loc);
110381ad6265SDimitry Andric switch (c) {
110481ad6265SDimitry Andric case '*':
110581ad6265SDimitry Andric return lhs.getValue() * e().getValue();
110681ad6265SDimitry Andric case '/':
110781ad6265SDimitry Andric if (uint64_t rv = e().getValue())
110881ad6265SDimitry Andric return lhs.getValue() / rv;
110981ad6265SDimitry Andric error(loc + ": division by zero");
111081ad6265SDimitry Andric return 0;
111181ad6265SDimitry Andric case '+':
111281ad6265SDimitry Andric return add(lhs, e());
111381ad6265SDimitry Andric case '-':
111481ad6265SDimitry Andric return sub(lhs, e());
111581ad6265SDimitry Andric case '<':
1116fe013be4SDimitry Andric return lhs.getValue() << e().getValue() % 64;
111781ad6265SDimitry Andric case '>':
1118fe013be4SDimitry Andric return lhs.getValue() >> e().getValue() % 64;
111981ad6265SDimitry Andric case '&':
112081ad6265SDimitry Andric return lhs.getValue() & e().getValue();
1121fe013be4SDimitry Andric case '^':
1122fe013be4SDimitry Andric return lhs.getValue() ^ e().getValue();
112381ad6265SDimitry Andric case '|':
112481ad6265SDimitry Andric return lhs.getValue() | e().getValue();
112581ad6265SDimitry Andric default:
112681ad6265SDimitry Andric llvm_unreachable("");
112781ad6265SDimitry Andric }
112881ad6265SDimitry Andric };
11290b57cec5SDimitry Andric }
1130c9157d92SDimitry Andric return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
1131c9157d92SDimitry Andric getCurrentLocation());
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric
11340b57cec5SDimitry Andric // This is an operator-precedence parser to parse a linker
11350b57cec5SDimitry Andric // script expression.
readExpr()11360b57cec5SDimitry Andric Expr ScriptParser::readExpr() {
11370b57cec5SDimitry Andric // Our lexer is context-aware. Set the in-expression bit so that
11380b57cec5SDimitry Andric // they apply different tokenization rules.
11390b57cec5SDimitry Andric bool orig = inExpr;
11400b57cec5SDimitry Andric inExpr = true;
11410b57cec5SDimitry Andric Expr e = readExpr1(readPrimary(), 0);
11420b57cec5SDimitry Andric inExpr = orig;
11430b57cec5SDimitry Andric return e;
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric
combine(StringRef op,Expr l,Expr r)11460b57cec5SDimitry Andric Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
11470b57cec5SDimitry Andric if (op == "+")
11480b57cec5SDimitry Andric return [=] { return add(l(), r()); };
11490b57cec5SDimitry Andric if (op == "-")
11500b57cec5SDimitry Andric return [=] { return sub(l(), r()); };
11510b57cec5SDimitry Andric if (op == "*")
11520b57cec5SDimitry Andric return [=] { return l().getValue() * r().getValue(); };
11530b57cec5SDimitry Andric if (op == "/") {
11540b57cec5SDimitry Andric std::string loc = getCurrentLocation();
11550b57cec5SDimitry Andric return [=]() -> uint64_t {
11560b57cec5SDimitry Andric if (uint64_t rv = r().getValue())
11570b57cec5SDimitry Andric return l().getValue() / rv;
11580b57cec5SDimitry Andric error(loc + ": division by zero");
11590b57cec5SDimitry Andric return 0;
11600b57cec5SDimitry Andric };
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric if (op == "%") {
11630b57cec5SDimitry Andric std::string loc = getCurrentLocation();
11640b57cec5SDimitry Andric return [=]() -> uint64_t {
11650b57cec5SDimitry Andric if (uint64_t rv = r().getValue())
11660b57cec5SDimitry Andric return l().getValue() % rv;
11670b57cec5SDimitry Andric error(loc + ": modulo by zero");
11680b57cec5SDimitry Andric return 0;
11690b57cec5SDimitry Andric };
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric if (op == "<<")
1172fe013be4SDimitry Andric return [=] { return l().getValue() << r().getValue() % 64; };
11730b57cec5SDimitry Andric if (op == ">>")
1174fe013be4SDimitry Andric return [=] { return l().getValue() >> r().getValue() % 64; };
11750b57cec5SDimitry Andric if (op == "<")
11760b57cec5SDimitry Andric return [=] { return l().getValue() < r().getValue(); };
11770b57cec5SDimitry Andric if (op == ">")
11780b57cec5SDimitry Andric return [=] { return l().getValue() > r().getValue(); };
11790b57cec5SDimitry Andric if (op == ">=")
11800b57cec5SDimitry Andric return [=] { return l().getValue() >= r().getValue(); };
11810b57cec5SDimitry Andric if (op == "<=")
11820b57cec5SDimitry Andric return [=] { return l().getValue() <= r().getValue(); };
11830b57cec5SDimitry Andric if (op == "==")
11840b57cec5SDimitry Andric return [=] { return l().getValue() == r().getValue(); };
11850b57cec5SDimitry Andric if (op == "!=")
11860b57cec5SDimitry Andric return [=] { return l().getValue() != r().getValue(); };
11870b57cec5SDimitry Andric if (op == "||")
11880b57cec5SDimitry Andric return [=] { return l().getValue() || r().getValue(); };
11890b57cec5SDimitry Andric if (op == "&&")
11900b57cec5SDimitry Andric return [=] { return l().getValue() && r().getValue(); };
11910b57cec5SDimitry Andric if (op == "&")
11920b57cec5SDimitry Andric return [=] { return bitAnd(l(), r()); };
1193fe013be4SDimitry Andric if (op == "^")
1194fe013be4SDimitry Andric return [=] { return bitXor(l(), r()); };
11950b57cec5SDimitry Andric if (op == "|")
11960b57cec5SDimitry Andric return [=] { return bitOr(l(), r()); };
11970b57cec5SDimitry Andric llvm_unreachable("invalid operator");
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric
12000b57cec5SDimitry Andric // This is a part of the operator-precedence parser. This function
12010b57cec5SDimitry Andric // assumes that the remaining token stream starts with an operator.
readExpr1(Expr lhs,int minPrec)12020b57cec5SDimitry Andric Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
12030b57cec5SDimitry Andric while (!atEOF() && !errorCount()) {
12040b57cec5SDimitry Andric // Read an operator and an expression.
12050b57cec5SDimitry Andric StringRef op1 = peek();
12060b57cec5SDimitry Andric if (precedence(op1) < minPrec)
12070b57cec5SDimitry Andric break;
120881ad6265SDimitry Andric if (consume("?"))
120981ad6265SDimitry Andric return readTernary(lhs);
12100b57cec5SDimitry Andric skip();
12110b57cec5SDimitry Andric Expr rhs = readPrimary();
12120b57cec5SDimitry Andric
12130b57cec5SDimitry Andric // Evaluate the remaining part of the expression first if the
12140b57cec5SDimitry Andric // next operator has greater precedence than the previous one.
12150b57cec5SDimitry Andric // For example, if we have read "+" and "3", and if the next
12160b57cec5SDimitry Andric // operator is "*", then we'll evaluate 3 * ... part first.
12170b57cec5SDimitry Andric while (!atEOF()) {
12180b57cec5SDimitry Andric StringRef op2 = peek();
12190b57cec5SDimitry Andric if (precedence(op2) <= precedence(op1))
12200b57cec5SDimitry Andric break;
12210b57cec5SDimitry Andric rhs = readExpr1(rhs, precedence(op2));
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric
12240b57cec5SDimitry Andric lhs = combine(op1, lhs, rhs);
12250b57cec5SDimitry Andric }
12260b57cec5SDimitry Andric return lhs;
12270b57cec5SDimitry Andric }
12280b57cec5SDimitry Andric
getPageSize()12290b57cec5SDimitry Andric Expr ScriptParser::getPageSize() {
12300b57cec5SDimitry Andric std::string location = getCurrentLocation();
12310b57cec5SDimitry Andric return [=]() -> uint64_t {
12320b57cec5SDimitry Andric if (target)
12330b57cec5SDimitry Andric return config->commonPageSize;
12340b57cec5SDimitry Andric error(location + ": unable to calculate page size");
12350b57cec5SDimitry Andric return 4096; // Return a dummy value.
12360b57cec5SDimitry Andric };
12370b57cec5SDimitry Andric }
12380b57cec5SDimitry Andric
readConstant()12390b57cec5SDimitry Andric Expr ScriptParser::readConstant() {
12400b57cec5SDimitry Andric StringRef s = readParenLiteral();
12410b57cec5SDimitry Andric if (s == "COMMONPAGESIZE")
12420b57cec5SDimitry Andric return getPageSize();
12430b57cec5SDimitry Andric if (s == "MAXPAGESIZE")
12440b57cec5SDimitry Andric return [] { return config->maxPageSize; };
12450b57cec5SDimitry Andric setError("unknown constant: " + s);
12460b57cec5SDimitry Andric return [] { return 0; };
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric
12490b57cec5SDimitry Andric // Parses Tok as an integer. It recognizes hexadecimal (prefixed with
12500b57cec5SDimitry Andric // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
12510b57cec5SDimitry Andric // have "K" (Ki) or "M" (Mi) suffixes.
parseInt(StringRef tok)1252bdd1243dSDimitry Andric static std::optional<uint64_t> parseInt(StringRef tok) {
12530b57cec5SDimitry Andric // Hexadecimal
12540b57cec5SDimitry Andric uint64_t val;
1255fe013be4SDimitry Andric if (tok.starts_with_insensitive("0x")) {
12560b57cec5SDimitry Andric if (!to_integer(tok.substr(2), val, 16))
1257bdd1243dSDimitry Andric return std::nullopt;
12580b57cec5SDimitry Andric return val;
12590b57cec5SDimitry Andric }
1260fe013be4SDimitry Andric if (tok.ends_with_insensitive("H")) {
12610b57cec5SDimitry Andric if (!to_integer(tok.drop_back(), val, 16))
1262bdd1243dSDimitry Andric return std::nullopt;
12630b57cec5SDimitry Andric return val;
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric
12660b57cec5SDimitry Andric // Decimal
1267fe013be4SDimitry Andric if (tok.ends_with_insensitive("K")) {
12680b57cec5SDimitry Andric if (!to_integer(tok.drop_back(), val, 10))
1269bdd1243dSDimitry Andric return std::nullopt;
12700b57cec5SDimitry Andric return val * 1024;
12710b57cec5SDimitry Andric }
1272fe013be4SDimitry Andric if (tok.ends_with_insensitive("M")) {
12730b57cec5SDimitry Andric if (!to_integer(tok.drop_back(), val, 10))
1274bdd1243dSDimitry Andric return std::nullopt;
12750b57cec5SDimitry Andric return val * 1024 * 1024;
12760b57cec5SDimitry Andric }
12770b57cec5SDimitry Andric if (!to_integer(tok, val, 10))
1278bdd1243dSDimitry Andric return std::nullopt;
12790b57cec5SDimitry Andric return val;
12800b57cec5SDimitry Andric }
12810b57cec5SDimitry Andric
readByteCommand(StringRef tok)12820b57cec5SDimitry Andric ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
12830b57cec5SDimitry Andric int size = StringSwitch<int>(tok)
12840b57cec5SDimitry Andric .Case("BYTE", 1)
12850b57cec5SDimitry Andric .Case("SHORT", 2)
12860b57cec5SDimitry Andric .Case("LONG", 4)
12870b57cec5SDimitry Andric .Case("QUAD", 8)
12880b57cec5SDimitry Andric .Default(-1);
12890b57cec5SDimitry Andric if (size == -1)
12900b57cec5SDimitry Andric return nullptr;
12910b57cec5SDimitry Andric
12920b57cec5SDimitry Andric size_t oldPos = pos;
12930b57cec5SDimitry Andric Expr e = readParenExpr();
12940b57cec5SDimitry Andric std::string commandString =
12950b57cec5SDimitry Andric tok.str() + " " +
12960b57cec5SDimitry Andric llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
12970b57cec5SDimitry Andric return make<ByteCommand>(e, size, commandString);
12980b57cec5SDimitry Andric }
12990b57cec5SDimitry Andric
parseFlag(StringRef tok)1300bdd1243dSDimitry Andric static std::optional<uint64_t> parseFlag(StringRef tok) {
1301bdd1243dSDimitry Andric if (std::optional<uint64_t> asInt = parseInt(tok))
13025ffd83dbSDimitry Andric return asInt;
13035ffd83dbSDimitry Andric #define CASE_ENT(enum) #enum, ELF::enum
1304bdd1243dSDimitry Andric return StringSwitch<std::optional<uint64_t>>(tok)
13055ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_WRITE))
13065ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_ALLOC))
13075ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_EXECINSTR))
13085ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_MERGE))
13095ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_STRINGS))
13105ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_INFO_LINK))
13115ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_LINK_ORDER))
13125ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_OS_NONCONFORMING))
13135ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_GROUP))
13145ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_TLS))
13155ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_COMPRESSED))
13165ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_EXCLUDE))
13175ffd83dbSDimitry Andric .Case(CASE_ENT(SHF_ARM_PURECODE))
1318bdd1243dSDimitry Andric .Default(std::nullopt);
13195ffd83dbSDimitry Andric #undef CASE_ENT
13205ffd83dbSDimitry Andric }
13215ffd83dbSDimitry Andric
13225ffd83dbSDimitry Andric // Reads the '(' <flags> ')' list of section flags in
13235ffd83dbSDimitry Andric // INPUT_SECTION_FLAGS '(' <flags> ')' in the
13245ffd83dbSDimitry Andric // following form:
13255ffd83dbSDimitry Andric // <flags> ::= <flag>
13265ffd83dbSDimitry Andric // | <flags> & flag
13275ffd83dbSDimitry Andric // <flag> ::= Recognized Flag Name, or Integer value of flag.
13285ffd83dbSDimitry Andric // If the first character of <flag> is a ! then this means without flag,
13295ffd83dbSDimitry Andric // otherwise with flag.
13305ffd83dbSDimitry Andric // Example: SHF_EXECINSTR & !SHF_WRITE means with flag SHF_EXECINSTR and
13315ffd83dbSDimitry Andric // without flag SHF_WRITE.
readInputSectionFlags()13325ffd83dbSDimitry Andric std::pair<uint64_t, uint64_t> ScriptParser::readInputSectionFlags() {
13335ffd83dbSDimitry Andric uint64_t withFlags = 0;
13345ffd83dbSDimitry Andric uint64_t withoutFlags = 0;
13355ffd83dbSDimitry Andric expect("(");
13365ffd83dbSDimitry Andric while (!errorCount()) {
13375ffd83dbSDimitry Andric StringRef tok = unquote(next());
13385ffd83dbSDimitry Andric bool without = tok.consume_front("!");
1339bdd1243dSDimitry Andric if (std::optional<uint64_t> flag = parseFlag(tok)) {
13405ffd83dbSDimitry Andric if (without)
13415ffd83dbSDimitry Andric withoutFlags |= *flag;
13425ffd83dbSDimitry Andric else
13435ffd83dbSDimitry Andric withFlags |= *flag;
13445ffd83dbSDimitry Andric } else {
13455ffd83dbSDimitry Andric setError("unrecognised flag: " + tok);
13465ffd83dbSDimitry Andric }
13475ffd83dbSDimitry Andric if (consume(")"))
13485ffd83dbSDimitry Andric break;
13495ffd83dbSDimitry Andric if (!consume("&")) {
13505ffd83dbSDimitry Andric next();
13515ffd83dbSDimitry Andric setError("expected & or )");
13525ffd83dbSDimitry Andric }
13535ffd83dbSDimitry Andric }
13545ffd83dbSDimitry Andric return std::make_pair(withFlags, withoutFlags);
13555ffd83dbSDimitry Andric }
13565ffd83dbSDimitry Andric
readParenLiteral()13570b57cec5SDimitry Andric StringRef ScriptParser::readParenLiteral() {
13580b57cec5SDimitry Andric expect("(");
13590b57cec5SDimitry Andric bool orig = inExpr;
13600b57cec5SDimitry Andric inExpr = false;
13610b57cec5SDimitry Andric StringRef tok = next();
13620b57cec5SDimitry Andric inExpr = orig;
13630b57cec5SDimitry Andric expect(")");
13640b57cec5SDimitry Andric return tok;
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric
checkIfExists(const OutputSection & osec,StringRef location)136781ad6265SDimitry Andric static void checkIfExists(const OutputSection &osec, StringRef location) {
136881ad6265SDimitry Andric if (osec.location.empty() && script->errorOnMissingSection)
136981ad6265SDimitry Andric error(location + ": undefined section " + osec.name);
13700b57cec5SDimitry Andric }
13710b57cec5SDimitry Andric
isValidSymbolName(StringRef s)1372fe6060f1SDimitry Andric static bool isValidSymbolName(StringRef s) {
1373fe6060f1SDimitry Andric auto valid = [](char c) {
1374fe6060f1SDimitry Andric return isAlnum(c) || c == '$' || c == '.' || c == '_';
1375fe6060f1SDimitry Andric };
1376fe6060f1SDimitry Andric return !s.empty() && !isDigit(s[0]) && llvm::all_of(s, valid);
1377fe6060f1SDimitry Andric }
1378fe6060f1SDimitry Andric
readPrimary()13790b57cec5SDimitry Andric Expr ScriptParser::readPrimary() {
13800b57cec5SDimitry Andric if (peek() == "(")
13810b57cec5SDimitry Andric return readParenExpr();
13820b57cec5SDimitry Andric
13830b57cec5SDimitry Andric if (consume("~")) {
13840b57cec5SDimitry Andric Expr e = readPrimary();
13850b57cec5SDimitry Andric return [=] { return ~e().getValue(); };
13860b57cec5SDimitry Andric }
13870b57cec5SDimitry Andric if (consume("!")) {
13880b57cec5SDimitry Andric Expr e = readPrimary();
13890b57cec5SDimitry Andric return [=] { return !e().getValue(); };
13900b57cec5SDimitry Andric }
13910b57cec5SDimitry Andric if (consume("-")) {
13920b57cec5SDimitry Andric Expr e = readPrimary();
13930b57cec5SDimitry Andric return [=] { return -e().getValue(); };
13940b57cec5SDimitry Andric }
13950b57cec5SDimitry Andric
13960b57cec5SDimitry Andric StringRef tok = next();
13970b57cec5SDimitry Andric std::string location = getCurrentLocation();
13980b57cec5SDimitry Andric
13990b57cec5SDimitry Andric // Built-in functions are parsed here.
14000b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
14010b57cec5SDimitry Andric if (tok == "ABSOLUTE") {
14020b57cec5SDimitry Andric Expr inner = readParenExpr();
14030b57cec5SDimitry Andric return [=] {
14040b57cec5SDimitry Andric ExprValue i = inner();
14050b57cec5SDimitry Andric i.forceAbsolute = true;
14060b57cec5SDimitry Andric return i;
14070b57cec5SDimitry Andric };
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric if (tok == "ADDR") {
1410fe013be4SDimitry Andric StringRef name = unquote(readParenLiteral());
141181ad6265SDimitry Andric OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
141281ad6265SDimitry Andric osec->usedInExpression = true;
14130b57cec5SDimitry Andric return [=]() -> ExprValue {
141481ad6265SDimitry Andric checkIfExists(*osec, location);
141581ad6265SDimitry Andric return {osec, false, 0, location};
14160b57cec5SDimitry Andric };
14170b57cec5SDimitry Andric }
14180b57cec5SDimitry Andric if (tok == "ALIGN") {
14190b57cec5SDimitry Andric expect("(");
14200b57cec5SDimitry Andric Expr e = readExpr();
14210b57cec5SDimitry Andric if (consume(")")) {
14220b57cec5SDimitry Andric e = checkAlignment(e, location);
1423972a253aSDimitry Andric return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric expect(",");
14260b57cec5SDimitry Andric Expr e2 = checkAlignment(readExpr(), location);
14270b57cec5SDimitry Andric expect(")");
14280b57cec5SDimitry Andric return [=] {
14290b57cec5SDimitry Andric ExprValue v = e();
14300b57cec5SDimitry Andric v.alignment = e2().getValue();
14310b57cec5SDimitry Andric return v;
14320b57cec5SDimitry Andric };
14330b57cec5SDimitry Andric }
14340b57cec5SDimitry Andric if (tok == "ALIGNOF") {
1435fe013be4SDimitry Andric StringRef name = unquote(readParenLiteral());
143681ad6265SDimitry Andric OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
14370b57cec5SDimitry Andric return [=] {
143881ad6265SDimitry Andric checkIfExists(*osec, location);
1439bdd1243dSDimitry Andric return osec->addralign;
14400b57cec5SDimitry Andric };
14410b57cec5SDimitry Andric }
14420b57cec5SDimitry Andric if (tok == "ASSERT")
14430b57cec5SDimitry Andric return readAssert();
14440b57cec5SDimitry Andric if (tok == "CONSTANT")
14450b57cec5SDimitry Andric return readConstant();
14460b57cec5SDimitry Andric if (tok == "DATA_SEGMENT_ALIGN") {
14470b57cec5SDimitry Andric expect("(");
14480b57cec5SDimitry Andric Expr e = readExpr();
14490b57cec5SDimitry Andric expect(",");
14500b57cec5SDimitry Andric readExpr();
14510b57cec5SDimitry Andric expect(")");
1452c9157d92SDimitry Andric script->seenDataAlign = true;
14530b57cec5SDimitry Andric return [=] {
1454972a253aSDimitry Andric uint64_t align = std::max(uint64_t(1), e().getValue());
1455972a253aSDimitry Andric return (script->getDot() + align - 1) & -align;
14560b57cec5SDimitry Andric };
14570b57cec5SDimitry Andric }
14580b57cec5SDimitry Andric if (tok == "DATA_SEGMENT_END") {
14590b57cec5SDimitry Andric expect("(");
14600b57cec5SDimitry Andric expect(".");
14610b57cec5SDimitry Andric expect(")");
14620b57cec5SDimitry Andric return [] { return script->getDot(); };
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric if (tok == "DATA_SEGMENT_RELRO_END") {
14650b57cec5SDimitry Andric // GNU linkers implements more complicated logic to handle
14660b57cec5SDimitry Andric // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
14670b57cec5SDimitry Andric // just align to the next page boundary for simplicity.
14680b57cec5SDimitry Andric expect("(");
14690b57cec5SDimitry Andric readExpr();
14700b57cec5SDimitry Andric expect(",");
14710b57cec5SDimitry Andric readExpr();
14720b57cec5SDimitry Andric expect(")");
1473c9157d92SDimitry Andric script->seenRelroEnd = true;
1474c9157d92SDimitry Andric return [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric if (tok == "DEFINED") {
1477fe6060f1SDimitry Andric StringRef name = unquote(readParenLiteral());
1478c9157d92SDimitry Andric // Return 1 if s is defined. If the definition is only found in a linker
1479c9157d92SDimitry Andric // script, it must happen before this DEFINED.
1480c9157d92SDimitry Andric auto order = ctx.scriptSymOrderCounter++;
1481e8d8bef9SDimitry Andric return [=] {
1482c9157d92SDimitry Andric Symbol *s = symtab.find(name);
1483c9157d92SDimitry Andric return s && s->isDefined() && ctx.scriptSymOrder.lookup(s) < order ? 1
1484c9157d92SDimitry Andric : 0;
1485e8d8bef9SDimitry Andric };
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric if (tok == "LENGTH") {
14880b57cec5SDimitry Andric StringRef name = readParenLiteral();
14890b57cec5SDimitry Andric if (script->memoryRegions.count(name) == 0) {
14900b57cec5SDimitry Andric setError("memory region not defined: " + name);
14910b57cec5SDimitry Andric return [] { return 0; };
14920b57cec5SDimitry Andric }
14935ffd83dbSDimitry Andric return script->memoryRegions[name]->length;
14940b57cec5SDimitry Andric }
14950b57cec5SDimitry Andric if (tok == "LOADADDR") {
1496fe013be4SDimitry Andric StringRef name = unquote(readParenLiteral());
149781ad6265SDimitry Andric OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
149881ad6265SDimitry Andric osec->usedInExpression = true;
14990b57cec5SDimitry Andric return [=] {
150081ad6265SDimitry Andric checkIfExists(*osec, location);
150181ad6265SDimitry Andric return osec->getLMA();
15020b57cec5SDimitry Andric };
15030b57cec5SDimitry Andric }
1504e8d8bef9SDimitry Andric if (tok == "LOG2CEIL") {
1505e8d8bef9SDimitry Andric expect("(");
1506e8d8bef9SDimitry Andric Expr a = readExpr();
1507e8d8bef9SDimitry Andric expect(")");
1508e8d8bef9SDimitry Andric return [=] {
1509e8d8bef9SDimitry Andric // LOG2CEIL(0) is defined to be 0.
1510e8d8bef9SDimitry Andric return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1)));
1511e8d8bef9SDimitry Andric };
1512e8d8bef9SDimitry Andric }
15130b57cec5SDimitry Andric if (tok == "MAX" || tok == "MIN") {
15140b57cec5SDimitry Andric expect("(");
15150b57cec5SDimitry Andric Expr a = readExpr();
15160b57cec5SDimitry Andric expect(",");
15170b57cec5SDimitry Andric Expr b = readExpr();
15180b57cec5SDimitry Andric expect(")");
15190b57cec5SDimitry Andric if (tok == "MIN")
15200b57cec5SDimitry Andric return [=] { return std::min(a().getValue(), b().getValue()); };
15210b57cec5SDimitry Andric return [=] { return std::max(a().getValue(), b().getValue()); };
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric if (tok == "ORIGIN") {
15240b57cec5SDimitry Andric StringRef name = readParenLiteral();
15250b57cec5SDimitry Andric if (script->memoryRegions.count(name) == 0) {
15260b57cec5SDimitry Andric setError("memory region not defined: " + name);
15270b57cec5SDimitry Andric return [] { return 0; };
15280b57cec5SDimitry Andric }
15295ffd83dbSDimitry Andric return script->memoryRegions[name]->origin;
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric if (tok == "SEGMENT_START") {
15320b57cec5SDimitry Andric expect("(");
15330b57cec5SDimitry Andric skip();
15340b57cec5SDimitry Andric expect(",");
15350b57cec5SDimitry Andric Expr e = readExpr();
15360b57cec5SDimitry Andric expect(")");
15370b57cec5SDimitry Andric return [=] { return e(); };
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric if (tok == "SIZEOF") {
1540fe013be4SDimitry Andric StringRef name = unquote(readParenLiteral());
154181ad6265SDimitry Andric OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
15420b57cec5SDimitry Andric // Linker script does not create an output section if its content is empty.
15430b57cec5SDimitry Andric // We want to allow SIZEOF(.foo) where .foo is a section which happened to
15440b57cec5SDimitry Andric // be empty.
15450b57cec5SDimitry Andric return [=] { return cmd->size; };
15460b57cec5SDimitry Andric }
15470b57cec5SDimitry Andric if (tok == "SIZEOF_HEADERS")
15485ffd83dbSDimitry Andric return [=] { return elf::getHeaderSize(); };
15490b57cec5SDimitry Andric
15500b57cec5SDimitry Andric // Tok is the dot.
15510b57cec5SDimitry Andric if (tok == ".")
15520b57cec5SDimitry Andric return [=] { return script->getSymbolValue(tok, location); };
15530b57cec5SDimitry Andric
15540b57cec5SDimitry Andric // Tok is a literal number.
1555bdd1243dSDimitry Andric if (std::optional<uint64_t> val = parseInt(tok))
15560b57cec5SDimitry Andric return [=] { return *val; };
15570b57cec5SDimitry Andric
15580b57cec5SDimitry Andric // Tok is a symbol name.
1559fe013be4SDimitry Andric if (tok.starts_with("\""))
1560fe6060f1SDimitry Andric tok = unquote(tok);
1561349cc55cSDimitry Andric else if (!isValidSymbolName(tok))
15620b57cec5SDimitry Andric setError("malformed number: " + tok);
15630b57cec5SDimitry Andric script->referencedSymbols.push_back(tok);
15640b57cec5SDimitry Andric return [=] { return script->getSymbolValue(tok, location); };
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric
readTernary(Expr cond)15670b57cec5SDimitry Andric Expr ScriptParser::readTernary(Expr cond) {
15680b57cec5SDimitry Andric Expr l = readExpr();
15690b57cec5SDimitry Andric expect(":");
15700b57cec5SDimitry Andric Expr r = readExpr();
15710b57cec5SDimitry Andric return [=] { return cond().getValue() ? l() : r(); };
15720b57cec5SDimitry Andric }
15730b57cec5SDimitry Andric
readParenExpr()15740b57cec5SDimitry Andric Expr ScriptParser::readParenExpr() {
15750b57cec5SDimitry Andric expect("(");
15760b57cec5SDimitry Andric Expr e = readExpr();
15770b57cec5SDimitry Andric expect(")");
15780b57cec5SDimitry Andric return e;
15790b57cec5SDimitry Andric }
15800b57cec5SDimitry Andric
readOutputSectionPhdrs()158104eeddc0SDimitry Andric SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
158204eeddc0SDimitry Andric SmallVector<StringRef, 0> phdrs;
1583fe013be4SDimitry Andric while (!errorCount() && peek().starts_with(":")) {
15840b57cec5SDimitry Andric StringRef tok = next();
15850b57cec5SDimitry Andric phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));
15860b57cec5SDimitry Andric }
15870b57cec5SDimitry Andric return phdrs;
15880b57cec5SDimitry Andric }
15890b57cec5SDimitry Andric
15900b57cec5SDimitry Andric // Read a program header type name. The next token must be a
15910b57cec5SDimitry Andric // name of a program header type or a constant (e.g. "0x3").
readPhdrType()15920b57cec5SDimitry Andric unsigned ScriptParser::readPhdrType() {
15930b57cec5SDimitry Andric StringRef tok = next();
1594bdd1243dSDimitry Andric if (std::optional<uint64_t> val = parseInt(tok))
15950b57cec5SDimitry Andric return *val;
15960b57cec5SDimitry Andric
15970b57cec5SDimitry Andric unsigned ret = StringSwitch<unsigned>(tok)
15980b57cec5SDimitry Andric .Case("PT_NULL", PT_NULL)
15990b57cec5SDimitry Andric .Case("PT_LOAD", PT_LOAD)
16000b57cec5SDimitry Andric .Case("PT_DYNAMIC", PT_DYNAMIC)
16010b57cec5SDimitry Andric .Case("PT_INTERP", PT_INTERP)
16020b57cec5SDimitry Andric .Case("PT_NOTE", PT_NOTE)
16030b57cec5SDimitry Andric .Case("PT_SHLIB", PT_SHLIB)
16040b57cec5SDimitry Andric .Case("PT_PHDR", PT_PHDR)
16050b57cec5SDimitry Andric .Case("PT_TLS", PT_TLS)
16060b57cec5SDimitry Andric .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
16070b57cec5SDimitry Andric .Case("PT_GNU_STACK", PT_GNU_STACK)
16080b57cec5SDimitry Andric .Case("PT_GNU_RELRO", PT_GNU_RELRO)
16090b57cec5SDimitry Andric .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE)
16100b57cec5SDimitry Andric .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED)
16110b57cec5SDimitry Andric .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
16120b57cec5SDimitry Andric .Default(-1);
16130b57cec5SDimitry Andric
16140b57cec5SDimitry Andric if (ret == (unsigned)-1) {
16150b57cec5SDimitry Andric setError("invalid program header type: " + tok);
16160b57cec5SDimitry Andric return PT_NULL;
16170b57cec5SDimitry Andric }
16180b57cec5SDimitry Andric return ret;
16190b57cec5SDimitry Andric }
16200b57cec5SDimitry Andric
16210b57cec5SDimitry Andric // Reads an anonymous version declaration.
readAnonymousDeclaration()16220b57cec5SDimitry Andric void ScriptParser::readAnonymousDeclaration() {
162304eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
162404eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
16250b57cec5SDimitry Andric std::tie(locals, globals) = readSymbols();
162685868e8aSDimitry Andric for (const SymbolVersion &pat : locals)
16276e75b2fbSDimitry Andric config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat);
162885868e8aSDimitry Andric for (const SymbolVersion &pat : globals)
16296e75b2fbSDimitry Andric config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat);
16300b57cec5SDimitry Andric
16310b57cec5SDimitry Andric expect(";");
16320b57cec5SDimitry Andric }
16330b57cec5SDimitry Andric
16340b57cec5SDimitry Andric // Reads a non-anonymous version definition,
16350b57cec5SDimitry Andric // e.g. "VerStr { global: foo; bar; local: *; };".
readVersionDeclaration(StringRef verStr)16360b57cec5SDimitry Andric void ScriptParser::readVersionDeclaration(StringRef verStr) {
16370b57cec5SDimitry Andric // Read a symbol list.
163804eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
163904eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
16400b57cec5SDimitry Andric std::tie(locals, globals) = readSymbols();
16410b57cec5SDimitry Andric
16420b57cec5SDimitry Andric // Create a new version definition and add that to the global symbols.
16430b57cec5SDimitry Andric VersionDefinition ver;
16440b57cec5SDimitry Andric ver.name = verStr;
16456e75b2fbSDimitry Andric ver.nonLocalPatterns = std::move(globals);
16466e75b2fbSDimitry Andric ver.localPatterns = std::move(locals);
164785868e8aSDimitry Andric ver.id = config->versionDefinitions.size();
16480b57cec5SDimitry Andric config->versionDefinitions.push_back(ver);
16490b57cec5SDimitry Andric
16500b57cec5SDimitry Andric // Each version may have a parent version. For example, "Ver2"
16510b57cec5SDimitry Andric // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"
16520b57cec5SDimitry Andric // as a parent. This version hierarchy is, probably against your
16530b57cec5SDimitry Andric // instinct, purely for hint; the runtime doesn't care about it
16540b57cec5SDimitry Andric // at all. In LLD, we simply ignore it.
16555ffd83dbSDimitry Andric if (next() != ";")
16560b57cec5SDimitry Andric expect(";");
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric
hasWildcard(StringRef s)16595ffd83dbSDimitry Andric bool elf::hasWildcard(StringRef s) {
16600b57cec5SDimitry Andric return s.find_first_of("?*[") != StringRef::npos;
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric
16630b57cec5SDimitry Andric // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
166404eeddc0SDimitry Andric std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
readSymbols()16650b57cec5SDimitry Andric ScriptParser::readSymbols() {
166604eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> locals;
166704eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> globals;
166804eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> *v = &globals;
16690b57cec5SDimitry Andric
16700b57cec5SDimitry Andric while (!errorCount()) {
16710b57cec5SDimitry Andric if (consume("}"))
16720b57cec5SDimitry Andric break;
16730b57cec5SDimitry Andric if (consumeLabel("local")) {
16740b57cec5SDimitry Andric v = &locals;
16750b57cec5SDimitry Andric continue;
16760b57cec5SDimitry Andric }
16770b57cec5SDimitry Andric if (consumeLabel("global")) {
16780b57cec5SDimitry Andric v = &globals;
16790b57cec5SDimitry Andric continue;
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric
16820b57cec5SDimitry Andric if (consume("extern")) {
168304eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> ext = readVersionExtern();
16840b57cec5SDimitry Andric v->insert(v->end(), ext.begin(), ext.end());
16850b57cec5SDimitry Andric } else {
16860b57cec5SDimitry Andric StringRef tok = next();
16870b57cec5SDimitry Andric v->push_back({unquote(tok), false, hasWildcard(tok)});
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric expect(";");
16900b57cec5SDimitry Andric }
16910b57cec5SDimitry Andric return {locals, globals};
16920b57cec5SDimitry Andric }
16930b57cec5SDimitry Andric
16940b57cec5SDimitry Andric // Reads an "extern C++" directive, e.g.,
16950b57cec5SDimitry Andric // "extern "C++" { ns::*; "f(int, double)"; };"
16960b57cec5SDimitry Andric //
16970b57cec5SDimitry Andric // The last semicolon is optional. E.g. this is OK:
16980b57cec5SDimitry Andric // "extern "C++" { ns::*; "f(int, double)" };"
readVersionExtern()169904eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
17000b57cec5SDimitry Andric StringRef tok = next();
17010b57cec5SDimitry Andric bool isCXX = tok == "\"C++\"";
17020b57cec5SDimitry Andric if (!isCXX && tok != "\"C\"")
17030b57cec5SDimitry Andric setError("Unknown language");
17040b57cec5SDimitry Andric expect("{");
17050b57cec5SDimitry Andric
170604eeddc0SDimitry Andric SmallVector<SymbolVersion, 0> ret;
17070b57cec5SDimitry Andric while (!errorCount() && peek() != "}") {
17080b57cec5SDimitry Andric StringRef tok = next();
17090b57cec5SDimitry Andric ret.push_back(
1710fe013be4SDimitry Andric {unquote(tok), isCXX, !tok.starts_with("\"") && hasWildcard(tok)});
17110b57cec5SDimitry Andric if (consume("}"))
17120b57cec5SDimitry Andric return ret;
17130b57cec5SDimitry Andric expect(";");
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric
17160b57cec5SDimitry Andric expect("}");
17170b57cec5SDimitry Andric return ret;
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric
readMemoryAssignment(StringRef s1,StringRef s2,StringRef s3)17205ffd83dbSDimitry Andric Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
17210b57cec5SDimitry Andric StringRef s3) {
17220b57cec5SDimitry Andric if (!consume(s1) && !consume(s2) && !consume(s3)) {
17230b57cec5SDimitry Andric setError("expected one of: " + s1 + ", " + s2 + ", or " + s3);
17245ffd83dbSDimitry Andric return [] { return 0; };
17250b57cec5SDimitry Andric }
17260b57cec5SDimitry Andric expect("=");
17275ffd83dbSDimitry Andric return readExpr();
17280b57cec5SDimitry Andric }
17290b57cec5SDimitry Andric
17300b57cec5SDimitry Andric // Parse the MEMORY command as specified in:
17310b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/ld/MEMORY.html
17320b57cec5SDimitry Andric //
17330b57cec5SDimitry Andric // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
readMemory()17340b57cec5SDimitry Andric void ScriptParser::readMemory() {
17350b57cec5SDimitry Andric expect("{");
17360b57cec5SDimitry Andric while (!errorCount() && !consume("}")) {
17370b57cec5SDimitry Andric StringRef tok = next();
17380b57cec5SDimitry Andric if (tok == "INCLUDE") {
17390b57cec5SDimitry Andric readInclude();
17400b57cec5SDimitry Andric continue;
17410b57cec5SDimitry Andric }
17420b57cec5SDimitry Andric
17430b57cec5SDimitry Andric uint32_t flags = 0;
17444824e7fdSDimitry Andric uint32_t invFlags = 0;
17450b57cec5SDimitry Andric uint32_t negFlags = 0;
17464824e7fdSDimitry Andric uint32_t negInvFlags = 0;
17470b57cec5SDimitry Andric if (consume("(")) {
17484824e7fdSDimitry Andric readMemoryAttributes(flags, invFlags, negFlags, negInvFlags);
17490b57cec5SDimitry Andric expect(")");
17500b57cec5SDimitry Andric }
17510b57cec5SDimitry Andric expect(":");
17520b57cec5SDimitry Andric
17535ffd83dbSDimitry Andric Expr origin = readMemoryAssignment("ORIGIN", "org", "o");
17540b57cec5SDimitry Andric expect(",");
17555ffd83dbSDimitry Andric Expr length = readMemoryAssignment("LENGTH", "len", "l");
17560b57cec5SDimitry Andric
17570b57cec5SDimitry Andric // Add the memory region to the region map.
17584824e7fdSDimitry Andric MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags,
17594824e7fdSDimitry Andric negFlags, negInvFlags);
17600b57cec5SDimitry Andric if (!script->memoryRegions.insert({tok, mr}).second)
17610b57cec5SDimitry Andric setError("region '" + tok + "' already defined");
17620b57cec5SDimitry Andric }
17630b57cec5SDimitry Andric }
17640b57cec5SDimitry Andric
17650b57cec5SDimitry Andric // This function parses the attributes used to match against section
17660b57cec5SDimitry Andric // flags when placing output sections in a memory region. These flags
17670b57cec5SDimitry 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)17684824e7fdSDimitry Andric void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
17694824e7fdSDimitry Andric uint32_t &negFlags,
17704824e7fdSDimitry Andric uint32_t &negInvFlags) {
17710b57cec5SDimitry Andric bool invert = false;
17720b57cec5SDimitry Andric
17730b57cec5SDimitry Andric for (char c : next().lower()) {
17744824e7fdSDimitry Andric if (c == '!') {
17750b57cec5SDimitry Andric invert = !invert;
17764824e7fdSDimitry Andric std::swap(flags, negFlags);
17774824e7fdSDimitry Andric std::swap(invFlags, negInvFlags);
17784824e7fdSDimitry Andric continue;
17790b57cec5SDimitry Andric }
17804824e7fdSDimitry Andric if (c == 'w')
17814824e7fdSDimitry Andric flags |= SHF_WRITE;
17824824e7fdSDimitry Andric else if (c == 'x')
17834824e7fdSDimitry Andric flags |= SHF_EXECINSTR;
17844824e7fdSDimitry Andric else if (c == 'a')
17854824e7fdSDimitry Andric flags |= SHF_ALLOC;
17864824e7fdSDimitry Andric else if (c == 'r')
17874824e7fdSDimitry Andric invFlags |= SHF_WRITE;
17884824e7fdSDimitry Andric else
17894824e7fdSDimitry Andric setError("invalid memory region attribute");
17904824e7fdSDimitry Andric }
17914824e7fdSDimitry Andric
17924824e7fdSDimitry Andric if (invert) {
17934824e7fdSDimitry Andric std::swap(flags, negFlags);
17944824e7fdSDimitry Andric std::swap(invFlags, negInvFlags);
17954824e7fdSDimitry Andric }
17960b57cec5SDimitry Andric }
17970b57cec5SDimitry Andric
readLinkerScript(MemoryBufferRef mb)17985ffd83dbSDimitry Andric void elf::readLinkerScript(MemoryBufferRef mb) {
1799e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read linker script",
1800e8d8bef9SDimitry Andric mb.getBufferIdentifier());
18010b57cec5SDimitry Andric ScriptParser(mb).readLinkerScript();
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric
readVersionScript(MemoryBufferRef mb)18045ffd83dbSDimitry Andric void elf::readVersionScript(MemoryBufferRef mb) {
1805e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read version script",
1806e8d8bef9SDimitry Andric mb.getBufferIdentifier());
18070b57cec5SDimitry Andric ScriptParser(mb).readVersionScript();
18080b57cec5SDimitry Andric }
18090b57cec5SDimitry Andric
readDynamicList(MemoryBufferRef mb)18105ffd83dbSDimitry Andric void elf::readDynamicList(MemoryBufferRef mb) {
1811e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read dynamic list", mb.getBufferIdentifier());
18125ffd83dbSDimitry Andric ScriptParser(mb).readDynamicList();
18130b57cec5SDimitry Andric }
181485868e8aSDimitry Andric
readDefsym(StringRef name,MemoryBufferRef mb)18155ffd83dbSDimitry Andric void elf::readDefsym(StringRef name, MemoryBufferRef mb) {
1816e8d8bef9SDimitry Andric llvm::TimeTraceScope timeScope("Read defsym input", name);
18175ffd83dbSDimitry Andric ScriptParser(mb).readDefsym(name);
18185ffd83dbSDimitry Andric }
1819