12ec34544SRui Ueyama //===- ScriptParser.cpp ---------------------------------------------------===//
22ec34544SRui Ueyama //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62ec34544SRui Ueyama //
72ec34544SRui Ueyama //===----------------------------------------------------------------------===//
805f6b852SRui Ueyama //
905f6b852SRui Ueyama // This file contains a recursive-descendent parser for linker scripts.
1005f6b852SRui Ueyama // Parsed results are stored to Config and Script global objects.
1105f6b852SRui Ueyama //
1205f6b852SRui Ueyama //===----------------------------------------------------------------------===//
132ec34544SRui Ueyama 
142ec34544SRui Ueyama #include "ScriptParser.h"
152ec34544SRui Ueyama #include "Config.h"
162ec34544SRui Ueyama #include "Driver.h"
172ec34544SRui Ueyama #include "InputSection.h"
182ec34544SRui Ueyama #include "LinkerScript.h"
192ec34544SRui Ueyama #include "OutputSections.h"
202ec34544SRui Ueyama #include "ScriptLexer.h"
212ec34544SRui Ueyama #include "Symbols.h"
222ec34544SRui Ueyama #include "Target.h"
232017d52bSRui Ueyama #include "lld/Common/Memory.h"
242ec34544SRui Ueyama #include "llvm/ADT/SmallString.h"
252ec34544SRui Ueyama #include "llvm/ADT/StringRef.h"
260440be4aSRui Ueyama #include "llvm/ADT/StringSet.h"
272ec34544SRui Ueyama #include "llvm/ADT/StringSwitch.h"
28264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h"
292ec34544SRui Ueyama #include "llvm/Support/Casting.h"
302ec34544SRui Ueyama #include "llvm/Support/ErrorHandling.h"
312ec34544SRui Ueyama #include "llvm/Support/FileSystem.h"
322ec34544SRui Ueyama #include "llvm/Support/Path.h"
332ec34544SRui Ueyama #include <cassert>
342ec34544SRui Ueyama #include <limits>
352ec34544SRui Ueyama #include <vector>
362ec34544SRui Ueyama 
372ec34544SRui Ueyama using namespace llvm;
382ec34544SRui Ueyama using namespace llvm::ELF;
39b58079d4SRui Ueyama using namespace llvm::support::endian;
402ec34544SRui Ueyama using namespace lld;
412ec34544SRui Ueyama using namespace lld::elf;
422ec34544SRui Ueyama 
4396b3fe02SRui Ueyama namespace {
4496b3fe02SRui Ueyama class ScriptParser final : ScriptLexer {
452ec34544SRui Ueyama public:
463837f427SRui Ueyama   ScriptParser(MemoryBufferRef mb) : ScriptLexer(mb) {
4711ae59f0SRui Ueyama     // Initialize IsUnderSysroot
483837f427SRui Ueyama     if (config->sysroot == "")
4911ae59f0SRui Ueyama       return;
503837f427SRui Ueyama     StringRef path = mb.getBufferIdentifier();
513837f427SRui Ueyama     for (; !path.empty(); path = sys::path::parent_path(path)) {
523837f427SRui Ueyama       if (!sys::fs::equivalent(config->sysroot, path))
5311ae59f0SRui Ueyama         continue;
543837f427SRui Ueyama       isUnderSysroot = true;
5511ae59f0SRui Ueyama       return;
5611ae59f0SRui Ueyama     }
5711ae59f0SRui Ueyama   }
582ec34544SRui Ueyama 
592ec34544SRui Ueyama   void readLinkerScript();
602ec34544SRui Ueyama   void readVersionScript();
612ec34544SRui Ueyama   void readDynamicList();
623837f427SRui Ueyama   void readDefsym(StringRef name);
632ec34544SRui Ueyama 
642ec34544SRui Ueyama private:
653837f427SRui Ueyama   void addFile(StringRef path);
662ec34544SRui Ueyama 
672ec34544SRui Ueyama   void readAsNeeded();
682ec34544SRui Ueyama   void readEntry();
692ec34544SRui Ueyama   void readExtern();
702ec34544SRui Ueyama   void readGroup();
712ec34544SRui Ueyama   void readInclude();
721d92aa73SRui Ueyama   void readInput();
732ec34544SRui Ueyama   void readMemory();
742ec34544SRui Ueyama   void readOutput();
752ec34544SRui Ueyama   void readOutputArch();
762ec34544SRui Ueyama   void readOutputFormat();
772ec34544SRui Ueyama   void readPhdrs();
785f37541cSGeorge Rimar   void readRegionAlias();
792ec34544SRui Ueyama   void readSearchDir();
802ec34544SRui Ueyama   void readSections();
81e262bb1aSRui Ueyama   void readTarget();
822ec34544SRui Ueyama   void readVersion();
832ec34544SRui Ueyama   void readVersionScriptCommand();
842ec34544SRui Ueyama 
853837f427SRui Ueyama   SymbolAssignment *readSymbolAssignment(StringRef name);
863837f427SRui Ueyama   ByteCommand *readByteCommand(StringRef tok);
87b0486051SSimon Atanasyan   std::array<uint8_t, 4> readFill();
883837f427SRui Ueyama   bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
893837f427SRui Ueyama   void readSectionAddressType(OutputSection *cmd);
90a582419aSGeorge Rimar   OutputSection *readOverlaySectionDescription();
913837f427SRui Ueyama   OutputSection *readOutputSectionDescription(StringRef outSec);
92a582419aSGeorge Rimar   std::vector<BaseCommand *> readOverlay();
932ec34544SRui Ueyama   std::vector<StringRef> readOutputSectionPhdrs();
943837f427SRui Ueyama   InputSectionDescription *readInputSectionDescription(StringRef tok);
952ec34544SRui Ueyama   StringMatcher readFilePatterns();
962ec34544SRui Ueyama   std::vector<SectionPattern> readInputSectionsList();
973837f427SRui Ueyama   InputSectionDescription *readInputSectionRules(StringRef filePattern);
982ec34544SRui Ueyama   unsigned readPhdrType();
992ec34544SRui Ueyama   SortSectionPolicy readSortKind();
1003837f427SRui Ueyama   SymbolAssignment *readProvideHidden(bool provide, bool hidden);
1013837f427SRui Ueyama   SymbolAssignment *readAssignment(StringRef tok);
1022ec34544SRui Ueyama   void readSort();
103d30a78b3SGeorge Rimar   Expr readAssert();
1045fb17128SGeorge Rimar   Expr readConstant();
1055fb17128SGeorge Rimar   Expr getPageSize();
1062ec34544SRui Ueyama 
1072ec34544SRui Ueyama   uint64_t readMemoryAssignment(StringRef, StringRef, StringRef);
1082ec34544SRui Ueyama   std::pair<uint32_t, uint32_t> readMemoryAttributes();
1092ec34544SRui Ueyama 
1103837f427SRui Ueyama   Expr combine(StringRef op, Expr l, Expr r);
1112ec34544SRui Ueyama   Expr readExpr();
1123837f427SRui Ueyama   Expr readExpr1(Expr lhs, int minPrec);
1132ec34544SRui Ueyama   StringRef readParenLiteral();
1142ec34544SRui Ueyama   Expr readPrimary();
1153837f427SRui Ueyama   Expr readTernary(Expr cond);
1162ec34544SRui Ueyama   Expr readParenExpr();
1172ec34544SRui Ueyama 
1182ec34544SRui Ueyama   // For parsing version script.
1192ec34544SRui Ueyama   std::vector<SymbolVersion> readVersionExtern();
1202ec34544SRui Ueyama   void readAnonymousDeclaration();
1213837f427SRui Ueyama   void readVersionDeclaration(StringRef verStr);
1222ec34544SRui Ueyama 
1232ec34544SRui Ueyama   std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
1242ec34544SRui Ueyama   readSymbols();
1252ec34544SRui Ueyama 
126fd06b025SRui Ueyama   // True if a script being read is in a subdirectory specified by -sysroot.
1273837f427SRui Ueyama   bool isUnderSysroot = false;
1280440be4aSRui Ueyama 
1290440be4aSRui Ueyama   // A set to detect an INCLUDE() cycle.
1303837f427SRui Ueyama   StringSet<> seen;
1312ec34544SRui Ueyama };
13296b3fe02SRui Ueyama } // namespace
1332ec34544SRui Ueyama 
1343837f427SRui Ueyama static StringRef unquote(StringRef s) {
1353837f427SRui Ueyama   if (s.startswith("\""))
1363837f427SRui Ueyama     return s.substr(1, s.size() - 2);
1373837f427SRui Ueyama   return s;
1381e77ad14SRui Ueyama }
1391e77ad14SRui Ueyama 
1402ec34544SRui Ueyama // Some operations only support one non absolute value. Move the
1412ec34544SRui Ueyama // absolute one to the right hand side for convenience.
1423837f427SRui Ueyama static void moveAbsRight(ExprValue &a, ExprValue &b) {
1433837f427SRui Ueyama   if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
1443837f427SRui Ueyama     std::swap(a, b);
1453837f427SRui Ueyama   if (!b.isAbsolute())
1463837f427SRui Ueyama     error(a.loc + ": at least one side of the expression must be absolute");
1472ec34544SRui Ueyama }
1482ec34544SRui Ueyama 
1493837f427SRui Ueyama static ExprValue add(ExprValue a, ExprValue b) {
1503837f427SRui Ueyama   moveAbsRight(a, b);
1513837f427SRui Ueyama   return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
1522ec34544SRui Ueyama }
1532ec34544SRui Ueyama 
1543837f427SRui Ueyama static ExprValue sub(ExprValue a, ExprValue b) {
15563a4a98eSRafael Espindola   // The distance between two symbols in sections is absolute.
1563837f427SRui Ueyama   if (!a.isAbsolute() && !b.isAbsolute())
1573837f427SRui Ueyama     return a.getValue() - b.getValue();
1583837f427SRui Ueyama   return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
1592ec34544SRui Ueyama }
1602ec34544SRui Ueyama 
1613837f427SRui Ueyama static ExprValue bitAnd(ExprValue a, ExprValue b) {
1623837f427SRui Ueyama   moveAbsRight(a, b);
1633837f427SRui Ueyama   return {a.sec, a.forceAbsolute,
1643837f427SRui Ueyama           (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
1652ec34544SRui Ueyama }
1662ec34544SRui Ueyama 
1673837f427SRui Ueyama static ExprValue bitOr(ExprValue a, ExprValue b) {
1683837f427SRui Ueyama   moveAbsRight(a, b);
1693837f427SRui Ueyama   return {a.sec, a.forceAbsolute,
1703837f427SRui Ueyama           (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
1712ec34544SRui Ueyama }
1722ec34544SRui Ueyama 
1732ec34544SRui Ueyama void ScriptParser::readDynamicList() {
1743837f427SRui Ueyama   config->hasDynamicList = true;
1752ec34544SRui Ueyama   expect("{");
1763837f427SRui Ueyama   std::vector<SymbolVersion> locals;
1773837f427SRui Ueyama   std::vector<SymbolVersion> globals;
1783837f427SRui Ueyama   std::tie(locals, globals) = readSymbols();
179d72d97b3SRafael Espindola   expect(";");
180d72d97b3SRafael Espindola 
181d72d97b3SRafael Espindola   if (!atEOF()) {
1822ec34544SRui Ueyama     setError("EOF expected, but got " + next());
183d72d97b3SRafael Espindola     return;
184d72d97b3SRafael Espindola   }
1853837f427SRui Ueyama   if (!locals.empty()) {
186d72d97b3SRafael Espindola     setError("\"local:\" scope not supported in --dynamic-list");
187d72d97b3SRafael Espindola     return;
188d72d97b3SRafael Espindola   }
189d72d97b3SRafael Espindola 
1903837f427SRui Ueyama   for (SymbolVersion v : globals)
1913837f427SRui Ueyama     config->dynamicList.push_back(v);
1922ec34544SRui Ueyama }
1932ec34544SRui Ueyama 
1942ec34544SRui Ueyama void ScriptParser::readVersionScript() {
1952ec34544SRui Ueyama   readVersionScriptCommand();
1962ec34544SRui Ueyama   if (!atEOF())
1972ec34544SRui Ueyama     setError("EOF expected, but got " + next());
1982ec34544SRui Ueyama }
1992ec34544SRui Ueyama 
2002ec34544SRui Ueyama void ScriptParser::readVersionScriptCommand() {
2012ec34544SRui Ueyama   if (consume("{")) {
2022ec34544SRui Ueyama     readAnonymousDeclaration();
2032ec34544SRui Ueyama     return;
2042ec34544SRui Ueyama   }
2052ec34544SRui Ueyama 
206b8a59c8aSBob Haarman   while (!atEOF() && !errorCount() && peek() != "}") {
2073837f427SRui Ueyama     StringRef verStr = next();
2083837f427SRui Ueyama     if (verStr == "{") {
2092ec34544SRui Ueyama       setError("anonymous version definition is used in "
2102ec34544SRui Ueyama                "combination with other version definitions");
2112ec34544SRui Ueyama       return;
2122ec34544SRui Ueyama     }
2132ec34544SRui Ueyama     expect("{");
2143837f427SRui Ueyama     readVersionDeclaration(verStr);
2152ec34544SRui Ueyama   }
2162ec34544SRui Ueyama }
2172ec34544SRui Ueyama 
2182ec34544SRui Ueyama void ScriptParser::readVersion() {
2192ec34544SRui Ueyama   expect("{");
2202ec34544SRui Ueyama   readVersionScriptCommand();
2212ec34544SRui Ueyama   expect("}");
2222ec34544SRui Ueyama }
2232ec34544SRui Ueyama 
2242ec34544SRui Ueyama void ScriptParser::readLinkerScript() {
2252ec34544SRui Ueyama   while (!atEOF()) {
2263837f427SRui Ueyama     StringRef tok = next();
2273837f427SRui Ueyama     if (tok == ";")
2282ec34544SRui Ueyama       continue;
2292ec34544SRui Ueyama 
2303837f427SRui Ueyama     if (tok == "ENTRY") {
2312ec34544SRui Ueyama       readEntry();
2323837f427SRui Ueyama     } else if (tok == "EXTERN") {
2332ec34544SRui Ueyama       readExtern();
2343837f427SRui Ueyama     } else if (tok == "GROUP") {
2352ec34544SRui Ueyama       readGroup();
2363837f427SRui Ueyama     } else if (tok == "INCLUDE") {
2372ec34544SRui Ueyama       readInclude();
2383837f427SRui Ueyama     } else if (tok == "INPUT") {
2391d92aa73SRui Ueyama       readInput();
2403837f427SRui Ueyama     } else if (tok == "MEMORY") {
2412ec34544SRui Ueyama       readMemory();
2423837f427SRui Ueyama     } else if (tok == "OUTPUT") {
2432ec34544SRui Ueyama       readOutput();
2443837f427SRui Ueyama     } else if (tok == "OUTPUT_ARCH") {
2452ec34544SRui Ueyama       readOutputArch();
2463837f427SRui Ueyama     } else if (tok == "OUTPUT_FORMAT") {
2472ec34544SRui Ueyama       readOutputFormat();
2483837f427SRui Ueyama     } else if (tok == "PHDRS") {
2492ec34544SRui Ueyama       readPhdrs();
2503837f427SRui Ueyama     } else if (tok == "REGION_ALIAS") {
2515f37541cSGeorge Rimar       readRegionAlias();
2523837f427SRui Ueyama     } else if (tok == "SEARCH_DIR") {
2532ec34544SRui Ueyama       readSearchDir();
2543837f427SRui Ueyama     } else if (tok == "SECTIONS") {
2552ec34544SRui Ueyama       readSections();
2563837f427SRui Ueyama     } else if (tok == "TARGET") {
257e262bb1aSRui Ueyama       readTarget();
2583837f427SRui Ueyama     } else if (tok == "VERSION") {
2592ec34544SRui Ueyama       readVersion();
2603837f427SRui Ueyama     } else if (SymbolAssignment *cmd = readAssignment(tok)) {
2613837f427SRui Ueyama       script->sectionCommands.push_back(cmd);
2622ec34544SRui Ueyama     } else {
2633837f427SRui Ueyama       setError("unknown directive: " + tok);
2642ec34544SRui Ueyama     }
2652ec34544SRui Ueyama   }
2662ec34544SRui Ueyama }
2672ec34544SRui Ueyama 
2683837f427SRui Ueyama void ScriptParser::readDefsym(StringRef name) {
269c1522816SGeorge Rimar   if (errorCount())
270c1522816SGeorge Rimar     return;
2713837f427SRui Ueyama   Expr e = readExpr();
2728c7e8cceSPetr Hosek   if (!atEOF())
2738c7e8cceSPetr Hosek     setError("EOF expected, but got " + next());
2743837f427SRui Ueyama   SymbolAssignment *cmd = make<SymbolAssignment>(name, e, getCurrentLocation());
2753837f427SRui Ueyama   script->sectionCommands.push_back(cmd);
2768c7e8cceSPetr Hosek }
2778c7e8cceSPetr Hosek 
2783837f427SRui Ueyama void ScriptParser::addFile(StringRef s) {
2793837f427SRui Ueyama   if (isUnderSysroot && s.startswith("/")) {
2803837f427SRui Ueyama     SmallString<128> pathData;
2813837f427SRui Ueyama     StringRef path = (config->sysroot + s).toStringRef(pathData);
2823837f427SRui Ueyama     if (sys::fs::exists(path)) {
283*136d27abSRui Ueyama       driver->addFile(saver.save(path), /*WithLOption=*/false);
2842ec34544SRui Ueyama       return;
2852ec34544SRui Ueyama     }
2862ec34544SRui Ueyama   }
2872ec34544SRui Ueyama 
2883837f427SRui Ueyama   if (s.startswith("/")) {
2893837f427SRui Ueyama     driver->addFile(s, /*WithLOption=*/false);
2903837f427SRui Ueyama   } else if (s.startswith("=")) {
2913837f427SRui Ueyama     if (config->sysroot.empty())
2923837f427SRui Ueyama       driver->addFile(s.substr(1), /*WithLOption=*/false);
2932ec34544SRui Ueyama     else
294*136d27abSRui Ueyama       driver->addFile(saver.save(config->sysroot + "/" + s.substr(1)),
295a76349bfSEvgeniy Stepanov                       /*WithLOption=*/false);
2963837f427SRui Ueyama   } else if (s.startswith("-l")) {
2973837f427SRui Ueyama     driver->addLibrary(s.substr(2));
2983837f427SRui Ueyama   } else if (sys::fs::exists(s)) {
2993837f427SRui Ueyama     driver->addFile(s, /*WithLOption=*/false);
3002ec34544SRui Ueyama   } else {
3013837f427SRui Ueyama     if (Optional<std::string> path = findFromSearchPaths(s))
302*136d27abSRui Ueyama       driver->addFile(saver.save(*path), /*WithLOption=*/true);
3032ec34544SRui Ueyama     else
3043837f427SRui Ueyama       setError("unable to find " + s);
3052ec34544SRui Ueyama   }
3062ec34544SRui Ueyama }
3072ec34544SRui Ueyama 
3082ec34544SRui Ueyama void ScriptParser::readAsNeeded() {
3092ec34544SRui Ueyama   expect("(");
3103837f427SRui Ueyama   bool orig = config->asNeeded;
3113837f427SRui Ueyama   config->asNeeded = true;
312b8a59c8aSBob Haarman   while (!errorCount() && !consume(")"))
3132ec34544SRui Ueyama     addFile(unquote(next()));
3143837f427SRui Ueyama   config->asNeeded = orig;
3152ec34544SRui Ueyama }
3162ec34544SRui Ueyama 
3172ec34544SRui Ueyama void ScriptParser::readEntry() {
3182ec34544SRui Ueyama   // -e <symbol> takes predecence over ENTRY(<symbol>).
3192ec34544SRui Ueyama   expect("(");
3203837f427SRui Ueyama   StringRef tok = next();
3213837f427SRui Ueyama   if (config->entry.empty())
3223837f427SRui Ueyama     config->entry = tok;
3232ec34544SRui Ueyama   expect(")");
3242ec34544SRui Ueyama }
3252ec34544SRui Ueyama 
3262ec34544SRui Ueyama void ScriptParser::readExtern() {
3272ec34544SRui Ueyama   expect("(");
328b8a59c8aSBob Haarman   while (!errorCount() && !consume(")"))
3293837f427SRui Ueyama     config->undefined.push_back(unquote(next()));
3302ec34544SRui Ueyama }
3312ec34544SRui Ueyama 
3322ec34544SRui Ueyama void ScriptParser::readGroup() {
3333837f427SRui Ueyama   bool orig = InputFile::isInGroup;
3343837f427SRui Ueyama   InputFile::isInGroup = true;
3351d92aa73SRui Ueyama   readInput();
3363837f427SRui Ueyama   InputFile::isInGroup = orig;
3373837f427SRui Ueyama   if (!orig)
3383837f427SRui Ueyama     ++InputFile::nextGroupId;
3392ec34544SRui Ueyama }
3402ec34544SRui Ueyama 
3412ec34544SRui Ueyama void ScriptParser::readInclude() {
3423837f427SRui Ueyama   StringRef tok = unquote(next());
3432ec34544SRui Ueyama 
3443837f427SRui Ueyama   if (!seen.insert(tok).second) {
3450440be4aSRui Ueyama     setError("there is a cycle in linker script INCLUDEs");
3460440be4aSRui Ueyama     return;
3470440be4aSRui Ueyama   }
3480440be4aSRui Ueyama 
3493837f427SRui Ueyama   if (Optional<std::string> path = searchScript(tok)) {
3503837f427SRui Ueyama     if (Optional<MemoryBufferRef> mb = readFile(*path))
3513837f427SRui Ueyama       tokenize(*mb);
3522ec34544SRui Ueyama     return;
3532ec34544SRui Ueyama   }
3543837f427SRui Ueyama   setError("cannot find linker script " + tok);
3552ec34544SRui Ueyama }
3562ec34544SRui Ueyama 
3571d92aa73SRui Ueyama void ScriptParser::readInput() {
3581d92aa73SRui Ueyama   expect("(");
3591d92aa73SRui Ueyama   while (!errorCount() && !consume(")")) {
3601d92aa73SRui Ueyama     if (consume("AS_NEEDED"))
3611d92aa73SRui Ueyama       readAsNeeded();
3621d92aa73SRui Ueyama     else
3631d92aa73SRui Ueyama       addFile(unquote(next()));
3641d92aa73SRui Ueyama   }
3651d92aa73SRui Ueyama }
3661d92aa73SRui Ueyama 
3672ec34544SRui Ueyama void ScriptParser::readOutput() {
3682ec34544SRui Ueyama   // -o <file> takes predecence over OUTPUT(<file>).
3692ec34544SRui Ueyama   expect("(");
3703837f427SRui Ueyama   StringRef tok = next();
3713837f427SRui Ueyama   if (config->outputFile.empty())
3723837f427SRui Ueyama     config->outputFile = unquote(tok);
3732ec34544SRui Ueyama   expect(")");
3742ec34544SRui Ueyama }
3752ec34544SRui Ueyama 
3762ec34544SRui Ueyama void ScriptParser::readOutputArch() {
3772ec34544SRui Ueyama   // OUTPUT_ARCH is ignored for now.
3782ec34544SRui Ueyama   expect("(");
379b8a59c8aSBob Haarman   while (!errorCount() && !consume(")"))
3802ec34544SRui Ueyama     skip();
3812ec34544SRui Ueyama }
3822ec34544SRui Ueyama 
3833837f427SRui Ueyama static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
3843837f427SRui Ueyama   return StringSwitch<std::pair<ELFKind, uint16_t>>(s)
3854f8c8228SRui Ueyama       .Case("elf32-i386", {ELF32LEKind, EM_386})
3864f8c8228SRui Ueyama       .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})
3874f8c8228SRui Ueyama       .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})
3884f8c8228SRui Ueyama       .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64})
38919b134ccSDimitry Andric       .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64})
3904f8c8228SRui Ueyama       .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64})
3914134143cSRui Ueyama       .Case("elf32-powerpc", {ELF32BEKind, EM_PPC})
3924f8c8228SRui Ueyama       .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64})
3934f8c8228SRui Ueyama       .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64})
3944f8c8228SRui Ueyama       .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64})
3954134143cSRui Ueyama       .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS})
3964f8c8228SRui Ueyama       .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS})
3974f8c8228SRui Ueyama       .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS})
3984f8c8228SRui Ueyama       .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})
3994f8c8228SRui Ueyama       .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS})
4004f8c8228SRui Ueyama       .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})
40144d908d7SFangrui Song       .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV})
40244d908d7SFangrui Song       .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
4034f8c8228SRui Ueyama       .Default({ELFNoneKind, EM_NONE});
404ea8cd00aSRui Ueyama }
405ea8cd00aSRui Ueyama 
406ea8cd00aSRui Ueyama // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little).
407ea8cd00aSRui Ueyama // Currently we ignore big and little parameters.
4082ec34544SRui Ueyama void ScriptParser::readOutputFormat() {
4092ec34544SRui Ueyama   expect("(");
410ea8cd00aSRui Ueyama 
4113837f427SRui Ueyama   StringRef name = unquote(next());
4123837f427SRui Ueyama   StringRef s = name;
4133837f427SRui Ueyama   if (s.consume_back("-freebsd"))
4143837f427SRui Ueyama     config->osabi = ELFOSABI_FREEBSD;
4154f8c8228SRui Ueyama 
4163837f427SRui Ueyama   std::tie(config->ekind, config->emachine) = parseBfdName(s);
4173837f427SRui Ueyama   if (config->emachine == EM_NONE)
4183837f427SRui Ueyama     setError("unknown output format name: " + name);
4193837f427SRui Ueyama   if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips")
4203837f427SRui Ueyama     config->mipsN32Abi = true;
421ea8cd00aSRui Ueyama 
422b579c439SRui Ueyama   if (consume(")"))
4232ec34544SRui Ueyama     return;
424b579c439SRui Ueyama   expect(",");
4252ec34544SRui Ueyama   skip();
4262ec34544SRui Ueyama   expect(",");
4272ec34544SRui Ueyama   skip();
4282ec34544SRui Ueyama   expect(")");
4292ec34544SRui Ueyama }
4302ec34544SRui Ueyama 
4312ec34544SRui Ueyama void ScriptParser::readPhdrs() {
4322ec34544SRui Ueyama   expect("{");
4332ec34544SRui Ueyama 
434b8a59c8aSBob Haarman   while (!errorCount() && !consume("}")) {
4353837f427SRui Ueyama     PhdrsCommand cmd;
4363837f427SRui Ueyama     cmd.name = next();
4373837f427SRui Ueyama     cmd.type = readPhdrType();
438b579c439SRui Ueyama 
439b8a59c8aSBob Haarman     while (!errorCount() && !consume(";")) {
440b579c439SRui Ueyama       if (consume("FILEHDR"))
4413837f427SRui Ueyama         cmd.hasFilehdr = true;
442b579c439SRui Ueyama       else if (consume("PHDRS"))
4433837f427SRui Ueyama         cmd.hasPhdrs = true;
444b579c439SRui Ueyama       else if (consume("AT"))
4453837f427SRui Ueyama         cmd.lmaExpr = readParenExpr();
446b579c439SRui Ueyama       else if (consume("FLAGS"))
4473837f427SRui Ueyama         cmd.flags = readParenExpr()().getValue();
448b579c439SRui Ueyama       else
449b579c439SRui Ueyama         setError("unexpected header attribute: " + next());
450b579c439SRui Ueyama     }
4510ae2c24cSRui Ueyama 
4523837f427SRui Ueyama     script->phdrsCommands.push_back(cmd);
4532ec34544SRui Ueyama   }
4542ec34544SRui Ueyama }
4552ec34544SRui Ueyama 
4565f37541cSGeorge Rimar void ScriptParser::readRegionAlias() {
4575f37541cSGeorge Rimar   expect("(");
4583837f427SRui Ueyama   StringRef alias = unquote(next());
4595f37541cSGeorge Rimar   expect(",");
4603837f427SRui Ueyama   StringRef name = next();
4615f37541cSGeorge Rimar   expect(")");
4625f37541cSGeorge Rimar 
4633837f427SRui Ueyama   if (script->memoryRegions.count(alias))
4643837f427SRui Ueyama     setError("redefinition of memory region '" + alias + "'");
4653837f427SRui Ueyama   if (!script->memoryRegions.count(name))
4663837f427SRui Ueyama     setError("memory region '" + name + "' is not defined");
4673837f427SRui Ueyama   script->memoryRegions.insert({alias, script->memoryRegions[name]});
4685f37541cSGeorge Rimar }
4695f37541cSGeorge Rimar 
4702ec34544SRui Ueyama void ScriptParser::readSearchDir() {
4712ec34544SRui Ueyama   expect("(");
4723837f427SRui Ueyama   StringRef tok = next();
4733837f427SRui Ueyama   if (!config->nostdlib)
4743837f427SRui Ueyama     config->searchPaths.push_back(unquote(tok));
4752ec34544SRui Ueyama   expect(")");
4762ec34544SRui Ueyama }
4772ec34544SRui Ueyama 
478a582419aSGeorge Rimar // This reads an overlay description. Overlays are used to describe output
479a582419aSGeorge Rimar // sections that use the same virtual memory range and normally would trigger
480a582419aSGeorge Rimar // linker's sections sanity check failures.
481a582419aSGeorge Rimar // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
482a582419aSGeorge Rimar std::vector<BaseCommand *> ScriptParser::readOverlay() {
483a582419aSGeorge Rimar   // VA and LMA expressions are optional, though for simplicity of
484a582419aSGeorge Rimar   // implementation we assume they are not. That is what OVERLAY was designed
485a582419aSGeorge Rimar   // for first of all: to allow sections with overlapping VAs at different LMAs.
4863837f427SRui Ueyama   Expr addrExpr = readExpr();
487a582419aSGeorge Rimar   expect(":");
488a582419aSGeorge Rimar   expect("AT");
4893837f427SRui Ueyama   Expr lmaExpr = readParenExpr();
490a582419aSGeorge Rimar   expect("{");
491a582419aSGeorge Rimar 
4923837f427SRui Ueyama   std::vector<BaseCommand *> v;
4933837f427SRui Ueyama   OutputSection *prev = nullptr;
494a582419aSGeorge Rimar   while (!errorCount() && !consume("}")) {
495a582419aSGeorge Rimar     // VA is the same for all sections. The LMAs are consecutive in memory
496a582419aSGeorge Rimar     // starting from the base load address specified.
4973837f427SRui Ueyama     OutputSection *os = readOverlaySectionDescription();
4983837f427SRui Ueyama     os->addrExpr = addrExpr;
4993837f427SRui Ueyama     if (prev)
5003837f427SRui Ueyama       os->lmaExpr = [=] { return prev->getLMA() + prev->size; };
501a582419aSGeorge Rimar     else
5023837f427SRui Ueyama       os->lmaExpr = lmaExpr;
5033837f427SRui Ueyama     v.push_back(os);
5043837f427SRui Ueyama     prev = os;
505a582419aSGeorge Rimar   }
506a582419aSGeorge Rimar 
507a582419aSGeorge Rimar   // According to the specification, at the end of the overlay, the location
508a582419aSGeorge Rimar   // counter should be equal to the overlay base address plus size of the
509a582419aSGeorge Rimar   // largest section seen in the overlay.
510a582419aSGeorge Rimar   // Here we want to create the Dot assignment command to achieve that.
5113837f427SRui Ueyama   Expr moveDot = [=] {
5123837f427SRui Ueyama     uint64_t max = 0;
5133837f427SRui Ueyama     for (BaseCommand *cmd : v)
5143837f427SRui Ueyama       max = std::max(max, cast<OutputSection>(cmd)->size);
5153837f427SRui Ueyama     return addrExpr().getValue() + max;
516a582419aSGeorge Rimar   };
5173837f427SRui Ueyama   v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation()));
5183837f427SRui Ueyama   return v;
519a582419aSGeorge Rimar }
520a582419aSGeorge Rimar 
5212ec34544SRui Ueyama void ScriptParser::readSections() {
5223837f427SRui Ueyama   script->hasSectionsCommand = true;
523b579c439SRui Ueyama 
5242ec34544SRui Ueyama   // -no-rosegment is used to avoid placing read only non-executable sections in
5252ec34544SRui Ueyama   // their own segment. We do the same if SECTIONS command is present in linker
5262ec34544SRui Ueyama   // script. See comment for computeFlags().
5273837f427SRui Ueyama   config->singleRoRx = true;
5282ec34544SRui Ueyama 
5292ec34544SRui Ueyama   expect("{");
5303837f427SRui Ueyama   std::vector<BaseCommand *> v;
531b8a59c8aSBob Haarman   while (!errorCount() && !consume("}")) {
5323837f427SRui Ueyama     StringRef tok = next();
5333837f427SRui Ueyama     if (tok == "OVERLAY") {
5343837f427SRui Ueyama       for (BaseCommand *cmd : readOverlay())
5353837f427SRui Ueyama         v.push_back(cmd);
536a582419aSGeorge Rimar       continue;
5373837f427SRui Ueyama     } else if (tok == "INCLUDE") {
5382e9d40d5SRui Ueyama       readInclude();
5392e9d40d5SRui Ueyama       continue;
540a582419aSGeorge Rimar     }
541a582419aSGeorge Rimar 
5423837f427SRui Ueyama     if (BaseCommand *cmd = readAssignment(tok))
5433837f427SRui Ueyama       v.push_back(cmd);
544d30a78b3SGeorge Rimar     else
5453837f427SRui Ueyama       v.push_back(readOutputSectionDescription(tok));
5462ec34544SRui Ueyama   }
5479e2c8a9dSGeorge Rimar 
5489e2c8a9dSGeorge Rimar   if (!atEOF() && consume("INSERT")) {
5493837f427SRui Ueyama     std::vector<BaseCommand *> *dest = nullptr;
550796684b4SGeorge Rimar     if (consume("AFTER"))
5513837f427SRui Ueyama       dest = &script->insertAfterCommands[next()];
552796684b4SGeorge Rimar     else if (consume("BEFORE"))
5533837f427SRui Ueyama       dest = &script->insertBeforeCommands[next()];
554796684b4SGeorge Rimar     else
555796684b4SGeorge Rimar       setError("expected AFTER/BEFORE, but got '" + next() + "'");
5563837f427SRui Ueyama     if (dest)
5573837f427SRui Ueyama       dest->insert(dest->end(), v.begin(), v.end());
5589e2c8a9dSGeorge Rimar     return;
5599e2c8a9dSGeorge Rimar   }
5609e2c8a9dSGeorge Rimar 
5613837f427SRui Ueyama   script->sectionCommands.insert(script->sectionCommands.end(), v.begin(),
5623837f427SRui Ueyama                                  v.end());
5632ec34544SRui Ueyama }
5642ec34544SRui Ueyama 
565e262bb1aSRui Ueyama void ScriptParser::readTarget() {
566e262bb1aSRui Ueyama   // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers,
567e262bb1aSRui Ueyama   // we accept only a limited set of BFD names (i.e. "elf" or "binary")
568e262bb1aSRui Ueyama   // for --format. We recognize only /^elf/ and "binary" in the linker
569e262bb1aSRui Ueyama   // script as well.
570e262bb1aSRui Ueyama   expect("(");
5713837f427SRui Ueyama   StringRef tok = next();
572e262bb1aSRui Ueyama   expect(")");
573e262bb1aSRui Ueyama 
5743837f427SRui Ueyama   if (tok.startswith("elf"))
5753837f427SRui Ueyama     config->formatBinary = false;
5763837f427SRui Ueyama   else if (tok == "binary")
5773837f427SRui Ueyama     config->formatBinary = true;
578e262bb1aSRui Ueyama   else
5793837f427SRui Ueyama     setError("unknown target: " + tok);
580e262bb1aSRui Ueyama }
581e262bb1aSRui Ueyama 
5823837f427SRui Ueyama static int precedence(StringRef op) {
5833837f427SRui Ueyama   return StringSwitch<int>(op)
584a5005482SGeorge Rimar       .Cases("*", "/", "%", 8)
585a5005482SGeorge Rimar       .Cases("+", "-", 7)
586a5005482SGeorge Rimar       .Cases("<<", ">>", 6)
587a5005482SGeorge Rimar       .Cases("<", "<=", ">", ">=", "==", "!=", 5)
588a5005482SGeorge Rimar       .Case("&", 4)
589a5005482SGeorge Rimar       .Case("|", 3)
590a5005482SGeorge Rimar       .Case("&&", 2)
591a5005482SGeorge Rimar       .Case("||", 1)
5922ec34544SRui Ueyama       .Default(-1);
5932ec34544SRui Ueyama }
5942ec34544SRui Ueyama 
5952ec34544SRui Ueyama StringMatcher ScriptParser::readFilePatterns() {
5963837f427SRui Ueyama   std::vector<StringRef> v;
597b8a59c8aSBob Haarman   while (!errorCount() && !consume(")"))
5983837f427SRui Ueyama     v.push_back(next());
5993837f427SRui Ueyama   return StringMatcher(v);
6002ec34544SRui Ueyama }
6012ec34544SRui Ueyama 
6022ec34544SRui Ueyama SortSectionPolicy ScriptParser::readSortKind() {
6032ec34544SRui Ueyama   if (consume("SORT") || consume("SORT_BY_NAME"))
6042ec34544SRui Ueyama     return SortSectionPolicy::Name;
6052ec34544SRui Ueyama   if (consume("SORT_BY_ALIGNMENT"))
6062ec34544SRui Ueyama     return SortSectionPolicy::Alignment;
6072ec34544SRui Ueyama   if (consume("SORT_BY_INIT_PRIORITY"))
6082ec34544SRui Ueyama     return SortSectionPolicy::Priority;
6092ec34544SRui Ueyama   if (consume("SORT_NONE"))
6102ec34544SRui Ueyama     return SortSectionPolicy::None;
6112ec34544SRui Ueyama   return SortSectionPolicy::Default;
6122ec34544SRui Ueyama }
6132ec34544SRui Ueyama 
61403fc8d1eSRui Ueyama // Reads SECTIONS command contents in the following form:
61503fc8d1eSRui Ueyama //
61603fc8d1eSRui Ueyama // <contents> ::= <elem>*
61703fc8d1eSRui Ueyama // <elem>     ::= <exclude>? <glob-pattern>
61803fc8d1eSRui Ueyama // <exclude>  ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")"
61903fc8d1eSRui Ueyama //
62003fc8d1eSRui Ueyama // For example,
62103fc8d1eSRui Ueyama //
62203fc8d1eSRui Ueyama // *(.foo EXCLUDE_FILE (a.o) .bar EXCLUDE_FILE (b.o) .baz)
62303fc8d1eSRui Ueyama //
62403fc8d1eSRui Ueyama // is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o".
62503fc8d1eSRui Ueyama // The semantics of that is section .foo in any file, section .bar in
62603fc8d1eSRui Ueyama // any file but a.o, and section .baz in any file but b.o.
6272ec34544SRui Ueyama std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
6283837f427SRui Ueyama   std::vector<SectionPattern> ret;
629b8a59c8aSBob Haarman   while (!errorCount() && peek() != ")") {
6303837f427SRui Ueyama     StringMatcher excludeFilePat;
6312ec34544SRui Ueyama     if (consume("EXCLUDE_FILE")) {
6322ec34544SRui Ueyama       expect("(");
6333837f427SRui Ueyama       excludeFilePat = readFilePatterns();
6342ec34544SRui Ueyama     }
6352ec34544SRui Ueyama 
6363837f427SRui Ueyama     std::vector<StringRef> v;
637b8a59c8aSBob Haarman     while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")
6383837f427SRui Ueyama       v.push_back(unquote(next()));
6392ec34544SRui Ueyama 
6403837f427SRui Ueyama     if (!v.empty())
6413837f427SRui Ueyama       ret.push_back({std::move(excludeFilePat), StringMatcher(v)});
6422ec34544SRui Ueyama     else
6432ec34544SRui Ueyama       setError("section pattern is expected");
6442ec34544SRui Ueyama   }
6453837f427SRui Ueyama   return ret;
6462ec34544SRui Ueyama }
6472ec34544SRui Ueyama 
6482ec34544SRui Ueyama // Reads contents of "SECTIONS" directive. That directive contains a
6492ec34544SRui Ueyama // list of glob patterns for input sections. The grammar is as follows.
6502ec34544SRui Ueyama //
6512ec34544SRui Ueyama // <patterns> ::= <section-list>
6522ec34544SRui Ueyama //              | <sort> "(" <section-list> ")"
6532ec34544SRui Ueyama //              | <sort> "(" <sort> "(" <section-list> ")" ")"
6542ec34544SRui Ueyama //
6552ec34544SRui Ueyama // <sort>     ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT"
6562ec34544SRui Ueyama //              | "SORT_BY_INIT_PRIORITY" | "SORT_NONE"
6572ec34544SRui Ueyama //
6582ec34544SRui Ueyama // <section-list> is parsed by readInputSectionsList().
6592ec34544SRui Ueyama InputSectionDescription *
6603837f427SRui Ueyama ScriptParser::readInputSectionRules(StringRef filePattern) {
6613837f427SRui Ueyama   auto *cmd = make<InputSectionDescription>(filePattern);
6622ec34544SRui Ueyama   expect("(");
6632ec34544SRui Ueyama 
664b8a59c8aSBob Haarman   while (!errorCount() && !consume(")")) {
6653837f427SRui Ueyama     SortSectionPolicy outer = readSortKind();
6663837f427SRui Ueyama     SortSectionPolicy inner = SortSectionPolicy::Default;
6673837f427SRui Ueyama     std::vector<SectionPattern> v;
6683837f427SRui Ueyama     if (outer != SortSectionPolicy::Default) {
6692ec34544SRui Ueyama       expect("(");
6703837f427SRui Ueyama       inner = readSortKind();
6713837f427SRui Ueyama       if (inner != SortSectionPolicy::Default) {
6722ec34544SRui Ueyama         expect("(");
6733837f427SRui Ueyama         v = readInputSectionsList();
6742ec34544SRui Ueyama         expect(")");
6752ec34544SRui Ueyama       } else {
6763837f427SRui Ueyama         v = readInputSectionsList();
6772ec34544SRui Ueyama       }
6782ec34544SRui Ueyama       expect(")");
6792ec34544SRui Ueyama     } else {
6803837f427SRui Ueyama       v = readInputSectionsList();
6812ec34544SRui Ueyama     }
6822ec34544SRui Ueyama 
6833837f427SRui Ueyama     for (SectionPattern &pat : v) {
6843837f427SRui Ueyama       pat.sortInner = inner;
6853837f427SRui Ueyama       pat.sortOuter = outer;
6862ec34544SRui Ueyama     }
6872ec34544SRui Ueyama 
6883837f427SRui Ueyama     std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns));
6892ec34544SRui Ueyama   }
6903837f427SRui Ueyama   return cmd;
6912ec34544SRui Ueyama }
6922ec34544SRui Ueyama 
6932ec34544SRui Ueyama InputSectionDescription *
6943837f427SRui Ueyama ScriptParser::readInputSectionDescription(StringRef tok) {
6952ec34544SRui Ueyama   // Input section wildcard can be surrounded by KEEP.
6962ec34544SRui Ueyama   // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep
6973837f427SRui Ueyama   if (tok == "KEEP") {
6982ec34544SRui Ueyama     expect("(");
6993837f427SRui Ueyama     StringRef filePattern = next();
7003837f427SRui Ueyama     InputSectionDescription *cmd = readInputSectionRules(filePattern);
7012ec34544SRui Ueyama     expect(")");
7023837f427SRui Ueyama     script->keptSections.push_back(cmd);
7033837f427SRui Ueyama     return cmd;
7042ec34544SRui Ueyama   }
7053837f427SRui Ueyama   return readInputSectionRules(tok);
7062ec34544SRui Ueyama }
7072ec34544SRui Ueyama 
7082ec34544SRui Ueyama void ScriptParser::readSort() {
7092ec34544SRui Ueyama   expect("(");
7102ec34544SRui Ueyama   expect("CONSTRUCTORS");
7112ec34544SRui Ueyama   expect(")");
7122ec34544SRui Ueyama }
7132ec34544SRui Ueyama 
714d30a78b3SGeorge Rimar Expr ScriptParser::readAssert() {
7152ec34544SRui Ueyama   expect("(");
7163837f427SRui Ueyama   Expr e = readExpr();
7172ec34544SRui Ueyama   expect(",");
7183837f427SRui Ueyama   StringRef msg = unquote(next());
7192ec34544SRui Ueyama   expect(")");
720b579c439SRui Ueyama 
7212ec34544SRui Ueyama   return [=] {
7223837f427SRui Ueyama     if (!e().getValue())
7233837f427SRui Ueyama       error(msg);
7243837f427SRui Ueyama     return script->getDot();
7252ec34544SRui Ueyama   };
7262ec34544SRui Ueyama }
7272ec34544SRui Ueyama 
728a46d08ebSGeorge Rimar // Tries to read the special directive for an output section definition which
729a46d08ebSGeorge Rimar // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)".
730a46d08ebSGeorge Rimar // Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below.
7313837f427SRui Ueyama bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2) {
7323837f427SRui Ueyama   if (tok1 != "(")
733a46d08ebSGeorge Rimar     return false;
7343837f427SRui Ueyama   if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" && tok2 != "OVERLAY")
735a46d08ebSGeorge Rimar     return false;
736a46d08ebSGeorge Rimar 
737a46d08ebSGeorge Rimar   expect("(");
738a46d08ebSGeorge Rimar   if (consume("NOLOAD")) {
7393837f427SRui Ueyama     cmd->noload = true;
740a46d08ebSGeorge Rimar   } else {
741a46d08ebSGeorge Rimar     skip(); // This is "COPY", "INFO" or "OVERLAY".
7423837f427SRui Ueyama     cmd->nonAlloc = true;
743a46d08ebSGeorge Rimar   }
744a46d08ebSGeorge Rimar   expect(")");
745a46d08ebSGeorge Rimar   return true;
746a46d08ebSGeorge Rimar }
747a46d08ebSGeorge Rimar 
7481c08e9f5SGeorge Rimar // Reads an expression and/or the special directive for an output
7491c08e9f5SGeorge Rimar // section definition. Directive is one of following: "(NOLOAD)",
7501c08e9f5SGeorge Rimar // "(COPY)", "(INFO)" or "(OVERLAY)".
7513271d370SRui Ueyama //
7523271d370SRui Ueyama // An output section name can be followed by an address expression
7531c08e9f5SGeorge Rimar // and/or directive. This grammar is not LL(1) because "(" can be
75497f4d158SGeorge Rimar // interpreted as either the beginning of some expression or beginning
7551c08e9f5SGeorge Rimar // of directive.
7563271d370SRui Ueyama //
757b579c439SRui Ueyama // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
758fbb0463fSGeorge Rimar // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
7593837f427SRui Ueyama void ScriptParser::readSectionAddressType(OutputSection *cmd) {
7603837f427SRui Ueyama   if (readSectionDirective(cmd, peek(), peek2()))
7613271d370SRui Ueyama     return;
7623271d370SRui Ueyama 
7633837f427SRui Ueyama   cmd->addrExpr = readExpr();
7643837f427SRui Ueyama   if (peek() == "(" && !readSectionDirective(cmd, "(", peek2()))
765a46d08ebSGeorge Rimar     setError("unknown section directive: " + peek2());
766fbb0463fSGeorge Rimar }
767fbb0463fSGeorge Rimar 
7683837f427SRui Ueyama static Expr checkAlignment(Expr e, std::string &loc) {
769f22ec9ddSGeorge Rimar   return [=] {
7703837f427SRui Ueyama     uint64_t alignment = std::max((uint64_t)1, e().getValue());
7713837f427SRui Ueyama     if (!isPowerOf2_64(alignment)) {
7723837f427SRui Ueyama       error(loc + ": alignment must be power of 2");
773f22ec9ddSGeorge Rimar       return (uint64_t)1; // Return a dummy value.
774f22ec9ddSGeorge Rimar     }
7753837f427SRui Ueyama     return alignment;
776f22ec9ddSGeorge Rimar   };
777f22ec9ddSGeorge Rimar }
778f22ec9ddSGeorge Rimar 
779a582419aSGeorge Rimar OutputSection *ScriptParser::readOverlaySectionDescription() {
7803837f427SRui Ueyama   OutputSection *cmd =
7813837f427SRui Ueyama       script->createOutputSection(next(), getCurrentLocation());
7823837f427SRui Ueyama   cmd->inOverlay = true;
783a582419aSGeorge Rimar   expect("{");
784a582419aSGeorge Rimar   while (!errorCount() && !consume("}"))
7853837f427SRui Ueyama     cmd->sectionCommands.push_back(readInputSectionRules(next()));
7863837f427SRui Ueyama   cmd->phdrs = readOutputSectionPhdrs();
7873837f427SRui Ueyama   return cmd;
788a582419aSGeorge Rimar }
789a582419aSGeorge Rimar 
7903837f427SRui Ueyama OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
7913837f427SRui Ueyama   OutputSection *cmd =
7923837f427SRui Ueyama       script->createOutputSection(outSec, getCurrentLocation());
7933271d370SRui Ueyama 
7943837f427SRui Ueyama   size_t symbolsReferenced = script->referencedSymbols.size();
795c4df670dSGeorge Rimar 
7963271d370SRui Ueyama   if (peek() != ":")
7973837f427SRui Ueyama     readSectionAddressType(cmd);
7982ec34544SRui Ueyama   expect(":");
7992ec34544SRui Ueyama 
8003837f427SRui Ueyama   std::string location = getCurrentLocation();
8012ec34544SRui Ueyama   if (consume("AT"))
8023837f427SRui Ueyama     cmd->lmaExpr = readParenExpr();
8032ec34544SRui Ueyama   if (consume("ALIGN"))
8043837f427SRui Ueyama     cmd->alignExpr = checkAlignment(readParenExpr(), location);
8052ec34544SRui Ueyama   if (consume("SUBALIGN"))
8063837f427SRui Ueyama     cmd->subalignExpr = checkAlignment(readParenExpr(), location);
8072ec34544SRui Ueyama 
8082ec34544SRui Ueyama   // Parse constraints.
8092ec34544SRui Ueyama   if (consume("ONLY_IF_RO"))
8103837f427SRui Ueyama     cmd->constraint = ConstraintKind::ReadOnly;
8112ec34544SRui Ueyama   if (consume("ONLY_IF_RW"))
8123837f427SRui Ueyama     cmd->constraint = ConstraintKind::ReadWrite;
8132ec34544SRui Ueyama   expect("{");
8142ec34544SRui Ueyama 
815b8a59c8aSBob Haarman   while (!errorCount() && !consume("}")) {
8163837f427SRui Ueyama     StringRef tok = next();
8173837f427SRui Ueyama     if (tok == ";") {
8182ec34544SRui Ueyama       // Empty commands are allowed. Do nothing here.
8193837f427SRui Ueyama     } else if (SymbolAssignment *assign = readAssignment(tok)) {
8203837f427SRui Ueyama       cmd->sectionCommands.push_back(assign);
8213837f427SRui Ueyama     } else if (ByteCommand *data = readByteCommand(tok)) {
8223837f427SRui Ueyama       cmd->sectionCommands.push_back(data);
8233837f427SRui Ueyama     } else if (tok == "CONSTRUCTORS") {
8242ec34544SRui Ueyama       // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
8252ec34544SRui Ueyama       // by name. This is for very old file formats such as ECOFF/XCOFF.
8262ec34544SRui Ueyama       // For ELF, we should ignore.
8273837f427SRui Ueyama     } else if (tok == "FILL") {
8280810f16fSGeorge Rimar       // We handle the FILL command as an alias for =fillexp section attribute,
8290810f16fSGeorge Rimar       // which is different from what GNU linkers do.
8300810f16fSGeorge Rimar       // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
831c44a23f8SGeorge Rimar       expect("(");
8323837f427SRui Ueyama       cmd->filler = readFill();
833c44a23f8SGeorge Rimar       expect(")");
8343837f427SRui Ueyama     } else if (tok == "SORT") {
8352ec34544SRui Ueyama       readSort();
8363837f427SRui Ueyama     } else if (tok == "INCLUDE") {
8372e9d40d5SRui Ueyama       readInclude();
8382ec34544SRui Ueyama     } else if (peek() == "(") {
8393837f427SRui Ueyama       cmd->sectionCommands.push_back(readInputSectionDescription(tok));
8402ec34544SRui Ueyama     } else {
841f49fe218SGeorge Rimar       // We have a file name and no input sections description. It is not a
842f49fe218SGeorge Rimar       // commonly used syntax, but still acceptable. In that case, all sections
843f49fe218SGeorge Rimar       // from the file will be included.
8443837f427SRui Ueyama       auto *isd = make<InputSectionDescription>(tok);
8453837f427SRui Ueyama       isd->sectionPatterns.push_back({{}, StringMatcher({"*"})});
8463837f427SRui Ueyama       cmd->sectionCommands.push_back(isd);
8472ec34544SRui Ueyama     }
8482ec34544SRui Ueyama   }
8492ec34544SRui Ueyama 
8502ec34544SRui Ueyama   if (consume(">"))
8513837f427SRui Ueyama     cmd->memoryRegionName = next();
8522ec34544SRui Ueyama 
8535d01a8beSGeorge Rimar   if (consume("AT")) {
8545d01a8beSGeorge Rimar     expect(">");
8553837f427SRui Ueyama     cmd->lmaRegionName = next();
8565d01a8beSGeorge Rimar   }
8575d01a8beSGeorge Rimar 
8583837f427SRui Ueyama   if (cmd->lmaExpr && !cmd->lmaRegionName.empty())
8595d01a8beSGeorge Rimar     error("section can't have both LMA and a load region");
8605d01a8beSGeorge Rimar 
8613837f427SRui Ueyama   cmd->phdrs = readOutputSectionPhdrs();
8622ec34544SRui Ueyama 
8630810f16fSGeorge Rimar   if (peek() == "=" || peek().startswith("=")) {
8643837f427SRui Ueyama     inExpr = true;
8650810f16fSGeorge Rimar     consume("=");
8663837f427SRui Ueyama     cmd->filler = readFill();
8673837f427SRui Ueyama     inExpr = false;
8680810f16fSGeorge Rimar   }
8692ec34544SRui Ueyama 
8702ec34544SRui Ueyama   // Consume optional comma following output section command.
8712ec34544SRui Ueyama   consume(",");
8722ec34544SRui Ueyama 
8733837f427SRui Ueyama   if (script->referencedSymbols.size() > symbolsReferenced)
8743837f427SRui Ueyama     cmd->expressionsUseSymbols = true;
8753837f427SRui Ueyama   return cmd;
8762ec34544SRui Ueyama }
8772ec34544SRui Ueyama 
8780810f16fSGeorge Rimar // Reads a `=<fillexp>` expression and returns its value as a big-endian number.
8792ec34544SRui Ueyama // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html
8800810f16fSGeorge Rimar // We do not support using symbols in such expressions.
8812ec34544SRui Ueyama //
8828acbf1ccSRui Ueyama // When reading a hexstring, ld.bfd handles it as a blob of arbitrary
8838acbf1ccSRui Ueyama // size, while ld.gold always handles it as a 32-bit big-endian number.
8848acbf1ccSRui Ueyama // We are compatible with ld.gold because it's easier to implement.
8850810f16fSGeorge Rimar std::array<uint8_t, 4> ScriptParser::readFill() {
8863837f427SRui Ueyama   uint64_t value = readExpr()().val;
8873837f427SRui Ueyama   if (value > UINT32_MAX)
8880810f16fSGeorge Rimar     setError("filler expression result does not fit 32-bit: 0x" +
8893837f427SRui Ueyama              Twine::utohexstr(value));
890b58079d4SRui Ueyama 
8913837f427SRui Ueyama   std::array<uint8_t, 4> buf;
8923837f427SRui Ueyama   write32be(buf.data(), (uint32_t)value);
8933837f427SRui Ueyama   return buf;
8942ec34544SRui Ueyama }
8952ec34544SRui Ueyama 
8963837f427SRui Ueyama SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
8972ec34544SRui Ueyama   expect("(");
8983837f427SRui Ueyama   SymbolAssignment *cmd = readSymbolAssignment(next());
8993837f427SRui Ueyama   cmd->provide = provide;
9003837f427SRui Ueyama   cmd->hidden = hidden;
9012ec34544SRui Ueyama   expect(")");
9023837f427SRui Ueyama   return cmd;
9032ec34544SRui Ueyama }
9042ec34544SRui Ueyama 
9053837f427SRui Ueyama SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
906d30a78b3SGeorge Rimar   // Assert expression returns Dot, so this is equal to ".=."
9073837f427SRui Ueyama   if (tok == "ASSERT")
908d30a78b3SGeorge Rimar     return make<SymbolAssignment>(".", readAssert(), getCurrentLocation());
909d30a78b3SGeorge Rimar 
9103837f427SRui Ueyama   size_t oldPos = pos;
9113837f427SRui Ueyama   SymbolAssignment *cmd = nullptr;
912e88b76a9SGeorge Rimar   if (peek() == "=" || peek() == "+=")
9133837f427SRui Ueyama     cmd = readSymbolAssignment(tok);
9143837f427SRui Ueyama   else if (tok == "PROVIDE")
9153837f427SRui Ueyama     cmd = readProvideHidden(true, false);
9163837f427SRui Ueyama   else if (tok == "HIDDEN")
9173837f427SRui Ueyama     cmd = readProvideHidden(false, true);
9183837f427SRui Ueyama   else if (tok == "PROVIDE_HIDDEN")
9193837f427SRui Ueyama     cmd = readProvideHidden(true, true);
920e88b76a9SGeorge Rimar 
9213837f427SRui Ueyama   if (cmd) {
9223837f427SRui Ueyama     cmd->commandString =
9233837f427SRui Ueyama         tok.str() + " " +
9243837f427SRui Ueyama         llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
925e88b76a9SGeorge Rimar     expect(";");
9262ec34544SRui Ueyama   }
9273837f427SRui Ueyama   return cmd;
9282ec34544SRui Ueyama }
9292ec34544SRui Ueyama 
9303837f427SRui Ueyama SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
9313837f427SRui Ueyama   StringRef op = next();
9323837f427SRui Ueyama   assert(op == "=" || op == "+=");
9333837f427SRui Ueyama   Expr e = readExpr();
9343837f427SRui Ueyama   if (op == "+=") {
9353837f427SRui Ueyama     std::string loc = getCurrentLocation();
9363837f427SRui Ueyama     e = [=] { return add(script->getSymbolValue(name, loc), e()); };
9372ec34544SRui Ueyama   }
9383837f427SRui Ueyama   return make<SymbolAssignment>(name, e, getCurrentLocation());
9392ec34544SRui Ueyama }
9402ec34544SRui Ueyama 
9412ec34544SRui Ueyama // This is an operator-precedence parser to parse a linker
9422ec34544SRui Ueyama // script expression.
9432ec34544SRui Ueyama Expr ScriptParser::readExpr() {
9442ec34544SRui Ueyama   // Our lexer is context-aware. Set the in-expression bit so that
9452ec34544SRui Ueyama   // they apply different tokenization rules.
9463837f427SRui Ueyama   bool orig = inExpr;
9473837f427SRui Ueyama   inExpr = true;
9483837f427SRui Ueyama   Expr e = readExpr1(readPrimary(), 0);
9493837f427SRui Ueyama   inExpr = orig;
9503837f427SRui Ueyama   return e;
9512ec34544SRui Ueyama }
9522ec34544SRui Ueyama 
9533837f427SRui Ueyama Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
9543837f427SRui Ueyama   if (op == "+")
9553837f427SRui Ueyama     return [=] { return add(l(), r()); };
9563837f427SRui Ueyama   if (op == "-")
9573837f427SRui Ueyama     return [=] { return sub(l(), r()); };
9583837f427SRui Ueyama   if (op == "*")
9593837f427SRui Ueyama     return [=] { return l().getValue() * r().getValue(); };
9603837f427SRui Ueyama   if (op == "/") {
9613837f427SRui Ueyama     std::string loc = getCurrentLocation();
9627b91e213SGeorge Rimar     return [=]() -> uint64_t {
9633837f427SRui Ueyama       if (uint64_t rv = r().getValue())
9643837f427SRui Ueyama         return l().getValue() / rv;
9653837f427SRui Ueyama       error(loc + ": division by zero");
966067617f9SRui Ueyama       return 0;
9677b91e213SGeorge Rimar     };
9687b91e213SGeorge Rimar   }
9693837f427SRui Ueyama   if (op == "%") {
9703837f427SRui Ueyama     std::string loc = getCurrentLocation();
9717b91e213SGeorge Rimar     return [=]() -> uint64_t {
9723837f427SRui Ueyama       if (uint64_t rv = r().getValue())
9733837f427SRui Ueyama         return l().getValue() % rv;
9743837f427SRui Ueyama       error(loc + ": modulo by zero");
975067617f9SRui Ueyama       return 0;
9767b91e213SGeorge Rimar     };
9777b91e213SGeorge Rimar   }
9783837f427SRui Ueyama   if (op == "<<")
9793837f427SRui Ueyama     return [=] { return l().getValue() << r().getValue(); };
9803837f427SRui Ueyama   if (op == ">>")
9813837f427SRui Ueyama     return [=] { return l().getValue() >> r().getValue(); };
9823837f427SRui Ueyama   if (op == "<")
9833837f427SRui Ueyama     return [=] { return l().getValue() < r().getValue(); };
9843837f427SRui Ueyama   if (op == ">")
9853837f427SRui Ueyama     return [=] { return l().getValue() > r().getValue(); };
9863837f427SRui Ueyama   if (op == ">=")
9873837f427SRui Ueyama     return [=] { return l().getValue() >= r().getValue(); };
9883837f427SRui Ueyama   if (op == "<=")
9893837f427SRui Ueyama     return [=] { return l().getValue() <= r().getValue(); };
9903837f427SRui Ueyama   if (op == "==")
9913837f427SRui Ueyama     return [=] { return l().getValue() == r().getValue(); };
9923837f427SRui Ueyama   if (op == "!=")
9933837f427SRui Ueyama     return [=] { return l().getValue() != r().getValue(); };
9943837f427SRui Ueyama   if (op == "||")
9953837f427SRui Ueyama     return [=] { return l().getValue() || r().getValue(); };
9963837f427SRui Ueyama   if (op == "&&")
9973837f427SRui Ueyama     return [=] { return l().getValue() && r().getValue(); };
9983837f427SRui Ueyama   if (op == "&")
9993837f427SRui Ueyama     return [=] { return bitAnd(l(), r()); };
10003837f427SRui Ueyama   if (op == "|")
10013837f427SRui Ueyama     return [=] { return bitOr(l(), r()); };
10022ec34544SRui Ueyama   llvm_unreachable("invalid operator");
10032ec34544SRui Ueyama }
10042ec34544SRui Ueyama 
10052ec34544SRui Ueyama // This is a part of the operator-precedence parser. This function
10062ec34544SRui Ueyama // assumes that the remaining token stream starts with an operator.
10073837f427SRui Ueyama Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
1008b8a59c8aSBob Haarman   while (!atEOF() && !errorCount()) {
10092ec34544SRui Ueyama     // Read an operator and an expression.
10102ec34544SRui Ueyama     if (consume("?"))
10113837f427SRui Ueyama       return readTernary(lhs);
10123837f427SRui Ueyama     StringRef op1 = peek();
10133837f427SRui Ueyama     if (precedence(op1) < minPrec)
10142ec34544SRui Ueyama       break;
10152ec34544SRui Ueyama     skip();
10163837f427SRui Ueyama     Expr rhs = readPrimary();
10172ec34544SRui Ueyama 
10182ec34544SRui Ueyama     // Evaluate the remaining part of the expression first if the
10192ec34544SRui Ueyama     // next operator has greater precedence than the previous one.
10202ec34544SRui Ueyama     // For example, if we have read "+" and "3", and if the next
10212ec34544SRui Ueyama     // operator is "*", then we'll evaluate 3 * ... part first.
10222ec34544SRui Ueyama     while (!atEOF()) {
10233837f427SRui Ueyama       StringRef op2 = peek();
10243837f427SRui Ueyama       if (precedence(op2) <= precedence(op1))
10252ec34544SRui Ueyama         break;
10263837f427SRui Ueyama       rhs = readExpr1(rhs, precedence(op2));
10272ec34544SRui Ueyama     }
10282ec34544SRui Ueyama 
10293837f427SRui Ueyama     lhs = combine(op1, lhs, rhs);
10302ec34544SRui Ueyama   }
10313837f427SRui Ueyama   return lhs;
10322ec34544SRui Ueyama }
10332ec34544SRui Ueyama 
10345fb17128SGeorge Rimar Expr ScriptParser::getPageSize() {
10353837f427SRui Ueyama   std::string location = getCurrentLocation();
10365fb17128SGeorge Rimar   return [=]() -> uint64_t {
10373837f427SRui Ueyama     if (target)
10383837f427SRui Ueyama       return config->commonPageSize;
10393837f427SRui Ueyama     error(location + ": unable to calculate page size");
10405fb17128SGeorge Rimar     return 4096; // Return a dummy value.
10415fb17128SGeorge Rimar   };
10425fb17128SGeorge Rimar }
10435fb17128SGeorge Rimar 
10445fb17128SGeorge Rimar Expr ScriptParser::readConstant() {
10453837f427SRui Ueyama   StringRef s = readParenLiteral();
10463837f427SRui Ueyama   if (s == "COMMONPAGESIZE")
10475fb17128SGeorge Rimar     return getPageSize();
10483837f427SRui Ueyama   if (s == "MAXPAGESIZE")
10493837f427SRui Ueyama     return [] { return config->maxPageSize; };
10503837f427SRui Ueyama   setError("unknown constant: " + s);
1051b068b037SGeorge Rimar   return [] { return 0; };
10522ec34544SRui Ueyama }
10532ec34544SRui Ueyama 
10545c65088fSRui Ueyama // Parses Tok as an integer. It recognizes hexadecimal (prefixed with
10555c65088fSRui Ueyama // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
10565c65088fSRui Ueyama // have "K" (Ki) or "M" (Mi) suffixes.
10573837f427SRui Ueyama static Optional<uint64_t> parseInt(StringRef tok) {
10582ec34544SRui Ueyama   // Hexadecimal
10593837f427SRui Ueyama   uint64_t val;
10603837f427SRui Ueyama   if (tok.startswith_lower("0x")) {
10613837f427SRui Ueyama     if (!to_integer(tok.substr(2), val, 16))
10624092016bSRui Ueyama       return None;
10633837f427SRui Ueyama     return val;
10644092016bSRui Ueyama   }
10653837f427SRui Ueyama   if (tok.endswith_lower("H")) {
10663837f427SRui Ueyama     if (!to_integer(tok.drop_back(), val, 16))
10674092016bSRui Ueyama       return None;
10683837f427SRui Ueyama     return val;
10694092016bSRui Ueyama   }
10702ec34544SRui Ueyama 
10712ec34544SRui Ueyama   // Decimal
10723837f427SRui Ueyama   if (tok.endswith_lower("K")) {
10733837f427SRui Ueyama     if (!to_integer(tok.drop_back(), val, 10))
10745c65088fSRui Ueyama       return None;
10753837f427SRui Ueyama     return val * 1024;
10762ec34544SRui Ueyama   }
10773837f427SRui Ueyama   if (tok.endswith_lower("M")) {
10783837f427SRui Ueyama     if (!to_integer(tok.drop_back(), val, 10))
10795c65088fSRui Ueyama       return None;
10803837f427SRui Ueyama     return val * 1024 * 1024;
10815c65088fSRui Ueyama   }
10823837f427SRui Ueyama   if (!to_integer(tok, val, 10))
10835c65088fSRui Ueyama     return None;
10843837f427SRui Ueyama   return val;
10852ec34544SRui Ueyama }
10862ec34544SRui Ueyama 
10873837f427SRui Ueyama ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
10883837f427SRui Ueyama   int size = StringSwitch<int>(tok)
10892ec34544SRui Ueyama                  .Case("BYTE", 1)
10902ec34544SRui Ueyama                  .Case("SHORT", 2)
10912ec34544SRui Ueyama                  .Case("LONG", 4)
10922ec34544SRui Ueyama                  .Case("QUAD", 8)
10932ec34544SRui Ueyama                  .Default(-1);
10943837f427SRui Ueyama   if (size == -1)
10952ec34544SRui Ueyama     return nullptr;
109684bcabcbSGeorge Rimar 
10973837f427SRui Ueyama   size_t oldPos = pos;
10983837f427SRui Ueyama   Expr e = readParenExpr();
10993837f427SRui Ueyama   std::string commandString =
11003837f427SRui Ueyama       tok.str() + " " +
11013837f427SRui Ueyama       llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
11023837f427SRui Ueyama   return make<ByteCommand>(e, size, commandString);
11032ec34544SRui Ueyama }
11042ec34544SRui Ueyama 
11052ec34544SRui Ueyama StringRef ScriptParser::readParenLiteral() {
11062ec34544SRui Ueyama   expect("(");
11073837f427SRui Ueyama   bool orig = inExpr;
11083837f427SRui Ueyama   inExpr = false;
11093837f427SRui Ueyama   StringRef tok = next();
11103837f427SRui Ueyama   inExpr = orig;
11112ec34544SRui Ueyama   expect(")");
11123837f427SRui Ueyama   return tok;
11132ec34544SRui Ueyama }
11142ec34544SRui Ueyama 
11153837f427SRui Ueyama static void checkIfExists(OutputSection *cmd, StringRef location) {
11163837f427SRui Ueyama   if (cmd->location.empty() && script->errorOnMissingSection)
11173837f427SRui Ueyama     error(location + ": undefined section " + cmd->name);
111805c4f67cSRafael Espindola }
111905c4f67cSRafael Espindola 
11202ec34544SRui Ueyama Expr ScriptParser::readPrimary() {
11212ec34544SRui Ueyama   if (peek() == "(")
11222ec34544SRui Ueyama     return readParenExpr();
11232ec34544SRui Ueyama 
11245c65088fSRui Ueyama   if (consume("~")) {
11253837f427SRui Ueyama     Expr e = readPrimary();
11263837f427SRui Ueyama     return [=] { return ~e().getValue(); };
11272ec34544SRui Ueyama   }
11286f1d954eSHafiz Abid Qadeer   if (consume("!")) {
11293837f427SRui Ueyama     Expr e = readPrimary();
11303837f427SRui Ueyama     return [=] { return !e().getValue(); };
11316f1d954eSHafiz Abid Qadeer   }
11325c65088fSRui Ueyama   if (consume("-")) {
11333837f427SRui Ueyama     Expr e = readPrimary();
11343837f427SRui Ueyama     return [=] { return -e().getValue(); };
11352ec34544SRui Ueyama   }
11362ec34544SRui Ueyama 
11373837f427SRui Ueyama   StringRef tok = next();
11383837f427SRui Ueyama   std::string location = getCurrentLocation();
11395c65088fSRui Ueyama 
11402ec34544SRui Ueyama   // Built-in functions are parsed here.
11412ec34544SRui Ueyama   // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
11423837f427SRui Ueyama   if (tok == "ABSOLUTE") {
11433837f427SRui Ueyama     Expr inner = readParenExpr();
11442ec34544SRui Ueyama     return [=] {
11453837f427SRui Ueyama       ExprValue i = inner();
11463837f427SRui Ueyama       i.forceAbsolute = true;
11473837f427SRui Ueyama       return i;
11482ec34544SRui Ueyama     };
11492ec34544SRui Ueyama   }
11503837f427SRui Ueyama   if (tok == "ADDR") {
11513837f427SRui Ueyama     StringRef name = readParenLiteral();
11523837f427SRui Ueyama     OutputSection *sec = script->getOrCreateOutputSection(name);
11533837f427SRui Ueyama     sec->usedInExpression = true;
115441c7ab4aSGeorge Rimar     return [=]() -> ExprValue {
11553837f427SRui Ueyama       checkIfExists(sec, location);
11563837f427SRui Ueyama       return {sec, false, 0, location};
115741c7ab4aSGeorge Rimar     };
11582ec34544SRui Ueyama   }
11593837f427SRui Ueyama   if (tok == "ALIGN") {
11602ec34544SRui Ueyama     expect("(");
11613837f427SRui Ueyama     Expr e = readExpr();
1162f22ec9ddSGeorge Rimar     if (consume(")")) {
11633837f427SRui Ueyama       e = checkAlignment(e, location);
11643837f427SRui Ueyama       return [=] { return alignTo(script->getDot(), e().getValue()); };
1165f22ec9ddSGeorge Rimar     }
1166b579c439SRui Ueyama     expect(",");
11673837f427SRui Ueyama     Expr e2 = checkAlignment(readExpr(), location);
11682ec34544SRui Ueyama     expect(")");
11693c6de1a6SPetr Hosek     return [=] {
11703837f427SRui Ueyama       ExprValue v = e();
11713837f427SRui Ueyama       v.alignment = e2().getValue();
11723837f427SRui Ueyama       return v;
11733c6de1a6SPetr Hosek     };
11742ec34544SRui Ueyama   }
11753837f427SRui Ueyama   if (tok == "ALIGNOF") {
11763837f427SRui Ueyama     StringRef name = readParenLiteral();
11773837f427SRui Ueyama     OutputSection *cmd = script->getOrCreateOutputSection(name);
1178617e2f98SRui Ueyama     return [=] {
11793837f427SRui Ueyama       checkIfExists(cmd, location);
11803837f427SRui Ueyama       return cmd->alignment;
1181617e2f98SRui Ueyama     };
11822ec34544SRui Ueyama   }
11833837f427SRui Ueyama   if (tok == "ASSERT")
1184d30a78b3SGeorge Rimar     return readAssert();
11853837f427SRui Ueyama   if (tok == "CONSTANT")
11865fb17128SGeorge Rimar     return readConstant();
11873837f427SRui Ueyama   if (tok == "DATA_SEGMENT_ALIGN") {
11882ec34544SRui Ueyama     expect("(");
11893837f427SRui Ueyama     Expr e = readExpr();
11902ec34544SRui Ueyama     expect(",");
11912ec34544SRui Ueyama     readExpr();
11922ec34544SRui Ueyama     expect(")");
119360833f6eSGeorge Rimar     return [=] {
11943837f427SRui Ueyama       return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue()));
119560833f6eSGeorge Rimar     };
11962ec34544SRui Ueyama   }
11973837f427SRui Ueyama   if (tok == "DATA_SEGMENT_END") {
11982ec34544SRui Ueyama     expect("(");
11992ec34544SRui Ueyama     expect(".");
12002ec34544SRui Ueyama     expect(")");
12013837f427SRui Ueyama     return [] { return script->getDot(); };
12022ec34544SRui Ueyama   }
12033837f427SRui Ueyama   if (tok == "DATA_SEGMENT_RELRO_END") {
12042ec34544SRui Ueyama     // GNU linkers implements more complicated logic to handle
12052ec34544SRui Ueyama     // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
12062ec34544SRui Ueyama     // just align to the next page boundary for simplicity.
12072ec34544SRui Ueyama     expect("(");
12082ec34544SRui Ueyama     readExpr();
12092ec34544SRui Ueyama     expect(",");
12102ec34544SRui Ueyama     readExpr();
12112ec34544SRui Ueyama     expect(")");
12123837f427SRui Ueyama     Expr e = getPageSize();
12133837f427SRui Ueyama     return [=] { return alignTo(script->getDot(), e().getValue()); };
12142ec34544SRui Ueyama   }
12153837f427SRui Ueyama   if (tok == "DEFINED") {
12163837f427SRui Ueyama     StringRef name = readParenLiteral();
12173837f427SRui Ueyama     return [=] { return symtab->find(name) ? 1 : 0; };
12182ec34544SRui Ueyama   }
12193837f427SRui Ueyama   if (tok == "LENGTH") {
12203837f427SRui Ueyama     StringRef name = readParenLiteral();
12213837f427SRui Ueyama     if (script->memoryRegions.count(name) == 0) {
12223837f427SRui Ueyama       setError("memory region not defined: " + name);
1223b068b037SGeorge Rimar       return [] { return 0; };
1224b068b037SGeorge Rimar     }
12253837f427SRui Ueyama     return [=] { return script->memoryRegions[name]->length; };
122691b95b61SRui Ueyama   }
12273837f427SRui Ueyama   if (tok == "LOADADDR") {
12283837f427SRui Ueyama     StringRef name = readParenLiteral();
12293837f427SRui Ueyama     OutputSection *cmd = script->getOrCreateOutputSection(name);
12303837f427SRui Ueyama     cmd->usedInExpression = true;
1231617e2f98SRui Ueyama     return [=] {
12323837f427SRui Ueyama       checkIfExists(cmd, location);
12333837f427SRui Ueyama       return cmd->getLMA();
1234617e2f98SRui Ueyama     };
12352ec34544SRui Ueyama   }
12363837f427SRui Ueyama   if (tok == "MAX" || tok == "MIN") {
1237fd11560fSGeorge Rimar     expect("(");
12383837f427SRui Ueyama     Expr a = readExpr();
1239fd11560fSGeorge Rimar     expect(",");
12403837f427SRui Ueyama     Expr b = readExpr();
1241fd11560fSGeorge Rimar     expect(")");
12423837f427SRui Ueyama     if (tok == "MIN")
12433837f427SRui Ueyama       return [=] { return std::min(a().getValue(), b().getValue()); };
12443837f427SRui Ueyama     return [=] { return std::max(a().getValue(), b().getValue()); };
1245fd11560fSGeorge Rimar   }
12463837f427SRui Ueyama   if (tok == "ORIGIN") {
12473837f427SRui Ueyama     StringRef name = readParenLiteral();
12483837f427SRui Ueyama     if (script->memoryRegions.count(name) == 0) {
12493837f427SRui Ueyama       setError("memory region not defined: " + name);
1250b068b037SGeorge Rimar       return [] { return 0; };
1251b068b037SGeorge Rimar     }
12523837f427SRui Ueyama     return [=] { return script->memoryRegions[name]->origin; };
125391b95b61SRui Ueyama   }
12543837f427SRui Ueyama   if (tok == "SEGMENT_START") {
12552ec34544SRui Ueyama     expect("(");
12562ec34544SRui Ueyama     skip();
12572ec34544SRui Ueyama     expect(",");
12583837f427SRui Ueyama     Expr e = readExpr();
12592ec34544SRui Ueyama     expect(")");
12603837f427SRui Ueyama     return [=] { return e(); };
12612ec34544SRui Ueyama   }
12623837f427SRui Ueyama   if (tok == "SIZEOF") {
12633837f427SRui Ueyama     StringRef name = readParenLiteral();
12643837f427SRui Ueyama     OutputSection *cmd = script->getOrCreateOutputSection(name);
126505c4f67cSRafael Espindola     // Linker script does not create an output section if its content is empty.
126605c4f67cSRafael Espindola     // We want to allow SIZEOF(.foo) where .foo is a section which happened to
126705c4f67cSRafael Espindola     // be empty.
12683837f427SRui Ueyama     return [=] { return cmd->size; };
12692ec34544SRui Ueyama   }
12703837f427SRui Ueyama   if (tok == "SIZEOF_HEADERS")
12712ec34544SRui Ueyama     return [=] { return elf::getHeaderSize(); };
12722ec34544SRui Ueyama 
12734eb2eccbSRui Ueyama   // Tok is the dot.
12743837f427SRui Ueyama   if (tok == ".")
12753837f427SRui Ueyama     return [=] { return script->getSymbolValue(tok, location); };
12764eb2eccbSRui Ueyama 
12772ec34544SRui Ueyama   // Tok is a literal number.
12783837f427SRui Ueyama   if (Optional<uint64_t> val = parseInt(tok))
12793837f427SRui Ueyama     return [=] { return *val; };
12802ec34544SRui Ueyama 
12812ec34544SRui Ueyama   // Tok is a symbol name.
12823837f427SRui Ueyama   if (!isValidCIdentifier(tok))
12833837f427SRui Ueyama     setError("malformed number: " + tok);
12843837f427SRui Ueyama   script->referencedSymbols.push_back(tok);
12853837f427SRui Ueyama   return [=] { return script->getSymbolValue(tok, location); };
12862ec34544SRui Ueyama }
12872ec34544SRui Ueyama 
12883837f427SRui Ueyama Expr ScriptParser::readTernary(Expr cond) {
12893837f427SRui Ueyama   Expr l = readExpr();
12902ec34544SRui Ueyama   expect(":");
12913837f427SRui Ueyama   Expr r = readExpr();
12923837f427SRui Ueyama   return [=] { return cond().getValue() ? l() : r(); };
12932ec34544SRui Ueyama }
12942ec34544SRui Ueyama 
12952ec34544SRui Ueyama Expr ScriptParser::readParenExpr() {
12962ec34544SRui Ueyama   expect("(");
12973837f427SRui Ueyama   Expr e = readExpr();
12982ec34544SRui Ueyama   expect(")");
12993837f427SRui Ueyama   return e;
13002ec34544SRui Ueyama }
13012ec34544SRui Ueyama 
13022ec34544SRui Ueyama std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
13033837f427SRui Ueyama   std::vector<StringRef> phdrs;
1304b8a59c8aSBob Haarman   while (!errorCount() && peek().startswith(":")) {
13053837f427SRui Ueyama     StringRef tok = next();
13063837f427SRui Ueyama     phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));
13072ec34544SRui Ueyama   }
13083837f427SRui Ueyama   return phdrs;
13092ec34544SRui Ueyama }
13102ec34544SRui Ueyama 
13112ec34544SRui Ueyama // Read a program header type name. The next token must be a
13122ec34544SRui Ueyama // name of a program header type or a constant (e.g. "0x3").
13132ec34544SRui Ueyama unsigned ScriptParser::readPhdrType() {
13143837f427SRui Ueyama   StringRef tok = next();
13153837f427SRui Ueyama   if (Optional<uint64_t> val = parseInt(tok))
13163837f427SRui Ueyama     return *val;
13172ec34544SRui Ueyama 
13183837f427SRui Ueyama   unsigned ret = StringSwitch<unsigned>(tok)
13192ec34544SRui Ueyama                      .Case("PT_NULL", PT_NULL)
13202ec34544SRui Ueyama                      .Case("PT_LOAD", PT_LOAD)
13212ec34544SRui Ueyama                      .Case("PT_DYNAMIC", PT_DYNAMIC)
13222ec34544SRui Ueyama                      .Case("PT_INTERP", PT_INTERP)
13232ec34544SRui Ueyama                      .Case("PT_NOTE", PT_NOTE)
13242ec34544SRui Ueyama                      .Case("PT_SHLIB", PT_SHLIB)
13252ec34544SRui Ueyama                      .Case("PT_PHDR", PT_PHDR)
13262ec34544SRui Ueyama                      .Case("PT_TLS", PT_TLS)
13272ec34544SRui Ueyama                      .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
13282ec34544SRui Ueyama                      .Case("PT_GNU_STACK", PT_GNU_STACK)
13292ec34544SRui Ueyama                      .Case("PT_GNU_RELRO", PT_GNU_RELRO)
13302ec34544SRui Ueyama                      .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE)
13312ec34544SRui Ueyama                      .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED)
13322ec34544SRui Ueyama                      .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
13332ec34544SRui Ueyama                      .Default(-1);
13342ec34544SRui Ueyama 
13353837f427SRui Ueyama   if (ret == (unsigned)-1) {
13363837f427SRui Ueyama     setError("invalid program header type: " + tok);
13372ec34544SRui Ueyama     return PT_NULL;
13382ec34544SRui Ueyama   }
13393837f427SRui Ueyama   return ret;
13402ec34544SRui Ueyama }
13412ec34544SRui Ueyama 
13422ec34544SRui Ueyama // Reads an anonymous version declaration.
13432ec34544SRui Ueyama void ScriptParser::readAnonymousDeclaration() {
13443837f427SRui Ueyama   std::vector<SymbolVersion> locals;
13453837f427SRui Ueyama   std::vector<SymbolVersion> globals;
13463837f427SRui Ueyama   std::tie(locals, globals) = readSymbols();
13472ec34544SRui Ueyama 
13483837f427SRui Ueyama   for (SymbolVersion v : locals) {
13493837f427SRui Ueyama     if (v.name == "*")
13503837f427SRui Ueyama       config->defaultSymbolVersion = VER_NDX_LOCAL;
13512ec34544SRui Ueyama     else
13523837f427SRui Ueyama       config->versionScriptLocals.push_back(v);
13532ec34544SRui Ueyama   }
13542ec34544SRui Ueyama 
13553837f427SRui Ueyama   for (SymbolVersion v : globals)
13563837f427SRui Ueyama     config->versionScriptGlobals.push_back(v);
13572ec34544SRui Ueyama 
13582ec34544SRui Ueyama   expect(";");
13592ec34544SRui Ueyama }
13602ec34544SRui Ueyama 
13612ec34544SRui Ueyama // Reads a non-anonymous version definition,
13622ec34544SRui Ueyama // e.g. "VerStr { global: foo; bar; local: *; };".
13633837f427SRui Ueyama void ScriptParser::readVersionDeclaration(StringRef verStr) {
13642ec34544SRui Ueyama   // Read a symbol list.
13653837f427SRui Ueyama   std::vector<SymbolVersion> locals;
13663837f427SRui Ueyama   std::vector<SymbolVersion> globals;
13673837f427SRui Ueyama   std::tie(locals, globals) = readSymbols();
13682ec34544SRui Ueyama 
13693837f427SRui Ueyama   for (SymbolVersion v : locals) {
13703837f427SRui Ueyama     if (v.name == "*")
13713837f427SRui Ueyama       config->defaultSymbolVersion = VER_NDX_LOCAL;
13722ec34544SRui Ueyama     else
13733837f427SRui Ueyama       config->versionScriptLocals.push_back(v);
13742ec34544SRui Ueyama   }
13752ec34544SRui Ueyama 
13762ec34544SRui Ueyama   // Create a new version definition and add that to the global symbols.
13773837f427SRui Ueyama   VersionDefinition ver;
13783837f427SRui Ueyama   ver.name = verStr;
13793837f427SRui Ueyama   ver.globals = globals;
13802ec34544SRui Ueyama 
13812ec34544SRui Ueyama   // User-defined version number starts from 2 because 0 and 1 are
13822ec34544SRui Ueyama   // reserved for VER_NDX_LOCAL and VER_NDX_GLOBAL, respectively.
13833837f427SRui Ueyama   ver.id = config->versionDefinitions.size() + 2;
13843837f427SRui Ueyama   config->versionDefinitions.push_back(ver);
13852ec34544SRui Ueyama 
13862ec34544SRui Ueyama   // Each version may have a parent version. For example, "Ver2"
13872ec34544SRui Ueyama   // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"
13882ec34544SRui Ueyama   // as a parent. This version hierarchy is, probably against your
13892ec34544SRui Ueyama   // instinct, purely for hint; the runtime doesn't care about it
13902ec34544SRui Ueyama   // at all. In LLD, we simply ignore it.
13912ec34544SRui Ueyama   if (peek() != ";")
13922ec34544SRui Ueyama     skip();
13932ec34544SRui Ueyama   expect(";");
13942ec34544SRui Ueyama }
13952ec34544SRui Ueyama 
13963837f427SRui Ueyama static bool hasWildcard(StringRef s) {
13973837f427SRui Ueyama   return s.find_first_of("?*[") != StringRef::npos;
13981e77ad14SRui Ueyama }
13991e77ad14SRui Ueyama 
14002ec34544SRui Ueyama // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
14012ec34544SRui Ueyama std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
14022ec34544SRui Ueyama ScriptParser::readSymbols() {
14033837f427SRui Ueyama   std::vector<SymbolVersion> locals;
14043837f427SRui Ueyama   std::vector<SymbolVersion> globals;
14053837f427SRui Ueyama   std::vector<SymbolVersion> *v = &globals;
14062ec34544SRui Ueyama 
1407b8a59c8aSBob Haarman   while (!errorCount()) {
14082ec34544SRui Ueyama     if (consume("}"))
14092ec34544SRui Ueyama       break;
14102ec34544SRui Ueyama     if (consumeLabel("local")) {
14113837f427SRui Ueyama       v = &locals;
14122ec34544SRui Ueyama       continue;
14132ec34544SRui Ueyama     }
14142ec34544SRui Ueyama     if (consumeLabel("global")) {
14153837f427SRui Ueyama       v = &globals;
14162ec34544SRui Ueyama       continue;
14172ec34544SRui Ueyama     }
14182ec34544SRui Ueyama 
14192ec34544SRui Ueyama     if (consume("extern")) {
14203837f427SRui Ueyama       std::vector<SymbolVersion> ext = readVersionExtern();
14213837f427SRui Ueyama       v->insert(v->end(), ext.begin(), ext.end());
14222ec34544SRui Ueyama     } else {
14233837f427SRui Ueyama       StringRef tok = next();
14243837f427SRui Ueyama       v->push_back({unquote(tok), false, hasWildcard(tok)});
14252ec34544SRui Ueyama     }
14262ec34544SRui Ueyama     expect(";");
14272ec34544SRui Ueyama   }
14283837f427SRui Ueyama   return {locals, globals};
14292ec34544SRui Ueyama }
14302ec34544SRui Ueyama 
14312ec34544SRui Ueyama // Reads an "extern C++" directive, e.g.,
14322ec34544SRui Ueyama // "extern "C++" { ns::*; "f(int, double)"; };"
143317324d8bSRui Ueyama //
143417324d8bSRui Ueyama // The last semicolon is optional. E.g. this is OK:
143517324d8bSRui Ueyama // "extern "C++" { ns::*; "f(int, double)" };"
14362ec34544SRui Ueyama std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
14373837f427SRui Ueyama   StringRef tok = next();
14383837f427SRui Ueyama   bool isCXX = tok == "\"C++\"";
14393837f427SRui Ueyama   if (!isCXX && tok != "\"C\"")
14402ec34544SRui Ueyama     setError("Unknown language");
14412ec34544SRui Ueyama   expect("{");
14422ec34544SRui Ueyama 
14433837f427SRui Ueyama   std::vector<SymbolVersion> ret;
1444b8a59c8aSBob Haarman   while (!errorCount() && peek() != "}") {
14453837f427SRui Ueyama     StringRef tok = next();
14463837f427SRui Ueyama     ret.push_back(
14473837f427SRui Ueyama         {unquote(tok), isCXX, !tok.startswith("\"") && hasWildcard(tok)});
144817324d8bSRui Ueyama     if (consume("}"))
14493837f427SRui Ueyama       return ret;
14502ec34544SRui Ueyama     expect(";");
14512ec34544SRui Ueyama   }
14522ec34544SRui Ueyama 
14532ec34544SRui Ueyama   expect("}");
14543837f427SRui Ueyama   return ret;
14552ec34544SRui Ueyama }
14562ec34544SRui Ueyama 
14573837f427SRui Ueyama uint64_t ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
14583837f427SRui Ueyama                                             StringRef s3) {
14593837f427SRui Ueyama   if (!consume(s1) && !consume(s2) && !consume(s3)) {
14603837f427SRui Ueyama     setError("expected one of: " + s1 + ", " + s2 + ", or " + s3);
14612ec34544SRui Ueyama     return 0;
14622ec34544SRui Ueyama   }
14632ec34544SRui Ueyama   expect("=");
1464040af7deSRui Ueyama   return readExpr()().getValue();
14652ec34544SRui Ueyama }
14662ec34544SRui Ueyama 
14672ec34544SRui Ueyama // Parse the MEMORY command as specified in:
14682ec34544SRui Ueyama // https://sourceware.org/binutils/docs/ld/MEMORY.html
14692ec34544SRui Ueyama //
14702ec34544SRui Ueyama // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
14712ec34544SRui Ueyama void ScriptParser::readMemory() {
14722ec34544SRui Ueyama   expect("{");
1473b8a59c8aSBob Haarman   while (!errorCount() && !consume("}")) {
14743837f427SRui Ueyama     StringRef tok = next();
14753837f427SRui Ueyama     if (tok == "INCLUDE") {
14762e9d40d5SRui Ueyama       readInclude();
14772e9d40d5SRui Ueyama       continue;
14782e9d40d5SRui Ueyama     }
14792ec34544SRui Ueyama 
14803837f427SRui Ueyama     uint32_t flags = 0;
14813837f427SRui Ueyama     uint32_t negFlags = 0;
14822ec34544SRui Ueyama     if (consume("(")) {
14833837f427SRui Ueyama       std::tie(flags, negFlags) = readMemoryAttributes();
14842ec34544SRui Ueyama       expect(")");
14852ec34544SRui Ueyama     }
14862ec34544SRui Ueyama     expect(":");
14872ec34544SRui Ueyama 
14883837f427SRui Ueyama     uint64_t origin = readMemoryAssignment("ORIGIN", "org", "o");
14892ec34544SRui Ueyama     expect(",");
14903837f427SRui Ueyama     uint64_t length = readMemoryAssignment("LENGTH", "len", "l");
14912ec34544SRui Ueyama 
14925f37541cSGeorge Rimar     // Add the memory region to the region map.
14933837f427SRui Ueyama     MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, negFlags);
14943837f427SRui Ueyama     if (!script->memoryRegions.insert({tok, mr}).second)
14953837f427SRui Ueyama       setError("region '" + tok + "' already defined");
14962ec34544SRui Ueyama   }
14972ec34544SRui Ueyama }
14982ec34544SRui Ueyama 
14992ec34544SRui Ueyama // This function parses the attributes used to match against section
15002ec34544SRui Ueyama // flags when placing output sections in a memory region. These flags
15012ec34544SRui Ueyama // are only used when an explicit memory region name is not used.
15022ec34544SRui Ueyama std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() {
15033837f427SRui Ueyama   uint32_t flags = 0;
15043837f427SRui Ueyama   uint32_t negFlags = 0;
15053837f427SRui Ueyama   bool invert = false;
15062ec34544SRui Ueyama 
15073837f427SRui Ueyama   for (char c : next().lower()) {
15083837f427SRui Ueyama     uint32_t flag = 0;
15093837f427SRui Ueyama     if (c == '!')
15103837f427SRui Ueyama       invert = !invert;
15113837f427SRui Ueyama     else if (c == 'w')
15123837f427SRui Ueyama       flag = SHF_WRITE;
15133837f427SRui Ueyama     else if (c == 'x')
15143837f427SRui Ueyama       flag = SHF_EXECINSTR;
15153837f427SRui Ueyama     else if (c == 'a')
15163837f427SRui Ueyama       flag = SHF_ALLOC;
15173837f427SRui Ueyama     else if (c != 'r')
15182ec34544SRui Ueyama       setError("invalid memory region attribute");
15192ec34544SRui Ueyama 
15203837f427SRui Ueyama     if (invert)
15213837f427SRui Ueyama       negFlags |= flag;
15222ec34544SRui Ueyama     else
15233837f427SRui Ueyama       flags |= flag;
15242ec34544SRui Ueyama   }
15253837f427SRui Ueyama   return {flags, negFlags};
15262ec34544SRui Ueyama }
15272ec34544SRui Ueyama 
15283837f427SRui Ueyama void elf::readLinkerScript(MemoryBufferRef mb) {
15293837f427SRui Ueyama   ScriptParser(mb).readLinkerScript();
15302ec34544SRui Ueyama }
15312ec34544SRui Ueyama 
15323837f427SRui Ueyama void elf::readVersionScript(MemoryBufferRef mb) {
15333837f427SRui Ueyama   ScriptParser(mb).readVersionScript();
15342ec34544SRui Ueyama }
15352ec34544SRui Ueyama 
15363837f427SRui Ueyama void elf::readDynamicList(MemoryBufferRef mb) {
15373837f427SRui Ueyama   ScriptParser(mb).readDynamicList();
15382ec34544SRui Ueyama }
15398c7e8cceSPetr Hosek 
15403837f427SRui Ueyama void elf::readDefsym(StringRef name, MemoryBufferRef mb) {
15413837f427SRui Ueyama   ScriptParser(mb).readDefsym(name);
15428c7e8cceSPetr Hosek }
1543